diff --git a/examples/quick/shared/shared.h b/examples/quick/shared/shared.h
index 1376459ae79a6ed43f744be16024006a892d21ef..d2f7c98311bfeb734aeaba04c34d990b94a49649 100644
--- a/examples/quick/shared/shared.h
+++ b/examples/quick/shared/shared.h
@@ -49,6 +49,12 @@
     app.setOrganizationDomain("qt-project.org");\
     app.setApplicationName(QFileInfo(app.applicationFilePath()).baseName());\
     QQuickView view;\
+    if (qgetenv("QT_QUICK_CORE_PROFILE").toInt()) {\
+        QSurfaceFormat f = view.format();\
+        f.setProfile(QSurfaceFormat::CoreProfile);\
+        f.setVersion(4, 4);\
+        view.setFormat(f);\
+    }\
     view.connect(view.engine(), SIGNAL(quit()), &app, SLOT(quit()));\
     new QQmlFileSelector(view.engine(), &view);\
     view.setSource(QUrl("qrc:///" #NAME ".qml")); \
diff --git a/src/particles/particles.pri b/src/particles/particles.pri
index b391050a58b701032e52026f25497b161e0459eb..af71634ec63bb5e6fc32f04f126c3d4a04d1ec7c 100644
--- a/src/particles/particles.pri
+++ b/src/particles/particles.pri
@@ -68,7 +68,12 @@ OTHER_FILES += \
     $$PWD/shaders/customparticle.vert \
     $$PWD/shaders/customparticle.frag \
     $$PWD/shaders/imageparticle.vert \
-    $$PWD/shaders/imageparticle.frag
+    $$PWD/shaders/imageparticle.frag \
+    $$PWD/shaders/customparticletemplate_core.vert \
+    $$PWD/shaders/customparticle_core.vert \
+    $$PWD/shaders/customparticle_core.frag \
+    $$PWD/shaders/imageparticle_core.vert \
+    $$PWD/shaders/imageparticle_core.frag
 
 RESOURCES += \
     $$PWD/particles.qrc
diff --git a/src/particles/particles.qrc b/src/particles/particles.qrc
index 689a5fb4e9444150934ec70f9e44d80e9892f690..ad44cf406ee429b57a9408040048be8d12eb1e65 100644
--- a/src/particles/particles.qrc
+++ b/src/particles/particles.qrc
@@ -11,5 +11,10 @@
         <file>shaders/customparticletemplate.vert</file>
         <file>shaders/imageparticle.frag</file>
         <file>shaders/imageparticle.vert</file>
+        <file>shaders/customparticle_core.frag</file>
+        <file>shaders/customparticle_core.vert</file>
+        <file>shaders/customparticletemplate_core.vert</file>
+        <file>shaders/imageparticle_core.frag</file>
+        <file>shaders/imageparticle_core.vert</file>
     </qresource>
 </RCC>
diff --git a/src/particles/qquickimageparticle.cpp b/src/particles/qquickimageparticle.cpp
index dfe4524c7cab46cea730f8a31a0ae2bedfc88057..0bea3a87af8358505edd7a00d533ed8f61e3aed1 100644
--- a/src/particles/qquickimageparticle.cpp
+++ b/src/particles/qquickimageparticle.cpp
@@ -59,14 +59,8 @@
 
 QT_BEGIN_NAMESPACE
 
-#ifndef QT_OPENGL_ES_2
-#define SHADER_DEFINES "#version 120\n"
-#else
-#define SHADER_DEFINES ""
-#endif
-
 #if defined(Q_OS_BLACKBERRY)
-#define SHADER_PLATFORM_DEFINES "#define Q_OS_BLACKBERRY\n"
+#define SHADER_PLATFORM_DEFINES "Q_OS_BLACKBERRY\n"
 #else
 #define SHADER_PLATFORM_DEFINES
 #endif
@@ -107,15 +101,26 @@ public:
     {
         QSGShaderSourceBuilder builder;
 
-        builder.appendSource(QByteArray(SHADER_DEFINES) + QByteArray(SHADER_PLATFORM_DEFINES));
-        builder.appendSource(QByteArray("#define TABLE\n#define DEFORM\n#define COLOR\n"));
         builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.vert"));
+        builder.addDefinition(QByteArray(SHADER_PLATFORM_DEFINES));
+        builder.addDefinition(QByteArrayLiteral("TABLE"));
+        builder.addDefinition(QByteArrayLiteral("DEFORM"));
+        builder.addDefinition(QByteArrayLiteral("COLOR"));
+#if defined(QT_OPENGL_ES_2)
+        builder.removeVersion();
+#endif
+
         m_vertex_code = builder.source();
         builder.clear();
 
-        builder.appendSource(QByteArray(SHADER_DEFINES));
-        builder.appendSource(QByteArray("#define TABLE\n#define DEFORM\n#define COLOR\n"));
         builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.frag"));
+        builder.addDefinition(QByteArray(SHADER_PLATFORM_DEFINES));
+        builder.addDefinition(QByteArrayLiteral("TABLE"));
+        builder.addDefinition(QByteArrayLiteral("DEFORM"));
+        builder.addDefinition(QByteArrayLiteral("COLOR"));
+#if defined(QT_OPENGL_ES_2)
+        builder.removeVersion();
+#endif
         m_fragment_code = builder.source();
 
         Q_ASSERT(!m_vertex_code.isNull());
@@ -174,15 +179,23 @@ public:
     {
         QSGShaderSourceBuilder builder;
 
-        builder.appendSource(QByteArray(SHADER_DEFINES) + QByteArray(SHADER_PLATFORM_DEFINES));
-        builder.appendSource(QByteArray("#define DEFORM\n#define COLOR\n"));
         builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.vert"));
+        builder.addDefinition(QByteArray(SHADER_PLATFORM_DEFINES));
+        builder.addDefinition(QByteArrayLiteral("DEFORM"));
+        builder.addDefinition(QByteArrayLiteral("COLOR"));
+#if defined(QT_OPENGL_ES_2)
+        builder.removeVersion();
+#endif
         m_vertex_code = builder.source();
         builder.clear();
 
-        builder.appendSource(QByteArray(SHADER_DEFINES));
-        builder.appendSource(QByteArray("#define DEFORM\n#define COLOR\n"));
         builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.frag"));
+        builder.addDefinition(QByteArray(SHADER_PLATFORM_DEFINES));
+        builder.addDefinition(QByteArrayLiteral("DEFORM"));
+        builder.addDefinition(QByteArrayLiteral("COLOR"));
+#if defined(QT_OPENGL_ES_2)
+        builder.removeVersion();
+#endif
         m_fragment_code = builder.source();
 
         Q_ASSERT(!m_vertex_code.isNull());
@@ -230,15 +243,27 @@ public:
     {
         QSGShaderSourceBuilder builder;
 
-        builder.appendSource(QByteArray(SHADER_DEFINES) + QByteArray(SHADER_PLATFORM_DEFINES));
-        builder.appendSource(QByteArray("#define SPRITE\n#define TABLE\n#define DEFORM\n#define COLOR\n"));
         builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.vert"));
+        builder.addDefinition(QByteArray(SHADER_PLATFORM_DEFINES));
+        builder.addDefinition(QByteArrayLiteral("SPRITE"));
+        builder.addDefinition(QByteArrayLiteral("TABLE"));
+        builder.addDefinition(QByteArrayLiteral("DEFORM"));
+        builder.addDefinition(QByteArrayLiteral("COLOR"));
+#if defined(QT_OPENGL_ES_2)
+        builder.removeVersion();
+#endif
         m_vertex_code = builder.source();
         builder.clear();
 
-        builder.appendSource(QByteArray(SHADER_DEFINES));
-        builder.appendSource(QByteArray("#define SPRITE\n#define TABLE\n#define DEFORM\n#define COLOR\n"));
         builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.frag"));
+        builder.addDefinition(QByteArray(SHADER_PLATFORM_DEFINES));
+        builder.addDefinition(QByteArrayLiteral("SPRITE"));
+        builder.addDefinition(QByteArrayLiteral("TABLE"));
+        builder.addDefinition(QByteArrayLiteral("DEFORM"));
+        builder.addDefinition(QByteArrayLiteral("COLOR"));
+#if defined(QT_OPENGL_ES_2)
+        builder.removeVersion();
+#endif
         m_fragment_code = builder.source();
 
         Q_ASSERT(!m_vertex_code.isNull());
@@ -299,15 +324,21 @@ public:
     {
         QSGShaderSourceBuilder builder;
 
-        builder.appendSource(QByteArray(SHADER_DEFINES) + QByteArray(SHADER_PLATFORM_DEFINES));
-        builder.appendSource(QByteArray("#define COLOR\n"));
         builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.vert"));
+        builder.addDefinition(QByteArray(SHADER_PLATFORM_DEFINES));
+        builder.addDefinition(QByteArrayLiteral("COLOR"));
+#if defined(QT_OPENGL_ES_2)
+        builder.removeVersion();
+#endif
         m_vertex_code = builder.source();
         builder.clear();
 
-        builder.appendSource(QByteArray(SHADER_DEFINES));
-        builder.appendSource(QByteArray("#define COLOR\n"));
         builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.frag"));
+        builder.addDefinition(QByteArray(SHADER_PLATFORM_DEFINES));
+        builder.addDefinition(QByteArrayLiteral("COLOR"));
+#if defined(QT_OPENGL_ES_2)
+        builder.removeVersion();
+#endif
         m_fragment_code = builder.source();
 
         Q_ASSERT(!m_vertex_code.isNull());
@@ -370,13 +401,19 @@ public:
     {
         QSGShaderSourceBuilder builder;
 
-        builder.appendSource(QByteArray(SHADER_DEFINES) + QByteArray(SHADER_PLATFORM_DEFINES));
         builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.vert"));
+        builder.addDefinition(QByteArray(SHADER_PLATFORM_DEFINES));
+#if defined(QT_OPENGL_ES_2)
+        builder.removeVersion();
+#endif
         m_vertex_code = builder.source();
         builder.clear();
 
-        builder.appendSource(QByteArray(SHADER_DEFINES));
         builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.frag"));
+        builder.addDefinition(QByteArray(SHADER_PLATFORM_DEFINES));
+#if defined(QT_OPENGL_ES_2)
+        builder.removeVersion();
+#endif
         m_fragment_code = builder.source();
 
         Q_ASSERT(!m_vertex_code.isNull());
diff --git a/src/particles/shaders/customparticle.frag b/src/particles/shaders/customparticle.frag
index c1c15ecb0ce05ccfb00b762ecc9edf992304a288..64007029f7e0a0c2608b4f05fac68baab69101c6 100644
--- a/src/particles/shaders/customparticle.frag
+++ b/src/particles/shaders/customparticle.frag
@@ -1,3 +1,5 @@
+#version 120
+
 varying highp vec2 qt_TexCoord0;
 
 uniform sampler2D source;
diff --git a/src/particles/shaders/customparticle_core.frag b/src/particles/shaders/customparticle_core.frag
new file mode 100644
index 0000000000000000000000000000000000000000..699c834605f9b1a4a4587102dcb553c9d2cef2c4
--- /dev/null
+++ b/src/particles/shaders/customparticle_core.frag
@@ -0,0 +1,13 @@
+#version 150
+
+in vec2 qt_TexCoord0;
+
+out vec4 fragColor;
+
+uniform sampler2D source;
+uniform float qt_Opacity;
+
+void main()
+{
+    fragColor = texture(source, qt_TexCoord0) * qt_Opacity;
+}
\ No newline at end of file
diff --git a/src/particles/shaders/customparticle_core.vert b/src/particles/shaders/customparticle_core.vert
new file mode 100644
index 0000000000000000000000000000000000000000..b99f73ea53a18ac9c3e25bb1acedb3735aef3fe4
--- /dev/null
+++ b/src/particles/shaders/customparticle_core.vert
@@ -0,0 +1,4 @@
+void main()
+{
+    defaultMain();
+}
\ No newline at end of file
diff --git a/src/particles/shaders/customparticletemplate.vert b/src/particles/shaders/customparticletemplate.vert
index c482c4207be6728e926781e2966874ab8abe33f2..eef8458a858a41b4118663d6e85f8844b390b68f 100644
--- a/src/particles/shaders/customparticletemplate.vert
+++ b/src/particles/shaders/customparticletemplate.vert
@@ -1,3 +1,5 @@
+#version 120
+
 attribute highp vec2 qt_ParticlePos;
 attribute highp vec2 qt_ParticleTex;
 attribute highp vec4 qt_ParticleData; // x = time, y = lifeSpan, z = size, w = endSize
diff --git a/src/particles/shaders/customparticletemplate_core.vert b/src/particles/shaders/customparticletemplate_core.vert
new file mode 100644
index 0000000000000000000000000000000000000000..15d38e797cc97e5fdc4acae4f0985cb71391d45e
--- /dev/null
+++ b/src/particles/shaders/customparticletemplate_core.vert
@@ -0,0 +1,28 @@
+#version 150 core
+
+in vec2 qt_ParticlePos;
+in vec2 qt_ParticleTex;
+in vec4 qt_ParticleData; // x = time, y = lifeSpan, z = size, w = endSize
+in vec4 qt_ParticleVec;  // x,y = constant velocity, z,w = acceleration
+in float qt_ParticleR;
+
+out vec2 qt_TexCoord0;
+
+uniform mat4 qt_Matrix;
+uniform float qt_Timestamp;
+
+void defaultMain()
+{
+    qt_TexCoord0 = qt_ParticleTex;
+    float size = qt_ParticleData.z;
+    float endSize = qt_ParticleData.w;
+    float t = (qt_Timestamp - qt_ParticleData.x) / qt_ParticleData.y;
+    float currentSize = mix(size, endSize, t * t);
+    if (t < 0. || t > 1.)
+        currentSize = 0.;
+    vec2 pos = qt_ParticlePos
+             - currentSize / 2. + currentSize * qt_ParticleTex   // adjust size
+             + qt_ParticleVec.xy * t * qt_ParticleData.y         // apply velocity vector..
+             + 0.5 * qt_ParticleVec.zw * pow(t * qt_ParticleData.y, 2.);
+    gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1);
+}
diff --git a/src/particles/shaders/imageparticle.frag b/src/particles/shaders/imageparticle.frag
index 699b90babf6d7ff31163275c677478f6acdd8c8f..92795a538140b923d7c95bc5392bdaebd2f29097 100644
--- a/src/particles/shaders/imageparticle.frag
+++ b/src/particles/shaders/imageparticle.frag
@@ -1,3 +1,5 @@
+#version 120
+
 uniform sampler2D _qt_texture;
 uniform lowp float qt_Opacity;
 
diff --git a/src/particles/shaders/imageparticle.vert b/src/particles/shaders/imageparticle.vert
index 9e607a74779153d3cc5a23a18c404b075d82b131..377f83168633b064e1e5e91215af73876e135ad2 100644
--- a/src/particles/shaders/imageparticle.vert
+++ b/src/particles/shaders/imageparticle.vert
@@ -1,3 +1,5 @@
+#version 120
+
 #if defined(DEFORM)
 attribute highp vec4 vPosTex;
 #else
diff --git a/src/particles/shaders/imageparticle_core.frag b/src/particles/shaders/imageparticle_core.frag
new file mode 100644
index 0000000000000000000000000000000000000000..3ac8c8d34ee3dbe72e2d6edf7ea345b42c6dcd01
--- /dev/null
+++ b/src/particles/shaders/imageparticle_core.frag
@@ -0,0 +1,44 @@
+#version 150 core
+
+#if defined(SPRITE)
+in vec4 fTexS;
+#elif defined(DEFORM)
+in vec2 fTex;
+#endif
+
+#if defined(COLOR)
+in vec4 fColor;
+#else
+in float fFade;
+#endif
+
+#if defined(TABLE)
+in vec2 tt;
+uniform sampler2D colortable;
+#endif
+
+out vec4 fragColor;
+
+uniform sampler2D _qt_texture;
+uniform float qt_Opacity;
+
+void main()
+{
+#if defined(SPRITE)
+    fragColor = mix(texture(_qt_texture, fTexS.xy), texture(_qt_texture, fTexS.zw), tt.y)
+              * fColor
+              * texture(colortable, tt)
+              * qt_Opacity;
+#elif defined(TABLE)
+    fragColor = texture(_qt_texture, fTex)
+              * fColor
+              * texture(colortable, tt)
+              * qt_Opacity;
+#elif defined(DEFORM)
+    fragColor = texture(_qt_texture, fTex) * fColor * qt_Opacity;
+#elif defined(COLOR)
+    fragColor = texture(_qt_texture, gl_PointCoord) * fColor * qt_Opacity;
+#else
+    fragColor = texture(_qt_texture, gl_PointCoord) * fFade * qt_Opacity;
+#endif
+}
\ No newline at end of file
diff --git a/src/particles/shaders/imageparticle_core.vert b/src/particles/shaders/imageparticle_core.vert
new file mode 100644
index 0000000000000000000000000000000000000000..ed9a918eb3aaeafd63784e6e3b8e556257363ce1
--- /dev/null
+++ b/src/particles/shaders/imageparticle_core.vert
@@ -0,0 +1,145 @@
+#version 150 core
+
+#if defined(DEFORM)
+in vec4 vPosTex;
+#else
+in vec2 vPos;
+#endif
+
+in vec4 vData; // x = time, y = lifeSpan, z = size, w = endSize
+in vec4 vVec;  // x,y = constant velocity,  z,w = acceleration
+uniform float entry;
+
+#if defined(COLOR)
+in vec4 vColor;
+#endif
+
+#if defined(DEFORM)
+in vec4 vDeformVec; // x,y x unit vector; z,w = y unit vector
+in vec3 vRotation;  // x = radians of rotation, y = rotation velocity, z = bool autoRotate
+#endif
+
+#if defined(SPRITE)
+in vec3 vAnimData; // w,h(premultiplied of anim), interpolation progress
+in vec4 vAnimPos;  // x,y, x,y (two frames for interpolation)
+#endif
+
+uniform mat4 qt_Matrix;
+uniform float timestamp;
+
+#if defined(TABLE)
+out vec2 tt;//y is progress if Sprite mode
+uniform float sizetable[64];
+uniform float opacitytable[64];
+#endif
+
+#if defined(SPRITE)
+out vec4 fTexS;
+#elif defined(DEFORM)
+out vec2 fTex;
+#endif
+
+#if defined(COLOR)
+out vec4 fColor;
+#else
+out float fFade;
+#endif
+
+
+void main()
+{
+    float t = (timestamp - vData.x) / vData.y;
+    if (t < 0. || t > 1.) {
+#if defined(DEFORM)
+        gl_Position = qt_Matrix * vec4(vPosTex.x, vPosTex.y, 0., 1.);
+#else
+        gl_PointSize = 0.;
+#endif
+    } else {
+#if defined(SPRITE)
+        tt.y = vAnimData.z;
+
+        // Calculate frame location in texture
+        fTexS.xy = vAnimPos.xy + vPosTex.zw * vAnimData.xy;
+
+        // Next frame is also passed, for interpolation
+        fTexS.zw = vAnimPos.zw + vPosTex.zw * vAnimData.xy;
+
+#elif defined(DEFORM)
+        fTex = vPosTex.zw;
+#endif
+        float currentSize = mix(vData.z, vData.w, t * t);
+#if defined (Q_OS_BLACKBERRY)
+        float fade = 1.;
+#else
+        float fade = 1.;
+#endif
+        float fadeIn = min(t * 10., 1.);
+        float fadeOut = 1. - clamp((t - 0.75) * 4.,0., 1.);
+
+#if defined(TABLE)
+        currentSize = currentSize * sizetable[int(floor(t*64.))];
+        fade = fade * opacitytable[int(floor(t*64.))];
+#endif
+
+        if (entry == 1.)
+            fade = fade * fadeIn * fadeOut;
+        else if (entry == 2.)
+            currentSize = currentSize * fadeIn * fadeOut;
+
+        if (currentSize <= 0.) {
+#if defined(DEFORM)
+            gl_Position = qt_Matrix * vec4(vPosTex.x, vPosTex.y, 0., 1.);
+#else
+            gl_PointSize = 0.;
+#endif
+        } else {
+            if (currentSize < 3.) // Sizes too small look jittery as they move
+                currentSize = 3.;
+
+            vec2 pos;
+#if defined(DEFORM)
+            float rotation = vRotation.x + vRotation.y * t * vData.y;
+            if (vRotation.z == 1.0) {
+                vec2 curVel = vVec.zw * t * vData.y + vVec.xy;
+                if (length(curVel) > 0.)
+                    rotation += atan(curVel.y, curVel.x);
+            }
+            vec2 trigCalcs = vec2(cos(rotation), sin(rotation));
+            vec4 deform = vDeformVec * currentSize * (vPosTex.zzww - 0.5);
+            vec4 rotatedDeform = deform.xxzz * trigCalcs.xyxy;
+            rotatedDeform = rotatedDeform + (deform.yyww * trigCalcs.yxyx * vec4(-1.,1.,-1.,1.));
+            /* The readable version:
+            vec2 xDeform = vDeformVec.xy * currentSize * (vTex.x-0.5);
+            vec2 yDeform = vDeformVec.zw * currentSize * (vTex.y-0.5);
+            vec2 xRotatedDeform;
+            xRotatedDeform.x = trigCalcs.x*xDeform.x - trigCalcs.y*xDeform.y;
+            xRotatedDeform.y = trigCalcs.y*xDeform.x + trigCalcs.x*xDeform.y;
+            vec2 yRotatedDeform;
+            yRotatedDeform.x = trigCalcs.x*yDeform.x - trigCalcs.y*yDeform.y;
+            yRotatedDeform.y = trigCalcs.y*yDeform.x + trigCalcs.x*yDeform.y;
+            */
+            pos = vPosTex.xy
+                  + rotatedDeform.xy
+                  + rotatedDeform.zw
+                  + vVec.xy * t * vData.y         // apply velocity
+                  + 0.5 * vVec.zw * pow(t * vData.y, 2.); // apply acceleration
+#else
+            pos = vPos
+                  + vVec.xy * t * vData.y         // apply velocity vector..
+                  + 0.5 * vVec.zw * pow(t * vData.y, 2.);
+            gl_PointSize = currentSize;
+#endif
+            gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1);
+
+#if defined(COLOR)
+            fColor = vColor * fade;
+#else
+            fFade = fade;
+#endif
+#if defined(TABLE)
+            tt.x = t;
+#endif
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/quick/items/items.pri b/src/quick/items/items.pri
index d0ebbcfcdbd129161caf8c11a9c1aac724ea9494..3996512f9dc661bc0b5b21a71c65394ca705767c 100644
--- a/src/quick/items/items.pri
+++ b/src/quick/items/items.pri
@@ -145,7 +145,13 @@ OTHER_FILES += \
     $$PWD/shaders/shadereffect.vert \
     $$PWD/shaders/shadereffect.frag \
     $$PWD/shaders/shadereffectfallback.vert \
-    $$PWD/shaders/shadereffectfallback.frag
+    $$PWD/shaders/shadereffectfallback.frag \
+    $$PWD/shaders/sprite_core.vert \
+    $$PWD/shaders/sprite_core.frag \
+    $$PWD/shaders/shadereffect_core.vert \
+    $$PWD/shaders/shadereffect_core.frag \
+    $$PWD/shaders/shadereffectfallback_core.vert \
+    $$PWD/shaders/shadereffectfallback_core.frag
 
 RESOURCES += \
     $$PWD/items.qrc
diff --git a/src/quick/items/items.qrc b/src/quick/items/items.qrc
index 837cffb65af2f174ef70781e5c51b6938706f040..671d8acdbb5614e522e30cb7fcace5fbc6932c9c 100644
--- a/src/quick/items/items.qrc
+++ b/src/quick/items/items.qrc
@@ -6,5 +6,11 @@
         <file>shaders/shadereffect.frag</file>
         <file>shaders/shadereffectfallback.frag</file>
         <file>shaders/shadereffectfallback.vert</file>
+        <file>shaders/shadereffect_core.frag</file>
+        <file>shaders/shadereffect_core.vert</file>
+        <file>shaders/shadereffectfallback_core.frag</file>
+        <file>shaders/shadereffectfallback_core.vert</file>
+        <file>shaders/sprite_core.frag</file>
+        <file>shaders/sprite_core.vert</file>
     </qresource>
 </RCC>
diff --git a/src/quick/items/shaders/shadereffect_core.frag b/src/quick/items/shaders/shadereffect_core.frag
new file mode 100644
index 0000000000000000000000000000000000000000..2163753edc9831e27fca56bf8b3cc81d93f8f70f
--- /dev/null
+++ b/src/quick/items/shaders/shadereffect_core.frag
@@ -0,0 +1,13 @@
+#version 150 core
+
+in vec2 qt_TexCoord0;
+
+out vec4 fragColor;
+
+uniform sampler2D source;
+uniform float qt_Opacity;
+
+void main()
+{
+    fragColor = texture(source, qt_TexCoord0) * qt_Opacity;
+}
\ No newline at end of file
diff --git a/src/quick/items/shaders/shadereffect_core.vert b/src/quick/items/shaders/shadereffect_core.vert
new file mode 100644
index 0000000000000000000000000000000000000000..2ed2d47b5f26663300ebc3aabb18e20d9cf7c31d
--- /dev/null
+++ b/src/quick/items/shaders/shadereffect_core.vert
@@ -0,0 +1,14 @@
+#version 150 core
+
+in vec4 qt_Vertex;
+in vec2 qt_MultiTexCoord0;
+
+out vec2 qt_TexCoord0;
+
+uniform mat4 qt_Matrix;
+
+void main()
+{
+    qt_TexCoord0 = qt_MultiTexCoord0;
+    gl_Position = qt_Matrix * qt_Vertex;
+}
\ No newline at end of file
diff --git a/src/quick/items/shaders/shadereffectfallback_core.frag b/src/quick/items/shaders/shadereffectfallback_core.frag
new file mode 100644
index 0000000000000000000000000000000000000000..4abf12473700884c0001f983bab6c4a4f9652f3b
--- /dev/null
+++ b/src/quick/items/shaders/shadereffectfallback_core.frag
@@ -0,0 +1,8 @@
+#version 150 core
+
+out vec4 fragColor;
+
+void main()
+{
+    fragColor = vec4(1., 0., 1., 1.);
+}
\ No newline at end of file
diff --git a/src/quick/items/shaders/shadereffectfallback_core.vert b/src/quick/items/shaders/shadereffectfallback_core.vert
new file mode 100644
index 0000000000000000000000000000000000000000..b1ca84cc6d0c9405c0c4b7353534f21fdd51fa7d
--- /dev/null
+++ b/src/quick/items/shaders/shadereffectfallback_core.vert
@@ -0,0 +1,10 @@
+#version 150 core
+
+in vec4 v;
+
+uniform mat4 qt_Matrix;
+
+void main()
+{
+    gl_Position = qt_Matrix * v;
+}
\ No newline at end of file
diff --git a/src/quick/items/shaders/sprite_core.frag b/src/quick/items/shaders/sprite_core.frag
new file mode 100644
index 0000000000000000000000000000000000000000..c1087a8754b0e69b27eeec5bdb32fd27ae994292
--- /dev/null
+++ b/src/quick/items/shaders/sprite_core.frag
@@ -0,0 +1,16 @@
+#version 150 core
+
+in vec4 fTexS;
+in float progress;
+
+out vec4 fragColor;
+
+uniform sampler2D _qt_texture;
+uniform float qt_Opacity;
+
+void main()
+{
+    fragColor = mix(texture(_qt_texture, fTexS.xy),
+                    texture(_qt_texture, fTexS.zw),
+                    progress) * qt_Opacity;
+}
\ No newline at end of file
diff --git a/src/quick/items/shaders/sprite_core.vert b/src/quick/items/shaders/sprite_core.vert
new file mode 100644
index 0000000000000000000000000000000000000000..5027bf03fce5fa7a2cf8c0c67ed7fe04a1b128d8
--- /dev/null
+++ b/src/quick/items/shaders/sprite_core.vert
@@ -0,0 +1,24 @@
+#version 150 core
+
+in vec2 vPos;
+in vec2 vTex;
+
+out vec4 fTexS;
+out float progress;
+
+uniform vec3 animData;  // w,h(premultiplied of anim), interpolation progress
+uniform vec4 animPos;   // x,y, x,y (two frames for interpolation)
+uniform mat4 qt_Matrix;
+
+void main()
+{
+    progress = animData.z;
+
+    // Calculate frame location in texture
+    fTexS.xy = animPos.xy + vTex.xy * animData.xy;
+
+    // Next frame is also passed, for interpolation
+    fTexS.zw = animPos.zw + vTex.xy * animData.xy;
+
+    gl_Position = qt_Matrix * vec4(vPos.x, vPos.y, 0, 1);
+}
\ No newline at end of file
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
index 3782cab5d3d3b28b52d892cdb6c9e311d87445d7..49c2cc8178d2fd3729840e4301d833073a95d3a2 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
@@ -46,6 +46,7 @@
 
 #include <QtGui/QGuiApplication>
 #include <QtGui/QOpenGLFramebufferObject>
+#include <QtGui/QOpenGLVertexArrayObject>
 
 #include <private/qqmlprofilerservice_p.h>
 
@@ -57,7 +58,7 @@
 
 QT_BEGIN_NAMESPACE
 
-extern QByteArray qsgShaderRewriter_insertZAttributes(const char *input);
+extern QByteArray qsgShaderRewriter_insertZAttributes(const char *input, QSurfaceFormat::OpenGLContextProfile profile);
 
 namespace QSGBatchRenderer
 {
@@ -132,10 +133,12 @@ ShaderManager::Shader *ShaderManager::prepareMaterial(QSGMaterial *material)
 #endif
 
     QSGMaterialShader *s = material->createShader();
+    QOpenGLContext *ctx = QOpenGLContext::currentContext();
+    QSurfaceFormat::OpenGLContextProfile profile = ctx->format().profile();
 
     QOpenGLShaderProgram *p = s->program();
     p->addShaderFromSourceCode(QOpenGLShader::Vertex,
-                               qsgShaderRewriter_insertZAttributes(s->vertexShader()));
+                               qsgShaderRewriter_insertZAttributes(s->vertexShader(), profile));
     p->addShaderFromSourceCode(QOpenGLShader::Fragment,
                                s->fragmentShader());
 
@@ -761,6 +764,7 @@ Renderer::Renderer(QSGRenderContext *ctx)
     , m_zRange(0)
     , m_currentMaterial(0)
     , m_currentShader(0)
+    , m_vao(0)
 {
     setNodeUpdater(new Updater(this));
 
@@ -801,6 +805,13 @@ Renderer::Renderer(QSGRenderContext *ctx)
         qDebug() << "Batch thresholds: nodes:" << m_batchNodeThreshold << " vertices:" << m_batchVertexThreshold;
         qDebug() << "Using buffer strategy:" << (m_bufferStrategy == GL_STATIC_DRAW ? "static" : (m_bufferStrategy == GL_DYNAMIC_DRAW ? "dynamic" : "stream"));
     }
+
+    // If rendering with an OpenGL Core profile context, we need to create a VAO
+    // to hold our vertex specification state.
+    if (context()->openglContext()->format().profile() == QSurfaceFormat::CoreProfile) {
+        m_vao = new QOpenGLVertexArrayObject(this);
+        m_vao->create();
+    }
 }
 
 static void qsg_wipeBuffer(Buffer *buffer, QOpenGLFunctions *funcs)
@@ -2211,6 +2222,17 @@ void Renderer::deleteRemovedElements()
     m_elementsToDelete.reset();
 }
 
+void Renderer::preprocess()
+{
+    // Bind our VAO. It's important that we do this here as the
+    // QSGRenderer::preprocess() call may well do work that requires
+    // a bound VAO.
+    if (m_vao)
+        m_vao->bind();
+
+    QSGRenderer::preprocess();
+}
+
 void Renderer::render()
 {
     if (Q_UNLIKELY(debug_dump)) {
@@ -2318,6 +2340,9 @@ void Renderer::render()
     renderBatches();
 
     m_rebuild = 0;
+
+    if (m_vao)
+        m_vao->release();
 }
 
 void Renderer::prepareRenderNode(RenderNodeElement *e)
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
index aacf482eadbecffda1a4e8abe49f0f3ed55d953f..95e111552d78e47b4d14619b7e5c86a93cbf3ac4 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
@@ -50,6 +50,8 @@
 
 QT_BEGIN_NAMESPACE
 
+class QOpenGLVertexArrayObject;
+
 namespace QSGBatchRenderer
 {
 
@@ -398,6 +400,7 @@ public:
 
 protected:
     void nodeChanged(QSGNode *node, QSGNode::DirtyState state);
+    void preprocess() Q_DECL_OVERRIDE;
     void render();
 
 private:
@@ -481,6 +484,9 @@ private:
     QSGMaterialShader *m_currentProgram;
     ShaderManager::Shader *m_currentShader;
     const QSGClipNode *m_currentClip;
+
+    // For minimal OpenGL core profile support
+    QOpenGLVertexArrayObject *m_vao;
 };
 
 Batch *Renderer::newBatch()
diff --git a/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp b/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp
index eade198cd0722365bf6662db578a562e4cbd3fd7..8c7c806cad0e22f27de07af213214c324dcaaf5c 100644
--- a/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp
+++ b/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp
@@ -40,6 +40,7 @@
 ****************************************************************************/
 
 #include <QtCore>
+#include <QtGui/QSurfaceFormat>
 
 // Duct Tape tokenizer for the purpose of parsing and rewriting
 // shader source code
@@ -173,7 +174,7 @@ Tokenizer::Token Tokenizer::next()
 
 using namespace QSGShaderRewriter;
 
-QByteArray qsgShaderRewriter_insertZAttributes(const char *input)
+QByteArray qsgShaderRewriter_insertZAttributes(const char *input, QSurfaceFormat::OpenGLContextProfile profile)
 {
     Tokenizer tok;
     tok.initialize(input);
@@ -182,15 +183,33 @@ QByteArray qsgShaderRewriter_insertZAttributes(const char *input)
     Tokenizer::Token t = tok.next();
 
     // First find "void main() { ... "
+    const char* voidPos;
     while (t != Tokenizer::Token_EOF) {
         if (lt == Tokenizer::Token_Void && t == Tokenizer::Token_Identifier) {
             if (qstrncmp("main", tok.identifier, 4) == 0)
                 break;
         }
+        voidPos = tok.pos - 4;
         lt = t;
         t = tok.next();
     }
 
+    QByteArray result;
+    result.reserve(1024);
+    result += QByteArray::fromRawData(input, voidPos - input);
+    switch (profile) {
+    case QSurfaceFormat::NoProfile:
+    case QSurfaceFormat::CompatibilityProfile:
+        result += QByteArrayLiteral("attribute highp float _qt_order;\n");
+        result += QByteArrayLiteral("uniform highp float _qt_zRange;\n");
+        break;
+
+    case QSurfaceFormat::CoreProfile:
+        result += QByteArrayLiteral("in float _qt_order;\n");
+        result += QByteArrayLiteral("uniform float _qt_zRange;\n");
+        break;
+    }
+
     // Find first brace '{'
     while (t != Tokenizer::Token_EOF && t != Tokenizer::Token_OpenBrace) t = tok.next();
     int braceDepth = 1;
@@ -202,12 +221,8 @@ QByteArray qsgShaderRewriter_insertZAttributes(const char *input)
         case Tokenizer::Token_CloseBrace:
             braceDepth--;
             if (braceDepth == 0) {
-                QByteArray result;
-                result.reserve(1024);
-                result += "attribute highp float _qt_order;\n";
-                result += "uniform highp float _qt_zRange;\n";
-                result += QByteArray::fromRawData(input, tok.pos - 1 - input);
-                result += "    gl_Position.z = gl_Position.z * _qt_zRange + _qt_order;\n";
+                result += QByteArray::fromRawData(voidPos, tok.pos - 1 - voidPos);
+                result += QByteArrayLiteral("    gl_Position.z = gl_Position.z * _qt_zRange + _qt_order;\n");
                 result += QByteArray(tok.pos - 1);
                 return result;
             }
diff --git a/src/quick/scenegraph/qsgadaptationlayer.cpp b/src/quick/scenegraph/qsgadaptationlayer.cpp
index 8585caa22dd997a9588d6e22a5b075a99c7d59a3..58c843a2862d564952e705dcbf8ff298f1f6c856 100644
--- a/src/quick/scenegraph/qsgadaptationlayer.cpp
+++ b/src/quick/scenegraph/qsgadaptationlayer.cpp
@@ -60,7 +60,7 @@ static QElapsedTimer qsg_render_timer;
 
 QSGDistanceFieldGlyphCache::Texture QSGDistanceFieldGlyphCache::s_emptyTexture;
 
-QSGDistanceFieldGlyphCache::QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, const QRawFont &font)
+QSGDistanceFieldGlyphCache::QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font)
     : m_manager(man)
     , m_pendingGlyphs(64)
 {
@@ -74,6 +74,8 @@ QSGDistanceFieldGlyphCache::QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCach
     m_referenceFont = font;
     m_referenceFont.setPixelSize(QT_DISTANCEFIELD_BASEFONTSIZE(m_doubleGlyphResolution));
     Q_ASSERT(m_referenceFont.isValid());
+
+    m_coreProfile = (c->format().profile() == QSurfaceFormat::CoreProfile);
 }
 
 QSGDistanceFieldGlyphCache::~QSGDistanceFieldGlyphCache()
diff --git a/src/quick/scenegraph/qsgadaptationlayer_p.h b/src/quick/scenegraph/qsgadaptationlayer_p.h
index f9e59f9c7f520abaeadccc1baa0a44f91d099213..f2d7dc07cade7d5ea7e8b1de10e3ea745c4577ee 100644
--- a/src/quick/scenegraph/qsgadaptationlayer_p.h
+++ b/src/quick/scenegraph/qsgadaptationlayer_p.h
@@ -66,6 +66,7 @@ class QImage;
 class TextureReference;
 class QSGDistanceFieldGlyphCacheManager;
 class QSGDistanceFieldGlyphNode;
+class QOpenGLContext;
 
 class Q_QUICK_PRIVATE_EXPORT QSGRectangleNode : public QSGGeometryNode
 {
@@ -149,7 +150,7 @@ public:
 class Q_QUICK_PRIVATE_EXPORT QSGDistanceFieldGlyphCache
 {
 public:
-    QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, const QRawFont &font);
+    QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font);
     virtual ~QSGDistanceFieldGlyphCache();
 
     struct Metrics {
@@ -246,6 +247,8 @@ protected:
 
     GlyphData &glyphData(glyph_t glyph);
 
+    inline bool isCoreProfile() const { return m_coreProfile; }
+
 private:
     QSGDistanceFieldGlyphCacheManager *m_manager;
 
@@ -253,6 +256,7 @@ private:
     int m_glyphCount;
 
     bool m_doubleGlyphResolution;
+    bool m_coreProfile;
 
     QList<Texture> m_textures;
     QHash<glyph_t, GlyphData> m_glyphsData;
diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp
index 1f219e735f27fff7a04edf02f4e3e36d0e3b3918..fa095b8165c60e3c75416a6f3b9b0340fe890ea9 100644
--- a/src/quick/scenegraph/qsgcontext.cpp
+++ b/src/quick/scenegraph/qsgcontext.cpp
@@ -391,12 +391,13 @@ QSGDistanceFieldGlyphCache *QSGRenderContext::distanceFieldGlyphCache(const QRaw
                     cache = new QSGSharedDistanceFieldGlyphCache(keyName,
                                                                  sharedGraphicsCache,
                                                                  m_distanceFieldCacheManager,
+                                                                 openglContext(),
                                                                  font);
                 }
             }
         }
         if (!cache)
-            cache = new QSGDefaultDistanceFieldGlyphCache(m_distanceFieldCacheManager, font);
+            cache = new QSGDefaultDistanceFieldGlyphCache(m_distanceFieldCacheManager, openglContext(), font);
         m_distanceFieldCacheManager->insertCache(font, cache);
     }
 
diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
index 25ff98bc67939a10f9c40f26601fabd5ccfd981f..c5c4e18e37cbdc819b02072fbadaf8a43b3c9b7d 100644
--- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
+++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
@@ -48,16 +48,23 @@
 #include <qopenglfunctions.h>
 #include <qmath.h>
 
+#if !defined(QT_OPENGL_ES_2)
+#include <QtGui/qopenglfunctions_3_2_core.h>
+#endif
+
 QT_BEGIN_NAMESPACE
 
 DEFINE_BOOL_CONFIG_OPTION(qmlUseGlyphCacheWorkaround, QML_USE_GLYPHCACHE_WORKAROUND)
 
-QSGDefaultDistanceFieldGlyphCache::QSGDefaultDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, const QRawFont &font)
-    : QSGDistanceFieldGlyphCache(man, font)
+QSGDefaultDistanceFieldGlyphCache::QSGDefaultDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font)
+    : QSGDistanceFieldGlyphCache(man, c, font)
     , m_maxTextureSize(0)
     , m_maxTextureCount(3)
     , m_blitProgram(0)
     , m_fboGuard(0)
+#if !defined(QT_OPENGL_ES_2)
+    , m_funcs(0)
+#endif
 {
     m_blitVertexCoordinateArray[0] = -1.0f;
     m_blitVertexCoordinateArray[1] = -1.0f;
@@ -177,17 +184,22 @@ void QSGDefaultDistanceFieldGlyphCache::storeGlyphs(const QList<QDistanceField>
             }
         }
 
+#if !defined(QT_OPENGL_ES_2)
+        const GLenum format = isCoreProfile() ? GL_RED : GL_ALPHA;
+#else
+        const GLenum format = GL_ALPHA;
+#endif
         if (useTextureUploadWorkaround()) {
             for (int i = 0; i < glyph.height(); ++i) {
                 glTexSubImage2D(GL_TEXTURE_2D, 0,
                                 c.x, c.y + i, glyph.width(),1,
-                                GL_ALPHA, GL_UNSIGNED_BYTE,
+                                format, GL_UNSIGNED_BYTE,
                                 glyph.scanLine(i));
             }
         } else {
             glTexSubImage2D(GL_TEXTURE_2D, 0,
                             c.x, c.y, glyph.width(), glyph.height(),
-                            GL_ALPHA, GL_UNSIGNED_BYTE,
+                            format, GL_UNSIGNED_BYTE,
                             glyph.constBits());
         }
     }
@@ -230,8 +242,14 @@ void QSGDefaultDistanceFieldGlyphCache::createTexture(TextureInfo *texInfo, int
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 #if !defined(QT_OPENGL_ES_2)
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
+    const GLint internalFormat = isCoreProfile() ? GL_R8 : GL_ALPHA;
+    const GLenum format = isCoreProfile() ? GL_RED : GL_ALPHA;
+#else
+    const GLint internalFormat = GL_ALPHA;
+    const GLenum format = GL_ALPHA;
 #endif
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, 0);
+
+    glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, GL_UNSIGNED_BYTE, 0);
 
     texInfo->size = QSize(width, height);
 
