1 /****************************************************************************
2 **
3 ** Copyright (C) 2017 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
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 The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #include "qeglfsopenwfdintegration.h"
41 
42 #include "wfd.h"
43 #include "wfdext2.h"
44 
45 QT_BEGIN_NAMESPACE
46 
47 #define MAX_NUM_OF_WFD_BUFFERS 3
48 #define MAX_NUM_OF_WFD_DEVICES 4
49 #define MAX_NUM_OF_WFD_PIPELINES 16
50 #define MAX_NUM_OF_WFD_PORT_MODES 64
51 #define MAX_NUM_OF_WFD_PORTS 4
52 
53 typedef struct wfd_buffer {
54     WFD_EGLImageType*   image;
55     WFDSource           source;
56 } wfd_buffer_t;
57 
58 typedef struct wfd_window {
59     WFDDevice       dev;
60     WFDPort         port;
61     WFDPipeline     pipeline;
62     int             numBuffers;
63     wfd_buffer_t    buffers[MAX_NUM_OF_WFD_BUFFERS];
64 } wfd_window_t;
65 
platformInit()66 void QEglFSOpenWFDIntegration::platformInit()
67 {
68     QEglFSDeviceIntegration::platformInit();
69 
70     mNativeDisplay = EGL_DEFAULT_DISPLAY;
71 
72     // Get device list
73     WFDint numDevs = wfdEnumerateDevices(nullptr, 0, nullptr);
74     WFDint devIds[MAX_NUM_OF_WFD_DEVICES];
75 
76     if (numDevs > 0)
77         wfdEnumerateDevices(devIds, numDevs, nullptr);
78 
79     // Create device
80     WFDint dev_attribs[3] = {WFD_DEVICE_CLIENT_TYPE,
81                               WFD_CLIENT_ID_CLUSTER,
82                               WFD_NONE};
83 
84     bool ok;
85     WFDint clientType = qgetenv("QT_OPENWFD_CLIENT_ID").toInt(&ok, 16);
86 
87     if (ok)
88         dev_attribs[1] = clientType;
89 
90     mDevice = wfdCreateDevice(WFD_DEFAULT_DEVICE_ID, dev_attribs);
91 
92     if (WFD_INVALID_HANDLE == mDevice)
93         qFatal( "Failed to create wfd device");
94 
95     // Get port list
96     WFDint portIds[MAX_NUM_OF_WFD_PORTS];
97     WFDint numPorts = wfdEnumeratePorts(mDevice, nullptr, 0, nullptr);
98     wfdEnumeratePorts(mDevice, portIds, numPorts, nullptr);
99 
100     // Create port
101     mPort = wfdCreatePort(mDevice, portIds[0], nullptr);
102 
103     if (WFD_INVALID_HANDLE == mPort)
104         qFatal("Failed to create wfd port");
105 
106     // Get port modes
107     WFDint numPortModes = wfdGetPortModes(mDevice, mPort, nullptr, 0);
108     WFDPortMode portModes[MAX_NUM_OF_WFD_PORT_MODES];
109     wfdGetPortModes(mDevice, mPort, portModes, numPortModes);
110 
111     // Get width and height
112     mScreenSize.setWidth(wfdGetPortModeAttribi(mDevice, mPort, portModes[0], WFD_PORT_MODE_WIDTH));
113     mScreenSize.setHeight(wfdGetPortModeAttribi(mDevice, mPort, portModes[0], WFD_PORT_MODE_HEIGHT));
114 
115     // Set port mode
116     wfdSetPortMode(mDevice, mPort, portModes[0]);
117     WFDErrorCode eError = wfdGetError(mDevice);
118     if (WFD_ERROR_NONE != eError)
119         qFatal("Failed to set wfd port mode");
120 
121     // Power on
122     wfdSetPortAttribi(mDevice, mPort, WFD_PORT_POWER_MODE, WFD_POWER_MODE_ON);
123     eError = wfdGetError(mDevice);
124     if (WFD_ERROR_NONE != eError)
125         qFatal("Failed to power on wfd port");
126 }
127 
screenSize() const128 QSize QEglFSOpenWFDIntegration::screenSize() const
129 {
130     return mScreenSize;
131 }
132 
platformDisplay() const133 EGLNativeDisplayType QEglFSOpenWFDIntegration::platformDisplay() const
134 {
135     return mNativeDisplay;
136 }
137 
createNativeWindow(QPlatformWindow * window,const QSize & size,const QSurfaceFormat & format)138 EGLNativeWindowType QEglFSOpenWFDIntegration::createNativeWindow(QPlatformWindow *window,
139                                                                  const QSize &size,
140                                                                  const QSurfaceFormat &format)
141 {
142     Q_UNUSED(window);
143     Q_UNUSED(format);
144 
145     // Get list of pipelines
146     WFDint numPipelines = wfdEnumeratePipelines(mDevice, nullptr, 0, nullptr);
147 
148     WFDint pipelineIds[MAX_NUM_OF_WFD_PIPELINES];
149     wfdEnumeratePipelines(mDevice, pipelineIds, numPipelines, nullptr);
150 
151     bool ok;
152     WFDint pipelineId = qgetenv("QT_OPENWFD_PIPELINE_ID").toInt(&ok);
153 
154     if (!ok)
155         pipelineId = pipelineIds[0];
156 
157     WFDPipeline pipeline = wfdCreatePipeline(mDevice, pipelineId, nullptr);
158     if (WFD_INVALID_HANDLE == pipeline)
159         qFatal("Failed to create wfd pipeline");
160 
161     wfdSetPipelineAttribi(mDevice, pipeline, WFD_PIPELINE_TRANSPARENCY_ENABLE,
162                           (WFD_TRANSPARENCY_SOURCE_ALPHA|WFD_TRANSPARENCY_GLOBAL_ALPHA));
163 
164     WFDErrorCode eError = wfdGetError(mDevice);
165     if (WFD_ERROR_NONE != eError)
166         qFatal("Failed to set WFD_PIPELINE_TRANSPARENCY_ENABLE");
167 
168     wfdSetPipelineAttribi(mDevice, pipeline, WFD_PIPELINE_GLOBAL_ALPHA, 255);
169     eError = wfdGetError(mDevice);
170     if (WFD_ERROR_NONE != eError)
171         qFatal("Failed to set WFD_PIPELINE_GLOBAL_ALPHA");
172 
173     wfdBindPipelineToPort(mDevice, mPort, pipeline);
174     eError = wfdGetError(mDevice);
175     if (WFD_ERROR_NONE != eError)
176         qFatal("Failed to bind port to pipeline");
177 
178     // Create buffers
179     WFDSource source[MAX_NUM_OF_WFD_BUFFERS] = {WFD_INVALID_HANDLE, WFD_INVALID_HANDLE,
180                                                 WFD_INVALID_HANDLE};
181     WFDEGLImage eglImageHandles[MAX_NUM_OF_WFD_BUFFERS];
182     WFD_EGLImageType* wfdEglImages[MAX_NUM_OF_WFD_BUFFERS];
183 
184     for (int i = 0; i < MAX_NUM_OF_WFD_BUFFERS; i++) {
185         wfdCreateWFDEGLImages(mDevice, mScreenSize.width(), mScreenSize.height(),
186                               WFD_FORMAT_RGBA8888, WFD_USAGE_OPENGL_ES2 | WFD_USAGE_DISPLAY,
187                               1, &(eglImageHandles[i]), 0);
188 
189         wfdEglImages[i] = (WFD_EGLImageType *)(eglImageHandles[i]);
190         if (WFD_INVALID_HANDLE == wfdEglImages[i])
191             qFatal("Failed to create WDFEGLImages");
192 
193         source[i] = wfdCreateSourceFromImage(mDevice, pipeline, eglImageHandles[i], nullptr);
194         if (WFD_INVALID_HANDLE == source[i])
195             qFatal("Failed to create source from EGLImage");
196     }
197 
198     // Commit port
199     wfdDeviceCommit(mDevice, WFD_COMMIT_ENTIRE_PORT, mPort);
200     eError = wfdGetError(mDevice);
201     if (WFD_ERROR_NONE != eError)
202             qFatal("Failed to commit port");
203 
204     // Create native window
205     wfd_window_t* nativeWindow = (wfd_window_t*)malloc(sizeof(wfd_window_t));
206     if (nullptr == nativeWindow)
207             qFatal("Failed to allocate memory for native window");
208 
209     nativeWindow->dev = mDevice;
210     nativeWindow->port = mPort;
211     nativeWindow->pipeline = pipeline;
212     nativeWindow->numBuffers = MAX_NUM_OF_WFD_BUFFERS;
213 
214     for (int i = 0; i < MAX_NUM_OF_WFD_BUFFERS; i++) {
215         nativeWindow->buffers[i].image  = wfdEglImages[i];
216         nativeWindow->buffers[i].source = source[i];
217     }
218 
219     return (EGLNativeWindowType)nativeWindow;
220 }
221 
surfaceFormatFor(const QSurfaceFormat & inputFormat) const222 QSurfaceFormat QEglFSOpenWFDIntegration::surfaceFormatFor(const QSurfaceFormat &inputFormat) const
223 {
224     QSurfaceFormat format = inputFormat;
225     format.setRedBufferSize(8);
226     format.setGreenBufferSize(8);
227     format.setBlueBufferSize(8);
228     format.setAlphaBufferSize(8);
229     return format;
230 }
231 
destroyNativeWindow(EGLNativeWindowType window)232 void QEglFSOpenWFDIntegration::destroyNativeWindow(EGLNativeWindowType window)
233 {
234     free((void*)window);
235 }
236 
237 QT_END_NAMESPACE
238