diff --git a/examples/quick/quick.pro b/examples/quick/quick.pro
index 421f95a1629ec4cdac0d6b43df3b65d8b1896d81..a412c53a65db853b32e480a0fd20cb88bd19afb2 100644
--- a/examples/quick/quick.pro
+++ b/examples/quick/quick.pro
@@ -22,7 +22,8 @@ SUBDIRS =   quick-accessibility \
             imageprovider \
             window \
             particles \
-            demos
+            demos \
+            rendercontrol
 
 # Widget dependent examples
 qtHaveModule(widgets) {
diff --git a/examples/quick/rendercontrol/demo.qml b/examples/quick/rendercontrol/demo.qml
new file mode 100644
index 0000000000000000000000000000000000000000..e7ede915404dccee9d84edd68ab8c3ae938733c8
--- /dev/null
+++ b/examples/quick/rendercontrol/demo.qml
@@ -0,0 +1,198 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtQuick.Particles 2.0
+
+Rectangle {
+    id: root
+    color: "green"
+
+    Rectangle {
+        width: 400
+        height: 400
+        anchors.centerIn: parent
+        color: "red"
+        NumberAnimation on rotation { from: 0; to: 360; duration: 2000; loops: Animation.Infinite; }
+    }
+
+    Text {
+        anchors.centerIn: parent
+        text: "Qt Quick in a texture"
+        font.pointSize: 40
+        color: "cyan"
+    }
+
+    ParticleSystem {
+        id: particles
+        anchors.fill: parent
+
+        ImageParticle {
+            id: smoke
+            system: particles
+            anchors.fill: parent
+            groups: ["A", "B"]
+            source: "qrc:///particleresources/glowdot.png"
+            colorVariation: 0
+            color: "#00111111"
+        }
+        ImageParticle {
+            id: flame
+            anchors.fill: parent
+            system: particles
+            groups: ["C", "D"]
+            source: "qrc:///particleresources/glowdot.png"
+            colorVariation: 0.1
+            color: "#00ff400f"
+        }
+
+        Emitter {
+            id: fire
+            system: particles
+            group: "C"
+
+            y: parent.height
+            width: parent.width
+
+            emitRate: 350
+            lifeSpan: 3500
+
+            acceleration: PointDirection { y: -17; xVariation: 3 }
+            velocity: PointDirection {xVariation: 3}
+
+            size: 24
+            sizeVariation: 8
+            endSize: 4
+        }
+
+        TrailEmitter {
+            id: fireSmoke
+            group: "B"
+            system: particles
+            follow: "C"
+            width: root.width
+            height: root.height - 68
+
+            emitRatePerParticle: 1
+            lifeSpan: 2000
+
+            velocity: PointDirection {y:-17*6; yVariation: -17; xVariation: 3}
+            acceleration: PointDirection {xVariation: 3}
+
+            size: 36
+            sizeVariation: 8
+            endSize: 16
+        }
+
+        TrailEmitter {
+            id: fireballFlame
+            anchors.fill: parent
+            system: particles
+            group: "D"
+            follow: "E"
+
+            emitRatePerParticle: 120
+            lifeSpan: 180
+            emitWidth: TrailEmitter.ParticleSize
+            emitHeight: TrailEmitter.ParticleSize
+            emitShape: EllipseShape{}
+
+            size: 16
+            sizeVariation: 4
+            endSize: 4
+        }
+
+        TrailEmitter {
+            id: fireballSmoke
+            anchors.fill: parent
+            system: particles
+            group: "A"
+            follow: "E"
+
+            emitRatePerParticle: 128
+            lifeSpan: 2400
+            emitWidth: TrailEmitter.ParticleSize
+            emitHeight: TrailEmitter.ParticleSize
+            emitShape: EllipseShape{}
+
+            velocity: PointDirection {yVariation: 16; xVariation: 16}
+            acceleration: PointDirection {y: -16}
+
+            size: 24
+            sizeVariation: 8
+            endSize: 8
+        }
+
+        Emitter {
+            id: balls
+            system: particles
+            group: "E"
+
+            y: parent.height
+            width: parent.width
+
+            emitRate: 2
+            lifeSpan: 7000
+
+            velocity: PointDirection {y:-17*4*2; xVariation: 6*6}
+            acceleration: PointDirection {y: 17*2; xVariation: 6*6}
+
+            size: 8
+            sizeVariation: 4
+        }
+
+        Turbulence { //A bit of turbulence makes the smoke look better
+            anchors.fill: parent
+            groups: ["A","B"]
+            strength: 32
+            system: particles
+        }
+    }
+
+    onWidthChanged: particles.reset()
+    onHeightChanged: particles.reset()
+
+    MouseArea {
+        anchors.fill: parent
+        onPressed: root.color = "gray"
+        onReleased: root.color = "green"
+    }
+}
diff --git a/examples/quick/rendercontrol/doc/images/rendercontrol-example.jpg b/examples/quick/rendercontrol/doc/images/rendercontrol-example.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..a899ebe7f5cdd38ce23e54cfa0a1ed3d960e68ce
Binary files /dev/null and b/examples/quick/rendercontrol/doc/images/rendercontrol-example.jpg differ
diff --git a/examples/quick/rendercontrol/doc/src/rendercontrol.qdoc b/examples/quick/rendercontrol/doc/src/rendercontrol.qdoc
new file mode 100644
index 0000000000000000000000000000000000000000..f8a9849a8a25ad63272da59ebc5b8357986497e5
--- /dev/null
+++ b/examples/quick/rendercontrol/doc/src/rendercontrol.qdoc
@@ -0,0 +1,33 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file.  Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+    \title QQuickRenderControl Example
+    \example rendercontrol
+    \brief Shows how to render a Qt Quick scene into a texture that is then used by a non-Quick based OpenGL renderer
+    \image rendercontrol-example.jpg
+*/
diff --git a/examples/quick/rendercontrol/main.cpp b/examples/quick/rendercontrol/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d362278ddf7c9c4baf0d1918bb22b562841bbc4f
--- /dev/null
+++ b/examples/quick/rendercontrol/main.cpp
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * Redistributions in binary form must reproduce the above copyright
+**     notice, this list of conditions and the following disclaimer in
+**     the documentation and/or other materials provided with the
+**     distribution.
+**   * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
+**     of its contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QGuiApplication>
+#include "window.h"
+
+int main(int argc, char **argv)
+{
+    QGuiApplication app(argc, argv);
+    Window window;
+    window.resize(1024, 768);
+    window.show();
+    return app.exec();
+}
diff --git a/examples/quick/rendercontrol/rendercontrol.pro b/examples/quick/rendercontrol/rendercontrol.pro
new file mode 100644
index 0000000000000000000000000000000000000000..ed25a11c1b915f91e186e1be3d5a11cb6a6e252c
--- /dev/null
+++ b/examples/quick/rendercontrol/rendercontrol.pro
@@ -0,0 +1,11 @@
+TEMPLATE = app
+
+QT += quick qml
+
+SOURCES += main.cpp window.cpp
+HEADERS += window.h
+
+RESOURCES += rendercontrol.qrc
+
+target.path = $$[QT_INSTALL_EXAMPLES]/quick/rendercontrol
+INSTALLS += target
diff --git a/examples/quick/rendercontrol/rendercontrol.qrc b/examples/quick/rendercontrol/rendercontrol.qrc
new file mode 100644
index 0000000000000000000000000000000000000000..2246eeb8423dfddd5e8b06c69745ac7ea28fd98f
--- /dev/null
+++ b/examples/quick/rendercontrol/rendercontrol.qrc
@@ -0,0 +1,5 @@
+<RCC>
+    <qresource prefix="/rendercontrol">
+        <file>demo.qml</file>
+    </qresource>
+</RCC>
diff --git a/examples/quick/rendercontrol/window.cpp b/examples/quick/rendercontrol/window.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..396e9f8afa565b1df232882084b80919f2319a80
--- /dev/null
+++ b/examples/quick/rendercontrol/window.cpp
@@ -0,0 +1,403 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * Redistributions in binary form must reproduce the above copyright
+**     notice, this list of conditions and the following disclaimer in
+**     the documentation and/or other materials provided with the
+**     distribution.
+**   * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
+**     of its contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "window.h"
+#include <QOpenGLContext>
+#include <QOpenGLFunctions>
+#include <QOpenGLFramebufferObject>
+#include <QOpenGLShaderProgram>
+#include <QOpenGLVertexArrayObject>
+#include <QOpenGLBuffer>
+#include <QOpenGLVertexArrayObject>
+#include <QOffscreenSurface>
+#include <QQmlEngine>
+#include <QQmlComponent>
+#include <QQuickItem>
+#include <QQuickWindow>
+#include <QQuickRenderControl>
+#include <QCoreApplication>
+
+Window::Window()
+    : m_rootItem(0),
+      m_fbo(0),
+      m_program(0),
+      m_vbo(0),
+      m_quickInitialized(false),
+      m_quickReady(false)
+{
+    setSurfaceType(QSurface::OpenGLSurface);
+
+    QSurfaceFormat format;
+    // Qt Quick may need a depth and stencil buffer. Always make sure these are available.
+    format.setDepthBufferSize(16);
+    format.setStencilBufferSize(8);
+    setFormat(format);
+
+    m_context = new QOpenGLContext;
+    m_context->setFormat(format);
+    m_context->create();
+
+    m_offscreenSurface = new QOffscreenSurface;
+    // Pass m_context->format(), not format. Format does not specify and color buffer
+    // sizes, while the context, that has just been created, reports a format that has
+    // these values filled in. Pass this to the offscreen surface to make sure it will be
+    // compatible with the context's configuration.
+    m_offscreenSurface->setFormat(m_context->format());
+    m_offscreenSurface->create();
+
+    m_renderControl = new QQuickRenderControl(this);
+
+    // Create a QQuickWindow that is associated with out render control. Note that this
+    // window never gets created or shown, meaning that it will never get an underlying
+    // native (platform) window.
+    m_quickWindow = new QQuickWindow(m_renderControl);
+
+    // Create a QML engine.
+    m_qmlEngine = new QQmlEngine;
+    if (!m_qmlEngine->incubationController())
+        m_qmlEngine->setIncubationController(m_quickWindow->incubationController());
+
+    // When Quick says there is a need to render, we will not render immediately. Instead,
+    // a timer with a small interval is used to get better performance.
+    m_updateTimer.setSingleShot(true);
+    m_updateTimer.setInterval(5);
+    connect(&m_updateTimer, &QTimer::timeout, this, &Window::updateQuick);
+
+    // Now hook up the signals. For simplicy we don't differentiate between
+    // renderRequested (only render is needed, no sync) and sceneChanged (polish and sync
+    // is needed too).
+    connect(m_quickWindow, &QQuickWindow::sceneGraphInitialized, this, &Window::createFbo);
+    connect(m_quickWindow, &QQuickWindow::sceneGraphInvalidated, this, &Window::destroyFbo);
+    connect(m_renderControl, &QQuickRenderControl::renderRequested, this, &Window::requestUpdate);
+    connect(m_renderControl, &QQuickRenderControl::sceneChanged, this, &Window::requestUpdate);
+}
+
+Window::~Window()
+{
+    // Make sure the context is current while doing cleanup.
+    m_context->makeCurrent(this);
+
+    // Delete the render control first since it will free the scenegraph resources.
+    // Destroy the QQuickWindow only afterwards.
+    delete m_renderControl;
+
+    delete m_qmlComponent;
+    delete m_quickWindow;
+    delete m_qmlEngine;
+    delete m_fbo;
+    delete m_program;
+    delete m_vbo;
+    delete m_vao;
+
+    m_context->doneCurrent();
+
+    delete m_offscreenSurface;
+    delete m_context;
+}
+
+void Window::createFbo()
+{
+    // The scene graph has been initialized. It is now time to create an FBO and associate
+    // it with the QQuickWindow.
+    m_fbo = new QOpenGLFramebufferObject(size(), QOpenGLFramebufferObject::CombinedDepthStencil);
+    m_quickWindow->setRenderTarget(m_fbo);
+}
+
+void Window::destroyFbo()
+{
+    delete m_fbo;
+    m_fbo = 0;
+}
+
+void Window::requestUpdate()
+{
+    if (!m_updateTimer.isActive())
+        m_updateTimer.start();
+}
+
+void Window::run()
+{
+    disconnect(m_qmlComponent, SIGNAL(statusChanged(QQmlComponent::Status)), this, SLOT(run()));
+
+    if (m_qmlComponent->isError()) {
+        QList<QQmlError> errorList = m_qmlComponent->errors();
+        foreach (const QQmlError &error, errorList)
+            qWarning() << error.url() << error.line() << error;
+        return;
+    }
+
+    QObject *rootObject = m_qmlComponent->create();
+    if (m_qmlComponent->isError()) {
+        QList<QQmlError> errorList = m_qmlComponent->errors();
+        foreach (const QQmlError &error, errorList)
+            qWarning() << error.url() << error.line() << error;
+        return;
+    }
+
+    m_rootItem = qobject_cast<QQuickItem *>(rootObject);
+    if (!m_rootItem) {
+        qWarning("run: Not a QQuickItem");
+        delete rootObject;
+        return;
+    }
+
+    // The root item is ready. Associate it with the window.
+    m_rootItem->setParentItem(m_quickWindow->contentItem());
+
+    // Update item and rendering related geometries.
+    updateSizes();
+
+    // Initialize the render control and our OpenGL resources.
+    m_context->makeCurrent(m_offscreenSurface);
+    m_renderControl->initialize(m_context);
+
+    static const char *vertexShaderSource =
+        "attribute highp vec4 vertex;\n"
+        "attribute lowp vec2 coord;\n"
+        "varying lowp vec2 v_coord;\n"
+        "uniform highp mat4 matrix;\n"
+        "void main() {\n"
+        "   v_coord = coord;\n"
+        "   gl_Position = matrix * vertex;\n"
+        "}\n";
+    static const char *fragmentShaderSource =
+        "varying lowp vec2 v_coord;\n"
+        "uniform sampler2D sampler;\n"
+        "void main() {\n"
+        "   gl_FragColor = vec4(texture2D(sampler, v_coord).rgb, 1.0);\n"
+        "}\n";
+    m_program = new QOpenGLShaderProgram;
+    m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);
+    m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);
+    m_program->bindAttributeLocation("vertex", 0);
+    m_program->bindAttributeLocation("coord", 1);
+    m_program->link();
+    m_matrixLoc = m_program->uniformLocation("matrix");
+
+    m_vao = new QOpenGLVertexArrayObject;
+    m_vao->create();
+    m_vao->bind();
+
+    m_vbo = new QOpenGLBuffer;
+    m_vbo->create();
+    m_vbo->bind();
+
+    GLfloat v[] = {
+        -0.5, 0.5, 0.5, 0.5,-0.5,0.5,-0.5,-0.5,0.5,
+        0.5, -0.5, 0.5, -0.5,0.5,0.5,0.5,0.5,0.5,
+        -0.5, -0.5, -0.5, 0.5,-0.5,-0.5,-0.5,0.5,-0.5,
+        0.5, 0.5, -0.5, -0.5,0.5,-0.5,0.5,-0.5,-0.5,
+
+        0.5, -0.5, -0.5, 0.5,-0.5,0.5,0.5,0.5,-0.5,
+        0.5, 0.5, 0.5, 0.5,0.5,-0.5,0.5,-0.5,0.5,
+        -0.5, 0.5, -0.5, -0.5,-0.5,0.5,-0.5,-0.5,-0.5,
+        -0.5, -0.5, 0.5, -0.5,0.5,-0.5,-0.5,0.5,0.5,
+
+        0.5, 0.5,  -0.5, -0.5, 0.5,  0.5,  -0.5,  0.5,  -0.5,
+        -0.5,  0.5,  0.5,  0.5,  0.5,  -0.5, 0.5, 0.5,  0.5,
+        -0.5,  -0.5, -0.5, -0.5, -0.5, 0.5,  0.5, -0.5, -0.5,
+        0.5, -0.5, 0.5,  0.5,  -0.5, -0.5, -0.5,  -0.5, 0.5
+    };
+    GLfloat texCoords[] = {
+        0.0f,0.0f, 1.0f,1.0f, 1.0f,0.0f,
+        1.0f,1.0f, 0.0f,0.0f, 0.0f,1.0f,
+        1.0f,1.0f, 1.0f,0.0f, 0.0f,1.0f,
+        0.0f,0.0f, 0.0f,1.0f, 1.0f,0.0f,
+
+        1.0f,1.0f, 1.0f,0.0f, 0.0f,1.0f,
+        0.0f,0.0f, 0.0f,1.0f, 1.0f,0.0f,
+        0.0f,0.0f, 1.0f,1.0f, 1.0f,0.0f,
+        1.0f,1.0f, 0.0f,0.0f, 0.0f,1.0f,
+
+        0.0f,1.0f, 1.0f,0.0f, 1.0f,1.0f,
+        1.0f,0.0f, 0.0f,1.0f, 0.0f,0.0f,
+        1.0f,0.0f, 1.0f,1.0f, 0.0f,0.0f,
+        0.0f,1.0f, 0.0f,0.0f, 1.0f,1.0f
+    };
+
+    const int vertexCount = 36;
+    m_vbo->allocate(sizeof(GLfloat) * vertexCount * 5);
+    m_vbo->write(0, v, sizeof(GLfloat) * vertexCount * 3);
+    m_vbo->write(sizeof(GLfloat) * vertexCount * 3, texCoords, sizeof(GLfloat) * vertexCount * 2);
+    m_vbo->release();
+
+    if (m_vao->isCreated())
+        setupVertexAttribs();
+
+    // Must unbind before changing the current context. Hence the absence of
+    // QOpenGLVertexArrayObject::Binder here.
+    m_vao->release();
+
+    m_context->doneCurrent();
+    m_quickInitialized = true;
+}
+
+void Window::updateSizes()
+{
+    // Behave like SizeRootObjectToView.
+    m_rootItem->setWidth(width());
+    m_rootItem->setHeight(height());
+
+    m_quickWindow->setGeometry(0, 0, width(), height());
+
+    m_proj.setToIdentity();
+    m_proj.perspective(45, width() / float(height()), 0.01f, 100.0f);
+}
+
+void Window::setupVertexAttribs()
+{
+    m_vbo->bind();
+    m_program->enableAttributeArray(0);
+    m_program->enableAttributeArray(1);
+    m_context->functions()->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
+    m_context->functions()->glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0,
+                                                  (const void *)(36 * 3 * sizeof(GLfloat)));
+    m_vbo->release();
+}
+
+void Window::startQuick(const QString &filename)
+{
+    m_qmlComponent = new QQmlComponent(m_qmlEngine, QUrl(filename));
+    if (m_qmlComponent->isLoading())
+        connect(m_qmlComponent, &QQmlComponent::statusChanged, this, &Window::run);
+    else
+        run();
+}
+
+void Window::exposeEvent(QExposeEvent *)
+{
+    if (isExposed()) {
+        render();
+        if (!m_quickInitialized)
+            startQuick(QStringLiteral("qrc:/rendercontrol/demo.qml"));
+    }
+}
+
+void Window::resizeEvent(QResizeEvent *)
+{
+    // If this is a resize after the scene is up and running, recreate the fbo and the
+    // Quick item and scene.
+    if (m_rootItem && m_context->makeCurrent(m_offscreenSurface)) {
+        delete m_fbo;
+        createFbo();
+        m_context->doneCurrent();
+        updateSizes();
+    }
+}
+
+void Window::updateQuick()
+{
+    if (!m_context->makeCurrent(m_offscreenSurface))
+        return;
+
+    // Polish, synchronize and render the next frame (into our fbo).  In this example
+    // everything happens on the same thread and therefore all three steps are performed
+    // in succession from here. In a threaded setup the render() call would happen on a
+    // separate thread.
+    m_renderControl->polishItems();
+    m_renderControl->sync();
+    m_renderControl->render();
+
+    m_quickWindow->resetOpenGLState();
+    QOpenGLFramebufferObject::bindDefault();
+
+    m_quickReady = true;
+
+    // Get something onto the screen.
+    render();
+}
+
+void Window::render()
+{
+    if (!m_context->makeCurrent(this))
+        return;
+
+    QOpenGLFunctions *f = m_context->functions();
+    f->glClearColor(0.0f, 0.1f, 0.25f, 1.0f);
+    f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+    if (m_quickReady) {
+        f->glFrontFace(GL_CW); // because our cube's vertex data is such
+        f->glEnable(GL_CULL_FACE);
+        f->glEnable(GL_DEPTH_TEST);
+
+        f->glBindTexture(GL_TEXTURE_2D, m_fbo->texture());
+
+        m_program->bind();
+        QOpenGLVertexArrayObject::Binder vaoBinder(m_vao);
+        // If VAOs are not supported, set the vertex attributes every time.
+        if (!m_vao->isCreated())
+            setupVertexAttribs();
+
+        static GLfloat angle = 0;
+        QMatrix4x4 m;
+        m.translate(0, 0, -2);
+        m.rotate(90, 0, 0, 1);
+        m.rotate(angle, 0.5, 1, 0);
+        angle += 0.5f;
+
+        m_program->setUniformValue(m_matrixLoc, m_proj * m);
+
+        // Draw the cube.
+        f->glDrawArrays(GL_TRIANGLES, 0, 36);
+
+        m_program->release();
+        f->glDisable(GL_DEPTH_TEST);
+        f->glDisable(GL_CULL_FACE);
+    }
+
+    m_context->swapBuffers(this);
+}
+
+void Window::mousePressEvent(QMouseEvent *e)
+{
+    // Use the constructor taking localPos and screenPos. That puts localPos into the
+    // event's localPos and windowPos, and screenPos into the event's screenPos. This way
+    // the windowPos in e is ignored and is replaced by localPos. This is necessary
+    // because QQuickWindow thinks of itself as a top-level window always.
+    QMouseEvent mappedEvent(e->type(), e->localPos(), e->screenPos(), e->button(), e->buttons(), e->modifiers());
+    QCoreApplication::sendEvent(m_quickWindow, &mappedEvent);
+}
+
+void Window::mouseReleaseEvent(QMouseEvent *e)
+{
+    QMouseEvent mappedEvent(e->type(), e->localPos(), e->screenPos(), e->button(), e->buttons(), e->modifiers());
+    QCoreApplication::sendEvent(m_quickWindow, &mappedEvent);
+}
diff --git a/examples/quick/rendercontrol/window.h b/examples/quick/rendercontrol/window.h
new file mode 100644
index 0000000000000000000000000000000000000000..2723aeb0111c655919a873928d59aa831c1ecb9c
--- /dev/null
+++ b/examples/quick/rendercontrol/window.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * Redistributions in binary form must reproduce the above copyright
+**     notice, this list of conditions and the following disclaimer in
+**     the documentation and/or other materials provided with the
+**     distribution.
+**   * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
+**     of its contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QWindow>
+#include <QMatrix4x4>
+#include <QTimer>
+
+QT_FORWARD_DECLARE_CLASS(QOpenGLContext)
+QT_FORWARD_DECLARE_CLASS(QOpenGLFramebufferObject)
+QT_FORWARD_DECLARE_CLASS(QOpenGLShaderProgram)
+QT_FORWARD_DECLARE_CLASS(QOpenGLBuffer)
+QT_FORWARD_DECLARE_CLASS(QOpenGLVertexArrayObject)
+QT_FORWARD_DECLARE_CLASS(QOffscreenSurface)
+QT_FORWARD_DECLARE_CLASS(QQuickRenderControl)
+QT_FORWARD_DECLARE_CLASS(QQuickWindow)
+QT_FORWARD_DECLARE_CLASS(QQmlEngine)
+QT_FORWARD_DECLARE_CLASS(QQmlComponent)
+QT_FORWARD_DECLARE_CLASS(QQuickItem)
+
+class Window : public QWindow
+{
+    Q_OBJECT
+
+public:
+    Window();
+    ~Window();
+
+protected:
+    void exposeEvent(QExposeEvent *e) Q_DECL_OVERRIDE;
+    void resizeEvent(QResizeEvent *e) Q_DECL_OVERRIDE;
+    void mousePressEvent(QMouseEvent *e) Q_DECL_OVERRIDE;
+    void mouseReleaseEvent(QMouseEvent *e) Q_DECL_OVERRIDE;
+
+private slots:
+    void render();
+    void updateQuick();
+    void run();
+    void createFbo();
+    void destroyFbo();
+    void requestUpdate();
+
+private:
+    void startQuick(const QString &filename);
+    void setupVertexAttribs();
+    void updateSizes();
+
+    QOpenGLContext *m_context;
+    QOffscreenSurface *m_offscreenSurface;
+    QQuickRenderControl *m_renderControl;
+    QQuickWindow *m_quickWindow;
+    QQmlEngine *m_qmlEngine;
+    QQmlComponent *m_qmlComponent;
+    QQuickItem *m_rootItem;
+    QOpenGLFramebufferObject *m_fbo;
+    QOpenGLShaderProgram *m_program;
+    QOpenGLBuffer *m_vbo;
+    QOpenGLVertexArrayObject *m_vao;
+    bool m_quickInitialized;
+    bool m_quickReady;
+    int m_matrixLoc;
+    QMatrix4x4 m_proj;
+    QTimer m_updateTimer;
+};
diff --git a/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc b/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc
index 7a54b7a021fa6b31c01875515dbd0ebafc743e37..1f8147c4d119c069ffb851caf8ab8527d1b086e6 100644
--- a/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc
+++ b/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc
@@ -244,11 +244,11 @@ animations, process events, etc.
 
 \endlist
 
