summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-31 17:10:43 +0000
committergman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-31 17:10:43 +0000
commitcadde4a696d15d4d5cb6b61c346d98ac2a8b1993 (patch)
treea237ce64bc5616f633e8fb265d7dc07534465162
parentfc586c7e48d90dac7963906bf34c8f6382b55846 (diff)
downloadchromium_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
-rwxr-xr-xgpu/command_buffer/build_gles2_cmd_buffer.py12
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc176
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_autogen.h12
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc131
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc22
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc6
-rw-r--r--gpu/command_buffer/service/texture_manager.cc49
-rw-r--r--gpu/command_buffer/service/texture_manager.h22
-rw-r--r--gpu/command_buffer/service/texture_manager_unittest.cc64
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);