~ubuntu-branches/ubuntu/wily/qtbase-opensource-src/wily

« back to all changes in this revision

Viewing changes to src/plugins/platforms/openwfd/qopenwfddevice.cpp

  • Committer: Package Import Robot
  • Author(s): Timo Jyrinki
  • Date: 2013-02-05 12:46:17 UTC
  • Revision ID: package-import@ubuntu.com-20130205124617-c8jouts182j002fx
Tags: upstream-5.0.1+dfsg
ImportĀ upstreamĀ versionĀ 5.0.1+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
 
4
** Contact: http://www.qt-project.org/legal
 
5
**
 
6
** This file is part of the plugins of the Qt Toolkit.
 
7
**
 
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.
 
16
**
 
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.
 
24
**
 
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.
 
28
**
 
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.
 
36
**
 
37
**
 
38
** $QT_END_LICENSE$
 
39
**
 
40
****************************************************************************/
 
41
 
 
42
#include "qopenwfddevice.h"
 
43
 
 
44
#include "qopenwfdport.h"
 
45
#include "qopenwfdscreen.h"
 
46
 
 
47
#include <QtCore/QDebug>
 
48
 
 
49
#include <WF/wfdext.h>
 
50
#include <gbm.h>
 
51
 
 
52
QOpenWFDDevice::QOpenWFDDevice(QOpenWFDIntegration *integration, WFDint device_enumeration)
 
53
    : mIntegration(integration)
 
54
    , mDeviceEnum(device_enumeration)
 
55
    , mCommitedDevice(false)
 
56
    , mWaitingForBindSourceEvent(false)
 
57
{
 
58
    mDevice = wfdCreateDevice(WFD_DEFAULT_DEVICE_ID,WFD_NONE);
 
59
    if (mDevice == WFD_INVALID_HANDLE)
 
60
        qDebug() << "failed to create device";
 
61
 
 
62
    mEvent = wfdCreateEvent(mDevice,0);
 
63
    if (mEvent == WFD_INVALID_HANDLE)
 
64
        qDebug() << "failed to create event handle";
 
65
 
 
66
    //initialize pipelines for device.
 
67
    wfdEnumeratePipelines(mDevice,WFD_NONE,0,WFD_NONE);
 
68
 
 
69
    initializeGbmAndEgl();
 
70
 
 
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);
 
75
 
 
76
    for (int i = 0; i < actualNumberOfPorts; i++)
 
77
    {
 
78
        QOpenWFDPort *port = new QOpenWFDPort(this,port_enumerations[i]);
 
79
        if (port->attached()) {
 
80
            mPorts.append(port);
 
81
        } else {
 
82
            delete port;
 
83
        }
 
84
    }
 
85
 
 
86
    int fd = wfdDeviceEventGetFD(mDevice,mEvent);
 
87
    mEventSocketNotifier = new QSocketNotifier(fd,QSocketNotifier::Read,this);
 
88
    connect(mEventSocketNotifier,SIGNAL(activated(int)),SLOT(readEvents()));
 
89
 
 
90
    mCommitedDevice = true;
 
91
    commit(WFD_COMMIT_ENTIRE_DEVICE, handle());
 
92
}
 
93
 
 
94
QOpenWFDDevice::~QOpenWFDDevice()
 
95
{
 
96
    delete mEventSocketNotifier;
 
97
    wfdDestroyEvent(mDevice,mEvent);
 
98
 
 
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));
 
104
        }
 
105
        //but we have to delete them :)
 
106
        delete mPorts[i];
 
107
    }
 
108
 
 
109
    eglDestroyContext(mEglDisplay,mEglContext);
 
110
    eglTerminate(mEglDisplay);
 
111
 
 
112
    gbm_device_destroy(mGbmDevice);
 
113
 
 
114
    wfdDestroyDevice(mDevice);
 
115
}
 
116
 
 
117
WFDDevice QOpenWFDDevice::handle() const
 
