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); |