@@ -267,22 +285,74 @@ void QSGDefaultDistanceFieldGlyphCache::resizeTexture(TextureInfo *texInfo, int
 
     updateTexture(oldTexture, texInfo->texture, texInfo->size);
 
+#if !defined(QT_OPENGL_ES_2)
+    if (isCoreProfile() && !useTextureResizeWorkaround()) {
+        // For an OpenGL Core Profile we can use http://www.opengl.org/wiki/Framebuffer#Blitting
+        // to efficiently copy the contents of the old texture to the new texture
+        // TODO: Use ARB_copy_image if available of if we have >=4.3 context
+        if (!m_funcs) {
+            m_funcs = ctx->versionFunctions<QOpenGLFunctions_3_2_Core>();
+            Q_ASSERT(m_funcs);
+            m_funcs->initializeOpenGLFunctions();
+        }
+
+        // Create a framebuffer object to which we can attach our old and new textures (to
+        // the first two color buffer attachment points)
+        if (!m_fboGuard) {
+            GLuint fbo;
+            m_funcs->glGenFramebuffers(1, &fbo);
+            m_fboGuard = new QOpenGLSharedResourceGuard(ctx, fbo, freeFramebufferFunc);
+        }
+
+        // Bind the FBO to both the GL_READ_FRAMEBUFFER? and GL_DRAW_FRAMEBUFFER targets
+        m_funcs->glBindFramebuffer(GL_FRAMEBUFFER, m_fboGuard->id());
+
+        // Bind the old texture to GL_COLOR_ATTACHMENT0
+        m_funcs->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+                                        GL_TEXTURE_2D, oldTexture, 0);
+
+        // Bind the new texture to GL_COLOR_ATTACHMENT1
+        m_funcs->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1,
+                                        GL_TEXTURE_2D, texInfo->texture, 0);
+
+        // Set the source and destination buffers
+        m_funcs->glReadBuffer(GL_COLOR_ATTACHMENT0);
+        m_funcs->glDrawBuffer(GL_COLOR_ATTACHMENT1);
+
+        // Do the blit
+        m_funcs->glBlitFramebuffer(0, 0, oldWidth, oldHeight,
+                                   0, 0, oldWidth, oldHeight,
+                                   GL_COLOR_BUFFER_BIT, GL_NEAREST);
+
+        // Reset the default framebuffer
+        m_funcs->glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+        return;
+    } else if (useTextureResizeWorkaround()) {
+#else
     if (useTextureResizeWorkaround()) {
+#endif
         GLint alignment = 4; // default value
         glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment);
         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
 
+#if !defined(QT_OPENGL_ES_2)
+        const GLenum format = isCoreProfile() ? GL_RED : GL_ALPHA;
+#else
+        const GLenum format = GL_ALPHA;
+#endif
+
         if (useTextureUploadWorkaround()) {
             for (int i = 0; i < texInfo->image.height(); ++i) {
                 glTexSubImage2D(GL_TEXTURE_2D, 0,
                                 0, i, oldWidth, 1,
-                                GL_ALPHA, GL_UNSIGNED_BYTE,
+                                format, GL_UNSIGNED_BYTE,
                                 texInfo->image.scanLine(i));
             }
         } else {
             glTexSubImage2D(GL_TEXTURE_2D, 0,
                             0, 0, oldWidth, oldHeight,
-                            GL_ALPHA, GL_UNSIGNED_BYTE,
+                            format, GL_UNSIGNED_BYTE,
                             texInfo->image.constBits());
         }
 
diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
index 3fee6c9ef3c1db23598d99ec4a48dfece2e639fa..a5833af5fb2bead9d9af01d622da5d78e58efa7a 100644
--- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
+++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
@@ -51,10 +51,14 @@
 QT_BEGIN_NAMESPACE
 
 class QOpenGLSharedResourceGuard;
+#if !defined(QT_OPENGL_ES_2)
+class QOpenGLFunctions_3_2_Core;
+#endif
+
 class Q_QUICK_PRIVATE_EXPORT QSGDefaultDistanceFieldGlyphCache : public QSGDistanceFieldGlyphCache
 {
 public:
-    QSGDefaultDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, const QRawFont &font);
+    QSGDefaultDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font);
     virtual ~QSGDefaultDistanceFieldGlyphCache();
 
     void requestGlyphs(const QSet<glyph_t> &glyphs);
