src/gui/egl/qegl.cpp
branchGCC_SURGE
changeset 31 5daf16870df6
parent 30 5dc02b23752f
child 33 3e2da88830cd
equal deleted inserted replaced
27:93b982ccede2 31:5daf16870df6
    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/qdebug.h>
    45 #include <QtCore/qdebug.h>
       
    46 
    46 #include "qegl_p.h"
    47 #include "qegl_p.h"
       
    48 #include "qeglcontext_p.h"
       
    49 
    47 
    50 
    48 QT_BEGIN_NAMESPACE
    51 QT_BEGIN_NAMESPACE
    49 
    52 
    50 // Current GL and VG contexts.  These are used to determine if
    53 // Current GL and VG contexts.  These are used to determine if
    51 // we can avoid an eglMakeCurrent() after a call to lazyDoneCurrent().
    54 // we can avoid an eglMakeCurrent() after a call to lazyDoneCurrent().
    52 // If a background thread modifies the value, the worst that will
    55 // If a background thread modifies the value, the worst that will
    53 // happen is a redundant eglMakeCurrent() in the foreground thread.
    56 // happen is a redundant eglMakeCurrent() in the foreground thread.
    54 static QEglContext * volatile currentGLContext = 0;
    57 static QEglContext * volatile currentGLContext = 0;
    55 static QEglContext * volatile currentVGContext = 0;
    58 static QEglContext * volatile currentVGContext = 0;
    56 
    59 
    57 EGLDisplay QEglContext::dpy = EGL_NO_DISPLAY;
       
    58 
       
    59 QEglContext::QEglContext()
    60 QEglContext::QEglContext()
    60     : apiType(QEgl::OpenGL)
    61     : apiType(QEgl::OpenGL)
    61     , ctx(EGL_NO_CONTEXT)
    62     , ctx(EGL_NO_CONTEXT)
    62     , cfg(0)
    63     , cfg(QEGL_NO_CONFIG)
    63     , currentSurface(EGL_NO_SURFACE)
    64     , currentSurface(EGL_NO_SURFACE)
    64     , current(false)
    65     , current(false)
    65     , ownsContext(true)
    66     , ownsContext(true)
    66     , sharing(false)
    67     , sharing(false)
    67 {
    68 {
    85 bool QEglContext::isCurrent() const
    86 bool QEglContext::isCurrent() const
    86 {
    87 {
    87     return current;
    88     return current;
    88 }
    89 }
    89 
    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 
    90 // Choose a configuration that matches "properties".
   252 // Choose a configuration that matches "properties".
    91 bool QEglContext::chooseConfig
   253 EGLConfig QEgl::chooseConfig(const QEglProperties* properties, QEgl::PixelFormatMatch match)
    92         (const QEglProperties& properties, QEgl::PixelFormatMatch match)
   254 {
    93 {
   255     QEglProperties props(*properties);
    94     QEglProperties props(properties);
   256     EGLConfig cfg = QEGL_NO_CONFIG;
    95     do {
   257     do {
    96         // Get the number of matching configurations for this set of properties.
   258         // Get the number of matching configurations for this set of properties.
    97         EGLint matching = 0;
   259         EGLint matching = 0;
    98         if (!eglChooseConfig(display(), props.properties(), 0, 0, &matching) || !matching)
   260         EGLDisplay dpy = QEgl::display();
       
   261         if (!eglChooseConfig(dpy, props.properties(), 0, 0, &matching) || !matching)
    99             continue;
   262             continue;
   100 
   263 
   101         // If we want the best pixel format, then return the first
   264         // If we want the best pixel format, then return the first
   102         // matching configuration.
   265         // matching configuration.
   103         if (match == QEgl::BestPixelFormat) {
   266         if (match == QEgl::BestPixelFormat) {
   104             eglChooseConfig(display(), props.properties(), &cfg, 1, &matching);
   267             eglChooseConfig(display(), props.properties(), &cfg, 1, &matching);
   105             if (matching < 1)
   268             if (matching < 1)
   106                 continue;
   269                 continue;
   107             return true;
   270             return cfg;
   108         }
   271         }
   109 
   272 
   110         // Fetch all of the matching configurations and find the
   273         // Fetch all of the matching configurations and find the
   111         // first that matches the pixel format we wanted.
   274         // first that matches the pixel format we wanted.
   112         EGLint size = matching;
   275         EGLint size = matching;
   123                     blue == props.value(EGL_BLUE_SIZE) &&
   286                     blue == props.value(EGL_BLUE_SIZE) &&
   124                     (props.value(EGL_ALPHA_SIZE) == 0 ||
   287                     (props.value(EGL_ALPHA_SIZE) == 0 ||
   125                      alpha == props.value(EGL_ALPHA_SIZE))) {
   288                      alpha == props.value(EGL_ALPHA_SIZE))) {
   126                 cfg = configs[index];
   289                 cfg = configs[index];
   127                 delete [] configs;
   290                 delete [] configs;
   128                 return true;
   291                 return cfg;
   129             }
   292             }
   130         }
   293         }
   131         delete [] configs;
   294         delete [] configs;
   132     } while (props.reduceConfiguration());
   295     } while (props.reduceConfiguration());
   133 
   296 
   140 #endif
   303 #endif
   141     {
   304     {
   142         qWarning() << "QEglContext::chooseConfig(): Could not find a suitable EGL configuration";
   305         qWarning() << "QEglContext::chooseConfig(): Could not find a suitable EGL configuration";
   143         qWarning() << "Requested:" << props.toString();
   306         qWarning() << "Requested:" << props.toString();
   144         qWarning() << "Available:";
   307         qWarning() << "Available:";
   145         dumpAllConfigs();
   308         QEgl::dumpAllConfigs();
   146     }
   309     }
   147     return false;
   310     return QEGL_NO_CONFIG;
   148 }
   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 
   149 
   324 
   150 // Create the EGLContext.
   325 // Create the EGLContext.
   151 bool QEglContext::createContext(QEglContext *shareContext, const QEglProperties *properties)
   326 bool QEglContext::createContext(QEglContext *shareContext, const QEglProperties *properties)
   152 {
   327 {
   153     // 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
   154 #ifdef EGL_OPENGL_ES_API
   330 #ifdef EGL_OPENGL_ES_API
   155     if (apiType == QEgl::OpenGL)
   331     if (apiType == QEgl::OpenGL)
   156         eglBindAPI(EGL_OPENGL_ES_API);
   332         eglBindAPI(EGL_OPENGL_ES_API);
   157 #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)
   158 #ifdef EGL_OPENVG_API
   340 #ifdef EGL_OPENVG_API
   159     if (apiType == QEgl::OpenVG)
   341     if (apiType == QEgl::OpenVG)
   160         eglBindAPI(EGL_OPENVG_API);
   342         eglBindAPI(EGL_OPENVG_API);
   161 #endif
   343 #endif
   162 
   344 
   163     // Create a new context for the configuration.
   345     // Create a new context for the configuration.
   164     QEglProperties contextProps;
   346     QEglProperties contextProps;
   165     if (properties)
   347     if (properties)
   166         contextProps = *properties;
   348         contextProps = *properties;
   167 #if defined(QT_OPENGL_ES_2)
   349 #ifdef QT_OPENGL_ES_2
   168     if (apiType == QEgl::OpenGL)
   350     if (apiType == QEgl::OpenGL)
   169         contextProps.setValue(EGL_CONTEXT_CLIENT_VERSION, 2);
   351         contextProps.setValue(EGL_CONTEXT_CLIENT_VERSION, 2);
   170 #endif
   352 #endif
   171     sharing = false;
   353     sharing = false;
   172     if (shareContext && shareContext->ctx == EGL_NO_CONTEXT)
   354     if (shareContext && shareContext->ctx == EGL_NO_CONTEXT)
   173         shareContext = 0;
   355         shareContext = 0;
   174     if (shareContext) {
   356     if (shareContext) {
   175         ctx = eglCreateContext(display(), cfg, shareContext->ctx, contextProps.properties());
   357         ctx = eglCreateContext(QEgl::display(), cfg, shareContext->ctx, contextProps.properties());
   176         if (ctx == EGL_NO_CONTEXT) {
   358         if (ctx == EGL_NO_CONTEXT) {
   177             qWarning() << "QEglContext::createContext(): Could not share context:" << errorString(eglGetError());
   359             qWarning() << "QEglContext::createContext(): Could not share context:" << QEgl::errorString();
   178             shareContext = 0;
   360             shareContext = 0;
   179         } else {
   361         } else {
   180             sharing = true;
   362             sharing = true;
   181         }
   363         }
   182     }
   364     }
   183     if (ctx == EGL_NO_CONTEXT) {
   365     if (ctx == EGL_NO_CONTEXT) {
   184         ctx = eglCreateContext(display(), cfg, 0, contextProps.properties());
   366         ctx = eglCreateContext(display(), cfg, 0, contextProps.properties());
   185         if (ctx == EGL_NO_CONTEXT) {
   367         if (ctx == EGL_NO_CONTEXT) {
   186             qWarning() << "QEglContext::createContext(): Unable to create EGL context:" << errorString(eglGetError());
   368             qWarning() << "QEglContext::createContext(): Unable to create EGL context:" << QEgl::errorString();
   187             return false;
   369             return false;
   188         }
   370         }
   189     }
   371     }
   190     return true;
   372     return true;
   191 }
   373 }
   212 
   394 
   213 bool QEglContext::makeCurrent(EGLSurface surface)
   395 bool QEglContext::makeCurrent(EGLSurface surface)
   214 {
   396 {
   215     if (ctx == EGL_NO_CONTEXT) {
   397     if (ctx == EGL_NO_CONTEXT) {
   216         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";
   217         return false;
   404         return false;
   218     }
   405     }
   219 
   406 
   220     // 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
   221     // to assume that it is still current within the thread.
   408     // to assume that it is still current within the thread.
   238 #ifdef EGL_OPENVG_API
   425 #ifdef EGL_OPENVG_API
   239     if (apiType == QEgl::OpenVG)
   426     if (apiType == QEgl::OpenVG)
   240         eglBindAPI(EGL_OPENVG_API);
   427         eglBindAPI(EGL_OPENVG_API);
   241 #endif
   428 #endif
   242 
   429 
   243     bool ok = eglMakeCurrent(display(), surface, surface, ctx);
   430     bool ok = eglMakeCurrent(QEgl::display(), surface, surface, ctx);
   244     if (!ok)
   431     if (!ok)
   245         qWarning() << "QEglContext::makeCurrent():" << errorString(eglGetError());
   432         qWarning() << "QEglContext::makeCurrent(" << surface << "):" << QEgl::errorString();
   246     return ok;
   433     return ok;
   247 }
   434 }
   248 
   435 
   249 bool QEglContext::doneCurrent()
   436 bool QEglContext::doneCurrent()
   250 {
   437 {
   267 #ifdef EGL_OPENVG_API
   454 #ifdef EGL_OPENVG_API
   268     if (apiType == QEgl::OpenVG)
   455     if (apiType == QEgl::OpenVG)
   269         eglBindAPI(EGL_OPENVG_API);
   456         eglBindAPI(EGL_OPENVG_API);
   270 #endif
   457 #endif
   271 
   458 
   272     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);
   273     if (!ok)
   460     if (!ok)
   274         qWarning() << "QEglContext::doneCurrent():" << errorString(eglGetError());
   461         qWarning() << "QEglContext::doneCurrent():" << QEgl::errorString();
   275     return ok;
   462     return ok;
   276 }
   463 }
   277 
   464 
   278 // Act as though doneCurrent() was called, but keep the context
   465 // Act as though doneCurrent() was called, but keep the context
   279 // and the surface active for the moment.  This allows makeCurrent()
   466 // and the surface active for the moment.  This allows makeCurrent()
   289 bool QEglContext::swapBuffers(EGLSurface surface)
   476 bool QEglContext::swapBuffers(EGLSurface surface)
   290 {
   477 {
   291     if(ctx == EGL_NO_CONTEXT)
   478     if(ctx == EGL_NO_CONTEXT)
   292         return false;
   479         return false;
   293 
   480 
   294     bool ok = eglSwapBuffers(display(), surface);
   481     bool ok = eglSwapBuffers(QEgl::display(), surface);
   295     if (!ok)
   482     if (!ok)
   296         qWarning() << "QEglContext::swapBuffers():" << errorString(eglGetError());
   483         qWarning() << "QEglContext::swapBuffers():" << QEgl::errorString();
   297     return ok;
   484     return ok;
   298 }
   485 }
   299 
   486 
   300 // Wait for native rendering operations to complete before starting
   487 int QEglContext::configAttrib(int name) const
   301 // to use OpenGL/OpenVG operations.
   488 {
   302 void QEglContext::waitNative()
   489     EGLint value;
   303 {
   490     EGLBoolean success = eglGetConfigAttrib(QEgl::display(), cfg, name, &value);
   304 #ifdef EGL_CORE_NATIVE_ENGINE
   491     if (success)
   305     eglWaitNative(EGL_CORE_NATIVE_ENGINE);
   492         return value;
   306 #endif
   493     else
   307 }
   494         return EGL_DONT_CARE;
   308 
   495 }
   309 // Wait for client OpenGL/OpenVG operations to complete before
   496 
   310 // using native rendering operations.
   497 typedef EGLImageKHR (EGLAPIENTRY *_eglCreateImageKHR)(EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, const EGLint*);
   311 void QEglContext::waitClient()
   498 typedef EGLBoolean (EGLAPIENTRY *_eglDestroyImageKHR)(EGLDisplay, EGLImageKHR);
   312 {
   499 
   313 #ifdef EGL_OPENGL_ES_API
   500 // Defined in qegl.cpp:
   314     if (apiType == QEgl::OpenGL) {
   501 static _eglCreateImageKHR qt_eglCreateImageKHR = 0;
   315         eglBindAPI(EGL_OPENGL_ES_API);
   502 static _eglDestroyImageKHR qt_eglDestroyImageKHR = 0;
   316         eglWaitClient();
   503 
   317     }
   504 
   318 #else
   505 EGLDisplay QEgl::display()
   319     if (apiType == QEgl::OpenGL)
   506 {
   320         eglWaitGL();
   507     static EGLDisplay dpy = EGL_NO_DISPLAY;
   321 #endif
       
   322 #ifdef EGL_OPENVG_API
       
   323     if (apiType == QEgl::OpenVG) {
       
   324         eglBindAPI(EGL_OPENVG_API);
       
   325         eglWaitClient();
       
   326     }
       
   327 #endif
       
   328 }
       
   329 
       
   330 // Query the value of a configuration attribute.
       
   331 bool QEglContext::configAttrib(int name, EGLint *value) const
       
   332 {
       
   333     return eglGetConfigAttrib(display(), cfg, name, value);
       
   334 }
       
   335 
       
   336 // Retrieve all of the properties on "cfg".  If zero, return
       
   337 // the context's configuration.
       
   338 QEglProperties QEglContext::configProperties(EGLConfig cfg) const
       
   339 {
       
   340     if (!cfg)
       
   341         cfg = config();
       
   342     QEglProperties props;
       
   343     for (int name = 0x3020; name <= 0x304F; ++name) {
       
   344         EGLint value;
       
   345         if (name != EGL_NONE && eglGetConfigAttrib(display(), cfg, name, &value))
       
   346             props.setValue(name, value);
       
   347     }
       
   348     eglGetError();  // Clear the error state.
       
   349     return props;
       
   350 }
       
   351 
       
   352 EGLDisplay QEglContext::display()
       
   353 {
       
   354     static bool openedDisplay = false;
   508     static bool openedDisplay = false;
   355 
   509 
   356     if (!openedDisplay) {
   510     if (!openedDisplay) {
   357         dpy = eglGetDisplay(nativeDisplay());
   511         dpy = eglGetDisplay(nativeDisplay());
   358         openedDisplay = true;
   512         openedDisplay = true;
   359         if (dpy == EGL_NO_DISPLAY) {
   513         if (dpy == EGL_NO_DISPLAY) {
   360             qWarning("QEglContext::display(): Falling back to EGL_DEFAULT_DISPLAY");
   514             qWarning("QEgl::display(): Falling back to EGL_DEFAULT_DISPLAY");
   361             dpy = eglGetDisplay(EGLNativeDisplayType(EGL_DEFAULT_DISPLAY));
   515             dpy = eglGetDisplay(EGLNativeDisplayType(EGL_DEFAULT_DISPLAY));
   362         }
   516         }
   363         if (dpy == EGL_NO_DISPLAY) {
   517         if (dpy == EGL_NO_DISPLAY) {
   364             qWarning("QEglContext::display(): Can't even open the default display");
   518             qWarning("QEgl::display(): Can't even open the default display");
   365             return EGL_NO_DISPLAY;
   519             return EGL_NO_DISPLAY;
   366         }
   520         }
   367 
   521 
   368         if (!eglInitialize(dpy, NULL, NULL)) {
   522         if (!eglInitialize(dpy, NULL, NULL)) {
   369             qWarning() << "QEglContext::display(): Cannot initialize EGL display:" << errorString(eglGetError());
   523             qWarning() << "QEgl::display(): Cannot initialize EGL display:" << QEgl::errorString();
   370             return EGL_NO_DISPLAY;
   524             return EGL_NO_DISPLAY;
   371         }
   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
   372     }
   534     }
   373 
   535 
   374     return dpy;
   536     return dpy;
   375 }
   537 }
   376 
   538 
   377 #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)
   378 EGLNativeDisplayType QEglContext::nativeDisplay()
   540 {
   379 {
   541     if (qt_eglCreateImageKHR)
   380     return EGL_DEFAULT_DISPLAY;
   542         return qt_eglCreateImageKHR(dpy, ctx, target, buffer, attrib_list);
   381 }
   543 
   382 #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 
   383 
   606 
   384 // Return the error string associated with a specific code.
   607 // Return the error string associated with a specific code.
   385 QString QEglContext::errorString(EGLint code)
   608 QString QEgl::errorString(EGLint code)
   386 {
   609 {
   387     static const char * const errors[] = {
   610     static const char * const errors[] = {
   388         "Success (0x3000)",                 // No tr
   611         "Success (0x3000)",                 // No tr
   389         "Not initialized (0x3001)",         // No tr
   612         "Not initialized (0x3001)",         // No tr
   390         "Bad access (0x3002)",              // No tr
   613         "Bad access (0x3002)",              // No tr
   407         return QLatin1String("0x") + QString::number(int(code), 16);
   630         return QLatin1String("0x") + QString::number(int(code), 16);
   408     }
   631     }
   409 }
   632 }
   410 
   633 
   411 // Dump all of the EGL configurations supported by the system.
   634 // Dump all of the EGL configurations supported by the system.
   412 void QEglContext::dumpAllConfigs()
   635 void QEgl::dumpAllConfigs()
   413 {
   636 {
   414     QEglProperties props;
   637     QEglProperties props;
   415     EGLint count = 0;
   638     EGLint count = 0;
   416     if (!eglGetConfigs(display(), 0, 0, &count) || count < 1)
   639     if (!eglGetConfigs(display(), 0, 0, &count) || count < 1)
   417         return;
   640         return;
   418     EGLConfig *configs = new EGLConfig [count];
   641     EGLConfig *configs = new EGLConfig [count];
   419     eglGetConfigs(display(), configs, count, &count);
   642     eglGetConfigs(display(), configs, count, &count);
   420     for (EGLint index = 0; index < count; ++index) {
   643     for (EGLint index = 0; index < count; ++index) {
   421         props = configProperties(configs[index]);
   644         props = QEglProperties(configs[index]);
   422         qWarning() << props.toString();
   645         qWarning() << props.toString();
   423     }
   646     }
   424     delete [] configs;
   647     delete [] configs;
   425 }
   648 }
   426 
   649 
   427 QString QEglContext::extensions()
   650 QString QEgl::extensions()
   428 {
   651 {
   429     const char* exts = eglQueryString(QEglContext::display(), EGL_EXTENSIONS);
   652     const char* exts = eglQueryString(QEgl::display(), EGL_EXTENSIONS);
   430     return QString(QLatin1String(exts));
   653     return QString(QLatin1String(exts));
   431 }
   654 }
   432 
   655 
   433 bool QEglContext::hasExtension(const char* extensionName)
   656 bool QEgl::hasExtension(const char* extensionName)
   434 {
   657 {
   435     QList<QByteArray> extensions =
   658     QList<QByteArray> extensions =
   436         QByteArray(reinterpret_cast<const char *>
   659         QByteArray(reinterpret_cast<const char *>
   437             (eglQueryString(QEglContext::display(), EGL_EXTENSIONS))).split(' ');
   660             (eglQueryString(QEgl::display(), EGL_EXTENSIONS))).split(' ');
   438     return extensions.contains(extensionName);
   661     return extensions.contains(extensionName);
   439 }
   662 }
   440 
   663 
   441 QEglContext *QEglContext::currentContext(QEgl::API api)
   664 QEglContext *QEglContext::currentContext(QEgl::API api)
   442 {
   665 {