-The threaded renderer is currently used by default on Linux, Mac OS X
-and EGLFS based QPA platforms, but this is subject to change. It is
-possible to force use of the threaded renderer by setting \c
-{QML_FORCE_THREADED_RENDERER=1} in the environment.
-
+The threaded renderer is currently used by default on Linux with
+non-Mesa based drivers, OS X and EGLFS based QPA platforms, but this
+is subject to change. It is possible to force use of the threaded
+renderer by setting \c {QSG_RENDER_LOOP=threaded} in the
+environment.
 
 \section2 Non-threaded Render Loop
 
@@ -267,6 +267,16 @@ sequence in the non-threaded renderer.
 \image sg-renderloop-singlethreaded.jpg
 
 
+\section2 Custom control over rendering with QQuickRenderControl
+
+When using QQuickRenderControl, the responsibility for driving the
+rendering loop is transferred to the application. In this case no
+built-in render loop is used. Instead, it is up to the application to
+invoke the polish, synchronize and rendering steps at the appropriate
+time. It is possible to implement either a threaded or non-threaded
+behavior similar to the ones shown above.
+
+
 \section2 Mixing Scene Graph and OpenGL
 
 The scene graph offers two methods for integrating OpenGL content:
diff --git a/src/quick/items/items.pri b/src/quick/items/items.pri
index add909d0cb34fd3f9dd41bb5177bd98adda64f4e..042ff80abc4c2f9d4af70ebf551534f406f6e03a 100644
--- a/src/quick/items/items.pri
+++ b/src/quick/items/items.pri
@@ -10,7 +10,6 @@ HEADERS += \
     $$PWD/qquickrectangle_p_p.h \
     $$PWD/qquickwindow.h \
     $$PWD/qquickwindow_p.h \