@@ -133,6 +137,9 @@ private:
     GLfloat m_blitTextureCoordinateArray[8];
 
     QOpenGLSharedResourceGuard *m_fboGuard;
+#if !defined(QT_OPENGL_ES_2)
+    QOpenGLFunctions_3_2_Core *m_funcs;
+#endif
 };
 
 QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp
index 20e1210b680b52b1956992bbe36af7251b76dab5..cc0218aefdcf00fcab8389ec75855d97e9fa0d46 100644
--- a/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp
+++ b/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp
@@ -199,8 +199,9 @@ namespace {
 QSGSharedDistanceFieldGlyphCache::QSGSharedDistanceFieldGlyphCache(const QByteArray &cacheId,
                                                                    QPlatformSharedGraphicsCache *sharedGraphicsCache,
                                                                    QSGDistanceFieldGlyphCacheManager *man,
+                                                                   QOpenGLContext *c,
                                                                    const QRawFont &font)
-    : QSGDistanceFieldGlyphCache(man, font)
+    : QSGDistanceFieldGlyphCache(man, c, font)
     , m_cacheId(cacheId)
     , m_sharedGraphicsCache(sharedGraphicsCache)
     , m_isInSceneGraphUpdate(false)
@@ -227,7 +228,6 @@ QSGSharedDistanceFieldGlyphCache::QSGSharedDistanceFieldGlyphCache(const QByteAr
             this, SLOT(reportItemsInvalidated(QByteArray,QVector<quint32>)),
             Qt::DirectConnection);
 
-    QOpenGLContext *c = QOpenGLContext::currentContext();
     Q_ASSERT(c);
     QQuickWindow *window = static_cast<QQuickWindow *>(c->surface());
     Q_ASSERT(window != 0);
diff --git a/src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h b/src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h
index a8d70be7324a9400708abdb192cd80fc29933335..d72d2a740f45b11fb7d85505d8a3dd0d0b6c5983 100644
--- a/src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h
+++ b/src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h
@@ -55,6 +55,7 @@ public:
     explicit QSGSharedDistanceFieldGlyphCache(const QByteArray &cacheId,
                                               QPlatformSharedGraphicsCache *sharedGraphicsCache,
                                               QSGDistanceFieldGlyphCacheManager *man,
+                                              QOpenGLContext *c,
                                               const QRawFont &font);
     ~QSGSharedDistanceFieldGlyphCache();
 
diff --git a/src/quick/scenegraph/scenegraph.pri b/src/quick/scenegraph/scenegraph.pri
index aebc2ece9c9c390570326eee8bdc1d712d49788c..6f64c881a852aade5118644f5cfb130a7e812b03 100644
--- a/src/quick/scenegraph/scenegraph.pri
+++ b/src/quick/scenegraph/scenegraph.pri
@@ -126,5 +126,37 @@ OTHER_FILES += \
     $$PWD/shaders/textmask.vert \
     $$PWD/shaders/texture.frag \
     $$PWD/shaders/vertexcolor.frag \
-    $$PWD/shaders/vertexcolor.vert
+    $$PWD/shaders/vertexcolor.vert \
+    $$PWD/shaders/24bittextmask_core.frag \
+    $$PWD/shaders/8bittextmask_core.frag \
+    $$PWD/shaders/distancefieldoutlinetext_core.frag \
+    $$PWD/shaders/distancefieldshiftedtext_core.frag \
+    $$PWD/shaders/distancefieldshiftedtext_core.vert \
+    $$PWD/shaders/distancefieldtext_core.frag \
+    $$PWD/shaders/distancefieldtext_core.vert \
+    $$PWD/shaders/flatcolor_core.frag \
+    $$PWD/shaders/flatcolor_core.vert \
+    $$PWD/shaders/hiqsubpixeldistancefieldtext_core.frag \
+    $$PWD/shaders/hiqsubpixeldistancefieldtext_core.vert \
+    $$PWD/shaders/loqsubpixeldistancefieldtext_core.frag \
+    $$PWD/shaders/loqsubpixeldistancefieldtext_core.vert \
+    $$PWD/shaders/opaquetexture_core.frag \
+    $$PWD/shaders/opaquetexture_core.vert \
+    $$PWD/shaders/outlinedtext_core.frag \
+    $$PWD/shaders/outlinedtext_core.vert \
+    $$PWD/shaders/rendernode_core.frag \
+    $$PWD/shaders/rendernode_core.vert \
+    $$PWD/shaders/smoothcolor_core.frag \
+    $$PWD/shaders/smoothcolor_core.vert \
+    $$PWD/shaders/smoothtexture_core.frag \
+    $$PWD/shaders/smoothtexture_core.vert \
+    $$PWD/shaders/stencilclip_core.frag \
+    $$PWD/shaders/stencilclip_core.vert \
+    $$PWD/shaders/styledtext_core.frag \
+    $$PWD/shaders/styledtext_core.vert \
+    $$PWD/shaders/textmask_core.frag \
+    $$PWD/shaders/textmask_core.vert \
+    $$PWD/shaders/texture_core.frag \
+    $$PWD/shaders/vertexcolor_core.frag \
+    $$PWD/shaders/vertexcolor_core.vert
 
diff --git a/src/quick/scenegraph/scenegraph.qrc b/src/quick/scenegraph/scenegraph.qrc
index 5299ec6d9ff0e1a18b54b5b7d98c283c3191ed99..2be8b246d3ceb3f354954a653d1cf595902b05bf 100644
--- a/src/quick/scenegraph/scenegraph.qrc
+++ b/src/quick/scenegraph/scenegraph.qrc
@@ -32,5 +32,37 @@
         <file>shaders/rendernode.frag</file>
         <file>shaders/stencilclip.frag</file>
         <file>shaders/stencilclip.vert</file>
+        <file>shaders/8bittextmask_core.frag</file>
+        <file>shaders/24bittextmask_core.frag</file>
+        <file>shaders/distancefieldoutlinetext_core.frag</file>
+        <file>shaders/distancefieldshiftedtext_core.frag</file>
+        <file>shaders/distancefieldshiftedtext_core.vert</file>
+        <file>shaders/distancefieldtext_core.frag</file>
+        <file>shaders/distancefieldtext_core.vert</file>
+        <file>shaders/flatcolor_core.frag</file>
+        <file>shaders/flatcolor_core.vert</file>
+        <file>shaders/hiqsubpixeldistancefieldtext_core.frag</file>
+        <file>shaders/hiqsubpixeldistancefieldtext_core.vert</file>
+        <file>shaders/loqsubpixeldistancefieldtext_core.frag</file>
+        <file>shaders/loqsubpixeldistancefieldtext_core.vert</file>
+        <file>shaders/opaquetexture_core.frag</file>
+        <file>shaders/opaquetexture_core.vert</file>
+        <file>shaders/outlinedtext_core.frag</file>
+        <file>shaders/outlinedtext_core.vert</file>
+        <file>shaders/rendernode_core.frag</file>
+        <file>shaders/rendernode_core.vert</file>
+        <file>shaders/smoothcolor_core.frag</file>
+        <file>shaders/smoothcolor_core.vert</file>
+        <file>shaders/smoothtexture_core.frag</file>
+        <file>shaders/smoothtexture_core.vert</file>
+        <file>shaders/stencilclip_core.frag</file>
+        <file>shaders/stencilclip_core.vert</file>
+        <file>shaders/styledtext_core.frag</file>
+        <file>shaders/styledtext_core.vert</file>
+        <file>shaders/textmask_core.frag</file>
+        <file>shaders/textmask_core.vert</file>
+        <file>shaders/texture_core.frag</file>
+        <file>shaders/vertexcolor_core.frag</file>
+        <file>shaders/vertexcolor_core.vert</file>
     </qresource>
 </RCC>
diff --git a/src/quick/scenegraph/shaders/24bittextmask.frag b/src/quick/scenegraph/shaders/24bittextmask.frag
index ac62e7b642fb6a5e203a7961f071196a0fa9e7c3..5c21e202f9c5375f78445728f530b0eea107b923 100644
--- a/src/quick/scenegraph/shaders/24bittextmask.frag
+++ b/src/quick/scenegraph/shaders/24bittextmask.frag
@@ -1,10 +1,10 @@
 varying highp vec2 sampleCoord;
 
-uniform lowp sampler2D texture;
+uniform lowp sampler2D _qt_texture;
 uniform lowp float color; // just the alpha, really...
 
 void main()
 {
-    lowp vec4 glyph = texture2D(texture, sampleCoord);
+    lowp vec4 glyph = texture2D(_qt_texture, sampleCoord);
     gl_FragColor = vec4(glyph.rgb * color, glyph.a);
 }
\ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/24bittextmask_core.frag b/src/quick/scenegraph/shaders/24bittextmask_core.frag
new file mode 100644
index 0000000000000000000000000000000000000000..29d1f2301751621b84354b844691b304f7ca53c2
--- /dev/null
+++ b/src/quick/scenegraph/shaders/24bittextmask_core.frag
@@ -0,0 +1,14 @@
+#version 150 core
+
+in vec2 sampleCoord;
+
+out vec4 fragColor;
+
+uniform sampler2D _qt_texture;
+uniform float color; // just the alpha, really...
+
+void main()
+{
+    vec4 glyph = texture(_qt_texture, sampleCoord);
+    fragColor = vec4(glyph.rgb * color, glyph.a);
+}
\ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/8bittextmask.frag b/src/quick/scenegraph/shaders/8bittextmask.frag
index f2f06e8e0705f6a28f169a79c4c7c514deb15b47..44ffb279cbd0b59c14722ffd62e9fbb76b687079 100644
--- a/src/quick/scenegraph/shaders/8bittextmask.frag
+++ b/src/quick/scenegraph/shaders/8bittextmask.frag
@@ -1,9 +1,9 @@
 varying highp vec2 sampleCoord;
 
-uniform lowp sampler2D texture;
+uniform lowp sampler2D _qt_texture;
 uniform lowp vec4 color;
 
 void main()
 {
-    gl_FragColor = color * texture2D(texture, sampleCoord).a;
+    gl_FragColor = color * texture2D(_qt_texture, sampleCoord).a;
 }
\ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/8bittextmask_core.frag b/src/quick/scenegraph/shaders/8bittextmask_core.frag
new file mode 100644
index 0000000000000000000000000000000000000000..2d67a4676af35a2e15bc0f2e9157be55d8149ce2
--- /dev/null
+++ b/src/quick/scenegraph/shaders/8bittextmask_core.frag
@@ -0,0 +1,13 @@
+#version 150 core
+
+in vec2 sampleCoord;
+
+out vec4 fragColor;
+
+uniform sampler2D _qt_texture;
+uniform vec4 color;
+
+void main()
+{
+    fragColor = color * texture(_qt_texture, sampleCoord).r;
+}
\ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/distancefieldoutlinetext_core.frag b/src/quick/scenegraph/shaders/distancefieldoutlinetext_core.frag
new file mode 100644
index 0000000000000000000000000000000000000000..80fa05ca3cff72e820128bf589b6a52854160566
--- /dev/null
+++ b/src/quick/scenegraph/shaders/distancefieldoutlinetext_core.frag
@@ -0,0 +1,20 @@
+#version 150 core
+
+in vec2 sampleCoord;
+
+out vec4 fragColor;
+
+uniform sampler2D _qt_texture;
+uniform vec4 color;
+uniform vec4 styleColor;
+uniform float alphaMin;
+uniform float alphaMax;
+uniform float outlineAlphaMax0;
+uniform float outlineAlphaMax1;
+
+void main()
+{
+    float d = texture(_qt_texture, sampleCoord).r;
+    fragColor = mix(styleColor, color, smoothstep(alphaMin, alphaMax, d))
+                    * smoothstep(outlineAlphaMax0, outlineAlphaMax1, d);
+}
\ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/distancefieldshiftedtext_core.frag b/src/quick/scenegraph/shaders/distancefieldshiftedtext_core.frag
new file mode 100644
index 0000000000000000000000000000000000000000..3f66965e789968a18b482434ccd99e0735b47b77
--- /dev/null
+++ b/src/quick/scenegraph/shaders/distancefieldshiftedtext_core.frag
@@ -0,0 +1,20 @@
+#version 150 core
+
+in vec2 sampleCoord;
+in vec2 shiftedSampleCoord;
+
+out vec4 fragColor;
+
+uniform sampler2D _qt_texture;
+uniform vec4 color;
+uniform vec4 styleColor;
+uniform float alphaMin;
+uniform float alphaMax;
+
+void main()
+{
+    float a = smoothstep(alphaMin, alphaMax, texture(_qt_texture, sampleCoord).r);
+    vec4 shifted = styleColor * smoothstep(alphaMin, alphaMax,
+                                           texture(_qt_texture, shiftedSampleCoord).r);
+    fragColor = mix(shifted, color, a);
+}
\ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/distancefieldshiftedtext_core.vert b/src/quick/scenegraph/shaders/distancefieldshiftedtext_core.vert
new file mode 100644
index 0000000000000000000000000000000000000000..b7a3ecc66759755b1ff5902a6d4bbc642f3485d0
--- /dev/null
+++ b/src/quick/scenegraph/shaders/distancefieldshiftedtext_core.vert
@@ -0,0 +1,18 @@
+#version 150 core
+
+in vec4 vCoord;
+in vec2 tCoord;
+
+out vec2 sampleCoord;
+out vec2 shiftedSampleCoord;
+
+uniform mat4 matrix;
+uniform vec2 textureScale;
+uniform vec2 shift;
+
+void main()
+{
+     sampleCoord = tCoord * textureScale;
+     shiftedSampleCoord = (tCoord - shift) * textureScale;
+     gl_Position = matrix * vCoord;
+}
\ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/distancefieldtext_core.frag b/src/quick/scenegraph/shaders/distancefieldtext_core.frag
new file mode 100644
index 0000000000000000000000000000000000000000..9c64a60d3df327fd704756e4e1c2f2984e35530b
--- /dev/null
+++ b/src/quick/scenegraph/shaders/distancefieldtext_core.frag
@@ -0,0 +1,16 @@
+#version 150 core
+
+in vec2 sampleCoord;
+
+out vec4 fragColor;
+
+uniform sampler2D _qt_texture;
+uniform vec4 color;
+uniform float alphaMin;
+uniform float alphaMax;
+
+void main()
+{
+    fragColor = color * smoothstep(alphaMin, alphaMax,
+                                   texture(_qt_texture, sampleCoord).r);
+}
\ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/distancefieldtext_core.vert b/src/quick/scenegraph/shaders/distancefieldtext_core.vert
new file mode 100644
index 0000000000000000000000000000000000000000..7fc693d139d5ad322fd7f9d34a7c5da503784991
--- /dev/null
+++ b/src/quick/scenegraph/shaders/distancefieldtext_core.vert
@@ -0,0 +1,15 @@
+#version 150 core
+
+in vec4 vCoord;
+in vec2 tCoord;
+
+out vec2 sampleCoord;
+
+uniform mat4 matrix;
+uniform vec2 textureScale;
+
+void main()
+{
+     sampleCoord = tCoord * textureScale;
+     gl_Position = matrix * vCoord;
+}
\ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/flatcolor_core.frag b/src/quick/scenegraph/shaders/flatcolor_core.frag
new file mode 100644
index 0000000000000000000000000000000000000000..23a957ad7bddc1722b390f2bf4134a7830a3d60a
--- /dev/null
+++ b/src/quick/scenegraph/shaders/flatcolor_core.frag
@@ -0,0 +1,10 @@
+#version 150 core
+
+out vec4 fragColor;
+
+uniform vec4 color;
+
+void main()
+{
+    fragColor = color;
+}
\ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/flatcolor_core.vert b/src/quick/scenegraph/shaders/flatcolor_core.vert
new file mode 100644
index 0000000000000000000000000000000000000000..e33c591b9538d66f08aa6e562b0c6ce925c9ec2e
--- /dev/null
+++ b/src/quick/scenegraph/shaders/flatcolor_core.vert
@@ -0,0 +1,10 @@
+#version 150 core
+
+in vec4 vCoord;
+
+uniform mat4 matrix;
+
+void main()
+{
+    gl_Position = matrix * vCoord;
+}
diff --git a/src/quick/scenegraph/shaders/hiqsubpixeldistancefieldtext_core.frag b/src/quick/scenegraph/shaders/hiqsubpixeldistancefieldtext_core.frag
new file mode 100644
index 0000000000000000000000000000000000000000..cf6ba2b8d9c843c1ed9b545a8551312aad54a43f
--- /dev/null
+++ b/src/quick/scenegraph/shaders/hiqsubpixeldistancefieldtext_core.frag
@@ -0,0 +1,32 @@
+#version 150 core
+
+in vec2 sampleCoord;
+in vec3 sampleFarLeft;
+in vec3 sampleNearLeft;
+in vec3 sampleNearRight;
+in vec3 sampleFarRight;
+
+out vec4 fragColor;
+
+uniform sampler2D _qt_texture;
+uniform vec4 color;
+uniform float alphaMin;
+uniform float alphaMax;
+
+void main()
+{
+    vec4 n;
+    n.x = textureProj(_qt_texture, sampleFarLeft).r;
+    n.y = textureProj(_qt_texture, sampleNearLeft).r;
+    float c = texture(_qt_texture, sampleCoord).r;
+    n.z = textureProj(_qt_texture, sampleNearRight).r;
+    n.w = textureProj(_qt_texture, sampleFarRight).r;
+
+    vec2 d = min(abs(n.yw - n.xz) * 2., 0.67);
+    vec2 lo = mix(vec2(alphaMin), vec2(0.5), d);
+    vec2 hi = mix(vec2(alphaMax), vec2(0.5), d);
+    n = smoothstep(lo.xxyy, hi.xxyy, n);
+    c = smoothstep(lo.x + lo.y, hi.x + hi.y, 2. * c);
+
+    fragColor = vec4(0.333 * (n.xyz + n.yzw + c), c) * color.w;
+}
\ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/hiqsubpixeldistancefieldtext_core.vert b/src/quick/scenegraph/shaders/hiqsubpixeldistancefieldtext_core.vert
new file mode 100644
index 0000000000000000000000000000000000000000..936f74725b3a40817456f3d6ad17dc55c20c0392
--- /dev/null
+++ b/src/quick/scenegraph/shaders/hiqsubpixeldistancefieldtext_core.vert
@@ -0,0 +1,36 @@
+#version 150 core
+
+in vec4 vCoord;
+in vec2 tCoord;
+
+out vec2 sampleCoord;
+out vec3 sampleFarLeft;
+out vec3 sampleNearLeft;
+out vec3 sampleNearRight;
+out vec3 sampleFarRight;
+
+uniform mat4 matrix;
+uniform vec2 textureScale;
+uniform float fontScale;
+uniform vec4 vecDelta;
+
+void main()
+{
+    sampleCoord = tCoord * textureScale;
+    gl_Position = matrix * vCoord;
+
+    // Calculate neighbor pixel position in item space.
+    vec3 wDelta = gl_Position.w * vecDelta.xyw;
+    vec3 farLeft = vCoord.xyw - 0.667 * wDelta;
+    vec3 nearLeft = vCoord.xyw - 0.333 * wDelta;
+    vec3 nearRight = vCoord.xyw + 0.333 * wDelta;
+    vec3 farRight = vCoord.xyw + 0.667 * wDelta;
+
+    // Calculate neighbor texture coordinate.
+    vec2 scale = textureScale / fontScale;
+    vec2 base = sampleCoord - scale * vCoord.xy;
+    sampleFarLeft = vec3(base * farLeft.z + scale * farLeft.xy, farLeft.z);
+    sampleNearLeft = vec3(base * nearLeft.z + scale * nearLeft.xy, nearLeft.z);
+    sampleNearRight = vec3(base * nearRight.z + scale * nearRight.xy, nearRight.z);
+    sampleFarRight = vec3(base * farRight.z + scale * farRight.xy, farRight.z);
+}
\ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/loqsubpixeldistancefieldtext_core.frag b/src/quick/scenegraph/shaders/loqsubpixeldistancefieldtext_core.frag
new file mode 100644
index 0000000000000000000000000000000000000000..2dd588d3077245b46cf6501257f9ab4bcb78dab6
--- /dev/null
+++ b/src/quick/scenegraph/shaders/loqsubpixeldistancefieldtext_core.frag
@@ -0,0 +1,21 @@
+#version 150 core
+
+in vec3 sampleNearLeft;
+in vec3 sampleNearRight;
+
+out vec4 fragColor;
+
+uniform sampler2D _qt_texture;
+uniform vec4 color;
+uniform float alphaMin;
+uniform float alphaMax;
+
+void main()
+{
+    vec2 n;
+    n.x = textureProj(_qt_texture, sampleNearLeft).r;
+    n.y = textureProj(_qt_texture, sampleNearRight).r;
+    n = smoothstep(alphaMin, alphaMax, n);
+    float c = 0.5 * (n.x + n.y);
+    fragColor = vec4(n.x, c, n.y, c) * color.w;
+}
\ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/loqsubpixeldistancefieldtext_core.vert b/src/quick/scenegraph/shaders/loqsubpixeldistancefieldtext_core.vert
new file mode 100644
index 0000000000000000000000000000000000000000..b887a700016e64ecdb2b8340f65526768f053360
--- /dev/null
+++ b/src/quick/scenegraph/shaders/loqsubpixeldistancefieldtext_core.vert
@@ -0,0 +1,29 @@
+#version 150 core
+
+in vec4 vCoord;
+in vec2 tCoord;
+
+out vec3 sampleNearLeft;
+out vec3 sampleNearRight;
+
+uniform mat4 matrix;
+uniform vec2 textureScale;
+uniform float fontScale;
+uniform vec4 vecDelta;
+
+void main()
+{
+    vec2 sampleCoord = tCoord * textureScale;
+    gl_Position = matrix * vCoord;
+
+    // Calculate neighbor pixel position in item space.
+    vec3 wDelta = gl_Position.w * vecDelta.xyw;
+    vec3 nearLeft = vCoord.xyw - 0.25 * wDelta;
+    vec3 nearRight = vCoord.xyw + 0.25 * wDelta;
+
+    // Calculate neighbor texture coordinate.
+    vec2 scale = textureScale / fontScale;
+    vec2 base = sampleCoord - scale * vCoord.xy;
+    sampleNearLeft = vec3(base * nearLeft.z + scale * nearLeft.xy, nearLeft.z);
+    sampleNearRight = vec3(base * nearRight.z + scale * nearRight.xy, nearRight.z);
+}
\ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/opaquetexture_core.frag b/src/quick/scenegraph/shaders/opaquetexture_core.frag
new file mode 100644
index 0000000000000000000000000000000000000000..5f30e68677d5957cb2236c3c263583aa306fbdf1
--- /dev/null
+++ b/src/quick/scenegraph/shaders/opaquetexture_core.frag
@@ -0,0 +1,12 @@
+#version 150 core
+
+in vec2 qt_TexCoord;
+
+out vec4 fragColor;
+
+uniform sampler2D qt_Texture;
+
+void main()
+{
+    fragColor = texture(qt_Texture, qt_TexCoord);
+}
\ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/opaquetexture_core.vert b/src/quick/scenegraph/shaders/opaquetexture_core.vert
new file mode 100644
index 0000000000000000000000000000000000000000..419b1a825c8647f2edebb4ac714cdb97b3f593a2
--- /dev/null
+++ b/src/quick/scenegraph/shaders/opaquetexture_core.vert
@@ -0,0 +1,14 @@
+#version 150 core
+
+uniform mat4 qt_Matrix;
+
+in vec4 qt_VertexPosition;
+in vec2 qt_VertexTexCoord;
+
+out vec2 qt_TexCoord;
+
+void main()
+{
+    qt_TexCoord = qt_VertexTexCoord;
+    gl_Position = qt_Matrix * qt_VertexPosition;
+}
\ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/outlinedtext_core.frag b/src/quick/scenegraph/shaders/outlinedtext_core.frag
new file mode 100644
index 0000000000000000000000000000000000000000..e19c8937f9d8b949323ff187a948ddf57a0c2135
--- /dev/null
+++ b/src/quick/scenegraph/shaders/outlinedtext_core.frag
@@ -0,0 +1,25 @@
+#version 150 core
+
+in vec2 sampleCoord;
+in vec2 sCoordUp;
+in vec2 sCoordDown;
+in vec2 sCoordLeft;
+in vec2 sCoordRight;
+
+out vec4 fragColor;
+
+uniform sampler2D _qt_texture;
+uniform vec4 color;
+uniform vec4 styleColor;
+
+void main()
+{
+    float glyph = texture(_qt_texture, sampleCoord).r;
+    float outline = clamp(clamp(texture(_qt_texture, sCoordUp).r +
+                                texture(_qt_texture, sCoordDown).r +
+                                texture(_qt_texture, sCoordLeft).r +
+                                texture(_qt_texture, sCoordRight).r,
+                                0.0, 1.0) - glyph,
+                          0.0, 1.0);
+    fragColor = outline * styleColor + glyph * color;
+}
\ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/outlinedtext_core.vert b/src/quick/scenegraph/shaders/outlinedtext_core.vert
new file mode 100644
index 0000000000000000000000000000000000000000..4aa13101fdde508b218780e10cd11ead211c2eab
--- /dev/null
+++ b/src/quick/scenegraph/shaders/outlinedtext_core.vert
@@ -0,0 +1,24 @@
+#version 150 core
+
+in vec4 vCoord;
+in vec2 tCoord;
+
+out vec2 sampleCoord;
+out vec2 sCoordUp;
+out vec2 sCoordDown;
+out vec2 sCoordLeft;
+out vec2 sCoordRight;
+
+uniform mat4 matrix;
+uniform vec2 textureScale;
+uniform vec2 shift;
+
+void main()
+{
+     sampleCoord = tCoord * textureScale;
+     sCoordUp = (tCoord - vec2(0.0, -1.0)) * textureScale;
+     sCoordDown = (tCoord - vec2(0.0, 1.0)) * textureScale;
+     sCoordLeft = (tCoord - vec2(-1.0, 0.0)) * textureScale;
+     sCoordRight = (tCoord - vec2(1.0, 0.0)) * textureScale;
+     gl_Position = matrix * vCoord;
+}
\ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/rendernode_core.frag b/src/quick/scenegraph/shaders/rendernode_core.frag
new file mode 100644
index 0000000000000000000000000000000000000000..7c187265df284f7b3a7ff4970748a7af6b43769e
--- /dev/null
+++ b/src/quick/scenegraph/shaders/rendernode_core.frag
@@ -0,0 +1,12 @@
+#version 150 core
+
+uniform sampler2D tex;
+
+in vec2 t;
+
+out vec4 color;
+
+void main()
+{
+    fragColor = texture(tex, t);
+}
\ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/rendernode_core.vert b/src/quick/scenegraph/shaders/rendernode_core.vert
new file mode 100644
index 0000000000000000000000000000000000000000..a76d519a5ae027955410856a9f689bc55d6a5630
--- /dev/null
+++ b/src/quick/scenegraph/shaders/rendernode_core.vert
@@ -0,0 +1,12 @@
+#version 150 core
+
+in vec4 av;
+in vec2 at;
+
+out vec2 t;
+
+void main()
+{
+    gl_Position = av;
+    t = at;
+}
\ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/smoothcolor_core.frag b/src/quick/scenegraph/shaders/smoothcolor_core.frag
new file mode 100644
index 0000000000000000000000000000000000000000..84533c2b4019fcccbb05b7d4f00e411656ff5a15
--- /dev/null
+++ b/src/quick/scenegraph/shaders/smoothcolor_core.frag
@@ -0,0 +1,10 @@
+#version 150 core
+
+in vec4 color;
+
+out vec4 fragColor;
+
+void main()
+{
+    fragColor = color;
+}
\ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/smoothcolor_core.vert b/src/quick/scenegraph/shaders/smoothcolor_core.vert
new file mode 100644
index 0000000000000000000000000000000000000000..1eed751ccdc349b7346bf9033ff78bebb450c06b
--- /dev/null
+++ b/src/quick/scenegraph/shaders/smoothcolor_core.vert
@@ -0,0 +1,47 @@
+#version 150 core
+
+in vec4 vertex;
+in vec4 vertexColor;
+in vec2 vertexOffset;
+
+out vec4 color;
+
+uniform vec2 pixelSize;
+uniform mat4 matrix;
+uniform float opacity;
+
+void main()
+{
+    vec4 pos = matrix * vertex;
+    gl_Position = pos;
+
+    if (vertexOffset.x != 0.) {
+        vec4 delta = matrix[0] * vertexOffset.x;
+        vec2 dir = delta.xy * pos.w - pos.xy * delta.w;
+        vec2 ndir = .5 * pixelSize * normalize(dir / pixelSize);
+        dir -= ndir * delta.w * pos.w;
+        float numerator = dot(dir, ndir * pos.w * pos.w);
+        float scale = 0.0;
+        if (numerator < 0.0)
+            scale = 1.0;
+        else
+            scale = min(1.0, numerator / dot(dir, dir));
+        gl_Position += scale * delta;
+    }
+
+    if (vertexOffset.y != 0.) {
+        vec4 delta = matrix[1] * vertexOffset.y;
+        vec2 dir = delta.xy * pos.w - pos.xy * delta.w;
+        vec2 ndir = .5 * pixelSize * normalize(dir / pixelSize);
+        dir -= ndir * delta.w * pos.w;
+        float numerator = dot(dir, ndir * pos.w * pos.w);
+        float scale = 0.0;
+        if (numerator < 0.0)
+            scale = 1.0;
+        else
+            scale = min(1.0, numerator / dot(dir, dir));
+        gl_Position += scale * delta;
+    }
+
+    color = vertexColor * opacity;
+}
\ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/smoothtexture_core.frag b/src/quick/scenegraph/shaders/smoothtexture_core.frag
new file mode 100644
index 0000000000000000000000000000000000000000..8a9aefd4c81b844b7ce2abd5be0dfabc758d9996
--- /dev/null
+++ b/src/quick/scenegraph/shaders/smoothtexture_core.frag
@@ -0,0 +1,13 @@
+#version 150 core
+
+in vec2 texCoord;
+in float vertexOpacity;
+
+out vec4 fragColor;
+
+uniform sampler2D qt_Texture;
+
+void main()
+{
+    fragColor = texture(qt_Texture, texCoord) * vertexOpacity;
+}
\ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/smoothtexture_core.vert b/src/quick/scenegraph/shaders/smoothtexture_core.vert
new file mode 100644
index 0000000000000000000000000000000000000000..a2489a39c526a1fab66409a502fee97e87f49afe
--- /dev/null
+++ b/src/quick/scenegraph/shaders/smoothtexture_core.vert
@@ -0,0 +1,54 @@
+#version 150 core
+
+in vec4 vertex;
+in vec2 multiTexCoord;
+in vec2 vertexOffset;
+in vec2 texCoordOffset;
+
+out vec2 texCoord;
+out float vertexOpacity;
+
+uniform vec2 pixelSize;
+uniform mat4 qt_Matrix;
+uniform float opacity;
+
+void main()
+{
+    vec4 pos = qt_Matrix * vertex;
+    gl_Position = pos;
+    texCoord = multiTexCoord;
+
+    if (vertexOffset.x != 0.) {
+        vec4 delta = qt_Matrix[0] * vertexOffset.x;
+        vec2 dir = delta.xy * pos.w - pos.xy * delta.w;
+        vec2 ndir = .5 * pixelSize * normalize(dir / pixelSize);
+        dir -= ndir * delta.w * pos.w;
+        float numerator = dot(dir, ndir * pos.w * pos.w);
+        float scale = 0.0;
+        if (numerator < 0.0)
+            scale = 1.0;
+        else
+            scale = min(1.0, numerator / dot(dir, dir));
+        gl_Position += scale * delta;
+        texCoord.x += scale * texCoordOffset.x;
+    }
+
+    if (vertexOffset.y != 0.) {
+        vec4 delta = qt_Matrix[1] * vertexOffset.y;
+        vec2 dir = delta.xy * pos.w - pos.xy * delta.w;
+        vec2 ndir = .5 * pixelSize * normalize(dir / pixelSize);
+        dir -= ndir * delta.w * pos.w;
+        float numerator = dot(dir, ndir * pos.w * pos.w);
+        float scale = 0.0;
+        if (numerator < 0.0)
+            scale = 1.0;
+        else
+            scale = min(1.0, numerator / dot(dir, dir));
+        gl_Position += scale * delta;
+        texCoord.y += scale * texCoordOffset.y;
+    }
+
+    bool onEdge = any(notEqual(vertexOffset, vec2(0.)));
+    bool outerEdge = all(equal(texCoordOffset, vec2(0.)));
+    vertexOpacity = onEdge && outerEdge ? 0. : opacity;
+}
\ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/stencilclip_core.frag b/src/quick/scenegraph/shaders/stencilclip_core.frag
new file mode 100644
index 0000000000000000000000000000000000000000..4d05de4ca951cd009a4d3013897a74690086bd06
--- /dev/null
+++ b/src/quick/scenegraph/shaders/stencilclip_core.frag
@@ -0,0 +1,8 @@
+#version 150 core
+
+out vec4 fragColor;
+
+void main()
+{
+    fragColor = vec4(0.81, 0.83, 0.12, 1.0); // Trolltech green ftw!
+}
\ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/stencilclip_core.vert b/src/quick/scenegraph/shaders/stencilclip_core.vert
new file mode 100644
index 0000000000000000000000000000000000000000..37e240c7350393ed280d783b80241f9c70a693b5
--- /dev/null
+++ b/src/quick/scenegraph/shaders/stencilclip_core.vert
@@ -0,0 +1,10 @@
+#version 150 core
+
+in vec4 vCoord;
+
+uniform mat4 matrix;
+
+void main()
+{
+    gl_Position = matrix * vCoord;
+}
\ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/styledtext_core.frag b/src/quick/scenegraph/shaders/styledtext_core.frag
new file mode 100644
index 0000000000000000000000000000000000000000..50f64c64a280e8d5989b217e82866f2f01ff6011
--- /dev/null
+++ b/src/quick/scenegraph/shaders/styledtext_core.frag
@@ -0,0 +1,18 @@
+#version 150 core
+
+in vec2 sampleCoord;
+in vec2 shiftedSampleCoord;
+
+out vec4 color;
+
+uniform sampler2D _qt_texture;
+uniform vec4 color;
+uniform vec4 styleColor;
+
+void main()
+{
+    float glyph = texture(_qt_texture, sampleCoord).a;
+    float style = clamp(texture(_qt_texture, shiftedSampleCoord).r - glyph,
+                        0.0, 1.0);
+    fragColor = style * styleColor + glyph * color;
+}
\ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/styledtext_core.vert b/src/quick/scenegraph/shaders/styledtext_core.vert
new file mode 100644
index 0000000000000000000000000000000000000000..b7a3ecc66759755b1ff5902a6d4bbc642f3485d0
--- /dev/null
+++ b/src/quick/scenegraph/shaders/styledtext_core.vert
@@ -0,0 +1,18 @@
+#version 150 core
+
+in vec4 vCoord;
+in vec2 tCoord;
+
+out vec2 sampleCoord;
+out vec2 shiftedSampleCoord;
+
+uniform mat4 matrix;
+uniform vec2 textureScale;
+uniform vec2 shift;
+
+void main()
+{
+     sampleCoord = tCoord * textureScale;
+     shiftedSampleCoord = (tCoord - shift) * textureScale;
+     gl_Position = matrix * vCoord;
+}
\ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/textmask_core.frag b/src/quick/scenegraph/shaders/textmask_core.frag
new file mode 100644
index 0000000000000000000000000000000000000000..17dda53c97704f978f6934d74bff784090495a49
--- /dev/null
+++ b/src/quick/scenegraph/shaders/textmask_core.frag
@@ -0,0 +1,14 @@
+#version 150 core
+
+in vec2 sampleCoord;
+
+out vec4 fragColor;
+
+uniform sampler2D _qt_texture;
+uniform vec4 color;
+
+void main()
+{
+    vec4 glyph = texture(_qt_texture, sampleCoord);
+    fragColor = vec4(glyph.rgb * color.a, glyph.a);
+}
\ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/textmask_core.vert b/src/quick/scenegraph/shaders/textmask_core.vert
new file mode 100644
index 0000000000000000000000000000000000000000..619248dccb4ed9e13b76daba200f83b30d3c59c5
--- /dev/null
+++ b/src/quick/scenegraph/shaders/textmask_core.vert
@@ -0,0 +1,15 @@
+#version 150 core
+
+in vec4 vCoord;
+in vec2 tCoord;
+
+out vec2 sampleCoord;
+
+uniform mat4 matrix;
+uniform vec2 textureScale;
+
+void main()
+{
+     sampleCoord = tCoord * textureScale;
+     gl_Position = matrix * vCoord;
+}
diff --git a/src/quick/scenegraph/shaders/texture_core.frag b/src/quick/scenegraph/shaders/texture_core.frag
new file mode 100644
index 0000000000000000000000000000000000000000..d9bdf6a2383efdf270130ad936a670052e57eb9d
--- /dev/null
+++ b/src/quick/scenegraph/shaders/texture_core.frag
@@ -0,0 +1,13 @@
+#version 150 core
+
+in vec2 qt_TexCoord;
+
+out vec4 fragColor;
+
+uniform sampler2D qt_Texture;
+uniform float opacity;
+
+void main()
+{
+    fragColor = texture(qt_Texture, qt_TexCoord) * opacity;
+}
\ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/vertexcolor_core.frag b/src/quick/scenegraph/shaders/vertexcolor_core.frag
new file mode 100644
index 0000000000000000000000000000000000000000..84533c2b4019fcccbb05b7d4f00e411656ff5a15
--- /dev/null
+++ b/src/quick/scenegraph/shaders/vertexcolor_core.frag
@@ -0,0 +1,10 @@
+#version 150 core
+
+in vec4 color;
+
+out vec4 fragColor;
+
+void main()
+{
+    fragColor = color;
+}
\ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/vertexcolor_core.vert b/src/quick/scenegraph/shaders/vertexcolor_core.vert
new file mode 100644
index 0000000000000000000000000000000000000000..219b840913c067aef3a7e356d399fbe32249ac69
--- /dev/null
+++ b/src/quick/scenegraph/shaders/vertexcolor_core.vert
@@ -0,0 +1,15 @@
+#version 150 core
+
+in vec4 vertexCoord;
+in vec4 vertexColor;
+
+out vec4 color;
+
+uniform mat4 matrix;
+uniform float opacity;
+
+void main()
+{
+    gl_Position = matrix * vertexCoord;
+    color = vertexColor * opacity;
+}
\ No newline at end of file
diff --git a/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp b/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp
index c7dd1a97998aa428db93ffc1f553d9b6cfb5f14b..1a1963dbca93c118d649557eb064f2b4d2bff407 100644
--- a/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp
+++ b/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp
@@ -41,6 +41,7 @@
 
 #include "qsgshadersourcebuilder_p.h"
 
+#include <QtGui/qopenglcontext.h>
 #include <QtGui/qopenglshaderprogram.h>
 
 #include <QtCore/qdebug.h>
@@ -48,6 +49,162 @@
 
 QT_BEGIN_NAMESPACE
 
+namespace QSGShaderParser {
+
+struct Tokenizer {
+
+    enum Token {
+        Token_Invalid,
+        Token_Void,
+        Token_OpenBrace,
+        Token_CloseBrace,
+        Token_SemiColon,
+        Token_Identifier,
+        Token_Macro,
+        Token_Version,
+        Token_Extension,
+        Token_SingleLineComment,
+        Token_MultiLineCommentStart,
+        Token_MultiLineCommentEnd,
+        Token_NewLine,
+        Token_Unspecified,
+        Token_EOF
+    };
+
+    static const char *NAMES[];
+
+    void initialize(const char *input);
+    Token next();
+
+    const char *stream;
+    const char *pos;
+    const char *identifier;
+};
+
+const char *Tokenizer::NAMES[] = {
+    "Invalid",
+    "Void",
+    "OpenBrace",
+    "CloseBrace",
+    "SemiColon",
+    "Identifier",
+    "Macro",
+    "Version",
+    "Extension",
+    "SingleLineComment",
+    "MultiLineCommentStart",
+    "MultiLineCommentEnd",
+    "NewLine",
+    "Unspecified",
+    "EOF"
+};
+
+void Tokenizer::initialize(const char *input)
+{
+    stream = input;
+    pos = input;
+    identifier = input;
+}
+
+Tokenizer::Token Tokenizer::next()
+{
+    while (*pos != 0) {
+        char c = *pos++;
+        switch (c) {
+        case '/':
+            if (*pos == '/') {
+                // '//' comment
+                return Token_SingleLineComment;
+            } else if (*pos == '*') {
+                // /* */ comment
+                return Token_MultiLineCommentStart;
+            }
+            break;
+
+        case '*':
+            if (*pos == '/')
+                return Token_MultiLineCommentEnd;
+
+        case '\n':
+            return Token_NewLine;
+
+        case '\r':
+            if (*pos == '\n')
+                return Token_NewLine;
+
+        case '#': {
+            if (*pos == 'v' && pos[1] == 'e' && pos[2] == 'r' && pos[3] == 's'
+                && pos[4] == 'i' && pos[5] == 'o' && pos[6] == 'n') {
+                return Token_Version;
+            } else if (*pos == 'e' && pos[1] == 'x' && pos[2] == 't' && pos[3] == 'e'
+                       && pos[4] == 'n' && pos[5] == 's' && pos[6] == 'i'&& pos[7] == 'o'
+                       && pos[8] == 'n') {
+                return Token_Extension;
+            } else {
+                while (*pos != 0) {
+                    if (*pos == '\n') {
+                        ++pos;
+                        break;
+                    } else if (*pos == '\\') {
+                        ++pos;
+                        while (*pos != 0 && (*pos == ' ' || *pos == '\t'))
+                            ++pos;
+                        if (*pos != 0 && (*pos == '\n' || (*pos == '\r' && pos[1] == '\n')))
+                            pos+=2;
+                    } else {
+                        ++pos;
+                    }
+                }
+            }
+            break;
+        }
+
+        case ';':
+            return Token_SemiColon;
+
+        case 0:
+            return Token_EOF;
+
+        case '{':
+            return Token_OpenBrace;
+
+        case '}':
+            return Token_CloseBrace;
+
+        case ' ':
+            break;
+
+        case 'v': {
+            if (*pos == 'o' && pos[1] == 'i' && pos[2] == 'd') {
+                pos += 3;
+                return Token_Void;
+            }
+            // Fall-thru
+        }
+        default:
+            // Identifier...
+            if ((c >= 'a' && c <= 'z' ) || (c >= 'A' && c <= 'Z' ) || c == '_') {
+                identifier = pos - 1;
+                while (*pos != 0 && ((*pos >= 'a' && *pos <= 'z')
+                                     || (*pos >= 'A' && *pos <= 'Z')
+                                     || *pos == '_'
+                                     || (*pos >= '0' && *pos <= '9'))) {
+                    ++pos;
+                }
+                return Token_Identifier;
+            } else {
+                return Token_Unspecified;
+            }
+        }
+    }
+
+    return Token_Invalid;
+}
+
+} // namespace QSGShaderParser
+
+using namespace QSGShaderParser;
+
 QSGShaderSourceBuilder::QSGShaderSourceBuilder()
 {
 }
@@ -87,7 +244,7 @@ void QSGShaderSourceBuilder::appendSource(const QByteArray &source)
 void QSGShaderSourceBuilder::appendSourceFile(const QString &fileName)
 {
     const QString resolvedFileName = resolveShaderPath(fileName);
-    QFile f(fileName);
+    QFile f(resolvedFileName);
     if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) {
         qWarning() << "Failed to find shader" << resolvedFileName;
         return;
@@ -95,12 +252,152 @@ void QSGShaderSourceBuilder::appendSourceFile(const QString &fileName)
     m_source += f.readAll();
 }
 
+void QSGShaderSourceBuilder::addDefinition(const QByteArray &definition)
+{
+    if (definition.isEmpty())
+        return;
+
+    Tokenizer tok;
+    const char *input = m_source.constData();
+    tok.initialize(input);
+
+    // First find #version, #extension's and "void main() { ... "
+    const char *versionPos = 0;
+    const char *extensionPos = 0;
+    bool inSingleLineComment = false;
+    bool inMultiLineComment = false;
+    bool foundVersionStart = false;
+    bool foundExtensionStart = false;
+
+    Tokenizer::Token lt = Tokenizer::Token_Unspecified;
+    Tokenizer::Token t = tok.next();
+    while (t != Tokenizer::Token_EOF) {
+        // Handle comment blocks
+        if (t == Tokenizer::Token_MultiLineCommentStart )
+            inMultiLineComment = true;
+        if (t == Tokenizer::Token_MultiLineCommentEnd)
+            inMultiLineComment = false;
+        if (t == Tokenizer::Token_SingleLineComment)
+            inSingleLineComment = true;
+        if (t == Tokenizer::Token_NewLine && inSingleLineComment && !inMultiLineComment)
+            inSingleLineComment = false;
+
+        // Have we found #version, #extension or void main()?
+        if (t == Tokenizer::Token_Version && !inSingleLineComment && !inMultiLineComment)
+            foundVersionStart = true;
+
+        if (t == Tokenizer::Token_Extension && !inSingleLineComment && !inMultiLineComment)
+            foundExtensionStart = true;
+
+        if (foundVersionStart && t == Tokenizer::Token_NewLine) {
+            versionPos = tok.pos;
+            foundVersionStart = false;
+        } else if (foundExtensionStart && t == Tokenizer::Token_NewLine) {
+            extensionPos = tok.pos;
+            foundExtensionStart = false;
+        } else if (lt == Tokenizer::Token_Void && t == Tokenizer::Token_Identifier) {
+            if (qstrncmp("main", tok.identifier, 4) == 0)
+                break;
+        }
+
+        // Scan to next token
+        lt = t;
+        t = tok.next();
+    }
+
+    // Determine where to insert the definition.
+    // If we found #extension directives, insert after last one,
+    // else, if we found #version insert after #version
+    // otherwise, insert at beginning.
+    const char *insertionPos = extensionPos ? extensionPos : (versionPos ? versionPos : input);
+
+    // Construct a new shader string, inserting the definition
+    QByteArray newSource;
+    newSource.reserve(m_source.size() + definition.size() + 9);
+    newSource += QByteArray::fromRawData(input, insertionPos - input);
+    newSource += QByteArrayLiteral("#define ") + definition + QByteArrayLiteral("\n");
+    newSource += QByteArray::fromRawData(insertionPos, m_source.size() - (insertionPos - input));
+
+    m_source = newSource;
+}
+
+void QSGShaderSourceBuilder::removeVersion()
+{
+    Tokenizer tok;
+    const char *input = m_source.constData();
+    tok.initialize(input);
+
+    // First find #version beginning and end (if present)
+    const char *versionStartPos = 0;
+    const char *versionEndPos = 0;
+    bool inSingleLineComment = false;
+    bool inMultiLineComment = false;
+    bool foundVersionStart = false;
+
+    Tokenizer::Token lt = Tokenizer::Token_Unspecified;
+    Tokenizer::Token t = tok.next();
+    while (t != Tokenizer::Token_EOF) {
+        // Handle comment blocks
+        if (t == Tokenizer::Token_MultiLineCommentStart )
+            inMultiLineComment = true;
+        if (t == Tokenizer::Token_MultiLineCommentEnd)
+            inMultiLineComment = false;
+        if (t == Tokenizer::Token_SingleLineComment)
+            inSingleLineComment = true;
+        if (t == Tokenizer::Token_NewLine && inSingleLineComment && !inMultiLineComment)
+            inSingleLineComment = false;
+
+        // Have we found #version, #extension or void main()?
+        if (t == Tokenizer::Token_Version && !inSingleLineComment && !inMultiLineComment) {
+            versionStartPos = tok.pos - 1;
+            foundVersionStart = true;
+        } else if (foundVersionStart && t == Tokenizer::Token_NewLine) {
+            versionEndPos = tok.pos;
+            break;
+        } else if (lt == Tokenizer::Token_Void && t == Tokenizer::Token_Identifier) {
+            if (qstrncmp("main", tok.identifier, 4) == 0)
+                break;
+        }
+
+        // Scan to next token
+        lt = t;
+        t = tok.next();
+    }
+
+    if (versionStartPos == 0)
+        return;
+
+    // Construct a new shader string, inserting the definition
+    QByteArray newSource;
+    newSource.reserve(m_source.size() - (versionEndPos - versionStartPos));
+    newSource += QByteArray::fromRawData(input, versionStartPos - input);
+    newSource += QByteArray::fromRawData(versionEndPos, m_source.size() - (versionEndPos - versionStartPos));
+
+    m_source = newSource;
+}
+
 QString QSGShaderSourceBuilder::resolveShaderPath(const QString &path) const
 {
-    // For now, just return the path unaltered.
-    // TODO: Resolve to more specific filename based upon OpenGL profile and
-    // version, platform, GPU type etc
-    return path;
+    if (contextProfile() != QSurfaceFormat::CoreProfile) {
+        return path;
+    } else {
+        int idx = path.lastIndexOf(QStringLiteral("."));
+        QString resolvedPath;
+        if (idx != -1)
+            resolvedPath = path.left(idx)
+                         + QStringLiteral("_core")
+                         + path.right(path.length() - idx);
+        return resolvedPath;
+    }
+}
+
+QSurfaceFormat::OpenGLContextProfile QSGShaderSourceBuilder::contextProfile() const
+{
+    QOpenGLContext *context = QOpenGLContext::currentContext();
+    QSurfaceFormat::OpenGLContextProfile profile = QSurfaceFormat::NoProfile;
+    Q_ASSERT(context);
+    profile = context->format().profile();
+    return profile;
 }
 
 QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/util/qsgshadersourcebuilder_p.h b/src/quick/scenegraph/util/qsgshadersourcebuilder_p.h
index 8def250d4f51ea11101c5ab8206ddccfea814f6f..63f2d787672b8baa12874cc05755f7cd7cd8d0a6 100644
--- a/src/quick/scenegraph/util/qsgshadersourcebuilder_p.h
+++ b/src/quick/scenegraph/util/qsgshadersourcebuilder_p.h
@@ -44,6 +44,7 @@
 
 #include <private/qtquickglobal_p.h>
 
+#include <QtGui/qsurfaceformat.h>
 #include <QtCore/qbytearray.h>
 
 QT_BEGIN_NAMESPACE
@@ -64,11 +65,15 @@ public:
 
     void appendSource(const QByteArray &source);
     void appendSourceFile(const QString &fileName);
+    void addDefinition(const QByteArray &definition);
+    void removeVersion();
 
 protected:
     virtual QString resolveShaderPath(const QString &path) const;
 
 private:
+    QSurfaceFormat::OpenGLContextProfile contextProfile() const;
+
     QByteArray m_source;
 };
 
