diff --git a/examples/quick/scenegraph/openglunderqml/doc/src/openglunderqml.qdoc b/examples/quick/scenegraph/openglunderqml/doc/src/openglunderqml.qdoc
index 1f87412aa44703b7c66f73a1fd6732d97f0cd899..de023ff95cc02b75ead942a39705a244e865cb77 100644
--- a/examples/quick/scenegraph/openglunderqml/doc/src/openglunderqml.qdoc
+++ b/examples/quick/scenegraph/openglunderqml/doc/src/openglunderqml.qdoc
@@ -50,54 +50,40 @@
     in the QML file and this value is used by the OpenGL shader
     program that draws the squircles.
 
+    \snippet scenegraph/openglunderqml/squircle.h 2
+
+    First of all, we need an object we can expose to QML. This is a
+    subclass of QQuickItem so we can easily access \l QQuickItem::window().
+
     \snippet scenegraph/openglunderqml/squircle.h 1
 
-    First of all, we need a QObject with a slot to connect the signals
-    to. We subclass QQuickItem in order to use the \l
-    QQuickItem::window() which holds the window instance we want to
-    connect to.
-
-    We use two values of \c t. The variable \c m_t is the property
-    value as it exists in the GUI thread. The \c m_thread_t value is a
-    copy of \c m_t for use in the rendering thread. We need an
-    explicit copy because the scene graph can render in one thread
-    while updating properties on the GUI thread in preparation for the
-    next frame. If we had used only one value, the animation could
-    have updated the value to that of the next frame before we got a
-    chance to render it.
-
-    \note In this example, a wrong value for \c t will have minimal
-    consequences, but we emphasize that rendering and GUI thread
-    objects and values must stay separate to avoid race conditions,
-    undesired behavior and in the worst case, crashes.
+    Then we need an object to take care of the rendering. This
+    instance needs to be separated from the QQuickItem because the
+    item lives in the GUI thread and the rendering potentially happens
+    on the render thread. Since we want to connect to \l
+    QQuickWindow::beforeRendering(), we make the renderer a QObject.
+    The renderer contains a copy of all the state it needs,
+    independent of the GUI thread.
+
+    \note Don't be tempted to merge the two objects into
+    one. QQuickItems may be deleted on the GUI thread while the render
+    thread is rendering.
 
     Lets move on to the implementation.
 
     \snippet scenegraph/openglunderqml/squircle.cpp 7
 
     The constructor of the \c Squircle class simply initializes the
-    values. The shader program will be initialized during rendering
-    later.
-
-    \snippet scenegraph/openglunderqml/squircle.cpp 8
-
-    The property setter checks that the value has indeed changed
-    before updating its internal variable. It then calls \l
-    QQuickWindow::update() which will trigger another frame to be
-    rendered. Note that the setter might be called during
-    initialization, before the object has been entered into the scene
-    and before it has a window.
+    values and connects to the window changed signal which we will use
+    to prepare our renderer.
 
     \snippet scenegraph/openglunderqml/squircle.cpp 1
-    \snippet scenegraph/openglunderqml/squircle.cpp 2
 
-    For our paint function to be called, we need to connect to the
-    window's signals. When Squircle object is populated into the
-    scene, the windowChanged signal is emitted. In our handler,
-    we connect \l QQuickWindow::beforeRendering() to
-    \c paint() to do the rendering, and \l
-    QQuickWindow::beforeSynchronizing() to \c sync() to copy the state
-    of the \c t property for the upcoming frame.
+    Once we have a window, we attach to the \l
+    QQuickWindow::beforeSynchronizing() signal which we will use to
+    create the renderer and to copy state into it safely. We also
+    connect to the \l QQuickWindow::sceneGraphInvalidated() signal to
+    handle the cleanup of the renderer.
 
     \note Since the Squircle object has affinity to the GUI thread and
     the signals are emitted from the rendering thread, it is crucial
@@ -113,18 +99,35 @@
     graph, we need to turn this clearing off. This means that we need
     to clear ourselves in the \c paint() function.
 
