LCOV - code coverage report
Current view: top level - gfx/layers/opengl - OGLShaderProgram.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 594 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 26 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13