summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamuel Rødal <sroedal@trolltech.com>2009-05-20 10:40:59 (GMT)
committerSamuel Rødal <sroedal@trolltech.com>2009-05-25 08:43:53 (GMT)
commitbd9197b8c344e2f259f5e1c08a746464a04687bb (patch)
treed4ceedbe0e453c2e6c4bc0f0eb3dd4ede2429926
parentfc0b94eb37f5aee0d4921f3c87c87527c5aa8585 (diff)
downloadQt-bd9197b8c344e2f259f5e1c08a746464a04687bb.zip
Qt-bd9197b8c344e2f259f5e1c08a746464a04687bb.tar.gz
Qt-bd9197b8c344e2f259f5e1c08a746464a04687bb.tar.bz2
Introduced preserved swap buffer path in GL window surface.
When a buffer swap leaves the back buffer intact we don't have to use an FBO or PB, but can render directly to the window's back buffer, yielding higher performance and depending less on extensions such as multisample FBOs and FBO blitting. Reviewed-by: Trond
-rw-r--r--src/opengl/qwindowsurface_gl.cpp114
1 files changed, 64 insertions, 50 deletions
diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp
index 6fce3e3..a3422b5 100644
--- a/src/opengl/qwindowsurface_gl.cpp
+++ b/src/opengl/qwindowsurface_gl.cpp
@@ -102,16 +102,18 @@ QGLGraphicsSystem::QGLGraphicsSystem()
int spec[16];
spec[i++] = GLX_RGBA;
spec[i++] = GLX_DOUBLEBUFFER;
-#if 0
- spec[i++] = GLX_DEPTH_SIZE;
- spec[i++] = 8;
- spec[i++] = GLX_STENCIL_SIZE;
- spec[i++] = 8;
- spec[i++] = GLX_SAMPLE_BUFFERS_ARB;
- spec[i++] = 1;
- spec[i++] = GLX_SAMPLES_ARB;
- spec[i++] = 4;
-#endif
+
+ if (!qgetenv("QT_GL_SWAPBUFFER_PRESERVE").isNull()) {
+ spec[i++] = GLX_DEPTH_SIZE;
+ spec[i++] = 8;
+ spec[i++] = GLX_STENCIL_SIZE;
+ spec[i++] = 8;
+ spec[i++] = GLX_SAMPLE_BUFFERS_ARB;
+ spec[i++] = 1;
+ spec[i++] = GLX_SAMPLES_ARB;
+ spec[i++] = 4;
+ }
+
spec[i++] = XNone;
XVisualInfo *vi = glXChooseVisual(X11->display, X11->defaultScreen, spec);
@@ -229,6 +231,7 @@ struct QGLWindowSurfacePrivate
int tried_fbo : 1;
int tried_pb : 1;
+ int destructive_swap_buffers : 1;
QGLContext *ctx;
@@ -252,6 +255,7 @@ QGLWindowSurface::QGLWindowSurface(QWidget *window)
d_ptr->ctx = 0;
d_ptr->tried_fbo = false;
d_ptr->tried_pb = false;
+ d_ptr->destructive_swap_buffers = qgetenv("QT_GL_SWAPBUFFER_PRESERVE").isNull();
}
QGLWindowSurface::~QGLWindowSurface()
@@ -342,6 +346,9 @@ void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &
QWidget *parent = widget->internalWinId() ? widget : widget->nativeParentWidget();
Q_ASSERT(parent);
+ if (!geometry().isValid())
+ return;
+
hijackWindow(parent);
QRect br = rgn.boundingRect().translated(offset);
@@ -356,48 +363,50 @@ void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &
if (context()->format().doubleBuffer()) {
#if !defined(QT_OPENGL_ES_2)
- glBindTexture(target, d_ptr->tex_id);
+ if (d_ptr->destructive_swap_buffers) {
+ glBindTexture(target, d_ptr->tex_id);
- QVector<QRect> rects = d_ptr->paintedRegion.rects();
- for (int i = 0; i < rects.size(); ++i) {
- QRect br = rects.at(i);
- if (br.isEmpty())
- continue;
+ QVector<QRect> rects = d_ptr->paintedRegion.rects();
+ for (int i = 0; i < rects.size(); ++i) {
+ QRect br = rects.at(i);
+ if (br.isEmpty())
+ continue;
- const uint bottom = window()->height() - (br.y() + br.height());
- glCopyTexSubImage2D(target, 0, br.x(), bottom, br.x(), bottom, br.width(), br.height());
- }
+ const uint bottom = window()->height() - (br.y() + br.height());
+ glCopyTexSubImage2D(target, 0, br.x(), bottom, br.x(), bottom, br.width(), br.height());
+ }
- glBindTexture(target, 0);
+ glBindTexture(target, 0);
- QRegion dirtyRegion = QRegion(window()->rect()) - d_ptr->paintedRegion;
+ QRegion dirtyRegion = QRegion(window()->rect()) - d_ptr->paintedRegion;
- if (!dirtyRegion.isEmpty()) {
- context()->makeCurrent();
+ if (!dirtyRegion.isEmpty()) {
+ context()->makeCurrent();
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
#ifndef QT_OPENGL_ES
- glOrtho(0, window()->width(), window()->height(), 0, -999999, 999999);
+ glOrtho(0, window()->width(), window()->height(), 0, -999999, 999999);
#else
- glOrthof(0, window()->width(), window()->height(), 0, -999999, 999999);
+ glOrthof(0, window()->width(), window()->height(), 0, -999999, 999999);
#endif
- glViewport(0, 0, window()->width(), window()->height());
+ glViewport(0, 0, window()->width(), window()->height());
- QVector<QRect> rects = dirtyRegion.rects();
- glColor4f(1, 1, 1, 1);
- for (int i = 0; i < rects.size(); ++i) {
- QRect rect = rects.at(i);
- if (rect.isEmpty())
- continue;
+ QVector<QRect> rects = dirtyRegion.rects();
+ glColor4f(1, 1, 1, 1);
+ for (int i = 0; i < rects.size(); ++i) {
+ QRect rect = rects.at(i);
+ if (rect.isEmpty())
+ continue;
- drawTexture(rect, d_ptr->tex_id, window()->size(), rect);
+ drawTexture(rect, d_ptr->tex_id, window()->size(), rect);
+ }
}
- }
#endif
+ }
d_ptr->paintedRegion = QRegion();
context()->swapBuffers();
@@ -422,7 +431,7 @@ void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &
}
QSize size = widget->rect().size();
- if (ctx->format().doubleBuffer()) {
+ if (d_ptr->destructive_swap_buffers && ctx->format().doubleBuffer()) {
rect = parent->rect();
br = rect.translated(wOffset);
size = parent->size();
@@ -501,13 +510,16 @@ void QGLWindowSurface::updateGeometry()
d_ptr->size = rect.size();
if (d_ptr->ctx) {
- glBindTexture(target, d_ptr->tex_id);
- glTexImage2D(target, 0, GL_RGBA, rect.width(), rect.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
- glBindTexture(target, 0);
+ if (d_ptr->destructive_swap_buffers) {
+ glBindTexture(target, d_ptr->tex_id);
+ glTexImage2D(target, 0, GL_RGBA, rect.width(), rect.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
+ glBindTexture(target, 0);
+ }
return;
}
- if ((QGLExtensions::glExtensions & QGLExtensions::FramebufferObject)
+ if (d_ptr->destructive_swap_buffers
+ && (QGLExtensions::glExtensions & QGLExtensions::FramebufferObject)
#ifdef QT_OPENGL_ES_2
&& (QGLExtensions::glExtensions & QGLExtensions::FramebufferBlit)
#endif
@@ -542,7 +554,7 @@ void QGLWindowSurface::updateGeometry()
}
#if !defined(QT_OPENGL_ES_2)
- if (d_ptr->pb || !d_ptr->tried_pb) {
+ if (d_ptr->destructive_swap_buffers && (d_ptr->pb || !d_ptr->tried_pb)) {
d_ptr->tried_pb = true;
if (d_ptr->pb) {
@@ -590,13 +602,15 @@ void QGLWindowSurface::updateGeometry()
QGLContext *ctx = reinterpret_cast<QGLContext *>(window()->d_func()->extraData()->glContext);
ctx->makeCurrent();
- glGenTextures(1, &d_ptr->tex_id);
- glBindTexture(target, d_ptr->tex_id);
- glTexImage2D(target, 0, GL_RGBA, rect.width(), rect.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
+ if (d_ptr->destructive_swap_buffers) {
+ glGenTextures(1, &d_ptr->tex_id);
+ glBindTexture(target, d_ptr->tex_id);
+ glTexImage2D(target, 0, GL_RGBA, rect.width(), rect.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
- glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glBindTexture(target, 0);
+ glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glBindTexture(target, 0);
+ }
qDebug() << "QGLWindowSurface: Using plain widget as window surface" << this;;
d_ptr->ctx = ctx;