-    \snippet scenegraph/openglunderqml/squircle.cpp 4
+    \snippet scenegraph/openglunderqml/squircle.cpp 9
+
+    We use the \c sync() function to initialize the renderer and to
+    copy the state in our item into the renderer. When the renderer is
+    created, we also connect the \l QQuickWindow::beforeRendering() to
+    the renderer's \c paint() slot.
 
-    The first thing we do in the \c paint() function is to
-    initialize the shader program. By initializing the shader program
-    here, we make sure that the OpenGL context is bound and that we
-    are on the correct thread.
+    \note The \l QQuickWindow::beforeSynchronizing() signal is emitted
+    on the rendering thread while the GUI thread is blocked, so it is
+    safe to simply copy the value without any additional protection.
 
-    We also connect to the QOpenGLContext::aboutToBeDestroyed()
-    signal, so that we can clean up the shader program when the
-    context is destroyed. Again, this is a \l Qt::DirectConnection as
-    all rendering related operations must happen on the rendering
-    thread.
+    \snippet scenegraph/openglunderqml/squircle.cpp 6
+
+    In the \c cleanup() function we delete the renderer which in turn
+    cleans up its own resources.
+
+    \snippet scenegraph/openglunderqml/squircle.cpp 8
+
+    When the value of \c t changes, we call \l QQuickWindow::update()
+    rather than \l QQuickItem::update() because the former will force
+    the entire window to be redrawn, even when the scene graph has not
+    changed since the last frame.
+
+    \snippet scenegraph/openglunderqml/squircle.cpp 4
+
+    In the SquircleRenderer's \c paint() function we start by
+    initializing the shader program. By initializing the shader
+    program here, we make sure that the OpenGL context is bound and
+    that we are on the correct thread.
 
     \snippet scenegraph/openglunderqml/squircle.cpp 5
 
@@ -133,18 +136,10 @@
     attributes we used so that the OpenGL context is in a "clean"
     state for the scene graph to pick it up.
 
-    \snippet scenegraph/openglunderqml/squircle.cpp 6
-
-    In the \c cleanup() function we delete the program.
-
-    \snippet scenegraph/openglunderqml/squircle.cpp 9
-
-    We use the \c sync() function to copy the state of the
-    object in the GUI thread into the rendering thread.
-
-    The signal is emitted on the rendering thread while the GUI
-    thread is blocked, so it is safe to simply copy the value without
-    any additional protection.
+    \note If tracking the changes in the OpenGL context's state is not
+    feasible, one can use the function \l
+    QQuickWindow::resetOpenGLState() which will reset all state that
+    the scene graph relies on.
 
     \snippet scenegraph/openglunderqml/main.cpp 1
 
diff --git a/examples/quick/scenegraph/openglunderqml/squircle.cpp b/examples/quick/scenegraph/openglunderqml/squircle.cpp
index 91d69c90a477b4a887d5f6cbaeb6f7e173b98559..4b892e37615a71f22606ea9ec0dca2e06d4cc999 100644
--- a/examples/quick/scenegraph/openglunderqml/squircle.cpp
+++ b/examples/quick/scenegraph/openglunderqml/squircle.cpp
@@ -47,9 +47,8 @@
 
 //! [7]
 Squircle::Squircle()
-    : m_program(0)
-    , m_t(0)
-    , m_thread_t(0)
+    : m_t(0)
+    , m_renderer(0)
 {
     connect(this, SIGNAL(windowChanged(QQuickWindow*)), this, SLOT(handleWindowChanged(QQuickWindow*)));
 }
@@ -71,24 +70,46 @@ void Squircle::setT(qreal t)
 void Squircle::handleWindowChanged(QQuickWindow *win)
 {
     if (win) {
-//! [1]
-        // Connect the beforeRendering signal to our paint function.
-        // Since this call is executed on the rendering thread it must be
-        // a Qt::DirectConnection
-//! [2]
-        connect(win, SIGNAL(beforeRendering()), this, SLOT(paint()), Qt::DirectConnection);
         connect(win, SIGNAL(beforeSynchronizing()), this, SLOT(sync()), Qt::DirectConnection);
-//! [2]
-
+        connect(win, SIGNAL(sceneGraphInvalidated()), this, SLOT(cleanup()), Qt::DirectConnection);
+//! [1]
         // If we allow QML to do the clearing, they would clear what we paint
         // and nothing would show.
 //! [3]
         win->setClearBeforeRendering(false);
     }
 }
