Allow SG and GL resources to survive a releaseResources.
authorGunnar Sletta <gunnar.sletta@nokia.com>
Mon, 19 Mar 2012 19:23:02 +0000 (20:23 +0100)
committerQt by Nokia <qt-info@nokia.com>
Tue, 20 Mar 2012 09:12:49 +0000 (10:12 +0100)
The presence of these functions required some documentation so I
added some.

Change-Id: Id66bb6704b3db788ed612ebd6497a5c16ee8b2ca
Reviewed-by: Samuel Rødal <samuel.rodal@nokia.com>
src/quick/items/qquickcanvas.cpp
src/quick/items/qquickcanvas.h
src/quick/items/qquickcanvas_p.h

index a5d3250..7f51202 100644 (file)
@@ -306,6 +306,8 @@ QQuickCanvasPrivate::QQuickCanvasPrivate()
     , windowManager(0)
     , clearColor(Qt::white)
     , clearBeforeRendering(true)
+    , persistentGLContext(false)
+    , persistentSceneGraph(false)
     , renderTarget(0)
     , renderTargetId(0)
     , incubationController(0)
@@ -728,6 +730,55 @@ void QQuickCanvasPrivate::cleanup(QSGNode *n)
     reparent the items to the root item or to an existing item in the scene.
 
     For easily displaying a scene from a QML file, see \l{QQuickView}.
+
+
+    \section1 Scene Graph and Rendering
+
+    The QQuickCanvas uses a scene graph on top of OpenGL to render. This scene graph is disconnected
+    from the QML scene and potentially lives in another thread, depending on the platform
+    implementation. Since the rendering scene graph lives independently from the QML scene, it can
+    also be completely released without affecting the state of the QML scene.
+
+    The sceneGraphInitialized() signal is emitted on the rendering thread before the QML scene is
+    rendered to the screen for the first time. If the rendering scene graph has been released
+    the signal will be emitted again before the next frame is rendered.
+
+    Rendering is done by first copying the QML scene's state into the rendering scene graph. This is
+    done by calling QQuickItem::updatePaintNode() functions on all items that have changed. This phase
+    is run on the rendering thread with the GUI thread blocked, when a separate rendering thread
+    is being used. The scene can then be rendered.
+
+    Before the scene graph is rendered, the beforeRendering() signal is emitted. The OpenGL context
+    is bound at this point and the application is free to do its own rendering. Also
+    make sure to disable the clearing of the color buffer, using setClearBeforeRendering(). The
+    default clear color is white and can be changed with setClearColor(). After the scene has
+    been rendered, the afterRendering() signal is emitted. The application can use this to render
+    OpenGL on top of a QML application. Once the frame is fully done and has been swapped,
+    the frameSwapped() signal is emitted.
+
+    While the scene graph is being rendered on the rendering thread, the GUI will process animations
+    for the next frame. This means that as long as users are not using scene graph API
+    directly, the added complexity of a rendering thread can be completely ignored.
+
+    When a QQuickCanvas is programatically hidden with hide() or setVisible(false), it will
+    stop rendering and its scene graph and OpenGL context might be released. The
+    sceneGraphInvalidated() signal will be emitted when this happens.
+
+    \warning It is crucial that OpenGL operations and interaction with the scene graph happens
+    exclusively on the rendering thread, primarily during the updatePaintNode() phase.
+
+    \warning As signals related to rendering might be emitted from the rendering thread,
+    connections should be made using Qt::DirectConnection
+
+
+    \section1 Resource Management
+
+    QML will typically try to cache images, scene graph nodes, etc to improve performance, but in
+    some low-memory scenarios it might be required to aggressively release these resources. The
+    releaseResources() can be used to force clean up of certain resources. Calling releaseResources()
+    may result in the entire scene graph and its OpenGL context being deleted. The
+    sceneGraphInvalidated() signal will be emitted when this happens.
+
 */
 QQuickCanvas::QQuickCanvas(QWindow *parent)
     : QWindow(*(new QQuickCanvasPrivate), parent)
@@ -764,6 +815,15 @@ QQuickCanvas::~QQuickCanvas()
 
 /*!
     This function tries to release redundant resources currently held by the QML scene.
+
+    Calling this function might result in the scene graph and the OpenGL context used
+    for rendering being released to release graphics memory. If this happens, the
+    sceneGraphInvalidated() signal will be called, allowing users to clean up their
+    own graphics resources. The setPersistentOpenGLContext() and setPersistentSceneGraph()
+    functions can be used to prevent this from happening, if handling the cleanup is
+    not feasible in the application, at the cost of higher memory usage.
+
+    \sa sceneGraphInvalidated(), setPersistentOpenGLContext(), setPersistentSceneGraph().
  */
 
 void QQuickCanvas::releaseResources()
@@ -776,6 +836,69 @@ void QQuickCanvas::releaseResources()
 
 
 /*!
+    Controls whether the OpenGL context can be released as a part of a call to
+    releaseResources().
+
+    The OpenGL context might still be released when the user makes an explicit
+    call to hide().
+
+    \sa setPersistentSceneGraph()
+ */
+
+void QQuickCanvas::setPersistentOpenGLContext(bool persistent)
+{
+    Q_D(QQuickCanvas);
+    d->persistentGLContext = persistent;
+}
+
+
+/*!
+    Returns whether the OpenGL context can be released as a part of a call to
+    releaseResources().
+ */
+
+bool QQuickCanvas::isPersistentOpenGLContext() const
+{
+    Q_D(const QQuickCanvas);
+    return d->persistentGLContext;
+}
+
+
+
+/*!
+    Controls whether the scene graph nodes and resources can be released as a
+    part of a call to releaseResources().
+
+    The scene graph nodes and resources might still be released when the user
+    makes an explicit call to hide().
+
+    \sa setPersistentOpenGLContext()
+ */
+
+void QQuickCanvas::setPersistentSceneGraph(bool persistent)
+{
+    Q_D(QQuickCanvas);
+    d->persistentSceneGraph = persistent;
+}
+
+
+
+/*!
+    Returns whether the scene graph nodes and resources can be released as a part
+    of a call to releaseResources().
+ */
+
+bool QQuickCanvas::isPersistentSceneGraph() const
+{
+    Q_D(const QQuickCanvas);
+    return d->persistentSceneGraph;
+}
+
+
+
+
+
+/*!
   Returns the invisible root item of the scene.
 
   A QQuickCanvas always has a single invisible root item. To add items to this canvas,
index 4ac9509..787bb7e 100644 (file)
@@ -114,6 +114,12 @@ public:
     void setClearColor(const QColor &color);
     QColor clearColor() const;
 
+    void setPersistentOpenGLContext(bool persistent);
+    bool isPersistentOpenGLContext() const;
+
+    void setPersistentSceneGraph(bool persistent);
+    bool isPersistentSceneGraph() const;
+
     QOpenGLContext *openglContext() const;
 
 Q_SIGNALS:
index 0ecdf1f..643d694 100644 (file)
@@ -184,6 +184,11 @@ public:
 
     uint clearBeforeRendering : 1;
 
+    // Currently unused in the default implementation, as we're not stopping
+    // rendering when obscured as we should...
+    uint persistentGLContext : 1;
+    uint persistentSceneGraph : 1;
+
     QOpenGLFramebufferObject *renderTarget;
     uint renderTargetId;
     QSize renderTargetSize;