-    $$PWD/qquickrendercontrol_p.h \
     $$PWD/qquickfocusscope_p.h \
     $$PWD/qquickitemsmodule_p.h \
     $$PWD/qquickpainteditem.h \
@@ -76,7 +75,9 @@ HEADERS += \
     $$PWD/qquickscreen_p.h \
     $$PWD/qquickwindowmodule_p.h \
     $$PWD/qquickframebufferobject.h \
-    $$PWD/qquickitemgrabresult.h
+    $$PWD/qquickitemgrabresult.h \
+    $$PWD/qquickrendercontrol.h \
+    $$PWD/qquickrendercontrol_p.h
 
 SOURCES += \
     $$PWD/qquickevents.cpp \
@@ -84,7 +85,6 @@ SOURCES += \
     $$PWD/qquickitem.cpp \
     $$PWD/qquickrectangle.cpp \
     $$PWD/qquickwindow.cpp \
-    $$PWD/qquickrendercontrol.cpp \
     $$PWD/qquickfocusscope.cpp \
     $$PWD/qquickitemsmodule.cpp \
     $$PWD/qquickpainteditem.cpp \
@@ -130,7 +130,8 @@ SOURCES += \
     $$PWD/qquickwindowmodule.cpp \
     $$PWD/qquickscreen.cpp \
     $$PWD/qquickframebufferobject.cpp \
