diff options
Diffstat (limited to 'src/opengl/qwindowsurface_gl.cpp')
-rw-r--r-- | src/opengl/qwindowsurface_gl.cpp | 91 |
1 files changed, 68 insertions, 23 deletions
diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp index 3a6ed06..e89352d 100644 --- a/src/opengl/qwindowsurface_gl.cpp +++ b/src/opengl/qwindowsurface_gl.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the QtOpenGL module of the Qt Toolkit. @@ -20,10 +21,9 @@ ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this -** package. +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. @@ -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 { @@ -579,7 +623,8 @@ void QGLWindowSurface::updateGeometry() #ifdef QT_OPENGL_ES_2 && (QGLExtensions::glExtensions & QGLExtensions::FramebufferBlit) #endif - && (d_ptr->fbo || !d_ptr->tried_fbo)) + && (d_ptr->fbo || !d_ptr->tried_fbo) + && qt_gl_preferGL2Engine()) { d_ptr->tried_fbo = true; hijackWindow(window()); |