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