118
{
 
119
    return mDevice;
 
120
}
 
121
 
 
122
QOpenWFDIntegration * QOpenWFDDevice::integration() const
 
123
{
 
124
    return mIntegration;
 
125
}
 
126
 
 
127
bool QOpenWFDDevice::isPipelineUsed(WFDint pipelineId)
 
128
{
 
129
    return mUsedPipelines.contains(pipelineId);
 
130
}
 
131
 
 
132
void QOpenWFDDevice::addToUsedPipelineSet(WFDint pipelineId,QOpenWFDPort *port)
 
133
{
 
134
    mUsedPipelines.insert(pipelineId,port);
 
135
}
 
136
 
 
137
void QOpenWFDDevice::removeFromUsedPipelineSet(WFDint pipelineId)
 
138
{
 
139
    mUsedPipelines.remove(pipelineId);
 
140
}
 
141
 
 
142
gbm_device * QOpenWFDDevice::gbmDevice() const
 
143
 
 
144
{
 
145
    return mGbmDevice;
 
146
}
 
147
 
 
148
EGLDisplay QOpenWFDDevice::eglDisplay() const
 
149
{
 
150
    return mEglDisplay;
 
151
}
 
152
 
 
153
EGLContext QOpenWFDDevice::eglContext() const
 
154
{
 
155
    return mEglContext;
 
156
}
 
157
 
 
158
void QOpenWFDDevice::commit(WFDCommitType type, WFDHandle handle)
 
159
{
 
160
    if (mCommitedDevice) {
 
161
        wfdDeviceCommit(mDevice,type,handle);
 
162
    }
 
163
}
 
164
 
 
165
void QOpenWFDDevice::waitForPipelineBindSourceCompleteEvent()
 
166
{
 
167
    mWaitingForBindSourceEvent = true;
 
168
 
 
169
    while (mWaitingForBindSourceEvent) {
 
170
        readEvents(WFD_FOREVER);
 
171
    }
 
172
}
 
173
 
 
174
void QOpenWFDDevice::readEvents(WFDtime wait)
 
175
{
 
176
    WFDEventType type = wfdDeviceEventWait(mDevice,mEvent,wait);
 
177
 
 
178
    if (type == WFD_EVENT_NONE || type == WFD_EVENT_DESTROYED) {
 
179
        return;
 
180
    }
 
181
    switch (type) {
 
182
    case WFD_EVENT_INVALID:
 
183
    case WFD_EVENT_NONE:
 
184
        return;
 
185
    case WFD_EVENT_DESTROYED:
 
186
        qDebug() << "Event or Device destoryed!";
 
187
        return;
 
188
    case WFD_EVENT_PORT_ATTACH_DETACH:
 
189
        handlePortAttachDetach();
 
190
        break;
 
191
    case WFD_EVENT_PORT_PROTECTION_FAILURE:
 
192
        qDebug() << "Port protection event handling not implemented";
 
193
        break;
 
194
    case WFD_EVENT_PIPELINE_BIND_SOURCE_COMPLETE:
 
195
        handlePipelineBindSourceComplete();
 
196
        break;
 
197
    case WFD_EVENT_PIPELINE_BIND_MASK_COMPLETE:
 
198
        qDebug() << "Pipeline bind mask event handling not implemented";
 
199
        break;
 
200
    default:
 
201
        qDebug() << "Not recognised event type";
 
202
        break;
 
203
    }
 
204
 
 
205
 
 
206
}
 
207
 
 
208
void QOpenWFDDevice::initializeGbmAndEgl()
 
209
{
 
210
 
 
211
    qDebug() << "initializing GBM and EGL";
 
212
    int fd = wfdGetDeviceAttribi(mDevice,WFD_DEVICE_ID);
 
213
    if (fd < 0) {
 
214
        qDebug() << "failed to get WFD_DEVICE_ID";
 
215
    }
 
216
 
 
217
    mGbmDevice = gbm_create_device(fd);
 
218
 
 
219
    setenv("EGL_PLATFORM", "drm",1);
 
220
 
 
221
    mEglDisplay = eglGetDisplay(mGbmDevice);
 
222
 
 
223
    EGLint minor, major;
 
224
 
 
225
    if (!eglInitialize(mEglDisplay,&major,&minor)) {
 
226
        qDebug() << "failed to initialize egl";
 
227
    }
 
228
 
 
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";
 
232
    }
 
