diff options
Diffstat (limited to 'src/gui/egl')
-rw-r--r-- | src/gui/egl/qegl.cpp | 110 | ||||
-rw-r--r-- | src/gui/egl/qegl_p.h | 28 | ||||
-rw-r--r-- | src/gui/egl/qegl_qws.cpp | 4 | ||||
-rw-r--r-- | src/gui/egl/qegl_symbian.cpp | 11 | ||||
-rw-r--r-- | src/gui/egl/qegl_wince.cpp | 8 | ||||
-rw-r--r-- | src/gui/egl/qegl_x11.cpp | 8 |
6 files changed, 94 insertions, 75 deletions
diff --git a/src/gui/egl/qegl.cpp b/src/gui/egl/qegl.cpp index 222524e..840b9d6 100644 --- a/src/gui/egl/qegl.cpp +++ b/src/gui/egl/qegl.cpp @@ -47,21 +47,31 @@ QT_BEGIN_NAMESPACE +// Current GL and VG contexts. These are used to determine if +// we can avoid an eglMakeCurrent() after a call to lazyDoneCurrent(). +// If a background thread modifies the value, the worst that will +// happen is a redundant eglMakeCurrent() in the foreground thread. +static QEglContext * volatile currentGLContext = 0; +static QEglContext * volatile currentVGContext = 0; + QEglContext::QEglContext() : apiType(QEgl::OpenGL) , dpy(EGL_NO_DISPLAY) , ctx(EGL_NO_CONTEXT) - , surf(EGL_NO_SURFACE) , cfg(0) - , share(false) + , currentSurface(EGL_NO_SURFACE) , current(false) - , reserved(0) { } QEglContext::~QEglContext() { destroy(); + + if (currentGLContext == this) + currentGLContext = 0; + if (currentVGContext == this) + currentVGContext = 0; } bool QEglContext::isValid() const @@ -69,11 +79,6 @@ bool QEglContext::isValid() const return (ctx != EGL_NO_CONTEXT); } -bool QEglContext::isSharing() const -{ - return share; -} - bool QEglContext::isCurrent() const { return current; @@ -148,7 +153,7 @@ bool QEglContext::chooseConfig } // Create the EGLContext. -bool QEglContext::createContext(QEglContext *shareContext) +bool QEglContext::createContext(QEglContext *shareContext, const QEglProperties *properties) { // We need to select the correct API before calling eglCreateContext(). #ifdef EGL_OPENGL_ES_API @@ -162,6 +167,8 @@ bool QEglContext::createContext(QEglContext *shareContext) // Create a new context for the configuration. QEglProperties contextProps; + if (properties) + contextProps = *properties; #if defined(QT_OPENGL_ES_2) if (apiType == QEgl::OpenGL) contextProps.setValue(EGL_CONTEXT_CLIENT_VERSION, 2); @@ -182,31 +189,17 @@ bool QEglContext::createContext(QEglContext *shareContext) return false; } } - share = (shareContext != 0); return true; } -// Recreate the surface for a paint device because the native id has changed. -bool QEglContext::recreateSurface(QPaintDevice *device) -{ - // Bail out if the surface has not been created for the first time yet. - if (surf == EGL_NO_SURFACE) - return true; - - // Destroy the old surface. - eglDestroySurface(dpy, surf); - surf = EGL_NO_SURFACE; - - // Create a new one. - return createSurface(device); -} - -// Destroy the EGL surface object. -void QEglContext::destroySurface() +// Destroy an EGL surface object. If it was current on this context +// then call doneCurrent() for it first. +void QEglContext::destroySurface(EGLSurface surface) { - if (surf != EGL_NO_SURFACE) { - eglDestroySurface(dpy, surf); - surf = EGL_NO_SURFACE; + if (surface != EGL_NO_SURFACE) { + if (surface == currentSurface) + doneCurrent(); + eglDestroySurface(dpy, surface); } } @@ -217,21 +210,28 @@ void QEglContext::destroy() eglDestroyContext(dpy, ctx); dpy = EGL_NO_DISPLAY; ctx = EGL_NO_CONTEXT; - surf = EGL_NO_SURFACE; cfg = 0; - share = false; } -bool QEglContext::makeCurrent() +bool QEglContext::makeCurrent(EGLSurface surface) { if (ctx == EGL_NO_CONTEXT) { qWarning() << "QEglContext::makeCurrent(): Cannot make invalid context current"; return false; } + // If lazyDoneCurrent() was called on the surface, then we may be able + // to assume that it is still current within the thread. + if (surface == currentSurface && currentContext(apiType) == this) { + current = true; + return true; + } + current = true; + currentSurface = surface; + setCurrentContext(apiType, this); - bool ok = eglMakeCurrent(dpy, surf, surf, ctx); + bool ok = eglMakeCurrent(dpy, surface, surface, ctx); if (!ok) qWarning() << "QEglContext::makeCurrent():" << errorString(eglGetError()); return ok; @@ -245,6 +245,8 @@ bool QEglContext::doneCurrent() return false; current = false; + currentSurface = EGL_NO_SURFACE; + setCurrentContext(apiType, 0); // We need to select the correct API before calling eglMakeCurrent() // with EGL_NO_CONTEXT because threads can have both OpenGL and OpenVG @@ -264,12 +266,23 @@ bool QEglContext::doneCurrent() return ok; } -bool QEglContext::swapBuffers() +// Act as though doneCurrent() was called, but keep the context +// and the surface active for the moment. This allows makeCurrent() +// to skip a call to eglMakeCurrent() if we are using the same +// surface as the last set of painting operations. We leave the +// currentContext() pointer as-is for now. +bool QEglContext::lazyDoneCurrent() +{ + current = false; + return true; +} + +bool QEglContext::swapBuffers(EGLSurface surface) { if(ctx == EGL_NO_CONTEXT) return false; - bool ok = eglSwapBuffers(dpy, surf); + bool ok = eglSwapBuffers(dpy, surface); if (!ok) qWarning() << "QEglContext::swapBuffers():" << errorString(eglGetError()); return ok; @@ -305,15 +318,6 @@ void QEglContext::waitClient() #endif } -// Query the actual size of the EGL surface. -QSize QEglContext::surfaceSize() const -{ - int w, h; - eglQuerySurface(dpy, surf, EGL_WIDTH, &w); - eglQuerySurface(dpy, surf, EGL_HEIGHT, &h); - return QSize(w, h); -} - // Query the value of a configuration attribute. bool QEglContext::configAttrib(int name, EGLint *value) const { @@ -411,4 +415,20 @@ bool QEglContext::hasExtension(const char* extensionName) return extensions().contains(QLatin1String(extensionName)); } +QEglContext *QEglContext::currentContext(QEgl::API api) +{ + if (api == QEgl::OpenGL) + return currentGLContext; + else + return currentVGContext; +} + +void QEglContext::setCurrentContext(QEgl::API api, QEglContext *context) +{ + if (api == QEgl::OpenGL) + currentGLContext = context; + else + currentVGContext = context; +} + QT_END_NAMESPACE diff --git a/src/gui/egl/qegl_p.h b/src/gui/egl/qegl_p.h index 366bd9e..dc399da 100644 --- a/src/gui/egl/qegl_p.h +++ b/src/gui/egl/qegl_p.h @@ -80,7 +80,6 @@ public: ~QEglContext(); bool isValid() const; - bool isSharing() const; bool isCurrent() const; QEgl::API api() const { return apiType; } @@ -88,22 +87,20 @@ public: bool openDisplay(QPaintDevice *device); bool chooseConfig(const QEglProperties& properties, QEgl::PixelFormatMatch match = QEgl::ExactPixelFormat); - bool createContext(QEglContext *shareContext = 0); - bool createSurface(QPaintDevice *device, const QEglProperties *properties = 0); - bool recreateSurface(QPaintDevice *device); - void destroySurface(); + bool createContext(QEglContext *shareContext = 0, const QEglProperties *properties = 0); + EGLSurface createSurface(QPaintDevice *device, const QEglProperties *properties = 0); + void destroySurface(EGLSurface surface); void destroy(); - bool makeCurrent(); + bool makeCurrent(EGLSurface surface); bool doneCurrent(); - bool swapBuffers(); + bool lazyDoneCurrent(); + bool swapBuffers(EGLSurface surface); void waitNative(); void waitClient(); - QSize surfaceSize() const; - bool configAttrib(int name, EGLint *value) const; static void clearError() { eglGetError(); } @@ -111,10 +108,12 @@ public: static QString errorString(EGLint code); EGLDisplay display() const { return dpy; } + EGLContext context() const { return ctx; } - EGLSurface surface() const { return surf; } - void setSurface(EGLSurface surface) { surf = surface; } + void setContext(EGLContext context) { ctx = context; } + EGLConfig config() const { return cfg; } + void setConfig(EGLConfig config) { cfg = config; } QEglProperties configProperties(EGLConfig cfg = 0) const; @@ -129,13 +128,14 @@ private: QEgl::API apiType; EGLDisplay dpy; EGLContext ctx; - EGLSurface surf; EGLConfig cfg; - bool share; + EGLSurface currentSurface; bool current; - void *reserved; // For extension data in future versions. static EGLDisplay getDisplay(QPaintDevice *device); + + static QEglContext *currentContext(QEgl::API api); + static void setCurrentContext(QEgl::API api, QEglContext *context); }; QT_END_NAMESPACE diff --git a/src/gui/egl/qegl_qws.cpp b/src/gui/egl/qegl_qws.cpp index 2754589..590b666 100644 --- a/src/gui/egl/qegl_qws.cpp +++ b/src/gui/egl/qegl_qws.cpp @@ -57,11 +57,11 @@ QT_BEGIN_NAMESPACE // We don't have QGLScreen to create EGL surfaces for us, // so surface creation needs to be done in QtOpenGL or // QtOpenVG for Qt/Embedded. -bool QEglContext::createSurface(QPaintDevice *device, const QEglProperties *properties) +EGLSurface QEglContext::createSurface(QPaintDevice *device, const QEglProperties *properties) { Q_UNUSED(device); Q_UNUSED(properties); - return false; + return EGL_NO_SURFACE; } EGLDisplay QEglContext::getDisplay(QPaintDevice *device) diff --git a/src/gui/egl/qegl_symbian.cpp b/src/gui/egl/qegl_symbian.cpp index fa0b5cb..2101f0b 100644 --- a/src/gui/egl/qegl_symbian.cpp +++ b/src/gui/egl/qegl_symbian.cpp @@ -48,7 +48,7 @@ QT_BEGIN_NAMESPACE -bool QEglContext::createSurface(QPaintDevice *device, const QEglProperties *properties) +EGLSurface QEglContext::createSurface(QPaintDevice *device, const QEglProperties *properties) { // Create the native drawable for the paint device. int devType = device->devType(); @@ -67,7 +67,7 @@ bool QEglContext::createSurface(QPaintDevice *device, const QEglProperties *prop } if (!ok) { qWarning("QEglContext::createSurface(): Cannot create the native EGL drawable"); - return false; + return EGL_NO_SURFACE; } // Create the EGL surface to draw into, based on the native drawable. @@ -76,15 +76,14 @@ bool QEglContext::createSurface(QPaintDevice *device, const QEglProperties *prop props = properties->properties(); else props = 0; + EGLSurface surf; if (devType == QInternal::Widget) surf = eglCreateWindowSurface(dpy, cfg, windowDrawable, 0); else surf = eglCreatePixmapSurface(dpy, cfg, pixmapDrawable, 0); - if (surf == EGL_NO_SURFACE) { + if (surf == EGL_NO_SURFACE) qWarning("QEglContext::createSurface(): Unable to create EGL surface, error = 0x%x", eglGetError()); - return false; - } - return true; + return surf; } EGLDisplay QEglContext::getDisplay(QPaintDevice *device) diff --git a/src/gui/egl/qegl_wince.cpp b/src/gui/egl/qegl_wince.cpp index e07d748..bf07f85 100644 --- a/src/gui/egl/qegl_wince.cpp +++ b/src/gui/egl/qegl_wince.cpp @@ -49,7 +49,7 @@ QT_BEGIN_NAMESPACE -bool QEglContext::createSurface(QPaintDevice *device, const QEglProperties *properties) +EGLSurface QEglContext::createSurface(QPaintDevice *device, const QEglProperties *properties) { // Create the native drawable for the paint device. int devType = device->devType(); @@ -67,7 +67,7 @@ bool QEglContext::createSurface(QPaintDevice *device, const QEglProperties *prop } if (!ok) { qWarning("QEglContext::createSurface(): Cannot create the native EGL drawable"); - return false; + return EGL_NO_SURFACE; } // Create the EGL surface to draw into, based on the native drawable. @@ -76,15 +76,15 @@ bool QEglContext::createSurface(QPaintDevice *device, const QEglProperties *prop props = properties->properties(); else props = 0; + EGLSurface surf; if (devType == QInternal::Widget) surf = eglCreateWindowSurface(dpy, cfg, windowDrawable, props); else surf = eglCreatePixmapSurface(dpy, cfg, pixmapDrawable, props); if (surf == EGL_NO_SURFACE) { qWarning("QEglContext::createSurface(): Unable to create EGL surface, error = 0x%x", eglGetError()); - return false; } - return true; + return surf; } EGLDisplay QEglContext::getDisplay(QPaintDevice *device) diff --git a/src/gui/egl/qegl_x11.cpp b/src/gui/egl/qegl_x11.cpp index 5f34f8e..9d556a8 100644 --- a/src/gui/egl/qegl_x11.cpp +++ b/src/gui/egl/qegl_x11.cpp @@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE -bool QEglContext::createSurface(QPaintDevice *device, const QEglProperties *properties) +EGLSurface QEglContext::createSurface(QPaintDevice *device, const QEglProperties *properties) { // Create the native drawable for the paint device. int devType = device->devType(); @@ -72,7 +72,7 @@ bool QEglContext::createSurface(QPaintDevice *device, const QEglProperties *prop } if (!ok) { qWarning("QEglContext::createSurface(): Cannot create the native EGL drawable"); - return false; + return EGL_NO_SURFACE; } // Create the EGL surface to draw into, based on the native drawable. @@ -81,6 +81,7 @@ bool QEglContext::createSurface(QPaintDevice *device, const QEglProperties *prop props = properties->properties(); else props = 0; + EGLSurface surf; if (devType == QInternal::Widget) surf = eglCreateWindowSurface(dpy, cfg, windowDrawable, props); else @@ -88,9 +89,8 @@ bool QEglContext::createSurface(QPaintDevice *device, const QEglProperties *prop if (surf == EGL_NO_SURFACE) { qWarning() << "QEglContext::createSurface(): Unable to create EGL surface:" << errorString(eglGetError()); - return false; } - return true; + return surf; } EGLDisplay QEglContext::getDisplay(QPaintDevice *device) |