diff options
author | twiz@chromium.org <twiz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-19 15:43:17 +0000 |
---|---|---|
committer | twiz@chromium.org <twiz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-19 15:43:17 +0000 |
commit | 6c75c71e79b70dcf32982b1da3e219c277872162 (patch) | |
tree | e815368906a055004f7273b3c7119764f48689e0 /gpu/command_buffer | |
parent | a9377f622db492fbf08fc12eac9d504bb5a4a8b7 (diff) | |
download | chromium_src-6c75c71e79b70dcf32982b1da3e219c277872162.zip chromium_src-6c75c71e79b70dcf32982b1da3e219c277872162.tar.gz chromium_src-6c75c71e79b70dcf32982b1da3e219c277872162.tar.bz2 |
Addition of an unpremultiplied-alpha setting for the GL_CHROMIUM_copy_texture command buffer GL extension.
The extension needs to support the ability to unpremultiply the source of the copy because of the canvas2d-webgl texture use case. Canvas is stored in premultiplied form, yet WebGL expects texture contents to be in unpremultiplied form.
Change also includes conversion of argument types to overriders of WebGraphicsContext3D::copyTextureCHROMIUM(...).
This change is necessary as a result of a wk-change: https://bugs.webkit.org/show_bug.cgi?id=86275
BUG=101051
TEST=none
Review URL: https://chromiumcodereview.appspot.com/10535174
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@142962 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu/command_buffer')
8 files changed, 147 insertions, 10 deletions
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index 9d14137..aec1984 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py @@ -200,6 +200,9 @@ _ENUM_LISTS = { 'GL_TEXTURE_BINDING_2D', 'GL_TEXTURE_BINDING_CUBE_MAP', 'GL_UNPACK_ALIGNMENT', + 'GL_UNPACK_FLIP_Y_CHROMIUM', + 'GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM', + 'GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM', 'GL_VIEWPORT', ], 'invalid': [ @@ -589,6 +592,7 @@ _ENUM_LISTS = { 'GL_UNPACK_ALIGNMENT', 'GL_UNPACK_FLIP_Y_CHROMIUM', 'GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM', + 'GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM', ], 'invalid': [ 'GL_PACK_SWAP_BYTES', diff --git a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h index 98f7f7e..35982fe 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h @@ -291,6 +291,7 @@ static GLES2Util::EnumToString enum_to_string_table[] = { { 0x8827, "GL_DRAW_BUFFER2_NV", }, { 0x9243, "GL_UNPACK_COLORSPACE_CONVERSION_CHROMIUM", }, { 0x8DF3, "GL_LOW_INT", }, + { 0x9242, "GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM", }, { 0x8B53, "GL_INT_VEC2", }, { 0x0C02, "GL_READ_BUFFER_NV", }, { 0x9241, "GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM", }, @@ -829,6 +830,11 @@ std::string GLES2Util::GetStringGLState(uint32 value) { { GL_TEXTURE_BINDING_2D, "GL_TEXTURE_BINDING_2D" }, { GL_TEXTURE_BINDING_CUBE_MAP, "GL_TEXTURE_BINDING_CUBE_MAP" }, { GL_UNPACK_ALIGNMENT, "GL_UNPACK_ALIGNMENT" }, + { GL_UNPACK_FLIP_Y_CHROMIUM, "GL_UNPACK_FLIP_Y_CHROMIUM" }, + { GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM, + "GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM" }, + { GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, + "GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM" }, { GL_VIEWPORT, "GL_VIEWPORT" }, }; return GLES2Util::GetQualifiedEnumString( @@ -893,6 +899,8 @@ std::string GLES2Util::GetStringPixelStore(uint32 value) { { GL_UNPACK_FLIP_Y_CHROMIUM, "GL_UNPACK_FLIP_Y_CHROMIUM" }, { GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM, "GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM" }, + { GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, + "GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM" }, }; return GLES2Util::GetQualifiedEnumString( string_table, arraysize(string_table), value); diff --git a/gpu/command_buffer/service/gl_utils.h b/gpu/command_buffer/service/gl_utils.h index f8f52ee..316c3bb 100644 --- a/gpu/command_buffer/service/gl_utils.h +++ b/gpu/command_buffer/service/gl_utils.h @@ -46,6 +46,7 @@ #define GL_UNPACK_FLIP_Y_CHROMIUM 0x9240 #define GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM 0x9241 +#define GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM 0x9242 #define GL_UNPACK_COLORSPACE_CONVERSION_CHROMIUM 0x9243 // GL_ANGLE_pack_reverse_row_order 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 80fe484..cdf2f30 100644 --- a/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc +++ b/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc @@ -27,34 +27,52 @@ const GLfloat kTextureCoords[] = { 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f }; -const int kNumShaders = 5; +const int kNumShaders = 7; enum ShaderId { VERTEX_SHADER_POS_TEX, FRAGMENT_SHADER_TEX, FRAGMENT_SHADER_TEX_FLIP_Y, FRAGMENT_SHADER_TEX_PREMULTIPLY_ALPHA, - FRAGMENT_SHADER_TEX_PREMULTIPLY_ALPHA_FLIP_Y + FRAGMENT_SHADER_TEX_UNPREMULTIPLY_ALPHA, + FRAGMENT_SHADER_TEX_PREMULTIPLY_ALPHA_FLIP_Y, + FRAGMENT_SHADER_TEX_UNPREMULTIPLY_ALPHA_FLIP_Y }; enum ProgramId { PROGRAM_COPY_TEXTURE, PROGRAM_COPY_TEXTURE_FLIP_Y, PROGRAM_COPY_TEXTURE_PREMULTIPLY_ALPHA, - PROGRAM_COPY_TEXTURE_PREMULTIPLY_ALPHA_FLIPY + PROGRAM_COPY_TEXTURE_UNPREMULTIPLY_ALPHA, + PROGRAM_COPY_TEXTURE_PREMULTIPLY_ALPHA_FLIPY, + PROGRAM_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_FLIPY }; // Returns the correct program to evaluate the copy operation for // the CHROMIUM_flipy and premultiply alpha pixel store settings. -ProgramId GetProgram(bool flip_y, bool premultiply_alpha) { +ProgramId GetProgram(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) { + premultiply_alpha = false; + unpremultiply_alpha = false; + } + if (flip_y && premultiply_alpha) return PROGRAM_COPY_TEXTURE_PREMULTIPLY_ALPHA_FLIPY; + if (flip_y && unpremultiply_alpha) + return PROGRAM_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_FLIPY; + if (flip_y) return PROGRAM_COPY_TEXTURE_FLIP_Y; if (premultiply_alpha) return PROGRAM_COPY_TEXTURE_PREMULTIPLY_ALPHA; + if (unpremultiply_alpha) + return PROGRAM_COPY_TEXTURE_UNPREMULTIPLY_ALPHA; + return PROGRAM_COPY_TEXTURE; } @@ -91,6 +109,15 @@ const char* GetShaderSource(ShaderId shader) { gl_FragColor = texture2D(u_texSampler, v_uv.st); gl_FragColor.rgb *= gl_FragColor.a; }); + case FRAGMENT_SHADER_TEX_UNPREMULTIPLY_ALPHA: + return SHADER( + uniform sampler2D u_texSampler; + varying vec2 v_uv; + void main(void) { + gl_FragColor = texture2D(u_texSampler, v_uv.st); + if (gl_FragColor.a > 0.0) + gl_FragColor.rgb /= gl_FragColor.a; + }); case FRAGMENT_SHADER_TEX_PREMULTIPLY_ALPHA_FLIP_Y: return SHADER( uniform sampler2D u_texSampler; @@ -99,6 +126,15 @@ const char* GetShaderSource(ShaderId shader) { gl_FragColor = texture2D(u_texSampler, vec2(v_uv.s, 1.0 - v_uv.t)); gl_FragColor.rgb *= gl_FragColor.a; }); + case FRAGMENT_SHADER_TEX_UNPREMULTIPLY_ALPHA_FLIP_Y: + return 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; + }); default: return 0; } @@ -184,13 +220,14 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTexture( GLuint dest_id, GLint level, bool flip_y, - bool premultiply_alpha) { + bool premultiply_alpha, + bool unpremultiply_alpha) { if (!initialized_) { DLOG(ERROR) << "CopyTextureCHROMIUM: Uninitialized manager."; return; } - GLuint program = GetProgram(flip_y, premultiply_alpha); + GLuint program = GetProgram(flip_y, premultiply_alpha, unpremultiply_alpha); glUseProgram(programs_[program]); #ifndef NDEBUG diff --git a/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h b/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h index d207fca..933bf65 100644 --- a/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h +++ b/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h @@ -18,7 +18,8 @@ class CopyTextureCHROMIUMResourceManager { void Destroy(); void DoCopyTexture(GLenum target, GLuint source_id, GLuint dest_id, - GLint level, bool flip_y, bool premultiply_alpha); + GLint level, bool flip_y, bool premultiply_alpha, + bool unpremultiply_alpha); // The attributes used during invocation of the extension. static const GLuint kVertexPositionAttrib = 0; @@ -27,7 +28,7 @@ class CopyTextureCHROMIUMResourceManager { private: bool initialized_; - static const int kNumPrograms = 4; + static const int kNumPrograms = 6; GLuint programs_[kNumPrograms]; GLuint buffer_ids_[2]; GLuint framebuffer_; diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 091b96b..b40198e 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -1389,8 +1389,9 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, // unpack flip y as last set by glPixelStorei bool unpack_flip_y_; - // unpack premultiply alpha as last set by glPixelStorei + // unpack (un)premultiply alpha as last set by glPixelStorei bool unpack_premultiply_alpha_; + bool unpack_unpremultiply_alpha_; // The currently bound array buffer. If this is 0 it is illegal to call // glVertexAttribPointer. @@ -1905,6 +1906,7 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group) unpack_alignment_(4), unpack_flip_y_(false), unpack_premultiply_alpha_(false), + unpack_unpremultiply_alpha_(false), attrib_0_buffer_id_(0), attrib_0_buffer_matches_value_(true), attrib_0_size_(0), @@ -3838,6 +3840,24 @@ bool GLES2DecoderImpl::GetHelper( } } return true; + case GL_UNPACK_FLIP_Y_CHROMIUM: + *num_written = 1; + if (params) { + params[0] = unpack_flip_y_; + } + return true; + case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM: + *num_written = 1; + if (params) { + params[0] = unpack_premultiply_alpha_; + } + return true; + case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM: + *num_written = 1; + if (params) { + params[0] = unpack_unpremultiply_alpha_; + } + return true; default: *num_written = util_.GLGetNumValuesReturned(pname); return false; @@ -6369,6 +6389,9 @@ error::Error GLES2DecoderImpl::HandlePixelStorei( case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM: unpack_premultiply_alpha_ = (param != 0); return error::kNoError; + case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM: + unpack_unpremultiply_alpha_ = (param != 0); + return error::kNoError; default: break; } @@ -8829,7 +8852,8 @@ void GLES2DecoderImpl::DoCopyTextureCHROMIUM( copy_texture_CHROMIUM_->DoCopyTexture(target, source_info->service_id(), dest_info->service_id(), level, unpack_flip_y_, - unpack_premultiply_alpha_); + unpack_premultiply_alpha_, + unpack_unpremultiply_alpha_); glViewport(viewport_x_, viewport_y_, viewport_width_, viewport_height_); // Restore all of the state touched by the extension. diff --git a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h index bc19e4f..79f4e57 100644 --- a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h @@ -202,6 +202,9 @@ static GLenum valid_g_l_state_table[] = { GL_TEXTURE_BINDING_2D, GL_TEXTURE_BINDING_CUBE_MAP, GL_UNPACK_ALIGNMENT, + GL_UNPACK_FLIP_Y_CHROMIUM, + GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM, + GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, GL_VIEWPORT, }; @@ -241,6 +244,7 @@ static GLenum valid_pixel_store_table[] = { GL_UNPACK_ALIGNMENT, GL_UNPACK_FLIP_Y_CHROMIUM, GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM, + GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, }; static GLint valid_pixel_store_alignment_table[] = { diff --git a/gpu/command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc b/gpu/command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc index 39cfe47..bd53e51 100644 --- a/gpu/command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc +++ b/gpu/command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc @@ -116,6 +116,29 @@ TEST_F(GLCopyTextureCHROMIUMTest, PremultiplyAlpha) { EXPECT_TRUE(GL_NO_ERROR == glGetError()); } +// Test that the extension respects the GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM +// storage setting. +TEST_F(GLCopyTextureCHROMIUMTest, UnpremultiplyAlpha) { + uint8 pixels[1 * 4] = { 16, 16, 16, 128 }; + + glBindTexture(GL_TEXTURE_2D, textures_[0]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + pixels); + + glPixelStorei(GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, GL_TRUE); + glCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], 0, GL_RGBA); + EXPECT_TRUE(GL_NO_ERROR == glGetError()); + + uint8 copied_pixels[1 * 4]; + glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, copied_pixels); + EXPECT_EQ(32u, copied_pixels[0]); + EXPECT_EQ(32u, copied_pixels[1]); + EXPECT_EQ(32u, copied_pixels[2]); + EXPECT_EQ(128u, copied_pixels[3]); + + EXPECT_TRUE(GL_NO_ERROR == glGetError()); +} + TEST_F(GLCopyTextureCHROMIUMTest, FlipYAndPremultiplyAlpha) { uint8 pixels[2][2][4]; for (int x = 0; x < 2; ++x) { @@ -151,6 +174,41 @@ TEST_F(GLCopyTextureCHROMIUMTest, FlipYAndPremultiplyAlpha) { EXPECT_TRUE(GL_NO_ERROR == glGetError()); } +TEST_F(GLCopyTextureCHROMIUMTest, FlipYAndUnpremultiplyAlpha) { + uint8 pixels[2][2][4]; + for (int x = 0; x < 2; ++x) { + for (int y = 0; y < 2; ++y) { + uint8 color = 16 * x + 16 * y; + pixels[y][x][0] = color; + pixels[y][x][1] = color; + pixels[y][x][2] = color; + pixels[y][x][3] = 128u; + } + } + + glBindTexture(GL_TEXTURE_2D, textures_[0]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, + pixels); + + glPixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, GL_TRUE); + glPixelStorei(GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, GL_TRUE); + glCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], 0, GL_RGBA); + EXPECT_TRUE(GL_NO_ERROR == glGetError()); + + uint8 copied_pixels[2][2][4]; + glReadPixels(0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, copied_pixels); + for (int x = 0; x < 2; ++x) { + for (int y = 0; y < 2; ++y) { + EXPECT_EQ(pixels[1-y][x][0] * 2, copied_pixels[y][x][0]); + EXPECT_EQ(pixels[1-y][x][1] * 2, copied_pixels[y][x][1]); + EXPECT_EQ(pixels[1-y][x][2] * 2, copied_pixels[y][x][2]); + EXPECT_EQ(pixels[1-y][x][3], copied_pixels[y][x][3]); + } + } + + EXPECT_TRUE(GL_NO_ERROR == glGetError()); +} + namespace { void glEnableDisable(GLint param, GLboolean value) { |