-    $$PWD/qquickitemgrabresult.cpp
+    $$PWD/qquickitemgrabresult.cpp \
+    $$PWD/qquickrendercontrol.cpp
 
 SOURCES += \
     $$PWD/qquickshadereffect.cpp \
diff --git a/src/quick/items/qquickrendercontrol.cpp b/src/quick/items/qquickrendercontrol.cpp
index b8d572114aea0206ffd2265badb786003577e459..311a1b95f88f502065c8fb0c3ba80c2a5c65ca3f 100644
--- a/src/quick/items/qquickrendercontrol.cpp
+++ b/src/quick/items/qquickrendercontrol.cpp
@@ -1,6 +1,6 @@
 /****************************************************************************
 **
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
 ** Contact: http://www.qt-project.org/legal
 **
 ** This file is part of the QtQuick module of the Qt Toolkit.
@@ -39,6 +39,7 @@
 **
 ****************************************************************************/
 
+#include "qquickrendercontrol.h"
 #include "qquickrendercontrol_p.h"
 
 #include <QtCore/QCoreApplication>
@@ -53,7 +54,6 @@
 
 #include <QtQuick/QQuickWindow>
 #include <QtQuick/private/qquickwindow_p.h>
-#include <QtQuick/private/qsgcontext_p.h>
 #include <private/qqmlprofilerservice_p.h>
 #include <QtCore/private/qobject_p.h>
 
