source: trunk/src/gui/egl/qegl.cpp

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

  • Property svn:eol-style set to native
File size: 25.4 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include <QtGui/qpaintdevice.h>
43#include <QtGui/qpixmap.h>
44#include <QtGui/qwidget.h>
45#include <QtCore/qatomic.h>
46#include <QtCore/qdebug.h>
47
48#include "qegl_p.h"
49#include "qeglcontext_p.h"
50
51
52QT_BEGIN_NAMESPACE
53
54
55/*
56 QEglContextTracker is used to track the EGL contexts that we
57 create internally in Qt, so that we can call eglTerminate() to
58 free additional EGL resources when the last context is destroyed.
59*/
60
61class QEglContextTracker
62{
63public:
64 static void ref() { contexts.ref(); }
65 static void deref() {
66 if (!contexts.deref()) {
67 eglTerminate(QEgl::display());
68 displayOpen = 0;
69 }
70 }
71 static void setDisplayOpened() { displayOpen = 1; }
72 static bool displayOpened() { return displayOpen; }
73
74private:
75 static QBasicAtomicInt contexts;
76 static QBasicAtomicInt displayOpen;
77};
78
79QBasicAtomicInt QEglContextTracker::contexts = Q_BASIC_ATOMIC_INITIALIZER(0);
80QBasicAtomicInt QEglContextTracker::displayOpen = Q_BASIC_ATOMIC_INITIALIZER(0);
81
82// Current GL and VG contexts. These are used to determine if
83// we can avoid an eglMakeCurrent() after a call to lazyDoneCurrent().
84// If a background thread modifies the value, the worst that will
85// happen is a redundant eglMakeCurrent() in the foreground thread.
86static QEglContext * volatile currentGLContext = 0;
87static QEglContext * volatile currentVGContext = 0;
88
89QEglContext::QEglContext()
90 : apiType(QEgl::OpenGL)
91 , ctx(EGL_NO_CONTEXT)
92 , cfg(QEGL_NO_CONFIG)
93 , currentSurface(EGL_NO_SURFACE)
94 , current(false)
95 , ownsContext(true)
96 , sharing(false)
97{
98 QEglContextTracker::ref();
99}
100
101QEglContext::~QEglContext()
102{
103 destroyContext();
104
105 if (currentGLContext == this)
106 currentGLContext = 0;
107 if (currentVGContext == this)
108 currentVGContext = 0;
109 QEglContextTracker::deref();
110}
111
112bool QEglContext::isValid() const
113{
114 return (ctx != EGL_NO_CONTEXT);
115}
116
117bool QEglContext::isCurrent() const
118{
119 return current;
120}
121
122EGLConfig QEgl::defaultConfig(int devType, API api, ConfigOptions options)
123{
124 if ( (devType != QInternal::Pixmap) && ((options & Renderable) == 0))
125 qWarning("QEgl::defaultConfig() - Only configs for pixmaps make sense to be read-only!");
126
127 EGLConfig* targetConfig = 0;
128
129 static EGLConfig defaultVGConfigs[] = {
130 QEGL_NO_CONFIG, // 0 Window Renderable Translucent
131 QEGL_NO_CONFIG, // 1 Window Renderable Opaque
132 QEGL_NO_CONFIG, // 2 Pixmap Renderable Translucent
133 QEGL_NO_CONFIG, // 3 Pixmap Renderable Opaque
134 QEGL_NO_CONFIG, // 4 Pixmap ReadOnly Translucent
135 QEGL_NO_CONFIG // 5 Pixmap ReadOnly Opaque
136 };
137 if (api == OpenVG) {
138 if (devType == QInternal::Widget) {
139 if (options & Translucent)
140 targetConfig = &(defaultVGConfigs[0]);
141 else
142 targetConfig = &(defaultVGConfigs[1]);
143 } else if (devType == QInternal::Pixmap) {
144 if (options & Renderable) {
145 if (options & Translucent)
146 targetConfig = &(defaultVGConfigs[2]);
147 else // Opaque
148 targetConfig = &(defaultVGConfigs[3]);
149 } else { // Read-only
150 if (options & Translucent)
151 targetConfig = &(defaultVGConfigs[4]);
152 else // Opaque
153 targetConfig = &(defaultVGConfigs[5]);
154 }
155 }
156 }
157
158
159 static EGLConfig defaultGLConfigs[] = {
160 QEGL_NO_CONFIG, // 0 Window Renderable Translucent
161 QEGL_NO_CONFIG, // 1 Window Renderable Opaque
162 QEGL_NO_CONFIG, // 2 PBuffer Renderable Translucent
163 QEGL_NO_CONFIG, // 3 PBuffer Renderable Opaque
164 QEGL_NO_CONFIG, // 4 Pixmap Renderable Translucent
165 QEGL_NO_CONFIG, // 5 Pixmap Renderable Opaque
166 QEGL_NO_CONFIG, // 6 Pixmap ReadOnly Translucent
167 QEGL_NO_CONFIG // 7 Pixmap ReadOnly Opaque
168 };
169 if (api == OpenGL) {
170 if (devType == QInternal::Widget) {
171 if (options & Translucent)
172 targetConfig = &(defaultGLConfigs[0]);
173 else // Opaque
174 targetConfig = &(defaultGLConfigs[1]);
175 } else if (devType == QInternal::Pbuffer) {
176 if (options & Translucent)
177 targetConfig = &(defaultGLConfigs[2]);
178 else // Opaque
179 targetConfig = &(defaultGLConfigs[3]);
180 } else if (devType == QInternal::Pixmap) {
181 if (options & Renderable) {
182 if (options & Translucent)
183 targetConfig = &(defaultGLConfigs[4]);
184 else // Opaque
185 targetConfig = &(defaultGLConfigs[5]);
186 } else { // ReadOnly
187 if (options & Translucent)
188 targetConfig = &(defaultGLConfigs[6]);
189 else // Opaque
190 targetConfig = &(defaultGLConfigs[7]);
191 }
192 }
193 }
194
195 if (!targetConfig) {
196 qWarning("QEgl::defaultConfig() - No default config for device/api/options combo");
197 return QEGL_NO_CONFIG;
198 }
199 if (*targetConfig != QEGL_NO_CONFIG)
200 return *targetConfig;
201
202
203 // We haven't found an EGL config for the target config yet, so do it now:
204
205
206 // Allow overriding from an environment variable:
207 QByteArray configId;
208 if (api == OpenVG)
209 configId = qgetenv("QT_VG_EGL_CONFIG");
210 else
211 configId = qgetenv("QT_GL_EGL_CONFIG");
212 if (!configId.isEmpty()) {
213 // Overridden, so get the EGLConfig for the specified config ID:
214 EGLint properties[] = {
215 EGL_CONFIG_ID, (EGLint)configId.toInt(),
216 EGL_NONE
217 };
218 EGLint configCount = 0;
219 eglChooseConfig(display(), properties, targetConfig, 1, &configCount);
220 if (configCount > 0)
221 return *targetConfig;
222 qWarning() << "QEgl::defaultConfig() -" << configId << "appears to be invalid";
223 }
224
225 QEglProperties configAttribs;
226 configAttribs.setRenderableType(api);
227
228 EGLint surfaceType;
229 switch (devType) {
230 case QInternal::Widget:
231 surfaceType = EGL_WINDOW_BIT;
232 break;
233 case QInternal::Pixmap:
234 surfaceType = EGL_PIXMAP_BIT;
235 break;
236 case QInternal::Pbuffer:
237 surfaceType = EGL_PBUFFER_BIT;
238 break;
239 default:
240 qWarning("QEgl::defaultConfig() - Can't create EGL surface for %d device type", devType);
241 return QEGL_NO_CONFIG;
242 };
243#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT
244 // For OpenVG, we try to create a surface using a pre-multiplied format if
245 // the surface needs to have an alpha channel:
246 if (api == OpenVG && (options & Translucent))
247 surfaceType |= EGL_VG_ALPHA_FORMAT_PRE_BIT;
248#endif
249 configAttribs.setValue(EGL_SURFACE_TYPE, surfaceType);
250
251#ifdef EGL_BIND_TO_TEXTURE_RGBA
252 if (devType == QInternal::Pixmap || devType == QInternal::Pbuffer) {
253 if (options & Translucent)
254 configAttribs.setValue(EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE);
255 else
256 configAttribs.setValue(EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE);
257 }
258#endif
259
260 // Add paint engine requirements
261 if (api == OpenVG) {
262#if !defined(QVG_SCISSOR_CLIP) && defined(EGL_ALPHA_MASK_SIZE)
263 configAttribs.setValue(EGL_ALPHA_MASK_SIZE, 1);
264#endif
265 } else {
266 // Both OpenGL paint engines need to have stencil and sample buffers
267 configAttribs.setValue(EGL_STENCIL_SIZE, 1);
268 configAttribs.setValue(EGL_SAMPLE_BUFFERS, 1);
269#ifndef QT_OPENGL_ES_2
270 // Additionally, the GL1 engine likes to have a depth buffer for clipping
271 configAttribs.setValue(EGL_DEPTH_SIZE, 1);
272#endif
273 }
274
275 if (options & Translucent)
276 configAttribs.setValue(EGL_ALPHA_SIZE, 1);
277
278 *targetConfig = chooseConfig(&configAttribs, QEgl::BestPixelFormat);
279 return *targetConfig;
280}
281
282
283// Choose a configuration that matches "properties".
284EGLConfig QEgl::chooseConfig(const QEglProperties* properties, QEgl::PixelFormatMatch match)
285{
286 QEglProperties props(*properties);
287 EGLConfig cfg = QEGL_NO_CONFIG;
288 do {
289 // Get the number of matching configurations for this set of properties.
290 EGLint matching = 0;
291 EGLDisplay dpy = QEgl::display();
292 if (!eglChooseConfig(dpy, props.properties(), 0, 0, &matching) || !matching)
293 continue;
294
295 // If we want the best pixel format, then return the first
296 // matching configuration.
297 if (match == QEgl::BestPixelFormat) {
298 eglChooseConfig(display(), props.properties(), &cfg, 1, &matching);
299 if (matching < 1)
300 continue;
301 return cfg;
302 }
303
304 // Fetch all of the matching configurations and find the
305 // first that matches the pixel format we wanted.
306 EGLint size = matching;
307 EGLConfig *configs = new EGLConfig [size];
308 eglChooseConfig(display(), props.properties(), configs, size, &matching);
309 for (EGLint index = 0; index < size; ++index) {
310 EGLint red, green, blue, alpha;
311 eglGetConfigAttrib(display(), configs[index], EGL_RED_SIZE, &red);
312 eglGetConfigAttrib(display(), configs[index], EGL_GREEN_SIZE, &green);
313 eglGetConfigAttrib(display(), configs[index], EGL_BLUE_SIZE, &blue);
314 eglGetConfigAttrib(display(), configs[index], EGL_ALPHA_SIZE, &alpha);
315 if (red == props.value(EGL_RED_SIZE) &&
316 green == props.value(EGL_GREEN_SIZE) &&
317 blue == props.value(EGL_BLUE_SIZE) &&
318 (props.value(EGL_ALPHA_SIZE) == 0 ||
319 alpha == props.value(EGL_ALPHA_SIZE))) {
320 cfg = configs[index];
321 delete [] configs;
322 return cfg;
323 }
324 }
325 delete [] configs;
326 } while (props.reduceConfiguration());
327
328#ifdef EGL_BIND_TO_TEXTURE_RGBA
329 // Don't report an error just yet if we failed to get a pbuffer
330 // configuration with texture rendering. Only report failure if
331 // we cannot get any pbuffer configurations at all.
332 if (props.value(EGL_BIND_TO_TEXTURE_RGBA) == EGL_DONT_CARE &&
333 props.value(EGL_BIND_TO_TEXTURE_RGB) == EGL_DONT_CARE)
334#endif
335 {
336 qWarning() << "QEglContext::chooseConfig(): Could not find a suitable EGL configuration";
337 qWarning() << "Requested:" << props.toString();
338 qWarning() << "Available:";
339 QEgl::dumpAllConfigs();
340 }
341 return QEGL_NO_CONFIG;
342}
343
344bool QEglContext::chooseConfig(const QEglProperties& properties, QEgl::PixelFormatMatch match)
345{
346 cfg = QEgl::chooseConfig(&properties, match);
347 return cfg != QEGL_NO_CONFIG;
348}
349
350EGLSurface QEglContext::createSurface(QPaintDevice* device, const QEglProperties *properties)
351{
352 return QEgl::createSurface(device, cfg, properties);
353}
354
355
356// Create the EGLContext.
357bool QEglContext::createContext(QEglContext *shareContext, const QEglProperties *properties)
358{
359 // We need to select the correct API before calling eglCreateContext().
360#ifdef QT_OPENGL_ES
361#ifdef EGL_OPENGL_ES_API
362 if (apiType == QEgl::OpenGL)
363 eglBindAPI(EGL_OPENGL_ES_API);
364#endif
365#else
366#ifdef EGL_OPENGL_API
367 if (apiType == QEgl::OpenGL)
368 eglBindAPI(EGL_OPENGL_API);
369#endif
370#endif //defined(QT_OPENGL_ES)
371#ifdef EGL_OPENVG_API
372 if (apiType == QEgl::OpenVG)
373 eglBindAPI(EGL_OPENVG_API);
374#endif
375
376 // Create a new context for the configuration.
377 QEglProperties contextProps;
378 if (properties)
379 contextProps = *properties;
380#ifdef QT_OPENGL_ES_2
381 if (apiType == QEgl::OpenGL)
382 contextProps.setValue(EGL_CONTEXT_CLIENT_VERSION, 2);
383#endif
384 sharing = false;
385 if (shareContext && shareContext->ctx == EGL_NO_CONTEXT)
386 shareContext = 0;
387 if (shareContext) {
388 ctx = eglCreateContext(QEgl::display(), cfg, shareContext->ctx, contextProps.properties());
389 if (ctx == EGL_NO_CONTEXT) {
390 qWarning() << "QEglContext::createContext(): Could not share context:" << QEgl::errorString();
391 shareContext = 0;
392 } else {
393 sharing = true;
394 }
395 }
396 if (ctx == EGL_NO_CONTEXT) {
397 ctx = eglCreateContext(display(), cfg, 0, contextProps.properties());
398 if (ctx == EGL_NO_CONTEXT) {
399 qWarning() << "QEglContext::createContext(): Unable to create EGL context:" << QEgl::errorString();
400 return false;
401 }
402 }
403 return true;
404}
405
406// Destroy an EGL surface object. If it was current on this context
407// then call doneCurrent() for it first.
408void QEglContext::destroySurface(EGLSurface surface)
409{
410 if (surface != EGL_NO_SURFACE) {
411 if (surface == currentSurface)
412 doneCurrent();
413 eglDestroySurface(display(), surface);
414 }
415}
416
417// Destroy the context. Note: this does not destroy the surface.
418void QEglContext::destroyContext()
419{
420 if (ctx != EGL_NO_CONTEXT && ownsContext)
421 eglDestroyContext(display(), ctx);
422 ctx = EGL_NO_CONTEXT;
423 cfg = 0;
424}
425
426bool QEglContext::makeCurrent(EGLSurface surface)
427{
428 if (ctx == EGL_NO_CONTEXT) {
429 qWarning() << "QEglContext::makeCurrent(): Cannot make invalid context current";
430 return false;
431 }
432
433 if (surface == EGL_NO_SURFACE) {
434 qWarning() << "QEglContext::makeCurrent(): Cannot make invalid surface current";
435 return false;
436 }
437
438 // If lazyDoneCurrent() was called on the surface, then we may be able
439 // to assume that it is still current within the thread.
440 if (surface == currentSurface && currentContext(apiType) == this) {
441 current = true;
442 return true;
443 }
444
445 current = true;
446 currentSurface = surface;
447 setCurrentContext(apiType, this);
448
449 // Force the right API to be bound before making the context current.
450 // The EGL implementation should be able to figure this out from ctx,
451 // but some systems require the API to be explicitly set anyway.
452#ifdef EGL_OPENGL_ES_API
453 if (apiType == QEgl::OpenGL)
454 eglBindAPI(EGL_OPENGL_ES_API);
455#endif
456#ifdef EGL_OPENVG_API
457 if (apiType == QEgl::OpenVG)
458 eglBindAPI(EGL_OPENVG_API);
459#endif
460
461 bool ok = eglMakeCurrent(QEgl::display(), surface, surface, ctx);
462 if (!ok)
463 qWarning() << "QEglContext::makeCurrent(" << surface << "):" << QEgl::errorString();
464 return ok;
465}
466
467bool QEglContext::doneCurrent()
468{
469 // If the context is invalid, we assume that an error was reported
470 // when makeCurrent() was called.
471 if (ctx == EGL_NO_CONTEXT)
472 return false;
473
474 current = false;
475 currentSurface = EGL_NO_SURFACE;
476 setCurrentContext(apiType, 0);
477
478 // We need to select the correct API before calling eglMakeCurrent()
479 // with EGL_NO_CONTEXT because threads can have both OpenGL and OpenVG
480 // contexts active at the same time.
481#ifdef EGL_OPENGL_ES_API
482 if (apiType == QEgl::OpenGL)
483 eglBindAPI(EGL_OPENGL_ES_API);
484#endif
485#ifdef EGL_OPENVG_API
486 if (apiType == QEgl::OpenVG)
487 eglBindAPI(EGL_OPENVG_API);
488#endif
489
490 bool ok = eglMakeCurrent(QEgl::display(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
491 if (!ok)
492 qWarning() << "QEglContext::doneCurrent():" << QEgl::errorString();
493 return ok;
494}
495
496// Act as though doneCurrent() was called, but keep the context
497// and the surface active for the moment. This allows makeCurrent()
498// to skip a call to eglMakeCurrent() if we are using the same
499// surface as the last set of painting operations. We leave the
500// currentContext() pointer as-is for now.
501bool QEglContext::lazyDoneCurrent()
502{
503 current = false;
504 return true;
505}
506
507bool QEglContext::swapBuffers(EGLSurface surface)
508{
509 if(ctx == EGL_NO_CONTEXT)
510 return false;
511
512 bool ok = eglSwapBuffers(QEgl::display(), surface);
513 if (!ok)
514 qWarning() << "QEglContext::swapBuffers():" << QEgl::errorString();
515 return ok;
516}
517
518bool QEglContext::swapBuffersRegion2NOK(EGLSurface surface, const QRegion *region) {
519 QVector<QRect> qrects = region->rects();
520 EGLint *gl_rects;
521 uint count;
522 uint i;
523
524 count = qrects.size();
525 QVarLengthArray <EGLint> arr(4 * count);
526 gl_rects = arr.data();
527 for (i = 0; i < count; i++) {
528 QRect qrect = qrects[i];
529
530 gl_rects[4 * i + 0] = qrect.x();
531 gl_rects[4 * i + 1] = qrect.y();
532 gl_rects[4 * i + 2] = qrect.width();
533 gl_rects[4 * i + 3] = qrect.height();
534 }
535
536 bool ok = QEgl::eglSwapBuffersRegion2NOK(QEgl::display(), surface, count, gl_rects);
537
538 if (!ok)
539 qWarning() << "QEglContext::swapBuffersRegion2NOK():" << QEgl::errorString();
540 return ok;
541}
542
543int QEglContext::configAttrib(int name) const
544{
545 EGLint value;
546 EGLBoolean success = eglGetConfigAttrib(QEgl::display(), cfg, name, &value);
547 if (success)
548 return value;
549 else
550 return EGL_DONT_CARE;
551}
552
553typedef EGLImageKHR (EGLAPIENTRY *_eglCreateImageKHR)(EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, const EGLint*);
554typedef EGLBoolean (EGLAPIENTRY *_eglDestroyImageKHR)(EGLDisplay, EGLImageKHR);
555
556// Defined in qegl.cpp:
557static _eglCreateImageKHR qt_eglCreateImageKHR = 0;
558static _eglDestroyImageKHR qt_eglDestroyImageKHR = 0;
559
560typedef EGLBoolean (EGLAPIENTRY *_eglSwapBuffersRegion2NOK)(EGLDisplay, EGLSurface, EGLint, const EGLint*);
561
562static _eglSwapBuffersRegion2NOK qt_eglSwapBuffersRegion2NOK = 0;
563
564EGLDisplay QEgl::display()
565{
566 static EGLDisplay dpy = EGL_NO_DISPLAY;
567 if (!QEglContextTracker::displayOpened()) {
568 dpy = eglGetDisplay(nativeDisplay());
569 QEglContextTracker::setDisplayOpened();
570 if (dpy == EGL_NO_DISPLAY) {
571 qWarning("QEgl::display(): Falling back to EGL_DEFAULT_DISPLAY");
572 dpy = eglGetDisplay(EGLNativeDisplayType(EGL_DEFAULT_DISPLAY));
573 }
574 if (dpy == EGL_NO_DISPLAY) {
575 qWarning("QEgl::display(): Can't even open the default display");
576 return EGL_NO_DISPLAY;
577 }
578
579 if (!eglInitialize(dpy, NULL, NULL)) {
580 qWarning() << "QEgl::display(): Cannot initialize EGL display:" << QEgl::errorString();
581 return EGL_NO_DISPLAY;
582 }
583
584 // Resolve the egl extension function pointers:
585#if (defined(EGL_KHR_image) || defined(EGL_KHR_image_base)) && !defined(EGL_EGLEXT_PROTOTYPES)
586 if (QEgl::hasExtension("EGL_KHR_image") || QEgl::hasExtension("EGL_KHR_image_base")) {
587 qt_eglCreateImageKHR = (_eglCreateImageKHR) eglGetProcAddress("eglCreateImageKHR");
588 qt_eglDestroyImageKHR = (_eglDestroyImageKHR) eglGetProcAddress("eglDestroyImageKHR");
589 }
590#endif
591
592 if (QEgl::hasExtension("EGL_NOK_swap_region2")) {
593 qt_eglSwapBuffersRegion2NOK = (_eglSwapBuffersRegion2NOK) eglGetProcAddress("eglSwapBuffersRegion2NOK");
594 }
595 }
596
597 return dpy;
598}
599
600EGLImageKHR QEgl::eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
601{
602 if (qt_eglCreateImageKHR)
603 return qt_eglCreateImageKHR(dpy, ctx, target, buffer, attrib_list);
604
605 QEgl::display(); // Initialises function pointers
606 if (qt_eglCreateImageKHR)
607 return qt_eglCreateImageKHR(dpy, ctx, target, buffer, attrib_list);
608
609 qWarning("QEgl::eglCreateImageKHR() called but EGL_KHR_image(_base) extension not present");
610 return 0;
611}
612
613EGLBoolean QEgl::eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
614{
615 if (qt_eglDestroyImageKHR)
616 return qt_eglDestroyImageKHR(dpy, img);
617
618 QEgl::display(); // Initialises function pointers
619 if (qt_eglDestroyImageKHR)
620 return qt_eglDestroyImageKHR(dpy, img);
621
622 qWarning("QEgl::eglDestroyImageKHR() called but EGL_KHR_image(_base) extension not present");
623 return 0;
624}
625
626EGLBoolean QEgl::eglSwapBuffersRegion2NOK(EGLDisplay dpy, EGLSurface surface, EGLint count, const EGLint *rects)
627{
628 if (qt_eglSwapBuffersRegion2NOK)
629 return qt_eglSwapBuffersRegion2NOK(dpy, surface, count, rects);
630
631 QEgl::display(); // Initialises function pointers
632 if (qt_eglSwapBuffersRegion2NOK)
633 return qt_eglSwapBuffersRegion2NOK(dpy, surface, count, rects);
634
635 qWarning("QEgl::eglSwapBuffersRegion2NOK() called but EGL_NOK_swap_region2 extension not present");
636 return 0;
637}
638
639#ifndef Q_WS_X11
640EGLSurface QEgl::createSurface(QPaintDevice *device, EGLConfig cfg, const QEglProperties *properties)
641{
642 // Create the native drawable for the paint device.
643 int devType = device->devType();
644 EGLNativePixmapType pixmapDrawable = 0;
645 EGLNativeWindowType windowDrawable = 0;
646 bool ok;
647 if (devType == QInternal::Pixmap) {
648 pixmapDrawable = nativePixmap(static_cast<QPixmap *>(device));
649 ok = (pixmapDrawable != 0);
650 } else if (devType == QInternal::Widget) {
651 windowDrawable = nativeWindow(static_cast<QWidget *>(device));
652 ok = (windowDrawable != 0);
653 } else {
654 ok = false;
655 }
656 if (!ok) {
657 qWarning("QEglContext::createSurface(): Cannot create the native EGL drawable");
658 return EGL_NO_SURFACE;
659 }
660
661 // Create the EGL surface to draw into, based on the native drawable.
662 const int *props;
663 if (properties)
664 props = properties->properties();
665 else
666 props = 0;
667 EGLSurface surf;
668 if (devType == QInternal::Widget)
669 surf = eglCreateWindowSurface(QEgl::display(), cfg, windowDrawable, props);
670 else
671 surf = eglCreatePixmapSurface(QEgl::display(), cfg, pixmapDrawable, props);
672 if (surf == EGL_NO_SURFACE) {
673 qWarning("QEglContext::createSurface(): Unable to create EGL surface, error = 0x%x", eglGetError());
674 }
675 return surf;
676}
677#endif
678
679
680// Return the error string associated with a specific code.
681QString QEgl::errorString(EGLint code)
682{
683 static const char * const errors[] = {
684 "Success (0x3000)", // No tr
685 "Not initialized (0x3001)", // No tr
686 "Bad access (0x3002)", // No tr
687 "Bad alloc (0x3003)", // No tr
688 "Bad attribute (0x3004)", // No tr
689 "Bad config (0x3005)", // No tr
690 "Bad context (0x3006)", // No tr
691 "Bad current surface (0x3007)", // No tr
692 "Bad display (0x3008)", // No tr
693 "Bad match (0x3009)", // No tr
694 "Bad native pixmap (0x300A)", // No tr
695 "Bad native window (0x300B)", // No tr
696 "Bad parameter (0x300C)", // No tr
697 "Bad surface (0x300D)", // No tr
698 "Context lost (0x300E)" // No tr
699 };
700 if (code >= 0x3000 && code <= 0x300E) {
701 return QString::fromLatin1(errors[code - 0x3000]);
702 } else {
703 return QLatin1String("0x") + QString::number(int(code), 16);
704 }
705}
706
707// Dump all of the EGL configurations supported by the system.
708void QEgl::dumpAllConfigs()
709{
710 QEglProperties props;
711 EGLint count = 0;
712 if (!eglGetConfigs(display(), 0, 0, &count) || count < 1)
713 return;
714 EGLConfig *configs = new EGLConfig [count];
715 eglGetConfigs(display(), configs, count, &count);
716 for (EGLint index = 0; index < count; ++index) {
717 props = QEglProperties(configs[index]);
718 qWarning() << props.toString();
719 }
720 delete [] configs;
721}
722
723QString QEgl::extensions()
724{
725 const char* exts = eglQueryString(QEgl::display(), EGL_EXTENSIONS);
726 return QString(QLatin1String(exts));
727}
728
729bool QEgl::hasExtension(const char* extensionName)
730{
731 QList<QByteArray> extensions =
732 QByteArray(reinterpret_cast<const char *>
733 (eglQueryString(QEgl::display(), EGL_EXTENSIONS))).split(' ');
734 return extensions.contains(extensionName);
735}
736
737QEglContext *QEglContext::currentContext(QEgl::API api)
738{
739 if (api == QEgl::OpenGL)
740 return currentGLContext;
741 else
742 return currentVGContext;
743}
744
745void QEglContext::setCurrentContext(QEgl::API api, QEglContext *context)
746{
747 if (api == QEgl::OpenGL)
748 currentGLContext = context;
749 else
750 currentVGContext = context;
751}
752
753QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.