Qt 4.8
qegl.cpp
Go to the documentation of this file.
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 QtGui 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 <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 #ifdef Q_OS_SYMBIAN
52 #include "private/qt_s60_p.h"
53 #endif
54 
56 
57 
58 /*
59  QEglContextTracker is used to track the EGL contexts that we
60  create internally in Qt, so that we can call eglTerminate() to
61  free additional EGL resources when the last context is destroyed.
62 */
63 
65 {
66 public:
67  static void ref() { contexts.ref(); }
68  static void deref() {
69  if (!contexts.deref()) {
70  eglTerminate(QEgl::display());
71  displayOpen = 0;
72  }
73  }
74  static void setDisplayOpened() { displayOpen = 1; }
75  static bool displayOpened() { return displayOpen; }
76 
77 private:
80 };
81 
84 
85 // Current GL and VG contexts. These are used to determine if
86 // we can avoid an eglMakeCurrent() after a call to lazyDoneCurrent().
87 // If a background thread modifies the value, the worst that will
88 // happen is a redundant eglMakeCurrent() in the foreground thread.
89 static QEglContext * volatile currentGLContext = 0;
90 static QEglContext * volatile currentVGContext = 0;
91 
93  : apiType(QEgl::OpenGL)
94  , ctx(EGL_NO_CONTEXT)
95  , cfg(QEGL_NO_CONFIG)
96  , currentSurface(EGL_NO_SURFACE)
97  , current(false)
98  , ownsContext(true)
99  , sharing(false)
100  , apiChanged(false)
101 {
103 }
104 
106 {
107  destroyContext();
108 
109  if (currentGLContext == this)
110  currentGLContext = 0;
111  if (currentVGContext == this)
112  currentVGContext = 0;
114 }
115 
117 {
118  return (ctx != EGL_NO_CONTEXT);
119 }
120 
122 {
123  return current;
124 }
125 
126 EGLConfig QEgl::defaultConfig(int devType, API api, ConfigOptions options)
127 {
128  if ( (devType != QInternal::Pixmap) && ((options & Renderable) == 0))
129  qWarning("QEgl::defaultConfig() - Only configs for pixmaps make sense to be read-only!");
130 
131  EGLConfig* targetConfig = 0;
132 
133  static EGLConfig defaultVGConfigs[] = {
134  QEGL_NO_CONFIG, // 0 Window Renderable Translucent
135  QEGL_NO_CONFIG, // 1 Window Renderable Opaque
136  QEGL_NO_CONFIG, // 2 Pixmap Renderable Translucent
137  QEGL_NO_CONFIG, // 3 Pixmap Renderable Opaque
138  QEGL_NO_CONFIG, // 4 Pixmap ReadOnly Translucent
139  QEGL_NO_CONFIG // 5 Pixmap ReadOnly Opaque
140  };
141  if (api == OpenVG) {
142  if (devType == QInternal::Widget) {
143  if (options & Translucent)
144  targetConfig = &(defaultVGConfigs[0]);
145  else
146  targetConfig = &(defaultVGConfigs[1]);
147  } else if (devType == QInternal::Pixmap) {
148  if (options & Renderable) {
149  if (options & Translucent)
150  targetConfig = &(defaultVGConfigs[2]);
151  else // Opaque
152  targetConfig = &(defaultVGConfigs[3]);
153  } else { // Read-only
154  if (options & Translucent)
155  targetConfig = &(defaultVGConfigs[4]);
156  else // Opaque
157  targetConfig = &(defaultVGConfigs[5]);
158  }
159  }
160  }
161 
162 
163  static EGLConfig defaultGLConfigs[] = {
164  QEGL_NO_CONFIG, // 0 Window Renderable Translucent
165  QEGL_NO_CONFIG, // 1 Window Renderable Opaque
166  QEGL_NO_CONFIG, // 2 PBuffer Renderable Translucent
167  QEGL_NO_CONFIG, // 3 PBuffer Renderable Opaque
168  QEGL_NO_CONFIG, // 4 Pixmap Renderable Translucent
169  QEGL_NO_CONFIG, // 5 Pixmap Renderable Opaque
170  QEGL_NO_CONFIG, // 6 Pixmap ReadOnly Translucent
171  QEGL_NO_CONFIG // 7 Pixmap ReadOnly Opaque
172  };
173  if (api == OpenGL) {
174  if (devType == QInternal::Widget) {
175  if (options & Translucent)
176  targetConfig = &(defaultGLConfigs[0]);
177  else // Opaque
178  targetConfig = &(defaultGLConfigs[1]);
179  } else if (devType == QInternal::Pbuffer) {
180  if (options & Translucent)
181  targetConfig = &(defaultGLConfigs[2]);
182  else // Opaque
183  targetConfig = &(defaultGLConfigs[3]);
184  } else if (devType == QInternal::Pixmap) {
185  if (options & Renderable) {
186  if (options & Translucent)
187  targetConfig = &(defaultGLConfigs[4]);
188  else // Opaque
189  targetConfig = &(defaultGLConfigs[5]);
190  } else { // ReadOnly
191  if (options & Translucent)
192  targetConfig = &(defaultGLConfigs[6]);
193  else // Opaque
194  targetConfig = &(defaultGLConfigs[7]);
195  }
196  }
197  }
198 
199  if (!targetConfig) {
200  qWarning("QEgl::defaultConfig() - No default config for device/api/options combo");
201  return QEGL_NO_CONFIG;
202  }
203  if (*targetConfig != QEGL_NO_CONFIG)
204  return *targetConfig;
205 
206 
207  // We haven't found an EGL config for the target config yet, so do it now:
208 
209 
210  // Allow overriding from an environment variable:
211  QByteArray configId;
212  if (api == OpenVG)
213  configId = qgetenv("QT_VG_EGL_CONFIG");
214  else
215  configId = qgetenv("QT_GL_EGL_CONFIG");
216  if (!configId.isEmpty()) {
217  // Overridden, so get the EGLConfig for the specified config ID:
218  EGLint properties[] = {
219  EGL_CONFIG_ID, (EGLint)configId.toInt(),
220  EGL_NONE
221  };
222  EGLint configCount = 0;
223  eglChooseConfig(display(), properties, targetConfig, 1, &configCount);
224  if (configCount > 0)
225  return *targetConfig;
226  qWarning() << "QEgl::defaultConfig() -" << configId << "appears to be invalid";
227  }
228 
229  QEglProperties configAttribs;
230  configAttribs.setRenderableType(api);
231 
232  EGLint surfaceType;
233  switch (devType) {
234  case QInternal::Widget:
235  surfaceType = EGL_WINDOW_BIT;
236  break;
237  case QInternal::Pixmap:
238  surfaceType = EGL_PIXMAP_BIT;
239  break;
240  case QInternal::Pbuffer:
241  surfaceType = EGL_PBUFFER_BIT;
242  break;
243  default:
244  qWarning("QEgl::defaultConfig() - Can't create EGL surface for %d device type", devType);
245  return QEGL_NO_CONFIG;
246  };
247 #ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT
248  // For OpenVG, we try to create a surface using a pre-multiplied format if
249  // the surface needs to have an alpha channel:
250  if (api == OpenVG && (options & Translucent))
251  surfaceType |= EGL_VG_ALPHA_FORMAT_PRE_BIT;
252 #endif
253  configAttribs.setValue(EGL_SURFACE_TYPE, surfaceType);
254 
255 #ifdef EGL_BIND_TO_TEXTURE_RGBA
256  if (devType == QInternal::Pixmap || devType == QInternal::Pbuffer) {
257  if (options & Translucent)
258  configAttribs.setValue(EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE);
259  else
260  configAttribs.setValue(EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE);
261  }
262 #endif
263 
264  // Add paint engine requirements
265  if (api == OpenVG) {
266 #if !defined(QVG_SCISSOR_CLIP) && defined(EGL_ALPHA_MASK_SIZE)
267  configAttribs.setValue(EGL_ALPHA_MASK_SIZE, 1);
268 #endif
269  } else {
270  // Both OpenGL paint engines need to have stencil and sample buffers
271  configAttribs.setValue(EGL_STENCIL_SIZE, 1);
272  configAttribs.setValue(EGL_SAMPLE_BUFFERS, 1);
273 #ifndef QT_OPENGL_ES_2
274  // Additionally, the GL1 engine likes to have a depth buffer for clipping
275  configAttribs.setValue(EGL_DEPTH_SIZE, 1);
276 #endif
277  }
278 
279  if (options & Translucent)
280  configAttribs.setValue(EGL_ALPHA_SIZE, 1);
281 
282  *targetConfig = chooseConfig(&configAttribs, QEgl::BestPixelFormat);
283  return *targetConfig;
284 }
285 
286 
287 // Choose a configuration that matches "properties".
289 {
290  QEglProperties props(*properties);
291  EGLConfig cfg = QEGL_NO_CONFIG;
292  do {
293  // Get the number of matching configurations for this set of properties.
294  EGLint matching = 0;
295  EGLDisplay dpy = QEgl::display();
296  if (!eglChooseConfig(dpy, props.properties(), 0, 0, &matching) || !matching)
297  continue;
298 
299  // If we want the best pixel format, then return the first
300  // matching configuration.
301  if (match == QEgl::BestPixelFormat) {
302  eglChooseConfig(display(), props.properties(), &cfg, 1, &matching);
303  if (matching < 1)
304  continue;
305  return cfg;
306  }
307 
308  // Fetch all of the matching configurations and find the
309  // first that matches the pixel format we wanted.
310  EGLint size = matching;
311  EGLConfig *configs = new EGLConfig [size];
312  eglChooseConfig(display(), props.properties(), configs, size, &matching);
313  for (EGLint index = 0; index < size; ++index) {
314  EGLint red, green, blue, alpha;
315  eglGetConfigAttrib(display(), configs[index], EGL_RED_SIZE, &red);
316  eglGetConfigAttrib(display(), configs[index], EGL_GREEN_SIZE, &green);
317  eglGetConfigAttrib(display(), configs[index], EGL_BLUE_SIZE, &blue);
318  eglGetConfigAttrib(display(), configs[index], EGL_ALPHA_SIZE, &alpha);
319  if (red == props.value(EGL_RED_SIZE) &&
320  green == props.value(EGL_GREEN_SIZE) &&
321  blue == props.value(EGL_BLUE_SIZE) &&
322  (props.value(EGL_ALPHA_SIZE) == 0 ||
323  alpha == props.value(EGL_ALPHA_SIZE))) {
324  cfg = configs[index];
325  delete [] configs;
326  return cfg;
327  }
328  }
329  delete [] configs;
330  } while (props.reduceConfiguration());
331 
332 #ifdef EGL_BIND_TO_TEXTURE_RGBA
333  // Don't report an error just yet if we failed to get a pbuffer
334  // configuration with texture rendering. Only report failure if
335  // we cannot get any pbuffer configurations at all.
336  if (props.value(EGL_BIND_TO_TEXTURE_RGBA) == EGL_DONT_CARE &&
337  props.value(EGL_BIND_TO_TEXTURE_RGB) == EGL_DONT_CARE)
338 #endif
339  {
340  qWarning() << "QEglContext::chooseConfig(): Could not find a suitable EGL configuration";
341  qWarning() << "Requested:" << props.toString();
342  qWarning() << "Available:";
344  }
345  return QEGL_NO_CONFIG;
346 }
347 
349 {
350  cfg = QEgl::chooseConfig(&properties, match);
351  return cfg != QEGL_NO_CONFIG;
352 }
353 
355 {
356  return QEgl::createSurface(device, cfg, properties);
357 }
358 
359 
360 // Create the EGLContext.
362 {
363  // We need to select the correct API before calling eglCreateContext().
364 #ifdef QT_OPENGL_ES
365 #ifdef EGL_OPENGL_ES_API
366  if (apiType == QEgl::OpenGL)
367  eglBindAPI(EGL_OPENGL_ES_API);
368 #endif
369 #else
370 #ifdef EGL_OPENGL_API
371  if (apiType == QEgl::OpenGL)
372  eglBindAPI(EGL_OPENGL_API);
373 #endif
374 #endif //defined(QT_OPENGL_ES)
375 #ifdef EGL_OPENVG_API
376  if (apiType == QEgl::OpenVG)
377  eglBindAPI(EGL_OPENVG_API);
378 #endif
379 
380  // Create a new context for the configuration.
381  QEglProperties contextProps;
382  if (properties)
383  contextProps = *properties;
384 #ifdef QT_OPENGL_ES_2
385  if (apiType == QEgl::OpenGL)
386  contextProps.setValue(EGL_CONTEXT_CLIENT_VERSION, 2);
387 #endif
388  sharing = false;
389  if (shareContext && shareContext->ctx == EGL_NO_CONTEXT)
390  shareContext = 0;
391  if (shareContext) {
392  ctx = eglCreateContext(QEgl::display(), cfg, shareContext->ctx, contextProps.properties());
393  if (ctx == EGL_NO_CONTEXT) {
394  qWarning() << "QEglContext::createContext(): Could not share context:" << QEgl::errorString();
395  shareContext = 0;
396  } else {
397  sharing = true;
398  }
399  }
400  if (ctx == EGL_NO_CONTEXT) {
401  ctx = eglCreateContext(display(), cfg, EGL_NO_CONTEXT, contextProps.properties());
402  if (ctx == EGL_NO_CONTEXT) {
403  qWarning() << "QEglContext::createContext(): Unable to create EGL context:" << QEgl::errorString();
404 #ifdef Q_OS_SYMBIAN
405  S60->eglSurfaceCreationError = true;
406 #endif
407  return false;
408  }
409  }
410  return true;
411 }
412 
413 // Destroy an EGL surface object. If it was current on this context
414 // then call doneCurrent() for it first.
415 void QEglContext::destroySurface(EGLSurface surface)
416 {
417  if (surface != EGL_NO_SURFACE) {
418  if (surface == currentSurface)
419  doneCurrent();
420  eglDestroySurface(display(), surface);
421  }
422 }
423 
424 // Destroy the context. Note: this does not destroy the surface.
426 {
427  if (ctx != EGL_NO_CONTEXT && ownsContext)
428  eglDestroyContext(display(), ctx);
429  ctx = EGL_NO_CONTEXT;
430  cfg = 0;
431 }
432 
433 bool QEglContext::makeCurrent(EGLSurface surface)
434 {
435  if (ctx == EGL_NO_CONTEXT) {
436  qWarning() << "QEglContext::makeCurrent(): Cannot make invalid context current";
437  return false;
438  }
439 
440  if (surface == EGL_NO_SURFACE) {
441  qWarning() << "QEglContext::makeCurrent(): Cannot make invalid surface current";
442  return false;
443  }
444 
445 #ifdef Q_OS_SYMBIAN
446  apiChanged = false;
448  && currentContext(apiType)->ctx != eglGetCurrentContext()) {
449  // some other EGL based API active. Complete its rendering
450  eglWaitClient();
451  apiChanged = true;
452  }
453 #endif
454 
455  // If lazyDoneCurrent() was called on the surface, then we may be able
456  // to assume that it is still current within the thread.
457  if (surface == currentSurface && currentContext(apiType) == this
458  && !apiChanged) {
459  current = true;
460  return true;
461  }
462 
463  current = true;
464  currentSurface = surface;
465  setCurrentContext(apiType, this);
466 
467  // Force the right API to be bound before making the context current.
468  // The EGL implementation should be able to figure this out from ctx,
469  // but some systems require the API to be explicitly set anyway.
470 #ifdef EGL_OPENGL_ES_API
471  if (apiType == QEgl::OpenGL)
472  eglBindAPI(EGL_OPENGL_ES_API);
473 #endif
474 #ifdef EGL_OPENVG_API
475  if (apiType == QEgl::OpenVG)
476  eglBindAPI(EGL_OPENVG_API);
477 #endif
478 
479  bool ok = eglMakeCurrent(QEgl::display(), surface, surface, ctx);
480  if (!ok)
481  qWarning() << "QEglContext::makeCurrent(" << surface << "):" << QEgl::errorString();
482  return ok;
483 }
484 
486 {
487  // If the context is invalid, we assume that an error was reported
488  // when makeCurrent() was called.
489  if (ctx == EGL_NO_CONTEXT)
490  return false;
491 
492  current = false;
493  currentSurface = EGL_NO_SURFACE;
495 
496  // We need to select the correct API before calling eglMakeCurrent()
497  // with EGL_NO_CONTEXT because threads can have both OpenGL and OpenVG
498  // contexts active at the same time.
499 #ifdef EGL_OPENGL_ES_API
500  if (apiType == QEgl::OpenGL)
501  eglBindAPI(EGL_OPENGL_ES_API);
502 #endif
503 #ifdef EGL_OPENVG_API
504  if (apiType == QEgl::OpenVG)
505  eglBindAPI(EGL_OPENVG_API);
506 #endif
507 
508  bool ok = eglMakeCurrent(QEgl::display(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
509  if (!ok)
510  qWarning() << "QEglContext::doneCurrent():" << QEgl::errorString();
511  return ok;
512 }
513 
514 // Act as though doneCurrent() was called, but keep the context
515 // and the surface active for the moment. This allows makeCurrent()
516 // to skip a call to eglMakeCurrent() if we are using the same
517 // surface as the last set of painting operations. We leave the
518 // currentContext() pointer as-is for now.
520 {
521  current = false;
522  return true;
523 }
524 
525 bool QEglContext::swapBuffers(EGLSurface surface)
526 {
527  if(ctx == EGL_NO_CONTEXT)
528  return false;
529 
530  bool ok = eglSwapBuffers(QEgl::display(), surface);
531  if (!ok)
532  qWarning() << "QEglContext::swapBuffers():" << QEgl::errorString();
533 
534 #ifdef Q_OS_SYMBIAN
535  if (apiChanged) {
536  eglWaitClient();
537  apiChanged = false;
538  }
539 #endif
540  return ok;
541 }
542 
543 bool QEglContext::swapBuffersRegion2NOK(EGLSurface surface, const QRegion *region) {
544  QVector<QRect> qrects = region->rects();
545  EGLint *gl_rects;
546  uint count;
547  uint i;
548 
549  count = qrects.size();
550  QVarLengthArray <EGLint> arr(4 * count);
551  gl_rects = arr.data();
552  for (i = 0; i < count; i++) {
553  QRect qrect = qrects[i];
554 
555  gl_rects[4 * i + 0] = qrect.x();
556  gl_rects[4 * i + 1] = qrect.y();
557  gl_rects[4 * i + 2] = qrect.width();
558  gl_rects[4 * i + 3] = qrect.height();
559  }
560 
561  bool ok = QEgl::eglSwapBuffersRegion2NOK(QEgl::display(), surface, count, gl_rects);
562 
563  if (!ok)
564  qWarning() << "QEglContext::swapBuffersRegion2NOK():" << QEgl::errorString();
565  return ok;
566 }
567 
569 {
570  EGLint value;
571  EGLBoolean success = eglGetConfigAttrib(QEgl::display(), cfg, name, &value);
572  if (success)
573  return value;
574  else
575  return EGL_DONT_CARE;
576 }
577 
578 typedef EGLImageKHR (EGLAPIENTRY *_eglCreateImageKHR)(EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, const EGLint*);
579 typedef EGLBoolean (EGLAPIENTRY *_eglDestroyImageKHR)(EGLDisplay, EGLImageKHR);
580 
581 // Defined in qegl.cpp:
584 
585 typedef EGLBoolean (EGLAPIENTRY *_eglSwapBuffersRegion2NOK)(EGLDisplay, EGLSurface, EGLint, const EGLint*);
586 
588 
589 EGLDisplay QEgl::display()
590 {
591  static EGLDisplay dpy = EGL_NO_DISPLAY;
593  dpy = eglGetDisplay(nativeDisplay());
595  if (dpy == EGL_NO_DISPLAY) {
596  qWarning("QEgl::display(): Falling back to EGL_DEFAULT_DISPLAY");
597  dpy = eglGetDisplay(EGLNativeDisplayType(EGL_DEFAULT_DISPLAY));
598  }
599  if (dpy == EGL_NO_DISPLAY) {
600  qWarning("QEgl::display(): Can't even open the default display");
601  return EGL_NO_DISPLAY;
602  }
603 
604  if (!eglInitialize(dpy, NULL, NULL)) {
605  qWarning() << "QEgl::display(): Cannot initialize EGL display:" << QEgl::errorString();
606  return EGL_NO_DISPLAY;
607  }
608 
609  // Resolve the egl extension function pointers:
610 #if (defined(EGL_KHR_image) || defined(EGL_KHR_image_base)) && !defined(EGL_EGLEXT_PROTOTYPES)
611  if (QEgl::hasExtension("EGL_KHR_image") || QEgl::hasExtension("EGL_KHR_image_base")) {
612  qt_eglCreateImageKHR = (_eglCreateImageKHR) eglGetProcAddress("eglCreateImageKHR");
613  qt_eglDestroyImageKHR = (_eglDestroyImageKHR) eglGetProcAddress("eglDestroyImageKHR");
614  }
615 #endif
616 
617  if (QEgl::hasExtension("EGL_NOK_swap_region2")) {
618  qt_eglSwapBuffersRegion2NOK = (_eglSwapBuffersRegion2NOK) eglGetProcAddress("eglSwapBuffersRegion2NOK");
619  }
620  }
621 
622  return dpy;
623 }
624 
625 EGLImageKHR QEgl::eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
626 {
628  return qt_eglCreateImageKHR(dpy, ctx, target, buffer, attrib_list);
629 
630  QEgl::display(); // Initialises function pointers
632  return qt_eglCreateImageKHR(dpy, ctx, target, buffer, attrib_list);
633 
634  qWarning("QEgl::eglCreateImageKHR() called but EGL_KHR_image(_base) extension not present");
635  return 0;
636 }
637 
638 EGLBoolean QEgl::eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
639 {
641  return qt_eglDestroyImageKHR(dpy, img);
642 
643  QEgl::display(); // Initialises function pointers
645  return qt_eglDestroyImageKHR(dpy, img);
646 
647  qWarning("QEgl::eglDestroyImageKHR() called but EGL_KHR_image(_base) extension not present");
648  return 0;
649 }
650 
651 EGLBoolean QEgl::eglSwapBuffersRegion2NOK(EGLDisplay dpy, EGLSurface surface, EGLint count, const EGLint *rects)
652 {
654  return qt_eglSwapBuffersRegion2NOK(dpy, surface, count, rects);
655 
656  QEgl::display(); // Initialises function pointers
658  return qt_eglSwapBuffersRegion2NOK(dpy, surface, count, rects);
659 
660  qWarning("QEgl::eglSwapBuffersRegion2NOK() called but EGL_NOK_swap_region2 extension not present");
661  return 0;
662 }
663 
664 #ifndef Q_WS_X11
665 EGLSurface QEgl::createSurface(QPaintDevice *device, EGLConfig cfg, const QEglProperties *properties)
666 {
667  // Create the native drawable for the paint device.
668  int devType = device->devType();
669  EGLNativePixmapType pixmapDrawable = 0;
670  EGLNativeWindowType windowDrawable = 0;
671  bool ok;
672  if (devType == QInternal::Pixmap) {
673  pixmapDrawable = nativePixmap(static_cast<QPixmap *>(device));
674  ok = (pixmapDrawable != 0);
675  } else if (devType == QInternal::Widget) {
676  windowDrawable = nativeWindow(static_cast<QWidget *>(device));
677  ok = (windowDrawable != 0);
678  } else {
679  ok = false;
680  }
681  if (!ok) {
682  qWarning("QEglContext::createSurface(): Cannot create the native EGL drawable");
683  return EGL_NO_SURFACE;
684  }
685 
686  // Create the EGL surface to draw into, based on the native drawable.
687  const EGLint *props;
688  if (properties)
689  props = properties->properties();
690  else
691  props = 0;
692  EGLSurface surf = EGL_NO_SURFACE;
693 #ifdef Q_OS_SYMBIAN
694  // On Symbian there might be situations (especially on 32MB GPU devices)
695  // where Qt is trying to create EGL surface while some other application
696  // is still holding all available GPU memory but is about to release it
697  // soon. For an example when exiting native video recorder and going back to
698  // Qt application behind it. Video stack tear down takes some time and Qt
699  // app might be too quick in reserving its EGL surface and thus running out
700  // of GPU memory right away. So if EGL surface creation fails due to bad
701  // alloc, let's try recreating it four times within ~1 second if needed.
702  // This strategy gives some time for video recorder to tear down its stack
703  // and a chance to Qt for creating a valid surface.
704  // If the surface is still failing however, we don't keep the app blocked.
705  static int tries = 4;
706  if (tries <= 0)
707  tries = 1;
708  while (tries-- > 0) {
709  if (devType == QInternal::Widget)
710  surf = eglCreateWindowSurface(QEgl::display(), cfg, windowDrawable, props);
711  else
712  surf = eglCreatePixmapSurface(QEgl::display(), cfg, pixmapDrawable, props);
713  if (surf == EGL_NO_SURFACE) {
714  EGLint error = eglGetError();
715  if (error == EGL_BAD_ALLOC) {
716  if (tries > 0) {
717  User::After(1000 * 250); // 250ms
718  continue;
719  }
720  }
721  qWarning("QEglContext::createSurface(): Unable to create EGL surface, error = 0x%x", error);
722  S60->eglSurfaceCreationError = true;
723  } else {
724  tries = 4;
725  break;
726  }
727  }
728 #else
729  if (devType == QInternal::Widget)
730  surf = eglCreateWindowSurface(QEgl::display(), cfg, windowDrawable, props);
731  else
732  surf = eglCreatePixmapSurface(QEgl::display(), cfg, pixmapDrawable, props);
733  if (surf == EGL_NO_SURFACE) {
734  qWarning("QEglContext::createSurface(): Unable to create EGL surface, error = 0x%x", eglGetError());
735  }
736 #endif
737  return surf;
738 }
739 #endif
740 
741 
742 // Return the error string associated with a specific code.
744 {
745  static const char * const errors[] = {
746  "Success (0x3000)", // No tr
747  "Not initialized (0x3001)", // No tr
748  "Bad access (0x3002)", // No tr
749  "Bad alloc (0x3003)", // No tr
750  "Bad attribute (0x3004)", // No tr
751  "Bad config (0x3005)", // No tr
752  "Bad context (0x3006)", // No tr
753  "Bad current surface (0x3007)", // No tr
754  "Bad display (0x3008)", // No tr
755  "Bad match (0x3009)", // No tr
756  "Bad native pixmap (0x300A)", // No tr
757  "Bad native window (0x300B)", // No tr
758  "Bad parameter (0x300C)", // No tr
759  "Bad surface (0x300D)", // No tr
760  "Context lost (0x300E)" // No tr
761  };
762  if (code >= 0x3000 && code <= 0x300E) {
763  return QString::fromLatin1(errors[code - 0x3000]);
764  } else {
765  return QLatin1String("0x") + QString::number(int(code), 16);
766  }
767 }
768 
769 // Dump all of the EGL configurations supported by the system.
771 {
772  QEglProperties props;
773  EGLint count = 0;
774  if (!eglGetConfigs(display(), 0, 0, &count) || count < 1)
775  return;
776  EGLConfig *configs = new EGLConfig [count];
777  eglGetConfigs(display(), configs, count, &count);
778  for (EGLint index = 0; index < count; ++index) {
779  props = QEglProperties(configs[index]);
780  qWarning() << props.toString();
781  }
782  delete [] configs;
783 }
784 
786 {
787  const char* exts = eglQueryString(QEgl::display(), EGL_EXTENSIONS);
788  return QString(QLatin1String(exts));
789 }
790 
791 bool QEgl::hasExtension(const char* extensionName)
792 {
794  QByteArray(reinterpret_cast<const char *>
795  (eglQueryString(QEgl::display(), EGL_EXTENSIONS))).split(' ');
796  return extensions.contains(extensionName);
797 }
798 
800 {
801  if (api == QEgl::OpenGL)
802  return currentGLContext;
803  else
804  return currentVGContext;
805 }
806 
808 {
809  if (api == QEgl::OpenGL)
810  currentGLContext = context;
811  else
812  currentVGContext = context;
813 }
814 
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: qstring.cpp:6448
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
EGLSurface createSurface(QPaintDevice *device, const QEglProperties *properties=0)
Definition: qegl.cpp:354
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
bool createContext(QEglContext *shareContext=0, const QEglProperties *properties=0)
Definition: qegl.cpp:361
bool isValid() const
Definition: qegl.cpp:116
NativePixmapType EGLNativePixmapType
Definition: qegl_p.h:117
~QEglContext()
Definition: qegl.cpp:105
#define error(msg)
const EGLint * properties() const
QString toString() const
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
int value(int name) const
static bool match(const uchar *found, const char *target, uint len)
int width() const
Returns the width of the rectangle.
Definition: qrect.h:303
bool chooseConfig(const QEglProperties &properties, QEgl::PixelFormatMatch match=QEgl::ExactPixelFormat)
Definition: qegl.cpp:348
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
Definition: qegl_p.h:189
int height() const
Returns the height of the rectangle.
Definition: qrect.h:306
The QString class provides a Unicode character string.
Definition: qstring.h:83
void setValue(int name, int value)
#define Q_BASIC_ATOMIC_INITIALIZER(a)
Definition: qbasicatomic.h:218
Q_GUI_EXPORT QString extensions()
Definition: qegl.cpp:785
bool swapBuffers(EGLSurface surface)
Definition: qegl.cpp:525
NativeWindowType EGLNativeWindowType
Definition: qegl_p.h:116
Q_GUI_EXPORT EGLNativePixmapType nativePixmap(QPixmap *)
Definition: qegl_qpa.cpp:65
virtual int devType() const
Definition: qpaintdevice.h:167
Q_GUI_EXPORT QString errorString(EGLint code=eglGetError())
Definition: qegl.cpp:743
EGLContext ctx
bool swapBuffersRegion2NOK(EGLSurface surface, const QRegion *region)
Definition: qegl.cpp:543
EGLContext context() const
Definition: qeglcontext_p.h:91
static QBasicAtomicInt displayOpen
Definition: qegl.cpp:79
EGLConfig cfg
bool doneCurrent()
Definition: qegl.cpp:485
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
Q_GUI_EXPORT EGLDisplay display()
Definition: qegl.cpp:589
QEglContext()
Definition: qegl.cpp:92
QBool contains(const T &t) const
Returns true if the list contains an occurrence of value; otherwise returns false.
Definition: qlist.h:880
void setRenderableType(QEgl::API api)
static bool displayOpened()
Definition: qegl.cpp:75
Q_GUI_EXPORT EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
Definition: qegl.cpp:638
static QEglContext *volatile currentGLContext
Definition: qegl.cpp:89
static _eglSwapBuffersRegion2NOK qt_eglSwapBuffersRegion2NOK
Definition: qegl.cpp:587
const char * name
EGLSurface currentSurface
Q_CORE_EXPORT void qWarning(const char *,...)
void * EGLClientBuffer
Definition: qegl_p.h:70
unsigned int uint
Definition: qglobal.h:996
QEgl::API api() const
Definition: qeglcontext_p.h:74
unsigned int EGLenum
Definition: qegl_p.h:69
static void setDisplayOpened()
Definition: qegl.cpp:74
The QRegion class specifies a clip region for a painter.
Definition: qregion.h:68
QEgl::API apiType
bool reduceConfiguration()
void destroyContext()
Definition: qegl.cpp:425
bool isCurrent() const
Definition: qegl.cpp:121
Q_GUI_EXPORT bool hasExtension(const char *extensionName)
Definition: qegl.cpp:791
Q_GUI_EXPORT EGLConfig defaultConfig(int devType, API api, ConfigOptions options)
Definition: qegl.cpp:126
void * EGLImageKHR
Definition: qegl_p.h:165
int configAttrib(int name) const
Definition: qegl.cpp:568
static void deref()
Definition: qegl.cpp:68
QList< QByteArray > split(char sep) const
Splits the byte array into subarrays wherever sep occurs, and returns the list of those arrays...
#define QEGL_NO_CONFIG
Definition: qegl_p.h:129
bool lazyDoneCurrent()
Definition: qegl.cpp:519
static QEglContext * currentContext(QEgl::API api)
Definition: qegl.cpp:799
Q_GUI_EXPORT EGLSurface createSurface(QPaintDevice *device, EGLConfig cfg, const QEglProperties *surfaceAttribs=0)
Definition: qegl_x11.cpp:333
Q_GUI_EXPORT EGLNativeDisplayType nativeDisplay()
Definition: qegl_qpa.cpp:55
int y() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:255
Q_GUI_EXPORT void dumpAllConfigs()
Definition: qegl.cpp:770
bool makeCurrent(EGLSurface surface)
Definition: qegl.cpp:433
PixelFormatMatch
Definition: qegl_p.h:196
static QString fromLatin1(const char *, int size=-1)
Returns a QString initialized with the first size characters of the Latin-1 string str...
Definition: qstring.cpp:4188
int x() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:252
int toInt(bool *ok=0, int base=10) const
Returns the byte array converted to an int using base base, which is 10 by default and must be betwee...
#define ctx
Definition: qgl.cpp:6094
void destroySurface(EGLSurface surface)
Definition: qegl.cpp:415
EGLDisplay display()
Definition: qeglcontext_p.h:94
QVector< QRect > rects() const
Returns an array of non-overlapping rectangles that make up the region.
Definition: qregion.cpp:4412
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
#define EGLAPIENTRY
Definition: qegl_p.h:132
Q_GUI_EXPORT EGLBoolean eglSwapBuffersRegion2NOK(EGLDisplay dpy, EGLSurface surface, EGLint count, const EGLint *rects)
Definition: qegl.cpp:651
static const QCssKnownValue properties[NumProperties - 1]
Definition: qcssparser.cpp:67
static QBasicAtomicInt contexts
Definition: qegl.cpp:78
quint16 index
NativeDisplayType EGLNativeDisplayType
Definition: qegl_p.h:118
EGLBoolean(EGLAPIENTRY * _eglSwapBuffersRegion2NOK)(EGLDisplay, EGLSurface, EGLint, const EGLint *)
Definition: qegl.cpp:585
bool isEmpty() const
Returns true if the byte array has size 0; otherwise returns false.
Definition: qbytearray.h:421
API
Definition: qegl_p.h:190
static _eglCreateImageKHR qt_eglCreateImageKHR
Definition: qegl.cpp:582
Q_GUI_EXPORT EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
Definition: qegl.cpp:625
Q_GUI_EXPORT EGLConfig chooseConfig(const QEglProperties *configAttribs, QEgl::PixelFormatMatch match=QEgl::ExactPixelFormat)
Definition: qegl.cpp:288
static void setCurrentContext(QEgl::API api, QEglContext *context)
Definition: qegl.cpp:807
EGLBoolean(EGLAPIENTRY * _eglDestroyImageKHR)(EGLDisplay, EGLImageKHR)
Definition: qegl.cpp:579
int size() const
Returns the number of items in the vector.
Definition: qvector.h:137
static QEglContext *volatile currentVGContext
Definition: qegl.cpp:90
static void ref()
Definition: qegl.cpp:67
Q_GUI_EXPORT EGLNativeWindowType nativeWindow(QWidget *)
Definition: qegl_qpa.cpp:60
EGLImageKHR(EGLAPIENTRY * _eglCreateImageKHR)(EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, const EGLint *)
Definition: qegl.cpp:578
static _eglDestroyImageKHR qt_eglDestroyImageKHR
Definition: qegl.cpp:583