+//! [3]
+
+//! [6]
+void Squircle::cleanup()
+{
+    if (m_renderer) {
+        delete m_renderer;
+        m_renderer = 0;
+    }
+}
 
-//! [3] //! [4]
-void Squircle::paint()
+SquircleRenderer::~SquircleRenderer()
+{
+    delete m_program;
+}
+//! [6]
+
+//! [9]
+void Squircle::sync()
+{
+    if (!m_renderer) {
+        m_renderer = new SquircleRenderer();
+        connect(window(), SIGNAL(beforeRendering()), m_renderer, SLOT(paint()), Qt::DirectConnection);
+    }
+    m_renderer->setViewportSize(window()->size() * window()->devicePixelRatio());
+    m_renderer->setT(m_t);
+}
+//! [9]
+
+//! [4]
+void SquircleRenderer::paint()
 {
     if (!m_program) {
         m_program = new QOpenGLShaderProgram();
@@ -112,8 +133,6 @@ void Squircle::paint()
         m_program->bindAttributeLocation("vertices", 0);
         m_program->link();
 
-        connect(window()->openglContext(), SIGNAL(aboutToBeDestroyed()),
-                this, SLOT(cleanup()), Qt::DirectConnection);
     }
 //! [4] //! [5]
     m_program->bind();
@@ -127,12 +146,9 @@ void Squircle::paint()
         1, 1
     };
     m_program->setAttributeArray(0, GL_FLOAT, values, 2);
-    m_program->setUniformValue("t", (float) m_thread_t);
+    m_program->setUniformValue("t", (float) m_t);
 
-    qreal ratio = window()->devicePixelRatio();
-    int w = int(ratio * window()->width());
-    int h = int(ratio * window()->height());
-    glViewport(0, 0, w, h);
+    glViewport(0, 0, m_viewportSize.width(), m_viewportSize.height());
 
     glDisable(GL_DEPTH_TEST);
 
@@ -148,21 +164,3 @@ void Squircle::paint()
     m_program->release();
 }
 //! [5]
-
-//! [6]
-void Squircle::cleanup()
-{
-    if (m_program) {
-        delete m_program;
-        m_program = 0;
-    }
-}
-//! [6]
-
-//! [9]
-void Squircle::sync()
-{
-    m_thread_t = m_t;
-}
-//! [9]
-
diff --git a/examples/quick/scenegraph/openglunderqml/squircle.h b/examples/quick/scenegraph/openglunderqml/squircle.h
index 449e02bbf11a5f46a4576f668ed82fd5112dc815..aa509082424d4c4a3cdc3d2cd07222863029564e 100644
--- a/examples/quick/scenegraph/openglunderqml/squircle.h
+++ b/examples/quick/scenegraph/openglunderqml/squircle.h
@@ -45,11 +45,32 @@
 #include <QtQuick/QQuickItem>
 #include <QtGui/QOpenGLShaderProgram>
 
+
+
+//! [1]
+class SquircleRenderer : public QObject {
+    Q_OBJECT
+public:
+    SquircleRenderer() : m_t(0), m_program(0) { }
+    ~SquircleRenderer();
+
+    void setT(qreal t) { m_t = t; }
+    void setViewportSize(const QSize &size) { m_viewportSize = size; }
+
+public slots:
+    void paint();
+
+private:
+    QSize m_viewportSize;
+    qreal m_t;
+    QOpenGLShaderProgram *m_program;
+};
 //! [1]
+
+//! [2]
 class Squircle : public QQuickItem
 {
     Q_OBJECT
-
     Q_PROPERTY(qreal t READ t WRITE setT NOTIFY tChanged)
 
 public:
@@ -62,19 +83,16 @@ signals:
     void tChanged();
 
 public slots:
-    void paint();
-    void cleanup();
     void sync();
+    void cleanup();
 
 private slots:
     void handleWindowChanged(QQuickWindow *win);
 
 private:
-    QOpenGLShaderProgram *m_program;
-
     qreal m_t;
-    qreal m_thread_t;
+    SquircleRenderer *m_renderer;
 };
-//! [1]
+//! [2]
 
 #endif // SQUIRCLE_H