diff options
author | Rhys Weatherley <rhys.weatherley@nokia.com> | 2009-09-24 21:44:10 (GMT) |
---|---|---|
committer | Rhys Weatherley <rhys.weatherley@nokia.com> | 2009-09-24 21:44:10 (GMT) |
commit | f6dee67827e72a0660f37998dafb18c6ccd9834e (patch) | |
tree | 0966b303e93d1c66ece0e33014a0a99c086f6d84 /src/gui/egl | |
parent | eff806304094a46737846fc1bdac62e085e12404 (diff) | |
download | Qt-f6dee67827e72a0660f37998dafb18c6ccd9834e.zip Qt-f6dee67827e72a0660f37998dafb18c6ccd9834e.tar.gz Qt-f6dee67827e72a0660f37998dafb18c6ccd9834e.tar.bz2 |
Push the "lazy doneCurrent" logic down from QtOpenVG into QEgl
QtOpenVG was doing a lot of housekeeping to avoid having to
switch EGL contexts if the same surface was used over and over.
This housekeeping really belongs in the QEgl layer so that
QtOpenGL could potentially use it as well.
This change also adds some overrides for makeCurrent(),
swapBuffers(), and destroySurface() that take an EGLSurface
directly. This is the first step in separating EGL surface
management from context management.
Reviewed-by: Sarah Smith
Diffstat (limited to 'src/gui/egl')
-rw-r--r-- | src/gui/egl/qegl.cpp | 83 | ||||
-rw-r--r-- | src/gui/egl/qegl_p.h | 9 |
2 files changed, 89 insertions, 3 deletions
diff --git a/src/gui/egl/qegl.cpp b/src/gui/egl/qegl.cpp index 222524e..a405bbb 100644 --- a/src/gui/egl/qegl.cpp +++ b/src/gui/egl/qegl.cpp @@ -47,21 +47,33 @@ 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) + , currentSurface(EGL_NO_SURFACE) , share(false) , current(false) - , reserved(0) { } QEglContext::~QEglContext() { destroy(); + + if (currentGLContext == this) + currentGLContext = 0; + if (currentVGContext == this) + currentVGContext = 0; } bool QEglContext::isValid() const @@ -210,6 +222,19 @@ 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 (surface != EGL_NO_SURFACE) { + if (surface == currentSurface) + doneCurrent(); + eglDestroySurface(dpy, surface); + if (surf == surface) + surf = EGL_NO_SURFACE; + } +} + // Destroy the context. Note: this does not destroy the surface. void QEglContext::destroy() { @@ -224,14 +249,28 @@ void QEglContext::destroy() bool QEglContext::makeCurrent() { + return makeCurrent(surf); +} + +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 +284,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,6 +305,17 @@ bool QEglContext::doneCurrent() return ok; } +// 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() { if(ctx == EGL_NO_CONTEXT) @@ -275,6 +327,17 @@ bool QEglContext::swapBuffers() return ok; } +bool QEglContext::swapBuffers(EGLSurface surface) +{ + if(ctx == EGL_NO_CONTEXT) + return false; + + bool ok = eglSwapBuffers(dpy, surface); + if (!ok) + qWarning() << "QEglContext::swapBuffers():" << errorString(eglGetError()); + return ok; +} + // Wait for native rendering operations to complete before starting // to use OpenGL/OpenVG operations. void QEglContext::waitNative() @@ -411,4 +474,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..3903cd0 100644 --- a/src/gui/egl/qegl_p.h +++ b/src/gui/egl/qegl_p.h @@ -92,12 +92,16 @@ public: bool createSurface(QPaintDevice *device, const QEglProperties *properties = 0); bool recreateSurface(QPaintDevice *device); void destroySurface(); + void destroySurface(EGLSurface surface); void destroy(); bool makeCurrent(); + bool makeCurrent(EGLSurface surface); bool doneCurrent(); + bool lazyDoneCurrent(); bool swapBuffers(); + bool swapBuffers(EGLSurface surface); void waitNative(); void waitClient(); @@ -131,11 +135,14 @@ private: EGLContext ctx; EGLSurface surf; EGLConfig cfg; + EGLSurface currentSurface; bool share; 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 |