diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
index e68b001ad19e4ccbd18ad05cd210a8c13a5ca591..4119dfb5307bfcec050e8b8b91ef25a2e5d84b49 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
@@ -750,11 +750,14 @@ Renderer::Renderer(QSGRenderContext *ctx)
     , m_renderOrderRebuildUpper(-1)
     , m_currentMaterial(0)
     , m_currentShader(0)
+    , m_currentStencilValue(0)
+    , m_clipMatrixId(0)
     , m_currentClip(0)
     , m_currentClipType(NoClip)
     , m_vao(0)
     , m_visualizeMode(VisualizeNothing)
 {
+    initializeOpenGLFunctions();
     setNodeUpdater(new Updater(this));
 
     m_shaderManager = ctx->findChild<ShaderManager *>(QStringLiteral("__qt_ShaderManager"), Qt::FindDirectChildrenOnly);
@@ -1912,6 +1915,132 @@ void Renderer::uploadBatch(Batch *b)
             b->uploadedThisFrame = true;
 }
 
+/*!
+ * Convenience function to set up the stencil buffer for clipping based on \a clip.
+ *
+ * If the clip is a pixel aligned rectangle, this function will use glScissor instead
+ * of stencil.
+ */
+Renderer::ClipType Renderer::updateStencilClip(const QSGClipNode *clip)
+{
+    if (!clip) {
+        glDisable(GL_STENCIL_TEST);
+        glDisable(GL_SCISSOR_TEST);
+        return NoClip;
+    }
+
+    ClipType clipType = NoClip;
+
+    glDisable(GL_SCISSOR_TEST);
+
+    m_currentStencilValue = 0;
+    m_currentScissorRect = QRect();
+    while (clip) {
+        QMatrix4x4 m = m_current_projection_matrix;
+        if (clip->matrix())
+            m *= *clip->matrix();
+
+        // TODO: Check for multisampling and pixel grid alignment.
+        bool isRectangleWithNoPerspective = clip->isRectangular()
+                && qFuzzyIsNull(m(3, 0)) && qFuzzyIsNull(m(3, 1));
+        bool noRotate = qFuzzyIsNull(m(0, 1)) && qFuzzyIsNull(m(1, 0));
+        bool isRotate90 = qFuzzyIsNull(m(0, 0)) && qFuzzyIsNull(m(1, 1));
+
+        if (isRectangleWithNoPerspective && (noRotate || isRotate90)) {
+            QRectF bbox = clip->clipRect();
+            qreal invW = 1 / m(3, 3);
+            qreal fx1, fy1, fx2, fy2;
+            if (noRotate) {
+                fx1 = (bbox.left() * m(0, 0) + m(0, 3)) * invW;
+                fy1 = (bbox.bottom() * m(1, 1) + m(1, 3)) * invW;
+                fx2 = (bbox.right() * m(0, 0) + m(0, 3)) * invW;
+                fy2 = (bbox.top() * m(1, 1) + m(1, 3)) * invW;
+            } else {
+                Q_ASSERT(isRotate90);
+                fx1 = (bbox.bottom() * m(0, 1) + m(0, 3)) * invW;
+                fy1 = (bbox.left() * m(1, 0) + m(1, 3)) * invW;
+                fx2 = (bbox.top() * m(0, 1) + m(0, 3)) * invW;
+                fy2 = (bbox.right() * m(1, 0) + m(1, 3)) * invW;
+            }
+
+            if (fx1 > fx2)
+                qSwap(fx1, fx2);
+            if (fy1 > fy2)
+                qSwap(fy1, fy2);
+
+            QRect deviceRect = this->deviceRect();
+
+            GLint ix1 = qRound((fx1 + 1) * deviceRect.width() * qreal(0.5));
+            GLint iy1 = qRound((fy1 + 1) * deviceRect.height() * qreal(0.5));
+            GLint ix2 = qRound((fx2 + 1) * deviceRect.width() * qreal(0.5));
+            GLint iy2 = qRound((fy2 + 1) * deviceRect.height() * qreal(0.5));
+
+            if (!(clipType & ScissorClip)) {
+                m_currentScissorRect = QRect(ix1, iy1, ix2 - ix1, iy2 - iy1);
+                glEnable(GL_SCISSOR_TEST);
+                clipType |= ScissorClip;
+            } else {
+                m_currentScissorRect &= QRect(ix1, iy1, ix2 - ix1, iy2 - iy1);
+            }
+            glScissor(m_currentScissorRect.x(), m_currentScissorRect.y(),
+                      m_currentScissorRect.width(), m_currentScissorRect.height());
+        } else {
+            if (!(clipType & StencilClip)) {
+                if (!m_clipProgram.isLinked()) {
+                    QSGShaderSourceBuilder::initializeProgramFromFiles(
+                        &m_clipProgram,
+                        QStringLiteral(":/scenegraph/shaders/stencilclip.vert"),
+                        QStringLiteral(":/scenegraph/shaders/stencilclip.frag"));
+                    m_clipProgram.bindAttributeLocation("vCoord", 0);
+                    m_clipProgram.link();
+                    m_clipMatrixId = m_clipProgram.uniformLocation("matrix");
+                }
+
+                glClearStencil(0);
+                glClear(GL_STENCIL_BUFFER_BIT);
+                glEnable(GL_STENCIL_TEST);
+                glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+                glDepthMask(GL_FALSE);
+
+                m_clipProgram.bind();
+                m_clipProgram.enableAttributeArray(0);
+
+                clipType |= StencilClip;
+            }
+
+            glStencilFunc(GL_EQUAL, m_currentStencilValue, 0xff); // stencil test, ref, test mask
+            glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); // stencil fail, z fail, z pass
+
+            const QSGGeometry *g = clip->geometry();
+            Q_ASSERT(g->attributeCount() > 0);
+            const QSGGeometry::Attribute *a = g->attributes();
+            glVertexAttribPointer(0, a->tupleSize, a->type, GL_FALSE, g->sizeOfVertex(), g->vertexData());
+
+            m_clipProgram.setUniformValue(m_clipMatrixId, m);
+            if (g->indexCount()) {
+                glDrawElements(g->drawingMode(), g->indexCount(), g->indexType(), g->indexData());
+            } else {
+                glDrawArrays(g->drawingMode(), 0, g->vertexCount());
+            }
+
+            ++m_currentStencilValue;
+        }
+
+        clip = clip->clipList();
+    }
+
+    if (clipType & StencilClip) {
+        m_clipProgram.disableAttributeArray(0);
+        glStencilFunc(GL_EQUAL, m_currentStencilValue, 0xff); // stencil test, ref, test mask
+        glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // stencil fail, z fail, z pass
+        bindable()->reactivate();
+    } else {
+        glDisable(GL_STENCIL_TEST);
+    }
+
+    return clipType;
+}
+
 void Renderer::updateClip(const QSGClipNode *clipList, const Batch *batch)
 {
     if (clipList != m_currentClip && Q_LIKELY(!debug_noclip)) {
@@ -2485,8 +2614,8 @@ void Renderer::renderRenderNode(Batch *batch)
     state.projectionMatrix = &pm;
     state.scissorEnabled = m_currentClipType & ScissorClip;
     state.stencilEnabled = m_currentClipType & StencilClip;
-    state.scissorRect = m_current_scissor_rect;
-    state.stencilValue = m_current_stencil_value;
+    state.scissorRect = m_currentScissorRect;
+    state.stencilValue = m_currentStencilValue;
 
     QSGNode *xform = e->renderNode->parent();
     QMatrix4x4 matrix;
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
index 89a33cb8c474b741aac6be2ef7aac22b28a3de06..574c6df810400e1db305e3e318eddb418e5be6e9 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
@@ -406,7 +406,7 @@ public:
     QSGRenderContext *context;
 };
 
-class Q_QUICK_PRIVATE_EXPORT Renderer : public QSGRenderer
+class Q_QUICK_PRIVATE_EXPORT Renderer : public QSGRenderer, public QOpenGLFunctions
 {
 public:
     Renderer(QSGRenderContext *);
@@ -426,6 +426,14 @@ protected:
     void render();
 
 private:
+    enum ClipTypeBit
+    {
+        NoClip = 0x00,
+        ScissorClip = 0x01,
+        StencilClip = 0x02
+    };
+    Q_DECLARE_FLAGS(ClipType, ClipTypeBit)
+
     enum RebuildFlag {
         BuildRenderListsForTaggedRoots      = 0x0001,
         BuildRenderLists                    = 0x0002,
@@ -457,6 +465,7 @@ private:
     void renderBatches();
     void renderMergedBatch(const Batch *batch);
     void renderUnmergedBatch(const Batch *batch);
+    ClipType updateStencilClip(const QSGClipNode *clip);
     void updateClip(const QSGClipNode *clipList, const Batch *batch);
     const QMatrix4x4 &matrixForRoot(Node *node);
     void renderRenderNode(Batch *batch);
@@ -518,6 +527,11 @@ private:
     QSGMaterial *m_currentMaterial;
     QSGMaterialShader *m_currentProgram;
     ShaderManager::Shader *m_currentShader;
+
+    QRect m_currentScissorRect;
+    int m_currentStencilValue;
+    QOpenGLShaderProgram m_clipProgram;
+    int m_clipMatrixId;
     const QSGClipNode *m_currentClip;
     ClipType m_currentClipType;
 
diff --git a/src/quick/scenegraph/coreapi/qsgrenderer.cpp b/src/quick/scenegraph/coreapi/qsgrenderer.cpp
index 23afba368fbf771bb13b7d165a75a3fc53e80450..c05650772972972895665915e64977a07e97c49f 100644
--- a/src/quick/scenegraph/coreapi/qsgrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgrenderer.cpp
@@ -48,7 +48,6 @@
 #include <private/qsgadaptationlayer_p.h>
 #include <private/qsgshadersourcebuilder_p.h>
 
-#include <QOpenGLShaderProgram>
 #include <qopenglframebufferobject.h>
 #include <QtGui/qguiapplication.h>
 
@@ -125,7 +124,6 @@ QSGRenderer::QSGRenderer(QSGRenderContext *context)
     , m_current_opacity(1)
     , m_current_determinant(1)
     , m_device_pixel_ratio(1)
-    , m_current_stencil_value(0)
     , m_context(context)
     , m_root_node(0)
     , m_node_updater(0)
@@ -134,7 +132,6 @@ QSGRenderer::QSGRenderer(QSGRenderContext *context)
     , m_mirrored(false)
     , m_is_rendering(false)
 {
-    initializeOpenGLFunctions();
 }
 
 
@@ -224,10 +221,10 @@ void QSGRenderer::renderScene(const QSGBindable &bindable)
     // Sanity check that attribute registers are disabled
     if (qsg_sanity_check) {
         GLint count = 0;
-        glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &count);
+        QOpenGLContext::currentContext()->functions()->glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &count);
         GLint enabled;
         for (int i=0; i<count; ++i) {
-            glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &enabled);
+            QOpenGLContext::currentContext()->functions()->glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &enabled);
             if (enabled) {
                 qWarning("QSGRenderer: attribute %d is enabled, this can lead to memory corruption and crashes.", i);
             }
@@ -238,7 +235,6 @@ void QSGRenderer::renderScene(const QSGBindable &bindable)
     if (profileFrames)
         renderTime = frameTimer.nsecsElapsed();
 
-    glDisable(GL_SCISSOR_TEST);
     m_is_rendering = false;
     m_changed_emitted = false;
     m_bindable = 0;
@@ -355,133 +351,6 @@ void QSGRenderer::removeNodesToPreprocess(QSGNode *node)
 }
 
 