233
 
 
234
    eglBindAPI(EGL_OPENGL_ES_API);
 
235
 
 
236
    EGLint contextAttribs[] = {
 
237
        EGL_CONTEXT_CLIENT_VERSION, 2,
 
238
        EGL_NONE
 
239
    };
 
240
 
 
241
    mEglContext = eglCreateContext(mEglDisplay,NULL,EGL_NO_CONTEXT,contextAttribs);
 
242
    if (mEglContext == EGL_NO_CONTEXT) {
 
243
        qDebug() << "Failed to create EGL context";
 
244
    }
 
245
 
 
246
    eglCreateImage = (PFNEGLCREATEIMAGEKHRPROC) eglGetProcAddress("eglCreateImageKHR");
 
247
    if (!eglCreateImage) {
 
248
        qWarning("failed to load extension eglCreateImageKHR");
 
249
    }
 
250
 
 
251
    eglDestroyImage = (PFNEGLDESTROYIMAGEKHRPROC) eglGetProcAddress("eglDestroyImageKHR");
 
252
    if (!eglDestroyImage) {
 
253
        qWarning("failed to load extension eglDestoryImageKHR");
 
254
    }
 
255
 
 
256
    glEglImageTargetRenderBufferStorage = (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) eglGetProcAddress("glEGLImageTargetRenderbufferStorageOES");
 
257
    if (!glEglImageTargetRenderBufferStorage) {
 
258
        qWarning("failed to load extension glEGLImageTargetRenderbufferStorageOES");
 
259
    }
 
260
}
 
261
 
 
262
void QOpenWFDDevice::handlePortAttachDetach()
 
263
{
 
264
    WFDint id = wfdGetEventAttribi(mDevice,mEvent,WFD_EVENT_PORT_ATTACH_PORT_ID);
 
265
    if (id == WFD_INVALID_PORT_ID)
 
266
        return;
 
267
 
 
268
    WFDint attachState = wfdGetEventAttribi(mDevice,mEvent,WFD_EVENT_PORT_ATTACH_STATE);
 
269
    if (attachState == WFD_TRUE) {
 
270
        int indexToAdd = -1;
 
271
        for (int i = 0; i < mPorts.size(); i++) {
 
272
            if (mPorts.at(i)->portId() == id) {
 
273
                indexToAdd = i;
 
274
                qDebug() << "found index to attach";
 
275
                break;
 
276
            }
 
277
        }
 
278
        if (indexToAdd >= 0) {
 
279
            mPorts[indexToAdd]->attach();
 
280
        } else {
 
281
            mPorts.append(new QOpenWFDPort(this,id));
 
282
        }
 
283
 
 
284
    } else {
 
285
        int indexToDelete = -1;
 
286
        for (int i = 0; i < mPorts.size(); i++) {
 
287
            if (mPorts.at(i)->portId() == id) {
 
288
                indexToDelete = i;
 
289
                break;
 
290
            }
 
291
        }
 
292
        if (indexToDelete >= 0) {
 
293
            QOpenWFDPort *portToDelete = mPorts.at(indexToDelete);
 
294
            mPorts.removeAt(indexToDelete);
 
295
            delete portToDelete;
 
296
        }
 
297
    }
 
298
}
 
299
 
 
300
void QOpenWFDDevice::handlePipelineBindSourceComplete()
 
301
{
 
302
    mWaitingForBindSourceEvent = false;
 
303
 
 
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";
 
307
    }
 
308
 
 
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();
 
314
            break;
 
315
        }
 
316
    }
 
317
}