summaryrefslogtreecommitdiffstats
path: root/src/gui/egl
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/egl')
-rw-r--r--src/gui/egl/qegl.cpp110
-rw-r--r--src/gui/egl/qegl_p.h28
-rw-r--r--src/gui/egl/qegl_qws.cpp4
-rw-r--r--src/gui/egl/qegl_symbian.cpp11
-rw-r--r--src/gui/egl/qegl_wince.cpp8
-rw-r--r--src/gui/egl/qegl_x11.cpp8
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)