summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gpu/GLES2/extensions/CHROMIUM/CHROMIUM_copy_texture.txt12
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc42
-rw-r--r--gpu/command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc112
3 files changed, 146 insertions, 20 deletions
diff --git a/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_copy_texture.txt b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_copy_texture.txt
index fdaa7d6..ad9ca68 100644
--- a/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_copy_texture.txt
+++ b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_copy_texture.txt
@@ -48,7 +48,10 @@ New Procedures and Functions
The internal format of the destination texture is converted to that
specified by <internal_format>. Must be one of the following symbolic
- constants: GL_ALPHA, GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_RGB, GL_RGBA
+ constants: GL_RGB, GL_RGBA
+ The internal format of <source_id> texture must be one of the following
+ symbolic constants: GL_ALPHA, GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_RGB,
+ GL_RGBA, GL_BGRA_EXT
When <source_id> texture doens't contain a superset of the component
required by <internal_format>, fill the components by following rules.
@@ -59,12 +62,19 @@ New Procedures and Functions
GL_LUMINANCE_ALPHA (L, L, L, A)
GL_RGB (R, G, B, 1)
GL_RGBA (R, G, B, A)
+ GL_BGRA_EXT (R, G, B, A)
The format type of the destination texture is converted to that specified
by <dest_type>.
<target> uses the same parameters as TexImage2D.
+ INVALID_OPERATION is generated if <internal_format> is not one of the valid formats
+ described above.
+
+ INVALID_OPERATION is generated if the internal format of <source_id> is not one of
+ formats from the table above.
+
INVALID_VALUE is generated if <target> is not GL_TEXTURE_2D.
INVALID_VALUE is generated if <source_id> or <dest_id> are not valid texture
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 5e26477..ac33e69 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -10047,6 +10047,29 @@ void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
return;
}
+ GLenum source_type = 0;
+ GLenum source_internal_format = 0;
+ source_texture->GetLevelType(
+ source_texture->target(), 0, &source_type, &source_internal_format);
+
+ // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA,
+ // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not
+ // renderable on some platforms.
+ bool valid_dest_format =
+ internal_format == GL_RGB || internal_format == GL_RGBA;
+ bool valid_source_format = source_internal_format == GL_ALPHA ||
+ source_internal_format == GL_RGB ||
+ source_internal_format == GL_RGBA ||
+ source_internal_format == GL_LUMINANCE ||
+ source_internal_format == GL_LUMINANCE_ALPHA ||
+ source_internal_format == GL_BGRA_EXT;
+ if (!valid_source_format || !valid_dest_format) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
+ "glCopyTextureCHROMIUM",
+ "invalid internal format");
+ return;
+ }
+
// Defer initializing the CopyTextureCHROMIUMResourceManager until it is
// needed because it takes 10s of milliseconds to initialize.
if (!copy_texture_CHROMIUM_.get()) {
@@ -10058,11 +10081,6 @@ void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
return;
}
- GLenum source_type = 0;
- GLenum source_internal_format = 0;
- source_texture->GetLevelType(
- source_texture->target(), 0, &source_type, &source_internal_format);
-
GLenum dest_type_previous = dest_type;
GLenum dest_internal_format = internal_format;
bool dest_level_defined = dest_texture->GetLevelSize(
@@ -10073,20 +10091,6 @@ void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
&dest_internal_format);
}
- // The destination format should be GL_ALPHA, GL_RGB, GL_RGBA, GL_LUMINANCE,
- // or GL_LUMINANCE_ALPHA.
- bool valid_dest_format = dest_internal_format >= GL_ALPHA &&
- dest_internal_format <= GL_LUMINANCE_ALPHA;
- // The source format can be GL_BGRA_EXT.
- bool valid_source_format = (source_internal_format >= GL_ALPHA &&
- source_internal_format <= GL_LUMINANCE_ALPHA) ||
- source_internal_format == GL_BGRA_EXT;
- if (!valid_source_format || !valid_dest_format) {
- LOCAL_SET_GL_ERROR(
- GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "invalid internal format");
- return;
- }
-
// Resize the destination texture to the dimensions of the source texture.
if (!dest_level_defined || dest_width != source_width ||
dest_height != source_height ||
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 b6f82e7..e637f74 100644
--- a/gpu/command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc
+++ b/gpu/command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc
@@ -76,6 +76,118 @@ TEST_F(GLCopyTextureCHROMIUMTest, Basic) {
EXPECT_TRUE(GL_NO_ERROR == glGetError());
}
+TEST_F(GLCopyTextureCHROMIUMTest, InternalFormat) {
+ GLint src_formats[] = {GL_ALPHA, GL_RGB, GL_RGBA,
+ GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_BGRA_EXT};
+ GLint dest_formats[] = {GL_RGB, GL_RGBA};
+
+ for (size_t src_index = 0; src_index < arraysize(src_formats); src_index++) {
+ for (size_t dest_index = 0; dest_index < arraysize(dest_formats);
+ dest_index++) {
+ glBindTexture(GL_TEXTURE_2D, textures_[0]);
+ glTexImage2D(GL_TEXTURE_2D,
+ 0,
+ src_formats[src_index],
+ 1,
+ 1,
+ 0,
+ src_formats[src_index],
+ GL_UNSIGNED_BYTE,
+ NULL);
+ EXPECT_TRUE(GL_NO_ERROR == glGetError());
+
+ glCopyTextureCHROMIUM(GL_TEXTURE_2D,
+ textures_[0],
+ textures_[1],
+ 0,
+ dest_formats[dest_index],
+ GL_UNSIGNED_BYTE);
+ EXPECT_TRUE(GL_NO_ERROR == glGetError()) << "src_index:" << src_index
+ << " dest_index:" << dest_index;
+ }
+ }
+}
+
+TEST_F(GLCopyTextureCHROMIUMTest, InternalFormatNotSupported) {
+ glBindTexture(GL_TEXTURE_2D, textures_[0]);
+ glTexImage2D(
+ GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ EXPECT_TRUE(GL_NO_ERROR == glGetError());
+
+ // Check unsupported format reports error.
+ GLint unsupported_dest_formats[] = {GL_ALPHA, GL_LUMINANCE,
+ GL_LUMINANCE_ALPHA, GL_BGRA_EXT};
+ for (size_t dest_index = 0; dest_index < arraysize(unsupported_dest_formats);
+ dest_index++) {
+ glCopyTextureCHROMIUM(GL_TEXTURE_2D,
+ textures_[0],
+ textures_[1],
+ 0,
+ unsupported_dest_formats[dest_index],
+ GL_UNSIGNED_BYTE);
+ EXPECT_TRUE(GL_INVALID_OPERATION == glGetError())
+ << "dest_index:" << dest_index;
+ }
+}
+
+// Test to ensure that the destination texture is redefined if the properties
+// are different.
+TEST_F(GLCopyTextureCHROMIUMTest, RedefineDestinationTexture) {
+ uint8 pixels[4 * 4] = {255u, 0u, 0u, 255u, 255u, 0u, 0u, 255u,
+ 255u, 0u, 0u, 255u, 255u, 0u, 0u, 255u};
+
+ glBindTexture(GL_TEXTURE_2D, textures_[0]);
+ glTexImage2D(
+ GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+
+ glBindTexture(GL_TEXTURE_2D, textures_[1]);
+ glTexImage2D(GL_TEXTURE_2D,
+ 0,
+ GL_BGRA_EXT,
+ 1,
+ 1,
+ 0,
+ GL_BGRA_EXT,
+ GL_UNSIGNED_BYTE,
+ pixels);
+ EXPECT_TRUE(GL_NO_ERROR == glGetError());
+
+ // GL_INVALID_OPERATION due to "intrinsic format" != "internal format".
+ glTexSubImage2D(
+ GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+ EXPECT_TRUE(GL_INVALID_OPERATION == glGetError());
+ // GL_INVALID_VALUE due to bad dimensions.
+ glTexSubImage2D(
+ GL_TEXTURE_2D, 0, 1, 1, 1, 1, GL_BGRA_EXT, GL_UNSIGNED_BYTE, pixels);
+ EXPECT_TRUE(GL_INVALID_VALUE == glGetError());
+
+ // If the dest texture has different properties, glCopyTextureCHROMIUM()
+ // redefines them.
+ glCopyTextureCHROMIUM(
+ GL_TEXTURE_2D, textures_[0], textures_[1], 0, GL_RGBA, GL_UNSIGNED_BYTE);
+ EXPECT_TRUE(GL_NO_ERROR == glGetError());
+
+ // glTexSubImage2D() succeeds because textures_[1] is redefined into 2x2
+ // dimension and GL_RGBA format.
+ glBindTexture(GL_TEXTURE_2D, textures_[1]);
+ glTexSubImage2D(
+ GL_TEXTURE_2D, 0, 1, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+ EXPECT_TRUE(GL_NO_ERROR == glGetError());
+
+ // Check the FB is still bound.
+ GLint value = 0;
+ glGetIntegerv(GL_FRAMEBUFFER_BINDING, &value);
+ GLuint fb_id = value;
+ EXPECT_EQ(framebuffer_id_, fb_id);
+
+ // Check that FB is complete.
+ EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
+ glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+ GLTestHelper::CheckPixels(1, 1, 1, 1, 0, &pixels[12]);
+ EXPECT_TRUE(GL_NO_ERROR == glGetError());
+}
+
// Test that the extension respects the flip-y pixel storage setting.
TEST_F(GLCopyTextureCHROMIUMTest, FlipY) {
uint8 pixels[2][2][4];