Coverage Report

Created: 2018-09-25 14:53

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