@@ -61,59 +61,139 @@ QT_BEGIN_NAMESPACE
 
 extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha);
 
-class QQuickRenderControlPrivate : public QObjectPrivate
-{
-public:
-    QQuickRenderControlPrivate()
-        : window(0)
-    {
-        sg = QSGContext::createDefaultContext();
-        rc = new QSGRenderContext(sg);
-    }
+/*!
+  \class QQuickRenderControl
 
-    ~QQuickRenderControlPrivate()
-     {
-         delete rc;
-         delete sg;
-     }
+  \brief The QQuickRenderControl class provides a mechanism for rendering the Qt
+  Quick scenegraph onto an offscreen render target in a fully
+  application-controlled manner.
 
-    QQuickWindow *window;
-    QSGContext *sg;
-    QSGRenderContext *rc;
-};
+  \since 5.4
 
-/*!
-  \class QQuickRenderControl
-  \brief The QQuickRenderControl class provides a mechanism for rendering the Qt Quick scenegraph.
+  QQuickWindow and QQuickView and their associated internal render loops render
+  the Qt Quick scene onto a native window. In some cases, for example when
+  integrating with 3rd party OpenGL renderers, it might be beneficial to get the
+  scene into a texture that can then be used in arbitrary ways by the external
+  rendering engine. QQuickRenderControl makes this possible in a hardware
+  accelerated manner, unlike the performance-wise limited alternative of using
+  QQuickWindow::grabWindow()
+
+  When using a QQuickRenderControl, the QQuickWindow does not have to be shown
+  or even created at all. This means there will not be an underlying native
+  window for it. Instead, the QQuickWindow instance is associated with the
+  render control, using the overload of the QQuickWindow constructor, and an
+  OpenGL framebuffer object by calling QQuickWindow::setRenderTarget().
+
+  Management of the context and framebuffer object is up to the application. The
+  context that will be used by Qt Quick must be created before calling
+  initialize(). The creation of the framebuffer object can be deferred, see
+  below. Qt 5.4 introduces the ability for QOpenGLContext to adopt existing
+  native contexts. Together with QQuickRenderControl this makes it possible to
+  create a QOpenGLContext that shares with an external rendering engine's
+  existing context. This new QOpenGLContext can then be used to render the Qt
+  Quick scene into a texture that is accessible by the other engine's context
+  too.
+
+  Loading and instantiation of the QML components happen by using a
+  QQmlEngine. Once the root object is created, it will need to be parented to
+  the QQuickWindow's contentItem().
+
+  Applications will usually have to connect to 4 important signals:
 
-  \internal
+  \list
+
+  \li QQuickWindow::sceneGraphInitialized() Emitted at some point after calling
+  QQuickRenderControl::initialize(). Upon this signal, the application is
+  expected to create its framebuffer object and associate it with the
+  QQuickWindow.
+
+  \li QQuickWindow::sceneGraphInvalidated() When the scenegraph resources are
+  released, the framebuffer object can be destroyed too.
+
+  \li QQuickRenderControl::renderRequested() Indicates that the scene has to be
+  rendered by calling render(). After making the context current, applications
+  are expected to call render().
+
+  \li QQuickRenderControl::sceneChanged() Inidcates that the scene has changed
+  meaning that, before rendering, polishing and synchronizing is also necessary.
+
+  \endlist
+
+  To send events, for example mouse or keyboard events, to the scene, use
+  QCoreApplication::sendEvent() with the QQuickWindow instance as the receiver.
 
   \inmodule QtQuick
 */
 
-QQuickRenderControl::QQuickRenderControl()
-    : QObject(*(new QQuickRenderControlPrivate), 0)
+QSGContext *QQuickRenderControlPrivate::sg = 0;
+
+QQuickRenderControlPrivate::QQuickRenderControlPrivate()
+    : initialized(0),
+      window(0)
 {
+    if (!sg) {
+        qAddPostRoutine(cleanup);
+        sg = QSGContext::createDefaultContext();
+    }
+    rc = new QSGRenderContext(sg);
 }
 
-QQuickRenderControl::~QQuickRenderControl()
+QQuickRenderControlPrivate::~QQuickRenderControlPrivate()
 {
+    delete rc;
 }
 
-void QQuickRenderControl::windowDestroyed()
+void QQuickRenderControlPrivate::cleanup()
+{
+    delete sg;
+    sg = 0;
+}
+
+QQuickRenderControl::QQuickRenderControl(QObject *parent)
+    : QObject(*(new QQuickRenderControlPrivate), parent)
+{
+}
+
+/*!
+  Destroys the instance. Releases all scenegraph resources.
+
+  \sa stop()
+ */
+QQuickRenderControl::~QQuickRenderControl()
 {
     Q_D(QQuickRenderControl);
-    if (d->window == 0) {
-        d->rc->invalidate();
+
+    stop();
+
+    if (d->window)
+        QQuickWindowPrivate::get(d->window)->renderControl = 0;
+}
+
+void QQuickRenderControlPrivate::windowDestroyed()
+{
+    if (window == 0) {
+        rc->invalidate();
         QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
     }
 }
 
+/*!
+  Initializes the scene graph resources. The context \a gl has to
+  be the current context.
+ */
 void QQuickRenderControl::initialize(QOpenGLContext *gl)
 {
     Q_D(QQuickRenderControl);
-    if (!d->window)
+
+    if (!d->window) {
+        qWarning("QQuickRenderControl::initialize called with no associated window");
+        return;
+    }
+
+    if (QOpenGLContext::currentContext() != gl) {
+        qWarning("QQuickRenderControl::initialize called with incorrect current context");
         return;
+    }
 
     // It is the caller's responsiblity to make a context/surface current.
     // It cannot be done here since the surface to use may not be the
@@ -121,17 +201,14 @@ void QQuickRenderControl::initialize(QOpenGLContext *gl)
     // window/surface at all.
 
     d->rc->initialize(gl);
-}
 
-void QQuickRenderControl::invalidate()
-{
-    Q_D(QQuickRenderControl);
-    d->rc->invalidate();
+    d->initialized = true;
 }
 
 /*!
   This function should be called as late as possible before
-  sync(). In a threaded scenario, rendering can happen in parallel with this function.
+  sync(). In a threaded scenario, rendering can happen in parallel
+  with this function.
  */
 void QQuickRenderControl::polishItems()
 {
@@ -147,9 +224,13 @@ void QQuickRenderControl::polishItems()
 }
 
 /*!
-  Synchronize GUI and scenegraph. Returns true if the scene graph was changed.
+  This function is used to synchronize the QML scene with the rendering scene
+  graph.
 
-  This function is a synchronization point. Rendering can not happen in parallel.
+  If a dedicated render thread is used, the GUI thread should be blocked for the
+  duration of this call.
+
+  \return \e true if the synchronization changed the scene graph.
  */
 bool QQuickRenderControl::sync()
 {
@@ -165,15 +246,36 @@ bool QQuickRenderControl::sync()
 }
 
 /*!
-  Stop rendering and release resources. This function is typically
-  called when the window is hidden. Requires a current context.
+  Stop rendering and release resources. Requires a current context.
+
+  This is the equivalent of the cleanup operations that happen with a
+  real QQuickWindow when the window becomes hidden.
+
+  This function takes QQuickWindow::persistentSceneGraph() into
+  account, meaning that context-specific resources are not released
+  when persistency is enabled.
+
+  This function is called from the destructor. Therefore there will
+  typically be no need to call it directly. Pay attention however to
+  the fact that this requires the context, that was passed to
+  initialize(), to be the current one at the time of destroying the
+  QQuickRenderControl instance.
+
+  Once stop() has been called, it is possible to reuse the
+  QQuickRenderControl instance by calling initialize() again.
  */
 void QQuickRenderControl::stop()
 {
     Q_D(QQuickRenderControl);
+    if (!d->initialized)
+        return;
+
     if (!d->window)
         return;
 
+    if (!QOpenGLContext::currentContext())
+        return;
+
     QQuickWindowPrivate *cd = QQuickWindowPrivate::get(d->window);
     cd->fireAboutToStop();
     cd->cleanupNodesOnShutdown();
@@ -182,10 +284,12 @@ void QQuickRenderControl::stop()
         d->rc->invalidate();
         QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
     }
+
+    d->initialized = false;
 }
 
 /*!
-  Render the scenegraph using the current context.
+  Renders the scenegraph using the current context.
  */
 void QQuickRenderControl::render()
 {
@@ -197,7 +301,6 @@ void QQuickRenderControl::render()
     cd->renderSceneGraph(d->window->size());
 }
 
-
 /*!
     \fn void QQuickRenderControl::renderRequested()
 
@@ -212,7 +315,9 @@ void QQuickRenderControl::render()
     true, then render() needs to be called.
 */
 
-
+/*!
+  Grabs the contents of the scene and returns it as an image.
+ */
 QImage QQuickRenderControl::grab()
 {
     Q_D(QQuickRenderControl);
@@ -224,47 +329,16 @@ QImage QQuickRenderControl::grab()
     return grabContent;
 }
 
-QSGContext *QQuickRenderControl::sceneGraphContext() const
-{
-    Q_D(const QQuickRenderControl);
-    return d->sg;
-}
-
-QSGRenderContext *QQuickRenderControl::renderContext(QSGContext *) const
+void QQuickRenderControlPrivate::update()
 {
-    Q_D(const QQuickRenderControl);
-    return d->rc;
+    Q_Q(QQuickRenderControl);
+    emit q->renderRequested();
 }
 
-void QQuickRenderControl::setWindow(QQuickWindow *window)
+void QQuickRenderControlPrivate::maybeUpdate()
 {
-    Q_D(QQuickRenderControl);
-    d->window = window;
-}
-
-/*!
-  Returns the offscreen window.
- */
-
-QQuickWindow *QQuickRenderControl::window() const
-{
-    Q_D(const QQuickRenderControl);
-    return d->window;
-}
-
-/*!
-  Create an offscreen QQuickWindow for this render control,
-  unless the render control already has a window().
-
-  Returns the offscreen window if one is created, otherwise returns null.
-  The caller takes ownership of the window, and is responsible for deleting it.
- */
-QQuickWindow *QQuickRenderControl::createOffscreenWindow()
-{
-    Q_D(QQuickRenderControl);
-    if (!d->window)
-        return new QQuickWindow(this);
-    return 0;
+    Q_Q(QQuickRenderControl);
+    emit q->sceneChanged();
 }
 
 /*!
@@ -284,7 +358,6 @@ QQuickWindow *QQuickRenderControl::createOffscreenWindow()
   inside its window.
 
  */
-
 QWindow *QQuickRenderControl::renderWindowFor(QQuickWindow *win, QPoint *offset)
 {
     if (!win)
@@ -295,6 +368,4 @@ QWindow *QQuickRenderControl::renderWindowFor(QQuickWindow *win, QPoint *offset)
     return 0;
 }
 
-
-
 QT_END_NAMESPACE
diff --git a/src/quick/items/qquickrendercontrol.h b/src/quick/items/qquickrendercontrol.h
new file mode 100644
index 0000000000000000000000000000000000000000..e5c04fee2352fafa3886bd7318539deee62e7604
--- /dev/null
+++ b/src/quick/items/qquickrendercontrol.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKRENDERCONTROL_H
+#define QQUICKRENDERCONTROL_H
+
+#include <QtQuick/qtquickglobal.h>
+#include <QtGui/QImage>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickWindow;
+class QOpenGLContext;
+class QQuickRenderControlPrivate;
+
+class Q_QUICK_EXPORT QQuickRenderControl : public QObject
+{
+    Q_OBJECT
+
+public:
+    QQuickRenderControl(QObject *parent = 0);
+    ~QQuickRenderControl();
+
+    void initialize(QOpenGLContext *gl);
+    void stop();
+
+    void polishItems();
+    void render();
+    bool sync();
+
+    QImage grab();
+
+    static QWindow *renderWindowFor(QQuickWindow *win, QPoint *offset = 0);
+    virtual QWindow *renderWindow(QPoint *offset) { Q_UNUSED(offset); return 0; }
+
+Q_SIGNALS:
+    void renderRequested();
+    void sceneChanged();
+
+private:
+    Q_DECLARE_PRIVATE(QQuickRenderControl)
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKRENDERCONTROL_H
diff --git a/src/quick/items/qquickrendercontrol_p.h b/src/quick/items/qquickrendercontrol_p.h
index cc30e37724cfa4a682fd4327921b73b83d4a6273..18b1b370b3963642912fa6b08b0af9a696370417 100644
--- a/src/quick/items/qquickrendercontrol_p.h
+++ b/src/quick/items/qquickrendercontrol_p.h
@@ -1,6 +1,6 @@
 /****************************************************************************
 **
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
 ** Contact: http://www.qt-project.org/legal
 **
 ** This file is part of the QtQuick module of the Qt Toolkit.
@@ -42,55 +42,45 @@
 #ifndef QQUICKRENDERCONTROL_P_H
 #define QQUICKRENDERCONTROL_P_H
 
-#include <QtGui/QImage>
-#include <private/qtquickglobal_p.h>
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the Qt API.  It exists purely as an
+// implementation detail.  This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
 
-QT_BEGIN_NAMESPACE
+#include "qquickrendercontrol.h"
+#include <QtQuick/private/qsgcontext_p.h>
 
-class QQuickWindow;
-class QSGContext;
-class QSGRenderContext;
-class QAnimationDriver;
-class QOpenGLContext;
-class QQuickRenderControlPrivate;
+QT_BEGIN_NAMESPACE
 
-class Q_QUICK_PRIVATE_EXPORT QQuickRenderControl : public QObject
+class QQuickRenderControlPrivate : public QObjectPrivate
 {
-    Q_OBJECT
-    Q_DECLARE_PRIVATE(QQuickRenderControl)
 public:
-    QQuickRenderControl();
-    ~QQuickRenderControl();
+    Q_DECLARE_PUBLIC(QQuickRenderControl)
 
-    QQuickWindow *window() const;
-    QQuickWindow *createOffscreenWindow();
-    virtual QWindow *renderWindow(QPoint *offset) { Q_UNUSED(offset); return 0; }
-    static QWindow *renderWindowFor(QQuickWindow *win, QPoint *offset = 0);
+    QQuickRenderControlPrivate();
+    ~QQuickRenderControlPrivate();
 
-    void windowDestroyed();
+    static QQuickRenderControlPrivate *get(QQuickRenderControl *renderControl) {
+        return renderControl->d_func();
+    }
 
-    void initialize(QOpenGLContext *gl);
-    void invalidate();
-    void polishItems();
-    void render();
-    bool sync();
-    void stop();
+    static void cleanup();
 
-    QImage grab();
-
-Q_SIGNALS:
-    void renderRequested();
-    void sceneChanged();
+    void windowDestroyed();
 
-private:
-    friend class QQuickWindowPrivate;
-    friend class QQuickWindow;
-    void setWindow(QQuickWindow *window);
-    inline void update() { /*emit*/ renderRequested(); }
-    inline void maybeUpdate() { /*emit*/ sceneChanged(); }
+    void update();
+    void maybeUpdate();
 
-    QSGContext *sceneGraphContext() const;
-    QSGRenderContext *renderContext(QSGContext *) const;
+    bool initialized;
+    QQuickWindow *window;
+    static QSGContext *sg;
+    QSGRenderContext *rc;
 };
 
 QT_END_NAMESPACE
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 82897b3f5e420df8ed05907ebc0bfbc5e49c1bb7..de8eb115dc0762040f65ebbd5188534de5ca1449 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -287,7 +287,7 @@ void QQuickWindow::update()
     if (d->windowManager)
         d->windowManager->update(this);
     else if (d->renderControl)
