From 890648a91b266a889ac5c4d20acad2fe8ecb11e3 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Fri, 1 Jul 2011 08:19:52 +0200 Subject: [PATCH] Support setting an FBO as the render target for a canvas Change-Id: I8049580f1d2b27d6ebc4d595712939338c01b711 Reviewed-on: http://codereview.qt.nokia.com/986 Reviewed-by: Qt Sanity Bot Reviewed-by: Gunnar Sletta --- src/declarative/items/qsgcanvas.cpp | 44 +++++++++++++++++++++++++++++-- src/declarative/items/qsgcanvas.h | 5 ++++ src/declarative/items/qsgcanvas_p.h | 3 +++ src/declarative/scenegraph/qsgcontext.cpp | 10 +++++-- src/declarative/scenegraph/qsgcontext_p.h | 3 ++- 5 files changed, 60 insertions(+), 5 deletions(-) diff --git a/src/declarative/items/qsgcanvas.cpp b/src/declarative/items/qsgcanvas.cpp index 3abbec3..343a7e1 100644 --- a/src/declarative/items/qsgcanvas.cpp +++ b/src/declarative/items/qsgcanvas.cpp @@ -393,10 +393,10 @@ void QSGCanvasPrivate::syncSceneGraph() void QSGCanvasPrivate::renderSceneGraph(const QSize &size) { context->renderer()->setDeviceRect(QRect(QPoint(0, 0), size)); - context->renderer()->setViewportRect(QRect(QPoint(0, 0), size)); + context->renderer()->setViewportRect(QRect(QPoint(0, 0), renderTarget ? renderTarget->size() : size)); context->renderer()->setProjectionMatrixToDeviceRect(); - context->renderNextFrame(); + context->renderNextFrame(renderTarget); #ifdef FRAME_TIMING sceneGraphRenderTime = frameTimer.elapsed(); @@ -432,6 +432,7 @@ QSGCanvasPrivate::QSGCanvasPrivate() , vsyncAnimations(false) , thread(0) , animationDriver(0) + , renderTarget(0) { threadedRendering = !qmlNoThreadedRenderer(); } @@ -1979,6 +1980,44 @@ QSGEngine *QSGCanvas::sceneGraphEngine() const } + +/*! + Sets the render target for this canvas to be \a fbo. + + The specified fbo must be created in the context of the canvas + or one that shares with it. + + \warning + This function can only be called from the thread doing + the rendering. + */ + +void QSGCanvas::setRenderTarget(QGLFramebufferObject *fbo) +{ + Q_D(QSGCanvas); + if (d->context && d->context && QThread::currentThread() != d->context->thread()) { + qWarning("QSGCanvas::setRenderThread: Cannot set render target from outside the rendering thread"); + return; + } + + d->renderTarget = fbo; +} + + + +/*! + Returns the render target for this canvas. + + The default is to render to the surface of the canvas, in which + case the render target is 0. + */ +QGLFramebufferObject *QSGCanvas::renderTarget() const +{ + Q_D(const QSGCanvas); + return d->renderTarget; +} + + /*! Grabs the contents of the framebuffer and returns it as an image. @@ -2081,6 +2120,7 @@ void QSGCanvasRenderThread::run() #endif renderer->swapBuffers(); + #ifdef THREAD_DEBUG printf(" RenderThread: swap complete...\n"); #endif diff --git a/src/declarative/items/qsgcanvas.h b/src/declarative/items/qsgcanvas.h index 8913e41..aa0cdc8 100644 --- a/src/declarative/items/qsgcanvas.h +++ b/src/declarative/items/qsgcanvas.h @@ -55,6 +55,8 @@ QT_MODULE(Declarative) class QSGItem; class QSGEngine; class QSGCanvasPrivate; +class QGLFramebufferObject; + class Q_DECLARATIVE_EXPORT QSGCanvas : public QGLWidget { Q_OBJECT @@ -80,6 +82,9 @@ public: QImage grabFrameBuffer(); + void setRenderTarget(QGLFramebufferObject *fbo); + QGLFramebufferObject *renderTarget() const; + Q_SIGNALS: void sceneGraphInitialized(); diff --git a/src/declarative/items/qsgcanvas_p.h b/src/declarative/items/qsgcanvas_p.h index 7f7182e..c4c82b6 100644 --- a/src/declarative/items/qsgcanvas_p.h +++ b/src/declarative/items/qsgcanvas_p.h @@ -65,6 +65,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -168,6 +169,8 @@ public: QAnimationDriver *animationDriver; + QGLFramebufferObject *renderTarget; + QHash itemForTouchPointId; }; diff --git a/src/declarative/scenegraph/qsgcontext.cpp b/src/declarative/scenegraph/qsgcontext.cpp index 682b514..f5a082b 100644 --- a/src/declarative/scenegraph/qsgcontext.cpp +++ b/src/declarative/scenegraph/qsgcontext.cpp @@ -246,14 +246,20 @@ bool QSGContext::isReady() const } -void QSGContext::renderNextFrame() +void QSGContext::renderNextFrame(QGLFramebufferObject *fbo) { Q_D(QSGContext); emit d->engine.beforeRendering(); cleanupTextures(); - d->renderer->renderScene(); + + if (fbo) { + BindableFbo bindable(fbo); + d->renderer->renderScene(bindable); + } else { + d->renderer->renderScene(); + } emit d->engine.afterRendering(); diff --git a/src/declarative/scenegraph/qsgcontext_p.h b/src/declarative/scenegraph/qsgcontext_p.h index 1344ac7..5ce2e9e 100644 --- a/src/declarative/scenegraph/qsgcontext_p.h +++ b/src/declarative/scenegraph/qsgcontext_p.h @@ -65,6 +65,7 @@ class QSGMaterialShader; class QSGEngine; class QGLContext; +class QGLFramebufferObject; class Q_DECLARATIVE_EXPORT QSGContext : public QObject { @@ -89,7 +90,7 @@ public: QSGMaterialShader *prepareMaterial(QSGMaterial *material); - virtual void renderNextFrame(); + virtual void renderNextFrame(QGLFramebufferObject *fbo = 0); virtual QSGRectangleNode *createRectangleNode(); virtual QSGImageNode *createImageNode(); -- 2.7.4