Chromium Code Reviews| Index: gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc |
| diff --git a/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc b/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc |
| index 5ce4a223fb3d185563e6d8e1948f5b7b4916713b..258f63ef82da36b71abca2f06314ca849807a1a6 100644 |
| --- a/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc |
| +++ b/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc |
| @@ -10,19 +10,19 @@ |
| #include "gpu/command_buffer/service/gl_utils.h" |
| #include "gpu/command_buffer/service/gles2_cmd_decoder.h" |
| -#define SHADER0(src) \ |
| - "#ifdef GL_ES\n"\ |
| - "precision mediump float;\n"\ |
| - "#endif\n"\ |
| - #src |
| -#define SHADER(src) { false, SHADER0(src), } |
| -#define SHADER_EXTERNAL_OES0(src) \ |
| - "#extension GL_OES_EGL_image_external : require\n"\ |
| - "#ifdef GL_ES\n"\ |
| - "precision mediump float;\n"\ |
| - "#endif\n"\ |
| - #src |
| -#define SHADER_EXTERNAL_OES(src) { true, SHADER_EXTERNAL_OES0(src), } |
| +#define SHADER(src) \ |
| + "#ifdef GL_ES\n" \ |
| + "precision mediump float;\n" \ |
| + "#endif\n" #src |
| +#define SHADER_2D(src) \ |
| + "#define SamplerType sampler2D\n" \ |
| + "#define TextureLookup texture2D\n" SHADER(src) |
| +#define SHADER_EXTERNAL_OES(src) \ |
| + "#extension GL_OES_EGL_image_external : require\n" \ |
| + "#define SamplerType samplerExternalOES\n" \ |
| + "#define TextureLookup texture2D\n" SHADER(src) |
| +#define SHADERS(src) \ |
| + { SHADER_2D(src), SHADER_EXTERNAL_OES(src) } |
| namespace { |
| @@ -31,27 +31,23 @@ const GLfloat kQuadVertices[] = { -1.0f, -1.0f, 0.0f, 1.0f, |
| 1.0f, 1.0f, 0.0f, 1.0f, |
| -1.0f, 1.0f, 0.0f, 1.0f }; |
|
piman
2014/04/25 03:30:40
This should be 2 components per vertex instead of
reveman
2014/04/25 20:27:10
I'll fix this in a follow up.
|
| -enum ProgramId { |
| - PROGRAM_COPY_TEXTURE, |
| - PROGRAM_COPY_TEXTURE_FLIP_Y, |
| - PROGRAM_COPY_TEXTURE_PREMULTIPLY_ALPHA, |
| - PROGRAM_COPY_TEXTURE_UNPREMULTIPLY_ALPHA, |
| - PROGRAM_COPY_TEXTURE_PREMULTIPLY_ALPHA_FLIPY, |
| - PROGRAM_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_FLIPY, |
| - PROGRAM_COPY_TEXTURE_OES, |
| - PROGRAM_COPY_TEXTURE_OES_FLIP_Y, |
| - PROGRAM_COPY_TEXTURE_OES_PREMULTIPLY_ALPHA, |
| - PROGRAM_COPY_TEXTURE_OES_UNPREMULTIPLY_ALPHA, |
| - PROGRAM_COPY_TEXTURE_OES_PREMULTIPLY_ALPHA_FLIPY, |
| - PROGRAM_COPY_TEXTURE_OES_UNPREMULTIPLY_ALPHA_FLIPY, |
| +enum ShaderId { |
| + SHADER_COPY_TEXTURE, |
| + SHADER_COPY_TEXTURE_FLIP_Y, |
|
piman
2014/04/25 03:30:40
nit: it'd be nice to be consistent between FLIP_Y
reveman
2014/04/25 20:27:10
Done.
|
| + SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA, |
| + SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA, |
| + SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_FLIPY, |
| + SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_FLIPY, |
| + NUM_SHADERS, |
| }; |
| -struct ShaderInfo { |
| - bool needs_egl_image_external; |
| - const char* source; |
| +enum SamplerId { |
| + SAMPLER_TEXTURE_2D, |
| + SAMPLER_TEXTURE_EXTERNAL_OES, |
| + NUM_SAMPLERS, |
| }; |
| -const ShaderInfo shader_infos[] = { |
| +const char* vertex_shader_source = |
| // VERTEX_SHADER_POS_TEX |
| SHADER( |
| uniform mat4 u_matrix; |
| @@ -60,123 +56,64 @@ const ShaderInfo shader_infos[] = { |
| void main(void) { |
| gl_Position = u_matrix * a_position; |
| v_uv = a_position.xy * 0.5 + vec2(0.5, 0.5); |
| - }), |
| + }); |
| + |
| +const char* fragment_shader_source[NUM_SHADERS][NUM_SAMPLERS] = { |
| // FRAGMENT_SHADER_TEX |
| - SHADER( |
| - uniform sampler2D u_texSampler; |
| + SHADERS( |
| + uniform SamplerType u_texSampler; |
| varying vec2 v_uv; |
| void main(void) { |
| - gl_FragColor = texture2D(u_texSampler, v_uv.st); |
| + gl_FragColor = TextureLookup(u_texSampler, v_uv.st); |
| }), |
| // FRAGMENT_SHADER_TEX_FLIP_Y |
| - SHADER( |
| - uniform sampler2D u_texSampler; |
| + SHADERS( |
| + uniform SamplerType u_texSampler; |
| varying vec2 v_uv; |
| void main(void) { |
| - gl_FragColor = texture2D(u_texSampler, vec2(v_uv.s, 1.0 - v_uv.t)); |
| + gl_FragColor = TextureLookup(u_texSampler, vec2(v_uv.s, 1.0 - v_uv.t)); |
|
piman
2014/04/25 03:30:40
Maybe for later... those shaders would be more eff
reveman
2014/04/25 20:27:10
I'll do this in a follow up. I need to change this
|
| }), |
| // FRAGMENT_SHADER_TEX_PREMULTIPLY_ALPHA |
| - SHADER( |
| - uniform sampler2D u_texSampler; |
| + SHADERS( |
| + uniform SamplerType u_texSampler; |
| varying vec2 v_uv; |
| void main(void) { |
| - gl_FragColor = texture2D(u_texSampler, v_uv.st); |
| + gl_FragColor = TextureLookup(u_texSampler, v_uv.st); |
| gl_FragColor.rgb *= gl_FragColor.a; |
| }), |
| // FRAGMENT_SHADER_TEX_UNPREMULTIPLY_ALPHA |
| - SHADER( |
| - uniform sampler2D u_texSampler; |
| + SHADERS( |
| + uniform SamplerType u_texSampler; |
| varying vec2 v_uv; |
| void main(void) { |
| - gl_FragColor = texture2D(u_texSampler, v_uv.st); |
| + gl_FragColor = TextureLookup(u_texSampler, v_uv.st); |
| if (gl_FragColor.a > 0.0) |
| gl_FragColor.rgb /= gl_FragColor.a; |
| }), |
| // FRAGMENT_SHADER_TEX_PREMULTIPLY_ALPHA_FLIP_Y |
| - SHADER( |
| - uniform sampler2D u_texSampler; |
| + SHADERS( |
| + uniform SamplerType u_texSampler; |
| varying vec2 v_uv; |
| void main(void) { |
| - gl_FragColor = texture2D(u_texSampler, vec2(v_uv.s, 1.0 - v_uv.t)); |
| + gl_FragColor = TextureLookup(u_texSampler, vec2(v_uv.s, 1.0 - v_uv.t)); |
| gl_FragColor.rgb *= gl_FragColor.a; |
| }), |
| // FRAGMENT_SHADER_TEX_UNPREMULTIPLY_ALPHA_FLIP_Y |
| - SHADER( |
| - uniform sampler2D u_texSampler; |
| - varying vec2 v_uv; |
| - void main(void) { |
| - gl_FragColor = texture2D(u_texSampler, vec2(v_uv.s, 1.0 - v_uv.t)); |
| - if (gl_FragColor.a > 0.0) |
| - gl_FragColor.rgb /= gl_FragColor.a; |
| - }), |
| - // FRAGMENT_SHADER_TEX_OES |
| - SHADER_EXTERNAL_OES( |
| - precision mediump float; |
| - uniform samplerExternalOES u_texSampler; |
| + SHADERS( |
| + uniform SamplerType u_texSampler; |
| varying vec2 v_uv; |
| void main(void) { |
| - gl_FragColor = texture2D(u_texSampler, v_uv.st); |
| - }), |
| - // FRAGMENT_SHADER_TEX_OES_FLIP_Y |
| - SHADER_EXTERNAL_OES( |
| - precision mediump float; |
| - uniform samplerExternalOES u_texSampler; |
| - varying vec2 v_uv; |
| - void main(void) { |
| - gl_FragColor = |
| - texture2D(u_texSampler, vec2(v_uv.s, 1.0 - v_uv.t)); |
| - }), |
| - // FRAGMENT_SHADER_TEX_OES_PREMULTIPLY_ALPHA |
| - SHADER_EXTERNAL_OES( |
| - precision mediump float; |
| - uniform samplerExternalOES u_texSampler; |
| - varying vec2 v_uv; |
| - void main(void) { |
| - gl_FragColor = texture2D(u_texSampler, v_uv.st); |
| - gl_FragColor.rgb *= gl_FragColor.a; |
| - }), |
| - // FRAGMENT_SHADER_TEX_OES_UNPREMULTIPLY_ALPHA |
| - SHADER_EXTERNAL_OES( |
| - precision mediump float; |
| - uniform samplerExternalOES u_texSampler; |
| - varying vec2 v_uv; |
| - void main(void) { |
| - gl_FragColor = texture2D(u_texSampler, v_uv.st); |
| + gl_FragColor = TextureLookup(u_texSampler, vec2(v_uv.s, 1.0 - v_uv.t)); |
| if (gl_FragColor.a > 0.0) |
| gl_FragColor.rgb /= gl_FragColor.a; |
| }), |
| - // FRAGMENT_SHADER_TEX_OES_PREMULTIPLY_ALPHA_FLIP_Y |
| - SHADER_EXTERNAL_OES( |
| - precision mediump float; |
| - uniform samplerExternalOES u_texSampler; |
| - varying vec2 v_uv; |
| - void main(void) { |
| - gl_FragColor = |
| - texture2D(u_texSampler, vec2(v_uv.s, 1.0 - v_uv.t)); |
| - gl_FragColor.rgb *= gl_FragColor.a; |
| - }), |
| - // FRAGMENT_SHADER_TEX_OES_UNPREMULTIPLY_ALPHA_FLIP_Y |
| - SHADER_EXTERNAL_OES( |
| - precision mediump float; |
| - uniform samplerExternalOES u_texSampler; |
| - varying vec2 v_uv; |
| - void main(void) { |
| - gl_FragColor = |
| - texture2D(u_texSampler, vec2(v_uv.s, 1.0 - v_uv.t)); |
| - if (gl_FragColor.a > 0.0) |
| - gl_FragColor.rgb /= gl_FragColor.a; |
| - }), |
| }; |
| -const int kNumShaders = arraysize(shader_infos); |
| - |
| -// Returns the correct program to evaluate the copy operation for |
| +// Returns the correct shader id to evaluate the copy operation for |
| // the CHROMIUM_flipy and premultiply alpha pixel store settings. |
| -ProgramId GetProgram( |
| - bool flip_y, |
| - bool premultiply_alpha, |
| - bool unpremultiply_alpha, |
| - bool is_source_external_oes) { |
| +ShaderId GetShaderId(bool flip_y, |
| + bool premultiply_alpha, |
| + bool unpremultiply_alpha) { |
| // If both pre-multiply and unpremultiply are requested, then perform no |
| // alpha manipulation. |
| if (premultiply_alpha && unpremultiply_alpha) { |
| @@ -187,31 +124,44 @@ ProgramId GetProgram( |
| // bit 0: Flip_y |
| // bit 1: Premult |
| // bit 2: Unpremult |
| - // bit 3: External_oes |
| - static ProgramId program_ids[] = { |
| - PROGRAM_COPY_TEXTURE, |
| - PROGRAM_COPY_TEXTURE_FLIP_Y, // F |
| - PROGRAM_COPY_TEXTURE_PREMULTIPLY_ALPHA, // P |
| - PROGRAM_COPY_TEXTURE_PREMULTIPLY_ALPHA_FLIPY, // F P |
| - PROGRAM_COPY_TEXTURE_UNPREMULTIPLY_ALPHA, // U |
| - PROGRAM_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_FLIPY, // F U |
| - PROGRAM_COPY_TEXTURE, // P U |
| - PROGRAM_COPY_TEXTURE, // F P U |
| - PROGRAM_COPY_TEXTURE_OES, // E |
| - PROGRAM_COPY_TEXTURE_OES_FLIP_Y, // F E |
| - PROGRAM_COPY_TEXTURE_OES_PREMULTIPLY_ALPHA, // P E |
| - PROGRAM_COPY_TEXTURE_OES_PREMULTIPLY_ALPHA_FLIPY, // F P E |
| - PROGRAM_COPY_TEXTURE_OES_UNPREMULTIPLY_ALPHA, // U E |
| - PROGRAM_COPY_TEXTURE_OES_UNPREMULTIPLY_ALPHA_FLIPY, // F U E |
| - PROGRAM_COPY_TEXTURE_OES, // P U E |
| - PROGRAM_COPY_TEXTURE_OES, // F P U E |
| + static ShaderId shader_ids[] = { |
| + SHADER_COPY_TEXTURE, |
| + SHADER_COPY_TEXTURE_FLIP_Y, // F |
| + SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA, // P |
| + SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_FLIPY, // F P |
| + SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA, // U |
| + SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_FLIPY, // F U |
| + SHADER_COPY_TEXTURE, // P U |
| + SHADER_COPY_TEXTURE, // F P U |
|
piman
2014/04/25 03:30:40
Shouldn't this last one be SHADER_COPY_TEXTURE_FLI
reveman
2014/04/25 20:27:10
Sure, I assume these last two are invalid configur
|
| }; |
| - unsigned index = (flip_y ? (1 << 0) : 0) | |
| - (premultiply_alpha ? (1 << 1) : 0) | |
| - (unpremultiply_alpha ? (1 << 2) : 0) | |
| - (is_source_external_oes ? (1 << 3) : 0); |
| - return program_ids[index]; |
| + unsigned index = (flip_y ? (1 << 0) : 0) | |
| + (premultiply_alpha ? (1 << 1) : 0) | |
| + (unpremultiply_alpha ? (1 << 2) : 0); |
| + return shader_ids[index]; |
| +} |
| + |
| +SamplerId GetSamplerId(GLenum source_target) { |
| + switch (source_target) { |
| + case GL_TEXTURE_2D: |
| + return SAMPLER_TEXTURE_2D; |
| + case GL_TEXTURE_EXTERNAL_OES: |
| + return SAMPLER_TEXTURE_EXTERNAL_OES; |
| + } |
| + |
| + NOTREACHED(); |
| + return SAMPLER_TEXTURE_2D; |
| +} |
| + |
| +void CompileShader(GLuint shader, const char* shader_source) { |
| + glShaderSource(shader, 1, &shader_source, 0); |
| + glCompileShader(shader); |
| +#ifndef NDEBUG |
| + GLint compile_status; |
| + glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status); |
| + if (GL_TRUE != compile_status) |
| + DLOG(ERROR) << "CopyTextureCHROMIUM: shader compilation failure."; |
| +#endif |
| } |
| } // namespace |
| @@ -219,27 +169,17 @@ ProgramId GetProgram( |
| namespace gpu { |
| CopyTextureCHROMIUMResourceManager::CopyTextureCHROMIUMResourceManager() |
| - : initialized_(false), |
| - buffer_id_(0), |
| - framebuffer_(0) { |
| - for (int i = 0; i < kNumPrograms; ++i) { |
| - programs_[i] = 0; |
| - matrix_handle_[i] = 0; |
| - sampler_locations_[i] = 0; |
| - } |
| + : initialized_(false), buffer_id_(0), framebuffer_(0), vertex_shader_(0) { |
| } |
| +CopyTextureCHROMIUMResourceManager::~CopyTextureCHROMIUMResourceManager() {} |
| + |
| void CopyTextureCHROMIUMResourceManager::Initialize( |
| const gles2::GLES2Decoder* decoder) { |
| COMPILE_ASSERT( |
| kVertexPositionAttrib == 0u, |
| Position_attribs_must_be_0); |
| - const char* extensions = |
| - reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)); |
| - bool have_egl_image_external = extensions && |
| - strstr(extensions, "GL_OES_EGL_image_external"); |
| - |
| // Initialize all of the GPU resources required to perform the copy. |
| glGenBuffersARB(1, &buffer_id_); |
| glBindBuffer(GL_ARRAY_BUFFER, buffer_id_); |
| @@ -248,56 +188,8 @@ void CopyTextureCHROMIUMResourceManager::Initialize( |
| glGenFramebuffersEXT(1, &framebuffer_); |
| - // TODO(gman): Init these on demand. |
| - GLuint shaders[kNumShaders]; |
| - for (int shader = 0; shader < kNumShaders; ++shader) { |
| - shaders[shader] = glCreateShader( |
| - shader == 0 ? GL_VERTEX_SHADER : GL_FRAGMENT_SHADER); |
| - const ShaderInfo& info = shader_infos[shader]; |
| - if (info.needs_egl_image_external && !have_egl_image_external) { |
| - continue; |
| - } |
| - const char* shader_source = shader_infos[shader].source; |
| - glShaderSource(shaders[shader], 1, &shader_source, 0); |
| - glCompileShader(shaders[shader]); |
| -#ifndef NDEBUG |
| - GLint compile_status; |
| - glGetShaderiv(shaders[shader], GL_COMPILE_STATUS, &compile_status); |
| - if (GL_TRUE != compile_status) |
| - DLOG(ERROR) << "CopyTextureCHROMIUM: shader compilation failure."; |
| -#endif |
| - } |
| - |
| - // TODO(gman): Init these on demand. |
| - for (int program = 0; program < kNumPrograms; ++program) { |
| - const ShaderInfo& info = shader_infos[program + 1]; |
| - if (info.needs_egl_image_external && !have_egl_image_external) { |
| - continue; |
| - } |
| - programs_[program] = glCreateProgram(); |
| - glAttachShader(programs_[program], shaders[0]); |
| - glAttachShader(programs_[program], shaders[program + 1]); |
| - |
| - glBindAttribLocation(programs_[program], kVertexPositionAttrib, |
| - "a_position"); |
| - |
| - glLinkProgram(programs_[program]); |
| -#ifndef NDEBUG |
| - GLint linked; |
| - glGetProgramiv(programs_[program], GL_LINK_STATUS, &linked); |
| - if (!linked) |
| - DLOG(ERROR) << "CopyTextureCHROMIUM: program link failure."; |
| -#endif |
| - |
| - sampler_locations_[program] = glGetUniformLocation(programs_[program], |
| - "u_texSampler"); |
| - |
| - matrix_handle_[program] = glGetUniformLocation(programs_[program], |
| - "u_matrix"); |
| - } |
| - |
| - for (int shader = 0; shader < kNumShaders; ++shader) |
| - glDeleteShader(shaders[shader]); |
| + vertex_shader_ = glCreateShader(GL_VERTEX_SHADER); |
| + CompileShader(vertex_shader_, vertex_shader_source); |
| decoder->RestoreBufferBindings(); |
| @@ -310,9 +202,11 @@ void CopyTextureCHROMIUMResourceManager::Destroy() { |
| glDeleteFramebuffersEXT(1, &framebuffer_); |
| - for (int program = 0; program < kNumPrograms; ++program) { |
| - if (programs_[program]) |
| - glDeleteProgram(programs_[program]); |
| + glDeleteShader(vertex_shader_); |
| + for (ProgramMap::const_iterator it = programs_.begin(); it != programs_.end(); |
| + ++it) { |
| + const ProgramInfo& info = it->second; |
| + glDeleteProgram(info.program); |
| } |
| glDeleteBuffersARB(1, &buffer_id_); |
| @@ -360,22 +254,45 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTextureWithTransform( |
| return; |
| } |
| - GLuint program = GetProgram( |
| - flip_y, premultiply_alpha, unpremultiply_alpha, |
| - source_target == GL_TEXTURE_EXTERNAL_OES); |
| - glUseProgram(programs_[program]); |
| + ShaderId shader_id = |
| + GetShaderId(flip_y, premultiply_alpha, unpremultiply_alpha); |
| + SamplerId sampler_id = GetSamplerId(source_target); |
| + |
| + ProgramMapKey key(shader_id, sampler_id); |
| + ProgramInfo* info = &programs_[key]; |
| + // Create program if necessary. |
| + if (!info->program) { |
| + GLuint shader = glCreateShader(GL_FRAGMENT_SHADER); |
| + CompileShader(shader, fragment_shader_source[shader_id][sampler_id]); |
| + info->program = glCreateProgram(); |
| + glAttachShader(info->program, vertex_shader_); |
| + glAttachShader(info->program, shader); |
| + glBindAttribLocation(info->program, kVertexPositionAttrib, "a_position"); |
| + glLinkProgram(info->program); |
| +#ifndef NDEBUG |
| + GLint linked; |
| + glGetProgramiv(info->program, GL_LINK_STATUS, &linked); |
| + if (!linked) |
| + DLOG(ERROR) << "CopyTextureCHROMIUM: program link failure."; |
| +#endif |
| + info->sampler_locations = |
| + glGetUniformLocation(info->program, "u_texSampler"); |
| + info->matrix_handle = glGetUniformLocation(info->program, "u_matrix"); |
| + glDeleteShader(shader); |
| + } |
| + glUseProgram(info->program); |
| #ifndef NDEBUG |
| - glValidateProgram(programs_[program]); |
| + glValidateProgram(info->program); |
| GLint validation_status; |
| - glGetProgramiv(programs_[program], GL_VALIDATE_STATUS, &validation_status); |
| + glGetProgramiv(info->program, GL_VALIDATE_STATUS, &validation_status); |
| if (GL_TRUE != validation_status) { |
| DLOG(ERROR) << "CopyTextureCHROMIUM: Invalid shader."; |
| return; |
| } |
| #endif |
| - glUniformMatrix4fv(matrix_handle_[program], 1, GL_FALSE, transform_matrix); |
| + glUniformMatrix4fv(info->matrix_handle, 1, GL_FALSE, transform_matrix); |
| glActiveTexture(GL_TEXTURE0); |
| glBindTexture(GL_TEXTURE_2D, dest_id); |
| // NVidia drivers require texture settings to be a certain way |
| @@ -402,7 +319,7 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTextureWithTransform( |
| glVertexAttribPointer(kVertexPositionAttrib, 4, GL_FLOAT, GL_FALSE, |
| 4 * sizeof(GLfloat), 0); |
| - glUniform1i(sampler_locations_[program], 0); |
| + glUniform1i(info->sampler_locations, 0); |
| glBindTexture(source_target, source_id); |
| glTexParameterf(source_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |