• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above
9  *    copyright notice, this list of conditions and the following
10  *    disclaimer.
11  * 2. Redistributions in binary form must reproduce the above
12  *    copyright notice, this list of conditions and the following
13  *    disclaimer in the documentation and/or other materials
14  *    provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
21  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
25  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
26  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 
30 #include "config.h"
31 #include "platform/graphics/filters/custom/CustomFilterValidatedProgram.h"
32 
33 #include "platform/NotImplemented.h"
34 #include "platform/graphics/angle/ANGLEPlatformBridge.h"
35 #include "platform/graphics/filters/custom/CustomFilterConstants.h"
36 #include "platform/graphics/filters/custom/CustomFilterGlobalContext.h"
37 #include "wtf/HashMap.h"
38 #include "wtf/Vector.h"
39 #include "wtf/text/StringBuilder.h"
40 #include "wtf/text/StringHash.h"
41 
42 namespace WebCore {
43 
44 #define SHADER(Src) (#Src)
45 
46 typedef HashMap<String, ShDataType> SymbolNameToTypeMap;
47 
builtInAttributeNameToTypeMap()48 static SymbolNameToTypeMap* builtInAttributeNameToTypeMap()
49 {
50     static SymbolNameToTypeMap* nameToTypeMap = 0;
51     if (!nameToTypeMap) {
52         nameToTypeMap = new SymbolNameToTypeMap;
53         nameToTypeMap->set("a_meshCoord", SH_FLOAT_VEC2);
54         nameToTypeMap->set("a_position", SH_FLOAT_VEC4);
55         nameToTypeMap->set("a_texCoord", SH_FLOAT_VEC2);
56         nameToTypeMap->set("a_triangleCoord", SH_FLOAT_VEC3);
57     }
58     return nameToTypeMap;
59 }
60 
builtInUniformNameToTypeMap()61 static SymbolNameToTypeMap* builtInUniformNameToTypeMap()
62 {
63     static SymbolNameToTypeMap* nameToTypeMap = 0;
64     if (!nameToTypeMap) {
65         nameToTypeMap = new SymbolNameToTypeMap;
66         nameToTypeMap->set("u_meshBox", SH_FLOAT_VEC4);
67         nameToTypeMap->set("u_meshSize", SH_FLOAT_VEC2);
68         nameToTypeMap->set("u_projectionMatrix", SH_FLOAT_MAT4);
69         nameToTypeMap->set("u_textureSize", SH_FLOAT_VEC2);
70         nameToTypeMap->set("u_tileSize", SH_FLOAT_VEC2);
71     }
72     return nameToTypeMap;
73 }
74 
validateSymbols(const Vector<ANGLEShaderSymbol> & symbols,CustomFilterMeshType meshType)75 static bool validateSymbols(const Vector<ANGLEShaderSymbol>& symbols, CustomFilterMeshType meshType)
76 {
77     for (size_t i = 0; i < symbols.size(); ++i) {
78         const ANGLEShaderSymbol& symbol = symbols[i];
79         switch (symbol.symbolType) {
80         case SHADER_SYMBOL_TYPE_ATTRIBUTE: {
81             SymbolNameToTypeMap* attributeNameToTypeMap = builtInAttributeNameToTypeMap();
82             SymbolNameToTypeMap::iterator builtInAttribute = attributeNameToTypeMap->find(symbol.name);
83             if (builtInAttribute == attributeNameToTypeMap->end()) {
84                 // The author defined a custom attribute.
85                 // FIXME: Report the validation error.
86                 // https://bugs.webkit.org/show_bug.cgi?id=74416
87                 return false;
88             }
89             if (meshType == MeshTypeAttached && symbol.name == "a_triangleCoord") {
90                 // a_triangleCoord is only available for detached meshes.
91                 // FIXME: Report the validation error.
92                 // https://bugs.webkit.org/show_bug.cgi?id=74416
93                 return false;
94             }
95             if (symbol.dataType != builtInAttribute->value) {
96                 // The author defined one of the built-in attributes with the wrong type.
97                 // FIXME: Report the validation error.
98                 // https://bugs.webkit.org/show_bug.cgi?id=74416
99                 return false;
100             }
101             break;
102         }
103         case SHADER_SYMBOL_TYPE_UNIFORM: {
104             if (symbol.isSampler()) {
105                 // FIXME: For now, we restrict shaders with any sampler defined.
106                 // When we implement texture parameters, we will allow shaders whose samplers are bound to valid textures.
107                 // We must not allow OpenGL to give unbound samplers a default value of 0 because that references the element texture,
108                 // which should be inaccessible to the author's shader code.
109                 // https://bugs.webkit.org/show_bug.cgi?id=96230
110                 return false;
111             }
112 
113             SymbolNameToTypeMap* uniformNameToTypeMap = builtInUniformNameToTypeMap();
114             SymbolNameToTypeMap::iterator builtInUniform = uniformNameToTypeMap->find(symbol.name);
115             if (builtInUniform != uniformNameToTypeMap->end() && (symbol.isArray || symbol.dataType != builtInUniform->value)) {
116                 // The author defined one of the built-in uniforms with the wrong type.
117                 // FIXME: Report the validation error.
118                 // https://bugs.webkit.org/show_bug.cgi?id=74416
119                 return false;
120             }
121             break;
122         }
123         default:
124             ASSERT_NOT_REACHED();
125             break;
126         }
127     }
128 
129     return true;
130 }
131 
defaultVertexShaderString()132 String CustomFilterValidatedProgram::defaultVertexShaderString()
133 {
134     DEFINE_STATIC_LOCAL(String, vertexShaderString, (SHADER(
135         attribute mediump vec4 a_position;
136         uniform mediump mat4 u_projectionMatrix;
137 
138         void main()
139         {
140             gl_Position = u_projectionMatrix * a_position;
141         }
142     )));
143     return vertexShaderString;
144 }
145 
defaultFragmentShaderString()146 String CustomFilterValidatedProgram::defaultFragmentShaderString()
147 {
148     DEFINE_STATIC_LOCAL(String, fragmentShaderString, (SHADER(
149         void main()
150         {
151         }
152     )));
153     return fragmentShaderString;
154 }
155 
CustomFilterValidatedProgram(CustomFilterGlobalContext * globalContext,const CustomFilterProgramInfo & programInfo)156 CustomFilterValidatedProgram::CustomFilterValidatedProgram(CustomFilterGlobalContext* globalContext, const CustomFilterProgramInfo& programInfo)
157     : m_globalContext(globalContext)
158     , m_programInfo(programInfo)
159     , m_isInitialized(false)
160 {
161     platformInit();
162 
163     String originalVertexShader = programInfo.vertexShaderString();
164     if (originalVertexShader.isNull())
165         originalVertexShader = defaultVertexShaderString();
166 
167     String originalFragmentShader = programInfo.fragmentShaderString();
168     if (originalFragmentShader.isNull())
169         originalFragmentShader = defaultFragmentShaderString();
170 
171     // Shaders referenced from the CSS mix function use a different validator than regular WebGL shaders. See core/platform/graphics/filters/custom/CustomFilterGlobalContext.h for more details.
172     bool blendsElementTexture = (programInfo.programType() == ProgramTypeBlendsElementTexture);
173     ANGLEPlatformBridge* validator = blendsElementTexture ? m_globalContext->mixShaderValidator() : m_globalContext->webglShaderValidator();
174     String vertexShaderLog, fragmentShaderLog;
175     Vector<ANGLEShaderSymbol> symbols;
176     bool vertexShaderValid = validator->compileShaderSource(originalVertexShader.utf8().data(), SHADER_TYPE_VERTEX, m_validatedVertexShader, vertexShaderLog, symbols);
177     bool fragmentShaderValid = validator->compileShaderSource(originalFragmentShader.utf8().data(), SHADER_TYPE_FRAGMENT, m_validatedFragmentShader, fragmentShaderLog, symbols);
178     if (!vertexShaderValid || !fragmentShaderValid) {
179         // FIXME: Report the validation errors.
180         // https://bugs.webkit.org/show_bug.cgi?id=74416
181         return;
182     }
183 
184     if (!validateSymbols(symbols, m_programInfo.meshType())) {
185         // FIXME: Report validation errors.
186         // https://bugs.webkit.org/show_bug.cgi?id=74416
187         return;
188     }
189 
190     // We need to add texture access, blending, and compositing code to shaders that are referenced from the CSS mix function.
191     if (blendsElementTexture) {
192         rewriteMixVertexShader(symbols);
193         rewriteMixFragmentShader();
194     }
195 
196     m_isInitialized = true;
197 }
198 
compiledProgram()199 PassRefPtr<CustomFilterCompiledProgram> CustomFilterValidatedProgram::compiledProgram()
200 {
201     ASSERT(m_isInitialized && m_globalContext && !m_validatedVertexShader.isNull() && !m_validatedFragmentShader.isNull());
202     if (!m_compiledProgram) {
203         m_compiledProgram = CustomFilterCompiledProgram::create(m_globalContext->context(), m_validatedVertexShader, m_validatedFragmentShader, m_programInfo.programType());
204         ASSERT(m_compiledProgram->isInitialized());
205         ASSERT(m_compiledProgram->samplerLocation() != -1 || !needsInputTexture());
206     }
207     return m_compiledProgram;
208 }
209 
needsInputTexture() const210 bool CustomFilterValidatedProgram::needsInputTexture() const
211 {
212     return m_programInfo.programType() == ProgramTypeBlendsElementTexture
213         && m_programInfo.mixSettings().compositeOperator != CompositeClear
214         && m_programInfo.mixSettings().compositeOperator != CompositeCopy;
215 }
216 
rewriteMixVertexShader(const Vector<ANGLEShaderSymbol> & symbols)217 void CustomFilterValidatedProgram::rewriteMixVertexShader(const Vector<ANGLEShaderSymbol>& symbols)
218 {
219     ASSERT(m_programInfo.programType() == ProgramTypeBlendsElementTexture);
220 
221     // If the author defined a_texCoord, we can use it to shuttle the texture coordinate to the fragment shader.
222     // Note that vertex attributes are read-only in GLSL, so the author could not have changed a_texCoord's value.
223     // Also, note that we would have already rejected the shader if the author defined a_texCoord with the wrong type.
224     bool texCoordAttributeDefined = false;
225     for (size_t i = 0; i < symbols.size(); ++i) {
226         if (symbols[i].name == "a_texCoord")
227             texCoordAttributeDefined = true;
228     }
229 
230     if (!texCoordAttributeDefined)
231         m_validatedVertexShader.append("attribute mediump vec2 a_texCoord;");
232 
233     // During validation, ANGLE renamed the author's "main" function to "css_main".
234     // We write our own "main" function and call "css_main" from it.
235     // This makes rewriting easy and ensures that our code runs after all author code.
236     m_validatedVertexShader.append(SHADER(
237         varying mediump vec2 css_v_texCoord;
238 
239         void main()
240         {
241             css_main();
242             css_v_texCoord = a_texCoord;
243         }
244     ));
245 }
246 
rewriteMixFragmentShader()247 void CustomFilterValidatedProgram::rewriteMixFragmentShader()
248 {
249     ASSERT(m_programInfo.programType() == ProgramTypeBlendsElementTexture);
250 
251     StringBuilder builder;
252     // ANGLE considered these symbols as built-ins during validation under the SH_CSS_SHADERS_SPEC flag.
253     // Now, we have to define these symbols in order to make this shader valid GLSL.
254     // We define these symbols before the author's shader code, which makes them accessible to author code.
255     builder.append(SHADER(
256         mediump vec4 css_MixColor = vec4(0.0);
257         mediump mat4 css_ColorMatrix = mat4(1.0);
258     ));
259     builder.append(m_validatedFragmentShader);
260     builder.append(blendFunctionString(m_programInfo.mixSettings().blendMode));
261     builder.append(compositeFunctionString(m_programInfo.mixSettings().compositeOperator));
262     // We define symbols like "css_u_texture" after the author's shader code, which makes them inaccessible to author code.
263     // In particular, "css_u_texture" represents the DOM element texture, so it's important to keep it inaccessible to
264     // author code for security reasons.
265     builder.append(SHADER(
266         uniform sampler2D css_u_texture;
267         varying mediump vec2 css_v_texCoord;
268 
269         void main()
270         {
271             css_main();
272             mediump vec4 originalColor = texture2D(css_u_texture, css_v_texCoord);
273             mediump vec4 multipliedColor = clamp(css_ColorMatrix * originalColor, 0.0, 1.0);
274             mediump vec4 clampedMixColor = clamp(css_MixColor, 0.0, 1.0);
275             mediump vec3 blendedColor = css_BlendColor(multipliedColor.rgb, clampedMixColor.rgb);
276             mediump vec3 weightedColor = (1.0 - multipliedColor.a) * clampedMixColor.rgb + multipliedColor.a * blendedColor;
277             gl_FragColor = css_Composite(multipliedColor.rgb, multipliedColor.a, weightedColor.rgb, clampedMixColor.a);
278         }
279     ));
280     m_validatedFragmentShader = builder.toString();
281 }
282 
blendFunctionString(blink::WebBlendMode blendMode)283 String CustomFilterValidatedProgram::blendFunctionString(blink::WebBlendMode blendMode)
284 {
285     // Implemented using the same symbol names as the Compositing and Blending spec:
286     // https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blendingnormal
287     // Cs: is the source color in css_BlendColor() and the source color component in css_BlendComponent()
288     // Cb: is the backdrop color in css_BlendColor() and the backdrop color component in css_BlendComponent()
289     const char* blendColorExpression = "vec3(css_BlendComponent(Cb.r, Cs.r), css_BlendComponent(Cb.g, Cs.g), css_BlendComponent(Cb.b, Cs.b))";
290     const char* blendComponentExpression = "Co = 0.0;";
291     bool needsLuminosityHelperFunctions = false;
292     bool needsSaturationHelperFunctions = false;
293     String blendFunctionString;
294     switch (blendMode) {
295     case blink::WebBlendModeNormal:
296         blendColorExpression = "Cs";
297         break;
298     case blink::WebBlendModeMultiply:
299         blendColorExpression = "Cs * Cb";
300         break;
301     case blink::WebBlendModeScreen:
302         blendColorExpression = "Cb + Cs - (Cb * Cs)";
303         break;
304     case blink::WebBlendModeDarken:
305         blendColorExpression = "min(Cb, Cs)";
306         break;
307     case blink::WebBlendModeLighten:
308         blendColorExpression = "max(Cb, Cs)";
309         break;
310     case blink::WebBlendModeDifference:
311         blendColorExpression = "abs(Cb - Cs)";
312         break;
313     case blink::WebBlendModeExclusion:
314         blendColorExpression = "Cb + Cs - 2.0 * Cb * Cs";
315         break;
316     case blink::WebBlendModeOverlay:
317         /*
318             Co = HardLight(Cs, Cb)
319                = if(Cb <= 0.5)
320                      Multiply(Cs, 2 x Cb)
321                  else
322                      Screen(Cs, 2 x Cb - 1)
323                = if(Cb <= 0.5)
324                      Cs x (2 x Cb)
325                  else
326                      Cs + (2 x Cb - 1) - (Cs x (2 x Cb - 1))
327         */
328         blendComponentExpression = SHADER(
329             if (Cb <= 0.5)
330                 Co = Cs * (2.0 * Cb);
331             else
332                 Co = Cs + (2.0 * Cb - 1.0) - (Cs * (2.0 * Cb - 1.0));
333         );
334         break;
335     case blink::WebBlendModeColorDodge:
336         /*
337             Co = if(Cs < 1)
338                      min(1, Cb / (1 - Cs))
339                  else
340                      1
341         */
342         blendComponentExpression = SHADER(
343             if (Cs < 1.0)
344                 Co = min(1.0, Cb / (1.0 - Cs));
345             else
346                 Co = 1.0;
347         );
348         break;
349     case blink::WebBlendModeColorBurn:
350         /*
351             Co = if(Cs > 0)
352                      1 - min(1, (1 - Cb) / Cs)
353                  else
354                      0
355         */
356         blendComponentExpression = SHADER(
357             if (Cs > 0.0)
358                 Co = 1.0 - min(1.0, (1.0 - Cb) / Cs);
359             else
360                 Co = 0.0;
361         );
362         break;
363     case blink::WebBlendModeHardLight:
364         /*
365             Co = if(Cs <= 0.5)
366                      Multiply(Cb, 2 x Cs)
367                  else
368                      Screen(Cb, 2 x Cs -1)
369                = if(Cs <= 0.5)
370                      Cb x (2 x Cs)
371                  else
372                      Cb + (2 x Cs - 1) - (Cb x (2 x Cs - 1))
373         */
374         blendComponentExpression = SHADER(
375             if (Cs <= 0.5)
376                 Co = Cb * (2.0 * Cs);
377             else
378                 Co = Cb + (2.0 * Cs - 1.0) - (Cb * (2.0 * Cs - 1.0));
379         );
380         break;
381     case blink::WebBlendModeSoftLight:
382         /*
383             Co = if(Cs <= 0.5)
384                      Cb - (1 - 2 x Cs) x Cb x (1 - Cb)
385                  else
386                      Cb + (2 x Cs - 1) x (D(Cb) - Cb)
387 
388             with
389 
390             D(Cb) = if(Cb <= 0.25)
391                         (16 * Cb - 12) x Cb + 4) x Cb
392                     else
393                         sqrt(Cb)
394         */
395         blendComponentExpression = SHADER(
396             mediump float D;
397             if (Cb <= 0.25)
398                 D = ((16.0 * Cb - 12.0) * Cb + 4.0) * Cb;
399             else
400                 D = sqrt(Cb);
401 
402             if (Cs <= 0.5)
403                 Co = Cb - (1.0 - 2.0 * Cs) * Cb * (1.0 - Cb);
404             else
405                 Co = Cb + (2.0 * Cs - 1.0) * (D - Cb);
406         );
407         break;
408     case blink::WebBlendModeColor:
409         needsLuminosityHelperFunctions = true;
410         blendColorExpression = "css_SetLum(Cs, css_Lum(Cb))";
411         break;
412     case blink::WebBlendModeLuminosity:
413         needsLuminosityHelperFunctions = true;
414         blendColorExpression = "css_SetLum(Cb, css_Lum(Cs))";
415         break;
416     case blink::WebBlendModeHue:
417         needsLuminosityHelperFunctions = true;
418         needsSaturationHelperFunctions = true;
419         blendColorExpression = "css_SetLum(css_SetSat(Cs, css_Sat(Cb)), css_Lum(Cb))";
420         break;
421     case blink::WebBlendModeSaturation:
422         needsLuminosityHelperFunctions = true;
423         needsSaturationHelperFunctions = true;
424         blendColorExpression = "css_SetLum(css_SetSat(Cb, css_Sat(Cs)), css_Lum(Cb))";
425         break;
426     default:
427         ASSERT_NOT_REACHED();
428     }
429 
430     if (needsLuminosityHelperFunctions) {
431         blendFunctionString.append(SHADER(
432             mediump float css_Lum(mediump vec3 C)
433             {
434                 return 0.3 * C.r + 0.59 * C.g + 0.11 * C.b;
435             }
436             mediump vec3 css_ClipColor(mediump vec3 C)
437             {
438                 mediump float L = css_Lum(C);
439                 mediump float n = min(min(C.r, C.g), C.b);
440                 mediump float x = max(max(C.r, C.g), C.b);
441                 if (n < 0.0)
442                     C = L + (((C - L) * L) / (L - n));
443                 if (x > 1.0)
444                     C = L + (((C - L) * (1.0 - L) / (x - L)));
445                 return C;
446             }
447             mediump vec3 css_SetLum(mediump vec3 C, mediump float l)
448             {
449                 C += l - css_Lum(C);
450                 return css_ClipColor(C);
451             }
452         ));
453     }
454 
455     if (needsSaturationHelperFunctions) {
456         blendFunctionString.append(SHADER(
457             mediump float css_Sat(mediump vec3 C)
458             {
459                 mediump float cMin = min(min(C.r, C.g), C.b);
460                 mediump float cMax = max(max(C.r, C.g), C.b);
461                 return cMax - cMin;
462             }
463             void css_SetSatHelper(inout mediump float cMin, inout mediump float cMid, inout mediump float cMax, mediump float s)
464             {
465                 if (cMax > cMin) {
466                     cMid = (((cMid - cMin) * s) / (cMax - cMin));
467                     cMax = s;
468                 } else {
469                     cMid = cMax = 0.0;
470                 }
471                 cMin = 0.0;
472             }
473             mediump vec3 css_SetSat(mediump vec3 C, mediump float s)
474             {
475                 if (C.r <= C.g) {
476                     if (C.g <= C.b) {
477                         css_SetSatHelper(C.r, C.g, C.b, s);
478                     } else {
479                         if (C.r <= C.b)
480                             css_SetSatHelper(C.r, C.b, C.g, s);
481                         else
482                             css_SetSatHelper(C.b, C.r, C.g, s);
483                     }
484                 } else {
485                     if (C.r <= C.b) {
486                         css_SetSatHelper(C.g, C.r, C.b, s);
487                     } else {
488                         if (C.g <= C.b)
489                             css_SetSatHelper(C.g, C.b, C.r, s);
490                         else
491                             css_SetSatHelper(C.b, C.g, C.r, s);
492                     }
493                 }
494                 return C;
495             }
496         ));
497     }
498 
499     blendFunctionString.append(String::format(SHADER(
500         mediump float css_BlendComponent(mediump float Cb, mediump float Cs)
501         {
502             mediump float Co;
503             %s
504             return Co;
505         }
506         mediump vec3 css_BlendColor(mediump vec3 Cb, mediump vec3 Cs)
507         {
508             return %s;
509         }
510     ), blendComponentExpression, blendColorExpression));
511 
512     return blendFunctionString;
513 }
514 
compositeFunctionString(CompositeOperator compositeOperator)515 String CustomFilterValidatedProgram::compositeFunctionString(CompositeOperator compositeOperator)
516 {
517     // Use the same symbol names as the Compositing and Blending spec:
518     // https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blendingnormal
519     // Cs: is the source color
520     // Cb: is the backdrop color
521     // as: is the source alpha
522     // ab: is the backdrop alpha
523     // Fa: is defined by the Porter Duff operator in use
524     // Fb: is defined by the Porter Duff operator in use
525     const char* Fa = 0;
526     const char* Fb = 0;
527     switch (compositeOperator) {
528     case CompositeSourceAtop:
529         Fa = "ab";
530         Fb = "1.0 - as";
531         break;
532     case CompositeClear:
533         Fa = "0.0";
534         Fb = "0.0";
535         break;
536     case CompositeCopy:
537         Fa = "1.0";
538         Fb = "0.0";
539         break;
540     case CompositeSourceOver:
541         Fa = "1.0";
542         Fb = "1.0 - as";
543         break;
544     case CompositeSourceIn:
545         Fa = "ab";
546         Fb = "0.0";
547         break;
548     case CompositeSourceOut:
549         Fa = "1.0 - ab";
550         Fb = "0.0";
551         break;
552     case CompositeDestinationOver:
553         Fa = "1.0 - ab";
554         Fb = "1.0";
555         break;
556     case CompositeDestinationIn:
557         Fa = "0.0";
558         Fb = "as";
559         break;
560     case CompositeDestinationOut:
561         Fa = "0.0";
562         Fb = "1.0 - as";
563         break;
564     case CompositeDestinationAtop:
565         Fa = "1.0 - ab";
566         Fb = "as";
567         break;
568     case CompositeXOR:
569         Fa = "1.0 - ab";
570         Fb = "1.0 - as";
571         break;
572     case CompositePlusLighter:
573         notImplemented();
574         return String();
575     default:
576         // The CSS parser should not have accepted any other composite operators.
577         ASSERT_NOT_REACHED();
578         return String();
579     }
580 
581     ASSERT(Fa && Fb);
582     // Use the general formula for compositing, lifted from the spec:
583     // https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#generalformula
584     return String::format(SHADER(
585         mediump vec4 css_Composite(mediump vec3 Cb, mediump float ab, mediump vec3 Cs, mediump float as)
586         {
587             mediump float Fa = %s;
588             mediump float Fb = %s;
589             return vec4(as * Fa * Cs + ab * Fb * Cb, as * Fa + ab * Fb);
590         }
591     ), Fa, Fb);
592 }
593 
~CustomFilterValidatedProgram()594 CustomFilterValidatedProgram::~CustomFilterValidatedProgram()
595 {
596     platformDestroy();
597 
598     if (m_globalContext)
599         m_globalContext->removeValidatedProgram(this);
600 }
601 
validatedProgramInfo() const602 CustomFilterProgramInfo CustomFilterValidatedProgram::validatedProgramInfo() const
603 {
604     ASSERT(m_isInitialized);
605     return CustomFilterProgramInfo(m_validatedVertexShader, m_validatedFragmentShader, m_programInfo.programType(), m_programInfo.mixSettings(), m_programInfo.meshType());
606 }
607 
platformInit()608 void CustomFilterValidatedProgram::platformInit()
609 {
610 }
611 
platformDestroy()612 void CustomFilterValidatedProgram::platformDestroy()
613 {
614 }
615 
616 } // namespace WebCore
617 
618