Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Allow SG and GL resources to survive a releaseResources.
The presence of these functions required some documentation so I
added some.

Change-Id: Id66bb6704b3db788ed612ebd6497a5c16ee8b2ca
Reviewed-by: Samuel Rødal <samuel.rodal@nokia.com>
  • Loading branch information
Gunnar Sletta authored and Qt by Nokia committed Mar 20, 2012
1 parent 0432729 commit e20c351
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 0 deletions.
123 changes: 123 additions & 0 deletions src/quick/items/qquickcanvas.cpp
Expand Up @@ -306,6 +306,8 @@ QQuickCanvasPrivate::QQuickCanvasPrivate()
, windowManager(0)
, clearColor(Qt::white)
, clearBeforeRendering(true)
, persistentGLContext(false)
, persistentSceneGraph(false)
, renderTarget(0)
, renderTargetId(0)
, incubationController(0)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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()
Expand All @@ -775,6 +835,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.
Expand Down
6 changes: 6 additions & 0 deletions src/quick/items/qquickcanvas.h
Expand Up @@ -114,6 +114,12 @@ class Q_QUICK_EXPORT QQuickCanvas : public QWindow
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:
Expand Down
5 changes: 5 additions & 0 deletions src/quick/items/qquickcanvas_p.h
Expand Up @@ -184,6 +184,11 @@ class Q_QUICK_EXPORT QQuickCanvasPrivate : public QWindowPrivate

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;
Expand Down

0 comments on commit e20c351

Please sign in to comment.