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; }