diff options
author | Samuel Rødal <sroedal@trolltech.com> | 2009-09-11 14:09:47 (GMT) |
---|---|---|
committer | Samuel Rødal <sroedal@trolltech.com> | 2009-09-11 14:42:56 (GMT) |
commit | 3fed939e82e4946546775602f4898c363871c3f2 (patch) | |
tree | 7ae06261c354289783747704fc5e4129837c31c2 /src/opengl | |
parent | 33d1c616d8d4085ba6fa848bafaec66576eba224 (diff) | |
download | Qt-3fed939e82e4946546775602f4898c363871c3f2.zip Qt-3fed939e82e4946546775602f4898c363871c3f2.tar.gz Qt-3fed939e82e4946546775602f4898c363871c3f2.tar.bz2 |
Made GL window surface work better with native child widgets.
Need to unbind the window surface FBO and re-bind it in the child
widget's context before doing a blit.
Reviewed-by: Kim
Diffstat (limited to 'src/opengl')
-rw-r--r-- | src/opengl/qglframebufferobject.cpp | 2 | ||||
-rw-r--r-- | src/opengl/qwindowsurface_gl.cpp | 80 |
2 files changed, 64 insertions, 18 deletions
diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp index f15aa01..81f2aa9 100644 --- a/src/opengl/qglframebufferobject.cpp +++ b/src/opengl/qglframebufferobject.cpp @@ -854,6 +854,7 @@ bool QGLFramebufferObject::bind() d->valid = d->checkFramebufferStatus(); const QGLContext *context = QGLContext::currentContext(); if (d->valid && context) { + Q_ASSERT(QGLContextPrivate::contextGroup(context) == ctx); // Save the previous setting to automatically restore in release(). if (context->d_ptr->current_fbo != d->fbo) { d->previous_fbo = context->d_ptr->current_fbo; @@ -885,6 +886,7 @@ bool QGLFramebufferObject::release() const QGLContext *context = QGLContext::currentContext(); if (context) { + Q_ASSERT(QGLContextPrivate::contextGroup(context) == ctx); // Restore the previous setting for stacked framebuffer objects. if (d->previous_fbo != context->d_ptr->current_fbo) { context->d_ptr->current_fbo = d->previous_fbo; diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp index c2f05cc..e89352d 100644 --- a/src/opengl/qwindowsurface_gl.cpp +++ b/src/opengl/qwindowsurface_gl.cpp @@ -71,6 +71,7 @@ #include <private/qgraphicssystem_gl_p.h> #include <private/qpaintengineex_opengl2_p.h> +#include <private/qpixmapdata_gl_p.h> #ifndef QT_OPENGL_ES_2 #include <private/qpaintengine_opengl_p.h> @@ -399,6 +400,11 @@ void QGLWindowSurface::endPaint(const QRegion &rgn) void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &offset) { + if (context() && widget != window()) { + qWarning("No native child widget support in GL window surface without FBOs or pixel buffers"); + return; + } + QWidget *parent = widget->internalWinId() ? widget : widget->nativeParentWidget(); Q_ASSERT(parent); @@ -473,7 +479,22 @@ void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint & return; } + QGLContext *previous_ctx = const_cast<QGLContext *>(QGLContext::currentContext()); QGLContext *ctx = reinterpret_cast<QGLContext *>(parent->d_func()->extraData()->glContext); + + if (ctx != previous_ctx) { + if (d_ptr->fbo && d_ptr->fbo->isBound()) + d_ptr->fbo->release(); + ctx->makeCurrent(); + } + + QSize size = widget->rect().size(); + if (d_ptr->destructive_swap_buffers && ctx->format().doubleBuffer()) { + rect = parent->rect(); + br = rect.translated(wOffset + offset); + size = parent->size(); + } + GLuint texture; if (d_ptr->fbo) { texture = d_ptr->fbo->texture(); @@ -486,31 +507,54 @@ void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint & glBindTexture(target, 0); } - QSize size = widget->rect().size(); - if (d_ptr->destructive_swap_buffers && ctx->format().doubleBuffer()) { - rect = parent->rect(); - br = rect.translated(wOffset); - size = parent->size(); - } - glDisable(GL_SCISSOR_TEST); - if (d_ptr->fbo && QGLExtensions::glExtensions & QGLExtensions::FramebufferBlit) { + if (d_ptr->fbo && (QGLExtensions::glExtensions & QGLExtensions::FramebufferBlit)) { const int h = d_ptr->fbo->height(); - const int x0 = rect.left(); - const int x1 = rect.left() + rect.width(); - const int y0 = h - (rect.top() + rect.height()); - const int y1 = h - rect.top(); + const int sx0 = br.left(); + const int sx1 = br.left() + br.width(); + const int sy0 = h - (br.top() + br.height()); + const int sy1 = h - br.top(); + + const int tx0 = rect.left(); + const int tx1 = rect.left() + rect.width(); + const int ty0 = parent->height() - (rect.top() + rect.height()); + const int ty1 = parent->height() - rect.top(); + + if (window() == parent || d_ptr->fbo->format().samples() <= 1) { + glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, 0); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, 0); + glBlitFramebufferEXT(sx0, sy0, sx1, sy1, + tx0, ty0, tx1, ty1, + GL_COLOR_BUFFER_BIT, + GL_NEAREST); - glBlitFramebufferEXT(x0, y0, x1, y1, - x0, y0, x1, y1, - GL_COLOR_BUFFER_BIT, - GL_NEAREST); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, d_ptr->fbo->handle()); + } else { + // can't do sub-region blits with multisample FBOs + QGLFramebufferObject *temp = qgl_fbo_pool()->acquire(d_ptr->fbo->size(), QGLFramebufferObjectFormat()); + + glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, temp->handle()); + glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, d_ptr->fbo->handle()); + + glBlitFramebufferEXT(0, 0, d_ptr->fbo->width(), d_ptr->fbo->height(), + 0, 0, d_ptr->fbo->width(), d_ptr->fbo->height(), + GL_COLOR_BUFFER_BIT, + GL_NEAREST); + + glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, temp->handle()); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, 0); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, d_ptr->fbo->handle()); + glBlitFramebufferEXT(sx0, sy0, sx1, sy1, + tx0, ty0, tx1, ty1, + GL_COLOR_BUFFER_BIT, + GL_NEAREST); + + glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, 0); + + qgl_fbo_pool()->release(temp); + } } #if !defined(QT_OPENGL_ES_2) else { |