-/*!
-    Convenience function to set up the stencil buffer for clipping based on \a clip.
-
-    If the clip is a pixel aligned rectangle, this function will use glScissor instead
-    of stencil.
- */
-
-QSGRenderer::ClipType QSGRenderer::updateStencilClip(const QSGClipNode *clip)
-{
-    if (!clip) {
-        glDisable(GL_STENCIL_TEST);
-        glDisable(GL_SCISSOR_TEST);
-        return NoClip;
-    }
-
-    ClipType clipType = NoClip;
-
-    glDisable(GL_SCISSOR_TEST);
-
-    m_current_stencil_value = 0;
-    m_current_scissor_rect = QRect();
-    while (clip) {
-        QMatrix4x4 m = m_current_projection_matrix;
-        if (clip->matrix())
-            m *= *clip->matrix();
-
-        // TODO: Check for multisampling and pixel grid alignment.
-        bool isRectangleWithNoPerspective = clip->isRectangular()
-                && qFuzzyIsNull(m(3, 0)) && qFuzzyIsNull(m(3, 1));
-        bool noRotate = qFuzzyIsNull(m(0, 1)) && qFuzzyIsNull(m(1, 0));
-        bool isRotate90 = qFuzzyIsNull(m(0, 0)) && qFuzzyIsNull(m(1, 1));
-
-        if (isRectangleWithNoPerspective && (noRotate || isRotate90)) {
-            QRectF bbox = clip->clipRect();
-            qreal invW = 1 / m(3, 3);
-            qreal fx1, fy1, fx2, fy2;
-            if (noRotate) {
-                fx1 = (bbox.left() * m(0, 0) + m(0, 3)) * invW;
-                fy1 = (bbox.bottom() * m(1, 1) + m(1, 3)) * invW;
-                fx2 = (bbox.right() * m(0, 0) + m(0, 3)) * invW;
-                fy2 = (bbox.top() * m(1, 1) + m(1, 3)) * invW;
-            } else {
-                Q_ASSERT(isRotate90);
-                fx1 = (bbox.bottom() * m(0, 1) + m(0, 3)) * invW;
-                fy1 = (bbox.left() * m(1, 0) + m(1, 3)) * invW;
-                fx2 = (bbox.top() * m(0, 1) + m(0, 3)) * invW;
-                fy2 = (bbox.right() * m(1, 0) + m(1, 3)) * invW;
-            }
-
-            if (fx1 > fx2)
-                qSwap(fx1, fx2);
-            if (fy1 > fy2)
-                qSwap(fy1, fy2);
-
-            GLint ix1 = qRound((fx1 + 1) * m_device_rect.width() * qreal(0.5));
-            GLint iy1 = qRound((fy1 + 1) * m_device_rect.height() * qreal(0.5));
-            GLint ix2 = qRound((fx2 + 1) * m_device_rect.width() * qreal(0.5));
-            GLint iy2 = qRound((fy2 + 1) * m_device_rect.height() * qreal(0.5));
-
-            if (!(clipType & ScissorClip)) {
-                m_current_scissor_rect = QRect(ix1, iy1, ix2 - ix1, iy2 - iy1);
-                glEnable(GL_SCISSOR_TEST);
-                clipType |= ScissorClip;
-            } else {
-                m_current_scissor_rect &= QRect(ix1, iy1, ix2 - ix1, iy2 - iy1);
-            }
-            glScissor(m_current_scissor_rect.x(), m_current_scissor_rect.y(),
-                      m_current_scissor_rect.width(), m_current_scissor_rect.height());
-        } else {
-            if (!(clipType & StencilClip)) {
-                if (!m_clip_program.isLinked()) {
-                    QSGShaderSourceBuilder::initializeProgramFromFiles(
-                        &m_clip_program,
-                        QStringLiteral(":/scenegraph/shaders/stencilclip.vert"),
-                        QStringLiteral(":/scenegraph/shaders/stencilclip.frag"));
-                    m_clip_program.bindAttributeLocation("vCoord", 0);
-                    m_clip_program.link();
-                    m_clip_matrix_id = m_clip_program.uniformLocation("matrix");
-                }
-
-                glClearStencil(0);
-                glClear(GL_STENCIL_BUFFER_BIT);
-                glEnable(GL_STENCIL_TEST);
-                glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
-                glDepthMask(GL_FALSE);
-
-                m_clip_program.bind();
-                m_clip_program.enableAttributeArray(0);
-
-                clipType |= StencilClip;
-            }
-
-            glStencilFunc(GL_EQUAL, m_current_stencil_value, 0xff); // stencil test, ref, test mask
-            glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); // stencil fail, z fail, z pass
-
-            const QSGGeometry *g = clip->geometry();
-            Q_ASSERT(g->attributeCount() > 0);
-            const QSGGeometry::Attribute *a = g->attributes();
-            glVertexAttribPointer(0, a->tupleSize, a->type, GL_FALSE, g->sizeOfVertex(), g->vertexData());
-
-            m_clip_program.setUniformValue(m_clip_matrix_id, m);
-            if (g->indexCount()) {
-                glDrawElements(g->drawingMode(), g->indexCount(), g->indexType(), g->indexData());
-            } else {
-                glDrawArrays(g->drawingMode(), 0, g->vertexCount());
-            }
-
-            ++m_current_stencil_value;
-        }
-
-        clip = clip->clipList();
-    }
-
-    if (clipType & StencilClip) {
-        m_clip_program.disableAttributeArray(0);
-        glStencilFunc(GL_EQUAL, m_current_stencil_value, 0xff); // stencil test, ref, test mask
-        glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // stencil fail, z fail, z pass
-        bindable()->reactivate();
-    } else {
-        glDisable(GL_STENCIL_TEST);
-    }
-
-    return clipType;
-}
-
-
-
 /*!
     \class QSGNodeDumper
     \brief The QSGNodeDumper class provides a way of dumping a scene grahp to the console.
diff --git a/src/quick/scenegraph/coreapi/qsgrenderer_p.h b/src/quick/scenegraph/coreapi/qsgrenderer_p.h
index f0cd06abe908e04746c3dfbc390986d78fcb85a8..e24a6b652f96cc600dafccbed69ea77e682579da 100644
--- a/src/quick/scenegraph/coreapi/qsgrenderer_p.h
+++ b/src/quick/scenegraph/coreapi/qsgrenderer_p.h
@@ -42,13 +42,10 @@
 #ifndef QSGRENDERER_P_H
 #define QSGRENDERER_P_H
 
+#include <qcolor.h>
 #include <qset.h>
 #include <qhash.h>
 
-#include <qcolor.h>
-#include <qopenglfunctions.h>
-#include <qopenglshaderprogram.h>
-
 #include "qsgnode.h"
 #include "qsgmaterial.h"
 #include <QtQuick/qsgtexture.h>
@@ -67,18 +64,10 @@ class QSGNodeUpdater;
 Q_QUICK_PRIVATE_EXPORT bool qsg_test_and_clear_fatal_render_error();
 Q_QUICK_PRIVATE_EXPORT void qsg_set_fatal_renderer_error();
 
-class Q_QUICK_PRIVATE_EXPORT QSGRenderer : public QObject, public QOpenGLFunctions
+class Q_QUICK_PRIVATE_EXPORT QSGRenderer : public QObject
 {
     Q_OBJECT
 public:
-    enum ClipTypeBit
-    {
-        NoClip = 0x00,
-        ScissorClip = 0x01,
-        StencilClip = 0x02
-    };
-    Q_DECLARE_FLAGS(ClipType, ClipTypeBit)
-
     enum ClearModeBit
     {
         ClearColorBuffer    = 0x0001,
@@ -142,7 +131,6 @@ Q_SIGNALS:
 
 protected:
     virtual void render() = 0;
-    QSGRenderer::ClipType updateStencilClip(const QSGClipNode *clip);
 
     const QSGBindable *bindable() const { return m_bindable; }
 
@@ -160,8 +148,6 @@ protected:
     qreal m_current_opacity;
     qreal m_current_determinant;
     qreal m_device_pixel_ratio;
-    QRect m_current_scissor_rect;
-    int m_current_stencil_value;
 
     QSGRenderContext *m_context;
 
@@ -175,8 +161,6 @@ private:
     QSet<QSGNode *> m_nodes_to_preprocess;
 
     QMatrix4x4 m_projection_matrix;
-    QOpenGLShaderProgram m_clip_program;
-    int m_clip_matrix_id;
 
     const QSGBindable *m_bindable;