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>
This commit is contained in:
parent
365b5f7a92
commit
2d39471897
@ -68,6 +68,11 @@ public:
|
|||||||
|
|
||||||
static QThreadStorage<QGuiGLThreadContext *> qwindow_context_storage;
|
static QThreadStorage<QGuiGLThreadContext *> qwindow_context_storage;
|
||||||
|
|
||||||
|
#ifndef QT_NO_DEBUG
|
||||||
|
QHash<QOpenGLContext *, bool> QOpenGLContextPrivate::makeCurrentTracker;
|
||||||
|
QMutex QOpenGLContextPrivate::makeCurrentTrackerMutex;
|
||||||
|
#endif
|
||||||
|
|
||||||
void QOpenGLContextPrivate::setCurrentContext(QOpenGLContext *context)
|
void QOpenGLContextPrivate::setCurrentContext(QOpenGLContext *context)
|
||||||
{
|
{
|
||||||
QGuiGLThreadContext *threadContext = qwindow_context_storage.localData();
|
QGuiGLThreadContext *threadContext = qwindow_context_storage.localData();
|
||||||
@ -204,6 +209,10 @@ void QOpenGLContext::destroy()
|
|||||||
QOpenGLContext::~QOpenGLContext()
|
QOpenGLContext::~QOpenGLContext()
|
||||||
{
|
{
|
||||||
destroy();
|
destroy();
|
||||||
|
|
||||||
|
#ifndef QT_NO_DEBUG
|
||||||
|
QOpenGLContextPrivate::cleanMakeCurrentTracker(this);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -229,6 +238,29 @@ QOpenGLFunctions *QOpenGLContext::functions() const
|
|||||||
return d->functions;
|
return d->functions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
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().
|
If surface is 0 this is equivalent to calling doneCurrent().
|
||||||
|
|
||||||
@ -260,6 +292,10 @@ bool QOpenGLContext::makeCurrent(QSurface *surface)
|
|||||||
|
|
||||||
d->shareGroup->d_func()->deletePendingResources(this);
|
d->shareGroup->d_func()->deletePendingResources(this);
|
||||||
|
|
||||||
|
#ifndef QT_NO_DEBUG
|
||||||
|
QOpenGLContextPrivate::toggleMakeCurrentTracker(this, true);
|
||||||
|
#endif
|
||||||
|
|
||||||
return true;
|
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)
|
void QOpenGLContext::swapBuffers(QSurface *surface)
|
||||||
{
|
{
|
||||||
Q_D(QOpenGLContext);
|
Q_D(QOpenGLContext);
|
||||||
@ -306,8 +353,28 @@ void QOpenGLContext::swapBuffers(QSurface *surface)
|
|||||||
}
|
}
|
||||||
|
|
||||||
QPlatformSurface *surfaceHandle = surface->surfaceHandle();
|
QPlatformSurface *surfaceHandle = surface->surfaceHandle();
|
||||||
if (surfaceHandle)
|
if (!surfaceHandle)
|
||||||
d->platformGLContext->swapBuffers(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)
|
QFunctionPointer QOpenGLContext::getProcAddress(const QByteArray &procName)
|
||||||
|
@ -50,11 +50,17 @@
|
|||||||
|
|
||||||
#include <QtGui/QSurfaceFormat>
|
#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_HEADER
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
|
||||||
class QOpenGLContextPrivate;
|
class QOpenGLContextPrivate;
|
||||||
class QOpenGLContextGroupPrivate;
|
class QOpenGLContextGroupPrivate;
|
||||||
class QOpenGLFunctions;
|
class QOpenGLFunctions;
|
||||||
@ -103,6 +109,8 @@ public:
|
|||||||
QOpenGLContextGroup *shareGroup() const;
|
QOpenGLContextGroup *shareGroup() const;
|
||||||
QScreen *screen() const;
|
QScreen *screen() const;
|
||||||
|
|
||||||
|
GLuint defaultFramebufferObject() const;
|
||||||
|
|
||||||
bool makeCurrent(QSurface *surface);
|
bool makeCurrent(QSurface *surface);
|
||||||
void doneCurrent();
|
void doneCurrent();
|
||||||
|
|
||||||
|
@ -47,6 +47,10 @@
|
|||||||
#include <private/qobject_p.h>
|
#include <private/qobject_p.h>
|
||||||
#include <qmutex.h>
|
#include <qmutex.h>
|
||||||
|
|
||||||
|
#ifndef QT_NO_DEBUG
|
||||||
|
#include <QtCore/QHash>
|
||||||
|
#endif
|
||||||
|
|
||||||
QT_BEGIN_HEADER
|
QT_BEGIN_HEADER
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
@ -185,7 +189,6 @@ public:
|
|||||||
, surface(0)
|
, surface(0)
|
||||||
, functions(0)
|
, functions(0)
|
||||||
, current_fbo(0)
|
, current_fbo(0)
|
||||||
, default_fbo(0)
|
|
||||||
, workaround_brokenFBOReadBack(false)
|
, workaround_brokenFBOReadBack(false)
|
||||||
, workaround_brokenTexSubImage(false)
|
, workaround_brokenTexSubImage(false)
|
||||||
, active_engine(0)
|
, active_engine(0)
|
||||||
@ -210,7 +213,6 @@ public:
|
|||||||
QOpenGLFunctions *functions;
|
QOpenGLFunctions *functions;
|
||||||
|
|
||||||
GLuint current_fbo;
|
GLuint current_fbo;
|
||||||
GLuint default_fbo;
|
|
||||||
|
|
||||||
bool workaround_brokenFBOReadBack;
|
bool workaround_brokenFBOReadBack;
|
||||||
bool workaround_brokenTexSubImage;
|
bool workaround_brokenTexSubImage;
|
||||||
@ -220,6 +222,23 @@ public:
|
|||||||
static void setCurrentContext(QOpenGLContext *context);
|
static void setCurrentContext(QOpenGLContext *context);
|
||||||
|
|
||||||
int maxTextureSize() const { return 1024; }
|
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
|
QT_END_NAMESPACE
|
||||||
|
@ -41,6 +41,8 @@
|
|||||||
|
|
||||||
#include "qplatformopenglcontext_qpa.h"
|
#include "qplatformopenglcontext_qpa.h"
|
||||||
|
|
||||||
|
#include <QOpenGLFunctions>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
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
|
QOpenGLContext *QPlatformOpenGLContext::context() const
|
||||||
{
|
{
|
||||||
Q_D(const QPlatformOpenGLContext);
|
Q_D(const QPlatformOpenGLContext);
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
#include <QtCore/qnamespace.h>
|
#include <QtCore/qnamespace.h>
|
||||||
#include <QtGui/qsurfaceformat.h>
|
#include <QtGui/qsurfaceformat.h>
|
||||||
#include <QtGui/qwindow.h>
|
#include <QtGui/qwindow.h>
|
||||||
|
#include <QtGui/qopengl.h>
|
||||||
|
|
||||||
QT_BEGIN_HEADER
|
QT_BEGIN_HEADER
|
||||||
|
|
||||||
@ -64,6 +65,8 @@ public:
|
|||||||
|
|
||||||
virtual void swapBuffers(QPlatformSurface *surface) = 0;
|
virtual void swapBuffers(QPlatformSurface *surface) = 0;
|
||||||
|
|
||||||
|
virtual GLuint defaultFramebufferObject(QPlatformSurface *surface) const;
|
||||||
|
|
||||||
virtual bool makeCurrent(QPlatformSurface *surface) = 0;
|
virtual bool makeCurrent(QPlatformSurface *surface) = 0;
|
||||||
virtual void doneCurrent() = 0;
|
virtual void doneCurrent() = 0;
|
||||||
|
|
||||||
|
@ -892,8 +892,8 @@ bool QOpenGLFramebufferObject::release()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (current) {
|
if (current) {
|
||||||
current->d_func()->current_fbo = current->d_func()->default_fbo;
|
current->d_func()->current_fbo = current->defaultFramebufferObject();
|
||||||
d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, current->d_func()->default_fbo);
|
d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, current->d_func()->current_fbo);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -1057,8 +1057,8 @@ bool QOpenGLFramebufferObject::bindDefault()
|
|||||||
QOpenGLFunctions functions(ctx);
|
QOpenGLFunctions functions(ctx);
|
||||||
|
|
||||||
if (ctx) {
|
if (ctx) {
|
||||||
ctx->d_func()->current_fbo = ctx->d_func()->default_fbo;
|
ctx->d_func()->current_fbo = ctx->defaultFramebufferObject();
|
||||||
functions.glBindFramebuffer(GL_FRAMEBUFFER, ctx->d_func()->default_fbo);
|
functions.glBindFramebuffer(GL_FRAMEBUFFER, ctx->d_func()->current_fbo);
|
||||||
#ifdef QT_DEBUG
|
#ifdef QT_DEBUG
|
||||||
} else {
|
} else {
|
||||||
qWarning("QOpenGLFramebufferObject::bindDefault() called without current context.");
|
qWarning("QOpenGLFramebufferObject::bindDefault() called without current context.");
|
||||||
|
@ -478,6 +478,9 @@ void QOpenGLFunctions::initializeGLFunctions()
|
|||||||
|
|
||||||
Convenience function that calls glBindFramebuffer(\a target, \a framebuffer).
|
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
|
For more information, see the OpenGL/ES 2.0 documentation for
|
||||||
\l{http://www.khronos.org/opengles/sdk/docs/man/glBindFramebuffer.xml}{glBindFramebuffer()}.
|
\l{http://www.khronos.org/opengles/sdk/docs/man/glBindFramebuffer.xml}{glBindFramebuffer()}.
|
||||||
*/
|
*/
|
||||||
|
@ -478,6 +478,8 @@ inline void QOpenGLFunctions::glBindBuffer(GLenum target, GLuint buffer)
|
|||||||
|
|
||||||
inline void QOpenGLFunctions::glBindFramebuffer(GLenum target, GLuint framebuffer)
|
inline void QOpenGLFunctions::glBindFramebuffer(GLenum target, GLuint framebuffer)
|
||||||
{
|
{
|
||||||
|
if (framebuffer == 0)
|
||||||
|
framebuffer = QOpenGLContext::currentContext()->defaultFramebufferObject();
|
||||||
#if defined(QT_OPENGL_ES_2)
|
#if defined(QT_OPENGL_ES_2)
|
||||||
::glBindFramebuffer(target, framebuffer);
|
::glBindFramebuffer(target, framebuffer);
|
||||||
#else
|
#else
|
||||||
|
@ -395,6 +395,9 @@ void QGLFunctions::initializeGLFunctions(const QGLContext *context)
|
|||||||
|
|
||||||
Convenience function that calls glBindFramebuffer(\a target, \a framebuffer).
|
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
|
For more information, see the OpenGL/ES 2.0 documentation for
|
||||||
\l{http://www.khronos.org/opengles/sdk/docs/man/glBindFramebuffer.xml}{glBindFramebuffer()}.
|
\l{http://www.khronos.org/opengles/sdk/docs/man/glBindFramebuffer.xml}{glBindFramebuffer()}.
|
||||||
*/
|
*/
|
||||||
|
@ -48,6 +48,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <QtOpenGL/qgl.h>
|
#include <QtOpenGL/qgl.h>
|
||||||
|
#include <QtGui/qopenglcontext.h>
|
||||||
|
|
||||||
QT_BEGIN_HEADER
|
QT_BEGIN_HEADER
|
||||||
|
|
||||||
@ -450,6 +451,8 @@ inline void QGLFunctions::glBindBuffer(GLenum target, GLuint buffer)
|
|||||||
|
|
||||||
inline void QGLFunctions::glBindFramebuffer(GLenum target, GLuint framebuffer)
|
inline void QGLFunctions::glBindFramebuffer(GLenum target, GLuint framebuffer)
|
||||||
{
|
{
|
||||||
|
if (framebuffer == 0)
|
||||||
|
framebuffer = QOpenGLContext::currentContext()->defaultFramebufferObject();
|
||||||
#if defined(QT_OPENGL_ES_2)
|
#if defined(QT_OPENGL_ES_2)
|
||||||
::glBindFramebuffer(target, framebuffer);
|
::glBindFramebuffer(target, framebuffer);
|
||||||
#else
|
#else
|
||||||
|
Loading…
x
Reference in New Issue
Block a user