Explicitly add python-numpy dependency to install-build-deps.
[chromium-blink-merge.git] / cc / output / shader.cc
blobe22e4464a515974d4744722ab65c9a5e6d1e4c03
1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/output/shader.h"
7 #include <algorithm>
9 #include "base/basictypes.h"
10 #include "base/logging.h"
11 #include "cc/output/gl_renderer.h" // For the GLC() macro.
12 #include "gpu/command_buffer/client/gles2_interface.h"
14 #define SHADER0(Src) #Src
15 #define VERTEX_SHADER(Src) SetVertexTexCoordPrecision(SHADER0(Src))
16 #define FRAGMENT_SHADER(Src) \
17 SetFragmentTexCoordPrecision( \
18 precision, \
19 SetFragmentSamplerType(sampler, SetBlendModeFunctions(SHADER0(Src))))
21 using gpu::gles2::GLES2Interface;
23 namespace cc {
25 namespace {
27 static void GetProgramUniformLocations(GLES2Interface* context,
28 unsigned program,
29 size_t count,
30 const char** uniforms,
31 int* locations,
32 int* base_uniform_index) {
33 for (size_t i = 0; i < count; i++) {
34 locations[i] = (*base_uniform_index)++;
35 context->BindUniformLocationCHROMIUM(program, locations[i], uniforms[i]);
39 static std::string SetFragmentTexCoordPrecision(
40 TexCoordPrecision requested_precision,
41 std::string shader_string) {
42 switch (requested_precision) {
43 case TexCoordPrecisionHigh:
44 DCHECK_NE(shader_string.find("TexCoordPrecision"), std::string::npos);
45 return "#ifdef GL_FRAGMENT_PRECISION_HIGH\n"
46 " #define TexCoordPrecision highp\n"
47 "#else\n"
48 " #define TexCoordPrecision mediump\n"
49 "#endif\n" +
50 shader_string;
51 case TexCoordPrecisionMedium:
52 DCHECK_NE(shader_string.find("TexCoordPrecision"), std::string::npos);
53 return "#define TexCoordPrecision mediump\n" + shader_string;
54 case TexCoordPrecisionNA:
55 DCHECK_EQ(shader_string.find("TexCoordPrecision"), std::string::npos);
56 DCHECK_EQ(shader_string.find("texture2D"), std::string::npos);
57 DCHECK_EQ(shader_string.find("texture2DRect"), std::string::npos);
58 return shader_string;
59 default:
60 NOTREACHED();
61 break;
63 return shader_string;
66 static std::string SetVertexTexCoordPrecision(const char* shader_string) {
67 // We unconditionally use highp in the vertex shader since
68 // we are unlikely to be vertex shader bound when drawing large quads.
69 // Also, some vertex shaders mutate the texture coordinate in such a
70 // way that the effective precision might be lower than expected.
71 return "#define TexCoordPrecision highp\n" + std::string(shader_string);
74 TexCoordPrecision TexCoordPrecisionRequired(GLES2Interface* context,
75 int* highp_threshold_cache,
76 int highp_threshold_min,
77 int x,
78 int y) {
79 if (*highp_threshold_cache == 0) {
80 // Initialize range and precision with minimum spec values for when
81 // GetShaderPrecisionFormat is a test stub.
82 // TODO(brianderson): Implement better stubs of GetShaderPrecisionFormat
83 // everywhere.
84 GLint range[2] = {14, 14};
85 GLint precision = 10;
86 GLC(context,
87 context->GetShaderPrecisionFormat(
88 GL_FRAGMENT_SHADER, GL_MEDIUM_FLOAT, range, &precision));
89 *highp_threshold_cache = 1 << precision;
92 int highp_threshold = std::max(*highp_threshold_cache, highp_threshold_min);
93 if (x > highp_threshold || y > highp_threshold)
94 return TexCoordPrecisionHigh;
95 return TexCoordPrecisionMedium;
98 static std::string SetFragmentSamplerType(SamplerType requested_type,
99 std::string shader_string) {
100 switch (requested_type) {
101 case SamplerType2D:
102 DCHECK_NE(shader_string.find("SamplerType"), std::string::npos);
103 DCHECK_NE(shader_string.find("TextureLookup"), std::string::npos);
104 return "#define SamplerType sampler2D\n"
105 "#define TextureLookup texture2D\n" +
106 shader_string;
107 case SamplerType2DRect:
108 DCHECK_NE(shader_string.find("SamplerType"), std::string::npos);
109 DCHECK_NE(shader_string.find("TextureLookup"), std::string::npos);
110 return "#extension GL_ARB_texture_rectangle : require\n"
111 "#define SamplerType sampler2DRect\n"
112 "#define TextureLookup texture2DRect\n" +
113 shader_string;
114 case SamplerTypeExternalOES:
115 DCHECK_NE(shader_string.find("SamplerType"), std::string::npos);
116 DCHECK_NE(shader_string.find("TextureLookup"), std::string::npos);
117 return "#extension GL_OES_EGL_image_external : require\n"
118 "#define SamplerType samplerExternalOES\n"
119 "#define TextureLookup texture2D\n" +
120 shader_string;
121 case SamplerTypeNA:
122 DCHECK_EQ(shader_string.find("SamplerType"), std::string::npos);
123 DCHECK_EQ(shader_string.find("TextureLookup"), std::string::npos);
124 return shader_string;
125 default:
126 NOTREACHED();
127 break;
129 return shader_string;
132 } // namespace
134 TexCoordPrecision TexCoordPrecisionRequired(GLES2Interface* context,
135 int* highp_threshold_cache,
136 int highp_threshold_min,
137 const gfx::Point& max_coordinate) {
138 return TexCoordPrecisionRequired(context,
139 highp_threshold_cache,
140 highp_threshold_min,
141 max_coordinate.x(),
142 max_coordinate.y());
145 TexCoordPrecision TexCoordPrecisionRequired(GLES2Interface* context,
146 int* highp_threshold_cache,
147 int highp_threshold_min,
148 const gfx::Size& max_size) {
149 return TexCoordPrecisionRequired(context,
150 highp_threshold_cache,
151 highp_threshold_min,
152 max_size.width(),
153 max_size.height());
156 VertexShaderPosTex::VertexShaderPosTex() : matrix_location_(-1) {
159 void VertexShaderPosTex::Init(GLES2Interface* context,
160 unsigned program,
161 int* base_uniform_index) {
162 static const char* uniforms[] = {
163 "matrix",
165 int locations[arraysize(uniforms)];
167 GetProgramUniformLocations(context,
168 program,
169 arraysize(uniforms),
170 uniforms,
171 locations,
172 base_uniform_index);
173 matrix_location_ = locations[0];
176 std::string VertexShaderPosTex::GetShaderString() const {
177 // clang-format off
178 return VERTEX_SHADER(
179 // clang-format on
180 attribute vec4 a_position;
181 attribute TexCoordPrecision vec2 a_texCoord;
182 uniform mat4 matrix;
183 varying TexCoordPrecision vec2 v_texCoord;
184 void main() {
185 gl_Position = matrix * a_position;
186 v_texCoord = a_texCoord;
188 // clang-format off
189 ); // NOLINT(whitespace/parens)
190 // clang-format on
193 VertexShaderPosTexYUVStretchOffset::VertexShaderPosTexYUVStretchOffset()
194 : matrix_location_(-1), tex_scale_location_(-1), tex_offset_location_(-1) {
197 void VertexShaderPosTexYUVStretchOffset::Init(GLES2Interface* context,
198 unsigned program,
199 int* base_uniform_index) {
200 static const char* uniforms[] = {
201 "matrix", "texScale", "texOffset",
203 int locations[arraysize(uniforms)];
205 GetProgramUniformLocations(context,
206 program,
207 arraysize(uniforms),
208 uniforms,
209 locations,
210 base_uniform_index);
211 matrix_location_ = locations[0];
212 tex_scale_location_ = locations[1];
213 tex_offset_location_ = locations[2];
216 std::string VertexShaderPosTexYUVStretchOffset::GetShaderString() const {
217 // clang-format off
218 return VERTEX_SHADER(
219 // clang-format on
220 precision mediump float;
221 attribute vec4 a_position;
222 attribute TexCoordPrecision vec2 a_texCoord;
223 uniform mat4 matrix;
224 varying TexCoordPrecision vec2 v_texCoord;
225 uniform TexCoordPrecision vec2 texScale;
226 uniform TexCoordPrecision vec2 texOffset;
227 void main() {
228 gl_Position = matrix * a_position;
229 v_texCoord = a_texCoord * texScale + texOffset;
231 // clang-format off
232 ); // NOLINT(whitespace/parens)
233 // clang-format on
236 VertexShaderPos::VertexShaderPos() : matrix_location_(-1) {
239 void VertexShaderPos::Init(GLES2Interface* context,
240 unsigned program,
241 int* base_uniform_index) {
242 static const char* uniforms[] = {
243 "matrix",
245 int locations[arraysize(uniforms)];
247 GetProgramUniformLocations(context,
248 program,
249 arraysize(uniforms),
250 uniforms,
251 locations,
252 base_uniform_index);
253 matrix_location_ = locations[0];
256 std::string VertexShaderPos::GetShaderString() const {
257 // clang-format off
258 return VERTEX_SHADER(
259 // clang-format on
260 attribute vec4 a_position;
261 uniform mat4 matrix;
262 void main() { gl_Position = matrix * a_position; }
263 // clang-format off
264 ); // NOLINT(whitespace/parens)
265 // clang-format on
268 VertexShaderPosTexTransform::VertexShaderPosTexTransform()
269 : matrix_location_(-1),
270 tex_transform_location_(-1),
271 vertex_opacity_location_(-1) {
274 void VertexShaderPosTexTransform::Init(GLES2Interface* context,
275 unsigned program,
276 int* base_uniform_index) {
277 static const char* uniforms[] = {
278 "matrix", "texTransform", "opacity",
280 int locations[arraysize(uniforms)];
282 GetProgramUniformLocations(context,
283 program,
284 arraysize(uniforms),
285 uniforms,
286 locations,
287 base_uniform_index);
288 matrix_location_ = locations[0];
289 tex_transform_location_ = locations[1];
290 vertex_opacity_location_ = locations[2];
293 std::string VertexShaderPosTexTransform::GetShaderString() const {
294 // clang-format off
295 return VERTEX_SHADER(
296 // clang-format on
297 attribute vec4 a_position;
298 attribute TexCoordPrecision vec2 a_texCoord;
299 attribute float a_index;
300 uniform mat4 matrix[8];
301 uniform TexCoordPrecision vec4 texTransform[8];
302 uniform float opacity[32];
303 varying TexCoordPrecision vec2 v_texCoord;
304 varying float v_alpha;
305 void main() {
306 int quad_index = int(a_index * 0.25); // NOLINT
307 gl_Position = matrix[quad_index] * a_position;
308 TexCoordPrecision vec4 texTrans = texTransform[quad_index];
309 v_texCoord = a_texCoord * texTrans.zw + texTrans.xy;
310 v_alpha = opacity[int(a_index)]; // NOLINT
312 // clang-format off
313 ); // NOLINT(whitespace/parens)
314 // clang-format on
317 std::string VertexShaderPosTexIdentity::GetShaderString() const {
318 // clang-format off
319 return VERTEX_SHADER(
320 // clang-format on
321 attribute vec4 a_position;
322 varying TexCoordPrecision vec2 v_texCoord;
323 void main() {
324 gl_Position = a_position;
325 v_texCoord = (a_position.xy + vec2(1.0)) * 0.5;
327 // clang-format off
328 ); // NOLINT(whitespace/parens)
329 // clang-format on
332 VertexShaderQuad::VertexShaderQuad()
333 : matrix_location_(-1), quad_location_(-1) {
336 void VertexShaderQuad::Init(GLES2Interface* context,
337 unsigned program,
338 int* base_uniform_index) {
339 static const char* uniforms[] = {
340 "matrix", "quad",
342 int locations[arraysize(uniforms)];
344 GetProgramUniformLocations(context,
345 program,
346 arraysize(uniforms),
347 uniforms,
348 locations,
349 base_uniform_index);
350 matrix_location_ = locations[0];
351 quad_location_ = locations[1];
354 std::string VertexShaderQuad::GetShaderString() const {
355 #if defined(OS_ANDROID)
356 // TODO(epenner): Find the cause of this 'quad' uniform
357 // being missing if we don't add dummy variables.
358 // http://crbug.com/240602
359 // clang-format off
360 return VERTEX_SHADER(
361 // clang-format on
362 attribute TexCoordPrecision vec4 a_position;
363 attribute float a_index;
364 uniform mat4 matrix;
365 uniform TexCoordPrecision vec2 quad[4];
366 uniform TexCoordPrecision vec2 dummy_uniform;
367 varying TexCoordPrecision vec2 dummy_varying;
368 void main() {
369 vec2 pos = quad[int(a_index)]; // NOLINT
370 gl_Position = matrix * vec4(pos, a_position.z, a_position.w);
371 dummy_varying = dummy_uniform;
373 // clang-format off
374 ); // NOLINT(whitespace/parens)
375 // clang-format on
376 #else
377 // clang-format off
378 return VERTEX_SHADER(
379 // clang-format on
380 attribute TexCoordPrecision vec4 a_position;
381 attribute float a_index;
382 uniform mat4 matrix;
383 uniform TexCoordPrecision vec2 quad[4];
384 void main() {
385 vec2 pos = quad[int(a_index)]; // NOLINT
386 gl_Position = matrix * vec4(pos, a_position.z, a_position.w);
388 // clang-format off
389 ); // NOLINT(whitespace/parens)
390 // clang-format on
391 #endif
394 VertexShaderQuadAA::VertexShaderQuadAA()
395 : matrix_location_(-1),
396 viewport_location_(-1),
397 quad_location_(-1),
398 edge_location_(-1) {
401 void VertexShaderQuadAA::Init(GLES2Interface* context,
402 unsigned program,
403 int* base_uniform_index) {
404 static const char* uniforms[] = {
405 "matrix", "viewport", "quad", "edge",
407 int locations[arraysize(uniforms)];
409 GetProgramUniformLocations(context,
410 program,
411 arraysize(uniforms),
412 uniforms,
413 locations,
414 base_uniform_index);
415 matrix_location_ = locations[0];
416 viewport_location_ = locations[1];
417 quad_location_ = locations[2];
418 edge_location_ = locations[3];
421 std::string VertexShaderQuadAA::GetShaderString() const {
422 // clang-format off
423 return VERTEX_SHADER(
424 // clang-format on
425 attribute TexCoordPrecision vec4 a_position;
426 attribute float a_index;
427 uniform mat4 matrix;
428 uniform vec4 viewport;
429 uniform TexCoordPrecision vec2 quad[4];
430 uniform TexCoordPrecision vec3 edge[8];
431 varying TexCoordPrecision vec4 edge_dist[2]; // 8 edge distances.
433 void main() {
434 vec2 pos = quad[int(a_index)]; // NOLINT
435 gl_Position = matrix * vec4(pos, a_position.z, a_position.w);
436 vec2 ndc_pos = 0.5 * (1.0 + gl_Position.xy / gl_Position.w);
437 vec3 screen_pos = vec3(viewport.xy + viewport.zw * ndc_pos, 1.0);
438 edge_dist[0] = vec4(dot(edge[0], screen_pos),
439 dot(edge[1], screen_pos),
440 dot(edge[2], screen_pos),
441 dot(edge[3], screen_pos)) *
442 gl_Position.w;
443 edge_dist[1] = vec4(dot(edge[4], screen_pos),
444 dot(edge[5], screen_pos),
445 dot(edge[6], screen_pos),
446 dot(edge[7], screen_pos)) *
447 gl_Position.w;
449 // clang-format off
450 ); // NOLINT(whitespace/parens)
451 // clang-format on
454 VertexShaderQuadTexTransformAA::VertexShaderQuadTexTransformAA()
455 : matrix_location_(-1),
456 viewport_location_(-1),
457 quad_location_(-1),
458 edge_location_(-1),
459 tex_transform_location_(-1) {
462 void VertexShaderQuadTexTransformAA::Init(GLES2Interface* context,
463 unsigned program,
464 int* base_uniform_index) {
465 static const char* uniforms[] = {
466 "matrix", "viewport", "quad", "edge", "texTrans",
468 int locations[arraysize(uniforms)];
470 GetProgramUniformLocations(context,
471 program,
472 arraysize(uniforms),
473 uniforms,
474 locations,
475 base_uniform_index);
476 matrix_location_ = locations[0];
477 viewport_location_ = locations[1];
478 quad_location_ = locations[2];
479 edge_location_ = locations[3];
480 tex_transform_location_ = locations[4];
483 std::string VertexShaderQuadTexTransformAA::GetShaderString() const {
484 // clang-format off
485 return VERTEX_SHADER(
486 // clang-format on
487 attribute TexCoordPrecision vec4 a_position;
488 attribute float a_index;
489 uniform mat4 matrix;
490 uniform vec4 viewport;
491 uniform TexCoordPrecision vec2 quad[4];
492 uniform TexCoordPrecision vec3 edge[8];
493 uniform TexCoordPrecision vec4 texTrans;
494 varying TexCoordPrecision vec2 v_texCoord;
495 varying TexCoordPrecision vec4 edge_dist[2]; // 8 edge distances.
497 void main() {
498 vec2 pos = quad[int(a_index)]; // NOLINT
499 gl_Position = matrix * vec4(pos, a_position.z, a_position.w);
500 vec2 ndc_pos = 0.5 * (1.0 + gl_Position.xy / gl_Position.w);
501 vec3 screen_pos = vec3(viewport.xy + viewport.zw * ndc_pos, 1.0);
502 edge_dist[0] = vec4(dot(edge[0], screen_pos),
503 dot(edge[1], screen_pos),
504 dot(edge[2], screen_pos),
505 dot(edge[3], screen_pos)) *
506 gl_Position.w;
507 edge_dist[1] = vec4(dot(edge[4], screen_pos),
508 dot(edge[5], screen_pos),
509 dot(edge[6], screen_pos),
510 dot(edge[7], screen_pos)) *
511 gl_Position.w;
512 v_texCoord = (pos.xy + vec2(0.5)) * texTrans.zw + texTrans.xy;
514 // clang-format off
515 ); // NOLINT(whitespace/parens)
516 // clang-format on
519 VertexShaderTile::VertexShaderTile()
520 : matrix_location_(-1),
521 quad_location_(-1),
522 vertex_tex_transform_location_(-1) {
525 void VertexShaderTile::Init(GLES2Interface* context,
526 unsigned program,
527 int* base_uniform_index) {
528 static const char* uniforms[] = {
529 "matrix", "quad", "vertexTexTransform",
531 int locations[arraysize(uniforms)];
533 GetProgramUniformLocations(context,
534 program,
535 arraysize(uniforms),
536 uniforms,
537 locations,
538 base_uniform_index);
539 matrix_location_ = locations[0];
540 quad_location_ = locations[1];
541 vertex_tex_transform_location_ = locations[2];
544 std::string VertexShaderTile::GetShaderString() const {
545 // clang-format off
546 return VERTEX_SHADER(
547 // clang-format on
548 attribute TexCoordPrecision vec4 a_position;
549 attribute TexCoordPrecision vec2 a_texCoord;
550 attribute float a_index;
551 uniform mat4 matrix;
552 uniform TexCoordPrecision vec2 quad[4];
553 uniform TexCoordPrecision vec4 vertexTexTransform;
554 varying TexCoordPrecision vec2 v_texCoord;
555 void main() {
556 vec2 pos = quad[int(a_index)]; // NOLINT
557 gl_Position = matrix * vec4(pos, a_position.z, a_position.w);
558 v_texCoord = a_texCoord * vertexTexTransform.zw + vertexTexTransform.xy;
560 // clang-format off
561 ); // NOLINT(whitespace/parens)
562 // clang-format on
565 VertexShaderTileAA::VertexShaderTileAA()
566 : matrix_location_(-1),
567 viewport_location_(-1),
568 quad_location_(-1),
569 edge_location_(-1),
570 vertex_tex_transform_location_(-1) {
573 void VertexShaderTileAA::Init(GLES2Interface* context,
574 unsigned program,
575 int* base_uniform_index) {
576 static const char* uniforms[] = {
577 "matrix", "viewport", "quad", "edge", "vertexTexTransform",
579 int locations[arraysize(uniforms)];
581 GetProgramUniformLocations(context,
582 program,
583 arraysize(uniforms),
584 uniforms,
585 locations,
586 base_uniform_index);
587 matrix_location_ = locations[0];
588 viewport_location_ = locations[1];
589 quad_location_ = locations[2];
590 edge_location_ = locations[3];
591 vertex_tex_transform_location_ = locations[4];
594 std::string VertexShaderTileAA::GetShaderString() const {
595 // clang-format off
596 return VERTEX_SHADER(
597 // clang-format on
598 attribute TexCoordPrecision vec4 a_position;
599 attribute float a_index;
600 uniform mat4 matrix;
601 uniform vec4 viewport;
602 uniform TexCoordPrecision vec2 quad[4];
603 uniform TexCoordPrecision vec3 edge[8];
604 uniform TexCoordPrecision vec4 vertexTexTransform;
605 varying TexCoordPrecision vec2 v_texCoord;
606 varying TexCoordPrecision vec4 edge_dist[2]; // 8 edge distances.
608 void main() {
609 vec2 pos = quad[int(a_index)]; // NOLINT
610 gl_Position = matrix * vec4(pos, a_position.z, a_position.w);
611 vec2 ndc_pos = 0.5 * (1.0 + gl_Position.xy / gl_Position.w);
612 vec3 screen_pos = vec3(viewport.xy + viewport.zw * ndc_pos, 1.0);
613 edge_dist[0] = vec4(dot(edge[0], screen_pos),
614 dot(edge[1], screen_pos),
615 dot(edge[2], screen_pos),
616 dot(edge[3], screen_pos)) *
617 gl_Position.w;
618 edge_dist[1] = vec4(dot(edge[4], screen_pos),
619 dot(edge[5], screen_pos),
620 dot(edge[6], screen_pos),
621 dot(edge[7], screen_pos)) *
622 gl_Position.w;
623 v_texCoord = pos.xy * vertexTexTransform.zw + vertexTexTransform.xy;
625 // clang-format off
626 ); // NOLINT(whitespace/parens)
627 // clang-format on
630 VertexShaderVideoTransform::VertexShaderVideoTransform()
631 : matrix_location_(-1), tex_matrix_location_(-1) {
634 void VertexShaderVideoTransform::Init(GLES2Interface* context,
635 unsigned program,
636 int* base_uniform_index) {
637 static const char* uniforms[] = {
638 "matrix", "texMatrix",
640 int locations[arraysize(uniforms)];
642 GetProgramUniformLocations(context,
643 program,
644 arraysize(uniforms),
645 uniforms,
646 locations,
647 base_uniform_index);
648 matrix_location_ = locations[0];
649 tex_matrix_location_ = locations[1];
652 std::string VertexShaderVideoTransform::GetShaderString() const {
653 // clang-format off
654 return VERTEX_SHADER(
655 // clang-format on
656 attribute vec4 a_position;
657 attribute TexCoordPrecision vec2 a_texCoord;
658 uniform mat4 matrix;
659 uniform TexCoordPrecision mat4 texMatrix;
660 varying TexCoordPrecision vec2 v_texCoord;
661 void main() {
662 gl_Position = matrix * a_position;
663 v_texCoord =
664 vec2(texMatrix * vec4(a_texCoord.x, 1.0 - a_texCoord.y, 0.0, 1.0));
666 // clang-format off
667 ); // NOLINT(whitespace/parens)
668 // clang-format on
671 #define BLEND_MODE_UNIFORMS "s_backdropTexture", "backdropRect"
672 #define UNUSED_BLEND_MODE_UNIFORMS (!has_blend_mode() ? 2 : 0)
673 #define BLEND_MODE_SET_LOCATIONS(X, POS) \
674 if (has_blend_mode()) { \
675 DCHECK_LT(static_cast<size_t>(POS) + 1, arraysize(X)); \
676 backdrop_location_ = locations[POS]; \
677 backdrop_rect_location_ = locations[POS + 1]; \
680 FragmentTexBlendMode::FragmentTexBlendMode()
681 : backdrop_location_(-1),
682 backdrop_rect_location_(-1),
683 blend_mode_(BlendModeNone) {
686 std::string FragmentTexBlendMode::SetBlendModeFunctions(
687 std::string shader_string) const {
688 if (shader_string.find("ApplyBlendMode") == std::string::npos)
689 return shader_string;
691 if (!has_blend_mode()) {
692 return "#define ApplyBlendMode(X) (X)\n" + shader_string;
695 // clang-format off
696 static const std::string kFunctionApplyBlendMode = SHADER0(
697 // clang-format on
698 uniform SamplerType s_backdropTexture;
699 uniform TexCoordPrecision vec4 backdropRect;
701 vec4 GetBackdropColor() {
702 TexCoordPrecision vec2 bgTexCoord = gl_FragCoord.xy - backdropRect.xy;
703 bgTexCoord.x /= backdropRect.z;
704 bgTexCoord.y /= backdropRect.w;
705 return TextureLookup(s_backdropTexture, bgTexCoord);
708 vec4 ApplyBlendMode(vec4 src) {
709 vec4 dst = GetBackdropColor();
710 return Blend(src, dst);
712 // clang-format off
713 ); // NOLINT(whitespace/parens)
714 // clang-format on
716 return "precision mediump float;" + GetHelperFunctions() +
717 GetBlendFunction() + kFunctionApplyBlendMode + shader_string;
720 std::string FragmentTexBlendMode::GetHelperFunctions() const {
721 // clang-format off
722 static const std::string kFunctionHardLight = SHADER0(
723 // clang-format on
724 vec3 hardLight(vec4 src, vec4 dst) {
725 vec3 result;
726 result.r =
727 (2.0 * src.r <= src.a)
728 ? (2.0 * src.r * dst.r)
729 : (src.a * dst.a - 2.0 * (dst.a - dst.r) * (src.a - src.r));
730 result.g =
731 (2.0 * src.g <= src.a)
732 ? (2.0 * src.g * dst.g)
733 : (src.a * dst.a - 2.0 * (dst.a - dst.g) * (src.a - src.g));
734 result.b =
735 (2.0 * src.b <= src.a)
736 ? (2.0 * src.b * dst.b)
737 : (src.a * dst.a - 2.0 * (dst.a - dst.b) * (src.a - src.b));
738 result.rgb += src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a);
739 return result;
741 // clang-format off
742 ); // NOLINT(whitespace/parens)
744 static const std::string kFunctionColorDodgeComponent = SHADER0(
745 // clang-format on
746 float getColorDodgeComponent(
747 float srcc, float srca, float dstc, float dsta) {
748 if (0.0 == dstc)
749 return srcc * (1.0 - dsta);
750 float d = srca - srcc;
751 if (0.0 == d)
752 return srca * dsta + srcc * (1.0 - dsta) + dstc * (1.0 - srca);
753 d = min(dsta, dstc * srca / d);
754 return d * srca + srcc * (1.0 - dsta) + dstc * (1.0 - srca);
756 // clang-format off
757 ); // NOLINT(whitespace/parens)
759 static const std::string kFunctionColorBurnComponent = SHADER0(
760 // clang-format on
761 float getColorBurnComponent(
762 float srcc, float srca, float dstc, float dsta) {
763 if (dsta == dstc)
764 return srca * dsta + srcc * (1.0 - dsta) + dstc * (1.0 - srca);
765 if (0.0 == srcc)
766 return dstc * (1.0 - srca);
767 float d = max(0.0, dsta - (dsta - dstc) * srca / srcc);
768 return srca * d + srcc * (1.0 - dsta) + dstc * (1.0 - srca);
770 // clang-format off
771 ); // NOLINT(whitespace/parens)
773 static const std::string kFunctionSoftLightComponentPosDstAlpha = SHADER0(
774 // clang-format on
775 float getSoftLightComponent(
776 float srcc, float srca, float dstc, float dsta) {
777 if (2.0 * srcc <= srca) {
778 return (dstc * dstc * (srca - 2.0 * srcc)) / dsta +
779 (1.0 - dsta) * srcc + dstc * (-srca + 2.0 * srcc + 1.0);
780 } else if (4.0 * dstc <= dsta) {
781 float DSqd = dstc * dstc;
782 float DCub = DSqd * dstc;
783 float DaSqd = dsta * dsta;
784 float DaCub = DaSqd * dsta;
785 return (-DaCub * srcc +
786 DaSqd * (srcc - dstc * (3.0 * srca - 6.0 * srcc - 1.0)) +
787 12.0 * dsta * DSqd * (srca - 2.0 * srcc) -
788 16.0 * DCub * (srca - 2.0 * srcc)) /
789 DaSqd;
790 } else {
791 return -sqrt(dsta * dstc) * (srca - 2.0 * srcc) - dsta * srcc +
792 dstc * (srca - 2.0 * srcc + 1.0) + srcc;
795 // clang-format off
796 ); // NOLINT(whitespace/parens)
798 static const std::string kFunctionLum = SHADER0(
799 // clang-format on
800 float luminance(vec3 color) { return dot(vec3(0.3, 0.59, 0.11), color); }
802 vec3 set_luminance(vec3 hueSat, float alpha, vec3 lumColor) {
803 float diff = luminance(lumColor - hueSat);
804 vec3 outColor = hueSat + diff;
805 float outLum = luminance(outColor);
806 float minComp = min(min(outColor.r, outColor.g), outColor.b);
807 float maxComp = max(max(outColor.r, outColor.g), outColor.b);
808 if (minComp < 0.0 && outLum != minComp) {
809 outColor = outLum +
810 ((outColor - vec3(outLum, outLum, outLum)) * outLum) /
811 (outLum - minComp);
813 if (maxComp > alpha && maxComp != outLum) {
814 outColor =
815 outLum +
816 ((outColor - vec3(outLum, outLum, outLum)) * (alpha - outLum)) /
817 (maxComp - outLum);
819 return outColor;
821 // clang-format off
822 ); // NOLINT(whitespace/parens)
824 static const std::string kFunctionSat = SHADER0(
825 // clang-format on
826 float saturation(vec3 color) {
827 return max(max(color.r, color.g), color.b) -
828 min(min(color.r, color.g), color.b);
831 vec3 set_saturation_helper(
832 float minComp, float midComp, float maxComp, float sat) {
833 if (minComp < maxComp) {
834 vec3 result;
835 result.r = 0.0;
836 result.g = sat * (midComp - minComp) / (maxComp - minComp);
837 result.b = sat;
838 return result;
839 } else {
840 return vec3(0, 0, 0);
844 vec3 set_saturation(vec3 hueLumColor, vec3 satColor) {
845 float sat = saturation(satColor);
846 if (hueLumColor.r <= hueLumColor.g) {
847 if (hueLumColor.g <= hueLumColor.b) {
848 hueLumColor.rgb = set_saturation_helper(
849 hueLumColor.r, hueLumColor.g, hueLumColor.b, sat);
850 } else if (hueLumColor.r <= hueLumColor.b) {
851 hueLumColor.rbg = set_saturation_helper(
852 hueLumColor.r, hueLumColor.b, hueLumColor.g, sat);
853 } else {
854 hueLumColor.brg = set_saturation_helper(
855 hueLumColor.b, hueLumColor.r, hueLumColor.g, sat);
857 } else if (hueLumColor.r <= hueLumColor.b) {
858 hueLumColor.grb = set_saturation_helper(
859 hueLumColor.g, hueLumColor.r, hueLumColor.b, sat);
860 } else if (hueLumColor.g <= hueLumColor.b) {
861 hueLumColor.gbr = set_saturation_helper(
862 hueLumColor.g, hueLumColor.b, hueLumColor.r, sat);
863 } else {
864 hueLumColor.bgr = set_saturation_helper(
865 hueLumColor.b, hueLumColor.g, hueLumColor.r, sat);
867 return hueLumColor;
869 // clang-format off
870 ); // NOLINT(whitespace/parens)
871 // clang-format on
873 switch (blend_mode_) {
874 case BlendModeOverlay:
875 case BlendModeHardLight:
876 return kFunctionHardLight;
877 case BlendModeColorDodge:
878 return kFunctionColorDodgeComponent;
879 case BlendModeColorBurn:
880 return kFunctionColorBurnComponent;
881 case BlendModeSoftLight:
882 return kFunctionSoftLightComponentPosDstAlpha;
883 case BlendModeHue:
884 case BlendModeSaturation:
885 return kFunctionLum + kFunctionSat;
886 case BlendModeColor:
887 case BlendModeLuminosity:
888 return kFunctionLum;
889 default:
890 return std::string();
894 std::string FragmentTexBlendMode::GetBlendFunction() const {
895 return "vec4 Blend(vec4 src, vec4 dst) {"
896 " vec4 result;"
897 " result.a = src.a + (1.0 - src.a) * dst.a;" +
898 GetBlendFunctionBodyForRGB() +
899 " return result;"
900 "}";
903 std::string FragmentTexBlendMode::GetBlendFunctionBodyForRGB() const {
904 switch (blend_mode_) {
905 case BlendModeNormal:
906 return "result.rgb = src.rgb + dst.rgb * (1.0 - src.a);";
907 case BlendModeScreen:
908 return "result.rgb = src.rgb + (1.0 - src.rgb) * dst.rgb;";
909 case BlendModeLighten:
910 return "result.rgb = max((1.0 - src.a) * dst.rgb + src.rgb,"
911 " (1.0 - dst.a) * src.rgb + dst.rgb);";
912 case BlendModeOverlay:
913 return "result.rgb = hardLight(dst, src);";
914 case BlendModeDarken:
915 return "result.rgb = min((1.0 - src.a) * dst.rgb + src.rgb,"
916 " (1.0 - dst.a) * src.rgb + dst.rgb);";
917 case BlendModeColorDodge:
918 return "result.r = getColorDodgeComponent(src.r, src.a, dst.r, dst.a);"
919 "result.g = getColorDodgeComponent(src.g, src.a, dst.g, dst.a);"
920 "result.b = getColorDodgeComponent(src.b, src.a, dst.b, dst.a);";
921 case BlendModeColorBurn:
922 return "result.r = getColorBurnComponent(src.r, src.a, dst.r, dst.a);"
923 "result.g = getColorBurnComponent(src.g, src.a, dst.g, dst.a);"
924 "result.b = getColorBurnComponent(src.b, src.a, dst.b, dst.a);";
925 case BlendModeHardLight:
926 return "result.rgb = hardLight(src, dst);";
927 case BlendModeSoftLight:
928 return "if (0.0 == dst.a) {"
929 " result.rgb = src.rgb;"
930 "} else {"
931 " result.r = getSoftLightComponent(src.r, src.a, dst.r, dst.a);"
932 " result.g = getSoftLightComponent(src.g, src.a, dst.g, dst.a);"
933 " result.b = getSoftLightComponent(src.b, src.a, dst.b, dst.a);"
934 "}";
935 case BlendModeDifference:
936 return "result.rgb = src.rgb + dst.rgb -"
937 " 2.0 * min(src.rgb * dst.a, dst.rgb * src.a);";
938 case BlendModeExclusion:
939 return "result.rgb = dst.rgb + src.rgb - 2.0 * dst.rgb * src.rgb;";
940 case BlendModeMultiply:
941 return "result.rgb = (1.0 - src.a) * dst.rgb +"
942 " (1.0 - dst.a) * src.rgb + src.rgb * dst.rgb;";
943 case BlendModeHue:
944 return "vec4 dstSrcAlpha = dst * src.a;"
945 "result.rgb ="
946 " set_luminance(set_saturation(src.rgb * dst.a,"
947 " dstSrcAlpha.rgb),"
948 " dstSrcAlpha.a,"
949 " dstSrcAlpha.rgb);"
950 "result.rgb += (1.0 - src.a) * dst.rgb + (1.0 - dst.a) * src.rgb;";
951 case BlendModeSaturation:
952 return "vec4 dstSrcAlpha = dst * src.a;"
953 "result.rgb = set_luminance(set_saturation(dstSrcAlpha.rgb,"
954 " src.rgb * dst.a),"
955 " dstSrcAlpha.a,"
956 " dstSrcAlpha.rgb);"
957 "result.rgb += (1.0 - src.a) * dst.rgb + (1.0 - dst.a) * src.rgb;";
958 case BlendModeColor:
959 return "vec4 srcDstAlpha = src * dst.a;"
960 "result.rgb = set_luminance(srcDstAlpha.rgb,"
961 " srcDstAlpha.a,"
962 " dst.rgb * src.a);"
963 "result.rgb += (1.0 - src.a) * dst.rgb + (1.0 - dst.a) * src.rgb;";
964 case BlendModeLuminosity:
965 return "vec4 srcDstAlpha = src * dst.a;"
966 "result.rgb = set_luminance(dst.rgb * src.a,"
967 " srcDstAlpha.a,"
968 " srcDstAlpha.rgb);"
969 "result.rgb += (1.0 - src.a) * dst.rgb + (1.0 - dst.a) * src.rgb;";
970 case BlendModeNone:
971 case NumBlendModes:
972 NOTREACHED();
974 return "result = vec4(1.0, 0.0, 0.0, 1.0);";
977 FragmentTexAlphaBinding::FragmentTexAlphaBinding()
978 : sampler_location_(-1), alpha_location_(-1) {
981 void FragmentTexAlphaBinding::Init(GLES2Interface* context,
982 unsigned program,
983 int* base_uniform_index) {
984 static const char* uniforms[] = {
985 "s_texture", "alpha", BLEND_MODE_UNIFORMS,
987 int locations[arraysize(uniforms)];
989 GetProgramUniformLocations(context,
990 program,
991 arraysize(uniforms) - UNUSED_BLEND_MODE_UNIFORMS,
992 uniforms,
993 locations,
994 base_uniform_index);
995 sampler_location_ = locations[0];
996 alpha_location_ = locations[1];
997 BLEND_MODE_SET_LOCATIONS(locations, 2);
1000 FragmentTexColorMatrixAlphaBinding::FragmentTexColorMatrixAlphaBinding()
1001 : sampler_location_(-1),
1002 alpha_location_(-1),
1003 color_matrix_location_(-1),
1004 color_offset_location_(-1) {
1007 void FragmentTexColorMatrixAlphaBinding::Init(GLES2Interface* context,
1008 unsigned program,
1009 int* base_uniform_index) {
1010 static const char* uniforms[] = {
1011 "s_texture", "alpha", "colorMatrix", "colorOffset", BLEND_MODE_UNIFORMS,
1013 int locations[arraysize(uniforms)];
1015 GetProgramUniformLocations(context,
1016 program,
1017 arraysize(uniforms) - UNUSED_BLEND_MODE_UNIFORMS,
1018 uniforms,
1019 locations,
1020 base_uniform_index);
1021 sampler_location_ = locations[0];
1022 alpha_location_ = locations[1];
1023 color_matrix_location_ = locations[2];
1024 color_offset_location_ = locations[3];
1025 BLEND_MODE_SET_LOCATIONS(locations, 4);
1028 FragmentTexOpaqueBinding::FragmentTexOpaqueBinding() : sampler_location_(-1) {
1031 void FragmentTexOpaqueBinding::Init(GLES2Interface* context,
1032 unsigned program,
1033 int* base_uniform_index) {
1034 static const char* uniforms[] = {
1035 "s_texture",
1037 int locations[arraysize(uniforms)];
1039 GetProgramUniformLocations(context,
1040 program,
1041 arraysize(uniforms),
1042 uniforms,
1043 locations,
1044 base_uniform_index);
1045 sampler_location_ = locations[0];
1048 std::string FragmentShaderRGBATexAlpha::GetShaderString(
1049 TexCoordPrecision precision,
1050 SamplerType sampler) const {
1051 // clang-format off
1052 return FRAGMENT_SHADER(
1053 // clang-format on
1054 precision mediump float;
1055 varying TexCoordPrecision vec2 v_texCoord;
1056 uniform SamplerType s_texture;
1057 uniform float alpha;
1058 void main() {
1059 vec4 texColor = TextureLookup(s_texture, v_texCoord);
1060 gl_FragColor = ApplyBlendMode(texColor * alpha);
1062 // clang-format off
1063 ); // NOLINT(whitespace/parens)
1064 // clang-format on
1067 std::string FragmentShaderRGBATexColorMatrixAlpha::GetShaderString(
1068 TexCoordPrecision precision,
1069 SamplerType sampler) const {
1070 // clang-format off
1071 return FRAGMENT_SHADER(
1072 // clang-format on
1073 precision mediump float;
1074 varying TexCoordPrecision vec2 v_texCoord;
1075 uniform SamplerType s_texture;
1076 uniform float alpha;
1077 uniform mat4 colorMatrix;
1078 uniform vec4 colorOffset;
1079 void main() {
1080 vec4 texColor = TextureLookup(s_texture, v_texCoord);
1081 float nonZeroAlpha = max(texColor.a, 0.00001);
1082 texColor = vec4(texColor.rgb / nonZeroAlpha, nonZeroAlpha);
1083 texColor = colorMatrix * texColor + colorOffset;
1084 texColor.rgb *= texColor.a;
1085 texColor = clamp(texColor, 0.0, 1.0);
1086 gl_FragColor = ApplyBlendMode(texColor * alpha);
1088 // clang-format off
1089 ); // NOLINT(whitespace/parens)
1090 // clang-format on
1093 std::string FragmentShaderRGBATexVaryingAlpha::GetShaderString(
1094 TexCoordPrecision precision,
1095 SamplerType sampler) const {
1096 // clang-format off
1097 return FRAGMENT_SHADER(
1098 // clang-format on
1099 precision mediump float;
1100 varying TexCoordPrecision vec2 v_texCoord;
1101 varying float v_alpha;
1102 uniform SamplerType s_texture;
1103 void main() {
1104 vec4 texColor = TextureLookup(s_texture, v_texCoord);
1105 gl_FragColor = texColor * v_alpha;
1107 // clang-format off
1108 ); // NOLINT(whitespace/parens)
1109 // clang-format on
1112 std::string FragmentShaderRGBATexPremultiplyAlpha::GetShaderString(
1113 TexCoordPrecision precision,
1114 SamplerType sampler) const {
1115 // clang-format off
1116 return FRAGMENT_SHADER(
1117 // clang-format on
1118 precision mediump float;
1119 varying TexCoordPrecision vec2 v_texCoord;
1120 varying float v_alpha;
1121 uniform SamplerType s_texture;
1122 void main() {
1123 vec4 texColor = TextureLookup(s_texture, v_texCoord);
1124 texColor.rgb *= texColor.a;
1125 gl_FragColor = texColor * v_alpha;
1127 // clang-format off
1128 ); // NOLINT(whitespace/parens)
1129 // clang-format on
1132 FragmentTexBackgroundBinding::FragmentTexBackgroundBinding()
1133 : background_color_location_(-1), sampler_location_(-1) {
1136 void FragmentTexBackgroundBinding::Init(GLES2Interface* context,
1137 unsigned program,
1138 int* base_uniform_index) {
1139 static const char* uniforms[] = {
1140 "s_texture", "background_color",
1142 int locations[arraysize(uniforms)];
1144 GetProgramUniformLocations(context,
1145 program,
1146 arraysize(uniforms),
1147 uniforms,
1148 locations,
1149 base_uniform_index);
1151 sampler_location_ = locations[0];
1152 DCHECK_NE(sampler_location_, -1);
1154 background_color_location_ = locations[1];
1155 DCHECK_NE(background_color_location_, -1);
1158 std::string FragmentShaderTexBackgroundVaryingAlpha::GetShaderString(
1159 TexCoordPrecision precision,
1160 SamplerType sampler) const {
1161 // clang-format off
1162 return FRAGMENT_SHADER(
1163 // clang-format on
1164 precision mediump float;
1165 varying TexCoordPrecision vec2 v_texCoord;
1166 varying float v_alpha;
1167 uniform vec4 background_color;
1168 uniform SamplerType s_texture;
1169 void main() {
1170 vec4 texColor = TextureLookup(s_texture, v_texCoord);
1171 texColor += background_color * (1.0 - texColor.a);
1172 gl_FragColor = texColor * v_alpha;
1174 // clang-format off
1175 ); // NOLINT(whitespace/parens)
1176 // clang-format on
1179 std::string FragmentShaderTexBackgroundPremultiplyAlpha::GetShaderString(
1180 TexCoordPrecision precision,
1181 SamplerType sampler) const {
1182 // clang-format off
1183 return FRAGMENT_SHADER(
1184 // clang-format on
1185 precision mediump float;
1186 varying TexCoordPrecision vec2 v_texCoord;
1187 varying float v_alpha;
1188 uniform vec4 background_color;
1189 uniform SamplerType s_texture;
1190 void main() {
1191 vec4 texColor = TextureLookup(s_texture, v_texCoord);
1192 texColor.rgb *= texColor.a;
1193 texColor += background_color * (1.0 - texColor.a);
1194 gl_FragColor = texColor * v_alpha;
1196 // clang-format off
1197 ); // NOLINT(whitespace/parens)
1198 // clang-format on
1201 std::string FragmentShaderRGBATexOpaque::GetShaderString(
1202 TexCoordPrecision precision,
1203 SamplerType sampler) const {
1204 // clang-format off
1205 return FRAGMENT_SHADER(
1206 // clang-format on
1207 precision mediump float;
1208 varying TexCoordPrecision vec2 v_texCoord;
1209 uniform SamplerType s_texture;
1210 void main() {
1211 vec4 texColor = TextureLookup(s_texture, v_texCoord);
1212 gl_FragColor = vec4(texColor.rgb, 1.0);
1214 // clang-format off
1215 ); // NOLINT(whitespace/parens)
1216 // clang-format on
1219 std::string FragmentShaderRGBATex::GetShaderString(TexCoordPrecision precision,
1220 SamplerType sampler) const {
1221 // clang-format off
1222 return FRAGMENT_SHADER(
1223 // clang-format on
1224 precision mediump float;
1225 varying TexCoordPrecision vec2 v_texCoord;
1226 uniform SamplerType s_texture;
1227 void main() { gl_FragColor = TextureLookup(s_texture, v_texCoord); }
1228 // clang-format off
1229 ); // NOLINT(whitespace/parens)
1230 // clang-format on
1233 std::string FragmentShaderRGBATexSwizzleAlpha::GetShaderString(
1234 TexCoordPrecision precision,
1235 SamplerType sampler) const {
1236 // clang-format off
1237 return FRAGMENT_SHADER(
1238 // clang-format on
1239 precision mediump float;
1240 varying TexCoordPrecision vec2 v_texCoord;
1241 uniform SamplerType s_texture;
1242 uniform float alpha;
1243 void main() {
1244 vec4 texColor = TextureLookup(s_texture, v_texCoord);
1245 gl_FragColor =
1246 vec4(texColor.z, texColor.y, texColor.x, texColor.w) * alpha;
1248 // clang-format off
1249 ); // NOLINT(whitespace/parens)
1250 // clang-format on
1253 std::string FragmentShaderRGBATexSwizzleOpaque::GetShaderString(
1254 TexCoordPrecision precision,
1255 SamplerType sampler) const {
1256 // clang-format off
1257 return FRAGMENT_SHADER(
1258 // clang-format on
1259 precision mediump float;
1260 varying TexCoordPrecision vec2 v_texCoord;
1261 uniform SamplerType s_texture;
1262 void main() {
1263 vec4 texColor = TextureLookup(s_texture, v_texCoord);
1264 gl_FragColor = vec4(texColor.z, texColor.y, texColor.x, 1.0);
1266 // clang-format off
1267 ); // NOLINT(whitespace/parens)
1268 // clang-format on
1271 FragmentShaderRGBATexAlphaAA::FragmentShaderRGBATexAlphaAA()
1272 : sampler_location_(-1), alpha_location_(-1) {
1275 void FragmentShaderRGBATexAlphaAA::Init(GLES2Interface* context,
1276 unsigned program,
1277 int* base_uniform_index) {
1278 static const char* uniforms[] = {
1279 "s_texture", "alpha", BLEND_MODE_UNIFORMS,
1281 int locations[arraysize(uniforms)];
1283 GetProgramUniformLocations(context,
1284 program,
1285 arraysize(uniforms) - UNUSED_BLEND_MODE_UNIFORMS,
1286 uniforms,
1287 locations,
1288 base_uniform_index);
1289 sampler_location_ = locations[0];
1290 alpha_location_ = locations[1];
1291 BLEND_MODE_SET_LOCATIONS(locations, 2);
1294 std::string FragmentShaderRGBATexAlphaAA::GetShaderString(
1295 TexCoordPrecision precision,
1296 SamplerType sampler) const {
1297 // clang-format off
1298 return FRAGMENT_SHADER(
1299 // clang-format on
1300 precision mediump float;
1301 uniform SamplerType s_texture;
1302 uniform float alpha;
1303 varying TexCoordPrecision vec2 v_texCoord;
1304 varying TexCoordPrecision vec4 edge_dist[2]; // 8 edge distances.
1306 void main() {
1307 vec4 texColor = TextureLookup(s_texture, v_texCoord);
1308 vec4 d4 = min(edge_dist[0], edge_dist[1]);
1309 vec2 d2 = min(d4.xz, d4.yw);
1310 float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
1311 gl_FragColor = ApplyBlendMode(texColor * alpha * aa);
1313 // clang-format off
1314 ); // NOLINT(whitespace/parens)
1315 // clang-format on
1318 FragmentTexClampAlphaAABinding::FragmentTexClampAlphaAABinding()
1319 : sampler_location_(-1),
1320 alpha_location_(-1),
1321 fragment_tex_transform_location_(-1) {
1324 void FragmentTexClampAlphaAABinding::Init(GLES2Interface* context,
1325 unsigned program,
1326 int* base_uniform_index) {
1327 static const char* uniforms[] = {
1328 "s_texture", "alpha", "fragmentTexTransform",
1330 int locations[arraysize(uniforms)];
1332 GetProgramUniformLocations(context,
1333 program,
1334 arraysize(uniforms),
1335 uniforms,
1336 locations,
1337 base_uniform_index);
1338 sampler_location_ = locations[0];
1339 alpha_location_ = locations[1];
1340 fragment_tex_transform_location_ = locations[2];
1343 std::string FragmentShaderRGBATexClampAlphaAA::GetShaderString(
1344 TexCoordPrecision precision,
1345 SamplerType sampler) const {
1346 // clang-format off
1347 return FRAGMENT_SHADER(
1348 // clang-format on
1349 precision mediump float;
1350 uniform SamplerType s_texture;
1351 uniform float alpha;
1352 uniform TexCoordPrecision vec4 fragmentTexTransform;
1353 varying TexCoordPrecision vec2 v_texCoord;
1354 varying TexCoordPrecision vec4 edge_dist[2]; // 8 edge distances.
1356 void main() {
1357 TexCoordPrecision vec2 texCoord =
1358 clamp(v_texCoord, 0.0, 1.0) * fragmentTexTransform.zw +
1359 fragmentTexTransform.xy;
1360 vec4 texColor = TextureLookup(s_texture, texCoord);
1361 vec4 d4 = min(edge_dist[0], edge_dist[1]);
1362 vec2 d2 = min(d4.xz, d4.yw);
1363 float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
1364 gl_FragColor = texColor * alpha * aa;
1366 // clang-format off
1367 ); // NOLINT(whitespace/parens)
1368 // clang-format on
1371 std::string FragmentShaderRGBATexClampSwizzleAlphaAA::GetShaderString(
1372 TexCoordPrecision precision,
1373 SamplerType sampler) const {
1374 // clang-format off
1375 return FRAGMENT_SHADER(
1376 // clang-format on
1377 precision mediump float;
1378 uniform SamplerType s_texture;
1379 uniform float alpha;
1380 uniform TexCoordPrecision vec4 fragmentTexTransform;
1381 varying TexCoordPrecision vec2 v_texCoord;
1382 varying TexCoordPrecision vec4 edge_dist[2]; // 8 edge distances.
1384 void main() {
1385 TexCoordPrecision vec2 texCoord =
1386 clamp(v_texCoord, 0.0, 1.0) * fragmentTexTransform.zw +
1387 fragmentTexTransform.xy;
1388 vec4 texColor = TextureLookup(s_texture, texCoord);
1389 vec4 d4 = min(edge_dist[0], edge_dist[1]);
1390 vec2 d2 = min(d4.xz, d4.yw);
1391 float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
1392 gl_FragColor =
1393 vec4(texColor.z, texColor.y, texColor.x, texColor.w) * alpha * aa;
1395 // clang-format off
1396 ); // NOLINT(whitespace/parens)
1397 // clang-format on
1400 FragmentShaderRGBATexAlphaMask::FragmentShaderRGBATexAlphaMask()
1401 : sampler_location_(-1),
1402 mask_sampler_location_(-1),
1403 alpha_location_(-1),
1404 mask_tex_coord_scale_location_(-1) {
1407 void FragmentShaderRGBATexAlphaMask::Init(GLES2Interface* context,
1408 unsigned program,
1409 int* base_uniform_index) {
1410 static const char* uniforms[] = {
1411 "s_texture",
1412 "s_mask",
1413 "alpha",
1414 "maskTexCoordScale",
1415 "maskTexCoordOffset",
1416 BLEND_MODE_UNIFORMS,
1418 int locations[arraysize(uniforms)];
1420 GetProgramUniformLocations(context,
1421 program,
1422 arraysize(uniforms) - UNUSED_BLEND_MODE_UNIFORMS,
1423 uniforms,
1424 locations,
1425 base_uniform_index);
1426 sampler_location_ = locations[0];
1427 mask_sampler_location_ = locations[1];
1428 alpha_location_ = locations[2];
1429 mask_tex_coord_scale_location_ = locations[3];
1430 mask_tex_coord_offset_location_ = locations[4];
1431 BLEND_MODE_SET_LOCATIONS(locations, 5);
1434 std::string FragmentShaderRGBATexAlphaMask::GetShaderString(
1435 TexCoordPrecision precision,
1436 SamplerType sampler) const {
1437 // clang-format off
1438 return FRAGMENT_SHADER(
1439 // clang-format on
1440 precision mediump float;
1441 varying TexCoordPrecision vec2 v_texCoord;
1442 uniform sampler2D s_texture;
1443 uniform SamplerType s_mask;
1444 uniform TexCoordPrecision vec2 maskTexCoordScale;
1445 uniform TexCoordPrecision vec2 maskTexCoordOffset;
1446 uniform float alpha;
1447 void main() {
1448 vec4 texColor = texture2D(s_texture, v_texCoord);
1449 TexCoordPrecision vec2 maskTexCoord =
1450 vec2(maskTexCoordOffset.x + v_texCoord.x * maskTexCoordScale.x,
1451 maskTexCoordOffset.y + v_texCoord.y * maskTexCoordScale.y);
1452 vec4 maskColor = TextureLookup(s_mask, maskTexCoord);
1453 gl_FragColor = ApplyBlendMode(texColor * alpha * maskColor.w);
1455 // clang-format off
1456 ); // NOLINT(whitespace/parens)
1457 // clang-format on
1460 FragmentShaderRGBATexAlphaMaskAA::FragmentShaderRGBATexAlphaMaskAA()
1461 : sampler_location_(-1),
1462 mask_sampler_location_(-1),
1463 alpha_location_(-1),
1464 mask_tex_coord_scale_location_(-1),
1465 mask_tex_coord_offset_location_(-1) {
1468 void FragmentShaderRGBATexAlphaMaskAA::Init(GLES2Interface* context,
1469 unsigned program,
1470 int* base_uniform_index) {
1471 static const char* uniforms[] = {
1472 "s_texture",
1473 "s_mask",
1474 "alpha",
1475 "maskTexCoordScale",
1476 "maskTexCoordOffset",
1477 BLEND_MODE_UNIFORMS,
1479 int locations[arraysize(uniforms)];
1481 GetProgramUniformLocations(context,
1482 program,
1483 arraysize(uniforms) - UNUSED_BLEND_MODE_UNIFORMS,
1484 uniforms,
1485 locations,
1486 base_uniform_index);
1487 sampler_location_ = locations[0];
1488 mask_sampler_location_ = locations[1];
1489 alpha_location_ = locations[2];
1490 mask_tex_coord_scale_location_ = locations[3];
1491 mask_tex_coord_offset_location_ = locations[4];
1492 BLEND_MODE_SET_LOCATIONS(locations, 5);
1495 std::string FragmentShaderRGBATexAlphaMaskAA::GetShaderString(
1496 TexCoordPrecision precision,
1497 SamplerType sampler) const {
1498 // clang-format off
1499 return FRAGMENT_SHADER(
1500 // clang-format on
1501 precision mediump float;
1502 uniform sampler2D s_texture;
1503 uniform SamplerType s_mask;
1504 uniform TexCoordPrecision vec2 maskTexCoordScale;
1505 uniform TexCoordPrecision vec2 maskTexCoordOffset;
1506 uniform float alpha;
1507 varying TexCoordPrecision vec2 v_texCoord;
1508 varying TexCoordPrecision vec4 edge_dist[2]; // 8 edge distances.
1510 void main() {
1511 vec4 texColor = texture2D(s_texture, v_texCoord);
1512 TexCoordPrecision vec2 maskTexCoord =
1513 vec2(maskTexCoordOffset.x + v_texCoord.x * maskTexCoordScale.x,
1514 maskTexCoordOffset.y + v_texCoord.y * maskTexCoordScale.y);
1515 vec4 maskColor = TextureLookup(s_mask, maskTexCoord);
1516 vec4 d4 = min(edge_dist[0], edge_dist[1]);
1517 vec2 d2 = min(d4.xz, d4.yw);
1518 float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
1519 gl_FragColor = ApplyBlendMode(texColor * alpha * maskColor.w * aa);
1521 // clang-format off
1522 ); // NOLINT(whitespace/parens)
1523 // clang-format on
1526 FragmentShaderRGBATexAlphaMaskColorMatrixAA::
1527 FragmentShaderRGBATexAlphaMaskColorMatrixAA()
1528 : sampler_location_(-1),
1529 mask_sampler_location_(-1),
1530 alpha_location_(-1),
1531 mask_tex_coord_scale_location_(-1),
1532 color_matrix_location_(-1),
1533 color_offset_location_(-1) {
1536 void FragmentShaderRGBATexAlphaMaskColorMatrixAA::Init(
1537 GLES2Interface* context,
1538 unsigned program,
1539 int* base_uniform_index) {
1540 static const char* uniforms[] = {
1541 "s_texture",
1542 "s_mask",
1543 "alpha",
1544 "maskTexCoordScale",
1545 "maskTexCoordOffset",
1546 "colorMatrix",
1547 "colorOffset",
1548 BLEND_MODE_UNIFORMS,
1550 int locations[arraysize(uniforms)];
1552 GetProgramUniformLocations(context,
1553 program,
1554 arraysize(uniforms) - UNUSED_BLEND_MODE_UNIFORMS,
1555 uniforms,
1556 locations,
1557 base_uniform_index);
1558 sampler_location_ = locations[0];
1559 mask_sampler_location_ = locations[1];
1560 alpha_location_ = locations[2];
1561 mask_tex_coord_scale_location_ = locations[3];
1562 mask_tex_coord_offset_location_ = locations[4];
1563 color_matrix_location_ = locations[5];
1564 color_offset_location_ = locations[6];
1565 BLEND_MODE_SET_LOCATIONS(locations, 7);
1568 std::string FragmentShaderRGBATexAlphaMaskColorMatrixAA::GetShaderString(
1569 TexCoordPrecision precision,
1570 SamplerType sampler) const {
1571 // clang-format off
1572 return FRAGMENT_SHADER(
1573 // clang-format on
1574 precision mediump float;
1575 uniform sampler2D s_texture;
1576 uniform SamplerType s_mask;
1577 uniform vec2 maskTexCoordScale;
1578 uniform vec2 maskTexCoordOffset;
1579 uniform mat4 colorMatrix;
1580 uniform vec4 colorOffset;
1581 uniform float alpha;
1582 varying TexCoordPrecision vec2 v_texCoord;
1583 varying TexCoordPrecision vec4 edge_dist[2]; // 8 edge distances.
1585 void main() {
1586 vec4 texColor = texture2D(s_texture, v_texCoord);
1587 float nonZeroAlpha = max(texColor.a, 0.00001);
1588 texColor = vec4(texColor.rgb / nonZeroAlpha, nonZeroAlpha);
1589 texColor = colorMatrix * texColor + colorOffset;
1590 texColor.rgb *= texColor.a;
1591 texColor = clamp(texColor, 0.0, 1.0);
1592 TexCoordPrecision vec2 maskTexCoord =
1593 vec2(maskTexCoordOffset.x + v_texCoord.x * maskTexCoordScale.x,
1594 maskTexCoordOffset.y + v_texCoord.y * maskTexCoordScale.y);
1595 vec4 maskColor = TextureLookup(s_mask, maskTexCoord);
1596 vec4 d4 = min(edge_dist[0], edge_dist[1]);
1597 vec2 d2 = min(d4.xz, d4.yw);
1598 float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
1599 gl_FragColor = ApplyBlendMode(texColor * alpha * maskColor.w * aa);
1601 // clang-format off
1602 ); // NOLINT(whitespace/parens)
1603 // clang-format on
1606 FragmentShaderRGBATexAlphaColorMatrixAA::
1607 FragmentShaderRGBATexAlphaColorMatrixAA()
1608 : sampler_location_(-1),
1609 alpha_location_(-1),
1610 color_matrix_location_(-1),
1611 color_offset_location_(-1) {
1614 void FragmentShaderRGBATexAlphaColorMatrixAA::Init(GLES2Interface* context,
1615 unsigned program,
1616 int* base_uniform_index) {
1617 static const char* uniforms[] = {
1618 "s_texture", "alpha", "colorMatrix", "colorOffset", BLEND_MODE_UNIFORMS,
1620 int locations[arraysize(uniforms)];
1622 GetProgramUniformLocations(context,
1623 program,
1624 arraysize(uniforms) - UNUSED_BLEND_MODE_UNIFORMS,
1625 uniforms,
1626 locations,
1627 base_uniform_index);
1628 sampler_location_ = locations[0];
1629 alpha_location_ = locations[1];
1630 color_matrix_location_ = locations[2];
1631 color_offset_location_ = locations[3];
1632 BLEND_MODE_SET_LOCATIONS(locations, 4);
1635 std::string FragmentShaderRGBATexAlphaColorMatrixAA::GetShaderString(
1636 TexCoordPrecision precision,
1637 SamplerType sampler) const {
1638 // clang-format off
1639 return FRAGMENT_SHADER(
1640 // clang-format on
1641 precision mediump float;
1642 uniform SamplerType s_texture;
1643 uniform float alpha;
1644 uniform mat4 colorMatrix;
1645 uniform vec4 colorOffset;
1646 varying TexCoordPrecision vec2 v_texCoord;
1647 varying TexCoordPrecision vec4 edge_dist[2]; // 8 edge distances.
1649 void main() {
1650 vec4 texColor = TextureLookup(s_texture, v_texCoord);
1651 float nonZeroAlpha = max(texColor.a, 0.00001);
1652 texColor = vec4(texColor.rgb / nonZeroAlpha, nonZeroAlpha);
1653 texColor = colorMatrix * texColor + colorOffset;
1654 texColor.rgb *= texColor.a;
1655 texColor = clamp(texColor, 0.0, 1.0);
1656 vec4 d4 = min(edge_dist[0], edge_dist[1]);
1657 vec2 d2 = min(d4.xz, d4.yw);
1658 float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
1659 gl_FragColor = ApplyBlendMode(texColor * alpha * aa);
1661 // clang-format off
1662 ); // NOLINT(whitespace/parens)
1663 // clang-format on
1666 FragmentShaderRGBATexAlphaMaskColorMatrix::
1667 FragmentShaderRGBATexAlphaMaskColorMatrix()
1668 : sampler_location_(-1),
1669 mask_sampler_location_(-1),
1670 alpha_location_(-1),
1671 mask_tex_coord_scale_location_(-1) {
1674 void FragmentShaderRGBATexAlphaMaskColorMatrix::Init(GLES2Interface* context,
1675 unsigned program,
1676 int* base_uniform_index) {
1677 static const char* uniforms[] = {
1678 "s_texture",
1679 "s_mask",
1680 "alpha",
1681 "maskTexCoordScale",
1682 "maskTexCoordOffset",
1683 "colorMatrix",
1684 "colorOffset",
1685 BLEND_MODE_UNIFORMS,
1687 int locations[arraysize(uniforms)];
1689 GetProgramUniformLocations(context,
1690 program,
1691 arraysize(uniforms) - UNUSED_BLEND_MODE_UNIFORMS,
1692 uniforms,
1693 locations,
1694 base_uniform_index);
1695 sampler_location_ = locations[0];
1696 mask_sampler_location_ = locations[1];
1697 alpha_location_ = locations[2];
1698 mask_tex_coord_scale_location_ = locations[3];
1699 mask_tex_coord_offset_location_ = locations[4];
1700 color_matrix_location_ = locations[5];
1701 color_offset_location_ = locations[6];
1702 BLEND_MODE_SET_LOCATIONS(locations, 7);
1705 std::string FragmentShaderRGBATexAlphaMaskColorMatrix::GetShaderString(
1706 TexCoordPrecision precision,
1707 SamplerType sampler) const {
1708 // clang-format off
1709 return FRAGMENT_SHADER(
1710 // clang-format on
1711 precision mediump float;
1712 varying TexCoordPrecision vec2 v_texCoord;
1713 uniform sampler2D s_texture;
1714 uniform SamplerType s_mask;
1715 uniform vec2 maskTexCoordScale;
1716 uniform vec2 maskTexCoordOffset;
1717 uniform mat4 colorMatrix;
1718 uniform vec4 colorOffset;
1719 uniform float alpha;
1720 void main() {
1721 vec4 texColor = texture2D(s_texture, v_texCoord);
1722 float nonZeroAlpha = max(texColor.a, 0.00001);
1723 texColor = vec4(texColor.rgb / nonZeroAlpha, nonZeroAlpha);
1724 texColor = colorMatrix * texColor + colorOffset;
1725 texColor.rgb *= texColor.a;
1726 texColor = clamp(texColor, 0.0, 1.0);
1727 TexCoordPrecision vec2 maskTexCoord =
1728 vec2(maskTexCoordOffset.x + v_texCoord.x * maskTexCoordScale.x,
1729 maskTexCoordOffset.y + v_texCoord.y * maskTexCoordScale.y);
1730 vec4 maskColor = TextureLookup(s_mask, maskTexCoord);
1731 gl_FragColor = ApplyBlendMode(texColor * alpha * maskColor.w);
1733 // clang-format off
1734 ); // NOLINT(whitespace/parens)
1735 // clang-format on
1738 FragmentShaderYUVVideo::FragmentShaderYUVVideo()
1739 : y_texture_location_(-1),
1740 u_texture_location_(-1),
1741 v_texture_location_(-1),
1742 alpha_location_(-1),
1743 yuv_matrix_location_(-1),
1744 yuv_adj_location_(-1) {
1747 void FragmentShaderYUVVideo::Init(GLES2Interface* context,
1748 unsigned program,
1749 int* base_uniform_index) {
1750 static const char* uniforms[] = {
1751 "y_texture", "u_texture", "v_texture", "alpha", "yuv_matrix", "yuv_adj",
1753 int locations[arraysize(uniforms)];
1755 GetProgramUniformLocations(context,
1756 program,
1757 arraysize(uniforms),
1758 uniforms,
1759 locations,
1760 base_uniform_index);
1761 y_texture_location_ = locations[0];
1762 u_texture_location_ = locations[1];
1763 v_texture_location_ = locations[2];
1764 alpha_location_ = locations[3];
1765 yuv_matrix_location_ = locations[4];
1766 yuv_adj_location_ = locations[5];
1769 std::string FragmentShaderYUVVideo::GetShaderString(TexCoordPrecision precision,
1770 SamplerType sampler) const {
1771 // clang-format off
1772 return FRAGMENT_SHADER(
1773 // clang-format on
1774 precision mediump float;
1775 precision mediump int;
1776 varying TexCoordPrecision vec2 v_texCoord;
1777 uniform SamplerType y_texture;
1778 uniform SamplerType u_texture;
1779 uniform SamplerType v_texture;
1780 uniform float alpha;
1781 uniform vec3 yuv_adj;
1782 uniform mat3 yuv_matrix;
1783 void main() {
1784 float y_raw = TextureLookup(y_texture, v_texCoord).x;
1785 float u_unsigned = TextureLookup(u_texture, v_texCoord).x;
1786 float v_unsigned = TextureLookup(v_texture, v_texCoord).x;
1787 vec3 yuv = vec3(y_raw, u_unsigned, v_unsigned) + yuv_adj;
1788 vec3 rgb = yuv_matrix * yuv;
1789 gl_FragColor = vec4(rgb, 1.0) * alpha;
1791 // clang-format off
1792 ); // NOLINT(whitespace/parens)
1793 // clang-format on
1796 FragmentShaderYUVAVideo::FragmentShaderYUVAVideo()
1797 : y_texture_location_(-1),
1798 u_texture_location_(-1),
1799 v_texture_location_(-1),
1800 a_texture_location_(-1),
1801 alpha_location_(-1),
1802 yuv_matrix_location_(-1),
1803 yuv_adj_location_(-1) {
1806 void FragmentShaderYUVAVideo::Init(GLES2Interface* context,
1807 unsigned program,
1808 int* base_uniform_index) {
1809 static const char* uniforms[] = {
1810 "y_texture",
1811 "u_texture",
1812 "v_texture",
1813 "a_texture",
1814 "alpha",
1815 "cc_matrix",
1816 "yuv_adj",
1818 int locations[arraysize(uniforms)];
1820 GetProgramUniformLocations(context,
1821 program,
1822 arraysize(uniforms),
1823 uniforms,
1824 locations,
1825 base_uniform_index);
1826 y_texture_location_ = locations[0];
1827 u_texture_location_ = locations[1];
1828 v_texture_location_ = locations[2];
1829 a_texture_location_ = locations[3];
1830 alpha_location_ = locations[4];
1831 yuv_matrix_location_ = locations[5];
1832 yuv_adj_location_ = locations[6];
1835 std::string FragmentShaderYUVAVideo::GetShaderString(
1836 TexCoordPrecision precision,
1837 SamplerType sampler) const {
1838 // clang-format off
1839 return FRAGMENT_SHADER(
1840 // clang-format on
1841 precision mediump float;
1842 precision mediump int;
1843 varying TexCoordPrecision vec2 v_texCoord;
1844 uniform SamplerType y_texture;
1845 uniform SamplerType u_texture;
1846 uniform SamplerType v_texture;
1847 uniform SamplerType a_texture;
1848 uniform float alpha;
1849 uniform vec3 yuv_adj;
1850 uniform mat3 yuv_matrix;
1851 void main() {
1852 float y_raw = TextureLookup(y_texture, v_texCoord).x;
1853 float u_unsigned = TextureLookup(u_texture, v_texCoord).x;
1854 float v_unsigned = TextureLookup(v_texture, v_texCoord).x;
1855 float a_raw = TextureLookup(a_texture, v_texCoord).x;
1856 vec3 yuv = vec3(y_raw, u_unsigned, v_unsigned) + yuv_adj;
1857 vec3 rgb = yuv_matrix * yuv;
1858 gl_FragColor = vec4(rgb, 1.0) * (alpha * a_raw);
1860 // clang-format off
1861 ); // NOLINT(whitespace/parens)
1862 // clang-format on
1865 FragmentShaderColor::FragmentShaderColor() : color_location_(-1) {
1868 void FragmentShaderColor::Init(GLES2Interface* context,
1869 unsigned program,
1870 int* base_uniform_index) {
1871 static const char* uniforms[] = {
1872 "color",
1874 int locations[arraysize(uniforms)];
1876 GetProgramUniformLocations(context,
1877 program,
1878 arraysize(uniforms),
1879 uniforms,
1880 locations,
1881 base_uniform_index);
1882 color_location_ = locations[0];
1885 std::string FragmentShaderColor::GetShaderString(TexCoordPrecision precision,
1886 SamplerType sampler) const {
1887 // clang-format off
1888 return FRAGMENT_SHADER(
1889 // clang-format on
1890 precision mediump float;
1891 uniform vec4 color;
1892 void main() { gl_FragColor = color; }
1893 // clang-format off
1894 ); // NOLINT(whitespace/parens)
1895 // clang-format on
1898 FragmentShaderColorAA::FragmentShaderColorAA() : color_location_(-1) {
1901 void FragmentShaderColorAA::Init(GLES2Interface* context,
1902 unsigned program,
1903 int* base_uniform_index) {
1904 static const char* uniforms[] = {
1905 "color",
1907 int locations[arraysize(uniforms)];
1909 GetProgramUniformLocations(context,
1910 program,
1911 arraysize(uniforms),
1912 uniforms,
1913 locations,
1914 base_uniform_index);
1915 color_location_ = locations[0];
1918 std::string FragmentShaderColorAA::GetShaderString(TexCoordPrecision precision,
1919 SamplerType sampler) const {
1920 // clang-format off
1921 return FRAGMENT_SHADER(
1922 // clang-format on
1923 precision mediump float;
1924 uniform vec4 color;
1925 varying vec4 edge_dist[2]; // 8 edge distances.
1927 void main() {
1928 vec4 d4 = min(edge_dist[0], edge_dist[1]);
1929 vec2 d2 = min(d4.xz, d4.yw);
1930 float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
1931 gl_FragColor = color * aa;
1933 // clang-format off
1934 ); // NOLINT(whitespace/parens)
1935 // clang-format on
1938 FragmentShaderCheckerboard::FragmentShaderCheckerboard()
1939 : alpha_location_(-1),
1940 tex_transform_location_(-1),
1941 frequency_location_(-1) {
1944 void FragmentShaderCheckerboard::Init(GLES2Interface* context,
1945 unsigned program,
1946 int* base_uniform_index) {
1947 static const char* uniforms[] = {
1948 "alpha", "texTransform", "frequency", "color",
1950 int locations[arraysize(uniforms)];
1952 GetProgramUniformLocations(context,
1953 program,
1954 arraysize(uniforms),
1955 uniforms,
1956 locations,
1957 base_uniform_index);
1958 alpha_location_ = locations[0];
1959 tex_transform_location_ = locations[1];
1960 frequency_location_ = locations[2];
1961 color_location_ = locations[3];
1964 std::string FragmentShaderCheckerboard::GetShaderString(
1965 TexCoordPrecision precision,
1966 SamplerType sampler) const {
1967 // Shader based on Example 13-17 of "OpenGL ES 2.0 Programming Guide"
1968 // by Munshi, Ginsburg, Shreiner.
1969 // clang-format off
1970 return FRAGMENT_SHADER(
1971 // clang-format on
1972 precision mediump float;
1973 precision mediump int;
1974 varying vec2 v_texCoord;
1975 uniform float alpha;
1976 uniform float frequency;
1977 uniform vec4 texTransform;
1978 uniform vec4 color;
1979 void main() {
1980 vec4 color1 = vec4(1.0, 1.0, 1.0, 1.0);
1981 vec4 color2 = color;
1982 vec2 texCoord =
1983 clamp(v_texCoord, 0.0, 1.0) * texTransform.zw + texTransform.xy;
1984 vec2 coord = mod(floor(texCoord * frequency * 2.0), 2.0);
1985 float picker = abs(coord.x - coord.y); // NOLINT
1986 gl_FragColor = mix(color1, color2, picker) * alpha;
1988 // clang-format off
1989 ); // NOLINT(whitespace/parens)
1990 // clang-format on
1993 } // namespace cc