1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 //
41 //  W A R N I N G
42 //  -------------
43 //
44 // This file is not part of the Qt API.  It exists purely as an
45 // implementation detail.  This header file may change from version to
46 // version without notice, or even be removed.
47 //
48 // We mean it.
49 //
50 
51 
52 #ifndef QOPENGL_ENGINE_SHADER_SOURCE_H
53 #define QOPENGL_ENGINE_SHADER_SOURCE_H
54 
55 #include <QtGui/private/qtguiglobal_p.h>
56 #include "qopenglengineshadermanager_p.h"
57 
58 QT_BEGIN_NAMESPACE
59 
60 
61 static const char* const qopenglslMainVertexShader = "\n\
62     void setPosition(); \n\
63     void main(void) \n\
64     { \n\
65         setPosition(); \n\
66     }\n";
67 
68 static const char* const qopenglslMainWithTexCoordsVertexShader = "\n\
69     attribute highp   vec2      textureCoordArray; \n\
70     varying   highp   vec2      textureCoords; \n\
71     void setPosition(); \n\
72     void main(void) \n\
73     { \n\
74         setPosition(); \n\
75         textureCoords = textureCoordArray; \n\
76     }\n";
77 
78 static const char* const qopenglslMainWithTexCoordsAndOpacityVertexShader = "\n\
79     attribute highp   vec2      textureCoordArray; \n\
80     attribute lowp    float     opacityArray; \n\
81     varying   highp   vec2      textureCoords; \n\
82     varying   lowp    float     opacity; \n\
83     void setPosition(); \n\
84     void main(void) \n\
85     { \n\
86         setPosition(); \n\
87         textureCoords = textureCoordArray; \n\
88         opacity = opacityArray; \n\
89     }\n";
90 
91 // NOTE: We let GL do the perspective correction so texture lookups in the fragment
92 //       shader are also perspective corrected.
93 static const char* const qopenglslPositionOnlyVertexShader = "\n\
94     attribute highp   vec2      vertexCoordsArray; \n\
95     attribute highp   vec3      pmvMatrix1; \n\
96     attribute highp   vec3      pmvMatrix2; \n\
97     attribute highp   vec3      pmvMatrix3; \n\
98     void setPosition(void) \n\
99     { \n\
100         highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
101         vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
102         gl_Position = vec4(transformedPos.xy, 0.0, transformedPos.z); \n\
103     }\n";
104 
105 static const char* const qopenglslComplexGeometryPositionOnlyVertexShader = "\n\
106     uniform highp mat3 matrix; \n\
107     attribute highp vec2 vertexCoordsArray; \n\
108     void setPosition(void) \n\
109     { \n\
110       gl_Position = vec4(matrix * vec3(vertexCoordsArray, 1), 1);\n\
111     } \n";
112 
113 static const char* const qopenglslUntransformedPositionVertexShader = "\n\
114     attribute highp   vec4      vertexCoordsArray; \n\
115     void setPosition(void) \n\
116     { \n\
117         gl_Position = vertexCoordsArray; \n\
118     }\n";
119 
120 // Pattern Brush - This assumes the texture size is 8x8 and thus, the inverted size is 0.125
121 static const char* const qopenglslPositionWithPatternBrushVertexShader = "\n\
122     attribute highp   vec2      vertexCoordsArray; \n\
123     attribute highp   vec3      pmvMatrix1; \n\
124     attribute highp   vec3      pmvMatrix2; \n\
125     attribute highp   vec3      pmvMatrix3; \n\
126     uniform   mediump vec2      halfViewportSize; \n\
127     uniform   highp   vec2      invertedTextureSize; \n\
128     uniform   highp   mat3      brushTransform; \n\
129     varying   highp   vec2      patternTexCoords; \n\
130     void setPosition(void) \n\
131     { \n\
132         highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
133         vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
134         gl_Position.xy = transformedPos.xy / transformedPos.z; \n\
135         mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\
136         mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1.0); \n\
137         mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\
138         gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\
139         patternTexCoords.xy = (hTexCoords.xy * 0.125) * invertedHTexCoordsZ; \n\
140     }\n";
141 
142 static const char* const qopenglslAffinePositionWithPatternBrushVertexShader
143                  = qopenglslPositionWithPatternBrushVertexShader;
144 
145 static const char* const qopenglslPatternBrushSrcFragmentShader = "\n\
146     uniform           sampler2D brushTexture; \n\
147     uniform   lowp    vec4      patternColor; \n\
148     varying   highp   vec2      patternTexCoords;\n\
149     lowp vec4 srcPixel() \n\
150     { \n\
151         return patternColor * (1.0 - texture2D(brushTexture, patternTexCoords).r); \n\
152     }\n";
153 
154 
155 // Linear Gradient Brush
156 static const char* const qopenglslPositionWithLinearGradientBrushVertexShader = "\n\
157     attribute highp   vec2      vertexCoordsArray; \n\
158     attribute highp   vec3      pmvMatrix1; \n\
159     attribute highp   vec3      pmvMatrix2; \n\
160     attribute highp   vec3      pmvMatrix3; \n\
161     uniform   mediump vec2      halfViewportSize; \n\
162     uniform   highp   vec3      linearData; \n\
163     uniform   highp   mat3      brushTransform; \n\
164     varying   mediump float     index; \n\
165     void setPosition() \n\
166     { \n\
167         highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
168         vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
169         gl_Position.xy = transformedPos.xy / transformedPos.z; \n\
170         mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\
171         mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\
172         mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\
173         gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\
174         index = (dot(linearData.xy, hTexCoords.xy) * linearData.z) * invertedHTexCoordsZ; \n\
175     }\n";
176 
177 static const char* const qopenglslAffinePositionWithLinearGradientBrushVertexShader
178                  = qopenglslPositionWithLinearGradientBrushVertexShader;
179 
180 static const char* const qopenglslLinearGradientBrushSrcFragmentShader = "\n\
181     uniform           sampler2D brushTexture; \n\
182     varying   mediump float     index; \n\
183     lowp vec4 srcPixel() \n\
184     { \n\
185         mediump vec2 val = vec2(index, 0.5); \n\
186         return texture2D(brushTexture, val); \n\
187     }\n";
188 
189 
190 // Conical Gradient Brush
191 static const char* const qopenglslPositionWithConicalGradientBrushVertexShader = "\n\
192     attribute highp   vec2      vertexCoordsArray; \n\
193     attribute highp   vec3      pmvMatrix1; \n\
194     attribute highp   vec3      pmvMatrix2; \n\
195     attribute highp   vec3      pmvMatrix3; \n\
196     uniform   mediump vec2      halfViewportSize; \n\
197     uniform   highp   mat3      brushTransform; \n\
198     varying   highp   vec2      A; \n\
199     void setPosition(void) \n\
200     { \n\
201         highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
202         vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
203         gl_Position.xy = transformedPos.xy / transformedPos.z; \n\
204         mediump vec2  viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\
205         mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\
206         mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\
207         gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\
208         A = hTexCoords.xy * invertedHTexCoordsZ; \n\
209     }\n";
210 
211 static const char* const qopenglslAffinePositionWithConicalGradientBrushVertexShader
212                  = qopenglslPositionWithConicalGradientBrushVertexShader;
213 
214 static const char* const qopenglslConicalGradientBrushSrcFragmentShader = "\n\
215     #define INVERSE_2PI 0.1591549430918953358 \n\
216     uniform           sampler2D brushTexture; \n\
217     uniform   mediump float     angle; \n\
218     varying   highp   vec2      A; \n\
219     lowp vec4 srcPixel() \n\
220     { \n\
221         highp float t; \n\
222         if (abs(A.y) == abs(A.x)) \n\
223             t = (atan(-A.y + 0.002, A.x) + angle) * INVERSE_2PI; \n\
224         else \n\
225             t = (atan(-A.y, A.x) + angle) * INVERSE_2PI; \n\
226         return texture2D(brushTexture, vec2(t - floor(t), 0.5)); \n\
227     }\n";
228 
229 
230 // Radial Gradient Brush
231 static const char* const qopenglslPositionWithRadialGradientBrushVertexShader = "\n\
232     attribute highp   vec2      vertexCoordsArray;\n\
233     attribute highp   vec3      pmvMatrix1; \n\
234     attribute highp   vec3      pmvMatrix2; \n\
235     attribute highp   vec3      pmvMatrix3; \n\
236     uniform   mediump vec2      halfViewportSize; \n\
237     uniform   highp   mat3      brushTransform; \n\
238     uniform   highp   vec2      fmp; \n\
239     uniform   mediump vec3      bradius; \n\
240     varying   highp   float     b; \n\
241     varying   highp   vec2      A; \n\
242     void setPosition(void) \n\
243     {\n\
244         highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
245         vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
246         gl_Position.xy = transformedPos.xy / transformedPos.z; \n\
247         mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\
248         mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\
249         mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\
250         gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\
251         A = hTexCoords.xy * invertedHTexCoordsZ; \n\
252         b = bradius.x + 2.0 * dot(A, fmp); \n\
253     }\n";
254 
255 static const char* const qopenglslAffinePositionWithRadialGradientBrushVertexShader
256                  = qopenglslPositionWithRadialGradientBrushVertexShader;
257 
258 static const char* const qopenglslRadialGradientBrushSrcFragmentShader = "\n\
259     uniform           sampler2D brushTexture; \n\
260     uniform   highp   float     fmp2_m_radius2; \n\
261     uniform   highp   float     inverse_2_fmp2_m_radius2; \n\
262     uniform   highp   float     sqrfr; \n\
263     varying   highp   float     b; \n\
264     varying   highp   vec2      A; \n\
265     uniform   mediump vec3      bradius; \n\
266     lowp vec4 srcPixel() \n\
267     { \n\
268         highp float c = sqrfr-dot(A, A); \n\
269         highp float det = b*b - 4.0*fmp2_m_radius2*c; \n\
270         lowp vec4 result = vec4(0.0); \n\
271         if (det >= 0.0) { \n\
272             highp float detSqrt = sqrt(det); \n\
273             highp float w = max((-b - detSqrt) * inverse_2_fmp2_m_radius2, (-b + detSqrt) * inverse_2_fmp2_m_radius2); \n\
274             if (bradius.y + w * bradius.z >= 0.0) \n\
275                 result = texture2D(brushTexture, vec2(w, 0.5)); \n\
276         } \n\
277         return result; \n\
278     }\n";
279 
280 
281 // Texture Brush
282 static const char* const qopenglslPositionWithTextureBrushVertexShader = "\n\
283     attribute highp   vec2      vertexCoordsArray; \n\
284     attribute highp   vec3      pmvMatrix1; \n\
285     attribute highp   vec3      pmvMatrix2; \n\
286     attribute highp   vec3      pmvMatrix3; \n\
287     uniform   mediump vec2      halfViewportSize; \n\
288     uniform   highp   vec2      invertedTextureSize; \n\
289     uniform   highp   mat3      brushTransform; \n\
290     varying   highp   vec2      brushTextureCoords; \n\
291     void setPosition(void) \n\
292     { \n\
293         highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
294         vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
295         gl_Position.xy = transformedPos.xy / transformedPos.z; \n\
296         mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\
297         mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\
298         mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\
299         gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\
300         brushTextureCoords.xy = (hTexCoords.xy * invertedTextureSize) * gl_Position.w; \n\
301     }\n";
302 
303 static const char* const qopenglslAffinePositionWithTextureBrushVertexShader
304                  = qopenglslPositionWithTextureBrushVertexShader;
305 
306 static const char* const qopenglslTextureBrushSrcFragmentShader = "\n\
307     varying   highp   vec2      brushTextureCoords; \n\
308     uniform           sampler2D brushTexture; \n\
309     lowp vec4 srcPixel() \n\
310     { \n\
311         return texture2D(brushTexture, brushTextureCoords); \n\
312     }\n";
313 
314 static const char* const qopenglslTextureBrushSrcWithPatternFragmentShader = "\n\
315     varying   highp   vec2      brushTextureCoords; \n\
316     uniform   lowp    vec4      patternColor; \n\
317     uniform           sampler2D brushTexture; \n\
318     lowp vec4 srcPixel() \n\
319     { \n\
320         return patternColor * (1.0 - texture2D(brushTexture, brushTextureCoords).r); \n\
321     }\n";
322 
323 // Solid Fill Brush
324 static const char* const qopenglslSolidBrushSrcFragmentShader = "\n\
325     uniform   lowp    vec4      fragmentColor; \n\
326     lowp vec4 srcPixel() \n\
327     { \n\
328         return fragmentColor; \n\
329     }\n";
330 
331 static const char* const qopenglslImageSrcFragmentShader = "\n\
332     varying   highp   vec2      textureCoords; \n\
333     uniform           sampler2D imageTexture; \n\
334     lowp vec4 srcPixel() \n\
335     { \n"
336         "return texture2D(imageTexture, textureCoords); \n"
337     "}\n";
338 
339 static const char* const qopenglslCustomSrcFragmentShader = "\n\
340     varying   highp   vec2      textureCoords; \n\
341     uniform           sampler2D imageTexture; \n\
342     lowp vec4 srcPixel() \n\
343     { \n\
344         return customShader(imageTexture, textureCoords); \n\
345     }\n";
346 
347 static const char* const qopenglslImageSrcWithPatternFragmentShader = "\n\
348     varying   highp   vec2      textureCoords; \n\
349     uniform   lowp    vec4      patternColor; \n\
350     uniform           sampler2D imageTexture; \n\
351     lowp vec4 srcPixel() \n\
352     { \n\
353         return patternColor * (1.0 - texture2D(imageTexture, textureCoords).r); \n\
354     }\n";
355 
356 static const char* const qopenglslNonPremultipliedImageSrcFragmentShader = "\n\
357     varying   highp   vec2      textureCoords; \n\
358     uniform          sampler2D imageTexture; \n\
359     lowp vec4 srcPixel() \n\
360     { \n\
361         lowp vec4 sample = texture2D(imageTexture, textureCoords); \n\
362         sample.rgb = sample.rgb * sample.a; \n\
363         return sample; \n\
364     }\n";
365 
366 static const char* const qopenglslGrayscaleImageSrcFragmentShader = "\n\
367     varying   highp   vec2      textureCoords; \n\
368     uniform          sampler2D imageTexture; \n\
369     lowp vec4 srcPixel() \n\
370     { \n\
371         return texture2D(imageTexture, textureCoords).rrra; \n\
372     }\n";
373 
374 static const char* const qopenglslAlphaImageSrcFragmentShader = "\n\
375     varying   highp   vec2      textureCoords; \n\
376     uniform          sampler2D imageTexture; \n\
377     lowp vec4 srcPixel() \n\
378     { \n\
379         return vec4(0, 0, 0, texture2D(imageTexture, textureCoords).r); \n\
380     }\n";
381 
382 static const char* const qopenglslShockingPinkSrcFragmentShader = "\n\
383     lowp vec4 srcPixel() \n\
384     { \n\
385         return vec4(0.98, 0.06, 0.75, 1.0); \n\
386     }\n";
387 
388 static const char* const qopenglslMainFragmentShader_ImageArrays = "\n\
389     varying   lowp    float     opacity; \n\
390     lowp vec4 srcPixel(); \n\
391     void main() \n\
392     { \n\
393         gl_FragColor = srcPixel() * opacity; \n\
394     }\n";
395 
396 static const char* const qopenglslMainFragmentShader_MO = "\n\
397     uniform   lowp    float     globalOpacity; \n\
398     lowp vec4 srcPixel(); \n\
399     lowp vec4 applyMask(lowp vec4); \n\
400     void main() \n\
401     { \n\
402         gl_FragColor = applyMask(srcPixel()*globalOpacity); \n\
403     }\n";
404 
405 static const char* const qopenglslMainFragmentShader_M = "\n\
406     lowp vec4 srcPixel(); \n\
407     lowp vec4 applyMask(lowp vec4); \n\
408     void main() \n\
409     { \n\
410         gl_FragColor = applyMask(srcPixel()); \n\
411     }\n";
412 
413 static const char* const qopenglslMainFragmentShader_O = "\n\
414     uniform   lowp    float     globalOpacity; \n\
415     lowp vec4 srcPixel(); \n\
416     void main() \n\
417     { \n\
418         gl_FragColor = srcPixel()*globalOpacity; \n\
419     }\n";
420 
421 static const char* const qopenglslMainFragmentShader = "\n\
422     lowp vec4 srcPixel(); \n\
423     void main() \n\
424     { \n\
425         gl_FragColor = srcPixel(); \n\
426     }\n";
427 
428 static const char* const qopenglslMaskFragmentShader = "\n\
429     varying   highp   vec2      textureCoords;\n\
430     uniform           sampler2D maskTexture;\n\
431     lowp vec4 applyMask(lowp vec4 src) \n\
432     {\n\
433         lowp vec4 mask = texture2D(maskTexture, textureCoords); \n\
434         return src * mask.a; \n\
435     }\n";
436 
437 // For source over with subpixel antialiasing, the final color is calculated per component as follows
438 // (.a is alpha component, .c is red, green or blue component):
439 // alpha = src.a * mask.c * opacity
440 // dest.c = dest.c * (1 - alpha) + src.c * alpha
441 //
442 // In the first pass, calculate: dest.c = dest.c * (1 - alpha) with blend funcs: zero, 1 - source color
443 // In the second pass, calculate: dest.c = dest.c + src.c * alpha with blend funcs: one, one
444 //
445 // If source is a solid color (src is constant), only the first pass is needed, with blend funcs: constant, 1 - source color
446 
447 // For source composition with subpixel antialiasing, the final color is calculated per component as follows:
448 // alpha = src.a * mask.c * opacity
449 // dest.c = dest.c * (1 - mask.c) + src.c * alpha
450 //
451 
452 static const char* const qopenglslRgbMaskFragmentShaderPass1 = "\n\
453     varying   highp   vec2      textureCoords;\n\
454     uniform           sampler2D maskTexture;\n\
455     lowp vec4 applyMask(lowp vec4 src) \n\
456     { \n\
457         lowp vec4 mask = texture2D(maskTexture, textureCoords); \n\
458         return src.a * mask; \n\
459     }\n";
460 
461 static const char* const qopenglslRgbMaskFragmentShaderPass2 = "\n\
462     varying   highp   vec2      textureCoords;\n\
463     uniform           sampler2D maskTexture;\n\
464     lowp vec4 applyMask(lowp vec4 src) \n\
465     { \n\
466         lowp vec4 mask = texture2D(maskTexture, textureCoords); \n\
467         return src * mask; \n\
468     }\n";
469 
470 static const char* const qopenglslMultiplyCompositionModeFragmentShader = "\n\
471     #ifdef GL_KHR_blend_equation_advanced\n\
472     layout(blend_support_multiply) out;\n\
473     #endif\n";
474 
475 static const char* const qopenglslScreenCompositionModeFragmentShader = "\n\
476     #ifdef GL_KHR_blend_equation_advanced\n\
477     layout(blend_support_screen) out;\n\
478     #endif\n";
479 
480 static const char* const qopenglslOverlayCompositionModeFragmentShader = "\n\
481     #ifdef GL_KHR_blend_equation_advanced\n\
482     layout(blend_support_overlay) out;\n\
483     #endif\n";
484 
485 static const char* const qopenglslDarkenCompositionModeFragmentShader = "\n\
486     #ifdef GL_KHR_blend_equation_advanced\n\
487     layout(blend_support_darken) out;\n\
488     #endif\n";
489 
490 static const char* const qopenglslLightenCompositionModeFragmentShader = "\n\
491     #ifdef GL_KHR_blend_equation_advanced\n\
492     layout(blend_support_lighten) out;\n\
493     #endif\n";
494 
495 static const char* const qopenglslColorDodgeCompositionModeFragmentShader = "\n\
496     #ifdef GL_KHR_blend_equation_advanced\n\
497     layout(blend_support_colordodge) out;\n\
498     #endif\n";
499 
500 static const char* const qopenglslColorBurnCompositionModeFragmentShader = "\n\
501     #ifdef GL_KHR_blend_equation_advanced\n\
502     layout(blend_support_colorburn) out;\n\
503     #endif\n";
504 
505 static const char* const qopenglslHardLightCompositionModeFragmentShader = "\n\
506     #ifdef GL_KHR_blend_equation_advanced\n\
507     layout(blend_support_hardlight) out;\n\
508     #endif\n";
509 
510 static const char* const qopenglslSoftLightCompositionModeFragmentShader = "\n\
511     #ifdef GL_KHR_blend_equation_advanced\n\
512     layout(blend_support_softlight) out;\n\
513     #endif\n";
514 
515 static const char* const qopenglslDifferenceCompositionModeFragmentShader = "\n\
516     #ifdef GL_KHR_blend_equation_advanced\n\
517     layout(blend_support_difference) out;\n\
518     #endif\n";
519 
520 static const char* const qopenglslExclusionCompositionModeFragmentShader = "\n\
521     #ifdef GL_KHR_blend_equation_advanced\n\
522     layout(blend_support_exclusion) out;\n\
523     #endif\n";
524 
525 /*
526     Left to implement:
527         RgbMaskFragmentShader,
528         RgbMaskWithGammaFragmentShader,
529 */
530 
531 /*
532     OpenGL 3.2+ Core Profile shaders
533     The following shader snippets are copies of the snippets above
534     but use the modern GLSL 1.5 keywords. New shaders should make
535     a snippet for both profiles and add them appropriately in the
536     shader manager.
537 */
538 static const char* const qopenglslMainVertexShader_core =
539     "#version 150 core\n\
540     void setPosition(); \n\
541     void main(void) \n\
542     { \n\
543         setPosition(); \n\
544     }\n";
545 
546 static const char* const qopenglslMainWithTexCoordsVertexShader_core =
547     "#version 150 core\n\
548     in      vec2      textureCoordArray; \n\
549     out     vec2      textureCoords; \n\
550     void setPosition(); \n\
551     void main(void) \n\
552     { \n\
553         setPosition(); \n\
554         textureCoords = textureCoordArray; \n\
555     }\n";
556 
557 static const char* const qopenglslMainWithTexCoordsAndOpacityVertexShader_core =
558     "#version 150 core\n\
559     in      vec2      textureCoordArray; \n\
560     in      float     opacityArray; \n\
561     out     vec2      textureCoords; \n\
562     out     float     opacity; \n\
563     void setPosition(); \n\
564     void main(void) \n\
565     { \n\
566         setPosition(); \n\
567         textureCoords = textureCoordArray; \n\
568         opacity = opacityArray; \n\
569     }\n";
570 
571 // NOTE: We let GL do the perspective correction so texture lookups in the fragment
572 //       shader are also perspective corrected.
573 static const char* const qopenglslPositionOnlyVertexShader_core = "\n\
574     in      vec2      vertexCoordsArray; \n\
575     in      vec3      pmvMatrix1; \n\
576     in      vec3      pmvMatrix2; \n\
577     in      vec3      pmvMatrix3; \n\
578     void setPosition(void) \n\
579     { \n\
580         mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
581         vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
582         gl_Position = vec4(transformedPos.xy, 0.0, transformedPos.z); \n\
583     }\n";
584 
585 static const char* const qopenglslComplexGeometryPositionOnlyVertexShader_core = "\n\
586     in      vec2      vertexCoordsArray; \n\
587     uniform mat3      matrix; \n\
588     void setPosition(void) \n\
589     { \n\
590       gl_Position = vec4(matrix * vec3(vertexCoordsArray, 1), 1);\n\
591     } \n";
592 
593 static const char* const qopenglslUntransformedPositionVertexShader_core = "\n\
594     in      vec4      vertexCoordsArray; \n\
595     void setPosition(void) \n\
596     { \n\
597         gl_Position = vertexCoordsArray; \n\
598     }\n";
599 
600 // Pattern Brush - This assumes the texture size is 8x8 and thus, the inverted size is 0.125
601 static const char* const qopenglslPositionWithPatternBrushVertexShader_core = "\n\
602     in      vec2      vertexCoordsArray; \n\
603     in      vec3      pmvMatrix1; \n\
604     in      vec3      pmvMatrix2; \n\
605     in      vec3      pmvMatrix3; \n\
606     out     vec2      patternTexCoords; \n\
607     uniform vec2      halfViewportSize; \n\
608     uniform vec2      invertedTextureSize; \n\
609     uniform mat3      brushTransform; \n\
610     void setPosition(void) \n\
611     { \n\
612         mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
613         vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
614         gl_Position.xy = transformedPos.xy / transformedPos.z; \n\
615         vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\
616         vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1.0); \n\
617         float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\
618         gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\
619         patternTexCoords.xy = (hTexCoords.xy * 0.125) * invertedHTexCoordsZ; \n\
620     }\n";
621 
622 static const char* const qopenglslAffinePositionWithPatternBrushVertexShader_core
623                  = qopenglslPositionWithPatternBrushVertexShader_core;
624 
625 static const char* const qopenglslPatternBrushSrcFragmentShader_core = "\n\
626     in      vec2      patternTexCoords;\n\
627     uniform sampler2D brushTexture; \n\
628     uniform vec4      patternColor; \n\
629     vec4 srcPixel() \n\
630     { \n\
631         return patternColor * (1.0 - texture(brushTexture, patternTexCoords).r); \n\
632     }\n";
633 
634 
635 // Linear Gradient Brush
636 static const char* const qopenglslPositionWithLinearGradientBrushVertexShader_core = "\n\
637     in      vec2      vertexCoordsArray; \n\
638     in      vec3      pmvMatrix1; \n\
639     in      vec3      pmvMatrix2; \n\
640     in      vec3      pmvMatrix3; \n\
641     out     float     index; \n\
642     uniform vec2      halfViewportSize; \n\
643     uniform vec3      linearData; \n\
644     uniform mat3      brushTransform; \n\
645     void setPosition() \n\
646     { \n\
647         mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
648         vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
649         gl_Position.xy = transformedPos.xy / transformedPos.z; \n\
650         vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\
651         vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\
652         float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\
653         gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\
654         index = (dot(linearData.xy, hTexCoords.xy) * linearData.z) * invertedHTexCoordsZ; \n\
655     }\n";
656 
657 static const char* const qopenglslAffinePositionWithLinearGradientBrushVertexShader_core
658                  = qopenglslPositionWithLinearGradientBrushVertexShader_core;
659 
660 static const char* const qopenglslLinearGradientBrushSrcFragmentShader_core = "\n\
661     uniform sampler2D brushTexture; \n\
662     in      float     index; \n\
663     vec4 srcPixel() \n\
664     { \n\
665         vec2 val = vec2(index, 0.5); \n\
666         return texture(brushTexture, val); \n\
667     }\n";
668 
669 
670 // Conical Gradient Brush
671 static const char* const qopenglslPositionWithConicalGradientBrushVertexShader_core = "\n\
672     in      vec2      vertexCoordsArray; \n\
673     in      vec3      pmvMatrix1; \n\
674     in      vec3      pmvMatrix2; \n\
675     in      vec3      pmvMatrix3; \n\
676     out     vec2      A; \n\
677     uniform vec2      halfViewportSize; \n\
678     uniform mat3      brushTransform; \n\
679     void setPosition(void) \n\
680     { \n\
681         mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
682         vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
683         gl_Position.xy = transformedPos.xy / transformedPos.z; \n\
684         vec2  viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\
685         vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\
686         float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\
687         gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\
688         A = hTexCoords.xy * invertedHTexCoordsZ; \n\
689     }\n";
690 
691 static const char* const qopenglslAffinePositionWithConicalGradientBrushVertexShader_core
692                  = qopenglslPositionWithConicalGradientBrushVertexShader_core;
693 
694 static const char* const qopenglslConicalGradientBrushSrcFragmentShader_core = "\n\
695     #define INVERSE_2PI 0.1591549430918953358 \n\
696     in      vec2      A; \n\
697     uniform sampler2D brushTexture; \n\
698     uniform float     angle; \n\
699     vec4 srcPixel() \n\
700     { \n\
701         float t; \n\
702         if (abs(A.y) == abs(A.x)) \n\
703             t = (atan(-A.y + 0.002, A.x) + angle) * INVERSE_2PI; \n\
704         else \n\
705             t = (atan(-A.y, A.x) + angle) * INVERSE_2PI; \n\
706         return texture(brushTexture, vec2(t - floor(t), 0.5)); \n\
707     }\n";
708 
709 
710 // Radial Gradient Brush
711 static const char* const qopenglslPositionWithRadialGradientBrushVertexShader_core = "\n\
712     in      vec2      vertexCoordsArray;\n\
713     in      vec3      pmvMatrix1; \n\
714     in      vec3      pmvMatrix2; \n\
715     in      vec3      pmvMatrix3; \n\
716     out     float     b; \n\
717     out     vec2      A; \n\
718     uniform vec2      halfViewportSize; \n\
719     uniform mat3      brushTransform; \n\
720     uniform vec2      fmp; \n\
721     uniform vec3      bradius; \n\
722     void setPosition(void) \n\
723     {\n\
724         mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
725         vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
726         gl_Position.xy = transformedPos.xy / transformedPos.z; \n\
727         vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\
728         vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\
729         float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\
730         gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\
731         A = hTexCoords.xy * invertedHTexCoordsZ; \n\
732         b = bradius.x + 2.0 * dot(A, fmp); \n\
733     }\n";
734 
735 static const char* const qopenglslAffinePositionWithRadialGradientBrushVertexShader_core
736                  = qopenglslPositionWithRadialGradientBrushVertexShader_core;
737 
738 static const char* const qopenglslRadialGradientBrushSrcFragmentShader_core = "\n\
739     in      float     b; \n\
740     in      vec2      A; \n\
741     uniform sampler2D brushTexture; \n\
742     uniform float     fmp2_m_radius2; \n\
743     uniform float     inverse_2_fmp2_m_radius2; \n\
744     uniform float     sqrfr; \n\
745     uniform vec3      bradius; \n\
746     \n\
747     vec4 srcPixel() \n\
748     { \n\
749         float c = sqrfr-dot(A, A); \n\
750         float det = b*b - 4.0*fmp2_m_radius2*c; \n\
751         vec4 result = vec4(0.0); \n\
752         if (det >= 0.0) { \n\
753             float detSqrt = sqrt(det); \n\
754             float w = max((-b - detSqrt) * inverse_2_fmp2_m_radius2, (-b + detSqrt) * inverse_2_fmp2_m_radius2); \n\
755             if (bradius.y + w * bradius.z >= 0.0) \n\
756                 result = texture(brushTexture, vec2(w, 0.5)); \n\
757         } \n\
758         return result; \n\
759     }\n";
760 
761 
762 // Texture Brush
763 static const char* const qopenglslPositionWithTextureBrushVertexShader_core = "\n\
764     in      vec2      vertexCoordsArray; \n\
765     in      vec3      pmvMatrix1; \n\
766     in      vec3      pmvMatrix2; \n\
767     in      vec3      pmvMatrix3; \n\
768     out     vec2      brushTextureCoords; \n\
769     uniform vec2      halfViewportSize; \n\
770     uniform vec2      invertedTextureSize; \n\
771     uniform mat3      brushTransform; \n\
772     \n\
773     void setPosition(void) \n\
774     { \n\
775         mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
776         vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
777         gl_Position.xy = transformedPos.xy / transformedPos.z; \n\
778         vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\
779         vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\
780         float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\
781         gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\
782         brushTextureCoords.xy = (hTexCoords.xy * invertedTextureSize) * gl_Position.w; \n\
783     }\n";
784 
785 static const char* const qopenglslAffinePositionWithTextureBrushVertexShader_core
786                  = qopenglslPositionWithTextureBrushVertexShader_core;
787 
788 static const char* const qopenglslTextureBrushSrcFragmentShader_core = "\n\
789     in      vec2      brushTextureCoords; \n\
790     uniform sampler2D brushTexture; \n\
791     vec4 srcPixel() \n\
792     { \n\
793         return texture(brushTexture, brushTextureCoords); \n\
794     }\n";
795 
796 static const char* const qopenglslTextureBrushSrcWithPatternFragmentShader_core = "\n\
797     in      vec2      brushTextureCoords; \n\
798     uniform vec4      patternColor; \n\
799     uniform sampler2D brushTexture; \n\
800     vec4 srcPixel() \n\
801     { \n\
802         return patternColor * (1.0 - texture(brushTexture, brushTextureCoords).r); \n\
803     }\n";
804 
805 // Solid Fill Brush
806 static const char* const qopenglslSolidBrushSrcFragmentShader_core = "\n\
807     uniform vec4      fragmentColor; \n\
808     vec4 srcPixel() \n\
809     { \n\
810         return fragmentColor; \n\
811     }\n";
812 
813 static const char* const qopenglslImageSrcFragmentShader_core = "\n\
814     in      vec2      textureCoords; \n\
815     uniform sampler2D imageTexture; \n\
816     vec4 srcPixel() \n\
817     { \n\
818         return texture(imageTexture, textureCoords); \n\
819     }\n";
820 
821 static const char* const qopenglslCustomSrcFragmentShader_core = "\n\
822     in      vec2      textureCoords; \n\
823     uniform sampler2D imageTexture; \n\
824     vec4 srcPixel() \n\
825     { \n\
826         return customShader(imageTexture, textureCoords); \n\
827     }\n";
828 
829 static const char* const qopenglslImageSrcWithPatternFragmentShader_core = "\n\
830     in      vec2      textureCoords; \n\
831     uniform vec4      patternColor; \n\
832     uniform sampler2D imageTexture; \n\
833     vec4 srcPixel() \n\
834     { \n\
835         return patternColor * (1.0 - texture(imageTexture, textureCoords).r); \n\
836     }\n";
837 
838 static const char* const qopenglslNonPremultipliedImageSrcFragmentShader_core = "\n\
839     in      vec2      textureCoords; \n\
840     uniform sampler2D imageTexture; \n\
841     vec4 srcPixel() \n\
842     { \n\
843         vec4 sample = texture(imageTexture, textureCoords); \n\
844         sample.rgb = sample.rgb * sample.a; \n\
845         return sample; \n\
846     }\n";
847 
848 static const char* const qopenglslGrayscaleImageSrcFragmentShader_core = "\n\
849     in      vec2      textureCoords; \n\
850     uniform sampler2D imageTexture; \n\
851     vec4 srcPixel() \n\
852     { \n\
853         return texture(imageTexture, textureCoords).rrra; \n\
854     }\n";
855 
856 static const char* const qopenglslAlphaImageSrcFragmentShader_core = "\n\
857     in      vec2      textureCoords; \n\
858     uniform sampler2D imageTexture; \n\
859     vec4 srcPixel() \n\
860     { \n\
861         return vec4(0, 0, 0, texture(imageTexture, textureCoords).r); \n\
862     }\n";
863 
864 static const char* const qopenglslShockingPinkSrcFragmentShader_core = "\n\
865     vec4 srcPixel() \n\
866     { \n\
867         return vec4(0.98, 0.06, 0.75, 1.0); \n\
868     }\n";
869 
870 static const char* const qopenglslMainFragmentShader_ImageArrays_core =
871     "#version 150 core\n\
872     in      float     opacity; \n\
873     out     vec4      fragColor; \n\
874     vec4 srcPixel(); \n\
875     void main() \n\
876     { \n\
877         fragColor = srcPixel() * opacity; \n\
878     }\n";
879 
880 static const char* const qopenglslMainFragmentShader_MO_core =
881     "#version 150 core\n\
882     out     vec4      fragColor; \n\
883     uniform float     globalOpacity; \n\
884     vec4 srcPixel(); \n\
885     vec4 applyMask(vec4); \n\
886     void main() \n\
887     { \n\
888         fragColor = applyMask(srcPixel()*globalOpacity); \n\
889     }\n";
890 
891 static const char* const qopenglslMainFragmentShader_M_core =
892     "#version 150 core\n\
893     out     vec4      fragColor; \n\
894     vec4 srcPixel(); \n\
895     vec4 applyMask(vec4); \n\
896     void main() \n\
897     { \n\
898         fragColor = applyMask(srcPixel()); \n\
899     }\n";
900 
901 static const char* const qopenglslMainFragmentShader_O_core =
902     "#version 150 core\n\
903     out     vec4      fragColor; \n\
904     uniform float     globalOpacity; \n\
905     vec4 srcPixel(); \n\
906     void main() \n\
907     { \n\
908         fragColor = srcPixel()*globalOpacity; \n\
909     }\n";
910 
911 static const char* const qopenglslMainFragmentShader_core =
912     "#version 150 core\n\
913     out     vec4      fragColor; \n\
914     vec4 srcPixel(); \n\
915     void main() \n\
916     { \n\
917         fragColor = srcPixel(); \n\
918     }\n";
919 
920 static const char* const qopenglslMaskFragmentShader_core = "\n\
921     in      vec2      textureCoords;\n\
922     uniform sampler2D maskTexture;\n\
923     vec4 applyMask(vec4 src) \n\
924     {\n\
925         vec4 mask = texture(maskTexture, textureCoords); \n\
926         return src * mask.r; \n\
927     }\n";
928 
929 // For source over with subpixel antialiasing, the final color is calculated per component as follows
930 // (.a is alpha component, .c is red, green or blue component):
931 // alpha = src.a * mask.c * opacity
932 // dest.c = dest.c * (1 - alpha) + src.c * alpha
933 //
934 // In the first pass, calculate: dest.c = dest.c * (1 - alpha) with blend funcs: zero, 1 - source color
935 // In the second pass, calculate: dest.c = dest.c + src.c * alpha with blend funcs: one, one
936 //
937 // If source is a solid color (src is constant), only the first pass is needed, with blend funcs: constant, 1 - source color
938 
939 // For source composition with subpixel antialiasing, the final color is calculated per component as follows:
940 // alpha = src.a * mask.c * opacity
941 // dest.c = dest.c * (1 - mask.c) + src.c * alpha
942 //
943 
944 static const char* const qopenglslRgbMaskFragmentShaderPass1_core = "\n\
945     in      vec2      textureCoords;\n\
946     uniform sampler2D maskTexture;\n\
947     vec4 applyMask(vec4 src) \n\
948     { \n\
949         vec4 mask = texture(maskTexture, textureCoords); \n\
950         return src.a * mask; \n\
951     }\n";
952 
953 static const char* const qopenglslRgbMaskFragmentShaderPass2_core = "\n\
954     in      vec2      textureCoords;\n\
955     uniform sampler2D maskTexture;\n\
956     vec4 applyMask(vec4 src) \n\
957     { \n\
958         vec4 mask = texture(maskTexture, textureCoords); \n\
959         return src * mask; \n\
960     }\n";
961 
962 /*
963     Left to implement:
964         RgbMaskFragmentShader_core,
965         RgbMaskWithGammaFragmentShader_core,
966 */
967 
968 QT_END_NAMESPACE
969 
970 #endif // GLGC_SHADER_SOURCE_H
971