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