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 "qgl.h" |
43 | #include <private/qt_s60_p.h> |
44 | #include <private/qpixmap_raster_symbian_p.h> |
45 | #include <private/qimagepixmapcleanuphooks_p.h> |
46 | #include <private/qgl_p.h> |
47 | #include <private/qpaintengine_opengl_p.h> |
48 | #include <private/qwidget_p.h> // to access QWExtra |
49 | #include <private/qnativeimagehandleprovider_p.h> |
50 | #include <private/qapplication_p.h> |
51 | #include <private/qgraphicssystem_p.h> |
52 | #include <private/qgraphicssystemex_symbian_p.h> |
53 | #include "qgl_egl_p.h" |
54 | #include "qpixmapdata_gl_p.h" |
55 | #include "qgltexturepool_p.h" |
56 | #include "qcolormap.h" |
57 | |
58 | |
59 | QT_BEGIN_NAMESPACE |
60 | |
61 | // Turn off "direct to window" rendering if EGL cannot support it. |
62 | #if !defined(EGL_RENDER_BUFFER) || !defined(EGL_SINGLE_BUFFER) |
63 | #if defined(QGL_DIRECT_TO_WINDOW) |
64 | #undef QGL_DIRECT_TO_WINDOW |
65 | #endif |
66 | #endif |
67 | |
68 | // Determine if preserved window contents should be used. |
69 | #if !defined(EGL_SWAP_BEHAVIOR) || !defined(EGL_BUFFER_PRESERVED) |
70 | #if !defined(QGL_NO_PRESERVED_SWAP) |
71 | #define QGL_NO_PRESERVED_SWAP 1 |
72 | #endif |
73 | #endif |
74 | |
75 | Q_OPENGL_EXPORT extern QGLWidget* qt_gl_share_widget(); |
76 | |
77 | /* |
78 | QGLTemporaryContext implementation |
79 | */ |
80 | |
81 | |
82 | class QGLTemporaryContextPrivate |
83 | { |
84 | public: |
85 | bool initialized; |
86 | RWindow *window; |
87 | EGLContext context; |
88 | EGLSurface surface; |
89 | EGLDisplay display; |
90 | }; |
91 | |
92 | QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *) |
93 | : d(new QGLTemporaryContextPrivate) |
94 | { |
95 | d->initialized = false; |
96 | d->window = 0; |
97 | d->context = 0; |
98 | d->surface = 0; |
99 | |
100 | d->display = d->display = QEgl::display(); |
101 | |
102 | EGLConfig config; |
103 | int numConfigs = 0; |
104 | EGLint attribs[] = { |
105 | EGL_SURFACE_TYPE, EGL_WINDOW_BIT, |
106 | #ifdef QT_OPENGL_ES_2 |
107 | EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, |
108 | #endif |
109 | EGL_NONE |
110 | }; |
111 | |
112 | eglChooseConfig(d->display, attribs, &config, 1, &numConfigs); |
113 | if (!numConfigs) { |
114 | qWarning("QGLTemporaryContext: No EGL configurations available."); |
115 | return; |
116 | } |
117 | |
118 | d->window = new RWindow(CCoeEnv::Static()->WsSession()); |
119 | d->window->Construct(CCoeEnv::Static()->RootWin(),(uint)this); |
120 | |
121 | d->surface = eglCreateWindowSurface(d->display, config, (EGLNativeWindowType) d->window, NULL); |
122 | |
123 | if (d->surface == EGL_NO_SURFACE) { |
124 | qWarning("QGLTemporaryContext: Error creating EGL surface."); |
125 | delete d->window; |
126 | d->window = 0; |
127 | return; |
128 | } |
129 | |
130 | EGLint contextAttribs[] = { |
131 | #ifdef QT_OPENGL_ES_2 |
132 | EGL_CONTEXT_CLIENT_VERSION, 2, |
133 | #endif |
134 | EGL_NONE |
135 | }; |
136 | d->context = eglCreateContext(d->display, config, 0, contextAttribs); |
137 | if (d->context != EGL_NO_CONTEXT |
138 | && eglMakeCurrent(d->display, d->surface, d->surface, d->context)) |
139 | { |
140 | d->initialized = true; |
141 | } else { |
142 | qWarning("QGLTemporaryContext: Error creating EGL context."); |
143 | d->window = 0; |
144 | return; |
145 | } |
146 | } |
147 | |
148 | QGLTemporaryContext::~QGLTemporaryContext() |
149 | { |
150 | if (d->initialized) { |
151 | eglMakeCurrent(d->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); |
152 | eglDestroyContext(d->display, d->context); |
153 | eglDestroySurface(d->display, d->surface); |
154 | delete d->window; |
155 | } |
156 | } |
157 | |
158 | bool QGLFormat::hasOpenGLOverlays() |
159 | { |
160 | return false; |
161 | } |
162 | |
163 | // Chooses the EGL config and creates the EGL context |
164 | bool QGLContext::chooseContext(const QGLContext* shareContext) // almost same as in qgl_x11egl.cpp |
165 | { |
166 | Q_D(QGLContext); |
167 | |
168 | if (!device()) |
169 | return false; |
170 | |
171 | int devType = device()->devType(); |
172 | |
173 | if ((devType != QInternal::Widget) && (devType != QInternal::Pbuffer)) { |
174 | qWarning("WARNING: Creating a QGLContext not supported on device type %d", devType); |
175 | return false; |
176 | } |
177 | |
178 | // Get the display and initialize it. |
179 | if (d->eglContext == 0) { |
180 | d->eglContext = new QEglContext(); |
181 | d->ownsEglContext = true; |
182 | d->eglContext->setApi(QEgl::OpenGL); |
183 | |
184 | if (d->glFormat.samples() == EGL_DONT_CARE) { |
185 | // Allow apps to override ability to use multisampling by setting an environment variable. Eg: |
186 | // qputenv("QT_SYMBIAN_DISABLE_GL_MULTISAMPLE", "1"); |
187 | // Added to allow camera app to start with limited memory. |
188 | if (!QSymbianGraphicsSystemEx::hasBCM2727() && !qgetenv("QT_SYMBIAN_DISABLE_GL_MULTISAMPLE").toInt()) { |
189 | // Most likely we have hw support for multisampling |
190 | // so let's enable it. |
191 | d->glFormat.setSampleBuffers(1); |
192 | d->glFormat.setSamples(4); |
193 | } else { |
194 | d->glFormat.setSampleBuffers(0); |
195 | d->glFormat.setSamples(0); |
196 | } |
197 | } |
198 | |
199 | // If the device is a widget with WA_TranslucentBackground set, make sure the glFormat |
200 | // has the alpha channel option set: |
201 | if (devType == QInternal::Widget) { |
202 | QWidget* widget = static_cast<QWidget*>(device()); |
203 | if (widget->testAttribute(Qt::WA_TranslucentBackground)) |
204 | d->glFormat.setAlpha(true); |
205 | } |
206 | |
207 | // Construct the configuration we need for this surface. |
208 | QEglProperties configProps; |
209 | configProps.setDeviceType(devType); |
210 | configProps.setPaintDeviceFormat(device()); |
211 | configProps.setRenderableType(QEgl::OpenGL); |
212 | configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_SWAP_BEHAVIOR_PRESERVED_BIT); |
213 | |
214 | qt_eglproperties_set_glformat(configProps, d->glFormat); |
215 | |
216 | if (!d->eglContext->chooseConfig(configProps, QEgl::BestPixelFormat)) { |
217 | delete d->eglContext; |
218 | d->eglContext = 0; |
219 | return false; |
220 | } |
221 | |
222 | // Create a new context for the configuration. |
223 | QEglContext* eglSharedContext = shareContext ? shareContext->d_func()->eglContext : 0; |
224 | if (!d->eglContext->createContext(eglSharedContext)) { |
225 | delete d->eglContext; |
226 | d->eglContext = 0; |
227 | return false; |
228 | } |
229 | d->sharing = d->eglContext->isSharing(); |
230 | if (d->sharing && shareContext) |
231 | const_cast<QGLContext *>(shareContext)->d_func()->sharing = true; |
232 | } |
233 | |
234 | // Inform the higher layers about the actual format properties |
235 | qt_glformat_from_eglconfig(d->glFormat, d->eglContext->config()); |
236 | |
237 | // Do don't create the EGLSurface for everything. |
238 | // QWidget - yes, create the EGLSurface and store it in QGLContextPrivate::eglSurface |
239 | // QGLWidget - yes, create the EGLSurface and store it in QGLContextPrivate::eglSurface |
240 | // QGLPixelBuffer - no, it creates the surface itself and stores it in QGLPixelBufferPrivate::pbuf |
241 | |
242 | if (devType == QInternal::Widget) { |
243 | if (d->eglSurface != EGL_NO_SURFACE) |
244 | eglDestroySurface(d->eglContext->display(), d->eglSurface); |
245 | |
246 | d->eglSurface = QEgl::createSurface(device(), d->eglContext->config()); |
247 | |
248 | eglGetError(); // Clear error state first. |
249 | |
250 | #ifdef QGL_NO_PRESERVED_SWAP |
251 | eglSurfaceAttrib(QEgl::display(), d->eglSurface, |
252 | EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED); |
253 | |
254 | if (eglGetError() != EGL_SUCCESS) |
255 | qWarning("QGLContext: could not enable destroyed swap behaviour"); |
256 | #else |
257 | eglSurfaceAttrib(QEgl::display(), d->eglSurface, |
258 | EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED); |
259 | |
260 | if (eglGetError() != EGL_SUCCESS) |
261 | qWarning("QGLContext: could not enable preserved swap behaviour"); |
262 | #endif |
263 | |
264 | setWindowCreated(true); |
265 | } |
266 | |
267 | return true; |
268 | } |
269 | |
270 | void QGLWidget::resizeEvent(QResizeEvent *e) |
271 | { |
272 | Q_D(QGLWidget); |
273 | if (!isValid()) |
274 | return; |
275 | |
276 | // Shared widget can ignore resize events which |
277 | // may happen due to orientation change |
278 | if (this == qt_gl_share_widget()) |
279 | return; |
280 | |
281 | if (!d->surfaceSizeInitialized || e->oldSize() != e->size()) { |
282 | // On Symbian we need to recreate the surface on resize. |
283 | d->recreateEglSurface(); |
284 | d->surfaceSizeInitialized = true; |
285 | } |
286 | |
287 | makeCurrent(); |
288 | |
289 | if (!d->glcx->initialized()) |
290 | glInit(); |
291 | |
292 | resizeGL(width(), height()); |
293 | } |
294 | |
295 | const QGLContext* QGLWidget::overlayContext() const |
296 | { |
297 | return 0; |
298 | } |
299 | |
300 | void QGLWidget::makeOverlayCurrent() |
301 | { |
302 | //handle overlay |
303 | } |
304 | |
305 | void QGLWidget::updateOverlayGL() |
306 | { |
307 | //handle overlay |
308 | } |
309 | |
310 | void QGLWidget::setContext(QGLContext *context, const QGLContext* shareContext, bool deleteOldContext) |
311 | { |
312 | Q_D(QGLWidget); |
313 | if (context == 0) { |
314 | qWarning("QGLWidget::setContext: Cannot set null context"); |
315 | return; |
316 | } |
317 | if (!context->deviceIsPixmap() && context->device() != this) { |
318 | qWarning("QGLWidget::setContext: Context must refer to this widget"); |
319 | return; |
320 | } |
321 | |
322 | if (d->glcx) |
323 | d->glcx->doneCurrent(); |
324 | QGLContext* oldcx = d->glcx; |
325 | d->glcx = context; |
326 | |
327 | bool createFailed = false; |
328 | if (!d->glcx->isValid()) { |
329 | // Create the QGLContext here, which in turn chooses the EGL config |
330 | // and creates the EGL context: |
331 | if (!d->glcx->create(shareContext ? shareContext : oldcx)) |
332 | createFailed = true; |
333 | } |
334 | if (createFailed) { |
335 | if (deleteOldContext) |
336 | delete oldcx; |
337 | return; |
338 | } |
339 | |
340 | d->eglSurfaceWindowId = winId(); // Remember the window id we created the surface for |
341 | } |
342 | |
343 | void QGLWidgetPrivate::init(QGLContext *context, const QGLWidget* shareWidget) |
344 | { |
345 | Q_Q(QGLWidget); |
346 | |
347 | initContext(context, shareWidget); |
348 | |
349 | if(q->isValid() && glcx->format().hasOverlay()) { |
350 | //no overlay |
351 | qWarning("QtOpenGL ES doesn't currently support overlays"); |
352 | } |
353 | } |
354 | |
355 | void QGLWidgetPrivate::cleanupColormaps() |
356 | { |
357 | } |
358 | |
359 | const QGLColormap & QGLWidget::colormap() const |
360 | { |
361 | return d_func()->cmap; |
362 | } |
363 | |
364 | void QGLWidget::setColormap(const QGLColormap &) |
365 | { |
366 | } |
367 | |
368 | void QGLWidgetPrivate::recreateEglSurface() |
369 | { |
370 | Q_Q(QGLWidget); |
371 | |
372 | WId currentId = q->winId(); |
373 | |
374 | if (glcx->d_func()->eglSurface != EGL_NO_SURFACE) { |
375 | if (glcx == QGLContext::currentContext()) |
376 | glcx->doneCurrent(); |
377 | |
378 | eglDestroySurface(glcx->d_func()->eglContext->display(), |
379 | glcx->d_func()->eglSurface); |
380 | } |
381 | |
382 | glcx->d_func()->eglSurface = QEgl::createSurface(glcx->device(), |
383 | glcx->d_func()->eglContext->config()); |
384 | |
385 | #if !defined(QGL_NO_PRESERVED_SWAP) |
386 | eglGetError(); // Clear error state first. |
387 | eglSurfaceAttrib(QEgl::display(), glcx->d_func()->eglSurface, |
388 | EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED); |
389 | if (eglGetError() != EGL_SUCCESS) { |
390 | qWarning("QGLContext: could not enable preserved swap"); |
391 | } |
392 | #endif |
393 | |
394 | eglSurfaceWindowId = currentId; |
395 | } |
396 | |
397 | QT_END_NAMESPACE |
398 |
Warning: That file was not part of the compilation database. It may have many parsing errors.