-        d->renderControl->update();
+        QQuickRenderControlPrivate::get(d->renderControl)->update();
 }
 
 void forcePolishHelper(QQuickItem *item)
@@ -438,7 +438,7 @@ void QQuickWindowPrivate::init(QQuickWindow *c, QQuickRenderControl *control)
     customRenderMode = qgetenv("QSG_VISUALIZE");
     renderControl = control;
     if (renderControl)
-        renderControl->setWindow(q);
+        QQuickRenderControlPrivate::get(renderControl)->window = q;
 
     if (!renderControl)
         windowManager = QSGRenderLoop::instance();
@@ -447,8 +447,9 @@ void QQuickWindowPrivate::init(QQuickWindow *c, QQuickRenderControl *control)
 
     QSGContext *sg;
     if (renderControl) {
-        sg = renderControl->sceneGraphContext();
-        context = renderControl->renderContext(sg);
+        QQuickRenderControlPrivate *renderControlPriv = QQuickRenderControlPrivate::get(renderControl);
+        sg = renderControlPriv->sg;
+        context = renderControlPriv->rc;
     } else {
         windowManager->addWindow(q);
         sg = windowManager->sceneGraphContext();
@@ -1087,7 +1088,7 @@ QQuickWindow::~QQuickWindow()
 
     d->animationController->deleteLater();
     if (d->renderControl) {
-        d->renderControl->windowDestroyed();
+        QQuickRenderControlPrivate::get(d->renderControl)->windowDestroyed();
     } else if (d->windowManager) {
         d->windowManager->removeWindow(this);
         d->windowManager->windowDestroyed(this);
@@ -1125,8 +1126,9 @@ void QQuickWindow::releaseResources()
 
 
 /*!
-    Sets whether the OpenGL context can be released to \a
-    persistent. The default value is true.
+    Sets whether the OpenGL context should be preserved, and cannot be
+    released until the last window is deleted, to \a persistent. The
+    default value is true.
 
     The OpenGL context can be released to free up graphics resources
     when the window is obscured, hidden or not rendering. When this
@@ -2798,7 +2800,7 @@ void QQuickWindow::maybeUpdate()
 {
     Q_D(QQuickWindow);
     if (d->renderControl)
-        d->renderControl->maybeUpdate();
+        QQuickRenderControlPrivate::get(d->renderControl)->maybeUpdate();
     else if (d->windowManager)
         d->windowManager->maybeUpdate(this);
 }
diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h
index c95ec5b46d550e34511a3b900febb2715c866037..4ed663ee6ee7298cc0659c64cc59780f97ef0679 100644
--- a/src/quick/items/qquickwindow.h
+++ b/src/quick/items/qquickwindow.h
@@ -87,6 +87,7 @@ public:
     Q_ENUMS(SceneGraphError)
 
     QQuickWindow(QWindow *parent = 0);
+    explicit QQuickWindow(QQuickRenderControl *renderControl);
 
     virtual ~QQuickWindow();
 
@@ -201,7 +202,6 @@ private:
     friend class QQuickWidget;
     friend class QQuickRenderControl;
     friend class QQuickAnimatorController;
-    explicit QQuickWindow(QQuickRenderControl*);
     Q_DISABLE_COPY(QQuickWindow)
 };
 
diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp
index f91d512ab06a220e4907d7f24fd31e042a49e84e..dc6b872fb28e3c6007ddc0cc208312cc95476869 100644
--- a/src/quickwidgets/qquickwidget.cpp
+++ b/src/quickwidgets/qquickwidget.cpp
@@ -72,7 +72,7 @@ class QQuickWidgetRenderControl : public QQuickRenderControl
 {
 public:
     QQuickWidgetRenderControl(QQuickWidget *quickwidget) : m_quickWidget(quickwidget) {}
-    QWindow *renderWindow(QPoint *offset) {
+    QWindow *renderWindow(QPoint *offset) Q_DECL_OVERRIDE {
         if (offset)
             *offset = m_quickWidget->mapTo(m_quickWidget->window(), QPoint());
         return m_quickWidget->window()->windowHandle();
@@ -86,7 +86,7 @@ void QQuickWidgetPrivate::init(QQmlEngine* e)
     Q_Q(QQuickWidget);
 
     renderControl = new QQuickWidgetRenderControl(q);
-    offscreenWindow = renderControl->createOffscreenWindow();
+    offscreenWindow = new QQuickWindow(renderControl);
     offscreenWindow->setTitle(QString::fromLatin1("Offscreen"));
     // Do not call create() on offscreenWindow.
 
@@ -162,8 +162,8 @@ QQuickWidgetPrivate::~QQuickWidgetPrivate()
 
     // context and offscreenSurface are current at this stage, if the context was created.
     Q_ASSERT(!context || (QOpenGLContext::currentContext() == context && context->surface() == offscreenSurface));
+    delete renderControl; // always delete the rendercontrol first
     delete offscreenWindow;
-    delete renderControl;
     delete resolvedFbo;
     delete fbo;
 
@@ -877,7 +877,7 @@ void QQuickWidget::resizeEvent(QResizeEvent *e)
 
     d->createContext();
     createFramebufferObject();
-    d->offscreenWindow->resizeEvent(e);
+    QCoreApplication::sendEvent(d->offscreenWindow, e);
     d->offscreenWindow->setGeometry(0, 0, e->size().width(), e->size().height());
 
     QOpenGLContext *context = d->offscreenWindow->openglContext();
@@ -898,7 +898,7 @@ void QQuickWidget::keyPressEvent(QKeyEvent *e)
     Q_D(QQuickWidget);
     Q_QUICK_PROFILE(addEvent<QQuickProfiler::Key>());
 
-    d->offscreenWindow->keyPressEvent(e);
+    QCoreApplication::sendEvent(d->offscreenWindow, e);
 }
 
 /*! \reimp */
@@ -907,7 +907,7 @@ void QQuickWidget::keyReleaseEvent(QKeyEvent *e)
     Q_D(QQuickWidget);
     Q_QUICK_PROFILE(addEvent<QQuickProfiler::Key>());
 
-    d->offscreenWindow->keyReleaseEvent(e);
+    QCoreApplication::sendEvent(d->offscreenWindow, e);
 }
 
 /*! \reimp */
@@ -921,7 +921,7 @@ void QQuickWidget::mouseMoveEvent(QMouseEvent *e)
     // the windowPos in e is ignored and is replaced by localPos. This is necessary
     // because QQuickWindow thinks of itself as a top-level window always.
     QMouseEvent mappedEvent(e->type(), e->localPos(), e->screenPos(), e->button(), e->buttons(), e->modifiers());
-    d->offscreenWindow->mouseMoveEvent(&mappedEvent);
+    QCoreApplication::sendEvent(d->offscreenWindow, &mappedEvent);
 }
 
 /*! \reimp */
