We started redesigning GpuMemoryBuffer interface to handle multiple buffers [0].
[chromium-blink-merge.git] / gpu / tools / compositor_model_bench / shaders.cc
blob5559e73a558d526707ef18b7298739b8fbdb43c3
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"
7 #include <algorithm>
9 #include "gpu/tools/compositor_model_bench/render_model_utils.h"
10 #include "gpu/tools/compositor_model_bench/render_tree.h"
12 using std::min;
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,
34 0.f, -.391f, 2.018f,
35 1.596f, -.813f, 0.f
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 ///////////////////////////////////////////////////////////////////////////////
43 // L R B T N F
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,
49 0.0, 0.0, -1.0, 0.0,
50 -1.0, 1.0, 0.0, 1.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) {
57 p[ADDR(i, j)] = 0;
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)
67 out[i] = in[i] * sx;
68 for (int j = 4; j < 8; ++j)
69 out[j] = in[j] * sy;
70 for (int k = 8; k < 12; ++k)
71 out[k] = in[k] * sz;
72 for (int l = 12; l < 16; ++l)
73 out[l] = in[l];
76 static void TranslateInPlace(float* m, float tx, float ty, float tz) {
77 m[12] += tx;
78 m[13] += ty;
79 m[14] += 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) {
101 switch (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";
114 default:
115 return "(unknown shader)";
119 #define SHADER0(Src) #Src
120 #define SHADER(Src) SHADER0(Src)
122 const char* GetShaderSource(ShaderID shader) {
123 switch (shader) {
124 case VERTEX_SHADER_POS_TEX_YUV_STRETCH:
125 return SHADER(
126 #ifdef GL_ES
127 precision mediump float;
128 #endif
129 attribute vec4 a_position;
130 attribute vec2 a_texCoord;
131 uniform mat4 matrix;
132 varying vec2 y_texCoord;
133 varying vec2 uv_texCoord;
134 uniform float y_widthScaleFactor;
135 uniform float uv_widthScaleFactor;
136 void main() {
137 gl_Position = matrix * a_position;
138 y_texCoord = vec2(y_widthScaleFactor * a_texCoord.x,
139 a_texCoord.y);
140 uv_texCoord = vec2(uv_widthScaleFactor * a_texCoord.x,
141 a_texCoord.y);
143 break;
144 case VERTEX_SHADER_POS_TEX:
145 return SHADER(
146 attribute vec4 a_position;
147 attribute vec2 a_texCoord;
148 uniform mat4 matrix;
149 varying vec2 v_texCoord;
150 void main() {
151 gl_Position = matrix * a_position;
152 v_texCoord = a_texCoord;
154 break;
155 case VERTEX_SHADER_POS_TEX_TRANSFORM:
156 return SHADER(
157 attribute vec4 a_position;
158 attribute vec2 a_texCoord;
159 uniform mat4 matrix;
160 uniform vec4 texTransform;
161 varying vec2 v_texCoord;
162 void main() {
163 gl_Position = matrix * a_position;
164 v_texCoord = a_texCoord*texTransform.zw + texTransform.xy;
166 break;
167 case FRAGMENT_SHADER_YUV_VIDEO:
168 return SHADER(
169 #ifdef GL_ES
170 precision mediump float;
171 precision mediump int;
172 #endif
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;
178 uniform float alpha;
179 uniform vec3 yuv_adj;
180 uniform mat3 cc_matrix;
181 void main() {
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;
189 break;
190 case FRAGMENT_SHADER_RGBA_TEX_FLIP_ALPHA:
191 return SHADER(
192 #ifdef GL_ES
193 precision mediump float;
194 #endif
195 varying vec2 v_texCoord;
196 uniform sampler2D s_texture;
197 uniform float alpha;
198 void main() {
199 vec4 texColor = texture2D(s_texture,
200 vec2(v_texCoord.x, 1.0 - v_texCoord.y));
201 gl_FragColor = vec4(texColor.x,
202 texColor.y,
203 texColor.z,
204 texColor.w) * alpha;
206 break;
207 case FRAGMENT_SHADER_RGBA_TEX_ALPHA:
208 return SHADER(
209 #ifdef GL_ES
210 precision mediump float;
211 #endif
212 varying vec2 v_texCoord;
213 uniform sampler2D s_texture;
214 uniform float alpha;
215 void main() {
216 vec4 texColor = texture2D(s_texture, v_texCoord);
217 gl_FragColor = texColor * alpha;
219 break;
220 default:
221 printf("Shader source requested for unknown shader\n");
222 return "";
226 int GetProgramIdx(ShaderID v, ShaderID f) {
227 return v * SHADER_ID_MAX + f;
230 static void ReportAnyShaderCompilationErrors(GLuint shader, ShaderID id) {
231 GLint status;
232 glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
233 if (status)
234 return;
235 // Get the length of the log string
236 GLsizei length;
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],
260 kPositionLocation,
261 "a_position");
262 glBindAttribLocationARB(g_program_objects[program_index],
263 kTexCoordLocation,
264 "a_texCoord");
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);
304 // Bind Y tex.
305 glActiveTexture(GL_TEXTURE0);
306 glBindTexture(GL_TEXTURE_2D, n->texture(0)->texID);
307 int yTexLoc = glGetUniformLocationARB(program, "y_texture");
308 glUniform1iARB(yTexLoc, 0);
309 // Bind U tex.
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);
314 // Bind V tex.
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);
319 // Set YUV offset.
320 int yuvAdjLoc = glGetUniformLocationARB(program, "yuv_adj");
321 glUniform3fARB(yuvAdjLoc, -0.0625f, -0.5f, -0.5f);
322 // Set YUV matrix.
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,
333 n->transform());
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() {
346 g_active_index = -1;
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;
356 void InitBuffers() {
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,
368 sizeof(vertices),
369 vertices,
370 GL_STATIC_DRAW);
371 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_quad_elements_vbo);
372 glBufferData(GL_ELEMENT_ARRAY_BUFFER,
373 sizeof(indices),
374 indices,
375 GL_STATIC_DRAW);
378 void BeginFrame() {
379 glBindBuffer(GL_ARRAY_BUFFER, g_quad_vertices_vbo);
380 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_quad_elements_vbo);
381 unsigned offset = 0;
382 glVertexAttribPointer(kPositionLocation,
384 GL_FLOAT,
385 false,
386 5 * sizeof(float),
387 reinterpret_cast<void*>(offset));
388 offset += 3 * sizeof(float);
389 glVertexAttribPointer(kTexCoordLocation,
391 GL_FLOAT,
392 false,
393 5 * sizeof(float),
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],
405 "matrix");
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)
415 return;
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);