src/gui/egl/qegl.cpp
changeset 7 f7bc934e204c
parent 3 41300fa6a67c
child 23 89e065397ea6
equal deleted inserted replaced
3:41300fa6a67c 7:f7bc934e204c
     1 /****************************************************************************
     1 /****************************************************************************
     2 **
     2 **
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     4 ** All rights reserved.
     4 ** All rights reserved.
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
     6 **
     6 **
     7 ** This file is part of the QtGui module of the Qt Toolkit.
     7 ** This file is part of the QtGui module of the Qt Toolkit.
     8 **
     8 **
    52 // If a background thread modifies the value, the worst that will
    52 // If a background thread modifies the value, the worst that will
    53 // happen is a redundant eglMakeCurrent() in the foreground thread.
    53 // happen is a redundant eglMakeCurrent() in the foreground thread.
    54 static QEglContext * volatile currentGLContext = 0;
    54 static QEglContext * volatile currentGLContext = 0;
    55 static QEglContext * volatile currentVGContext = 0;
    55 static QEglContext * volatile currentVGContext = 0;
    56 
    56 
       
    57 EGLDisplay QEglContext::dpy = EGL_NO_DISPLAY;
       
    58 
    57 QEglContext::QEglContext()
    59 QEglContext::QEglContext()
    58     : apiType(QEgl::OpenGL)
    60     : apiType(QEgl::OpenGL)
    59     , dpy(EGL_NO_DISPLAY)
       
    60     , ctx(EGL_NO_CONTEXT)
    61     , ctx(EGL_NO_CONTEXT)
    61     , cfg(0)
    62     , cfg(0)
    62     , currentSurface(EGL_NO_SURFACE)
    63     , currentSurface(EGL_NO_SURFACE)
    63     , current(false)
    64     , current(false)
    64     , ownsContext(true)
    65     , ownsContext(true)
    66 {
    67 {
    67 }
    68 }
    68 
    69 
    69 QEglContext::~QEglContext()
    70 QEglContext::~QEglContext()
    70 {
    71 {
    71     destroy();
    72     destroyContext();
    72 
    73 
    73     if (currentGLContext == this)
    74     if (currentGLContext == this)
    74         currentGLContext = 0;
    75         currentGLContext = 0;
    75     if (currentVGContext == this)
    76     if (currentVGContext == this)
    76         currentVGContext = 0;
    77         currentVGContext = 0;
    84 bool QEglContext::isCurrent() const
    85 bool QEglContext::isCurrent() const
    85 {
    86 {
    86     return current;
    87     return current;
    87 }
    88 }
    88 
    89 
    89 // Open the EGL display associated with "device".
       
    90 bool QEglContext::openDisplay(QPaintDevice *device)
       
    91 {
       
    92     if (dpy == EGL_NO_DISPLAY)
       
    93         dpy = defaultDisplay(device);
       
    94     return (dpy != EGL_NO_DISPLAY);
       
    95 }
       
    96 
       
    97 // Choose a configuration that matches "properties".
    90 // Choose a configuration that matches "properties".
    98 bool QEglContext::chooseConfig
    91 bool QEglContext::chooseConfig
    99         (const QEglProperties& properties, QEgl::PixelFormatMatch match)
    92         (const QEglProperties& properties, QEgl::PixelFormatMatch match)
   100 {
    93 {
   101     QEglProperties props(properties);
    94     QEglProperties props(properties);
   102     do {
    95     do {
   103         // Get the number of matching configurations for this set of properties.
    96         // Get the number of matching configurations for this set of properties.
   104         EGLint matching = 0;
    97         EGLint matching = 0;
   105         if (!eglChooseConfig(dpy, props.properties(), 0, 0, &matching) || !matching)
    98         if (!eglChooseConfig(display(), props.properties(), 0, 0, &matching) || !matching)
   106             continue;
    99             continue;
   107 
   100 
   108         // If we want the best pixel format, then return the first
   101         // If we want the best pixel format, then return the first
   109         // matching configuration.
   102         // matching configuration.
   110         if (match == QEgl::BestPixelFormat) {
   103         if (match == QEgl::BestPixelFormat) {
   111             eglChooseConfig(dpy, props.properties(), &cfg, 1, &matching);
   104             eglChooseConfig(display(), props.properties(), &cfg, 1, &matching);
   112             if (matching < 1)
   105             if (matching < 1)
   113                 continue;
   106                 continue;
   114             return true;
   107             return true;
   115         }
   108         }
   116 
   109 
   117         // Fetch all of the matching configurations and find the
   110         // Fetch all of the matching configurations and find the
   118         // first that matches the pixel format we wanted.
   111         // first that matches the pixel format we wanted.
   119         EGLint size = matching;
   112         EGLint size = matching;
   120         EGLConfig *configs = new EGLConfig [size];
   113         EGLConfig *configs = new EGLConfig [size];
   121         eglChooseConfig(dpy, props.properties(), configs, size, &matching);
   114         eglChooseConfig(display(), props.properties(), configs, size, &matching);
   122         for (EGLint index = 0; index < size; ++index) {
   115         for (EGLint index = 0; index < size; ++index) {
   123             EGLint red, green, blue, alpha;
   116             EGLint red, green, blue, alpha;
   124             eglGetConfigAttrib(dpy, configs[index], EGL_RED_SIZE, &red);
   117             eglGetConfigAttrib(display(), configs[index], EGL_RED_SIZE, &red);
   125             eglGetConfigAttrib(dpy, configs[index], EGL_GREEN_SIZE, &green);
   118             eglGetConfigAttrib(display(), configs[index], EGL_GREEN_SIZE, &green);
   126             eglGetConfigAttrib(dpy, configs[index], EGL_BLUE_SIZE, &blue);
   119             eglGetConfigAttrib(display(), configs[index], EGL_BLUE_SIZE, &blue);
   127             eglGetConfigAttrib(dpy, configs[index], EGL_ALPHA_SIZE, &alpha);
   120             eglGetConfigAttrib(display(), configs[index], EGL_ALPHA_SIZE, &alpha);
   128             if (red == props.value(EGL_RED_SIZE) &&
   121             if (red == props.value(EGL_RED_SIZE) &&
   129                     green == props.value(EGL_GREEN_SIZE) &&
   122                     green == props.value(EGL_GREEN_SIZE) &&
   130                     blue == props.value(EGL_BLUE_SIZE) &&
   123                     blue == props.value(EGL_BLUE_SIZE) &&
   131                     (props.value(EGL_ALPHA_SIZE) == 0 ||
   124                     (props.value(EGL_ALPHA_SIZE) == 0 ||
   132                      alpha == props.value(EGL_ALPHA_SIZE))) {
   125                      alpha == props.value(EGL_ALPHA_SIZE))) {
   177 #endif
   170 #endif
   178     sharing = false;
   171     sharing = false;
   179     if (shareContext && shareContext->ctx == EGL_NO_CONTEXT)
   172     if (shareContext && shareContext->ctx == EGL_NO_CONTEXT)
   180         shareContext = 0;
   173         shareContext = 0;
   181     if (shareContext) {
   174     if (shareContext) {
   182         ctx = eglCreateContext(dpy, cfg, shareContext->ctx, contextProps.properties());
   175         ctx = eglCreateContext(display(), cfg, shareContext->ctx, contextProps.properties());
   183         if (ctx == EGL_NO_CONTEXT) {
   176         if (ctx == EGL_NO_CONTEXT) {
   184             qWarning() << "QEglContext::createContext(): Could not share context:" << errorString(eglGetError());
   177             qWarning() << "QEglContext::createContext(): Could not share context:" << errorString(eglGetError());
   185             shareContext = 0;
   178             shareContext = 0;
   186         } else {
   179         } else {
   187             sharing = true;
   180             sharing = true;
   188         }
   181         }
   189     }
   182     }
   190     if (ctx == EGL_NO_CONTEXT) {
   183     if (ctx == EGL_NO_CONTEXT) {
   191         ctx = eglCreateContext(dpy, cfg, 0, contextProps.properties());
   184         ctx = eglCreateContext(display(), cfg, 0, contextProps.properties());
   192         if (ctx == EGL_NO_CONTEXT) {
   185         if (ctx == EGL_NO_CONTEXT) {
   193             qWarning() << "QEglContext::createContext(): Unable to create EGL context:" << errorString(eglGetError());
   186             qWarning() << "QEglContext::createContext(): Unable to create EGL context:" << errorString(eglGetError());
   194             return false;
   187             return false;
   195         }
   188         }
   196     }
   189     }
   202 void QEglContext::destroySurface(EGLSurface surface)
   195 void QEglContext::destroySurface(EGLSurface surface)
   203 {
   196 {
   204     if (surface != EGL_NO_SURFACE) {
   197     if (surface != EGL_NO_SURFACE) {
   205         if (surface == currentSurface)
   198         if (surface == currentSurface)
   206             doneCurrent();
   199             doneCurrent();
   207         eglDestroySurface(dpy, surface);
   200         eglDestroySurface(display(), surface);
   208     }
   201     }
   209 }
   202 }
   210 
   203 
   211 // Destroy the context.  Note: this does not destroy the surface.
   204 // Destroy the context.  Note: this does not destroy the surface.
   212 void QEglContext::destroy()
   205 void QEglContext::destroyContext()
   213 {
   206 {
   214     if (ctx != EGL_NO_CONTEXT && ownsContext)
   207     if (ctx != EGL_NO_CONTEXT && ownsContext)
   215         eglDestroyContext(dpy, ctx);
   208         eglDestroyContext(display(), ctx);
   216     dpy = EGL_NO_DISPLAY;
       
   217     ctx = EGL_NO_CONTEXT;
   209     ctx = EGL_NO_CONTEXT;
   218     cfg = 0;
   210     cfg = 0;
   219 }
   211 }
   220 
   212 
   221 bool QEglContext::makeCurrent(EGLSurface surface)
   213 bool QEglContext::makeCurrent(EGLSurface surface)
   246 #ifdef EGL_OPENVG_API
   238 #ifdef EGL_OPENVG_API
   247     if (apiType == QEgl::OpenVG)
   239     if (apiType == QEgl::OpenVG)
   248         eglBindAPI(EGL_OPENVG_API);
   240         eglBindAPI(EGL_OPENVG_API);
   249 #endif
   241 #endif
   250 
   242 
   251     bool ok = eglMakeCurrent(dpy, surface, surface, ctx);
   243     bool ok = eglMakeCurrent(display(), surface, surface, ctx);
   252     if (!ok)
   244     if (!ok)
   253         qWarning() << "QEglContext::makeCurrent():" << errorString(eglGetError());
   245         qWarning() << "QEglContext::makeCurrent():" << errorString(eglGetError());
   254     return ok;
   246     return ok;
   255 }
   247 }
   256 
   248 
   275 #ifdef EGL_OPENVG_API
   267 #ifdef EGL_OPENVG_API
   276     if (apiType == QEgl::OpenVG)
   268     if (apiType == QEgl::OpenVG)
   277         eglBindAPI(EGL_OPENVG_API);
   269         eglBindAPI(EGL_OPENVG_API);
   278 #endif
   270 #endif
   279 
   271 
   280     bool ok = eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
   272     bool ok = eglMakeCurrent(display(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
   281     if (!ok)
   273     if (!ok)
   282         qWarning() << "QEglContext::doneCurrent():" << errorString(eglGetError());
   274         qWarning() << "QEglContext::doneCurrent():" << errorString(eglGetError());
   283     return ok;
   275     return ok;
   284 }
   276 }
   285 
   277 
   297 bool QEglContext::swapBuffers(EGLSurface surface)
   289 bool QEglContext::swapBuffers(EGLSurface surface)
   298 {
   290 {
   299     if(ctx == EGL_NO_CONTEXT)
   291     if(ctx == EGL_NO_CONTEXT)
   300         return false;
   292         return false;
   301 
   293 
   302     bool ok = eglSwapBuffers(dpy, surface);
   294     bool ok = eglSwapBuffers(display(), surface);
   303     if (!ok)
   295     if (!ok)
   304         qWarning() << "QEglContext::swapBuffers():" << errorString(eglGetError());
   296         qWarning() << "QEglContext::swapBuffers():" << errorString(eglGetError());
   305     return ok;
   297     return ok;
   306 }
   298 }
   307 
   299 
   336 }
   328 }
   337 
   329 
   338 // Query the value of a configuration attribute.
   330 // Query the value of a configuration attribute.
   339 bool QEglContext::configAttrib(int name, EGLint *value) const
   331 bool QEglContext::configAttrib(int name, EGLint *value) const
   340 {
   332 {
   341     return eglGetConfigAttrib(dpy, cfg, name, value);
   333     return eglGetConfigAttrib(display(), cfg, name, value);
   342 }
   334 }
   343 
   335 
   344 // Retrieve all of the properties on "cfg".  If zero, return
   336 // Retrieve all of the properties on "cfg".  If zero, return
   345 // the context's configuration.
   337 // the context's configuration.
   346 QEglProperties QEglContext::configProperties(EGLConfig cfg) const
   338 QEglProperties QEglContext::configProperties(EGLConfig cfg) const
   348     if (!cfg)
   340     if (!cfg)
   349         cfg = config();
   341         cfg = config();
   350     QEglProperties props;
   342     QEglProperties props;
   351     for (int name = 0x3020; name <= 0x304F; ++name) {
   343     for (int name = 0x3020; name <= 0x304F; ++name) {
   352         EGLint value;
   344         EGLint value;
   353         if (name != EGL_NONE && eglGetConfigAttrib(dpy, cfg, name, &value))
   345         if (name != EGL_NONE && eglGetConfigAttrib(display(), cfg, name, &value))
   354             props.setValue(name, value);
   346             props.setValue(name, value);
   355     }
   347     }
   356     eglGetError();  // Clear the error state.
   348     eglGetError();  // Clear the error state.
   357     return props;
   349     return props;
   358 }
   350 }
   359 
   351 
   360 // Initialize and return the default display.
   352 EGLDisplay QEglContext::display()
   361 EGLDisplay QEglContext::defaultDisplay(QPaintDevice *device)
   353 {
   362 {
   354     static bool openedDisplay = false;
   363     static EGLDisplay dpy = EGL_NO_DISPLAY;
   355 
   364     if (dpy == EGL_NO_DISPLAY) {
   356     if (!openedDisplay) {
   365         dpy = getDisplay(device);
   357         dpy = eglGetDisplay(nativeDisplay());
       
   358         openedDisplay = true;
   366         if (dpy == EGL_NO_DISPLAY) {
   359         if (dpy == EGL_NO_DISPLAY) {
   367             qWarning() << "QEglContext::defaultDisplay(): Cannot open EGL display";
   360             qWarning("QEglContext::display(): Falling back to EGL_DEFAULT_DISPLAY");
       
   361             dpy = eglGetDisplay(EGLNativeDisplayType(EGL_DEFAULT_DISPLAY));
       
   362         }
       
   363         if (dpy == EGL_NO_DISPLAY) {
       
   364             qWarning("QEglContext::display(): Can't even open the default display");
   368             return EGL_NO_DISPLAY;
   365             return EGL_NO_DISPLAY;
   369         }
   366         }
       
   367 
   370         if (!eglInitialize(dpy, NULL, NULL)) {
   368         if (!eglInitialize(dpy, NULL, NULL)) {
   371             qWarning() << "QEglContext::defaultDisplay(): Cannot initialize EGL display:" << errorString(eglGetError());
   369             qWarning() << "QEglContext::display(): Cannot initialize EGL display:" << errorString(eglGetError());
   372             return EGL_NO_DISPLAY;
   370             return EGL_NO_DISPLAY;
   373         }
   371         }
   374 #ifdef EGL_OPENGL_ES_API
   372     }
   375         eglBindAPI(EGL_OPENGL_ES_API);
   373 
   376 #endif
       
   377     }
       
   378     return dpy;
   374     return dpy;
   379 }
   375 }
       
   376 
       
   377 #if !defined(Q_WS_X11) && !defined(Q_WS_WINCE) // WinCE & X11 implement this properly
       
   378 EGLNativeDisplayType QEglContext::nativeDisplay()
       
   379 {
       
   380     return EGL_DEFAULT_DISPLAY;
       
   381 }
       
   382 #endif
   380 
   383 
   381 // Return the error string associated with a specific code.
   384 // Return the error string associated with a specific code.
   382 QString QEglContext::errorString(EGLint code)
   385 QString QEglContext::errorString(EGLint code)
   383 {
   386 {
   384     static const char * const errors[] = {
   387     static const char * const errors[] = {
   408 // Dump all of the EGL configurations supported by the system.
   411 // Dump all of the EGL configurations supported by the system.
   409 void QEglContext::dumpAllConfigs()
   412 void QEglContext::dumpAllConfigs()
   410 {
   413 {
   411     QEglProperties props;
   414     QEglProperties props;
   412     EGLint count = 0;
   415     EGLint count = 0;
   413     if (!eglGetConfigs(dpy, 0, 0, &count) || count < 1)
   416     if (!eglGetConfigs(display(), 0, 0, &count) || count < 1)
   414         return;
   417         return;
   415     EGLConfig *configs = new EGLConfig [count];
   418     EGLConfig *configs = new EGLConfig [count];
   416     eglGetConfigs(dpy, configs, count, &count);
   419     eglGetConfigs(display(), configs, count, &count);
   417     for (EGLint index = 0; index < count; ++index) {
   420     for (EGLint index = 0; index < count; ++index) {
   418         props = configProperties(configs[index]);
   421         props = configProperties(configs[index]);
   419         qWarning() << props.toString();
   422         qWarning() << props.toString();
   420     }
   423     }
   421     delete [] configs;
   424     delete [] configs;
   422 }
   425 }
   423 
   426 
   424 QString QEglContext::extensions()
   427 QString QEglContext::extensions()
   425 {
   428 {
   426     const char* exts = eglQueryString(QEglContext::defaultDisplay(0), EGL_EXTENSIONS);
   429     const char* exts = eglQueryString(QEglContext::display(), EGL_EXTENSIONS);
   427     return QString(QLatin1String(exts));
   430     return QString(QLatin1String(exts));
   428 }
   431 }
   429 
   432 
   430 bool QEglContext::hasExtension(const char* extensionName)
   433 bool QEglContext::hasExtension(const char* extensionName)
   431 {
   434 {
   432     QList<QByteArray> extensions =
   435     QList<QByteArray> extensions =
   433         QByteArray(reinterpret_cast<const char *>
   436         QByteArray(reinterpret_cast<const char *>
   434             (eglQueryString(QEglContext::defaultDisplay(0), EGL_EXTENSIONS))).split(' ');
   437             (eglQueryString(QEglContext::display(), EGL_EXTENSIONS))).split(' ');
   435     return extensions.contains(extensionName);
   438     return extensions.contains(extensionName);
   436 }
   439 }
   437 
   440 
   438 QEglContext *QEglContext::currentContext(QEgl::API api)
   441 QEglContext *QEglContext::currentContext(QEgl::API api)
   439 {
   442 {