@@ -934,10 +934,10 @@ void QQuickWidget::mouseDoubleClickEvent(QMouseEvent *e)
     // See QTBUG-25831
     QMouseEvent pressEvent(QEvent::MouseButtonPress, e->localPos(), e->screenPos(), e->button(),
                            e->buttons(), e->modifiers());
-    d->offscreenWindow->mousePressEvent(&pressEvent);
+    QCoreApplication::sendEvent(d->offscreenWindow, &pressEvent);
     QMouseEvent mappedEvent(e->type(), e->localPos(), e->screenPos(), e->button(), e->buttons(),
                             e->modifiers());
-    d->offscreenWindow->mouseDoubleClickEvent(&mappedEvent);
+    QCoreApplication::sendEvent(d->offscreenWindow, &mappedEvent);
 }
 
 /*! \reimp */
@@ -963,7 +963,7 @@ void QQuickWidget::mousePressEvent(QMouseEvent *e)
     Q_QUICK_PROFILE(addEvent<QQuickProfiler::Mouse>());
 
     QMouseEvent mappedEvent(e->type(), e->localPos(), e->screenPos(), e->button(), e->buttons(), e->modifiers());
-    d->offscreenWindow->mousePressEvent(&mappedEvent);
+    QCoreApplication::sendEvent(d->offscreenWindow, &mappedEvent);
 }
 
 /*! \reimp */
