From 00b21807f5c050f8766685c20e1cfc2ed9db636e Mon Sep 17 00:00:00 2001 From: christiank Date: Wed, 19 Aug 2015 07:30:37 -0700 Subject: Add glCompressedCopySubTextureCHROMIUM This CL adds a GPU command for copying sub regions of compressed textures. The implementation is based on glCopySubTextureCHROMIUM. BUG=434699 Review URL: https://codereview.chromium.org/1272153004 Cr-Commit-Position: refs/heads/master@{#344220} --- .../CHROMIUM/CHROMIUM_compressed_copy_texture.txt | 45 ++- .../extensions/CHROMIUM/CHROMIUM_copy_texture.txt | 4 +- gpu/GLES2/gl2chromium_autogen.h | 2 + gpu/GLES2/gl2extchromium.h | 22 ++ gpu/command_buffer/build_gles2_cmd_buffer.py | 6 + gpu/command_buffer/client/gles2_c_lib_autogen.h | 17 + .../client/gles2_cmd_helper_autogen.h | 16 + .../client/gles2_implementation_autogen.h | 10 + .../client/gles2_implementation_impl_autogen.h | 32 ++ .../client/gles2_implementation_unittest_autogen.h | 11 + .../client/gles2_interface_autogen.h | 9 + .../client/gles2_interface_stub_autogen.h | 9 + .../client/gles2_interface_stub_impl_autogen.h | 10 + .../client/gles2_trace_implementation_autogen.h | 9 + .../gles2_trace_implementation_impl_autogen.h | 16 + gpu/command_buffer/cmd_buffer_functions.txt | 1 + .../common/gles2_cmd_format_autogen.h | 87 +++++ .../common/gles2_cmd_format_test_autogen.h | 24 ++ gpu/command_buffer/common/gles2_cmd_ids_autogen.h | 99 +++--- .../service/gles2_cmd_copy_texture_chromium.cc | 6 +- gpu/command_buffer/service/gles2_cmd_decoder.cc | 227 +++++++++++++ .../service/gles2_cmd_decoder_autogen.h | 31 ++ .../service/gles2_cmd_decoder_unittest_3_autogen.h | 1 + ...gl_compressed_copy_texture_CHROMIUM_unittest.cc | 373 ++++++++++++++++++++- 24 files changed, 999 insertions(+), 68 deletions(-) (limited to 'gpu') diff --git a/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_compressed_copy_texture.txt b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_compressed_copy_texture.txt index c236ce3..d4f823e 100644 --- a/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_compressed_copy_texture.txt +++ b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_compressed_copy_texture.txt @@ -8,7 +8,7 @@ Name Strings Version - Last Modifed Date: Jun 15, 2015 + Last Modifed Date: August 5, 2015 Dependencies @@ -71,6 +71,48 @@ New Procedures and Functions INVALID_VALUE is generated if level 0 of the source texture is not defined. + The command + + void glCompressedCopySubTextureCHROMIUM (GLenum target, + GLenum source_id, + GLenum dest_id, + GLint xoffset, GLint yoffset, + GLint x, GLint y, + GLsizei width, GLsizei height) + + Copies the sub contents of texture referred to by to + texture without redefining texture. + + uses the same parameters as TexImage2D. + + and specify a texel offset in the x and y direction + respectively within the destination texture. + + and specify a texel offset in the x and y direction respectively + within the source texture. + + specifies the width of the texture subimage. + + specifies the width of the texture subimage. + + INVALID_OPERATION is generated if internal format of source texture is not + one of the following: GL_ATC_RGB_AMD, GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD, + GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, + GL_ETC1_RGB8_OES + + INVALID_VALUE is generated if is not GL_TEXTURE_2D. + + INVALID_OPERATION is generated if the destination texture has not been + defined. + + INVALID_VALUE is generated if level 0 of the source texture or + the destination texture is not defined. + + INVALID_VALUE is generated if < 0 , or < 0. + + INVALID_VALUE is generated if ( + ) > dest_width, + or ( + ) > dest_height. + Errors None. @@ -86,3 +128,4 @@ New State Revision History 15/6/2015 Documented the extension. + 5/8/2015 Added glCompressedCopySubTextureCHROMIUM. diff --git a/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_copy_texture.txt b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_copy_texture.txt index be60af2..f579dda 100644 --- a/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_copy_texture.txt +++ b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_copy_texture.txt @@ -136,8 +136,8 @@ New Procedures and Functions INVALID_VALUE is generated if < 0 , or < 0. - INVALID_VALUE is generated if ( + source_width) > dest_width, - or ( + source_height) > dest_height. + INVALID_VALUE is generated if ( + ) > dest_width, + or ( + ) > dest_height. Dependencies on ARB_texture_rg diff --git a/gpu/GLES2/gl2chromium_autogen.h b/gpu/GLES2/gl2chromium_autogen.h index ddbfa20..a16804f 100644 --- a/gpu/GLES2/gl2chromium_autogen.h +++ b/gpu/GLES2/gl2chromium_autogen.h @@ -300,6 +300,8 @@ #define glCopySubTextureCHROMIUM GLES2_GET_FUN(CopySubTextureCHROMIUM) #define glCompressedCopyTextureCHROMIUM \ GLES2_GET_FUN(CompressedCopyTextureCHROMIUM) +#define glCompressedCopySubTextureCHROMIUM \ + GLES2_GET_FUN(CompressedCopySubTextureCHROMIUM) #define glDrawArraysInstancedANGLE GLES2_GET_FUN(DrawArraysInstancedANGLE) #define glDrawElementsInstancedANGLE GLES2_GET_FUN(DrawElementsInstancedANGLE) #define glVertexAttribDivisorANGLE GLES2_GET_FUN(VertexAttribDivisorANGLE) diff --git a/gpu/GLES2/gl2extchromium.h b/gpu/GLES2/gl2extchromium.h index c3b10eb..584d29a 100644 --- a/gpu/GLES2/gl2extchromium.h +++ b/gpu/GLES2/gl2extchromium.h @@ -446,9 +446,31 @@ typedef void(GL_APIENTRYP PFNGLCOPYSUBTEXTURECHROMIUMPROC)( #ifdef GL_GLEXT_PROTOTYPES GL_APICALL void GL_APIENTRY glCompressedCopyTextureCHROMIUM( GLenum target, GLenum source_id, GLenum dest_id); + +GL_APICALL void GL_APIENTRY glCompressedCopySubTextureCHROMIUM( + GLenum target, + GLenum source_id, + GLenum dest_id, + GLint xoffset, + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height); #endif typedef void(GL_APIENTRYP PFNGLCOMPRESSEDCOPYTEXTURECHROMIUMPROC)( GLenum target, GLenum source_id, GLenum dest_id); + +typedef void(GL_APIENTRYP PFNGLCOMPRESSEDCOPYSUBTEXTURECHROMIUMPROC)( + GLenum target, + GLenum source_id, + GLenum dest_id, + GLint xoffset, + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height); #endif /* GL_CHROMIUM_compressed_copy_texture */ /* GL_CHROMIUM_lose_context */ diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index 6b1272d..2566923 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py @@ -3760,6 +3760,12 @@ _FUNCTION_INFO = { 'extension': True, 'chromium': True, }, + 'CompressedCopySubTextureCHROMIUM': { + 'decoder_func': 'DoCompressedCopySubTextureCHROMIUM', + 'unit_test': False, + 'extension': True, + 'chromium': True, + }, 'TexStorage2DEXT': { 'unit_test': False, 'extension': True, diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h index d6eae8f..989c500 100644 --- a/gpu/command_buffer/client/gles2_c_lib_autogen.h +++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h @@ -1374,6 +1374,18 @@ void GL_APIENTRY GLES2CompressedCopyTextureCHROMIUM(GLenum target, gles2::GetGLContext()->CompressedCopyTextureCHROMIUM(target, source_id, dest_id); } +void GL_APIENTRY GLES2CompressedCopySubTextureCHROMIUM(GLenum target, + GLenum source_id, + GLenum dest_id, + GLint xoffset, + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height) { + gles2::GetGLContext()->CompressedCopySubTextureCHROMIUM( + target, source_id, dest_id, xoffset, yoffset, x, y, width, height); +} void GL_APIENTRY GLES2DrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, @@ -2641,6 +2653,11 @@ extern const NameToFunc g_gles2_function_table[] = { reinterpret_cast(glCompressedCopyTextureCHROMIUM), }, { + "glCompressedCopySubTextureCHROMIUM", + reinterpret_cast( + glCompressedCopySubTextureCHROMIUM), + }, + { "glDrawArraysInstancedANGLE", reinterpret_cast(glDrawArraysInstancedANGLE), }, diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h index 46eb093..249e8a4 100644 --- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h +++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h @@ -2537,6 +2537,22 @@ void CompressedCopyTextureCHROMIUM(GLenum target, } } +void CompressedCopySubTextureCHROMIUM(GLenum target, + GLenum source_id, + GLenum dest_id, + GLint xoffset, + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height) { + gles2::cmds::CompressedCopySubTextureCHROMIUM* c = + GetCmdSpace(); + if (c) { + c->Init(target, source_id, dest_id, xoffset, yoffset, x, y, width, height); + } +} + void DrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h index 5d2a4c1..64bfdf4 100644 --- a/gpu/command_buffer/client/gles2_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_autogen.h @@ -954,6 +954,16 @@ void CompressedCopyTextureCHROMIUM(GLenum target, GLenum source_id, GLenum dest_id) override; +void CompressedCopySubTextureCHROMIUM(GLenum target, + GLenum source_id, + GLenum dest_id, + GLint xoffset, + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height) override; + void DrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, diff --git a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h index 958efac..9f28fe2 100644 --- a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h @@ -3254,6 +3254,38 @@ void GLES2Implementation::CompressedCopyTextureCHROMIUM(GLenum target, CheckGLError(); } +void GLES2Implementation::CompressedCopySubTextureCHROMIUM(GLenum target, + GLenum source_id, + GLenum dest_id, + GLint xoffset, + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() + << "] glCompressedCopySubTextureCHROMIUM(" + << GLES2Util::GetStringEnum(target) << ", " + << GLES2Util::GetStringEnum(source_id) << ", " + << GLES2Util::GetStringEnum(dest_id) << ", " << xoffset + << ", " << yoffset << ", " << x << ", " << y << ", " + << width << ", " << height << ")"); + if (width < 0) { + SetGLError(GL_INVALID_VALUE, "glCompressedCopySubTextureCHROMIUM", + "width < 0"); + return; + } + if (height < 0) { + SetGLError(GL_INVALID_VALUE, "glCompressedCopySubTextureCHROMIUM", + "height < 0"); + return; + } + helper_->CompressedCopySubTextureCHROMIUM(target, source_id, dest_id, xoffset, + yoffset, x, y, width, height); + CheckGLError(); +} + void GLES2Implementation::GenValuebuffersCHROMIUM(GLsizei n, GLuint* buffers) { GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGenValuebuffersCHROMIUM(" << n << ", " << static_cast(buffers) << ")"); diff --git a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h index 253b4bf..949ec7e 100644 --- a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h @@ -2893,6 +2893,17 @@ TEST_F(GLES2ImplementationTest, CompressedCopyTextureCHROMIUM) { EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); } +TEST_F(GLES2ImplementationTest, CompressedCopySubTextureCHROMIUM) { + struct Cmds { + cmds::CompressedCopySubTextureCHROMIUM cmd; + }; + Cmds expected; + expected.cmd.Init(1, 2, 3, 4, 5, 6, 7, 8, 9); + + gl_->CompressedCopySubTextureCHROMIUM(1, 2, 3, 4, 5, 6, 7, 8, 9); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} + TEST_F(GLES2ImplementationTest, DrawArraysInstancedANGLE) { struct Cmds { cmds::DrawArraysInstancedANGLE cmd; diff --git a/gpu/command_buffer/client/gles2_interface_autogen.h b/gpu/command_buffer/client/gles2_interface_autogen.h index dc11fb0..815b995 100644 --- a/gpu/command_buffer/client/gles2_interface_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_autogen.h @@ -712,6 +712,15 @@ virtual void CopySubTextureCHROMIUM(GLenum target, virtual void CompressedCopyTextureCHROMIUM(GLenum target, GLenum source_id, GLenum dest_id) = 0; +virtual void CompressedCopySubTextureCHROMIUM(GLenum target, + GLenum source_id, + GLenum dest_id, + GLint xoffset, + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height) = 0; virtual void DrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, diff --git a/gpu/command_buffer/client/gles2_interface_stub_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_autogen.h index 2675fea..060dbf3 100644 --- a/gpu/command_buffer/client/gles2_interface_stub_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_stub_autogen.h @@ -689,6 +689,15 @@ void CopySubTextureCHROMIUM(GLenum target, void CompressedCopyTextureCHROMIUM(GLenum target, GLenum source_id, GLenum dest_id) override; +void CompressedCopySubTextureCHROMIUM(GLenum target, + GLenum source_id, + GLenum dest_id, + GLint xoffset, + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height) override; void DrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, diff --git a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h index c039d1f..5797b54 100644 --- a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h @@ -939,6 +939,16 @@ void GLES2InterfaceStub::CopySubTextureCHROMIUM( void GLES2InterfaceStub::CompressedCopyTextureCHROMIUM(GLenum /* target */, GLenum /* source_id */, GLenum /* dest_id */) {} +void GLES2InterfaceStub::CompressedCopySubTextureCHROMIUM( + GLenum /* target */, + GLenum /* source_id */, + GLenum /* dest_id */, + GLint /* xoffset */, + GLint /* yoffset */, + GLint /* x */, + GLint /* y */, + GLsizei /* width */, + GLsizei /* height */) {} void GLES2InterfaceStub::DrawArraysInstancedANGLE(GLenum /* mode */, GLint /* first */, GLsizei /* count */, diff --git a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h index 753bd2b..6f6551d 100644 --- a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h @@ -689,6 +689,15 @@ void CopySubTextureCHROMIUM(GLenum target, void CompressedCopyTextureCHROMIUM(GLenum target, GLenum source_id, GLenum dest_id) override; +void CompressedCopySubTextureCHROMIUM(GLenum target, + GLenum source_id, + GLenum dest_id, + GLint xoffset, + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height) override; void DrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, diff --git a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h index 24de8af..33234093 100644 --- a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h @@ -1992,6 +1992,22 @@ void GLES2TraceImplementation::CompressedCopyTextureCHROMIUM(GLenum target, gl_->CompressedCopyTextureCHROMIUM(target, source_id, dest_id); } +void GLES2TraceImplementation::CompressedCopySubTextureCHROMIUM( + GLenum target, + GLenum source_id, + GLenum dest_id, + GLint xoffset, + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", + "GLES2Trace::CompressedCopySubTextureCHROMIUM"); + gl_->CompressedCopySubTextureCHROMIUM(target, source_id, dest_id, xoffset, + yoffset, x, y, width, height); +} + void GLES2TraceImplementation::DrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, diff --git a/gpu/command_buffer/cmd_buffer_functions.txt b/gpu/command_buffer/cmd_buffer_functions.txt index 6ce51c6..04ae93a 100644 --- a/gpu/command_buffer/cmd_buffer_functions.txt +++ b/gpu/command_buffer/cmd_buffer_functions.txt @@ -283,6 +283,7 @@ GL_APICALL void GL_APIENTRY glTexImageIOSurface2DCHROMIUM (GLenumTexture GL_APICALL void GL_APIENTRY glCopyTextureCHROMIUM (GLenum target, GLenum source_id, GLenum dest_id, GLintTextureInternalFormat internalformat, GLenumPixelType dest_type, GLboolean unpack_flip_y, GLboolean unpack_premultiply_alpha, GLboolean unpack_unmultiply_alpha); GL_APICALL void GL_APIENTRY glCopySubTextureCHROMIUM (GLenum target, GLenum source_id, GLenum dest_id, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, GLboolean unpack_flip_y, GLboolean unpack_premultiply_alpha, GLboolean unpack_unmultiply_alpha); GL_APICALL void GL_APIENTRY glCompressedCopyTextureCHROMIUM (GLenum target, GLenum source_id, GLenum dest_id); +GL_APICALL void GL_APIENTRY glCompressedCopySubTextureCHROMIUM (GLenum target, GLenum source_id, GLenum dest_id, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); GL_APICALL void GL_APIENTRY glDrawArraysInstancedANGLE (GLenumDrawMode mode, GLint first, GLsizei count, GLsizei primcount); GL_APICALL void GL_APIENTRY glDrawElementsInstancedANGLE (GLenumDrawMode mode, GLsizei count, GLenumIndexType type, const void* indices, GLsizei primcount); GL_APICALL void GL_APIENTRY glVertexAttribDivisorANGLE (GLuint index, GLuint divisor); diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h index 4b76c2ef..6270b69 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h @@ -12523,6 +12523,93 @@ static_assert(offsetof(CompressedCopyTextureCHROMIUM, source_id) == 8, static_assert(offsetof(CompressedCopyTextureCHROMIUM, dest_id) == 12, "offset of CompressedCopyTextureCHROMIUM dest_id should be 12"); +struct CompressedCopySubTextureCHROMIUM { + typedef CompressedCopySubTextureCHROMIUM ValueType; + static const CommandId kCmdId = kCompressedCopySubTextureCHROMIUM; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + + static uint32_t ComputeSize() { + return static_cast(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { header.SetCmd(); } + + void Init(GLenum _target, + GLenum _source_id, + GLenum _dest_id, + GLint _xoffset, + GLint _yoffset, + GLint _x, + GLint _y, + GLsizei _width, + GLsizei _height) { + SetHeader(); + target = _target; + source_id = _source_id; + dest_id = _dest_id; + xoffset = _xoffset; + yoffset = _yoffset; + x = _x; + y = _y; + width = _width; + height = _height; + } + + void* Set(void* cmd, + GLenum _target, + GLenum _source_id, + GLenum _dest_id, + GLint _xoffset, + GLint _yoffset, + GLint _x, + GLint _y, + GLsizei _width, + GLsizei _height) { + static_cast(cmd)->Init(_target, _source_id, _dest_id, _xoffset, + _yoffset, _x, _y, _width, _height); + return NextCmdAddress(cmd); + } + + gpu::CommandHeader header; + uint32_t target; + uint32_t source_id; + uint32_t dest_id; + int32_t xoffset; + int32_t yoffset; + int32_t x; + int32_t y; + int32_t width; + int32_t height; +}; + +static_assert(sizeof(CompressedCopySubTextureCHROMIUM) == 40, + "size of CompressedCopySubTextureCHROMIUM should be 40"); +static_assert(offsetof(CompressedCopySubTextureCHROMIUM, header) == 0, + "offset of CompressedCopySubTextureCHROMIUM header should be 0"); +static_assert(offsetof(CompressedCopySubTextureCHROMIUM, target) == 4, + "offset of CompressedCopySubTextureCHROMIUM target should be 4"); +static_assert( + offsetof(CompressedCopySubTextureCHROMIUM, source_id) == 8, + "offset of CompressedCopySubTextureCHROMIUM source_id should be 8"); +static_assert( + offsetof(CompressedCopySubTextureCHROMIUM, dest_id) == 12, + "offset of CompressedCopySubTextureCHROMIUM dest_id should be 12"); +static_assert( + offsetof(CompressedCopySubTextureCHROMIUM, xoffset) == 16, + "offset of CompressedCopySubTextureCHROMIUM xoffset should be 16"); +static_assert( + offsetof(CompressedCopySubTextureCHROMIUM, yoffset) == 20, + "offset of CompressedCopySubTextureCHROMIUM yoffset should be 20"); +static_assert(offsetof(CompressedCopySubTextureCHROMIUM, x) == 24, + "offset of CompressedCopySubTextureCHROMIUM x should be 24"); +static_assert(offsetof(CompressedCopySubTextureCHROMIUM, y) == 28, + "offset of CompressedCopySubTextureCHROMIUM y should be 28"); +static_assert(offsetof(CompressedCopySubTextureCHROMIUM, width) == 32, + "offset of CompressedCopySubTextureCHROMIUM width should be 32"); +static_assert(offsetof(CompressedCopySubTextureCHROMIUM, height) == 36, + "offset of CompressedCopySubTextureCHROMIUM height should be 36"); + struct DrawArraysInstancedANGLE { typedef DrawArraysInstancedANGLE ValueType; static const CommandId kCmdId = kDrawArraysInstancedANGLE; diff --git a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h index e362eab..28cf3c68 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h @@ -4234,6 +4234,30 @@ TEST_F(GLES2FormatTest, CompressedCopyTextureCHROMIUM) { CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); } +TEST_F(GLES2FormatTest, CompressedCopySubTextureCHROMIUM) { + cmds::CompressedCopySubTextureCHROMIUM& cmd = + *GetBufferAs(); + void* next_cmd = cmd.Set(&cmd, static_cast(11), + static_cast(12), static_cast(13), + static_cast(14), static_cast(15), + static_cast(16), static_cast(17), + static_cast(18), static_cast(19)); + EXPECT_EQ( + static_cast(cmds::CompressedCopySubTextureCHROMIUM::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast(11), cmd.target); + EXPECT_EQ(static_cast(12), cmd.source_id); + EXPECT_EQ(static_cast(13), cmd.dest_id); + EXPECT_EQ(static_cast(14), cmd.xoffset); + EXPECT_EQ(static_cast(15), cmd.yoffset); + EXPECT_EQ(static_cast(16), cmd.x); + EXPECT_EQ(static_cast(17), cmd.y); + EXPECT_EQ(static_cast(18), cmd.width); + EXPECT_EQ(static_cast(19), cmd.height); + CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); +} + TEST_F(GLES2FormatTest, DrawArraysInstancedANGLE) { cmds::DrawArraysInstancedANGLE& cmd = *GetBufferAs(); diff --git a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h index 448dc8e..540bd4e 100644 --- a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h @@ -271,55 +271,56 @@ OP(CopyTextureCHROMIUM) /* 512 */ \ OP(CopySubTextureCHROMIUM) /* 513 */ \ OP(CompressedCopyTextureCHROMIUM) /* 514 */ \ - OP(DrawArraysInstancedANGLE) /* 515 */ \ - OP(DrawElementsInstancedANGLE) /* 516 */ \ - OP(VertexAttribDivisorANGLE) /* 517 */ \ - OP(GenMailboxCHROMIUM) /* 518 */ \ - OP(ProduceTextureCHROMIUMImmediate) /* 519 */ \ - OP(ProduceTextureDirectCHROMIUMImmediate) /* 520 */ \ - OP(ConsumeTextureCHROMIUMImmediate) /* 521 */ \ - OP(CreateAndConsumeTextureCHROMIUMImmediate) /* 522 */ \ - OP(BindUniformLocationCHROMIUMBucket) /* 523 */ \ - OP(GenValuebuffersCHROMIUMImmediate) /* 524 */ \ - OP(DeleteValuebuffersCHROMIUMImmediate) /* 525 */ \ - OP(IsValuebufferCHROMIUM) /* 526 */ \ - OP(BindValuebufferCHROMIUM) /* 527 */ \ - OP(SubscribeValueCHROMIUM) /* 528 */ \ - OP(PopulateSubscribedValuesCHROMIUM) /* 529 */ \ - OP(UniformValuebufferCHROMIUM) /* 530 */ \ - OP(BindTexImage2DCHROMIUM) /* 531 */ \ - OP(ReleaseTexImage2DCHROMIUM) /* 532 */ \ - OP(TraceBeginCHROMIUM) /* 533 */ \ - OP(TraceEndCHROMIUM) /* 534 */ \ - OP(AsyncTexSubImage2DCHROMIUM) /* 535 */ \ - OP(AsyncTexImage2DCHROMIUM) /* 536 */ \ - OP(WaitAsyncTexImage2DCHROMIUM) /* 537 */ \ - OP(WaitAllAsyncTexImage2DCHROMIUM) /* 538 */ \ - OP(DiscardFramebufferEXTImmediate) /* 539 */ \ - OP(LoseContextCHROMIUM) /* 540 */ \ - OP(InsertSyncPointCHROMIUM) /* 541 */ \ - OP(WaitSyncPointCHROMIUM) /* 542 */ \ - OP(DrawBuffersEXTImmediate) /* 543 */ \ - OP(DiscardBackbufferCHROMIUM) /* 544 */ \ - OP(ScheduleOverlayPlaneCHROMIUM) /* 545 */ \ - OP(SwapInterval) /* 546 */ \ - OP(FlushDriverCachesCHROMIUM) /* 547 */ \ - OP(MatrixLoadfCHROMIUMImmediate) /* 548 */ \ - OP(MatrixLoadIdentityCHROMIUM) /* 549 */ \ - OP(GenPathsCHROMIUM) /* 550 */ \ - OP(DeletePathsCHROMIUM) /* 551 */ \ - OP(IsPathCHROMIUM) /* 552 */ \ - OP(PathCommandsCHROMIUM) /* 553 */ \ - OP(PathParameterfCHROMIUM) /* 554 */ \ - OP(PathParameteriCHROMIUM) /* 555 */ \ - OP(PathStencilFuncCHROMIUM) /* 556 */ \ - OP(StencilFillPathCHROMIUM) /* 557 */ \ - OP(StencilStrokePathCHROMIUM) /* 558 */ \ - OP(CoverFillPathCHROMIUM) /* 559 */ \ - OP(CoverStrokePathCHROMIUM) /* 560 */ \ - OP(StencilThenCoverFillPathCHROMIUM) /* 561 */ \ - OP(StencilThenCoverStrokePathCHROMIUM) /* 562 */ \ - OP(BlendBarrierKHR) /* 563 */ + OP(CompressedCopySubTextureCHROMIUM) /* 515 */ \ + OP(DrawArraysInstancedANGLE) /* 516 */ \ + OP(DrawElementsInstancedANGLE) /* 517 */ \ + OP(VertexAttribDivisorANGLE) /* 518 */ \ + OP(GenMailboxCHROMIUM) /* 519 */ \ + OP(ProduceTextureCHROMIUMImmediate) /* 520 */ \ + OP(ProduceTextureDirectCHROMIUMImmediate) /* 521 */ \ + OP(ConsumeTextureCHROMIUMImmediate) /* 522 */ \ + OP(CreateAndConsumeTextureCHROMIUMImmediate) /* 523 */ \ + OP(BindUniformLocationCHROMIUMBucket) /* 524 */ \ + OP(GenValuebuffersCHROMIUMImmediate) /* 525 */ \ + OP(DeleteValuebuffersCHROMIUMImmediate) /* 526 */ \ + OP(IsValuebufferCHROMIUM) /* 527 */ \ + OP(BindValuebufferCHROMIUM) /* 528 */ \ + OP(SubscribeValueCHROMIUM) /* 529 */ \ + OP(PopulateSubscribedValuesCHROMIUM) /* 530 */ \ + OP(UniformValuebufferCHROMIUM) /* 531 */ \ + OP(BindTexImage2DCHROMIUM) /* 532 */ \ + OP(ReleaseTexImage2DCHROMIUM) /* 533 */ \ + OP(TraceBeginCHROMIUM) /* 534 */ \ + OP(TraceEndCHROMIUM) /* 535 */ \ + OP(AsyncTexSubImage2DCHROMIUM) /* 536 */ \ + OP(AsyncTexImage2DCHROMIUM) /* 537 */ \ + OP(WaitAsyncTexImage2DCHROMIUM) /* 538 */ \ + OP(WaitAllAsyncTexImage2DCHROMIUM) /* 539 */ \ + OP(DiscardFramebufferEXTImmediate) /* 540 */ \ + OP(LoseContextCHROMIUM) /* 541 */ \ + OP(InsertSyncPointCHROMIUM) /* 542 */ \ + OP(WaitSyncPointCHROMIUM) /* 543 */ \ + OP(DrawBuffersEXTImmediate) /* 544 */ \ + OP(DiscardBackbufferCHROMIUM) /* 545 */ \ + OP(ScheduleOverlayPlaneCHROMIUM) /* 546 */ \ + OP(SwapInterval) /* 547 */ \ + OP(FlushDriverCachesCHROMIUM) /* 548 */ \ + OP(MatrixLoadfCHROMIUMImmediate) /* 549 */ \ + OP(MatrixLoadIdentityCHROMIUM) /* 550 */ \ + OP(GenPathsCHROMIUM) /* 551 */ \ + OP(DeletePathsCHROMIUM) /* 552 */ \ + OP(IsPathCHROMIUM) /* 553 */ \ + OP(PathCommandsCHROMIUM) /* 554 */ \ + OP(PathParameterfCHROMIUM) /* 555 */ \ + OP(PathParameteriCHROMIUM) /* 556 */ \ + OP(PathStencilFuncCHROMIUM) /* 557 */ \ + OP(StencilFillPathCHROMIUM) /* 558 */ \ + OP(StencilStrokePathCHROMIUM) /* 559 */ \ + OP(CoverFillPathCHROMIUM) /* 560 */ \ + OP(CoverStrokePathCHROMIUM) /* 561 */ \ + OP(StencilThenCoverFillPathCHROMIUM) /* 562 */ \ + OP(StencilThenCoverStrokePathCHROMIUM) /* 563 */ \ + OP(BlendBarrierKHR) /* 564 */ enum CommandId { kStartPoint = cmd::kLastCommonId, // All GLES2 commands start after this. 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 6199dfa..a987a39 100644 --- a/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc +++ b/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc @@ -471,8 +471,10 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTextureInternal( DCHECK(source_target == GL_TEXTURE_2D || source_target == GL_TEXTURE_RECTANGLE_ARB || source_target == GL_TEXTURE_EXTERNAL_OES); - DCHECK(xoffset >= 0 && xoffset + source_width <= dest_width); - DCHECK(yoffset >= 0 && yoffset + source_height <= dest_height); + DCHECK_GE(xoffset, 0); + DCHECK_LE(xoffset + width, dest_width); + DCHECK_GE(yoffset, 0); + DCHECK_LE(yoffset + height, dest_height); if (!initialized_) { DLOG(ERROR) << "CopyTextureCHROMIUM: Uninitialized manager."; return; diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index e918b2e..82e9052 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -1064,6 +1064,16 @@ class GLES2DecoderImpl : public GLES2Decoder, GLuint source_id, GLuint dest_id); + void DoCompressedCopySubTextureCHROMIUM(GLenum target, + GLuint source_id, + GLuint dest_id, + GLint xoffset, + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height); + // Wrapper for TexStorage2DEXT. void DoTexStorage2DEXT( GLenum target, @@ -12806,6 +12816,223 @@ void GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM(GLenum target, DoDidUseTexImageIfNeeded(source_texture, source_texture->target()); } +void GLES2DecoderImpl::DoCompressedCopySubTextureCHROMIUM(GLenum target, + GLuint source_id, + GLuint dest_id, + GLint xoffset, + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height) { + TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompressedCopySubTextureCHROMIUM"); + + TextureRef* source_texture_ref = GetTexture(source_id); + TextureRef* dest_texture_ref = GetTexture(dest_id); + Texture* source_texture = source_texture_ref->texture(); + Texture* dest_texture = dest_texture_ref->texture(); + int source_width = 0; + int source_height = 0; + gfx::GLImage* image = + source_texture->GetLevelImage(source_texture->target(), 0); + if (image) { + gfx::Size size = image->GetSize(); + source_width = size.width(); + source_height = size.height(); + if (source_width <= 0 || source_height <= 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedCopySubTextureCHROMIUM", + "invalid image size"); + return; + } + } else { + if (!source_texture->GetLevelSize(source_texture->target(), 0, + &source_width, &source_height, nullptr)) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedCopySubTextureCHROMIUM", + "source texture has no level 0"); + return; + } + + // Check that this type of texture is allowed. + if (!texture_manager()->ValidForTarget(source_texture->target(), 0, + source_width, source_height, 1)) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedCopySubTextureCHROMIUM", + "source texture bad dimensions"); + return; + } + } + + GLenum source_type = 0; + GLenum source_internal_format = 0; + source_texture->GetLevelType(source_texture->target(), 0, &source_type, + &source_internal_format); + if (!source_texture->ValidForTexture(source_texture->target(), 0, x, y, 0, + width, height, 1, source_type)) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedCopySubTextureCHROMIUM", + "source texture bad dimensions."); + return; + } + + GLenum dest_type = 0; + GLenum dest_internal_format = 0; + bool dest_level_defined = dest_texture->GetLevelType( + dest_texture->target(), 0, &dest_type, &dest_internal_format); + if (!dest_level_defined) { + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, + "glCompressedCopySubTextureCHROMIUM", + "destination texture is not defined"); + return; + } + if (!dest_texture->ValidForTexture(dest_texture->target(), 0, xoffset, + yoffset, 0, width, height, 1, dest_type)) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedCopySubTextureCHROMIUM", + "destination texture bad dimensions."); + return; + } + + if (!ValidateCompressedCopyTextureCHROMIUM( + "glCompressedCopySubTextureCHROMIUM", target, source_texture_ref, + dest_texture_ref)) { + return; + } + + if (!ValidateCompressedTexSubDimensions("glCompressedCopySubTextureCHROMIUM", + source_texture->target(), 0, x, y, 0, + width, height, 1, + source_internal_format, + source_texture) || + !ValidateCompressedTexSubDimensions("glCompressedCopySubTextureCHROMIUM", + dest_texture->target(), 0, + xoffset, yoffset, 0, width, height, 1, + dest_internal_format, + dest_texture)) { + return; + } + + // Defer initializing the CopyTextureCHROMIUMResourceManager until it is + // needed because it takes 10s of milliseconds to initialize. + if (!copy_texture_CHROMIUM_.get()) { + LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopySubTextureCHROMIUM"); + copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager()); + copy_texture_CHROMIUM_->Initialize(this); + RestoreCurrentFramebufferBindings(); + if (LOCAL_PEEK_GL_ERROR("glCompressedCopySubTextureCHROMIUM") != + GL_NO_ERROR) { + return; + } + } + + // Clear the source texture if necessary. + if (!texture_manager()->ClearTextureLevel(this, source_texture_ref, + source_texture->target(), 0)) { + LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCompressedCopySubTextureCHROMIUM", + "source texture dimensions too big"); + return; + } + + int dest_width = 0; + int dest_height = 0; + bool ok = dest_texture->GetLevelSize( + GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr); + DCHECK(ok); + if (xoffset != 0 || yoffset != 0 || width != dest_width || + height != dest_height) { + gfx::Rect cleared_rect; + if (CombineAdjacentRects(dest_texture->GetLevelClearedRect(target, 0), + gfx::Rect(xoffset, yoffset, width, height), + &cleared_rect)) { + DCHECK_GE(cleared_rect.size().GetArea(), + dest_texture->GetLevelClearedRect(target, 0).size().GetArea()); + texture_manager()->SetLevelClearedRect(dest_texture_ref, target, 0, + cleared_rect); + } else { + // Otherwise clear part of texture level that is not already cleared. + if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target, + 0)) { + LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, + "glCompressedCopySubTextureCHROMIUM", + "destination texture dimensions too big"); + return; + } + } + } else { + texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0, + true); + } + + ScopedTextureBinder binder( + &state_, dest_texture->service_id(), GL_TEXTURE_2D); + + ScopedModifyPixels modify(dest_texture_ref); + + // Try using GLImage::CopyTexSubImage when possible. + if (image) { + if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(xoffset, yoffset), + gfx::Rect(x, y, width, height))) { + return; + } + } + + TRACE_EVENT0( + "gpu", + "GLES2DecoderImpl::DoCompressedCopySubTextureCHROMIUM, fallback"); + + DoWillUseTexImageIfNeeded(source_texture, source_texture->target()); + + // As a fallback, copy into a non-compressed GL_RGBA texture. + if (dest_internal_format != GL_RGBA) { + // To preserve the contents of the original destination texture we must + // first copy the original destination texture to a temporary storage, then + // copy it back to the original destination texture. + GLuint tmp_service_id; + glGenTextures(1, &tmp_service_id); + DCHECK_NE(0u, tmp_service_id); + + glBindTexture(GL_TEXTURE_2D, tmp_service_id); + + LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM"); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dest_width, dest_height, 0, GL_RGBA, + GL_UNSIGNED_BYTE, NULL); + GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedCopySubTextureCHROMIUM"); + if (error != GL_NO_ERROR) + return; + + copy_texture_CHROMIUM_->DoCopyTexture( + this, dest_texture->target(), dest_texture->service_id(), + dest_internal_format, tmp_service_id, GL_RGBA, + dest_width, dest_height, false, false, false); + + // Redefine destination texture to use RGBA. + glBindTexture(GL_TEXTURE_2D, dest_texture->service_id()); + LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM"); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dest_width, dest_height, 0, GL_RGBA, + GL_UNSIGNED_BYTE, NULL); + error = LOCAL_PEEK_GL_ERROR("glCompressedCopySubTextureCHROMIUM"); + if (error != GL_NO_ERROR) + return; + + texture_manager()->SetLevelInfo( + dest_texture_ref, GL_TEXTURE_2D, 0, GL_RGBA, dest_width, dest_height, + 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(dest_width, dest_height)); + + copy_texture_CHROMIUM_->DoCopyTexture( + this, GL_TEXTURE_2D, tmp_service_id, GL_RGBA, + dest_texture->service_id(), GL_RGBA, + dest_width, dest_height, false, false, false); + + glDeleteTextures(1, &tmp_service_id); + } + + // TODO(hkuang): get the StreamTexture transform matrix in GPU process. + // crbug.com/226218. + copy_texture_CHROMIUM_->DoCopySubTexture( + this, source_texture->target(), source_texture->service_id(), + source_internal_format, dest_texture->service_id(), GL_RGBA, + xoffset, yoffset, x, y, width, height, dest_width, dest_height, + source_width, source_height, false, false, false); + + DoDidUseTexImageIfNeeded(source_texture, source_texture->target()); +} + static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) { switch (internalformat) { case GL_R8: diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h index c5de9f5..86c3c67 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h @@ -4555,6 +4555,37 @@ error::Error GLES2DecoderImpl::HandleCompressedCopyTextureCHROMIUM( return error::kNoError; } +error::Error GLES2DecoderImpl::HandleCompressedCopySubTextureCHROMIUM( + uint32_t immediate_data_size, + const void* cmd_data) { + const gles2::cmds::CompressedCopySubTextureCHROMIUM& c = + *static_cast( + cmd_data); + (void)c; + GLenum target = static_cast(c.target); + GLenum source_id = static_cast(c.source_id); + GLenum dest_id = static_cast(c.dest_id); + GLint xoffset = static_cast(c.xoffset); + GLint yoffset = static_cast(c.yoffset); + GLint x = static_cast(c.x); + GLint y = static_cast(c.y); + GLsizei width = static_cast(c.width); + GLsizei height = static_cast(c.height); + if (width < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedCopySubTextureCHROMIUM", + "width < 0"); + return error::kNoError; + } + if (height < 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedCopySubTextureCHROMIUM", + "height < 0"); + return error::kNoError; + } + DoCompressedCopySubTextureCHROMIUM(target, source_id, dest_id, xoffset, + yoffset, x, y, width, height); + return error::kNoError; +} + error::Error GLES2DecoderImpl::HandleProduceTextureCHROMIUMImmediate( uint32_t immediate_data_size, const void* cmd_data) { diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h index 997d425..3f4f390 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h @@ -415,6 +415,7 @@ TEST_P(GLES2DecoderTest3, PopGroupMarkerEXTValidArgs) { // TODO(gman): CopyTextureCHROMIUM // TODO(gman): CopySubTextureCHROMIUM // TODO(gman): CompressedCopyTextureCHROMIUM +// TODO(gman): CompressedCopySubTextureCHROMIUM // TODO(gman): DrawArraysInstancedANGLE // TODO(gman): DrawElementsInstancedANGLE // TODO(gman): VertexAttribDivisorANGLE diff --git a/gpu/command_buffer/tests/gl_compressed_copy_texture_CHROMIUM_unittest.cc b/gpu/command_buffer/tests/gl_compressed_copy_texture_CHROMIUM_unittest.cc index 86b07cd..d50189d 100644 --- a/gpu/command_buffer/tests/gl_compressed_copy_texture_CHROMIUM_unittest.cc +++ b/gpu/command_buffer/tests/gl_compressed_copy_texture_CHROMIUM_unittest.cc @@ -22,6 +22,12 @@ namespace gpu { namespace { +enum CopyType { TexImage, TexSubImage }; +const CopyType kCopyTypes[] = { + TexImage, + TexSubImage, +}; + const uint8 kCompressedImageColor[4] = { 255u, 0u, 0u, 255u }; // Single compressed ATC block of source pixels all set to: @@ -40,6 +46,15 @@ const uint8 kCompressedImageATCIA[16] = { const uint8 kCompressedImageDXT1[8] = { 0x00, 0xf8, 0x00, 0xf8, 0xaa, 0xaa, 0xaa, 0xaa }; +// Four compressed DXT1 blocks solidly colored in red, green, blue and black: +// [R][G] +// [B][b] +const uint8 kCompressedImageDXT1RGB[32] = { + 0x0, 0xf8, 0x0, 0xf8, 0xaa, 0xaa, 0xaa, 0xaa, + 0xe0, 0x7, 0xe0, 0x7, 0xaa, 0xaa, 0xaa, 0xaa, + 0x1f, 0x0, 0x1f, 0x0, 0xaa, 0xaa, 0xaa, 0xaa, + 0x0, 0x0, 0x0, 0x0, 0xaa, 0xaa, 0xaa, 0xaa }; + // Single compressed DXT5 block of source pixels all set to: // kCompressedImageColor. const uint8 kCompressedImageDXT5[16] = { @@ -51,6 +66,17 @@ const uint8 kCompressedImageDXT5[16] = { const uint8 kCompressedImageETC1[8] = { 0x0, 0x0, 0xf8, 0x2, 0xff, 0xff, 0x0, 0x0 }; +// Single block of zeroes, used for texture pre-allocation. +const uint8 kInvalidCompressedImage[8] = { + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; + +// Four blocks of zeroes, used for texture pre-allocation. +const uint8 kInvalidCompressedImageLarge[32] = { + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; + void glEnableDisable(GLint param, GLboolean value) { if (value) glEnable(param); @@ -62,7 +88,8 @@ void glEnableDisable(GLint param, GLboolean value) { // A collection of tests that exercise the GL_CHROMIUM_copy_texture extension. class GLCompressedCopyTextureCHROMIUMTest - : public testing::Test { + : public testing::Test, + public ::testing::WithParamInterface { protected: void SetUp() override { gl_.Initialize(GLManager::Options()); @@ -100,14 +127,20 @@ class GLCompressedCopyTextureCHROMIUMTest GLuint framebuffer_id_; }; +INSTANTIATE_TEST_CASE_P(CopyType, + GLCompressedCopyTextureCHROMIUMTest, + ::testing::ValuesIn(kCopyTypes)); + // Test to ensure that the basic functionality of the extension works. -TEST_F(GLCompressedCopyTextureCHROMIUMTest, Basic) { +TEST_P(GLCompressedCopyTextureCHROMIUMTest, Basic) { if (!GLTestHelper::HasExtension("GL_EXT_texture_compression_dxt1")) { LOG(INFO) << "GL_EXT_texture_compression_dxt1 not supported. Skipping test..."; return; } + CopyType copy_type = GetParam(); + glBindTexture(GL_TEXTURE_2D, textures_[0]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); @@ -123,7 +156,17 @@ TEST_F(GLCompressedCopyTextureCHROMIUMTest, Basic) { glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glCompressedCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1]); + if (copy_type == TexImage) { + glCompressedCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1]); + } else { + glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, + 4, 4, 0, + sizeof(kInvalidCompressedImage), + kInvalidCompressedImage); + + glCompressedCopySubTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], + textures_[1], 0, 0, 0, 0, 4, 4); + } EXPECT_TRUE(glGetError() == GL_NO_ERROR); // Load shader program. @@ -152,7 +195,9 @@ TEST_F(GLCompressedCopyTextureCHROMIUMTest, Basic) { EXPECT_TRUE(GL_NO_ERROR == glGetError()); } -TEST_F(GLCompressedCopyTextureCHROMIUMTest, InternalFormat) { +TEST_P(GLCompressedCopyTextureCHROMIUMTest, InternalFormat) { + CopyType copy_type = GetParam(); + struct Image { const GLint format; const uint8* data; @@ -163,8 +208,9 @@ TEST_F(GLCompressedCopyTextureCHROMIUMTest, InternalFormat) { }; ScopedVector supported_formats; - if (GLTestHelper::HasExtension("GL_AMD_compressed_ATC_texture") || - GLTestHelper::HasExtension("GL_ATI_texture_compression_atitc")) { + if ((GLTestHelper::HasExtension("GL_AMD_compressed_ATC_texture") || + GLTestHelper::HasExtension("GL_ATI_texture_compression_atitc")) && + copy_type != TexSubImage) { supported_formats.push_back(new Image( GL_ATC_RGB_AMD, kCompressedImageATC, @@ -187,7 +233,8 @@ TEST_F(GLCompressedCopyTextureCHROMIUMTest, InternalFormat) { kCompressedImageDXT5, sizeof(kCompressedImageDXT5))); } - if (GLTestHelper::HasExtension("GL_OES_compressed_ETC1_RGB8_texture")) { + if (GLTestHelper::HasExtension("GL_OES_compressed_ETC1_RGB8_texture") && + copy_type != TexSubImage) { supported_formats.push_back(new Image( GL_ETC1_RGB8_OES, kCompressedImageETC1, @@ -209,18 +256,30 @@ TEST_F(GLCompressedCopyTextureCHROMIUMTest, InternalFormat) { glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glCompressedCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1]); + if (copy_type == TexImage) { + glCompressedCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], + textures_[1]); + } else { + glCompressedTexImage2D(GL_TEXTURE_2D, 0, image->format, 4, 4, 0, + sizeof(kInvalidCompressedImage), + kInvalidCompressedImage); + + glCompressedCopySubTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], + textures_[1], 0, 0, 0, 0, 4, 4); + } EXPECT_TRUE(GL_NO_ERROR == glGetError()); } } -TEST_F(GLCompressedCopyTextureCHROMIUMTest, InternalFormatNotSupported) { +TEST_P(GLCompressedCopyTextureCHROMIUMTest, InternalFormatNotSupported) { if (!GLTestHelper::HasExtension("GL_EXT_texture_compression_dxt1")) { LOG(INFO) << "GL_EXT_texture_compression_dxt1 not supported. Skipping test..."; return; } + CopyType copy_type = GetParam(); + const uint8 kUncompressedPixels[1 * 4] = { 255u, 0u, 0u, 255u }; glBindTexture(GL_TEXTURE_2D, textures_[0]); @@ -239,19 +298,29 @@ TEST_F(GLCompressedCopyTextureCHROMIUMTest, InternalFormatNotSupported) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // Check that the GL_RGBA format reports an error. - glCompressedCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1]); + if (copy_type == TexImage) { + glCompressedCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1]); + } else { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, + kUncompressedPixels); + + glCompressedCopySubTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], + textures_[1], 0, 0, 0, 0, 1, 1); + } EXPECT_TRUE(GL_INVALID_OPERATION == glGetError()); } // Validate that some basic GL state is not touched upon execution of // the extension. -TEST_F(GLCompressedCopyTextureCHROMIUMTest, BasicStatePreservation) { +TEST_P(GLCompressedCopyTextureCHROMIUMTest, BasicStatePreservation) { if (!GLTestHelper::HasExtension("GL_EXT_texture_compression_dxt1")) { LOG(INFO) << "GL_EXT_texture_compression_dxt1 not supported. Skipping test..."; return; } + CopyType copy_type = GetParam(); + glBindTexture(GL_TEXTURE_2D, textures_[0]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); @@ -268,6 +337,13 @@ TEST_F(GLCompressedCopyTextureCHROMIUMTest, BasicStatePreservation) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + if (copy_type == TexSubImage) { + glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, + 4, 4, 0, + sizeof(kInvalidCompressedImage), + kInvalidCompressedImage); + } + GLboolean reference_settings[2] = { GL_TRUE, GL_FALSE }; for (int x = 0; x < 2; ++x) { GLboolean setting = reference_settings[x]; @@ -281,7 +357,13 @@ TEST_F(GLCompressedCopyTextureCHROMIUMTest, BasicStatePreservation) { glActiveTexture(GL_TEXTURE1 + x); - glCompressedCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1]); + if (copy_type == TexImage) { + glCompressedCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], + textures_[1]); + } else { + glCompressedCopySubTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], + textures_[1], 0, 0, 0, 0, 4, 4); + } EXPECT_TRUE(glGetError() == GL_NO_ERROR); EXPECT_EQ(setting, glIsEnabled(GL_DEPTH_TEST)); @@ -311,13 +393,15 @@ TEST_F(GLCompressedCopyTextureCHROMIUMTest, BasicStatePreservation) { // Verify that invocation of the extension does not modify the bound // texture state. -TEST_F(GLCompressedCopyTextureCHROMIUMTest, TextureStatePreserved) { +TEST_P(GLCompressedCopyTextureCHROMIUMTest, TextureStatePreserved) { if (!GLTestHelper::HasExtension("GL_EXT_texture_compression_dxt1")) { LOG(INFO) << "GL_EXT_texture_compression_dxt1 not supported. Skipping test..."; return; } + CopyType copy_type = GetParam(); + glBindTexture(GL_TEXTURE_2D, textures_[0]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); @@ -334,6 +418,13 @@ TEST_F(GLCompressedCopyTextureCHROMIUMTest, TextureStatePreserved) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + if (copy_type == TexSubImage) { + glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, + 4, 4, 0, + sizeof(kInvalidCompressedImage), + kInvalidCompressedImage); + } + GLuint texture_ids[2]; glGenTextures(2, texture_ids); @@ -343,7 +434,12 @@ TEST_F(GLCompressedCopyTextureCHROMIUMTest, TextureStatePreserved) { glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, texture_ids[1]); - glCompressedCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1]); + if (copy_type == TexImage) { + glCompressedCopyTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1]); + } else { + glCompressedCopySubTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], + textures_[1], 0, 0, 0, 0, 4, 4); + } EXPECT_TRUE(GL_NO_ERROR == glGetError()); GLint active_texture = 0; @@ -366,4 +462,253 @@ TEST_F(GLCompressedCopyTextureCHROMIUMTest, TextureStatePreserved) { EXPECT_TRUE(GL_NO_ERROR == glGetError()); } +TEST_F(GLCompressedCopyTextureCHROMIUMTest, CopySubTextureDimension) { + if (!GLTestHelper::HasExtension("GL_EXT_texture_compression_dxt1")) { + LOG(INFO) << + "GL_EXT_texture_compression_dxt1 not supported. Skipping test..."; + return; + } + + glBindTexture(GL_TEXTURE_2D, textures_[0]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, + 8, 8, 0, + sizeof(kCompressedImageDXT1RGB), + kCompressedImageDXT1RGB); + EXPECT_TRUE(glGetError() == GL_NO_ERROR); + + glBindTexture(GL_TEXTURE_2D, textures_[1]); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, + 8, 8, 0, + sizeof(kInvalidCompressedImageLarge), + kInvalidCompressedImageLarge); + + glCompressedCopySubTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], + textures_[1], 4, 4, 0, 0, 4, 4); + EXPECT_TRUE(GL_NO_ERROR == glGetError()); + + // Reset the destination texture as it might have been converted to RGBA. + glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, + 8, 8, 0, + sizeof(kInvalidCompressedImageLarge), + kInvalidCompressedImageLarge); + + // xoffset < 0 + glCompressedCopySubTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], + -4, 4, 0, 0, 4, 4); + EXPECT_TRUE(glGetError() == GL_INVALID_VALUE); + + // x < 0 + glCompressedCopySubTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], + 4, 4, -4, 0, 4, 4); + EXPECT_TRUE(glGetError() == GL_INVALID_VALUE); + + // xoffset + width > dest_width + glCompressedCopySubTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], + 8, 8, 0, 0, 4, 4); + EXPECT_TRUE(glGetError() == GL_INVALID_VALUE); + + // x + width > source_width + glCompressedCopySubTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], + 0, 0, 8, 8, 4, 4); + EXPECT_TRUE(glGetError() == GL_INVALID_VALUE); + + // xoffset not within block-boundary + glCompressedCopySubTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], + 3, 0, 0, 0, 4, 4); + EXPECT_TRUE(glGetError() == GL_INVALID_OPERATION); + + // x not within block-boundary + glCompressedCopySubTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], textures_[1], + 0, 0, 3, 0, 4, 4); + EXPECT_TRUE(glGetError() == GL_INVALID_OPERATION); +} + +TEST_F(GLCompressedCopyTextureCHROMIUMTest, CopySubTextureOffset) { + if (!GLTestHelper::HasExtension("GL_EXT_texture_compression_dxt1")) { + LOG(INFO) << + "GL_EXT_texture_compression_dxt1 not supported. Skipping test..."; + return; + } + + glBindTexture(GL_TEXTURE_2D, textures_[0]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, + 8, 8, 0, + sizeof(kCompressedImageDXT1RGB), + kCompressedImageDXT1RGB); + EXPECT_TRUE(glGetError() == GL_NO_ERROR); + + glBindTexture(GL_TEXTURE_2D, textures_[1]); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, + 8, 8, 0, + sizeof(kInvalidCompressedImageLarge), + kInvalidCompressedImageLarge); + + // Load shader program. + GLuint program = LoadProgram(); + ASSERT_NE(program, 0u); + GLint position_loc = glGetAttribLocation(program, "a_position"); + GLint texture_loc = glGetUniformLocation(program, "u_texture"); + ASSERT_NE(position_loc, -1); + ASSERT_NE(texture_loc, -1); + glUseProgram(program); + + // Load geometry. + GLuint vbo = GLTestHelper::SetupUnitQuad(position_loc); + ASSERT_NE(vbo, 0u); + + // Load texture. + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, textures_[1]); + glUniform1i(texture_loc, 0); + + const uint8 kBlack[1 * 4] = {0u, 0u, 0u, 255u}; + const uint8 kRed[1 * 4] = {255u, 0u, 0u, 255u}; + const uint8 kGreen[1 * 4] = {0u, 255u, 0u, 255u}; + const uint8 kBlue[1 * 4] = {0u, 0u, 255u, 255u}; + + // Copy each block one by one in a clockwise fashion. Note that we reset the + // destination texture after each copy operation. That's because on some + // platforms we might fallback into replacing the compressed destination + // texture with an uncompressed one. + + // Move blue block up. + glCompressedCopySubTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], + textures_[1], 0, 0, 0, 4, 4, 4); + EXPECT_TRUE(glGetError() == GL_NO_ERROR); + + glDrawArrays(GL_TRIANGLES, 0, 6); + glFlush(); + GLTestHelper::CheckPixels(0, 0, 2, 2, 0, kBlue); + + glBindTexture(GL_TEXTURE_2D, textures_[1]); + glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, + 8, 8, 0, + sizeof(kInvalidCompressedImageLarge), + kInvalidCompressedImageLarge); + + // Move red block right. + glCompressedCopySubTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], + textures_[1], 4, 0, 0, 0, 4, 4); + EXPECT_TRUE(glGetError() == GL_NO_ERROR); + + glDrawArrays(GL_TRIANGLES, 0, 6); + glFlush(); + GLTestHelper::CheckPixels(2, 0, 2, 2, 0, kRed); + + glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, + 8, 8, 0, + sizeof(kInvalidCompressedImageLarge), + kInvalidCompressedImageLarge); + + // Move green block down. + glCompressedCopySubTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], + textures_[1], 4, 4, 4, 0, 4, 4); + EXPECT_TRUE(glGetError() == GL_NO_ERROR); + + glDrawArrays(GL_TRIANGLES, 0, 6); + glFlush(); + GLTestHelper::CheckPixels(2, 2, 2, 2, 0, kGreen); + + glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, + 8, 8, 0, + sizeof(kInvalidCompressedImageLarge), + kInvalidCompressedImageLarge); + + // Move black block left. + glCompressedCopySubTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], + textures_[1], 0, 4, 4, 4, 4, 4); + EXPECT_TRUE(glGetError() == GL_NO_ERROR); + + glDrawArrays(GL_TRIANGLES, 0, 6); + glFlush(); + GLTestHelper::CheckPixels(0, 2, 2, 2, 0, kBlack); + + EXPECT_TRUE(GL_NO_ERROR == glGetError()); +} + +TEST_F(GLCompressedCopyTextureCHROMIUMTest, CopySubTexturePreservation) { + if (!GLTestHelper::HasExtension("GL_EXT_texture_compression_dxt1")) { + LOG(INFO) << + "GL_EXT_texture_compression_dxt1 not supported. Skipping test..."; + return; + } + + glBindTexture(GL_TEXTURE_2D, textures_[0]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, + 4, 4, 0, + sizeof(kCompressedImageDXT1), + kCompressedImageDXT1); + EXPECT_TRUE(glGetError() == GL_NO_ERROR); + + glBindTexture(GL_TEXTURE_2D, textures_[1]); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, + 8, 8, 0, + sizeof(kCompressedImageDXT1RGB), + kCompressedImageDXT1RGB); + + // Copy entire first texture into the second, replacing the green block: + // [R][R] + // [B][b] + glCompressedCopySubTextureCHROMIUM(GL_TEXTURE_2D, textures_[0], + textures_[1], 4, 0, 0, 0, 4, 4); + EXPECT_TRUE(glGetError() == GL_NO_ERROR); + + // Load shader program. + GLuint program = LoadProgram(); + ASSERT_NE(program, 0u); + GLint position_loc = glGetAttribLocation(program, "a_position"); + GLint texture_loc = glGetUniformLocation(program, "u_texture"); + ASSERT_NE(position_loc, -1); + ASSERT_NE(texture_loc, -1); + glUseProgram(program); + + // Load geometry. + GLuint vbo = GLTestHelper::SetupUnitQuad(position_loc); + ASSERT_NE(vbo, 0u); + + // Load texture. + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, textures_[1]); + glUniform1i(texture_loc, 0); + + // Draw. + glDrawArrays(GL_TRIANGLES, 0, 6); + glFlush(); + + const uint8 kBlack[1 * 4] = {0u, 0u, 0u, 255u}; + const uint8 kRed[1 * 4] = {255u, 0u, 0u, 255u}; + const uint8 kBlue[1 * 4] = {0u, 0u, 255u, 255u}; + + // Note that while destination texture is 8 x 8 pixels the viewport is only + // 4 x 4. + GLTestHelper::CheckPixels(0, 0, 4, 2, 0, kRed); + GLTestHelper::CheckPixels(0, 2, 2, 2, 0, kBlue); + GLTestHelper::CheckPixels(2, 2, 2, 2, 0, kBlack); + EXPECT_TRUE(GL_NO_ERROR == glGetError()); +} + } // namespace gpu -- cgit v1.1