Warning: That file was not part of the compilation database. It may have many parsing errors.
1 | /**************************************************************************** |
---|---|
2 | ** |
3 | ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). |
4 | ** Contact: http://www.qt-project.org/legal |
5 | ** |
6 | ** This file is part of the QtOpenGL module 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 <QtCore/qdebug.h> |
43 | #include <QtOpenGL/qgl.h> |
44 | #include <QtOpenGL/qglpixelbuffer.h> |
45 | #include "qgl_p.h" |
46 | #include "qgl_egl_p.h" |
47 | #include "qglpixelbuffer_p.h" |
48 | |
49 | #ifdef Q_WS_X11 |
50 | #include <QtGui/private/qpixmap_x11_p.h> |
51 | #endif |
52 | |
53 | #if defined(Q_OS_SYMBIAN) |
54 | #include <QtGui/private/qgraphicssystemex_symbian_p.h> |
55 | #endif |
56 | |
57 | QT_BEGIN_NAMESPACE |
58 | |
59 | QEglProperties *QGLContextPrivate::extraWindowSurfaceCreationProps = NULL; |
60 | |
61 | void qt_eglproperties_set_glformat(QEglProperties& eglProperties, const QGLFormat& glFormat) |
62 | { |
63 | int redSize = glFormat.redBufferSize(); |
64 | int greenSize = glFormat.greenBufferSize(); |
65 | int blueSize = glFormat.blueBufferSize(); |
66 | int alphaSize = glFormat.alphaBufferSize(); |
67 | int depthSize = glFormat.depthBufferSize(); |
68 | int stencilSize = glFormat.stencilBufferSize(); |
69 | int sampleCount = glFormat.samples(); |
70 | |
71 | bool prefer32Bit = false; |
72 | #ifdef Q_OS_SYMBIAN |
73 | // on Symbian we prefer 32-bit configs, unless we're using the low memory GPU |
74 | prefer32Bit = !QSymbianGraphicsSystemEx::hasBCM2727(); |
75 | #endif |
76 | |
77 | if (prefer32Bit) { |
78 | if (glFormat.alpha() && alphaSize <= 0) |
79 | alphaSize = 8; |
80 | if (glFormat.depth() && depthSize <= 0) |
81 | depthSize = 24; |
82 | if (glFormat.stencil() && stencilSize <= 0) |
83 | stencilSize = 8; |
84 | if (glFormat.sampleBuffers() && sampleCount <= 0) |
85 | sampleCount = 1; |
86 | |
87 | redSize = redSize > 0 ? redSize : 8; |
88 | greenSize = greenSize > 0 ? greenSize : 8; |
89 | blueSize = blueSize > 0 ? blueSize : 8; |
90 | alphaSize = alphaSize > 0 ? alphaSize : 8; |
91 | depthSize = depthSize > 0 ? depthSize : 24; |
92 | stencilSize = stencilSize > 0 ? stencilSize : 8; |
93 | sampleCount = sampleCount >= 0 ? sampleCount : 4; |
94 | } else { |
95 | // QGLFormat uses a magic value of -1 to indicate "don't care", even when a buffer of that |
96 | // type has been requested. So we must check QGLFormat's booleans too if size is -1: |
97 | if (glFormat.alpha() && alphaSize <= 0) |
98 | alphaSize = 1; |
99 | if (glFormat.depth() && depthSize <= 0) |
100 | depthSize = 1; |
101 | if (glFormat.stencil() && stencilSize <= 0) |
102 | stencilSize = 1; |
103 | if (glFormat.sampleBuffers() && sampleCount <= 0) |
104 | sampleCount = 1; |
105 | |
106 | // We want to make sure 16-bit configs are chosen over 32-bit configs as they will provide |
107 | // the best performance. The EGL config selection algorithm is a bit stange in this regard: |
108 | // The selection criteria for EGL_BUFFER_SIZE is "AtLeast", so we can't use it to discard |
109 | // 32-bit configs completely from the selection. So it then comes to the sorting algorithm. |
110 | // The red/green/blue sizes have a sort priority of 3, so they are sorted by first. The sort |
111 | // order is special and described as "by larger _total_ number of color bits.". So EGL will |
112 | // put 32-bit configs in the list before the 16-bit configs. However, the spec also goes on |
113 | // to say "If the requested number of bits in attrib_list for a particular component is 0, |
114 | // then the number of bits for that component is not considered". This part of the spec also |
115 | // seems to imply that setting the red/green/blue bits to zero means none of the components |
116 | // are considered and EGL disregards the entire sorting rule. It then looks to the next |
117 | // highest priority rule, which is EGL_BUFFER_SIZE. Despite the selection criteria being |
118 | // "AtLeast" for EGL_BUFFER_SIZE, it's sort order is "smaller" meaning 16-bit configs are |
119 | // put in the list before 32-bit configs. So, to make sure 16-bit is preffered over 32-bit, |
120 | // we must set the red/green/blue sizes to zero. This has an unfortunate consequence that |
121 | // if the application sets the red/green/blue size to 5/6/5 on the QGLFormat, they will |
122 | // probably get a 32-bit config, even when there's an RGB565 config available. Oh well. |
123 | |
124 | // Now normalize the values so -1 becomes 0 |
125 | redSize = redSize > 0 ? redSize : 0; |
126 | greenSize = greenSize > 0 ? greenSize : 0; |
127 | blueSize = blueSize > 0 ? blueSize : 0; |
128 | alphaSize = alphaSize > 0 ? alphaSize : 0; |
129 | depthSize = depthSize > 0 ? depthSize : 0; |
130 | stencilSize = stencilSize > 0 ? stencilSize : 0; |
131 | sampleCount = sampleCount > 0 ? sampleCount : 0; |
132 | } |
133 | |
134 | eglProperties.setValue(EGL_RED_SIZE, redSize); |
135 | eglProperties.setValue(EGL_GREEN_SIZE, greenSize); |
136 | eglProperties.setValue(EGL_BLUE_SIZE, blueSize); |
137 | eglProperties.setValue(EGL_ALPHA_SIZE, alphaSize); |
138 | eglProperties.setValue(EGL_DEPTH_SIZE, depthSize); |
139 | eglProperties.setValue(EGL_STENCIL_SIZE, stencilSize); |
140 | eglProperties.setValue(EGL_SAMPLES, sampleCount); |
141 | eglProperties.setValue(EGL_SAMPLE_BUFFERS, sampleCount ? 1 : 0); |
142 | } |
143 | |
144 | // Updates "format" with the parameters of the selected configuration. |
145 | void qt_glformat_from_eglconfig(QGLFormat& format, const EGLConfig config) |
146 | { |
147 | EGLint redSize = 0; |
148 | EGLint greenSize = 0; |
149 | EGLint blueSize = 0; |
150 | EGLint alphaSize = 0; |
151 | EGLint depthSize = 0; |
152 | EGLint stencilSize = 0; |
153 | EGLint sampleCount = 0; |
154 | EGLint level = 0; |
155 | |
156 | EGLDisplay display = QEgl::display(); |
157 | eglGetConfigAttrib(display, config, EGL_RED_SIZE, &redSize); |
158 | eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &greenSize); |
159 | eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &blueSize); |
160 | eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &alphaSize); |
161 | eglGetConfigAttrib(display, config, EGL_DEPTH_SIZE, &depthSize); |
162 | eglGetConfigAttrib(display, config, EGL_STENCIL_SIZE, &stencilSize); |
163 | eglGetConfigAttrib(display, config, EGL_SAMPLES, &sampleCount); |
164 | eglGetConfigAttrib(display, config, EGL_LEVEL, &level); |
165 | |
166 | format.setRedBufferSize(redSize); |
167 | format.setGreenBufferSize(greenSize); |
168 | format.setBlueBufferSize(blueSize); |
169 | format.setAlphaBufferSize(alphaSize); |
170 | format.setDepthBufferSize(depthSize); |
171 | format.setStencilBufferSize(stencilSize); |
172 | format.setSamples(sampleCount); |
173 | format.setPlane(level); |
174 | format.setDirectRendering(true); // All EGL contexts are direct-rendered |
175 | format.setRgba(true); // EGL doesn't support colour index rendering |
176 | format.setStereo(false); // EGL doesn't support stereo buffers |
177 | format.setAccumBufferSize(0); // EGL doesn't support accululation buffers |
178 | format.setDoubleBuffer(true); // We don't support single buffered EGL contexts |
179 | |
180 | // Clear the EGL error state because some of the above may |
181 | // have errored out because the attribute is not applicable |
182 | // to the surface type. Such errors don't matter. |
183 | eglGetError(); |
184 | } |
185 | |
186 | bool QGLFormat::hasOpenGL() |
187 | { |
188 | return true; |
189 | } |
190 | |
191 | void QGLContext::reset() |
192 | { |
193 | Q_D(QGLContext); |
194 | if (!d->valid) |
195 | return; |
196 | d->cleanup(); |
197 | doneCurrent(); |
198 | if (d->eglContext && d->ownsEglContext) { |
199 | d->destroyEglSurfaceForDevice(); |
200 | delete d->eglContext; |
201 | } |
202 | d->ownsEglContext = false; |
203 | d->eglContext = 0; |
204 | d->eglSurface = EGL_NO_SURFACE; |
205 | d->crWin = false; |
206 | d->sharing = false; |
207 | d->valid = false; |
208 | d->transpColor = QColor(); |
209 | d->initDone = false; |
210 | QGLContextGroup::removeShare(this); |
211 | } |
212 | |
213 | void QGLContext::makeCurrent() |
214 | { |
215 | Q_D(QGLContext); |
216 | if (!d->valid || !d->eglContext || d->eglSurfaceForDevice() == EGL_NO_SURFACE) { |
217 | qWarning("QGLContext::makeCurrent(): Cannot make invalid context current"); |
218 | return; |
219 | } |
220 | |
221 | if (d->eglContext->makeCurrent(d->eglSurfaceForDevice())) { |
222 | QGLContextPrivate::setCurrentContext(this); |
223 | if (!d->workaroundsCached) { |
224 | d->workaroundsCached = true; |
225 | const char *renderer = reinterpret_cast<const char *>(glGetString(GL_RENDERER)); |
226 | if (!renderer) |
227 | return; |
228 | if ((strstr(renderer, "SGX") || strstr(renderer, "MBX"))) { |
229 | // PowerVR MBX/SGX chips needs to clear all buffers when starting to render |
230 | // a new frame, otherwise there will be a performance penalty to pay for |
231 | // each frame. |
232 | qDebug() << "Found SGX/MBX driver, enabling FullClearOnEveryFrame"; |
233 | d->workaround_needsFullClearOnEveryFrame = true; |
234 | |
235 | // Older PowerVR SGX drivers (like the one in the N900) have a |
236 | // bug which prevents glCopyTexSubImage2D() to work with a POT |
237 | // or GL_ALPHA texture bound to an FBO. The only way to |
238 | // identify that driver is to check the EGL version number for it. |
239 | const char *egl_version = eglQueryString(d->eglContext->display(), EGL_VERSION); |
240 | |
241 | if (egl_version && strstr(egl_version, "1.3")) { |
242 | qDebug() << "Found v1.3 driver, enabling brokenFBOReadBack"; |
243 | d->workaround_brokenFBOReadBack = true; |
244 | } else if (egl_version && strstr(egl_version, "1.4")) { |
245 | qDebug() << "Found v1.4 driver, enabling brokenTexSubImage"; |
246 | d->workaround_brokenTexSubImage = true; |
247 | |
248 | // this is a bit complicated; 1.4 version SGX drivers from |
249 | // Nokia have fixed the brokenFBOReadBack problem, but |
250 | // official drivers from TI haven't, meaning that things |
251 | // like the beagleboard are broken unless we hack around it |
252 | // - but at the same time, we want to not reduce performance |
253 | // by not enabling this elsewhere. |
254 | // |
255 | // so, let's check for a Nokia-specific addon, and only |
256 | // enable if it isn't present. |
257 | // (see MeeGo bug #5616) |
258 | if (!QEgl::hasExtension("EGL_NOK_image_shared")) { |
259 | // no Nokia extension, this is probably a standard SGX |
260 | // driver, so enable the workaround |
261 | qDebug() << "Found non-Nokia v1.4 driver, enabling brokenFBOReadBack"; |
262 | d->workaround_brokenFBOReadBack = true; |
263 | } |
264 | } |
265 | } else if (strstr(renderer, "VideoCore III")) { |
266 | // Some versions of VideoCore III drivers seem to pollute and use |
267 | // stencil buffer when using glScissors even if stencil test is disabled. |
268 | // Workaround is to clear stencil buffer before disabling scissoring. |
269 | |
270 | // qDebug() << "Found VideoCore III driver, enabling brokenDisableScissorTest"; |
271 | d->workaround_brokenScissor = true; |
272 | } |
273 | } |
274 | } |
275 | } |
276 | |
277 | void QGLContext::doneCurrent() |
278 | { |
279 | Q_D(QGLContext); |
280 | if (d->eglContext) |
281 | d->eglContext->doneCurrent(); |
282 | |
283 | QGLContextPrivate::setCurrentContext(0); |
284 | } |
285 | |
286 | |
287 | void QGLContext::swapBuffers() const |
288 | { |
289 | Q_D(const QGLContext); |
290 | if (!d->valid || !d->eglContext) |
291 | return; |
292 | |
293 | d->eglContext->swapBuffers(d->eglSurfaceForDevice()); |
294 | } |
295 | |
296 | void QGLContextPrivate::destroyEglSurfaceForDevice() |
297 | { |
298 | if (eglSurface != EGL_NO_SURFACE) { |
299 | #if defined(Q_WS_X11) || defined(Q_OS_SYMBIAN) |
300 | // Make sure we don't call eglDestroySurface on a surface which |
301 | // was created for a different winId. This applies only to QGLWidget |
302 | // paint device, so make sure this is the one we're operating on |
303 | // (as opposed to a QGLWindowSurface use case). |
304 | if (paintDevice && paintDevice->devType() == QInternal::Widget) { |
305 | QWidget *w = static_cast<QWidget *>(paintDevice); |
306 | if (QGLWidget *wgl = qobject_cast<QGLWidget *>(w)) { |
307 | if (wgl->d_func()->eglSurfaceWindowId != wgl->winId()) { |
308 | qWarning("WARNING: Potential EGL surface leak! Not destroying surface."); |
309 | eglSurface = EGL_NO_SURFACE; |
310 | return; |
311 | } |
312 | } |
313 | } |
314 | #endif |
315 | eglDestroySurface(eglContext->display(), eglSurface); |
316 | eglSurface = EGL_NO_SURFACE; |
317 | } |
318 | } |
319 | |
320 | EGLSurface QGLContextPrivate::eglSurfaceForDevice() const |
321 | { |
322 | // If a QPixmapData had to create the QGLContext, we don't have a paintDevice |
323 | if (!paintDevice) |
324 | return eglSurface; |
325 | |
326 | #ifdef Q_WS_X11 |
327 | if (paintDevice->devType() == QInternal::Pixmap) { |
328 | QPixmapData *pmd = static_cast<QPixmap*>(paintDevice)->data_ptr().data(); |
329 | if (pmd->classId() == QPixmapData::X11Class) { |
330 | QX11PixmapData* x11PixmapData = static_cast<QX11PixmapData*>(pmd); |
331 | return (EGLSurface)x11PixmapData->gl_surface; |
332 | } |
333 | } |
334 | #endif |
335 | |
336 | if (paintDevice->devType() == QInternal::Pbuffer) { |
337 | QGLPixelBuffer* pbuf = static_cast<QGLPixelBuffer*>(paintDevice); |
338 | return pbuf->d_func()->pbuf; |
339 | } |
340 | |
341 | return eglSurface; |
342 | } |
343 | |
344 | void QGLContextPrivate::swapRegion(const QRegion ®ion) |
345 | { |
346 | if (!valid || !eglContext) |
347 | return; |
348 | |
349 | eglContext->swapBuffersRegion2NOK(eglSurfaceForDevice(), ®ion); |
350 | } |
351 | |
352 | void QGLContextPrivate::setExtraWindowSurfaceCreationProps(QEglProperties *props) |
353 | { |
354 | extraWindowSurfaceCreationProps = props; |
355 | } |
356 | |
357 | void QGLWidget::setMouseTracking(bool enable) |
358 | { |
359 | QWidget::setMouseTracking(enable); |
360 | } |
361 | |
362 | QColor QGLContext::overlayTransparentColor() const |
363 | { |
364 | return d_func()->transpColor; |
365 | } |
366 | |
367 | uint QGLContext::colorIndex(const QColor &c) const |
368 | { |
369 | Q_UNUSED(c); |
370 | return 0; |
371 | } |
372 | |
373 | void QGLContext::generateFontDisplayLists(const QFont & fnt, int listBase) |
374 | { |
375 | Q_UNUSED(fnt); |
376 | Q_UNUSED(listBase); |
377 | } |
378 | |
379 | void *QGLContext::getProcAddress(const QString &proc) const |
380 | { |
381 | return (void*)eglGetProcAddress(reinterpret_cast<const char *>(proc.toLatin1().data())); |
382 | } |
383 | |
384 | bool QGLWidgetPrivate::renderCxPm(QPixmap*) |
385 | { |
386 | return false; |
387 | } |
388 | |
389 | QT_END_NAMESPACE |
390 |
Warning: That file was not part of the compilation database. It may have many parsing errors.