From 6b7f0bb52f10a03758b5625bd7112d214627812a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Thu, 9 Sep 2010 17:12:57 +0200 Subject: Some optimizations to the GL pixmap data. - Don't use toImage() / fromImage() to copy when a render FBO is active. - Use raster for rendering to small (< 32x32) pixmaps. Reviewed-by: Trond --- .../gl2paintengineex/qpaintengineex_opengl2.cpp | 6 ++++ .../gl2paintengineex/qpaintengineex_opengl2_p.h | 2 ++ src/opengl/qpixmapdata_gl.cpp | 40 +++++++++++++++++++--- src/opengl/qpixmapdata_gl_p.h | 2 +- 4 files changed, 44 insertions(+), 6 deletions(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 18192e3..aa217f6 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -591,6 +591,12 @@ void QGL2PaintEngineEx::endNativePainting() d->nativePaintingActive = false; } +void QGL2PaintEngineEx::invalidateState() +{ + Q_D(QGL2PaintEngineEx); + d->needsSync = true; +} + bool QGL2PaintEngineEx::isNativePaintingActive() const { Q_D(const QGL2PaintEngineEx); return d->nativePaintingActive; diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index 59b90d8..b255e75 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -151,6 +151,8 @@ public: void beginNativePainting(); void endNativePainting(); + void invalidateState(); + QPixmapFilter *pixmapFilter(int type, const QPixmapFilter *prototype); void setRenderTextActive(bool); diff --git a/src/opengl/qpixmapdata_gl.cpp b/src/opengl/qpixmapdata_gl.cpp index 1efd398..89000bb 100644 --- a/src/opengl/qpixmapdata_gl.cpp +++ b/src/opengl/qpixmapdata_gl.cpp @@ -472,13 +472,42 @@ bool QGLPixmapData::scroll(int dx, int dy, const QRect &rect) void QGLPixmapData::copy(const QPixmapData *data, const QRect &rect) { - if (data->classId() != QPixmapData::OpenGLClass) { + if (data->classId() != QPixmapData::OpenGLClass || !static_cast(data)->useFramebufferObjects()) { QPixmapData::copy(data, rect); return; } - // can be optimized to do a framebuffer blit or similar ... - QPixmapData::copy(data, rect); + const QGLPixmapData *other = static_cast(data); + if (other->m_renderFbo) { + QGLShareContextScope ctx(qt_gl_share_widget()->context()); + + resize(rect.width(), rect.height()); + m_hasAlpha = other->m_hasAlpha; + ensureCreated(); + + if (!ctx->d_ptr->fbo) + glGenFramebuffers(1, &ctx->d_ptr->fbo); + + glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, ctx->d_ptr->fbo); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, + GL_TEXTURE_2D, m_texture.id, 0); + + if (!other->m_renderFbo->isBound()) + glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, other->m_renderFbo->handle()); + + glDisable(GL_SCISSOR_TEST); + if (ctx->d_ptr->active_engine && ctx->d_ptr->active_engine->type() == QPaintEngine::OpenGL2) + static_cast(ctx->d_ptr->active_engine)->invalidateState(); + + glBlitFramebufferEXT(rect.x(), rect.y(), rect.x() + rect.width(), rect.y() + rect.height(), + 0, 0, w, h, + GL_COLOR_BUFFER_BIT, + GL_NEAREST); + + glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo); + } else { + QPixmapData::copy(data, rect); + } } void QGLPixmapData::fill(const QColor &color) @@ -623,11 +652,12 @@ void QGLPixmapData::copyBackFromRenderFbo(bool keepCurrentFboBound) const } } -bool QGLPixmapData::useFramebufferObjects() +bool QGLPixmapData::useFramebufferObjects() const { return QGLFramebufferObject::hasOpenGLFramebufferObjects() && QGLFramebufferObject::hasOpenGLFramebufferBlit() - && qt_gl_preferGL2Engine(); + && qt_gl_preferGL2Engine() + && (w * h > 32*32); // avoid overhead of FBOs for small pixmaps } QPaintEngine* QGLPixmapData::paintEngine() const diff --git a/src/opengl/qpixmapdata_gl_p.h b/src/opengl/qpixmapdata_gl_p.h index 736a28e..4cb67b0 100644 --- a/src/opengl/qpixmapdata_gl_p.h +++ b/src/opengl/qpixmapdata_gl_p.h @@ -145,7 +145,7 @@ private: void copyBackFromRenderFbo(bool keepCurrentFboBound) const; QSize size() const { return QSize(w, h); } - static bool useFramebufferObjects(); + bool useFramebufferObjects() const; QImage fillImage(const QColor &color) const; -- cgit v0.12 From 7670e34120843c08de70f3a5db0816aeeff9dcc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Thu, 9 Sep 2010 17:31:28 +0200 Subject: Make sure we blit to the correct FBO in the GL window surface. Reviewed-by: Trond --- src/opengl/qwindowsurface_gl.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp index d602000..e84bc29 100644 --- a/src/opengl/qwindowsurface_gl.cpp +++ b/src/opengl/qwindowsurface_gl.cpp @@ -574,7 +574,9 @@ void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint & const int ty1 = parent->height() - rect.top(); if (window() == parent || d_ptr->fbo->format().samples() <= 1) { - // glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, 0); + if (ctx->d_ptr->current_fbo != 0) + glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, 0); + glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, d_ptr->fbo->handle()); glBlitFramebufferEXT(sx0, sy0, sx1, sy1, @@ -607,6 +609,8 @@ void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint & qgl_fbo_pool()->release(temp); } + + ctx->d_ptr->current_fbo = 0; } #if !defined(QT_OPENGL_ES_2) else { -- cgit v0.12