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