OGLShaderProgram.cpp (41503B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "OGLShaderProgram.h" 8 9 #include <stdint.h> // for uint32_t 10 11 #include <sstream> // for std::ostringstream 12 13 #include "GLContext.h" 14 #include "gfxEnv.h" 15 #include "gfxRect.h" // for gfxRect 16 #include "gfxUtils.h" 17 #include "mozilla/DebugOnly.h" // for DebugOnly 18 #include "mozilla/gfx/Logging.h" 19 #include "mozilla/layers/Compositor.h" // for BlendOpIsMixBlendMode 20 #include "nsAString.h" 21 #include "nsString.h" // for nsAutoCString 22 23 namespace mozilla { 24 namespace layers { 25 26 using std::endl; 27 28 #define GAUSSIAN_KERNEL_HALF_WIDTH 11 29 #define GAUSSIAN_KERNEL_STEP 0.2 30 31 static void AddUniforms(ProgramProfileOGL& aProfile) { 32 // This needs to be kept in sync with the KnownUniformName enum 33 static const char* sKnownUniformNames[] = {"uLayerTransform", 34 "uLayerTransformInverse", 35 "uMaskTransform", 36 "uBackdropTransform", 37 "uLayerRects", 38 "uMatrixProj", 39 "uTextureTransform", 40 "uTextureRects", 41 "uRenderTargetOffset", 42 "uLayerOpacity", 43 "uTexture", 44 "uYTexture", 45 "uCbTexture", 46 "uCrTexture", 47 "uRenderColor", 48 "uTexCoordMultiplier", 49 "uCbCrTexCoordMultiplier", 50 "uSSEdges", 51 "uViewportSize", 52 "uVisibleCenter", 53 "uYuvColorMatrix", 54 "uYuvOffsetVector", 55 "uRoundedClipRect", 56 "uRoundedClipRadii", 57 nullptr}; 58 59 for (int i = 0; sKnownUniformNames[i] != nullptr; ++i) { 60 aProfile.mUniforms[i].mNameString = sKnownUniformNames[i]; 61 aProfile.mUniforms[i].mName = (KnownUniform::KnownUniformName)i; 62 } 63 } 64 65 void ShaderConfigOGL::SetRenderColor(bool aEnabled) { 66 SetFeature(ENABLE_RENDER_COLOR, aEnabled); 67 } 68 69 void ShaderConfigOGL::SetTextureTarget(GLenum aTarget) { 70 SetFeature(ENABLE_TEXTURE_EXTERNAL | ENABLE_TEXTURE_RECT, false); 71 switch (aTarget) { 72 case LOCAL_GL_TEXTURE_EXTERNAL: 73 SetFeature(ENABLE_TEXTURE_EXTERNAL, true); 74 break; 75 case LOCAL_GL_TEXTURE_RECTANGLE_ARB: 76 SetFeature(ENABLE_TEXTURE_RECT, true); 77 break; 78 } 79 } 80 81 void ShaderConfigOGL::SetMaskTextureTarget(GLenum aTarget) { 82 if (aTarget == LOCAL_GL_TEXTURE_RECTANGLE_ARB) { 83 SetFeature(ENABLE_MASK_TEXTURE_RECT, true); 84 } else { 85 MOZ_ASSERT(aTarget == LOCAL_GL_TEXTURE_2D); 86 SetFeature(ENABLE_MASK_TEXTURE_RECT, false); 87 } 88 } 89 90 void ShaderConfigOGL::SetRBSwap(bool aEnabled) { 91 SetFeature(ENABLE_TEXTURE_RB_SWAP, aEnabled); 92 } 93 94 void ShaderConfigOGL::SetNoAlpha(bool aEnabled) { 95 SetFeature(ENABLE_TEXTURE_NO_ALPHA, aEnabled); 96 } 97 98 void ShaderConfigOGL::SetOpacity(bool aEnabled) { 99 SetFeature(ENABLE_OPACITY, aEnabled); 100 } 101 102 void ShaderConfigOGL::SetYCbCr(bool aEnabled) { 103 SetFeature(ENABLE_TEXTURE_YCBCR, aEnabled); 104 MOZ_ASSERT(!(mFeatures & ENABLE_TEXTURE_NV12)); 105 } 106 107 void ShaderConfigOGL::SetColorMultiplier(uint32_t aMultiplier) { 108 MOZ_ASSERT(mFeatures & ENABLE_TEXTURE_YCBCR, 109 "Multiplier only supported with YCbCr!"); 110 mMultiplier = aMultiplier; 111 } 112 113 void ShaderConfigOGL::SetRoundedClip(bool aEnabled) { 114 SetFeature(ENABLE_ROUNDED_CLIP, aEnabled); 115 } 116 117 void ShaderConfigOGL::SetNV12(bool aEnabled) { 118 SetFeature(ENABLE_TEXTURE_NV12, aEnabled); 119 MOZ_ASSERT(!(mFeatures & ENABLE_TEXTURE_YCBCR)); 120 #ifdef MOZ_WIDGET_GTK 121 SetFeature(ENABLE_TEXTURE_NV12_GA_SWITCH, aEnabled); 122 #endif 123 } 124 125 void ShaderConfigOGL::SetComponentAlpha(bool aEnabled) { 126 SetFeature(ENABLE_TEXTURE_COMPONENT_ALPHA, aEnabled); 127 } 128 129 void ShaderConfigOGL::SetColorMatrix(bool aEnabled) { 130 SetFeature(ENABLE_COLOR_MATRIX, aEnabled); 131 } 132 133 void ShaderConfigOGL::SetBlur(bool aEnabled) { 134 SetFeature(ENABLE_BLUR, aEnabled); 135 } 136 137 void ShaderConfigOGL::SetMask(bool aEnabled) { 138 SetFeature(ENABLE_MASK, aEnabled); 139 } 140 141 void ShaderConfigOGL::SetNoPremultipliedAlpha() { 142 SetFeature(ENABLE_NO_PREMUL_ALPHA, true); 143 } 144 145 void ShaderConfigOGL::SetDEAA(bool aEnabled) { 146 SetFeature(ENABLE_DEAA, aEnabled); 147 } 148 149 void ShaderConfigOGL::SetCompositionOp(gfx::CompositionOp aOp) { 150 mCompositionOp = aOp; 151 } 152 153 void ShaderConfigOGL::SetDynamicGeometry(bool aEnabled) { 154 SetFeature(ENABLE_DYNAMIC_GEOMETRY, aEnabled); 155 } 156 157 /* static */ 158 ProgramProfileOGL ProgramProfileOGL::GetProfileFor(ShaderConfigOGL aConfig) { 159 ProgramProfileOGL result; 160 std::ostringstream fs, vs; 161 162 AddUniforms(result); 163 164 gfx::CompositionOp blendOp = aConfig.mCompositionOp; 165 166 vs << "#ifdef GL_ES" << endl; 167 vs << "#define EDGE_PRECISION mediump" << endl; 168 vs << "#else" << endl; 169 vs << "#define EDGE_PRECISION" << endl; 170 vs << "#endif" << endl; 171 vs << "uniform mat4 uMatrixProj;" << endl; 172 vs << "uniform vec4 uLayerRects[4];" << endl; 173 vs << "uniform mat4 uLayerTransform;" << endl; 174 if (aConfig.mFeatures & ENABLE_DEAA) { 175 vs << "uniform mat4 uLayerTransformInverse;" << endl; 176 vs << "uniform EDGE_PRECISION vec3 uSSEdges[4];" << endl; 177 vs << "uniform vec2 uVisibleCenter;" << endl; 178 vs << "uniform vec2 uViewportSize;" << endl; 179 } 180 vs << "uniform vec2 uRenderTargetOffset;" << endl; 181 if (aConfig.mFeatures & ENABLE_ROUNDED_CLIP) { 182 vs << "uniform vec4 uRoundedClipRect;" << endl; 183 vs << "varying vec2 vRoundedClipSize;" << endl; 184 vs << "varying vec2 vRoundedClipPos;" << endl; 185 } 186 187 if (!(aConfig.mFeatures & ENABLE_DYNAMIC_GEOMETRY)) { 188 vs << "attribute vec4 aCoord;" << endl; 189 } else { 190 vs << "attribute vec2 aCoord;" << endl; 191 } 192 193 result.mAttributes.AppendElement(std::pair<nsCString, GLuint>{"aCoord", 0}); 194 195 if (!(aConfig.mFeatures & ENABLE_RENDER_COLOR)) { 196 vs << "uniform mat4 uTextureTransform;" << endl; 197 vs << "uniform vec4 uTextureRects[4];" << endl; 198 vs << "varying vec2 vTexCoord;" << endl; 199 200 if (aConfig.mFeatures & ENABLE_DYNAMIC_GEOMETRY) { 201 vs << "attribute vec2 aTexCoord;" << endl; 202 result.mAttributes.AppendElement( 203 std::pair<nsCString, GLuint>{"aTexCoord", 1}); 204 } 205 } 206 207 if (BlendOpIsMixBlendMode(blendOp)) { 208 vs << "uniform mat4 uBackdropTransform;" << endl; 209 vs << "varying vec2 vBackdropCoord;" << endl; 210 } 211 212 if (aConfig.mFeatures & ENABLE_MASK) { 213 vs << "uniform mat4 uMaskTransform;" << endl; 214 vs << "varying vec3 vMaskCoord;" << endl; 215 } 216 217 vs << "void main() {" << endl; 218 219 if (aConfig.mFeatures & ENABLE_DYNAMIC_GEOMETRY) { 220 vs << " vec4 finalPosition = vec4(aCoord.xy, 0.0, 1.0);" << endl; 221 } else { 222 vs << " int vertexID = int(aCoord.w);" << endl; 223 vs << " vec4 layerRect = uLayerRects[vertexID];" << endl; 224 vs << " vec4 finalPosition = vec4(aCoord.xy * layerRect.zw + " 225 "layerRect.xy, 0.0, 1.0);" 226 << endl; 227 } 228 229 vs << " finalPosition = uLayerTransform * finalPosition;" << endl; 230 231 if (aConfig.mFeatures & ENABLE_ROUNDED_CLIP) { 232 vs << " vec2 halfSize = 0.5 * uRoundedClipRect.zw;" << endl; 233 vs << " vRoundedClipPos = uRoundedClipRect.xy + halfSize - " 234 "finalPosition.xy;" 235 << endl; 236 vs << " vRoundedClipSize = halfSize;" << endl; 237 } 238 239 if (aConfig.mFeatures & ENABLE_DEAA) { 240 // XXX kip - The DEAA shader could be made simpler if we switch to 241 // using dynamic vertex buffers instead of sending everything 242 // in through uniforms. This would enable passing information 243 // about how to dilate each vertex explicitly and eliminate the 244 // need to extrapolate this with the sub-pixel coverage 245 // calculation in the vertex shader. 246 247 // Calculate the screen space position of this vertex, in screen pixels 248 vs << " vec4 ssPos = finalPosition;" << endl; 249 vs << " ssPos.xy -= uRenderTargetOffset * finalPosition.w;" << endl; 250 vs << " ssPos = uMatrixProj * ssPos;" << endl; 251 vs << " ssPos.xy = ((ssPos.xy/ssPos.w)*0.5+0.5)*uViewportSize;" << endl; 252 253 if (aConfig.mFeatures & ENABLE_MASK || 254 !(aConfig.mFeatures & ENABLE_RENDER_COLOR)) { 255 vs << " vec4 coordAdjusted;" << endl; 256 vs << " coordAdjusted.xy = aCoord.xy;" << endl; 257 } 258 259 // It is necessary to dilate edges away from uVisibleCenter to ensure that 260 // fragments with less than 50% sub-pixel coverage will be shaded. 261 // This offset is applied when the sub-pixel coverage of the vertex is 262 // less than 100%. Expanding by 0.5 pixels in screen space is sufficient 263 // to include these pixels. 264 vs << " if (dot(uSSEdges[0], vec3(ssPos.xy, 1.0)) < 1.5 ||" << endl; 265 vs << " dot(uSSEdges[1], vec3(ssPos.xy, 1.0)) < 1.5 ||" << endl; 266 vs << " dot(uSSEdges[2], vec3(ssPos.xy, 1.0)) < 1.5 ||" << endl; 267 vs << " dot(uSSEdges[3], vec3(ssPos.xy, 1.0)) < 1.5) {" << endl; 268 // If the shader reaches this branch, then this vertex is on the edge of 269 // the layer's visible rect and should be dilated away from the center of 270 // the visible rect. We don't want to hit this for inner facing 271 // edges between tiles, as the pixels may be covered twice without clipping 272 // against uSSEdges. If all edges were dilated, it would result in 273 // artifacts visible within semi-transparent layers with multiple tiles. 274 vs << " vec4 visibleCenter = uLayerTransform * vec4(uVisibleCenter, " 275 "0.0, 1.0);" 276 << endl; 277 vs << " vec2 dilateDir = finalPosition.xy / finalPosition.w - " 278 "visibleCenter.xy / visibleCenter.w;" 279 << endl; 280 vs << " vec2 offset = sign(dilateDir) * 0.5;" << endl; 281 vs << " finalPosition.xy += offset * finalPosition.w;" << endl; 282 if (!(aConfig.mFeatures & ENABLE_RENDER_COLOR)) { 283 // We must adjust the texture coordinates to compensate for the dilation 284 vs << " coordAdjusted = uLayerTransformInverse * finalPosition;" 285 << endl; 286 vs << " coordAdjusted /= coordAdjusted.w;" << endl; 287 288 if (!(aConfig.mFeatures & ENABLE_DYNAMIC_GEOMETRY)) { 289 vs << " coordAdjusted.xy -= layerRect.xy;" << endl; 290 vs << " coordAdjusted.xy /= layerRect.zw;" << endl; 291 } 292 } 293 vs << " }" << endl; 294 295 if (!(aConfig.mFeatures & ENABLE_RENDER_COLOR)) { 296 if (aConfig.mFeatures & ENABLE_DYNAMIC_GEOMETRY) { 297 vs << " vTexCoord = (uTextureTransform * vec4(aTexCoord, 0.0, " 298 "1.0)).xy;" 299 << endl; 300 } else { 301 vs << " vec4 textureRect = uTextureRects[vertexID];" << endl; 302 vs << " vec2 texCoord = coordAdjusted.xy * textureRect.zw + " 303 "textureRect.xy;" 304 << endl; 305 vs << " vTexCoord = (uTextureTransform * vec4(texCoord, 0.0, 1.0)).xy;" 306 << endl; 307 } 308 } 309 } else if (!(aConfig.mFeatures & ENABLE_RENDER_COLOR)) { 310 if (aConfig.mFeatures & ENABLE_DYNAMIC_GEOMETRY) { 311 vs << " vTexCoord = (uTextureTransform * vec4(aTexCoord, 0.0, 1.0)).xy;" 312 << endl; 313 } else { 314 vs << " vec4 textureRect = uTextureRects[vertexID];" << endl; 315 vs << " vec2 texCoord = aCoord.xy * textureRect.zw + textureRect.xy;" 316 << endl; 317 vs << " vTexCoord = (uTextureTransform * vec4(texCoord, 0.0, 1.0)).xy;" 318 << endl; 319 } 320 } 321 322 if (aConfig.mFeatures & ENABLE_MASK) { 323 vs << " vMaskCoord.xy = (uMaskTransform * (finalPosition / " 324 "finalPosition.w)).xy;" 325 << endl; 326 // correct for perspective correct interpolation, see comment in D3D11 327 // shader 328 vs << " vMaskCoord.z = 1.0;" << endl; 329 vs << " vMaskCoord *= finalPosition.w;" << endl; 330 } 331 vs << " finalPosition.xy -= uRenderTargetOffset * finalPosition.w;" << endl; 332 vs << " finalPosition = uMatrixProj * finalPosition;" << endl; 333 if (BlendOpIsMixBlendMode(blendOp)) { 334 // Translate from clip space (-1, 1) to (0..1), apply the backdrop 335 // transform, then invert the y-axis. 336 vs << " vBackdropCoord.x = (finalPosition.x + 1.0) / 2.0;" << endl; 337 vs << " vBackdropCoord.y = 1.0 - (finalPosition.y + 1.0) / 2.0;" << endl; 338 vs << " vBackdropCoord = (uBackdropTransform * vec4(vBackdropCoord.xy, " 339 "0.0, 1.0)).xy;" 340 << endl; 341 vs << " vBackdropCoord.y = 1.0 - vBackdropCoord.y;" << endl; 342 } 343 vs << " gl_Position = finalPosition;" << endl; 344 vs << "}" << endl; 345 346 if (aConfig.mFeatures & ENABLE_TEXTURE_RECT) { 347 fs << "#extension GL_ARB_texture_rectangle : require" << endl; 348 } 349 if (aConfig.mFeatures & ENABLE_TEXTURE_EXTERNAL) { 350 fs << "#extension GL_OES_EGL_image_external : require" << endl; 351 } 352 fs << "#ifdef GL_ES" << endl; 353 fs << "precision mediump float;" << endl; 354 fs << "#define COLOR_PRECISION lowp" << endl; 355 fs << "#define EDGE_PRECISION mediump" << endl; 356 fs << "#else" << endl; 357 fs << "#define COLOR_PRECISION" << endl; 358 fs << "#define EDGE_PRECISION" << endl; 359 fs << "#endif" << endl; 360 if (aConfig.mFeatures & ENABLE_RENDER_COLOR) { 361 fs << "uniform COLOR_PRECISION vec4 uRenderColor;" << endl; 362 } else { 363 // for tiling, texcoord can be greater than the lowfp range 364 fs << "varying vec2 vTexCoord;" << endl; 365 if (aConfig.mFeatures & ENABLE_BLUR) { 366 fs << "uniform bool uBlurAlpha;" << endl; 367 fs << "uniform vec2 uBlurRadius;" << endl; 368 fs << "uniform vec2 uBlurOffset;" << endl; 369 fs << "uniform float uBlurGaussianKernel[" << GAUSSIAN_KERNEL_HALF_WIDTH 370 << "];" << endl; 371 } 372 if (aConfig.mFeatures & ENABLE_COLOR_MATRIX) { 373 fs << "uniform mat4 uColorMatrix;" << endl; 374 fs << "uniform vec4 uColorMatrixVector;" << endl; 375 } 376 if (aConfig.mFeatures & ENABLE_OPACITY) { 377 fs << "uniform COLOR_PRECISION float uLayerOpacity;" << endl; 378 } 379 } 380 if (aConfig.mFeatures & ENABLE_ROUNDED_CLIP) { 381 fs << "uniform vec4 uRoundedClipRadii;" << endl; 382 fs << "varying vec2 vRoundedClipSize;" << endl; 383 fs << "varying vec2 vRoundedClipPos;" << endl; 384 } 385 if (BlendOpIsMixBlendMode(blendOp)) { 386 fs << "varying vec2 vBackdropCoord;" << endl; 387 } 388 389 const char* sampler2D = "sampler2D"; 390 const char* texture2D = "texture2D"; 391 392 if (aConfig.mFeatures & ENABLE_TEXTURE_RECT) { 393 fs << "uniform vec2 uTexCoordMultiplier;" << endl; 394 if (aConfig.mFeatures & ENABLE_TEXTURE_YCBCR || 395 aConfig.mFeatures & ENABLE_TEXTURE_NV12) { 396 fs << "uniform vec2 uCbCrTexCoordMultiplier;" << endl; 397 } 398 sampler2D = "sampler2DRect"; 399 texture2D = "texture2DRect"; 400 } 401 402 const char* maskSampler2D = "sampler2D"; 403 const char* maskTexture2D = "texture2D"; 404 405 if (aConfig.mFeatures & ENABLE_MASK && 406 aConfig.mFeatures & ENABLE_MASK_TEXTURE_RECT) { 407 fs << "uniform vec2 uMaskCoordMultiplier;" << endl; 408 maskSampler2D = "sampler2DRect"; 409 maskTexture2D = "texture2DRect"; 410 } 411 412 if (aConfig.mFeatures & ENABLE_TEXTURE_EXTERNAL) { 413 sampler2D = "samplerExternalOES"; 414 } 415 416 if (aConfig.mFeatures & ENABLE_TEXTURE_YCBCR) { 417 fs << "uniform " << sampler2D << " uYTexture;" << endl; 418 fs << "uniform " << sampler2D << " uCbTexture;" << endl; 419 fs << "uniform " << sampler2D << " uCrTexture;" << endl; 420 fs << "uniform mat3 uYuvColorMatrix;" << endl; 421 fs << "uniform vec3 uYuvOffsetVector;" << endl; 422 } else if (aConfig.mFeatures & ENABLE_TEXTURE_NV12) { 423 fs << "uniform " << sampler2D << " uYTexture;" << endl; 424 fs << "uniform " << sampler2D << " uCbTexture;" << endl; 425 fs << "uniform mat3 uYuvColorMatrix;" << endl; 426 fs << "uniform vec3 uYuvOffsetVector;" << endl; 427 } else if (aConfig.mFeatures & ENABLE_TEXTURE_COMPONENT_ALPHA) { 428 fs << "uniform " << sampler2D << " uBlackTexture;" << endl; 429 fs << "uniform " << sampler2D << " uWhiteTexture;" << endl; 430 fs << "uniform bool uTexturePass2;" << endl; 431 } else { 432 fs << "uniform " << sampler2D << " uTexture;" << endl; 433 } 434 435 if (BlendOpIsMixBlendMode(blendOp)) { 436 // Component alpha should be flattened away inside blend containers. 437 MOZ_ASSERT(!(aConfig.mFeatures & ENABLE_TEXTURE_COMPONENT_ALPHA)); 438 439 fs << "uniform sampler2D uBackdropTexture;" << endl; 440 } 441 442 if (aConfig.mFeatures & ENABLE_MASK) { 443 fs << "varying vec3 vMaskCoord;" << endl; 444 fs << "uniform " << maskSampler2D << " uMaskTexture;" << endl; 445 } 446 447 if (aConfig.mFeatures & ENABLE_DEAA) { 448 fs << "uniform EDGE_PRECISION vec3 uSSEdges[4];" << endl; 449 } 450 451 if (BlendOpIsMixBlendMode(blendOp)) { 452 BuildMixBlender(aConfig, fs); 453 } 454 455 if (!(aConfig.mFeatures & ENABLE_RENDER_COLOR)) { 456 fs << "vec4 sample(vec2 coord) {" << endl; 457 fs << " vec4 color;" << endl; 458 if (aConfig.mFeatures & ENABLE_TEXTURE_YCBCR || 459 aConfig.mFeatures & ENABLE_TEXTURE_NV12) { 460 if (aConfig.mFeatures & ENABLE_TEXTURE_YCBCR) { 461 if (aConfig.mFeatures & ENABLE_TEXTURE_RECT) { 462 fs << " COLOR_PRECISION float y = " << texture2D 463 << "(uYTexture, coord * uTexCoordMultiplier).r;" << endl; 464 fs << " COLOR_PRECISION float cb = " << texture2D 465 << "(uCbTexture, coord * uCbCrTexCoordMultiplier).r;" << endl; 466 fs << " COLOR_PRECISION float cr = " << texture2D 467 << "(uCrTexture, coord * uCbCrTexCoordMultiplier).r;" << endl; 468 } else { 469 fs << " COLOR_PRECISION float y = " << texture2D 470 << "(uYTexture, coord).r;" << endl; 471 fs << " COLOR_PRECISION float cb = " << texture2D 472 << "(uCbTexture, coord).r;" << endl; 473 fs << " COLOR_PRECISION float cr = " << texture2D 474 << "(uCrTexture, coord).r;" << endl; 475 } 476 } else { 477 if (aConfig.mFeatures & ENABLE_TEXTURE_RECT) { 478 fs << " COLOR_PRECISION float y = " << texture2D 479 << "(uYTexture, coord * uTexCoordMultiplier).r;" << endl; 480 fs << " COLOR_PRECISION float cb = " << texture2D 481 << "(uCbTexture, coord * uCbCrTexCoordMultiplier).r;" << endl; 482 if (aConfig.mFeatures & ENABLE_TEXTURE_NV12_GA_SWITCH) { 483 fs << " COLOR_PRECISION float cr = " << texture2D 484 << "(uCbTexture, coord * uCbCrTexCoordMultiplier).g;" << endl; 485 } else { 486 fs << " COLOR_PRECISION float cr = " << texture2D 487 << "(uCbTexture, coord * uCbCrTexCoordMultiplier).a;" << endl; 488 } 489 } else { 490 fs << " COLOR_PRECISION float y = " << texture2D 491 << "(uYTexture, coord).r;" << endl; 492 fs << " COLOR_PRECISION float cb = " << texture2D 493 << "(uCbTexture, coord).r;" << endl; 494 if (aConfig.mFeatures & ENABLE_TEXTURE_NV12_GA_SWITCH) { 495 fs << " COLOR_PRECISION float cr = " << texture2D 496 << "(uCbTexture, coord).g;" << endl; 497 } else { 498 fs << " COLOR_PRECISION float cr = " << texture2D 499 << "(uCbTexture, coord).a;" << endl; 500 } 501 } 502 } 503 fs << " vec3 yuv = vec3(y, cb, cr);" << endl; 504 if (aConfig.mMultiplier != 1) { 505 fs << " yuv *= " << aConfig.mMultiplier << ".0;" << endl; 506 } 507 fs << " yuv -= uYuvOffsetVector;" << endl; 508 fs << " color.rgb = uYuvColorMatrix * yuv;" << endl; 509 fs << " color.a = 1.0;" << endl; 510 } else if (aConfig.mFeatures & ENABLE_TEXTURE_COMPONENT_ALPHA) { 511 if (aConfig.mFeatures & ENABLE_TEXTURE_RECT) { 512 fs << " COLOR_PRECISION vec3 onBlack = " << texture2D 513 << "(uBlackTexture, coord * uTexCoordMultiplier).rgb;" << endl; 514 fs << " COLOR_PRECISION vec3 onWhite = " << texture2D 515 << "(uWhiteTexture, coord * uTexCoordMultiplier).rgb;" << endl; 516 } else { 517 fs << " COLOR_PRECISION vec3 onBlack = " << texture2D 518 << "(uBlackTexture, coord).rgb;" << endl; 519 fs << " COLOR_PRECISION vec3 onWhite = " << texture2D 520 << "(uWhiteTexture, coord).rgb;" << endl; 521 } 522 fs << " COLOR_PRECISION vec4 alphas = (1.0 - onWhite + onBlack).rgbg;" 523 << endl; 524 fs << " if (uTexturePass2)" << endl; 525 fs << " color = vec4(onBlack, alphas.a);" << endl; 526 fs << " else" << endl; 527 fs << " color = alphas;" << endl; 528 } else { 529 if (aConfig.mFeatures & ENABLE_TEXTURE_RECT) { 530 fs << " color = " << texture2D 531 << "(uTexture, coord * uTexCoordMultiplier);" << endl; 532 } else { 533 fs << " color = " << texture2D << "(uTexture, coord);" << endl; 534 } 535 } 536 if (aConfig.mFeatures & ENABLE_TEXTURE_RB_SWAP) { 537 fs << " color = color.bgra;" << endl; 538 } 539 if (aConfig.mFeatures & ENABLE_TEXTURE_NO_ALPHA) { 540 fs << " color = vec4(color.rgb, 1.0);" << endl; 541 } 542 fs << " return color;" << endl; 543 fs << "}" << endl; 544 if (aConfig.mFeatures & ENABLE_BLUR) { 545 fs << "vec4 sampleAtRadius(vec2 coord, float radius) {" << endl; 546 fs << " coord += uBlurOffset;" << endl; 547 fs << " coord += radius * uBlurRadius;" << endl; 548 fs << " if (coord.x < 0. || coord.y < 0. || coord.x > 1. || coord.y > " 549 "1.)" 550 << endl; 551 fs << " return vec4(0, 0, 0, 0);" << endl; 552 fs << " return sample(coord);" << endl; 553 fs << "}" << endl; 554 fs << "vec4 blur(vec4 color, vec2 coord) {" << endl; 555 fs << " vec4 total = color * uBlurGaussianKernel[0];" << endl; 556 fs << " for (int i = 1; i < " << GAUSSIAN_KERNEL_HALF_WIDTH << "; ++i) {" 557 << endl; 558 fs << " float r = float(i) * " << GAUSSIAN_KERNEL_STEP << ";" << endl; 559 fs << " float k = uBlurGaussianKernel[i];" << endl; 560 fs << " total += sampleAtRadius(coord, r) * k;" << endl; 561 fs << " total += sampleAtRadius(coord, -r) * k;" << endl; 562 fs << " }" << endl; 563 fs << " if (uBlurAlpha) {" << endl; 564 fs << " color *= total.a;" << endl; 565 fs << " } else {" << endl; 566 fs << " color = total;" << endl; 567 fs << " }" << endl; 568 fs << " return color;" << endl; 569 fs << "}" << endl; 570 } 571 } 572 if (aConfig.mFeatures & ENABLE_ROUNDED_CLIP) { 573 fs << "float sd_round_box(vec2 pos, vec2 half_box_size, vec4 radii) {" 574 << endl; 575 fs << " radii.xy = (pos.x > 0.0) ? radii.xy : radii.zw;" << endl; 576 fs << " radii.x = (pos.y > 0.0) ? radii.x : radii.y;" << endl; 577 fs << " vec2 q = abs(pos) - half_box_size + radii.x;" << endl; 578 fs << " return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - radii.x;" 579 << endl; 580 fs << "}" << endl; 581 } 582 fs << "void main() {" << endl; 583 if (aConfig.mFeatures & ENABLE_RENDER_COLOR) { 584 fs << " vec4 color = uRenderColor;" << endl; 585 } else { 586 fs << " vec4 color = sample(vTexCoord);" << endl; 587 if (aConfig.mFeatures & ENABLE_BLUR) { 588 fs << " color = blur(color, vTexCoord);" << endl; 589 } 590 if (aConfig.mFeatures & ENABLE_COLOR_MATRIX) { 591 fs << " color = uColorMatrix * vec4(color.rgb / color.a, color.a) + " 592 "uColorMatrixVector;" 593 << endl; 594 fs << " color.rgb *= color.a;" << endl; 595 } 596 if (aConfig.mFeatures & ENABLE_OPACITY) { 597 fs << " color *= uLayerOpacity;" << endl; 598 } 599 } 600 if (aConfig.mFeatures & ENABLE_DEAA) { 601 // Calculate the sub-pixel coverage of the pixel and modulate its opacity 602 // by that amount to perform DEAA. 603 fs << " vec3 ssPos = vec3(gl_FragCoord.xy, 1.0);" << endl; 604 fs << " float deaaCoverage = clamp(dot(uSSEdges[0], ssPos), 0.0, 1.0);" 605 << endl; 606 fs << " deaaCoverage *= clamp(dot(uSSEdges[1], ssPos), 0.0, 1.0);" << endl; 607 fs << " deaaCoverage *= clamp(dot(uSSEdges[2], ssPos), 0.0, 1.0);" << endl; 608 fs << " deaaCoverage *= clamp(dot(uSSEdges[3], ssPos), 0.0, 1.0);" << endl; 609 fs << " color *= deaaCoverage;" << endl; 610 } 611 if (BlendOpIsMixBlendMode(blendOp)) { 612 fs << " vec4 backdrop = texture2D(uBackdropTexture, vBackdropCoord);" 613 << endl; 614 fs << " color = mixAndBlend(backdrop, color);" << endl; 615 } 616 if (aConfig.mFeatures & ENABLE_MASK) { 617 fs << " vec2 maskCoords = vMaskCoord.xy / vMaskCoord.z;" << endl; 618 if (aConfig.mFeatures & ENABLE_MASK_TEXTURE_RECT) { 619 fs << " COLOR_PRECISION float mask = " << maskTexture2D 620 << "(uMaskTexture, maskCoords * uMaskCoordMultiplier).r;" << endl; 621 } else { 622 fs << " COLOR_PRECISION float mask = " << maskTexture2D 623 << "(uMaskTexture, maskCoords).r;" << endl; 624 } 625 fs << " color *= mask;" << endl; 626 } else { 627 fs << " COLOR_PRECISION float mask = 1.0;" << endl; 628 fs << " color *= mask;" << endl; 629 } 630 if (aConfig.mFeatures & ENABLE_ROUNDED_CLIP) { 631 fs << " float d = sd_round_box(vRoundedClipPos, vRoundedClipSize, " 632 "uRoundedClipRadii);" 633 << endl; 634 // TODO(gw): Probably want some proper AA step here 635 fs << " color *= 1.0 - clamp(d, 0.0, 1.0);" << endl; 636 } 637 fs << " gl_FragColor = color;" << endl; 638 fs << "}" << endl; 639 640 result.mVertexShaderString = vs.str(); 641 result.mFragmentShaderString = fs.str(); 642 643 if (aConfig.mFeatures & ENABLE_RENDER_COLOR) { 644 result.mTextureCount = 0; 645 } else { 646 if (aConfig.mFeatures & ENABLE_TEXTURE_YCBCR) { 647 result.mTextureCount = 3; 648 } else if (aConfig.mFeatures & ENABLE_TEXTURE_NV12) { 649 result.mTextureCount = 2; 650 } else if (aConfig.mFeatures & ENABLE_TEXTURE_COMPONENT_ALPHA) { 651 result.mTextureCount = 2; 652 } else { 653 result.mTextureCount = 1; 654 } 655 } 656 if (aConfig.mFeatures & ENABLE_MASK) { 657 result.mTextureCount = 1; 658 } 659 if (BlendOpIsMixBlendMode(blendOp)) { 660 result.mTextureCount += 1; 661 } 662 663 return result; 664 } 665 666 void ProgramProfileOGL::BuildMixBlender(const ShaderConfigOGL& aConfig, 667 std::ostringstream& fs) { 668 // From the "Compositing and Blending Level 1" spec. 669 // Generate helper functions first. 670 switch (aConfig.mCompositionOp) { 671 case gfx::CompositionOp::OP_OVERLAY: 672 case gfx::CompositionOp::OP_HARD_LIGHT: 673 // Note: we substitute (2*src-1) into the screen formula below. 674 fs << "float hardlight(float dest, float src) {" << endl; 675 fs << " if (src <= 0.5) {" << endl; 676 fs << " return dest * (2.0 * src);" << endl; 677 fs << " } else {" << endl; 678 fs << " return 2.0*dest + 2.0*src - 1.0 - 2.0*dest*src;" << endl; 679 fs << " }" << endl; 680 fs << "}" << endl; 681 break; 682 case gfx::CompositionOp::OP_COLOR_DODGE: 683 fs << "float dodge(float dest, float src) {" << endl; 684 fs << " if (dest == 0.0) {" << endl; 685 fs << " return 0.0;" << endl; 686 fs << " } else if (src == 1.0) {" << endl; 687 fs << " return 1.0;" << endl; 688 fs << " } else {" << endl; 689 fs << " return min(1.0, dest / (1.0 - src));" << endl; 690 fs << " }" << endl; 691 fs << "}" << endl; 692 break; 693 case gfx::CompositionOp::OP_COLOR_BURN: 694 fs << "float burn(float dest, float src) {" << endl; 695 fs << " if (dest == 1.0) {" << endl; 696 fs << " return 1.0;" << endl; 697 fs << " } else if (src == 0.0) {" << endl; 698 fs << " return 0.0;" << endl; 699 fs << " } else {" << endl; 700 fs << " return 1.0 - min(1.0, (1.0 - dest) / src);" << endl; 701 fs << " }" << endl; 702 fs << "}" << endl; 703 break; 704 case gfx::CompositionOp::OP_SOFT_LIGHT: 705 fs << "float darken(float dest) {" << endl; 706 fs << " if (dest <= 0.25) {" << endl; 707 fs << " return ((16.0 * dest - 12.0) * dest + 4.0) * dest;" << endl; 708 fs << " } else {" << endl; 709 fs << " return sqrt(dest);" << endl; 710 fs << " }" << endl; 711 fs << "}" << endl; 712 fs << "float softlight(float dest, float src) {" << endl; 713 fs << " if (src <= 0.5) {" << endl; 714 fs << " return dest - (1.0 - 2.0 * src) * dest * (1.0 - dest);" 715 << endl; 716 fs << " } else {" << endl; 717 fs << " return dest + (2.0 * src - 1.0) * (darken(dest) - dest);" 718 << endl; 719 fs << " }" << endl; 720 fs << "}" << endl; 721 break; 722 case gfx::CompositionOp::OP_HUE: 723 case gfx::CompositionOp::OP_SATURATION: 724 case gfx::CompositionOp::OP_COLOR: 725 case gfx::CompositionOp::OP_LUMINOSITY: 726 fs << "float Lum(vec3 c) {" << endl; 727 fs << " return dot(vec3(0.3, 0.59, 0.11), c);" << endl; 728 fs << "}" << endl; 729 fs << "vec3 ClipColor(vec3 c) {" << endl; 730 fs << " float L = Lum(c);" << endl; 731 fs << " float n = min(min(c.r, c.g), c.b);" << endl; 732 fs << " float x = max(max(c.r, c.g), c.b);" << endl; 733 fs << " if (n < 0.0) {" << endl; 734 fs << " c = L + (((c - L) * L) / (L - n));" << endl; 735 fs << " }" << endl; 736 fs << " if (x > 1.0) {" << endl; 737 fs << " c = L + (((c - L) * (1.0 - L)) / (x - L));" << endl; 738 fs << " }" << endl; 739 fs << " return c;" << endl; 740 fs << "}" << endl; 741 fs << "vec3 SetLum(vec3 c, float L) {" << endl; 742 fs << " float d = L - Lum(c);" << endl; 743 fs << " return ClipColor(vec3(" << endl; 744 fs << " c.r + d," << endl; 745 fs << " c.g + d," << endl; 746 fs << " c.b + d));" << endl; 747 fs << "}" << endl; 748 fs << "float Sat(vec3 c) {" << endl; 749 fs << " return max(max(c.r, c.g), c.b) - min(min(c.r, c.g), c.b);" 750 << endl; 751 fs << "}" << endl; 752 753 // To use this helper, re-arrange rgb such that r=min, g=mid, and b=max. 754 fs << "vec3 SetSatInner(vec3 c, float s) {" << endl; 755 fs << " if (c.b > c.r) {" << endl; 756 fs << " c.g = (((c.g - c.r) * s) / (c.b - c.r));" << endl; 757 fs << " c.b = s;" << endl; 758 fs << " } else {" << endl; 759 fs << " c.gb = vec2(0.0, 0.0);" << endl; 760 fs << " }" << endl; 761 fs << " return vec3(0.0, c.gb);" << endl; 762 fs << "}" << endl; 763 764 fs << "vec3 SetSat(vec3 c, float s) {" << endl; 765 fs << " if (c.r <= c.g) {" << endl; 766 fs << " if (c.g <= c.b) {" << endl; 767 fs << " c.rgb = SetSatInner(c.rgb, s);" << endl; 768 fs << " } else if (c.r <= c.b) {" << endl; 769 fs << " c.rbg = SetSatInner(c.rbg, s);" << endl; 770 fs << " } else {" << endl; 771 fs << " c.brg = SetSatInner(c.brg, s);" << endl; 772 fs << " }" << endl; 773 fs << " } else if (c.r <= c.b) {" << endl; 774 fs << " c.grb = SetSatInner(c.grb, s);" << endl; 775 fs << " } else if (c.g <= c.b) {" << endl; 776 fs << " c.gbr = SetSatInner(c.gbr, s);" << endl; 777 fs << " } else {" << endl; 778 fs << " c.bgr = SetSatInner(c.bgr, s);" << endl; 779 fs << " }" << endl; 780 fs << " return c;" << endl; 781 fs << "}" << endl; 782 break; 783 default: 784 break; 785 } 786 787 // Generate the main blending helper. 788 fs << "vec3 blend(vec3 dest, vec3 src) {" << endl; 789 switch (aConfig.mCompositionOp) { 790 case gfx::CompositionOp::OP_MULTIPLY: 791 fs << " return dest * src;" << endl; 792 break; 793 case gfx::CompositionOp::OP_SCREEN: 794 fs << " return dest + src - (dest * src);" << endl; 795 break; 796 case gfx::CompositionOp::OP_OVERLAY: 797 fs << " return vec3(" << endl; 798 fs << " hardlight(src.r, dest.r)," << endl; 799 fs << " hardlight(src.g, dest.g)," << endl; 800 fs << " hardlight(src.b, dest.b));" << endl; 801 break; 802 case gfx::CompositionOp::OP_DARKEN: 803 fs << " return min(dest, src);" << endl; 804 break; 805 case gfx::CompositionOp::OP_LIGHTEN: 806 fs << " return max(dest, src);" << endl; 807 break; 808 case gfx::CompositionOp::OP_COLOR_DODGE: 809 fs << " return vec3(" << endl; 810 fs << " dodge(dest.r, src.r)," << endl; 811 fs << " dodge(dest.g, src.g)," << endl; 812 fs << " dodge(dest.b, src.b));" << endl; 813 break; 814 case gfx::CompositionOp::OP_COLOR_BURN: 815 fs << " return vec3(" << endl; 816 fs << " burn(dest.r, src.r)," << endl; 817 fs << " burn(dest.g, src.g)," << endl; 818 fs << " burn(dest.b, src.b));" << endl; 819 break; 820 case gfx::CompositionOp::OP_HARD_LIGHT: 821 fs << " return vec3(" << endl; 822 fs << " hardlight(dest.r, src.r)," << endl; 823 fs << " hardlight(dest.g, src.g)," << endl; 824 fs << " hardlight(dest.b, src.b));" << endl; 825 break; 826 case gfx::CompositionOp::OP_SOFT_LIGHT: 827 fs << " return vec3(" << endl; 828 fs << " softlight(dest.r, src.r)," << endl; 829 fs << " softlight(dest.g, src.g)," << endl; 830 fs << " softlight(dest.b, src.b));" << endl; 831 break; 832 case gfx::CompositionOp::OP_DIFFERENCE: 833 fs << " return abs(dest - src);" << endl; 834 break; 835 case gfx::CompositionOp::OP_EXCLUSION: 836 fs << " return dest + src - 2.0*dest*src;" << endl; 837 break; 838 case gfx::CompositionOp::OP_HUE: 839 fs << " return SetLum(SetSat(src, Sat(dest)), Lum(dest));" << endl; 840 break; 841 case gfx::CompositionOp::OP_SATURATION: 842 fs << " return SetLum(SetSat(dest, Sat(src)), Lum(dest));" << endl; 843 break; 844 case gfx::CompositionOp::OP_COLOR: 845 fs << " return SetLum(src, Lum(dest));" << endl; 846 break; 847 case gfx::CompositionOp::OP_LUMINOSITY: 848 fs << " return SetLum(dest, Lum(src));" << endl; 849 break; 850 default: 851 MOZ_ASSERT_UNREACHABLE("unknown blend mode"); 852 } 853 fs << "}" << endl; 854 855 // Generate the mix-blend function the fragment shader will call. 856 fs << "vec4 mixAndBlend(vec4 backdrop, vec4 color) {" << endl; 857 858 // Shortcut when the backdrop or source alpha is 0, otherwise we may leak 859 // Infinity into the blend function and return incorrect results. 860 fs << " if (backdrop.a == 0.0) {" << endl; 861 fs << " return color;" << endl; 862 fs << " }" << endl; 863 fs << " if (color.a == 0.0) {" << endl; 864 fs << " return vec4(0.0, 0.0, 0.0, 0.0);" << endl; 865 fs << " }" << endl; 866 867 // The spec assumes there is no premultiplied alpha. The backdrop is always 868 // premultiplied, so undo the premultiply. If the source is premultiplied we 869 // must fix that as well. 870 fs << " backdrop.rgb /= backdrop.a;" << endl; 871 if (!(aConfig.mFeatures & ENABLE_NO_PREMUL_ALPHA)) { 872 fs << " color.rgb /= color.a;" << endl; 873 } 874 fs << " vec3 blended = blend(backdrop.rgb, color.rgb);" << endl; 875 fs << " color.rgb = (1.0 - backdrop.a) * color.rgb + backdrop.a * " 876 "blended.rgb;" 877 << endl; 878 fs << " color.rgb *= color.a;" << endl; 879 fs << " return color;" << endl; 880 fs << "}" << endl; 881 } 882 883 ShaderProgramOGL::ShaderProgramOGL(GLContext* aGL, 884 const ProgramProfileOGL& aProfile) 885 : mGL(aGL), mProgram(0), mProfile(aProfile), mProgramState(STATE_NEW) {} 886 887 ShaderProgramOGL::~ShaderProgramOGL() { 888 if (mProgram <= 0) { 889 return; 890 } 891 892 RefPtr<GLContext> ctx = mGL->GetSharedContext(); 893 if (!ctx) { 894 ctx = mGL; 895 } 896 ctx->MakeCurrent(); 897 ctx->fDeleteProgram(mProgram); 898 } 899 900 bool ShaderProgramOGL::Initialize() { 901 NS_ASSERTION(mProgramState == STATE_NEW, 902 "Shader program has already been initialised"); 903 904 std::ostringstream vs, fs; 905 for (uint32_t i = 0; i < mProfile.mDefines.Length(); ++i) { 906 vs << mProfile.mDefines[i] << endl; 907 fs << mProfile.mDefines[i] << endl; 908 } 909 vs << mProfile.mVertexShaderString << endl; 910 fs << mProfile.mFragmentShaderString << endl; 911 912 if (!CreateProgram(vs.str().c_str(), fs.str().c_str())) { 913 mProgramState = STATE_ERROR; 914 return false; 915 } 916 917 mProgramState = STATE_OK; 918 919 for (uint32_t i = 0; i < KnownUniform::KnownUniformCount; ++i) { 920 mProfile.mUniforms[i].mLocation = 921 mGL->fGetUniformLocation(mProgram, mProfile.mUniforms[i].mNameString); 922 } 923 924 return true; 925 } 926 927 GLint ShaderProgramOGL::CreateShader(GLenum aShaderType, 928 const char* aShaderSource) { 929 GLint success, len = 0; 930 931 GLint sh = mGL->fCreateShader(aShaderType); 932 mGL->fShaderSource(sh, 1, (const GLchar**)&aShaderSource, nullptr); 933 mGL->fCompileShader(sh); 934 mGL->fGetShaderiv(sh, LOCAL_GL_COMPILE_STATUS, &success); 935 mGL->fGetShaderiv(sh, LOCAL_GL_INFO_LOG_LENGTH, (GLint*)&len); 936 /* Even if compiling is successful, there may still be warnings. Print them 937 * in a debug build. The > 10 is to catch silly compilers that might put 938 * some whitespace in the log but otherwise leave it empty. 939 */ 940 if (!success 941 #ifdef DEBUG 942 || (len > 10 && gfxEnv::MOZ_DEBUG_SHADERS()) 943 #endif 944 ) { 945 nsAutoCString log; 946 log.SetLength(len); 947 mGL->fGetShaderInfoLog(sh, len, (GLint*)&len, (char*)log.BeginWriting()); 948 log.Truncate(len); 949 950 if (!success) { 951 printf_stderr("=== SHADER COMPILATION FAILED ===\n"); 952 } else { 953 printf_stderr("=== SHADER COMPILATION WARNINGS ===\n"); 954 } 955 956 printf_stderr("=== Source:\n%s\n", aShaderSource); 957 printf_stderr("=== Log:\n%s\n", log.get()); 958 printf_stderr("============\n"); 959 960 if (!success) { 961 mGL->fDeleteShader(sh); 962 return 0; 963 } 964 } 965 966 return sh; 967 } 968 969 bool ShaderProgramOGL::CreateProgram(const char* aVertexShaderString, 970 const char* aFragmentShaderString) { 971 GLuint vertexShader = 972 CreateShader(LOCAL_GL_VERTEX_SHADER, aVertexShaderString); 973 GLuint fragmentShader = 974 CreateShader(LOCAL_GL_FRAGMENT_SHADER, aFragmentShaderString); 975 976 if (!vertexShader || !fragmentShader) return false; 977 978 GLint result = mGL->fCreateProgram(); 979 mGL->fAttachShader(result, vertexShader); 980 mGL->fAttachShader(result, fragmentShader); 981 982 for (std::pair<nsCString, GLuint>& attribute : mProfile.mAttributes) { 983 mGL->fBindAttribLocation(result, attribute.second, attribute.first.get()); 984 } 985 986 mGL->fLinkProgram(result); 987 988 GLint success, len; 989 mGL->fGetProgramiv(result, LOCAL_GL_LINK_STATUS, &success); 990 mGL->fGetProgramiv(result, LOCAL_GL_INFO_LOG_LENGTH, (GLint*)&len); 991 /* Even if linking is successful, there may still be warnings. Print them 992 * in a debug build. The > 10 is to catch silly compilers that might put 993 * some whitespace in the log but otherwise leave it empty. 994 */ 995 if (!success 996 #ifdef DEBUG 997 || (len > 10 && gfxEnv::MOZ_DEBUG_SHADERS()) 998 #endif 999 ) { 1000 nsAutoCString log; 1001 log.SetLength(len); 1002 mGL->fGetProgramInfoLog(result, len, (GLint*)&len, 1003 (char*)log.BeginWriting()); 1004 1005 if (!success) { 1006 printf_stderr("=== PROGRAM LINKING FAILED ===\n"); 1007 } else { 1008 printf_stderr("=== PROGRAM LINKING WARNINGS ===\n"); 1009 } 1010 printf_stderr("=== Log:\n%s\n", log.get()); 1011 printf_stderr("============\n"); 1012 } 1013 1014 // We can mark the shaders for deletion; they're attached to the program 1015 // and will remain attached. 1016 mGL->fDeleteShader(vertexShader); 1017 mGL->fDeleteShader(fragmentShader); 1018 1019 if (!success) { 1020 mGL->fDeleteProgram(result); 1021 return false; 1022 } 1023 1024 mProgram = result; 1025 return true; 1026 } 1027 1028 GLuint ShaderProgramOGL::GetProgram() { 1029 if (mProgramState == STATE_NEW) { 1030 if (!Initialize()) { 1031 NS_WARNING("Shader could not be initialised"); 1032 } 1033 } 1034 MOZ_ASSERT(HasInitialized(), 1035 "Attempting to get a program that's not been initialized!"); 1036 return mProgram; 1037 } 1038 1039 void ShaderProgramOGL::SetYUVColorSpace(gfx::YUVColorSpace aYUVColorSpace) { 1040 const float* yuvToRgb = 1041 gfxUtils::YuvToRgbMatrix3x3ColumnMajor(aYUVColorSpace); 1042 SetMatrix3fvUniform(KnownUniform::YuvColorMatrix, yuvToRgb); 1043 if (aYUVColorSpace == gfx::YUVColorSpace::Identity) { 1044 const float identity[] = {0.0, 0.0, 0.0}; 1045 SetVec3fvUniform(KnownUniform::YuvOffsetVector, identity); 1046 } else { 1047 const float offset[] = {0.06275, 0.50196, 0.50196}; 1048 SetVec3fvUniform(KnownUniform::YuvOffsetVector, offset); 1049 } 1050 } 1051 1052 ShaderProgramOGLsHolder::ShaderProgramOGLsHolder(gl::GLContext* aGL) 1053 : mGL(aGL) {} 1054 1055 ShaderProgramOGLsHolder::~ShaderProgramOGLsHolder() { Clear(); } 1056 1057 ShaderProgramOGL* ShaderProgramOGLsHolder::GetShaderProgramFor( 1058 const ShaderConfigOGL& aConfig) { 1059 auto iter = mPrograms.find(aConfig); 1060 if (iter != mPrograms.end()) { 1061 return iter->second.get(); 1062 } 1063 1064 ProgramProfileOGL profile = ProgramProfileOGL::GetProfileFor(aConfig); 1065 auto shader = MakeUnique<ShaderProgramOGL>(mGL, profile); 1066 if (!shader->Initialize()) { 1067 gfxCriticalError() << "Shader compilation failure, cfg:" 1068 << " features: " << gfx::hexa(aConfig.mFeatures) 1069 << " multiplier: " << aConfig.mMultiplier 1070 << " op: " << aConfig.mCompositionOp; 1071 return nullptr; 1072 } 1073 1074 mPrograms.emplace(aConfig, std::move(shader)); 1075 return mPrograms[aConfig].get(); 1076 } 1077 1078 void ShaderProgramOGLsHolder::Clear() { mPrograms.clear(); } 1079 1080 ShaderProgramOGL* ShaderProgramOGLsHolder::ActivateProgram( 1081 const ShaderConfigOGL& aConfig) { 1082 ShaderProgramOGL* program = GetShaderProgramFor(aConfig); 1083 MOZ_DIAGNOSTIC_ASSERT(program); 1084 if (!program) { 1085 return nullptr; 1086 } 1087 if (mCurrentProgram != program) { 1088 mGL->fUseProgram(program->GetProgram()); 1089 mCurrentProgram = program; 1090 } 1091 return program; 1092 } 1093 1094 void ShaderProgramOGLsHolder::ResetCurrentProgram() { 1095 mCurrentProgram = nullptr; 1096 } 1097 1098 } // namespace layers 1099 } // namespace mozilla