1 // Copyright (c) 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 "gpu/tools/compositor_model_bench/shaders.h"
9 #include "gpu/tools/compositor_model_bench/render_model_utils.h"
10 #include "gpu/tools/compositor_model_bench/render_tree.h"
14 static const int kPositionLocation
= 0;
15 static const int kTexCoordLocation
= 1;
17 static unsigned g_quad_vertices_vbo
;
18 static unsigned g_quad_elements_vbo
;
20 // Store a pointer to the transform matrix of the active layer (the complete
21 // transform isn't build until we draw the quad; then we can apply
22 // translation/scaling/projection)
23 static float* g_current_layer_transform
;
25 // In addition to the transform, store other useful information about tiled
26 // layers that we'll need to render each tile's quad
27 static float g_current_tile_layer_width
;
28 static float g_current_tile_layer_height
;
29 static float g_current_tile_width
;
30 static float g_current_tile_height
;
32 static const float yuv2RGB
[9] = {
33 1.164f
, 1.164f
, 1.164f
,
38 // Store shader programs in a sparse array so that they can be addressed easily.
39 static int g_program_objects
[SHADER_ID_MAX
*SHADER_ID_MAX
];
40 static int g_active_index
= -1;
42 ///////////////////////////////////////////////////////////////////////////////
44 // glOrtho(0, WINDOW_WIDTH, WINDOW_HEIGHT, 0, -1, 1); // column major
46 static float g_projection_matrix
[] = {
47 2.0 / WINDOW_WIDTH
, 0.0, 0.0, 0.0,
48 0.0, 2.0 / -WINDOW_HEIGHT
, 0.0, 0.0,
53 #define ADDR(i, j) (i*4 + j) /* column major */
54 static void Project(const float* v
, float* p
) {
55 for (int i
= 0; i
< 4; ++i
) {
56 for (int j
= 0; j
< 4; ++j
) {
58 for (int k
= 0; k
< 4; ++k
) {
59 p
[ADDR(i
, j
)] += g_projection_matrix
[ADDR(k
, i
)] * v
[ADDR(j
, k
)];
65 static void Scale(const float* in
, float* out
, float sx
, float sy
, float sz
) {
66 for (int i
= 0; i
< 4; ++i
)
68 for (int j
= 4; j
< 8; ++j
)
70 for (int k
= 8; k
< 12; ++k
)
72 for (int l
= 12; l
< 16; ++l
)
76 static void TranslateInPlace(float* m
, float tx
, float ty
, float tz
) {
82 ///////////////////////////////////////////////////////////////////////////////
84 ShaderID
ShaderIDFromString(std::string name
) {
85 if (name
== "VertexShaderPosTexYUVStretch")
86 return VERTEX_SHADER_POS_TEX_YUV_STRETCH
;
87 if (name
== "VertexShaderPosTex")
88 return VERTEX_SHADER_POS_TEX
;
89 if (name
== "VertexShaderPosTexTransform")
90 return VERTEX_SHADER_POS_TEX_TRANSFORM
;
91 if (name
== "FragmentShaderYUVVideo")
92 return FRAGMENT_SHADER_YUV_VIDEO
;
93 if (name
== "FragmentShaderRGBATexFlipAlpha")
94 return FRAGMENT_SHADER_RGBA_TEX_FLIP_ALPHA
;
95 if (name
== "FragmentShaderRGBATexAlpha")
96 return FRAGMENT_SHADER_RGBA_TEX_ALPHA
;
97 return SHADER_UNRECOGNIZED
;
100 std::string
ShaderNameFromID(ShaderID id
) {
102 case VERTEX_SHADER_POS_TEX_YUV_STRETCH
:
103 return "VertexShaderPosTexYUVStretch";
104 case VERTEX_SHADER_POS_TEX
:
105 return "VertexShaderPosTex";
106 case VERTEX_SHADER_POS_TEX_TRANSFORM
:
107 return "VertexShaderPosTexTransform";
108 case FRAGMENT_SHADER_YUV_VIDEO
:
109 return "FragmentShaderYUVVideo";
110 case FRAGMENT_SHADER_RGBA_TEX_FLIP_ALPHA
:
111 return "FragmentShaderRGBATexFlipAlpha";
112 case FRAGMENT_SHADER_RGBA_TEX_ALPHA
:
113 return "FragmentShaderRGBATexAlpha";
115 return "(unknown shader)";
119 #define SHADER0(Src) #Src
120 #define SHADER(Src) SHADER0(Src)
122 const char* GetShaderSource(ShaderID shader
) {
124 case VERTEX_SHADER_POS_TEX_YUV_STRETCH
:
127 precision mediump
float;
129 attribute vec4 a_position
;
130 attribute vec2 a_texCoord
;
132 varying vec2 y_texCoord
;
133 varying vec2 uv_texCoord
;
134 uniform
float y_widthScaleFactor
;
135 uniform
float uv_widthScaleFactor
;
137 gl_Position
= matrix
* a_position
;
138 y_texCoord
= vec2(y_widthScaleFactor
* a_texCoord
.x
,
140 uv_texCoord
= vec2(uv_widthScaleFactor
* a_texCoord
.x
,
144 case VERTEX_SHADER_POS_TEX
:
146 attribute vec4 a_position
;
147 attribute vec2 a_texCoord
;
149 varying vec2 v_texCoord
;
151 gl_Position
= matrix
* a_position
;
152 v_texCoord
= a_texCoord
;
155 case VERTEX_SHADER_POS_TEX_TRANSFORM
:
157 attribute vec4 a_position
;
158 attribute vec2 a_texCoord
;
160 uniform vec4 texTransform
;
161 varying vec2 v_texCoord
;
163 gl_Position
= matrix
* a_position
;
164 v_texCoord
= a_texCoord
*texTransform
.zw
+ texTransform
.xy
;
167 case FRAGMENT_SHADER_YUV_VIDEO
:
170 precision mediump
float;
171 precision mediump
int;
173 varying vec2 y_texCoord
;
174 varying vec2 uv_texCoord
;
175 uniform sampler2D y_texture
;
176 uniform sampler2D u_texture
;
177 uniform sampler2D v_texture
;
179 uniform vec3 yuv_adj
;
180 uniform mat3 cc_matrix
;
182 float y_raw
= texture2D(y_texture
, y_texCoord
).x
;
183 float u_unsigned
= texture2D(u_texture
, uv_texCoord
).x
;
184 float v_unsigned
= texture2D(v_texture
, uv_texCoord
).x
;
185 vec3 yuv
= vec3(y_raw
, u_unsigned
, v_unsigned
) + yuv_adj
;
186 vec3 rgb
= cc_matrix
* yuv
;
187 gl_FragColor
= vec4(rgb
, 1.0) * alpha
;
190 case FRAGMENT_SHADER_RGBA_TEX_FLIP_ALPHA
:
193 precision mediump
float;
195 varying vec2 v_texCoord
;
196 uniform sampler2D s_texture
;
199 vec4 texColor
= texture2D(s_texture
,
200 vec2(v_texCoord
.x
, 1.0 - v_texCoord
.y
));
201 gl_FragColor
= vec4(texColor
.x
,
207 case FRAGMENT_SHADER_RGBA_TEX_ALPHA
:
210 precision mediump
float;
212 varying vec2 v_texCoord
;
213 uniform sampler2D s_texture
;
216 vec4 texColor
= texture2D(s_texture
, v_texCoord
);
217 gl_FragColor
= texColor
* alpha
;
221 printf("Shader source requested for unknown shader\n");
226 int GetProgramIdx(ShaderID v
, ShaderID f
) {
227 return v
* SHADER_ID_MAX
+ f
;
230 static void ReportAnyShaderCompilationErrors(GLuint shader
, ShaderID id
) {
232 glGetShaderiv(shader
, GL_COMPILE_STATUS
, &status
);
235 // Get the length of the log string
237 glGetShaderiv(shader
, GL_INFO_LOG_LENGTH
, &length
);
238 scoped_ptr
<GLchar
[]> log(new GLchar
[length
+1]);
239 glGetShaderInfoLog(shader
, length
, NULL
, log
.get());
240 LOG(ERROR
) << log
.get() << " in shader " << ShaderNameFromID(id
);
243 static int ActivateShader(ShaderID v
, ShaderID f
, float* layer_transform
) {
244 int program_index
= GetProgramIdx(v
, f
);
245 if (!g_program_objects
[program_index
]) {
246 g_program_objects
[program_index
] = glCreateProgramObjectARB();
247 GLenum vs
= glCreateShaderObjectARB(GL_VERTEX_SHADER
);
248 GLenum fs
= glCreateShaderObjectARB(GL_FRAGMENT_SHADER
);
249 const char* vs_source
= GetShaderSource(v
);
250 const char* fs_source
= GetShaderSource(f
);
251 glShaderSourceARB(vs
, 1, &vs_source
, 0);
252 glShaderSourceARB(fs
, 1, &fs_source
, 0);
253 glCompileShaderARB(vs
);
254 ReportAnyShaderCompilationErrors(vs
, v
);
255 glCompileShaderARB(fs
);
256 ReportAnyShaderCompilationErrors(fs
, f
);
257 glAttachObjectARB(g_program_objects
[program_index
], vs
);
258 glAttachObjectARB(g_program_objects
[program_index
], fs
);
259 glBindAttribLocationARB(g_program_objects
[program_index
],
262 glBindAttribLocationARB(g_program_objects
[program_index
],
265 glLinkProgramARB(g_program_objects
[program_index
]);
267 if (g_active_index
!= program_index
)
268 glUseProgramObjectARB(g_program_objects
[program_index
]);
269 g_active_index
= program_index
;
271 g_current_layer_transform
= layer_transform
;
273 return g_program_objects
[program_index
];
276 void ConfigAndActivateShaderForNode(CCNode
* n
) {
277 ShaderID vs
= n
->vertex_shader();
278 ShaderID fs
= n
->fragment_shader();
279 float* transform
= n
->transform();
280 int program
= ActivateShader(vs
, fs
, transform
);
281 if (vs
== VERTEX_SHADER_POS_TEX_YUV_STRETCH
) {
282 GLint y_scale
= glGetUniformLocationARB(program
, "y_widthScaleFactor");
283 GLint uv_scale
= glGetUniformLocationARB(program
, "uv_widthScaleFactor");
284 glUniform1fARB(y_scale
, 1.0);
285 glUniform1fARB(uv_scale
, 1.0);
287 if (vs
== VERTEX_SHADER_POS_TEX_TRANSFORM
) {
288 GLint texTrans
= glGetUniformLocationARB(program
, "texTransform");
289 glUniform4fARB(texTrans
, 0.0, 0.0, 0.0, 0.0);
291 if (fs
== FRAGMENT_SHADER_RGBA_TEX_FLIP_ALPHA
) {
292 DCHECK_EQ(n
->num_textures(), 1u);
293 DCHECK_NE(n
->texture(0)->texID
, -1);
294 glActiveTexture(GL_TEXTURE0
);
295 glBindTexture(GL_TEXTURE_2D
, n
->texture(0)->texID
);
296 int sTexLoc
= glGetUniformLocationARB(program
, "s_texture");
297 glUniform1iARB(sTexLoc
, 0);
299 if (fs
== FRAGMENT_SHADER_YUV_VIDEO
) {
300 DCHECK_EQ(n
->num_textures(), 3u);
301 DCHECK_NE(n
->texture(0)->texID
, -1);
302 DCHECK_NE(n
->texture(1)->texID
, -1);
303 DCHECK_NE(n
->texture(2)->texID
, -1);
305 glActiveTexture(GL_TEXTURE0
);
306 glBindTexture(GL_TEXTURE_2D
, n
->texture(0)->texID
);
307 int yTexLoc
= glGetUniformLocationARB(program
, "y_texture");
308 glUniform1iARB(yTexLoc
, 0);
310 glActiveTexture(GL_TEXTURE0
+ 1);
311 glBindTexture(GL_TEXTURE_2D
, n
->texture(1)->texID
);
312 int uTexLoc
= glGetUniformLocationARB(program
, "u_texture");
313 glUniform1iARB(uTexLoc
, 1);
315 glActiveTexture(GL_TEXTURE0
+ 2);
316 glBindTexture(GL_TEXTURE_2D
, n
->texture(2)->texID
);
317 int vTexLoc
= glGetUniformLocationARB(program
, "v_texture");
318 glUniform1iARB(vTexLoc
, 2);
320 int yuvAdjLoc
= glGetUniformLocationARB(program
, "yuv_adj");
321 glUniform3fARB(yuvAdjLoc
, -0.0625f
, -0.5f
, -0.5f
);
323 int ccMatLoc
= glGetUniformLocationARB(program
, "cc_matrix");
324 glUniformMatrix3fvARB(ccMatLoc
, 1, false, yuv2RGB
);
326 GLint alpha
= glGetUniformLocationARB(program
, "alpha");
327 glUniform1fARB(alpha
, 0.9);
330 void ConfigAndActivateShaderForTiling(ContentLayerNode
* n
) {
331 int program
= ActivateShader(VERTEX_SHADER_POS_TEX_TRANSFORM
,
332 FRAGMENT_SHADER_RGBA_TEX_ALPHA
,
334 GLint texTrans
= glGetUniformLocationARB(program
, "texTransform");
335 glUniform4fARB(texTrans
, 0.0, 0.0, 1.0, 1.0);
336 GLint alpha
= glGetUniformLocationARB(program
, "alpha");
337 glUniform1fARB(alpha
, 0.9);
339 g_current_tile_layer_width
= n
->width();
340 g_current_tile_layer_height
= n
->height();
341 g_current_tile_width
= n
->tile_width();
342 g_current_tile_height
= n
->tile_height();
345 void DeleteShaders() {
347 glUseProgramObjectARB(0);
348 for (int i
= 0; i
< SHADER_ID_MAX
*SHADER_ID_MAX
; ++i
) {
349 if (g_program_objects
[i
]) {
350 glDeleteObjectARB(g_program_objects
[i
]);
352 g_program_objects
[i
] = 0;
357 // Vertex positions and texture coordinates for the 4 corners of a 1x1 quad.
358 float vertices
[] = { -0.5f
, 0.5f
, 0.0f
, 0.0f
, 1.0f
,
359 -0.5f
, -0.5f
, 0.0f
, 0.0f
, 0.0f
,
360 0.5f
, -0.5f
, 0.0f
, 1.0f
, 0.0f
,
361 0.5f
, 0.5f
, 0.0f
, 1.0f
, 1.0f
};
362 uint16_t indices
[] = { 0, 1, 2, 0, 2, 3};
364 glGenBuffers(1, &g_quad_vertices_vbo
);
365 glGenBuffers(1, &g_quad_elements_vbo
);
366 glBindBuffer(GL_ARRAY_BUFFER
, g_quad_vertices_vbo
);
367 glBufferData(GL_ARRAY_BUFFER
,
371 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, g_quad_elements_vbo
);
372 glBufferData(GL_ELEMENT_ARRAY_BUFFER
,
379 glBindBuffer(GL_ARRAY_BUFFER
, g_quad_vertices_vbo
);
380 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, g_quad_elements_vbo
);
382 glVertexAttribPointer(kPositionLocation
,
387 reinterpret_cast<void*>(offset
));
388 offset
+= 3 * sizeof(float);
389 glVertexAttribPointer(kTexCoordLocation
,
394 reinterpret_cast<void*>(offset
));
395 glEnableVertexAttribArray(kPositionLocation
);
396 glEnableVertexAttribArray(kTexCoordLocation
);
399 void DrawQuad(float width
, float height
) {
400 float mv_transform
[16];
401 float proj_transform
[16];
402 Scale(g_current_layer_transform
, mv_transform
, width
, height
, 1.0);
403 Project(mv_transform
, proj_transform
);
404 GLint mat
= glGetUniformLocationARB(g_program_objects
[g_active_index
],
406 glUniformMatrix4fvARB(mat
, 1, GL_TRUE
, proj_transform
);
408 glDrawElements(GL_TRIANGLES
, 6, GL_UNSIGNED_SHORT
, 0);
411 void DrawTileQuad(GLuint texID
, int x
, int y
) {
412 float left
= g_current_tile_width
*x
;
413 float top
= g_current_tile_height
*y
;
414 if (left
> g_current_tile_layer_width
|| top
> g_current_tile_layer_height
)
417 float right
= min(left
+g_current_tile_width
, g_current_tile_layer_width
);
418 float bottom
= min(top
+g_current_tile_height
, g_current_tile_layer_height
);
419 float width
= right
-left
;
420 float height
= bottom
-top
;
422 int prog
= g_program_objects
[g_active_index
];
424 // Scale the texture if the full tile rectangle doesn't get drawn.
425 float u_scale
= width
/ g_current_tile_width
;
426 float v_scale
= height
/ g_current_tile_height
;
427 GLint texTrans
= glGetUniformLocationARB(prog
, "texTransform");
428 glUniform4fARB(texTrans
, 0.0, 0.0, u_scale
, v_scale
);
430 glActiveTexture(GL_TEXTURE0
);
431 glBindTexture(GL_TEXTURE_2D
, texID
);
432 int texLoc
= glGetUniformLocationARB(prog
, "s_texture");
433 glUniform1iARB(texLoc
, 0);
435 float mv_transform
[16];
436 float proj_transform
[16];
437 Scale(g_current_layer_transform
, mv_transform
, width
, height
, 1.0);
439 // We have to position the tile by its center.
440 float center_x
= (left
+right
)/2 - g_current_tile_layer_width
/2;
441 float center_y
= (top
+bottom
)/2 - g_current_tile_layer_height
/2;
442 TranslateInPlace(mv_transform
, center_x
, center_y
, 0.0);
444 Project(mv_transform
, proj_transform
);
445 GLint mat
= glGetUniformLocationARB(prog
, "matrix");
446 glUniformMatrix4fvARB(mat
, 1, GL_TRUE
, proj_transform
);
448 glDrawElements(GL_TRIANGLES
, 6, GL_UNSIGNED_SHORT
, 0);