diff --git a/src/quick/scenegraph/util/qsgtexture.cpp b/src/quick/scenegraph/util/qsgtexture.cpp
index b079100a370c4cc4f6b51f0e1d7cf1a85b88b16a..ddee887bd1af8b093fe5f734b38f2d55c7215508 100644
--- a/src/quick/scenegraph/util/qsgtexture.cpp
+++ b/src/quick/scenegraph/util/qsgtexture.cpp
@@ -682,14 +682,14 @@ void QSGPlainTexture::bind()
     GLenum externalFormat = GL_RGBA;
     GLenum internalFormat = GL_RGBA;
 
-    const char *extensions = (const char *) glGetString(GL_EXTENSIONS);
-    if (strstr(extensions, "GL_EXT_bgra")) {
+    QOpenGLContext *context = QOpenGLContext::currentContext();
+    if (context->hasExtension(QByteArrayLiteral("GL_EXT_bgra"))) {
         externalFormat = GL_BGRA;
 #ifdef QT_OPENGL_ES
         internalFormat = GL_BGRA;
 #endif
-    } else if (strstr(extensions, "GL_EXT_texture_format_BGRA8888")
-               || strstr(extensions, "GL_IMG_texture_format_BGRA8888")) {
+    } else if (context->hasExtension(QByteArrayLiteral("GL_EXT_texture_format_BGRA8888"))
+            || context->hasExtension(QByteArrayLiteral("GL_IMG_texture_format_BGRA8888"))) {
         externalFormat = GL_BGRA;
         internalFormat = GL_BGRA;
     } else {
@@ -711,8 +711,7 @@ void QSGPlainTexture::bind()
 
 
     if (m_has_mipmaps) {
-        QOpenGLContext *ctx = QOpenGLContext::currentContext();
-        ctx->functions()->glGenerateMipmap(GL_TEXTURE_2D);
+        context->functions()->glGenerateMipmap(GL_TEXTURE_2D);
         m_mipmaps_generated = true;
     }