summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSamuel Rødal <samuel.rodal@nokia.com>2012-01-26 11:44:05 +0100
committerQt by Nokia <qt-info@nokia.com>2012-01-27 10:58:32 +0100
commit2d39471897f0a3a769406ec9c2b39558ebd45af3 (patch)
tree8c417f4ba814e9dbe70e56bdbf8a13cc46b3827f /src
parent365b5f7a9271e5fc503b10e6c17371d76643fc94 (diff)
Introduced QOpenGLContext::defaultFramebufferObject().
Also add some debugging helpers to make sure applications are correctly written even on less restrictive platforms. Change-Id: Ie92e497c32e07b2b83662f7ab5540d8f37777fd0 Reviewed-by: Jørgen Lind <jorgen.lind@nokia.com>
Diffstat (limited to 'src')
-rw-r--r--src/gui/kernel/qopenglcontext.cpp71
-rw-r--r--src/gui/kernel/qopenglcontext.h10
-rw-r--r--src/gui/kernel/qopenglcontext_p.h23
-rw-r--r--src/gui/kernel/qplatformopenglcontext_qpa.cpp12
-rw-r--r--src/gui/kernel/qplatformopenglcontext_qpa.h3
-rw-r--r--src/gui/opengl/qopenglframebufferobject.cpp8
-rw-r--r--src/gui/opengl/qopenglfunctions.cpp3
-rw-r--r--src/gui/opengl/qopenglfunctions.h2
-rw-r--r--src/opengl/qglfunctions.cpp3
-rw-r--r--src/opengl/qglfunctions.h3
10 files changed, 129 insertions, 9 deletions
diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp
index 29107d4261..cd4e8ebc01 100644
--- a/src/gui/kernel/qopenglcontext.cpp
+++ b/src/gui/kernel/qopenglcontext.cpp
@@ -68,6 +68,11 @@ public:
static QThreadStorage<QGuiGLThreadContext *> qwindow_context_storage;
+#ifndef QT_NO_DEBUG
+QHash<QOpenGLContext *, bool> QOpenGLContextPrivate::makeCurrentTracker;
+QMutex QOpenGLContextPrivate::makeCurrentTrackerMutex;
+#endif
+
void QOpenGLContextPrivate::setCurrentContext(QOpenGLContext *context)
{
QGuiGLThreadContext *threadContext = qwindow_context_storage.localData();
@@ -204,6 +209,10 @@ void QOpenGLContext::destroy()
QOpenGLContext::~QOpenGLContext()
{
destroy();
+
+#ifndef QT_NO_DEBUG
+ QOpenGLContextPrivate::cleanMakeCurrentTracker(this);
+#endif
}
/*!
@@ -230,6 +239,29 @@ QOpenGLFunctions *QOpenGLContext::functions() const
}
/*!
+ Call this to get the default framebuffer object for the current surface.
+
+ On some platforms the default framebuffer object depends on the surface being rendered to,
+ and might be different from 0. Thus, instead of calling glBindFramebuffer(0), you should
+ call glBindFramebuffer(ctx->defaultFramebufferObject()) if you want your application to
+ work across different Qt platforms.
+
+ If you use the glBindFramebuffer() in QOpenGLFunctions you do not have to worry about this,
+ as it automatically binds the current context's defaultFramebufferObject() when 0 is passed.
+*/
+GLuint QOpenGLContext::defaultFramebufferObject() const
+{
+ if (!isValid())
+ return 0;
+
+ Q_D(const QOpenGLContext);
+ if (!d->surface || !d->surface->surfaceHandle())
+ return 0;
+
+ return d->platformGLContext->defaultFramebufferObject(d->surface->surfaceHandle());
+}
+
+/*!
If surface is 0 this is equivalent to calling doneCurrent().
Do not call this function from a different thread than the one the QOpenGLContext instance lives in. If
@@ -260,6 +292,10 @@ bool QOpenGLContext::makeCurrent(QSurface *surface)
d->shareGroup->d_func()->deletePendingResources(this);
+#ifndef QT_NO_DEBUG
+ QOpenGLContextPrivate::toggleMakeCurrentTracker(this, true);
+#endif
+
return true;
}
@@ -294,6 +330,17 @@ QSurface *QOpenGLContext::surface() const
}
+/*!
+ Swap the back and front buffers of the given surface.
+
+ Call this to finish a frame of OpenGL rendering, and make sure to
+ call makeCurrent() again before you begin a new frame.
+
+ If you have bound a non-default framebuffer object, you need to
+ use bindDefaultFramebufferObject() to make sure that the default
+ framebuffer object is bound before calling swapBuffers(), as
+ some Qt platforms assume that the default framebuffer object is bound.
+*/
void QOpenGLContext::swapBuffers(QSurface *surface)
{
Q_D(QOpenGLContext);
@@ -306,8 +353,28 @@ void QOpenGLContext::swapBuffers(QSurface *surface)
}
QPlatformSurface *surfaceHandle = surface->surfaceHandle();
- if (surfaceHandle)
- d->platformGLContext->swapBuffers(surfaceHandle);
+ if (!surfaceHandle)
+ return;
+
+#if !defined(QT_NO_DEBUG)
+ if (currentContext() != this)
+ qWarning() << "QOpenGLContext::swapBuffers() called with non-current surface";
+ else if (!QOpenGLContextPrivate::toggleMakeCurrentTracker(this, false))
+ qWarning() << "QOpenGLContext::swapBuffers() called without corresponding makeCurrent()";
+
+#ifndef GL_FRAMEBUFFER_BINDING
+#define GL_FRAMEBUFFER_BINDING 0x8CA6
+#endif
+
+ GLint framebufferBinding = 0;
+ glGetIntegerv(GL_FRAMEBUFFER_BINDING, &framebufferBinding);
+
+ GLint platformFramebuffer = GLint(d->platformGLContext->defaultFramebufferObject(surfaceHandle));
+ if (framebufferBinding != platformFramebuffer)
+ qWarning() << "QOpenGLContext::swapBuffers() called with non-default framebuffer object bound";
+#endif
+
+ d->platformGLContext->swapBuffers(surfaceHandle);
}
QFunctionPointer QOpenGLContext::getProcAddress(const QByteArray &procName)
diff --git a/src/gui/kernel/qopenglcontext.h b/src/gui/kernel/qopenglcontext.h
index 2d86a6db31..449c75f22a 100644
--- a/src/gui/kernel/qopenglcontext.h
+++ b/src/gui/kernel/qopenglcontext.h
@@ -50,11 +50,17 @@
#include <QtGui/QSurfaceFormat>
+#ifdef __GLEW_H__
+#warning qopenglfunctions.h is not compatible with GLEW, GLEW defines will be undefined
+#warning To use GLEW with Qt, do not include <qopengl.h> or <QOpenGLFunctions> after glew.h
+#endif
+
+#include <QtGui/qopengl.h>
+
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
-
class QOpenGLContextPrivate;
class QOpenGLContextGroupPrivate;
class QOpenGLFunctions;
@@ -103,6 +109,8 @@ public:
QOpenGLContextGroup *shareGroup() const;
QScreen *screen() const;
+ GLuint defaultFramebufferObject() const;
+
bool makeCurrent(QSurface *surface);
void doneCurrent();
diff --git a/src/gui/kernel/qopenglcontext_p.h b/src/gui/kernel/qopenglcontext_p.h
index bd5fae989b..819f86fb24 100644
--- a/src/gui/kernel/qopenglcontext_p.h
+++ b/src/gui/kernel/qopenglcontext_p.h
@@ -47,6 +47,10 @@
#include <private/qobject_p.h>
#include <qmutex.h>
+#ifndef QT_NO_DEBUG
+#include <QtCore/QHash>
+#endif
+
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
@@ -185,7 +189,6 @@ public:
, surface(0)
, functions(0)
, current_fbo(0)
- , default_fbo(0)
, workaround_brokenFBOReadBack(false)
, workaround_brokenTexSubImage(false)
, active_engine(0)
@@ -210,7 +213,6 @@ public:
QOpenGLFunctions *functions;
GLuint current_fbo;
- GLuint default_fbo;
bool workaround_brokenFBOReadBack;
bool workaround_brokenTexSubImage;
@@ -220,6 +222,23 @@ public:
static void setCurrentContext(QOpenGLContext *context);
int maxTextureSize() const { return 1024; }
+
+#if !defined(QT_NO_DEBUG)
+ static bool toggleMakeCurrentTracker(QOpenGLContext *context, bool value)
+ {
+ QMutexLocker locker(&makeCurrentTrackerMutex);
+ bool old = makeCurrentTracker.value(context, false);
+ makeCurrentTracker.insert(context, value);
+ return old;
+ }
+ static void cleanMakeCurrentTracker(QOpenGLContext *context)
+ {
+ QMutexLocker locker(&makeCurrentTrackerMutex);
+ makeCurrentTracker.remove(context);
+ }
+ static QHash<QOpenGLContext *, bool> makeCurrentTracker;
+ static QMutex makeCurrentTrackerMutex;
+#endif
};
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatformopenglcontext_qpa.cpp b/src/gui/kernel/qplatformopenglcontext_qpa.cpp
index ba7a75a6b8..244556b13b 100644
--- a/src/gui/kernel/qplatformopenglcontext_qpa.cpp
+++ b/src/gui/kernel/qplatformopenglcontext_qpa.cpp
@@ -41,6 +41,8 @@
#include "qplatformopenglcontext_qpa.h"
+#include <QOpenGLFunctions>
+
QT_BEGIN_NAMESPACE
/*!
@@ -94,6 +96,16 @@ QPlatformOpenGLContext::~QPlatformOpenGLContext()
{
}
+/*!
+ Reimplement in subclass if your platform uses framebuffer objects for surfaces.
+
+ The default implementation returns 0.
+*/
+GLuint QPlatformOpenGLContext::defaultFramebufferObject(QPlatformSurface *) const
+{
+ return 0;
+}
+
QOpenGLContext *QPlatformOpenGLContext::context() const
{
Q_D(const QPlatformOpenGLContext);
diff --git a/src/gui/kernel/qplatformopenglcontext_qpa.h b/src/gui/kernel/qplatformopenglcontext_qpa.h
index 772fbdf06f..5a838a0909 100644
--- a/src/gui/kernel/qplatformopenglcontext_qpa.h
+++ b/src/gui/kernel/qplatformopenglcontext_qpa.h
@@ -45,6 +45,7 @@
#include <QtCore/qnamespace.h>
#include <QtGui/qsurfaceformat.h>
#include <QtGui/qwindow.h>
+#include <QtGui/qopengl.h>
QT_BEGIN_HEADER
@@ -64,6 +65,8 @@ public:
virtual void swapBuffers(QPlatformSurface *surface) = 0;
+ virtual GLuint defaultFramebufferObject(QPlatformSurface *surface) const;
+
virtual bool makeCurrent(QPlatformSurface *surface) = 0;
virtual void doneCurrent() = 0;
diff --git a/src/gui/opengl/qopenglframebufferobject.cpp b/src/gui/opengl/qopenglframebufferobject.cpp
index bb723b7ce6..6cfb3c1b01 100644
--- a/src/gui/opengl/qopenglframebufferobject.cpp
+++ b/src/gui/opengl/qopenglframebufferobject.cpp
@@ -892,8 +892,8 @@ bool QOpenGLFramebufferObject::release()
#endif
if (current) {
- current->d_func()->current_fbo = current->d_func()->default_fbo;
- d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, current->d_func()->default_fbo);
+ current->d_func()->current_fbo = current->defaultFramebufferObject();
+ d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, current->d_func()->current_fbo);
}
return true;
@@ -1057,8 +1057,8 @@ bool QOpenGLFramebufferObject::bindDefault()
QOpenGLFunctions functions(ctx);
if (ctx) {
- ctx->d_func()->current_fbo = ctx->d_func()->default_fbo;
- functions.glBindFramebuffer(GL_FRAMEBUFFER, ctx->d_func()->default_fbo);
+ ctx->d_func()->current_fbo = ctx->defaultFramebufferObject();
+ functions.glBindFramebuffer(GL_FRAMEBUFFER, ctx->d_func()->current_fbo);
#ifdef QT_DEBUG
} else {
qWarning("QOpenGLFramebufferObject::bindDefault() called without current context.");
diff --git a/src/gui/opengl/qopenglfunctions.cpp b/src/gui/opengl/qopenglfunctions.cpp
index b2a329067b..50f70d7408 100644
--- a/src/gui/opengl/qopenglfunctions.cpp
+++ b/src/gui/opengl/qopenglfunctions.cpp
@@ -478,6 +478,9 @@ void QOpenGLFunctions::initializeGLFunctions()
Convenience function that calls glBindFramebuffer(\a target, \a framebuffer).
+ Note that Qt will translate a \a framebuffer argument of 0 to the currently
+ bound QOpenGLContext's defaultFramebufferObject().
+
For more information, see the OpenGL/ES 2.0 documentation for
\l{http://www.khronos.org/opengles/sdk/docs/man/glBindFramebuffer.xml}{glBindFramebuffer()}.
*/
diff --git a/src/gui/opengl/qopenglfunctions.h b/src/gui/opengl/qopenglfunctions.h
index 99b35a3a93..d197ccac91 100644
--- a/src/gui/opengl/qopenglfunctions.h
+++ b/src/gui/opengl/qopenglfunctions.h
@@ -478,6 +478,8 @@ inline void QOpenGLFunctions::glBindBuffer(GLenum target, GLuint buffer)
inline void QOpenGLFunctions::glBindFramebuffer(GLenum target, GLuint framebuffer)
{
+ if (framebuffer == 0)
+ framebuffer = QOpenGLContext::currentContext()->defaultFramebufferObject();
#if defined(QT_OPENGL_ES_2)
::glBindFramebuffer(target, framebuffer);
#else
diff --git a/src/opengl/qglfunctions.cpp b/src/opengl/qglfunctions.cpp
index 2a11ee6a28..6e640b0fe7 100644
--- a/src/opengl/qglfunctions.cpp
+++ b/src/opengl/qglfunctions.cpp
@@ -395,6 +395,9 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context)
Convenience function that calls glBindFramebuffer(\a target, \a framebuffer).
+ Note that Qt will translate a \a framebuffer argument of 0 to the currently
+ bound QOpenGLContext's defaultFramebufferObject().
+
For more information, see the OpenGL/ES 2.0 documentation for
\l{http://www.khronos.org/opengles/sdk/docs/man/glBindFramebuffer.xml}{glBindFramebuffer()}.
*/
diff --git a/src/opengl/qglfunctions.h b/src/opengl/qglfunctions.h
index af6c583a10..40c00f1af8 100644
--- a/src/opengl/qglfunctions.h
+++ b/src/opengl/qglfunctions.h
@@ -48,6 +48,7 @@
#endif
#include <QtOpenGL/qgl.h>
+#include <QtGui/qopenglcontext.h>
QT_BEGIN_HEADER
@@ -450,6 +451,8 @@ inline void QGLFunctions::glBindBuffer(GLenum target, GLuint buffer)
inline void QGLFunctions::glBindFramebuffer(GLenum target, GLuint framebuffer)
{
+ if (framebuffer == 0)
+ framebuffer = QOpenGLContext::currentContext()->defaultFramebufferObject();
#if defined(QT_OPENGL_ES_2)
::glBindFramebuffer(target, framebuffer);
#else