diff options
author | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-31 17:10:43 +0000 |
---|---|---|
committer | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-31 17:10:43 +0000 |
commit | cadde4a696d15d4d5cb6b61c346d98ac2a8b1993 (patch) | |
tree | a237ce64bc5616f633e8fb265d7dc07534465162 /gpu | |
parent | fc586c7e48d90dac7963906bf34c8f6382b55846 (diff) | |
download | chromium_src-cadde4a696d15d4d5cb6b61c346d98ac2a8b1993.zip chromium_src-cadde4a696d15d4d5cb6b61c346d98ac2a8b1993.tar.gz chromium_src-cadde4a696d15d4d5cb6b61c346d98ac2a8b1993.tar.bz2 |
Adds range checking to glTexSubImage2D, glCompressedTexSubImage2D,
glCopyTexSubImage2D. Adds missing range tracking for glCopyTexImage2D
Also makes glTexImage2D, glCopyTexImage2D and glCompressedTexImage2D
check for errors.
TEST=some unit test and ran conformance tests.
BUG=none
Review URL: http://codereview.chromium.org/3046033
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@54452 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
-rwxr-xr-x | gpu/command_buffer/build_gles2_cmd_buffer.py | 12 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder.cc | 176 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder_autogen.h | 12 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc | 131 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc | 22 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc | 6 | ||||
-rw-r--r-- | gpu/command_buffer/service/texture_manager.cc | 49 | ||||
-rw-r--r-- | gpu/command_buffer/service/texture_manager.h | 22 | ||||
-rw-r--r-- | gpu/command_buffer/service/texture_manager_unittest.cc | 64 |
9 files changed, 473 insertions, 21 deletions
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index ef4a004..58c3025 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py @@ -1056,6 +1056,13 @@ _FUNCTION_INFO = { 'CompressedTexSubImage2D': { 'type': 'Data', 'bucket': True, + 'decoder_func': 'DoCompressedTexSubImage2D', + }, + 'CopyTexImage2D': { + 'decoder_func': 'DoCopyTexImage2D', + }, + 'CopyTexSubImage2D': { + 'decoder_func': 'DoCopyTexSubImage2D', }, 'CreateProgram': {'type': 'Create'}, 'CreateShader': {'type': 'Create'}, @@ -1388,7 +1395,10 @@ _FUNCTION_INFO = { 'count': 1, 'decoder_func': 'DoTexParameteriv', }, - 'TexSubImage2D': {'type': 'Data'}, + 'TexSubImage2D': { + 'type': 'Data', + 'decoder_func': 'DoTexSubImage2D', + }, 'Uniform1f': {'type': 'PUTXn', 'data_type': 'GLfloat', 'count': 1}, 'Uniform1fv': { 'type': 'PUTn', diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index fa26f20..d75ce4b 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -632,6 +632,40 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, GLsizei image_size, const void* data); + // Wrapper for CompressedTexSubImage2D. + void DoCompressedTexSubImage2D( + GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLsizei width, + GLsizei height, + GLenum format, + GLsizei imageSize, + const void * data); + + // Wrapper for CopyTexImage2D. + void DoCopyTexImage2D( + GLenum target, + GLint level, + GLenum internal_format, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLint border); + + // Wrapper for CopyTexSubImage2D. + void DoCopyTexSubImage2D( + GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height); + // Wrapper for TexImage2D commands. error::Error DoTexImage2D( GLenum target, @@ -645,6 +679,18 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, const void* pixels, uint32 pixels_size); + // Wrapper for TexSubImage2D. + void DoTexSubImage2D( + GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLsizei width, + GLsizei height, + GLenum format, + GLenum type, + const void * data); + // Creates a ProgramInfo for the given program. void CreateProgramInfo(GLuint client_id, GLuint service_id) { program_manager()->CreateProgramInfo(client_id, service_id); @@ -4193,10 +4239,14 @@ error::Error GLES2DecoderImpl::DoCompressedTexImage2D( memset(zero.get(), 0, image_size); data = zero.get(); } - texture_manager()->SetLevelInfo( - info, target, level, internal_format, width, height, 1, border, 0, 0); + CopyRealGLErrorsToWrapper(); glCompressedTexImage2D( target, level, internal_format, width, height, border, image_size, data); + GLenum error = glGetError(); + if (error == GL_NO_ERROR) { + texture_manager()->SetLevelInfo( + info, target, level, internal_format, width, height, 1, border, 0, 0); + } return error::kNoError; } @@ -4291,7 +4341,7 @@ error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket( SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: imageSize < 0"); return error::kNoError; } - glCompressedTexSubImage2D( + DoCompressedTexSubImage2D( target, level, xoffset, yoffset, width, height, format, imageSize, data); return error::kNoError; } @@ -4345,8 +4395,6 @@ error::Error GLES2DecoderImpl::DoTexImage2D( memset(zero.get(), 0, pixels_size); pixels = zero.get(); } - texture_manager()->SetLevelInfo(info, - target, level, internal_format, width, height, 1, border, format, type); #if !defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2) if (format == GL_BGRA_EXT && internal_format == GL_BGRA_EXT) { internal_format = GL_RGBA; @@ -4364,9 +4412,15 @@ error::Error GLES2DecoderImpl::DoTexImage2D( } } #endif + CopyRealGLErrorsToWrapper(); glTexImage2D( target, level, internal_format, width, height, border, format, type, pixels); + GLenum error = glGetError(); + if (error == GL_NO_ERROR) { + texture_manager()->SetLevelInfo(info, + target, level, internal_format, width, height, 1, border, format, type); + } return error::kNoError; } @@ -4426,6 +4480,118 @@ error::Error GLES2DecoderImpl::HandleTexImage2DImmediate( return error::kNoError; } +void GLES2DecoderImpl::DoCompressedTexSubImage2D( + GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLsizei width, + GLsizei height, + GLenum format, + GLsizei image_size, + const void * data) { + TextureManager::TextureInfo* info = GetTextureInfoForTarget(target); + if (!info) { + SetGLError(GL_INVALID_OPERATION, + "glCompressedTexSubImage2D: unknown texture for target"); + return; + } + GLenum type = 0; + GLenum dummy = 0; + if (!info->GetLevelType(target, level, &type, &dummy) || + !info->ValidForTexture( + target, level, xoffset, yoffset, width, height, format, type)) { + SetGLError(GL_INVALID_VALUE, + "glCompressdTexSubImage2D: bad dimensions."); + return; + } + glCompressedTexSubImage2D( + target, level, xoffset, yoffset, width, height, format, image_size, data); +} + +void GLES2DecoderImpl::DoCopyTexImage2D( + GLenum target, + GLint level, + GLenum internal_format, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLint border) { + TextureManager::TextureInfo* info = GetTextureInfoForTarget(target); + if (!info) { + SetGLError(GL_INVALID_OPERATION, + "glCopyTexImage2D: unknown texture for target"); + return; + } + // TODO(gman): Need to check that current FBO is compatible with + // internal_format. + // TODO(gman): Type needs to match format for FBO. + CopyRealGLErrorsToWrapper(); + glCopyTexImage2D(target, level, internal_format, x, y, width, height, border); + GLenum error = glGetError(); + if (error == GL_NO_ERROR) { + texture_manager()->SetLevelInfo( + info, target, level, internal_format, width, height, 1, border, + internal_format, GL_UNSIGNED_BYTE); + } +} + +void GLES2DecoderImpl::DoCopyTexSubImage2D( + GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height) { + TextureManager::TextureInfo* info = GetTextureInfoForTarget(target); + if (!info) { + SetGLError(GL_INVALID_OPERATION, + "glCopyTexSubImage2D: unknown texture for target"); + return; + } + GLenum type = 0; + GLenum format = 0; + if (!info->GetLevelType(target, level, &type, &format) || + !info->ValidForTexture( + target, level, xoffset, yoffset, width, height, format, type)) { + SetGLError(GL_INVALID_VALUE, + "glCopyTexSubImage2D: bad dimensions."); + return; + } + // TODO(gman): Should we check that x, y, width, and height are in range + // for current FBO? + glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); +} + +void GLES2DecoderImpl::DoTexSubImage2D( + GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLsizei width, + GLsizei height, + GLenum format, + GLenum type, + const void * data) { + TextureManager::TextureInfo* info = GetTextureInfoForTarget(target); + if (!info) { + SetGLError(GL_INVALID_OPERATION, + "glTexSubImage2D: unknown texture for target"); + return; + } + if (!info->ValidForTexture( + target, level, xoffset, yoffset, width, height, format, type)) { + SetGLError(GL_INVALID_VALUE, + "glTexSubImage2D: bad dimensions."); + return; + } + glTexSubImage2D( + target, level, xoffset, yoffset, width, height, format, type, data); +} + error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv( uint32 immediate_data_size, const gles2::GetVertexAttribPointerv& c) { GLuint index = static_cast<GLuint>(c.index); diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h index c7aca37..874bd8a 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h @@ -304,7 +304,7 @@ error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2D( if (data == NULL) { return error::kOutOfBounds; } - glCompressedTexSubImage2D( + DoCompressedTexSubImage2D( target, level, xoffset, yoffset, width, height, format, imageSize, data); return error::kNoError; } @@ -348,7 +348,7 @@ error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DImmediate( if (data == NULL) { return error::kOutOfBounds; } - glCompressedTexSubImage2D( + DoCompressedTexSubImage2D( target, level, xoffset, yoffset, width, height, format, imageSize, data); return error::kNoError; } @@ -375,7 +375,7 @@ error::Error GLES2DecoderImpl::HandleCopyTexImage2D( SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D: height < 0"); return error::kNoError; } - glCopyTexImage2D(target, level, internalformat, x, y, width, height, border); + DoCopyTexImage2D(target, level, internalformat, x, y, width, height, border); return error::kNoError; } @@ -401,7 +401,7 @@ error::Error GLES2DecoderImpl::HandleCopyTexSubImage2D( SetGLError(GL_INVALID_VALUE, "glCopyTexSubImage2D: height < 0"); return error::kNoError; } - glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); + DoCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); return error::kNoError; } @@ -1852,7 +1852,7 @@ error::Error GLES2DecoderImpl::HandleTexSubImage2D( if (pixels == NULL) { return error::kOutOfBounds; } - glTexSubImage2D( + DoTexSubImage2D( target, level, xoffset, yoffset, width, height, format, type, pixels); return error::kNoError; } @@ -1897,7 +1897,7 @@ error::Error GLES2DecoderImpl::HandleTexSubImage2DImmediate( if (pixels == NULL) { return error::kOutOfBounds; } - glTexSubImage2D( + DoTexSubImage2D( target, level, xoffset, yoffset, width, height, format, type, pixels); return error::kNoError; } diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc index e77b78f..e914ee2 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc @@ -2160,6 +2160,133 @@ TEST_F(GLES2DecoderTest, DeleteSharedIdsBadArgs) { EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); } +TEST_F(GLES2DecoderTest, TexSubImage2DValidArgs) { + const int kWidth = 16; + const int kHeight = 8; + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + DoTexImage2D( + GL_TEXTURE_2D, 1, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, + 0, 0); + EXPECT_CALL(*gl_, TexSubImage2D( + GL_TEXTURE_2D, 1, 0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, + shared_memory_address_)) + .Times(1) + .RetiresOnSaturation(); + TexSubImage2D cmd; + cmd.Init(GL_TEXTURE_2D, 1, 0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, + kSharedMemoryId, kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_F(GLES2DecoderTest, TexSubImage2DBadArgs) { + const int kWidth = 16; + const int kHeight = 8; + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + DoTexImage2D( + GL_TEXTURE_2D, 1, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, + 0, 0); + TexSubImage2D cmd; + cmd.Init(GL_TEXTURE0, 1, 0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, + kSharedMemoryId, kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); + cmd.Init(GL_TEXTURE_2D, 1, 0, 0, kWidth, kHeight, GL_TRUE, GL_UNSIGNED_BYTE, + kSharedMemoryId, kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); + cmd.Init(GL_TEXTURE_2D, 1, 0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_INT, + kSharedMemoryId, kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); + cmd.Init(GL_TEXTURE_2D, 1, -1, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, + kSharedMemoryId, kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + cmd.Init(GL_TEXTURE_2D, 1, 1, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, + kSharedMemoryId, kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + cmd.Init(GL_TEXTURE_2D, 1, 0, -1, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, + kSharedMemoryId, kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + cmd.Init(GL_TEXTURE_2D, 1, 0, 1, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, + kSharedMemoryId, kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + cmd.Init(GL_TEXTURE_2D, 1, 0, 0, kWidth + 1, kHeight, GL_RGBA, + GL_UNSIGNED_BYTE, kSharedMemoryId, kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + cmd.Init(GL_TEXTURE_2D, 1, 0, 0, kWidth, kHeight + 1, GL_RGBA, + GL_UNSIGNED_BYTE, kSharedMemoryId, kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + cmd.Init(GL_TEXTURE_2D, 1, 0, 0, kWidth, kHeight, GL_RGB, GL_UNSIGNED_BYTE, + kSharedMemoryId, kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + cmd.Init(GL_TEXTURE_2D, 1, 0, 0, kWidth, kHeight, GL_RGBA, + GL_UNSIGNED_SHORT_4_4_4_4, kSharedMemoryId, kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + cmd.Init(GL_TEXTURE_2D, 1, 0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, + kInvalidSharedMemoryId, kSharedMemoryOffset); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); + cmd.Init(GL_TEXTURE_2D, 1, 0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, + kSharedMemoryId, kInvalidSharedMemoryOffset); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); +} + +TEST_F(GLES2DecoderTest, CopyTexSubImage2DValidArgs) { + const int kWidth = 16; + const int kHeight = 8; + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + DoTexImage2D( + GL_TEXTURE_2D, 1, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, + 0, 0); + EXPECT_CALL(*gl_, CopyTexSubImage2D( + GL_TEXTURE_2D, 1, 0, 0, 0, 0, kWidth, kHeight)) + .Times(1) + .RetiresOnSaturation(); + CopyTexSubImage2D cmd; + cmd.Init(GL_TEXTURE_2D, 1, 0, 0, 0, 0, kWidth, kHeight); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_F(GLES2DecoderTest, CopyTexSubImage2DBadArgs) { + const int kWidth = 16; + const int kHeight = 8; + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + DoTexImage2D( + GL_TEXTURE_2D, 1, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, + 0, 0); + CopyTexSubImage2D cmd; + cmd.Init(GL_TEXTURE0, 1, 0, 0, 0, 0, kWidth, kHeight); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); + cmd.Init(GL_TEXTURE_2D, 1, -1, 0, 0, 0, kWidth, kHeight); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + cmd.Init(GL_TEXTURE_2D, 1, 1, 0, 0, 0, kWidth, kHeight); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + cmd.Init(GL_TEXTURE_2D, 1, 0, -1, 0, 0, kWidth, kHeight); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + cmd.Init(GL_TEXTURE_2D, 1, 0, 1, 0, 0, kWidth, kHeight); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + cmd.Init(GL_TEXTURE_2D, 1, 0, 0, 0, 0, kWidth + 1, kHeight); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + cmd.Init(GL_TEXTURE_2D, 1, 0, 0, 0, 0, kWidth, kHeight + 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); +} + // TODO(gman): BufferData // TODO(gman): BufferDataImmediate @@ -2172,8 +2299,6 @@ TEST_F(GLES2DecoderTest, DeleteSharedIdsBadArgs) { // TODO(gman): CompressedTexImage2DImmediate -// TODO(gman): CompressedTexSubImage2D - // TODO(gman): CompressedTexSubImage2DImmediate // TODO(gman): DeleteProgram @@ -2186,8 +2311,6 @@ TEST_F(GLES2DecoderTest, DeleteSharedIdsBadArgs) { // TODO(gman): TexImage2DImmediate -// TODO(gman): TexSubImage2D - // TODO(gman): TexSubImage2DImmediate // TODO(gman): UseProgram diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc index 96c964d..45f47bb 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc @@ -49,6 +49,28 @@ void GLES2DecoderTestBase::SpecializedSetup<CheckFramebufferStatus, 0>( }; template <> +void GLES2DecoderTestBase::SpecializedSetup<CopyTexImage2D, 0>( + bool valid) { + if (valid) { + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + } +}; + +template <> +void GLES2DecoderTestBase::SpecializedSetup<CopyTexSubImage2D, 0>( + bool valid) { + if (valid) { + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + DoTexImage2D( + GL_TEXTURE_2D, 2, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, + 0, 0); + } +}; + +template <> void GLES2DecoderTestBase::SpecializedSetup<FramebufferRenderbuffer, 0>( bool /* valid */) { DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_, diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc index c0ab738..51e666e 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc @@ -332,10 +332,16 @@ void GLES2DecoderTestBase::DoTexImage2D( GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, uint32 shared_memory_id, uint32 shared_memory_offset) { + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); EXPECT_CALL(*gl_, TexImage2D(target, level, internal_format, width, height, border, format, type, _)) .Times(1) .RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); TexImage2D cmd; cmd.Init(target, level, internal_format, width, height, border, format, type, shared_memory_id, shared_memory_offset); diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc index 18a0ae8..a973fa8 100644 --- a/gpu/command_buffer/service/texture_manager.cc +++ b/gpu/command_buffer/service/texture_manager.cc @@ -157,7 +157,7 @@ void TextureManager::TextureInfo::SetLevelInfo( const TextureManager* manager, GLenum target, GLint level, - GLint internal_format, + GLenum internal_format, GLsizei width, GLsizei height, GLsizei depth, @@ -186,8 +186,37 @@ void TextureManager::TextureInfo::SetLevelInfo( Update(manager); } +bool TextureManager::TextureInfo::ValidForTexture( + GLint face, + GLint level, + GLint xoffset, + GLint yoffset, + GLsizei width, + GLsizei height, + GLenum format, + GLenum type) const { + size_t face_index = GLTargetToFaceIndex(face); + if (!IsDeleted() && level >= 0 && face_index < level_infos_.size() && + static_cast<size_t>(level) < level_infos_[face_index].size()) { + const LevelInfo& info = level_infos_[GLTargetToFaceIndex(face)][level]; + GLint right; + GLint top; + return SafeAdd(xoffset, width, &right) && + SafeAdd(yoffset, height, &top) && + xoffset >= 0 && + yoffset >= 0 && + right <= info.width && + top <= info.height && + format == info.internal_format && + type == info.type; + } + return false; +} + bool TextureManager::TextureInfo::GetLevelSize( GLint face, GLint level, GLsizei* width, GLsizei* height) const { + DCHECK(width); + DCHECK(height); size_t face_index = GLTargetToFaceIndex(face); if (!IsDeleted() && level >= 0 && face_index < level_infos_.size() && static_cast<size_t>(level) < level_infos_[face_index].size()) { @@ -199,8 +228,24 @@ bool TextureManager::TextureInfo::GetLevelSize( return false; } +bool TextureManager::TextureInfo::GetLevelType( + GLint face, GLint level, GLenum* type, GLenum* internal_format) const { + DCHECK(type); + DCHECK(internal_format); + size_t face_index = GLTargetToFaceIndex(face); + if (!IsDeleted() && level >= 0 && face_index < level_infos_.size() && + static_cast<size_t>(level) < level_infos_[face_index].size()) { + const LevelInfo& info = level_infos_[GLTargetToFaceIndex(face)][level]; + *type = info.type; + *internal_format = info.internal_format; + return true; + } + return false; +} + void TextureManager::TextureInfo::SetParameter( const TextureManager* manager, GLenum pname, GLint param) { + DCHECK(manager); switch (pname) { case GL_TEXTURE_MIN_FILTER: min_filter_ = param; @@ -345,7 +390,7 @@ void TextureManager::SetLevelInfo( TextureManager::TextureInfo* info, GLenum target, GLint level, - GLint internal_format, + GLenum internal_format, GLsizei width, GLsizei height, GLsizei depth, diff --git a/gpu/command_buffer/service/texture_manager.h b/gpu/command_buffer/service/texture_manager.h index 4fbfb68..070a801 100644 --- a/gpu/command_buffer/service/texture_manager.h +++ b/gpu/command_buffer/service/texture_manager.h @@ -83,10 +83,26 @@ class TextureManager { bool GetLevelSize( GLint face, GLint level, GLsizei* width, GLsizei* height) const; + // Get the type of a level. Returns false if level does not exist. + bool GetLevelType( + GLint face, GLint level, GLenum* type, GLenum* internal_format) const; + bool IsDeleted() const { return deleted_; } + // Returns true of the given dimensions are inside the dimensions of the + // level and if the format and type match the level. + bool ValidForTexture( + GLint face, + GLint level, + GLint xoffset, + GLint yoffset, + GLsizei width, + GLsizei height, + GLenum format, + GLenum type) const; + private: friend class TextureManager; friend class base::RefCounted<TextureInfo>; @@ -106,7 +122,7 @@ class TextureManager { } bool valid; - GLint internal_format; + GLenum internal_format; GLsizei width; GLsizei height; GLsizei depth; @@ -120,7 +136,7 @@ class TextureManager { const TextureManager* manager, GLenum target, GLint level, - GLint internal_format, + GLenum internal_format, GLsizei width, GLsizei height, GLsizei depth, @@ -249,7 +265,7 @@ class TextureManager { TextureInfo* info, GLenum target, GLint level, - GLint internal_format, + GLenum internal_format, GLsizei width, GLsizei height, GLsizei depth, diff --git a/gpu/command_buffer/service/texture_manager_unittest.cc b/gpu/command_buffer/service/texture_manager_unittest.cc index 72aac0a..8520895 100644 --- a/gpu/command_buffer/service/texture_manager_unittest.cc +++ b/gpu/command_buffer/service/texture_manager_unittest.cc @@ -392,6 +392,70 @@ TEST_F(TextureInfoTest, GetLevelSize) { EXPECT_FALSE(info_->GetLevelSize(GL_TEXTURE_2D, 1, &width, &height)); } +TEST_F(TextureInfoTest, GetLevelType) { + manager_.SetInfoTarget(info_, GL_TEXTURE_2D); + manager_.SetLevelInfo(info_, + GL_TEXTURE_2D, 1, GL_RGBA, 4, 5, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE); + GLenum type = -1; + GLenum format = -1; + EXPECT_FALSE(info_->GetLevelType(GL_TEXTURE_2D, -1, &type, &format)); + EXPECT_FALSE(info_->GetLevelType(GL_TEXTURE_2D, 1000, &type, &format)); + EXPECT_TRUE(info_->GetLevelType(GL_TEXTURE_2D, 0, &type, &format)); + EXPECT_EQ(0u, type); + EXPECT_EQ(0u, format); + EXPECT_TRUE(info_->GetLevelType(GL_TEXTURE_2D, 1, &type, &format)); + EXPECT_EQ(static_cast<GLenum>(GL_UNSIGNED_BYTE), type); + EXPECT_EQ(static_cast<GLenum>(GL_RGBA), format); + manager_.RemoveTextureInfo(kClient1Id); + EXPECT_FALSE(info_->GetLevelType(GL_TEXTURE_2D, 1, &type, &format)); +} + +TEST_F(TextureInfoTest, ValidForTexture) { + manager_.SetInfoTarget(info_, GL_TEXTURE_2D); + manager_.SetLevelInfo(info_, + GL_TEXTURE_2D, 1, GL_RGBA, 4, 5, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE); + // Check bad face. + EXPECT_FALSE(info_->ValidForTexture( + GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, + 1, 0, 0, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE)); + // Check bad level. + EXPECT_FALSE(info_->ValidForTexture( + GL_TEXTURE_2D, 0, 0, 0, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE)); + // Check bad xoffset. + EXPECT_FALSE(info_->ValidForTexture( + GL_TEXTURE_2D, 1, -1, 0, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE)); + // Check bad xoffset + width > width. + EXPECT_FALSE(info_->ValidForTexture( + GL_TEXTURE_2D, 1, 1, 0, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE)); + // Check bad yoffset. + EXPECT_FALSE(info_->ValidForTexture( + GL_TEXTURE_2D, 1, 0, -1, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE)); + // Check bad yoffset + height > height. + EXPECT_FALSE(info_->ValidForTexture( + GL_TEXTURE_2D, 1, 0, 1, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE)); + // Check bad width. + EXPECT_FALSE(info_->ValidForTexture( + GL_TEXTURE_2D, 1, 0, 0, 5, 5, GL_RGBA, GL_UNSIGNED_BYTE)); + // Check bad height. + EXPECT_FALSE(info_->ValidForTexture( + GL_TEXTURE_2D, 1, 0, 0, 4, 6, GL_RGBA, GL_UNSIGNED_BYTE)); + // Check bad format. + EXPECT_FALSE(info_->ValidForTexture( + GL_TEXTURE_2D, 1, 0, 0, 4, 5, GL_RGB, GL_UNSIGNED_BYTE)); + // Check bad type. + EXPECT_FALSE(info_->ValidForTexture( + GL_TEXTURE_2D, 1, 0, 0, 4, 5, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4)); + // Check valid full size + EXPECT_TRUE(info_->ValidForTexture( + GL_TEXTURE_2D, 1, 0, 0, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE)); + // Check valid particial size. + EXPECT_TRUE(info_->ValidForTexture( + GL_TEXTURE_2D, 1, 1, 1, 2, 3, GL_RGBA, GL_UNSIGNED_BYTE)); + manager_.RemoveTextureInfo(kClient1Id); + EXPECT_FALSE(info_->ValidForTexture( + GL_TEXTURE_2D, 1, 0, 0, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE)); +} + TEST_F(TextureInfoTest, FloatNotLinear) { TextureManager manager( false, false, false, kMaxTextureSize, kMaxCubeMapTextureSize); |