1
/****************************************************************************
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4
** Contact: http://www.qt-project.org/legal
6
** This file is part of the plugins of the Qt Toolkit.
8
** $QT_BEGIN_LICENSE:LGPL$
9
** Commercial License Usage
10
** Licensees holding valid commercial Qt licenses may use this file in
11
** accordance with the commercial license agreement provided with the
12
** Software or, alternatively, in accordance with the terms contained in
13
** a written agreement between you and Digia. For licensing terms and
14
** conditions see http://qt.digia.com/licensing. For further information
15
** use the contact form at http://qt.digia.com/contact-us.
17
** GNU Lesser General Public License Usage
18
** Alternatively, this file may be used under the terms of the GNU Lesser
19
** General Public License version 2.1 as published by the Free Software
20
** Foundation and appearing in the file LICENSE.LGPL included in the
21
** packaging of this file. Please review the following information to
22
** ensure the GNU Lesser General Public License version 2.1 requirements
23
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25
** In addition, as a special exception, Digia gives you certain additional
26
** rights. These rights are described in the Digia Qt LGPL Exception
27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29
** GNU General Public License Usage
30
** Alternatively, this file may be used under the terms of the GNU
31
** General Public License version 3.0 as published by the Free Software
32
** Foundation and appearing in the file LICENSE.GPL included in the
33
** packaging of this file. Please review the following information to
34
** ensure the GNU General Public License version 3.0 requirements will be
35
** met: http://www.gnu.org/copyleft/gpl.html.
40
****************************************************************************/
42
#include "qopenwfddevice.h"
44
#include "qopenwfdport.h"
45
#include "qopenwfdscreen.h"
47
#include <QtCore/QDebug>
49
#include <WF/wfdext.h>
52
QOpenWFDDevice::QOpenWFDDevice(QOpenWFDIntegration *integration, WFDint device_enumeration)
53
: mIntegration(integration)
54
, mDeviceEnum(device_enumeration)
55
, mCommitedDevice(false)
56
, mWaitingForBindSourceEvent(false)
58
mDevice = wfdCreateDevice(WFD_DEFAULT_DEVICE_ID,WFD_NONE);
59
if (mDevice == WFD_INVALID_HANDLE)
60
qDebug() << "failed to create device";
62
mEvent = wfdCreateEvent(mDevice,0);
63
if (mEvent == WFD_INVALID_HANDLE)
64
qDebug() << "failed to create event handle";
66
//initialize pipelines for device.
67
wfdEnumeratePipelines(mDevice,WFD_NONE,0,WFD_NONE);
69
initializeGbmAndEgl();
71
WFDint numberOfPorts = wfdEnumeratePorts(mDevice,0,0,0);
72
WFDint port_enumerations[numberOfPorts];
73
WFDint actualNumberOfPorts = wfdEnumeratePorts(mDevice,port_enumerations,numberOfPorts,WFD_NONE);
74
Q_ASSERT(actualNumberOfPorts == numberOfPorts);
76
for (int i = 0; i < actualNumberOfPorts; i++)
78
QOpenWFDPort *port = new QOpenWFDPort(this,port_enumerations[i]);
79
if (port->attached()) {
86
int fd = wfdDeviceEventGetFD(mDevice,mEvent);
87
mEventSocketNotifier = new QSocketNotifier(fd,QSocketNotifier::Read,this);
88
connect(mEventSocketNotifier,SIGNAL(activated(int)),SLOT(readEvents()));
90
mCommitedDevice = true;
91
commit(WFD_COMMIT_ENTIRE_DEVICE, handle());
94
QOpenWFDDevice::~QOpenWFDDevice()
96
delete mEventSocketNotifier;
97
wfdDestroyEvent(mDevice,mEvent);
99
for (int i = 0; i < mPorts.size(); i++) {
100
//probably don't need to remove them from the list
101
QList <WFDint> keys = mUsedPipelines.keys(mPorts.at(i));
102
for (int keyIndex = 0; keyIndex < keys.size(); keyIndex++) {
103
mUsedPipelines.remove(keys.at(keyIndex));
105
//but we have to delete them :)
109
eglDestroyContext(mEglDisplay,mEglContext);
110
eglTerminate(mEglDisplay);
112
gbm_device_destroy(mGbmDevice);
114
wfdDestroyDevice(mDevice);
117
WFDDevice QOpenWFDDevice::handle() const
122
QOpenWFDIntegration * QOpenWFDDevice::integration() const
127
bool QOpenWFDDevice::isPipelineUsed(WFDint pipelineId)
129
return mUsedPipelines.contains(pipelineId);
132
void QOpenWFDDevice::addToUsedPipelineSet(WFDint pipelineId,QOpenWFDPort *port)
134
mUsedPipelines.insert(pipelineId,port);
137
void QOpenWFDDevice::removeFromUsedPipelineSet(WFDint pipelineId)
139
mUsedPipelines.remove(pipelineId);
142
gbm_device * QOpenWFDDevice::gbmDevice() const
148
EGLDisplay QOpenWFDDevice::eglDisplay() const
153
EGLContext QOpenWFDDevice::eglContext() const
158
void QOpenWFDDevice::commit(WFDCommitType type, WFDHandle handle)
160
if (mCommitedDevice) {
161
wfdDeviceCommit(mDevice,type,handle);
165
void QOpenWFDDevice::waitForPipelineBindSourceCompleteEvent()
167
mWaitingForBindSourceEvent = true;
169
while (mWaitingForBindSourceEvent) {
170
readEvents(WFD_FOREVER);
174
void QOpenWFDDevice::readEvents(WFDtime wait)
176
WFDEventType type = wfdDeviceEventWait(mDevice,mEvent,wait);
178
if (type == WFD_EVENT_NONE || type == WFD_EVENT_DESTROYED) {
182
case WFD_EVENT_INVALID:
185
case WFD_EVENT_DESTROYED:
186
qDebug() << "Event or Device destoryed!";
188
case WFD_EVENT_PORT_ATTACH_DETACH:
189
handlePortAttachDetach();
191
case WFD_EVENT_PORT_PROTECTION_FAILURE:
192
qDebug() << "Port protection event handling not implemented";
194
case WFD_EVENT_PIPELINE_BIND_SOURCE_COMPLETE:
195
handlePipelineBindSourceComplete();
197
case WFD_EVENT_PIPELINE_BIND_MASK_COMPLETE:
198
qDebug() << "Pipeline bind mask event handling not implemented";
201
qDebug() << "Not recognised event type";
208
void QOpenWFDDevice::initializeGbmAndEgl()
211
qDebug() << "initializing GBM and EGL";
212
int fd = wfdGetDeviceAttribi(mDevice,WFD_DEVICE_ID);
214
qDebug() << "failed to get WFD_DEVICE_ID";
217
mGbmDevice = gbm_create_device(fd);
219
setenv("EGL_PLATFORM", "drm",1);
221
mEglDisplay = eglGetDisplay(mGbmDevice);
225
if (!eglInitialize(mEglDisplay,&major,&minor)) {
226
qDebug() << "failed to initialize egl";
229
QByteArray eglExtensions = eglQueryString(mEglDisplay, EGL_EXTENSIONS);
230
if (!eglExtensions.contains("EGL_KHR_surfaceless_opengl")) {
231
qDebug() << "This egl implementation does not have the required EGL extension EGL_KHR_surfaceless_opengl";
234
eglBindAPI(EGL_OPENGL_ES_API);
236
EGLint contextAttribs[] = {
237
EGL_CONTEXT_CLIENT_VERSION, 2,
241
mEglContext = eglCreateContext(mEglDisplay,NULL,EGL_NO_CONTEXT,contextAttribs);
242
if (mEglContext == EGL_NO_CONTEXT) {
243
qDebug() << "Failed to create EGL context";
246
eglCreateImage = (PFNEGLCREATEIMAGEKHRPROC) eglGetProcAddress("eglCreateImageKHR");
247
if (!eglCreateImage) {
248
qWarning("failed to load extension eglCreateImageKHR");
251
eglDestroyImage = (PFNEGLDESTROYIMAGEKHRPROC) eglGetProcAddress("eglDestroyImageKHR");
252
if (!eglDestroyImage) {
253
qWarning("failed to load extension eglDestoryImageKHR");
256
glEglImageTargetRenderBufferStorage = (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) eglGetProcAddress("glEGLImageTargetRenderbufferStorageOES");
257
if (!glEglImageTargetRenderBufferStorage) {
258
qWarning("failed to load extension glEGLImageTargetRenderbufferStorageOES");
262
void QOpenWFDDevice::handlePortAttachDetach()
264
WFDint id = wfdGetEventAttribi(mDevice,mEvent,WFD_EVENT_PORT_ATTACH_PORT_ID);
265
if (id == WFD_INVALID_PORT_ID)
268
WFDint attachState = wfdGetEventAttribi(mDevice,mEvent,WFD_EVENT_PORT_ATTACH_STATE);
269
if (attachState == WFD_TRUE) {
271
for (int i = 0; i < mPorts.size(); i++) {
272
if (mPorts.at(i)->portId() == id) {
274
qDebug() << "found index to attach";
278
if (indexToAdd >= 0) {
279
mPorts[indexToAdd]->attach();
281
mPorts.append(new QOpenWFDPort(this,id));
285
int indexToDelete = -1;
286
for (int i = 0; i < mPorts.size(); i++) {
287
if (mPorts.at(i)->portId() == id) {
292
if (indexToDelete >= 0) {
293
QOpenWFDPort *portToDelete = mPorts.at(indexToDelete);
294
mPorts.removeAt(indexToDelete);
300
void QOpenWFDDevice::handlePipelineBindSourceComplete()
302
mWaitingForBindSourceEvent = false;
304
WFDint overflow = wfdGetEventAttribi(mDevice,mEvent, WFD_EVENT_PIPELINE_BIND_QUEUE_OVERFLOW);
305
if (overflow == WFD_TRUE) {
306
qDebug() << "PIPELINE_BIND_QUEUE_OVERFLOW event occurred";
309
WFDint pipelineId = wfdGetEventAttribi(mDevice,mEvent,WFD_EVENT_PIPELINE_BIND_PIPELINE_ID);
310
for (int i = 0; i < mPorts.size(); i++) {
311
if (pipelineId != WFD_INVALID_PIPELINE_ID && mUsedPipelines.contains(pipelineId)) {
312
QOpenWFDPort *port = mUsedPipelines.value(pipelineId);
313
port->screen()->pipelineBindSourceComplete();