@@ -973,7 +973,7 @@ void QQuickWidget::mouseReleaseEvent(QMouseEvent *e)
     Q_QUICK_PROFILE(addEvent<QQuickProfiler::Mouse>());
 
     QMouseEvent mappedEvent(e->type(), e->localPos(), e->screenPos(), e->button(), e->buttons(), e->modifiers());
-    d->offscreenWindow->mouseReleaseEvent(&mappedEvent);
+    QCoreApplication::sendEvent(d->offscreenWindow, &mappedEvent);
 }
 
 #ifndef QT_NO_WHEELEVENT
@@ -984,7 +984,7 @@ void QQuickWidget::wheelEvent(QWheelEvent *e)
     Q_QUICK_PROFILE(addEvent<QQuickProfiler::Mouse>());
 
     // Wheel events only have local and global positions, no need to map.
-    d->offscreenWindow->wheelEvent(e);
+    QCoreApplication::sendEvent(d->offscreenWindow, e);
 }
 #endif
 
@@ -1027,7 +1027,8 @@ bool QQuickWidget::event(QEvent *e)
     case QEvent::TouchUpdate:
     case QEvent::TouchCancel:
         // Touch events only have local and global positions, no need to map.
-        return d->offscreenWindow->event(e);
+        return QCoreApplication::sendEvent(d->offscreenWindow, e);
+
     case QEvent::WindowChangeInternal:
         d->handleWindowChange();
         break;