src/gui/egl/qegl.cpp
changeset 30 5dc02b23752f
parent 29 b72c6db6890b
child 33 3e2da88830cd
equal deleted inserted replaced
29:b72c6db6890b 30:5dc02b23752f
    40 ****************************************************************************/
    40 ****************************************************************************/
    41 
    41 
    42 #include <QtGui/qpaintdevice.h>
    42 #include <QtGui/qpaintdevice.h>
    43 #include <QtGui/qpixmap.h>
    43 #include <QtGui/qpixmap.h>
    44 #include <QtGui/qwidget.h>
    44 #include <QtGui/qwidget.h>
    45 #include <QtCore/qatomic.h>
       
    46 #include <QtCore/qdebug.h>
    45 #include <QtCore/qdebug.h>
       
    46 
    47 #include "qegl_p.h"
    47 #include "qegl_p.h"
       
    48 #include "qeglcontext_p.h"
       
    49 
    48 
    50 
    49 QT_BEGIN_NAMESPACE
    51 QT_BEGIN_NAMESPACE
    50 
       
    51 
       
    52 /*
       
    53     QEglContextTracker is used to track the EGL contexts that we
       
    54     create internally in Qt, so that we can call eglTerminate() to
       
    55     free additional EGL resources when the last context is destroyed.
       
    56 */
       
    57 
       
    58 class QEglContextTracker
       
    59 {
       
    60 public:
       
    61     static void ref() { contexts.ref(); }
       
    62     static void deref() {
       
    63         if (!contexts.deref()) {
       
    64             eglTerminate(QEglContext::display());
       
    65             displayOpen = 0;
       
    66         }
       
    67     }
       
    68     static void setDisplayOpened() { displayOpen = 1; }
       
    69     static bool displayOpened() { return displayOpen; }
       
    70 
       
    71 private:
       
    72     static QBasicAtomicInt contexts;
       
    73     static QBasicAtomicInt displayOpen;
       
    74 };
       
    75 
       
    76 QBasicAtomicInt QEglContextTracker::contexts = Q_BASIC_ATOMIC_INITIALIZER(0);
       
    77 QBasicAtomicInt QEglContextTracker::displayOpen = Q_BASIC_ATOMIC_INITIALIZER(0);
       
    78 
    52 
    79 // Current GL and VG contexts.  These are used to determine if
    53 // Current GL and VG contexts.  These are used to determine if
    80 // we can avoid an eglMakeCurrent() after a call to lazyDoneCurrent().
    54 // we can avoid an eglMakeCurrent() after a call to lazyDoneCurrent().
    81 // If a background thread modifies the value, the worst that will
    55 // If a background thread modifies the value, the worst that will
    82 // happen is a redundant eglMakeCurrent() in the foreground thread.
    56 // happen is a redundant eglMakeCurrent() in the foreground thread.
    83 static QEglContext * volatile currentGLContext = 0;
    57 static QEglContext * volatile currentGLContext = 0;
    84 static QEglContext * volatile currentVGContext = 0;
    58 static QEglContext * volatile currentVGContext = 0;
    85 
    59 
    86 EGLDisplay QEglContext::dpy = EGL_NO_DISPLAY;
       
    87 
       
    88 QEglContext::QEglContext()
    60 QEglContext::QEglContext()
    89     : apiType(QEgl::OpenGL)
    61     : apiType(QEgl::OpenGL)
    90     , ctx(EGL_NO_CONTEXT)
    62     , ctx(EGL_NO_CONTEXT)
    91     , cfg(0)
    63     , cfg(QEGL_NO_CONFIG)
    92     , currentSurface(EGL_NO_SURFACE)
    64     , currentSurface(EGL_NO_SURFACE)
    93     , current(false)
    65     , current(false)
    94     , ownsContext(true)
    66     , ownsContext(true)
    95     , sharing(false)
    67     , sharing(false)
    96 {
    68 {
    97     QEglContextTracker::ref();
       
    98 }
    69 }
    99 
    70 
   100 QEglContext::~QEglContext()
    71 QEglContext::~QEglContext()
   101 {
    72 {
   102     destroyContext();
    73     destroyContext();
   103 
    74 
   104     if (currentGLContext == this)
    75     if (currentGLContext == this)
   105         currentGLContext = 0;
    76         currentGLContext = 0;
   106     if (currentVGContext == this)
    77     if (currentVGContext == this)
   107         currentVGContext = 0;
    78         currentVGContext = 0;
   108     QEglContextTracker::deref();
       
   109 }
    79 }
   110 
    80 
   111 bool QEglContext::isValid() const
    81 bool QEglContext::isValid() const
   112 {
    82 {
   113     return (ctx != EGL_NO_CONTEXT);
    83     return (ctx != EGL_NO_CONTEXT);
   116 bool QEglContext::isCurrent() const
    86 bool QEglContext::isCurrent() const
   117 {
    87 {
   118     return current;
    88     return current;
   119 }
    89 }
   120 
    90 
       
    91 EGLConfig QEgl::defaultConfig(int devType, API api, ConfigOptions options)
       
    92 {
       
    93     if ( (devType != QInternal::Pixmap) && ((options & Renderable) == 0))
       
    94         qWarning("QEgl::defaultConfig() - Only configs for pixmaps make sense to be read-only!");
       
    95 
       
    96     EGLConfig* targetConfig = 0;
       
    97 
       
    98     static EGLConfig defaultVGConfigs[] = {
       
    99         QEGL_NO_CONFIG, // 0    Window  Renderable  Translucent
       
   100         QEGL_NO_CONFIG, // 1    Window  Renderable  Opaque
       
   101         QEGL_NO_CONFIG, // 2    Pixmap  Renderable  Translucent
       
   102         QEGL_NO_CONFIG, // 3    Pixmap  Renderable  Opaque
       
   103         QEGL_NO_CONFIG, // 4    Pixmap  ReadOnly    Translucent
       
   104         QEGL_NO_CONFIG  // 5    Pixmap  ReadOnly    Opaque
       
   105     };
       
   106     if (api == OpenVG) {
       
   107         if (devType == QInternal::Widget) {
       
   108             if (options & Translucent)
       
   109                 targetConfig = &(defaultVGConfigs[0]);
       
   110             else
       
   111                 targetConfig = &(defaultVGConfigs[1]);
       
   112         } else if (devType == QInternal::Pixmap) {
       
   113             if (options & Renderable) {
       
   114                 if (options & Translucent)
       
   115                     targetConfig = &(defaultVGConfigs[2]);
       
   116                 else // Opaque
       
   117                     targetConfig = &(defaultVGConfigs[3]);
       
   118             } else { // Read-only
       
   119                 if (options & Translucent)
       
   120                     targetConfig = &(defaultVGConfigs[4]);
       
   121                 else // Opaque
       
   122                     targetConfig = &(defaultVGConfigs[5]);
       
   123             }
       
   124         }
       
   125     }
       
   126 
       
   127 
       
   128     static EGLConfig defaultGLConfigs[] = {
       
   129         QEGL_NO_CONFIG, // 0    Window  Renderable  Translucent
       
   130         QEGL_NO_CONFIG, // 1    Window  Renderable  Opaque
       
   131         QEGL_NO_CONFIG, // 2    PBuffer Renderable  Translucent
       
   132         QEGL_NO_CONFIG, // 3    PBuffer Renderable  Opaque
       
   133         QEGL_NO_CONFIG, // 4    Pixmap  Renderable  Translucent
       
   134         QEGL_NO_CONFIG, // 5    Pixmap  Renderable  Opaque
       
   135         QEGL_NO_CONFIG, // 6    Pixmap  ReadOnly    Translucent
       
   136         QEGL_NO_CONFIG  // 7    Pixmap  ReadOnly    Opaque
       
   137     };
       
   138     if (api == OpenGL) {
       
   139         if (devType == QInternal::Widget) {
       
   140             if (options & Translucent)
       
   141                 targetConfig = &(defaultGLConfigs[0]);
       
   142             else // Opaque
       
   143                 targetConfig = &(defaultGLConfigs[1]);
       
   144         } else if (devType == QInternal::Pbuffer) {
       
   145             if (options & Translucent)
       
   146                 targetConfig = &(defaultGLConfigs[2]);
       
   147             else // Opaque
       
   148                 targetConfig = &(defaultGLConfigs[3]);
       
   149         } else if (devType == QInternal::Pixmap) {
       
   150             if (options & Renderable) {
       
   151                 if (options & Translucent)
       
   152                     targetConfig = &(defaultGLConfigs[4]);
       
   153                 else // Opaque
       
   154                     targetConfig = &(defaultGLConfigs[5]);
       
   155             } else { // ReadOnly
       
   156                 if (options & Translucent)
       
   157                     targetConfig = &(defaultGLConfigs[6]);
       
   158                 else // Opaque
       
   159                     targetConfig = &(defaultGLConfigs[7]);
       
   160             }
       
   161         }
       
   162     }
       
   163 
       
   164     if (!targetConfig) {
       
   165         qWarning("QEgl::defaultConfig() - No default config for device/api/options combo");
       
   166         return QEGL_NO_CONFIG;
       
   167     }
       
   168     if (*targetConfig != QEGL_NO_CONFIG)
       
   169         return *targetConfig;
       
   170 
       
   171 
       
   172     // We haven't found an EGL config for the target config yet, so do it now:
       
   173 
       
   174 
       
   175     // Allow overriding from an environment variable:
       
   176     QByteArray configId;
       
   177     if (api == OpenVG)
       
   178         configId = qgetenv("QT_VG_EGL_CONFIG");
       
   179     else
       
   180         configId = qgetenv("QT_GL_EGL_CONFIG");
       
   181     if (!configId.isEmpty()) {
       
   182         // Overriden, so get the EGLConfig for the specified config ID:
       
   183         EGLint properties[] = {
       
   184             EGL_CONFIG_ID, (EGLint)configId.toInt(),
       
   185             EGL_NONE
       
   186         };
       
   187         EGLint configCount = 0;
       
   188         eglChooseConfig(display(), properties, targetConfig, 1, &configCount);
       
   189         if (configCount > 0)
       
   190             return *targetConfig;
       
   191         qWarning() << "QEgl::defaultConfig() -" << configId << "appears to be invalid";
       
   192     }
       
   193 
       
   194     QEglProperties configAttribs;
       
   195     configAttribs.setRenderableType(api);
       
   196 
       
   197     EGLint surfaceType;
       
   198     switch (devType) {
       
   199         case QInternal::Widget:
       
   200             surfaceType = EGL_WINDOW_BIT;
       
   201             break;
       
   202         case QInternal::Pixmap:
       
   203             surfaceType = EGL_PIXMAP_BIT;
       
   204             break;
       
   205         case QInternal::Pbuffer:
       
   206             surfaceType = EGL_PBUFFER_BIT;
       
   207             break;
       
   208         default:
       
   209             qWarning("QEgl::defaultConfig() - Can't create EGL surface for %d device type", devType);
       
   210             return QEGL_NO_CONFIG;
       
   211     };
       
   212 #ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT
       
   213     // For OpenVG, we try to create a surface using a pre-multiplied format if
       
   214     // the surface needs to have an alpha channel:
       
   215     if (api == OpenVG && (options & Translucent))
       
   216         surfaceType |= EGL_VG_ALPHA_FORMAT_PRE_BIT;
       
   217 #endif
       
   218     configAttribs.setValue(EGL_SURFACE_TYPE, surfaceType);
       
   219 
       
   220 #ifdef EGL_BIND_TO_TEXTURE_RGBA
       
   221     if (devType == QInternal::Pixmap || devType == QInternal::Pbuffer) {
       
   222         if (options & Translucent)
       
   223             configAttribs.setValue(EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE);
       
   224         else
       
   225             configAttribs.setValue(EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE);
       
   226     }
       
   227 #endif
       
   228 
       
   229     // Add paint engine requirements
       
   230     if (api == OpenVG) {
       
   231 #ifndef QVG_SCISSOR_CLIP
       
   232         configAttribs.setValue(EGL_ALPHA_MASK_SIZE, 1);
       
   233 #endif
       
   234     } else {
       
   235         // Both OpenGL paint engines need to have stencil and sample buffers
       
   236         configAttribs.setValue(EGL_STENCIL_SIZE, 1);
       
   237         configAttribs.setValue(EGL_SAMPLE_BUFFERS, 1);
       
   238 #ifndef QT_OPENGL_ES_2
       
   239         // Aditionally, the GL1 engine likes to have a depth buffer for clipping
       
   240         configAttribs.setValue(EGL_DEPTH_SIZE, 1);
       
   241 #endif
       
   242     }
       
   243 
       
   244     if (options & Translucent)
       
   245         configAttribs.setValue(EGL_ALPHA_SIZE, 1);
       
   246 
       
   247     *targetConfig = chooseConfig(&configAttribs, QEgl::BestPixelFormat);
       
   248     return *targetConfig;
       
   249 }
       
   250 
       
   251 
   121 // Choose a configuration that matches "properties".
   252 // Choose a configuration that matches "properties".
   122 bool QEglContext::chooseConfig
   253 EGLConfig QEgl::chooseConfig(const QEglProperties* properties, QEgl::PixelFormatMatch match)
   123         (const QEglProperties& properties, QEgl::PixelFormatMatch match)
   254 {
   124 {
   255     QEglProperties props(*properties);
   125     QEglProperties props(properties);
   256     EGLConfig cfg = QEGL_NO_CONFIG;
   126     do {
   257     do {
   127         // Get the number of matching configurations for this set of properties.
   258         // Get the number of matching configurations for this set of properties.
   128         EGLint matching = 0;
   259         EGLint matching = 0;
   129         if (!eglChooseConfig(display(), props.properties(), 0, 0, &matching) || !matching)
   260         EGLDisplay dpy = QEgl::display();
       
   261         if (!eglChooseConfig(dpy, props.properties(), 0, 0, &matching) || !matching)
   130             continue;
   262             continue;
   131 
   263 
   132         // If we want the best pixel format, then return the first
   264         // If we want the best pixel format, then return the first
   133         // matching configuration.
   265         // matching configuration.
   134         if (match == QEgl::BestPixelFormat) {
   266         if (match == QEgl::BestPixelFormat) {
   135             eglChooseConfig(display(), props.properties(), &cfg, 1, &matching);
   267             eglChooseConfig(display(), props.properties(), &cfg, 1, &matching);
   136             if (matching < 1)
   268             if (matching < 1)
   137                 continue;
   269                 continue;
   138             return true;
   270             return cfg;
   139         }
   271         }
   140 
   272 
   141         // Fetch all of the matching configurations and find the
   273         // Fetch all of the matching configurations and find the
   142         // first that matches the pixel format we wanted.
   274         // first that matches the pixel format we wanted.
   143         EGLint size = matching;
   275         EGLint size = matching;
   154                     blue == props.value(EGL_BLUE_SIZE) &&
   286                     blue == props.value(EGL_BLUE_SIZE) &&
   155                     (props.value(EGL_ALPHA_SIZE) == 0 ||
   287                     (props.value(EGL_ALPHA_SIZE) == 0 ||
   156                      alpha == props.value(EGL_ALPHA_SIZE))) {
   288                      alpha == props.value(EGL_ALPHA_SIZE))) {
   157                 cfg = configs[index];
   289                 cfg = configs[index];
   158                 delete [] configs;
   290                 delete [] configs;
   159                 return true;
   291                 return cfg;
   160             }
   292             }
   161         }
   293         }
   162         delete [] configs;
   294         delete [] configs;
   163     } while (props.reduceConfiguration());
   295     } while (props.reduceConfiguration());
   164 
   296 
   171 #endif
   303 #endif
   172     {
   304     {
   173         qWarning() << "QEglContext::chooseConfig(): Could not find a suitable EGL configuration";
   305         qWarning() << "QEglContext::chooseConfig(): Could not find a suitable EGL configuration";
   174         qWarning() << "Requested:" << props.toString();
   306         qWarning() << "Requested:" << props.toString();
   175         qWarning() << "Available:";
   307         qWarning() << "Available:";
   176         dumpAllConfigs();
   308         QEgl::dumpAllConfigs();
   177     }
   309     }
   178     return false;
   310     return QEGL_NO_CONFIG;
   179 }
   311 }
       
   312 
       
   313 bool QEglContext::chooseConfig(const QEglProperties& properties, QEgl::PixelFormatMatch match)
       
   314 {
       
   315     cfg = QEgl::chooseConfig(&properties, match);
       
   316     return cfg != QEGL_NO_CONFIG;
       
   317 }
       
   318 
       
   319 EGLSurface QEglContext::createSurface(QPaintDevice* device, const QEglProperties *properties)
       
   320 {
       
   321     return QEgl::createSurface(device, cfg, properties);
       
   322 }
       
   323 
   180 
   324 
   181 // Create the EGLContext.
   325 // Create the EGLContext.
   182 bool QEglContext::createContext(QEglContext *shareContext, const QEglProperties *properties)
   326 bool QEglContext::createContext(QEglContext *shareContext, const QEglProperties *properties)
   183 {
   327 {
   184     // We need to select the correct API before calling eglCreateContext().
   328     // We need to select the correct API before calling eglCreateContext().
       
   329 #ifdef QT_OPENGL_ES
   185 #ifdef EGL_OPENGL_ES_API
   330 #ifdef EGL_OPENGL_ES_API
   186     if (apiType == QEgl::OpenGL)
   331     if (apiType == QEgl::OpenGL)
   187         eglBindAPI(EGL_OPENGL_ES_API);
   332         eglBindAPI(EGL_OPENGL_ES_API);
   188 #endif
   333 #endif
       
   334 #else
       
   335 #ifdef EGL_OPENGL_API
       
   336     if (apiType == QEgl::OpenGL)
       
   337         eglBindAPI(EGL_OPENGL_API);
       
   338 #endif
       
   339 #endif //defined(QT_OPENGL_ES)
   189 #ifdef EGL_OPENVG_API
   340 #ifdef EGL_OPENVG_API
   190     if (apiType == QEgl::OpenVG)
   341     if (apiType == QEgl::OpenVG)
   191         eglBindAPI(EGL_OPENVG_API);
   342         eglBindAPI(EGL_OPENVG_API);
   192 #endif
   343 #endif
   193 
   344 
   194     // Create a new context for the configuration.
   345     // Create a new context for the configuration.
   195     QEglProperties contextProps;
   346     QEglProperties contextProps;
   196     if (properties)
   347     if (properties)
   197         contextProps = *properties;
   348         contextProps = *properties;
   198 #if defined(QT_OPENGL_ES_2)
   349 #ifdef QT_OPENGL_ES_2
   199     if (apiType == QEgl::OpenGL)
   350     if (apiType == QEgl::OpenGL)
   200         contextProps.setValue(EGL_CONTEXT_CLIENT_VERSION, 2);
   351         contextProps.setValue(EGL_CONTEXT_CLIENT_VERSION, 2);
   201 #endif
   352 #endif
   202     sharing = false;
   353     sharing = false;
   203     if (shareContext && shareContext->ctx == EGL_NO_CONTEXT)
   354     if (shareContext && shareContext->ctx == EGL_NO_CONTEXT)
   204         shareContext = 0;
   355         shareContext = 0;
   205     if (shareContext) {
   356     if (shareContext) {
   206         ctx = eglCreateContext(display(), cfg, shareContext->ctx, contextProps.properties());
   357         ctx = eglCreateContext(QEgl::display(), cfg, shareContext->ctx, contextProps.properties());
   207         if (ctx == EGL_NO_CONTEXT) {
   358         if (ctx == EGL_NO_CONTEXT) {
   208             qWarning() << "QEglContext::createContext(): Could not share context:" << errorString(eglGetError());
   359             qWarning() << "QEglContext::createContext(): Could not share context:" << QEgl::errorString();
   209             shareContext = 0;
   360             shareContext = 0;
   210         } else {
   361         } else {
   211             sharing = true;
   362             sharing = true;
   212         }
   363         }
   213     }
   364     }
   214     if (ctx == EGL_NO_CONTEXT) {
   365     if (ctx == EGL_NO_CONTEXT) {
   215         ctx = eglCreateContext(display(), cfg, 0, contextProps.properties());
   366         ctx = eglCreateContext(display(), cfg, 0, contextProps.properties());
   216         if (ctx == EGL_NO_CONTEXT) {
   367         if (ctx == EGL_NO_CONTEXT) {
   217             qWarning() << "QEglContext::createContext(): Unable to create EGL context:" << errorString(eglGetError());
   368             qWarning() << "QEglContext::createContext(): Unable to create EGL context:" << QEgl::errorString();
   218             return false;
   369             return false;
   219         }
   370         }
   220     }
   371     }
   221     return true;
   372     return true;
   222 }
   373 }
   243 
   394 
   244 bool QEglContext::makeCurrent(EGLSurface surface)
   395 bool QEglContext::makeCurrent(EGLSurface surface)
   245 {
   396 {
   246     if (ctx == EGL_NO_CONTEXT) {
   397     if (ctx == EGL_NO_CONTEXT) {
   247         qWarning() << "QEglContext::makeCurrent(): Cannot make invalid context current";
   398         qWarning() << "QEglContext::makeCurrent(): Cannot make invalid context current";
       
   399         return false;
       
   400     }
       
   401 
       
   402     if (surface == EGL_NO_SURFACE) {
       
   403         qWarning() << "QEglContext::makeCurrent(): Cannot make invalid surface current";
   248         return false;
   404         return false;
   249     }
   405     }
   250 
   406 
   251     // If lazyDoneCurrent() was called on the surface, then we may be able
   407     // If lazyDoneCurrent() was called on the surface, then we may be able
   252     // to assume that it is still current within the thread.
   408     // to assume that it is still current within the thread.
   269 #ifdef EGL_OPENVG_API
   425 #ifdef EGL_OPENVG_API
   270     if (apiType == QEgl::OpenVG)
   426     if (apiType == QEgl::OpenVG)
   271         eglBindAPI(EGL_OPENVG_API);
   427         eglBindAPI(EGL_OPENVG_API);
   272 #endif
   428 #endif
   273 
   429 
   274     bool ok = eglMakeCurrent(display(), surface, surface, ctx);
   430     bool ok = eglMakeCurrent(QEgl::display(), surface, surface, ctx);
   275     if (!ok)
   431     if (!ok)
   276         qWarning() << "QEglContext::makeCurrent():" << errorString(eglGetError());
   432         qWarning() << "QEglContext::makeCurrent(" << surface << "):" << QEgl::errorString();
   277     return ok;
   433     return ok;
   278 }
   434 }
   279 
   435 
   280 bool QEglContext::doneCurrent()
   436 bool QEglContext::doneCurrent()
   281 {
   437 {
   298 #ifdef EGL_OPENVG_API
   454 #ifdef EGL_OPENVG_API
   299     if (apiType == QEgl::OpenVG)
   455     if (apiType == QEgl::OpenVG)
   300         eglBindAPI(EGL_OPENVG_API);
   456         eglBindAPI(EGL_OPENVG_API);
   301 #endif
   457 #endif
   302 
   458 
   303     bool ok = eglMakeCurrent(display(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
   459     bool ok = eglMakeCurrent(QEgl::display(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
   304     if (!ok)
   460     if (!ok)
   305         qWarning() << "QEglContext::doneCurrent():" << errorString(eglGetError());
   461         qWarning() << "QEglContext::doneCurrent():" << QEgl::errorString();
   306     return ok;
   462     return ok;
   307 }
   463 }
   308 
   464 
   309 // Act as though doneCurrent() was called, but keep the context
   465 // Act as though doneCurrent() was called, but keep the context
   310 // and the surface active for the moment.  This allows makeCurrent()
   466 // and the surface active for the moment.  This allows makeCurrent()
   320 bool QEglContext::swapBuffers(EGLSurface surface)
   476 bool QEglContext::swapBuffers(EGLSurface surface)
   321 {
   477 {
   322     if(ctx == EGL_NO_CONTEXT)
   478     if(ctx == EGL_NO_CONTEXT)
   323         return false;
   479         return false;
   324 
   480 
   325     bool ok = eglSwapBuffers(display(), surface);
   481     bool ok = eglSwapBuffers(QEgl::display(), surface);
   326     if (!ok)
   482     if (!ok)
   327         qWarning() << "QEglContext::swapBuffers():" << errorString(eglGetError());
   483         qWarning() << "QEglContext::swapBuffers():" << QEgl::errorString();
   328     return ok;
   484     return ok;
   329 }
   485 }
   330 
   486 
   331 // Wait for native rendering operations to complete before starting
   487 int QEglContext::configAttrib(int name) const
   332 // to use OpenGL/OpenVG operations.
   488 {
   333 void QEglContext::waitNative()
   489     EGLint value;
   334 {
   490     EGLBoolean success = eglGetConfigAttrib(QEgl::display(), cfg, name, &value);
   335 #ifdef EGL_CORE_NATIVE_ENGINE
   491     if (success)
   336     eglWaitNative(EGL_CORE_NATIVE_ENGINE);
   492         return value;
   337 #endif
   493     else
   338 }
   494         return EGL_DONT_CARE;
   339 
   495 }
   340 // Wait for client OpenGL/OpenVG operations to complete before
   496 
   341 // using native rendering operations.
   497 typedef EGLImageKHR (EGLAPIENTRY *_eglCreateImageKHR)(EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, const EGLint*);
   342 void QEglContext::waitClient()
   498 typedef EGLBoolean (EGLAPIENTRY *_eglDestroyImageKHR)(EGLDisplay, EGLImageKHR);
   343 {
   499 
   344 #ifdef EGL_OPENGL_ES_API
   500 // Defined in qegl.cpp:
   345     if (apiType == QEgl::OpenGL) {
   501 static _eglCreateImageKHR qt_eglCreateImageKHR = 0;
   346         eglBindAPI(EGL_OPENGL_ES_API);
   502 static _eglDestroyImageKHR qt_eglDestroyImageKHR = 0;
   347         eglWaitClient();
   503 
   348     }
   504 
   349 #else
   505 EGLDisplay QEgl::display()
   350     if (apiType == QEgl::OpenGL)
   506 {
   351         eglWaitGL();
   507     static EGLDisplay dpy = EGL_NO_DISPLAY;
   352 #endif
   508     static bool openedDisplay = false;
   353 #ifdef EGL_OPENVG_API
   509 
   354     if (apiType == QEgl::OpenVG) {
   510     if (!openedDisplay) {
   355         eglBindAPI(EGL_OPENVG_API);
       
   356         eglWaitClient();
       
   357     }
       
   358 #endif
       
   359 }
       
   360 
       
   361 // Query the value of a configuration attribute.
       
   362 bool QEglContext::configAttrib(int name, EGLint *value) const
       
   363 {
       
   364     return eglGetConfigAttrib(display(), cfg, name, value);
       
   365 }
       
   366 
       
   367 void QEglContext::clearError()
       
   368 {
       
   369     eglGetError();
       
   370 }
       
   371 
       
   372 EGLint QEglContext::error()
       
   373 {
       
   374     return eglGetError();
       
   375 }
       
   376 
       
   377 // Retrieve all of the properties on "cfg".  If zero, return
       
   378 // the context's configuration.
       
   379 QEglProperties QEglContext::configProperties(EGLConfig cfg) const
       
   380 {
       
   381     if (!cfg)
       
   382         cfg = config();
       
   383     QEglProperties props;
       
   384     for (int name = 0x3020; name <= 0x304F; ++name) {
       
   385         EGLint value;
       
   386         if (name != EGL_NONE && eglGetConfigAttrib(display(), cfg, name, &value))
       
   387             props.setValue(name, value);
       
   388     }
       
   389     eglGetError();  // Clear the error state.
       
   390     return props;
       
   391 }
       
   392 
       
   393 EGLDisplay QEglContext::display()
       
   394 {
       
   395     if (!QEglContextTracker::displayOpened()) {
       
   396         dpy = eglGetDisplay(nativeDisplay());
   511         dpy = eglGetDisplay(nativeDisplay());
   397         QEglContextTracker::setDisplayOpened();
   512         openedDisplay = true;
   398         if (dpy == EGL_NO_DISPLAY) {
   513         if (dpy == EGL_NO_DISPLAY) {
   399             qWarning("QEglContext::display(): Falling back to EGL_DEFAULT_DISPLAY");
   514             qWarning("QEgl::display(): Falling back to EGL_DEFAULT_DISPLAY");
   400             dpy = eglGetDisplay(EGLNativeDisplayType(EGL_DEFAULT_DISPLAY));
   515             dpy = eglGetDisplay(EGLNativeDisplayType(EGL_DEFAULT_DISPLAY));
   401         }
   516         }
   402         if (dpy == EGL_NO_DISPLAY) {
   517         if (dpy == EGL_NO_DISPLAY) {
   403             qWarning("QEglContext::display(): Can't even open the default display");
   518             qWarning("QEgl::display(): Can't even open the default display");
   404             return EGL_NO_DISPLAY;
   519             return EGL_NO_DISPLAY;
   405         }
   520         }
   406 
   521 
   407         if (!eglInitialize(dpy, NULL, NULL)) {
   522         if (!eglInitialize(dpy, NULL, NULL)) {
   408             qWarning() << "QEglContext::display(): Cannot initialize EGL display:" << errorString(eglGetError());
   523             qWarning() << "QEgl::display(): Cannot initialize EGL display:" << QEgl::errorString();
   409             return EGL_NO_DISPLAY;
   524             return EGL_NO_DISPLAY;
   410         }
   525         }
       
   526 
       
   527         // Resolve the egl extension function pointers:
       
   528 #if (defined(EGL_KHR_image) || defined(EGL_KHR_image_base)) && !defined(EGL_EGLEXT_PROTOTYPES)
       
   529         if (QEgl::hasExtension("EGL_KHR_image") || QEgl::hasExtension("EGL_KHR_image_base")) {
       
   530             qt_eglCreateImageKHR = (_eglCreateImageKHR) eglGetProcAddress("eglCreateImageKHR");
       
   531             qt_eglDestroyImageKHR = (_eglDestroyImageKHR) eglGetProcAddress("eglDestroyImageKHR");
       
   532         }
       
   533 #endif
   411     }
   534     }
   412 
   535 
   413     return dpy;
   536     return dpy;
   414 }
   537 }
   415 
   538 
   416 #if !defined(Q_WS_X11) && !defined(Q_WS_WINCE) // WinCE & X11 implement this properly
   539 EGLImageKHR QEgl::eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
   417 EGLNativeDisplayType QEglContext::nativeDisplay()
   540 {
   418 {
   541     if (qt_eglCreateImageKHR)
   419     return EGL_DEFAULT_DISPLAY;
   542         return qt_eglCreateImageKHR(dpy, ctx, target, buffer, attrib_list);
   420 }
   543 
   421 #endif
   544     QEgl::display(); // Initialises function pointers
       
   545     if (qt_eglCreateImageKHR)
       
   546         return qt_eglCreateImageKHR(dpy, ctx, target, buffer, attrib_list);
       
   547 
       
   548     qWarning("QEgl::eglCreateImageKHR() called but EGL_KHR_image(_base) extension not present");
       
   549     return 0;
       
   550 }
       
   551 
       
   552 EGLBoolean QEgl::eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
       
   553 {
       
   554     if (qt_eglDestroyImageKHR)
       
   555         return qt_eglDestroyImageKHR(dpy, img);
       
   556 
       
   557     QEgl::display(); // Initialises function pointers
       
   558     if (qt_eglDestroyImageKHR)
       
   559         return qt_eglDestroyImageKHR(dpy, img);
       
   560 
       
   561     qWarning("QEgl::eglDestroyImageKHR() called but EGL_KHR_image(_base) extension not present");
       
   562     return 0;
       
   563 }
       
   564 
       
   565 
       
   566 #ifndef Q_WS_X11
       
   567 EGLSurface QEgl::createSurface(QPaintDevice *device, EGLConfig cfg, const QEglProperties *properties)
       
   568 {
       
   569     // Create the native drawable for the paint device.
       
   570     int devType = device->devType();
       
   571     EGLNativePixmapType pixmapDrawable = 0;
       
   572     EGLNativeWindowType windowDrawable = 0;
       
   573     bool ok;
       
   574     if (devType == QInternal::Pixmap) {
       
   575         pixmapDrawable = nativePixmap(static_cast<QPixmap *>(device));
       
   576         ok = (pixmapDrawable != 0);
       
   577     } else if (devType == QInternal::Widget) {
       
   578         windowDrawable = nativeWindow(static_cast<QWidget *>(device));
       
   579         ok = (windowDrawable != 0);
       
   580     } else {
       
   581         ok = false;
       
   582     }
       
   583     if (!ok) {
       
   584         qWarning("QEglContext::createSurface(): Cannot create the native EGL drawable");
       
   585         return EGL_NO_SURFACE;
       
   586     }
       
   587 
       
   588     // Create the EGL surface to draw into, based on the native drawable.
       
   589     const int *props;
       
   590     if (properties)
       
   591         props = properties->properties();
       
   592     else
       
   593         props = 0;
       
   594     EGLSurface surf;
       
   595     if (devType == QInternal::Widget)
       
   596         surf = eglCreateWindowSurface(QEgl::display(), cfg, windowDrawable, props);
       
   597     else
       
   598         surf = eglCreatePixmapSurface(QEgl::display(), cfg, pixmapDrawable, props);
       
   599     if (surf == EGL_NO_SURFACE) {
       
   600         qWarning("QEglContext::createSurface(): Unable to create EGL surface, error = 0x%x", eglGetError());
       
   601     }
       
   602     return surf;
       
   603 }
       
   604 #endif
       
   605 
   422 
   606 
   423 // Return the error string associated with a specific code.
   607 // Return the error string associated with a specific code.
   424 QString QEglContext::errorString(EGLint code)
   608 QString QEgl::errorString(EGLint code)
   425 {
   609 {
   426     static const char * const errors[] = {
   610     static const char * const errors[] = {
   427         "Success (0x3000)",                 // No tr
   611         "Success (0x3000)",                 // No tr
   428         "Not initialized (0x3001)",         // No tr
   612         "Not initialized (0x3001)",         // No tr
   429         "Bad access (0x3002)",              // No tr
   613         "Bad access (0x3002)",              // No tr
   446         return QLatin1String("0x") + QString::number(int(code), 16);
   630         return QLatin1String("0x") + QString::number(int(code), 16);
   447     }
   631     }
   448 }
   632 }
   449 
   633 
   450 // Dump all of the EGL configurations supported by the system.
   634 // Dump all of the EGL configurations supported by the system.
   451 void QEglContext::dumpAllConfigs()
   635 void QEgl::dumpAllConfigs()
   452 {
   636 {
   453     QEglProperties props;
   637     QEglProperties props;
   454     EGLint count = 0;
   638     EGLint count = 0;
   455     if (!eglGetConfigs(display(), 0, 0, &count) || count < 1)
   639     if (!eglGetConfigs(display(), 0, 0, &count) || count < 1)
   456         return;
   640         return;
   457     EGLConfig *configs = new EGLConfig [count];
   641     EGLConfig *configs = new EGLConfig [count];
   458     eglGetConfigs(display(), configs, count, &count);
   642     eglGetConfigs(display(), configs, count, &count);
   459     for (EGLint index = 0; index < count; ++index) {
   643     for (EGLint index = 0; index < count; ++index) {
   460         props = configProperties(configs[index]);
   644         props = QEglProperties(configs[index]);
   461         qWarning() << props.toString();
   645         qWarning() << props.toString();
   462     }
   646     }
   463     delete [] configs;
   647     delete [] configs;
   464 }
   648 }
   465 
   649 
   466 QString QEglContext::extensions()
   650 QString QEgl::extensions()
   467 {
   651 {
   468     const char* exts = eglQueryString(QEglContext::display(), EGL_EXTENSIONS);
   652     const char* exts = eglQueryString(QEgl::display(), EGL_EXTENSIONS);
   469     return QString(QLatin1String(exts));
   653     return QString(QLatin1String(exts));
   470 }
   654 }
   471 
   655 
   472 bool QEglContext::hasExtension(const char* extensionName)
   656 bool QEgl::hasExtension(const char* extensionName)
   473 {
   657 {
   474     QList<QByteArray> extensions =
   658     QList<QByteArray> extensions =
   475         QByteArray(reinterpret_cast<const char *>
   659         QByteArray(reinterpret_cast<const char *>
   476             (eglQueryString(QEglContext::display(), EGL_EXTENSIONS))).split(' ');
   660             (eglQueryString(QEgl::display(), EGL_EXTENSIONS))).split(' ');
   477     return extensions.contains(extensionName);
   661     return extensions.contains(extensionName);
   478 }
   662 }
   479 
   663 
   480 QEglContext *QEglContext::currentContext(QEgl::API api)
   664 QEglContext *QEglContext::currentContext(QEgl::API api)
   481 {
   665 {