summaryrefslogtreecommitdiffstats
path: root/src/opengl/qwindowsurface_gl.cpp
diff options
context:
space:
mode:
authorQt Continuous Integration System <qt-info@nokia.com>2010-10-26 01:16:18 (GMT)
committerQt Continuous Integration System <qt-info@nokia.com>2010-10-26 01:16:18 (GMT)
commit9e17ec82f6915a636338c8be693773ec21db3a92 (patch)
tree46bde7e8b2b5b522b4710d895bf38a0d384f37e0 /src/opengl/qwindowsurface_gl.cpp
parentd67a5534cb50f66807b87526d42603c7d4df3595 (diff)
parentef704ebad66559170d761459d42d6c99996db529 (diff)
downloadQt-9e17ec82f6915a636338c8be693773ec21db3a92.zip
Qt-9e17ec82f6915a636338c8be693773ec21db3a92.tar.gz
Qt-9e17ec82f6915a636338c8be693773ec21db3a92.tar.bz2
Merge branch 4.7 into qt-master-from-4.7
Diffstat (limited to 'src/opengl/qwindowsurface_gl.cpp')
-rw-r--r--src/opengl/qwindowsurface_gl.cpp139
1 files changed, 83 insertions, 56 deletions
diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp
index 3067e24..cdd234a 100644
--- a/src/opengl/qwindowsurface_gl.cpp
+++ b/src/opengl/qwindowsurface_gl.cpp
@@ -275,6 +275,8 @@ struct QGLWindowSurfacePrivate
QRegion paintedRegion;
QSize size;
+ QSize textureSize;
+
QList<QImage> buffers;
QGLWindowSurfaceGLPaintDevice glDevice;
QGLWindowSurface* q_ptr;
@@ -316,6 +318,7 @@ QGLWindowSurface::QGLWindowSurface(QWidget *window)
d_ptr->pb = 0;
d_ptr->fbo = 0;
d_ptr->ctx = 0;
+ d_ptr->tex_id = 0;
#if defined (QT_OPENGL_ES_2)
d_ptr->tried_fbo = true;
d_ptr->tried_pb = true;
@@ -433,7 +436,7 @@ static void drawTexture(const QRectF &rect, GLuint tex_id, const QSize &texSize,
void QGLWindowSurface::beginPaint(const QRegion &)
{
- if (! context())
+ if (!context())
return;
int clearFlags = 0;
@@ -457,13 +460,42 @@ void QGLWindowSurface::endPaint(const QRegion &rgn)
d_ptr->buffers.clear();
}
-void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &offset)
+static void blitTexture(QGLContext *ctx, GLuint texture, const QSize &viewport, const QSize &texSize, const QRect &targetRect, const QRect &sourceRect)
{
- if (context() && widget != window()) {
- qWarning("No native child widget support in GL window surface without FBOs or pixel buffers");
- return;
- }
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_SCISSOR_TEST);
+ glDisable(GL_BLEND);
+
+ glViewport(0, 0, viewport.width(), viewport.height());
+
+ QGLShaderProgram *blitProgram =
+ QGLEngineSharedShaders::shadersForContext(ctx)->blitProgram();
+ blitProgram->bind();
+ blitProgram->setUniformValue("imageTexture", 0 /*QT_IMAGE_TEXTURE_UNIT*/);
+
+ // The shader manager's blit program does not multiply the
+ // vertices by the pmv matrix, so we need to do the effect
+ // of the orthographic projection here ourselves.
+ QRectF r;
+ qreal w = viewport.width();
+ qreal h = viewport.height();
+ r.setLeft((targetRect.left() / w) * 2.0f - 1.0f);
+ if (targetRect.right() == (viewport.width() - 1))
+ r.setRight(1.0f);
+ else
+ r.setRight((targetRect.right() / w) * 2.0f - 1.0f);
+ r.setBottom((targetRect.top() / h) * 2.0f - 1.0f);
+ if (targetRect.bottom() == (viewport.height() - 1))
+ r.setTop(1.0f);
+ else
+ r.setTop((targetRect.bottom() / w) * 2.0f - 1.0f);
+
+ drawTexture(r, texture, texSize, sourceRect);
+}
+
+void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &offset)
+{
//### Find out why d_ptr->geometry_updated isn't always false.
// flush() should not be called when d_ptr->geometry_updated is true. It assumes that either
// d_ptr->fbo or d_ptr->pb is allocated and has the correct size.
@@ -534,12 +566,29 @@ void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &
}
}
#endif
- if (hasPartialUpdateSupport() &&
- d_ptr->paintedRegion.boundingRect().width() * d_ptr->paintedRegion.boundingRect().height() <
- geometry().width() * geometry().height() * 0.2) {
- context()->d_func()->swapRegion(&d_ptr->paintedRegion);
- } else
- context()->swapBuffers();
+ bool doingPartialUpdate = hasPartialUpdateSupport() && br.width() * br.height() < parent->geometry().width() * parent->geometry().height() * 0.2;
+ QGLContext *ctx = reinterpret_cast<QGLContext *>(parent->d_func()->extraData()->glContext);
+ if (widget != window()) {
+ if (initializeOffscreenTexture(window()->size()))
+ qWarning() << "QGLWindowSurface: Flushing to native child widget, may lead to significant performance loss";
+ glBindTexture(target, d_ptr->tex_id);
+
+ 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);
+
+ ctx->makeCurrent();
+ if (doingPartialUpdate)
+ blitTexture(ctx, d_ptr->tex_id, parent->size(), window()->size(), rect, br);
+ else
+ blitTexture(ctx, d_ptr->tex_id, parent->size(), window()->size(), parent->rect(), parent->rect().translated(offset + wOffset));
+ }
+
+ if (doingPartialUpdate)
+ ctx->d_func()->swapRegion(br);
+ else
+ ctx->swapBuffers();
d_ptr->paintedRegion = QRegion();
} else {
@@ -665,38 +714,10 @@ void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &
else if (d_ptr->fbo) {
Q_UNUSED(target);
- GLuint texture = d_ptr->fbo->texture();
-
- glDisable(GL_DEPTH_TEST);
-
if (d_ptr->fbo->isBound())
d_ptr->fbo->release();
- glViewport(0, 0, size.width(), size.height());
-
- QGLShaderProgram *blitProgram =
- QGLEngineSharedShaders::shadersForContext(ctx)->blitProgram();
- blitProgram->bind();
- blitProgram->setUniformValue("imageTexture", 0 /*QT_IMAGE_TEXTURE_UNIT*/);
-
- // The shader manager's blit program does not multiply the
- // vertices by the pmv matrix, so we need to do the effect
- // of the orthographic projection here ourselves.
- QRectF r;
- qreal w = size.width() ? size.width() : 1.0f;
- qreal h = size.height() ? size.height() : 1.0f;
- r.setLeft((rect.left() / w) * 2.0f - 1.0f);
- if (rect.right() == (size.width() - 1))
- r.setRight(1.0f);
- else
- r.setRight((rect.right() / w) * 2.0f - 1.0f);
- r.setBottom((rect.top() / h) * 2.0f - 1.0f);
- if (rect.bottom() == (size.height() - 1))
- r.setTop(1.0f);
- else
- r.setTop((rect.bottom() / w) * 2.0f - 1.0f);
-
- drawTexture(r, texture, window()->size(), br);
+ blitTexture(ctx, d_ptr->fbo->texture(), size, window()->size(), rect, br);
}
#endif
@@ -719,7 +740,6 @@ void QGLWindowSurface::updateGeometry() {
return;
d_ptr->geometry_updated = false;
-
QRect rect = geometry();
hijackWindow(window());
QGLContext *ctx = reinterpret_cast<QGLContext *>(window()->d_func()->extraData()->glContext);
@@ -740,11 +760,8 @@ void QGLWindowSurface::updateGeometry() {
if (d_ptr->ctx) {
#ifndef QT_OPENGL_ES_2
- 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);
- }
+ if (d_ptr->destructive_swap_buffers)
+ initializeOffscreenTexture(rect.size());
#endif
return;
}
@@ -824,15 +841,8 @@ void QGLWindowSurface::updateGeometry() {
ctx->makeCurrent();
#ifndef QT_OPENGL_ES_2
- 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);
- }
+ if (d_ptr->destructive_swap_buffers)
+ initializeOffscreenTexture(rect.size());
#endif
qDebug() << "QGLWindowSurface: Using plain widget as window surface" << this;;
@@ -840,6 +850,23 @@ void QGLWindowSurface::updateGeometry() {
d_ptr->ctx->d_ptr->internal_context = true;
}
+bool QGLWindowSurface::initializeOffscreenTexture(const QSize &size)
+{
+ if (size == d_ptr->textureSize)
+ return false;
+
+ glGenTextures(1, &d_ptr->tex_id);
+ glBindTexture(GL_TEXTURE_2D, d_ptr->tex_id);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, size.width(), size.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
+
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ d_ptr->textureSize = size;
+ return true;
+}
+
bool QGLWindowSurface::scroll(const QRegion &area, int dx, int dy)
{
// this code randomly fails currently for unknown reasons