diff options
author | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-25 18:35:36 +0000 |
---|---|---|
committer | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-25 18:35:36 +0000 |
commit | 43c2f1f8071ddcf6ef9c4402d248e63375cda943 (patch) | |
tree | e38d7d14722630bcaa73c781c4d0d4d917cc45e6 /gpu | |
parent | ca82a57b77b455e132feaf8f010643f91af07759 (diff) | |
download | chromium_src-43c2f1f8071ddcf6ef9c4402d248e63375cda943.zip chromium_src-43c2f1f8071ddcf6ef9c4402d248e63375cda943.tar.gz chromium_src-43c2f1f8071ddcf6ef9c4402d248e63375cda943.tar.bz2 |
Make Command Buffer limit count for glUniformXXv calls.
TEST=unit tests
BUG=77233
R=zmo@chromium.org,
Review URL: http://codereview.chromium.org/6713094
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@79421 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
10 files changed, 474 insertions, 83 deletions
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index d827b82..bd5bef7 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py @@ -1519,7 +1519,12 @@ _FUNCTION_INFO = { 'count': 2, 'decoder_func': 'DoUniform2fv', }, - 'Uniform2iv': {'type': 'PUTn', 'data_type': 'GLint', 'count': 2}, + 'Uniform2iv': { + 'type': 'PUTn', + 'data_type': 'GLint', + 'count': 2, + 'decoder_func': 'DoUniform2iv', + }, 'Uniform3f': {'type': 'PUTXn', 'data_type': 'GLfloat', 'count': 3}, 'Uniform3fv': { 'type': 'PUTn', @@ -1527,7 +1532,12 @@ _FUNCTION_INFO = { 'count': 3, 'decoder_func': 'DoUniform3fv', }, - 'Uniform3iv': {'type': 'PUTn', 'data_type': 'GLint', 'count': 3}, + 'Uniform3iv': { + 'type': 'PUTn', + 'data_type': 'GLint', + 'count': 3, + 'decoder_func': 'DoUniform3iv', + }, 'Uniform4f': { 'type': 'PUTXn', 'data_type': 'GLfloat', 'count': 4 }, @@ -1537,10 +1547,30 @@ _FUNCTION_INFO = { 'count': 4, 'decoder_func': 'DoUniform4fv', }, - 'Uniform4iv': {'type': 'PUTn', 'data_type': 'GLint', 'count': 4}, - 'UniformMatrix2fv': {'type': 'PUTn', 'data_type': 'GLfloat', 'count': 4}, - 'UniformMatrix3fv': {'type': 'PUTn', 'data_type': 'GLfloat', 'count': 9}, - 'UniformMatrix4fv': {'type': 'PUTn', 'data_type': 'GLfloat', 'count': 16}, + 'Uniform4iv': { + 'type': 'PUTn', + 'data_type': 'GLint', + 'count': 4, + 'decoder_func': 'DoUniform4iv', + }, + 'UniformMatrix2fv': { + 'type': 'PUTn', + 'data_type': 'GLfloat', + 'count': 4, + 'decoder_func': 'DoUniformMatrix2fv', + }, + 'UniformMatrix3fv': { + 'type': 'PUTn', + 'data_type': 'GLfloat', + 'count': 9, + 'decoder_func': 'DoUniformMatrix3fv', + }, + 'UniformMatrix4fv': { + 'type': 'PUTn', + 'data_type': 'GLfloat', + 'count': 16, + 'decoder_func': 'DoUniformMatrix4fv', + }, 'UnmapBufferSubDataCHROMIUM': { 'gen_cmd': False, 'extension': True, @@ -3446,8 +3476,46 @@ class PUTnHandler(TypeHandler): def __init__(self): TypeHandler.__init__(self) + def WriteServiceUnitTest(self, func, file): + """Overridden from TypeHandler.""" + TypeHandler.WriteServiceUnitTest(self, func, file) + + valid_test = """ +TEST_F(%(test_name)s, %(name)sValidArgsCountTooLarge) { + EXPECT_CALL(*gl_, %(gl_func_name)s(%(gl_args)s)); + SpecializedSetup<%(name)s, 0>(true); + %(name)s cmd; + cmd.Init(%(args)s); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} +""" + gl_arg_strings = [] + arg_strings = [] + count = 0 + for arg in func.GetOriginalArgs(): + # hardcoded to match unit tests. + if count == 0: + # the location of the second element of the first uniform. + gl_arg_strings.append("3") + arg_strings.append("3") + elif count == 1: + # the number of elements that gl will be called with. + gl_arg_strings.append("2") + # the number of elements requested in the command. + arg_strings.append("5") + else: + gl_arg_strings.append(arg.GetValidGLArg(count, 0)) + arg_strings.append(arg.GetValidArg(count, 0)) + count += 1 + extra = { + 'gl_args': ", ".join(gl_arg_strings), + 'args': ", ".join(arg_strings), + } + self.WriteValidUnitTest(func, file, valid_test, extra) + def WriteImmediateServiceUnitTest(self, func, file): - """Writes the service unit test for a command.""" + """Overridden from TypeHandler.""" valid_test = """ TEST_F(%(test_name)s, %(name)sValidArgs) { %(name)s& cmd = *GetImmediateAs<%(name)s>(); diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 57df63c..5444b15 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -1006,9 +1006,10 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, // Gets the type of a uniform for a location in the current program. Sets GL // errors if the current program is not valid. Returns true if the current - // program is valid and the location exists. - bool GetUniformTypeByLocation( - GLint location, const char* function_name, GLenum* type); + // program is valid and the location exists. Adjusts count so it + // does not overflow the uniform. + bool PrepForSetUniformByLocation( + GLint location, const char* function_name, GLenum* type, GLsizei* count); // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written); @@ -1179,6 +1180,9 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, // spec only these 2 functions can be used to set sampler uniforms. void DoUniform1i(GLint location, GLint v0); void DoUniform1iv(GLint location, GLsizei count, const GLint* value); + void DoUniform2iv(GLint location, GLsizei count, const GLint* value); + void DoUniform3iv(GLint location, GLsizei count, const GLint* value); + void DoUniform4iv(GLint location, GLsizei count, const GLint* value); // Wrappers for glUniformfv because some drivers don't correctly accept // bool uniforms. @@ -1187,6 +1191,13 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, void DoUniform3fv(GLint location, GLsizei count, const GLfloat* value); void DoUniform4fv(GLint location, GLsizei count, const GLfloat* value); + void DoUniformMatrix2fv( + GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + void DoUniformMatrix3fv( + GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + void DoUniformMatrix4fv( + GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + // Wrappers for glVertexAttrib?? void DoVertexAttrib1f(GLuint index, GLfloat v0); void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1); @@ -3757,20 +3768,35 @@ bool GLES2DecoderImpl::CheckCurrentProgramForUniform( return location != -1; } -bool GLES2DecoderImpl::GetUniformTypeByLocation( - GLint location, const char* function_name, GLenum* type) { +bool GLES2DecoderImpl::PrepForSetUniformByLocation( + GLint location, const char* function_name, GLenum* type, GLsizei* count) { + DCHECK(type); + DCHECK(count); if (!CheckCurrentProgramForUniform(location, function_name)) { return false; } - if (!current_program_->GetUniformTypeByLocation(location, type)) { + GLint array_index = -1; + const ProgramManager::ProgramInfo::UniformInfo* info = + current_program_->GetUniformInfoByLocation(location, &array_index); + if (!info) { SetGLError(GL_INVALID_OPERATION, - (std::string(function_name) + ": program not linked").c_str()); + (std::string(function_name) + ": unknown location").c_str()); + return false; + } + if (*count > 1 && !info->is_array) { + SetGLError( + GL_INVALID_OPERATION, + (std::string(function_name) + ": count > 1 for non-array").c_str()); return false; } + *count = std::min(info->size - array_index, *count); + if (*count <= 0) { + return false; + } + *type = info->type; return true; } - void GLES2DecoderImpl::DoUniform1i(GLint location, GLint v0) { if (!CheckCurrentProgramForUniform(location, "glUniform1i")) { return; @@ -3784,14 +3810,20 @@ void GLES2DecoderImpl::DoUniform1iv( if (!CheckCurrentProgramForUniform(location, "glUniform1iv")) { return; } - current_program_->SetSamplers(location, count, value); + GLenum type = 0; + if (!PrepForSetUniformByLocation(location, "glUniform1iv", &type, &count)) { + return; + } + if (type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE) { + current_program_->SetSamplers(location, count, value); + } glUniform1iv(location, count, value); } void GLES2DecoderImpl::DoUniform1fv( GLint location, GLsizei count, const GLfloat* value) { - GLenum type; - if (!GetUniformTypeByLocation(location, "glUniform1fv", &type)) { + GLenum type = 0; + if (!PrepForSetUniformByLocation(location, "glUniform1fv", &type, &count)) { return; } if (type == GL_BOOL) { @@ -3807,8 +3839,8 @@ void GLES2DecoderImpl::DoUniform1fv( void GLES2DecoderImpl::DoUniform2fv( GLint location, GLsizei count, const GLfloat* value) { - GLenum type; - if (!GetUniformTypeByLocation(location, "glUniform2fv", &type)) { + GLenum type = 0; + if (!PrepForSetUniformByLocation(location, "glUniform2fv", &type, &count)) { return; } if (type == GL_BOOL_VEC2) { @@ -3825,8 +3857,8 @@ void GLES2DecoderImpl::DoUniform2fv( void GLES2DecoderImpl::DoUniform3fv( GLint location, GLsizei count, const GLfloat* value) { - GLenum type; - if (!GetUniformTypeByLocation(location, "glUniform3fv", &type)) { + GLenum type = 0; + if (!PrepForSetUniformByLocation(location, "glUniform3fv", &type, &count)) { return; } if (type == GL_BOOL_VEC3) { @@ -3843,8 +3875,8 @@ void GLES2DecoderImpl::DoUniform3fv( void GLES2DecoderImpl::DoUniform4fv( GLint location, GLsizei count, const GLfloat* value) { - GLenum type; - if (!GetUniformTypeByLocation(location, "glUniform4fv", &type)) { + GLenum type = 0; + if (!PrepForSetUniformByLocation(location, "glUniform4fv", &type, &count)) { return; } if (type == GL_BOOL_VEC4) { @@ -3859,6 +3891,63 @@ void GLES2DecoderImpl::DoUniform4fv( } } +void GLES2DecoderImpl::DoUniform2iv( + GLint location, GLsizei count, const GLint* value) { + GLenum type = 0; + if (!PrepForSetUniformByLocation(location, "glUniform2iv", &type, &count)) { + return; + } + glUniform2iv(location, count, value); +} + +void GLES2DecoderImpl::DoUniform3iv( + GLint location, GLsizei count, const GLint* value) { + GLenum type = 0; + if (!PrepForSetUniformByLocation(location, "glUniform3iv", &type, &count)) { + return; + } + glUniform3iv(location, count, value); +} + +void GLES2DecoderImpl::DoUniform4iv( + GLint location, GLsizei count, const GLint* value) { + GLenum type = 0; + if (!PrepForSetUniformByLocation(location, "glUniform4iv", &type, &count)) { + return; + } + glUniform4iv(location, count, value); +} + +void GLES2DecoderImpl::DoUniformMatrix2fv( + GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { + GLenum type = 0; + if (!PrepForSetUniformByLocation( + location, "glUniformMatrix2fv", &type, &count)) { + return; + } + glUniformMatrix2fv (location, count, transpose, value); +} + +void GLES2DecoderImpl::DoUniformMatrix3fv( + GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { + GLenum type = 0; + if (!PrepForSetUniformByLocation( + location, "glUniformMatrix3fv", &type, &count)) { + return; + } + glUniformMatrix3fv (location, count, transpose, value); +} + +void GLES2DecoderImpl::DoUniformMatrix4fv( + GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { + GLenum type = 0; + if (!PrepForSetUniformByLocation( + location, "glUniformMatrix4fv", &type, &count)) { + return; + } + glUniformMatrix4fv (location, count, transpose, value); +} + void GLES2DecoderImpl::DoUseProgram(GLuint program) { GLuint service_id = 0; ProgramManager::ProgramInfo* info = NULL; @@ -5847,12 +5936,15 @@ bool GLES2DecoderImpl::GetUniformSetup( return false; } *service_id = info->service_id(); - GLenum type; - if (!info->GetUniformTypeByLocation(location, &type)) { + GLint array_index = -1; + const ProgramManager::ProgramInfo::UniformInfo* uniform_info = + info->GetUniformInfoByLocation(location, &array_index); + if (!uniform_info) { // No such location. SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown location"); return false; } + GLenum type = uniform_info->type; GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type); if (size == 0) { SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown type"); diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h index 06ebf50..7ac471a 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h @@ -2012,7 +2012,7 @@ error::Error GLES2DecoderImpl::HandleUniform2iv( if (v == NULL) { return error::kOutOfBounds; } - glUniform2iv(location, count, v); + DoUniform2iv(location, count, v); return error::kNoError; } @@ -2032,7 +2032,7 @@ error::Error GLES2DecoderImpl::HandleUniform2ivImmediate( if (v == NULL) { return error::kOutOfBounds; } - glUniform2iv(location, count, v); + DoUniform2iv(location, count, v); return error::kNoError; } @@ -2107,7 +2107,7 @@ error::Error GLES2DecoderImpl::HandleUniform3iv( if (v == NULL) { return error::kOutOfBounds; } - glUniform3iv(location, count, v); + DoUniform3iv(location, count, v); return error::kNoError; } @@ -2127,7 +2127,7 @@ error::Error GLES2DecoderImpl::HandleUniform3ivImmediate( if (v == NULL) { return error::kOutOfBounds; } - glUniform3iv(location, count, v); + DoUniform3iv(location, count, v); return error::kNoError; } @@ -2204,7 +2204,7 @@ error::Error GLES2DecoderImpl::HandleUniform4iv( if (v == NULL) { return error::kOutOfBounds; } - glUniform4iv(location, count, v); + DoUniform4iv(location, count, v); return error::kNoError; } @@ -2224,7 +2224,7 @@ error::Error GLES2DecoderImpl::HandleUniform4ivImmediate( if (v == NULL) { return error::kOutOfBounds; } - glUniform4iv(location, count, v); + DoUniform4iv(location, count, v); return error::kNoError; } @@ -2247,7 +2247,7 @@ error::Error GLES2DecoderImpl::HandleUniformMatrix2fv( if (value == NULL) { return error::kOutOfBounds; } - glUniformMatrix2fv(location, count, transpose, value); + DoUniformMatrix2fv(location, count, transpose, value); return error::kNoError; } @@ -2273,7 +2273,7 @@ error::Error GLES2DecoderImpl::HandleUniformMatrix2fvImmediate( if (value == NULL) { return error::kOutOfBounds; } - glUniformMatrix2fv(location, count, transpose, value); + DoUniformMatrix2fv(location, count, transpose, value); return error::kNoError; } @@ -2296,7 +2296,7 @@ error::Error GLES2DecoderImpl::HandleUniformMatrix3fv( if (value == NULL) { return error::kOutOfBounds; } - glUniformMatrix3fv(location, count, transpose, value); + DoUniformMatrix3fv(location, count, transpose, value); return error::kNoError; } @@ -2322,7 +2322,7 @@ error::Error GLES2DecoderImpl::HandleUniformMatrix3fvImmediate( if (value == NULL) { return error::kOutOfBounds; } - glUniformMatrix3fv(location, count, transpose, value); + DoUniformMatrix3fv(location, count, transpose, value); return error::kNoError; } @@ -2345,7 +2345,7 @@ error::Error GLES2DecoderImpl::HandleUniformMatrix4fv( if (value == NULL) { return error::kOutOfBounds; } - glUniformMatrix4fv(location, count, transpose, value); + DoUniformMatrix4fv(location, count, transpose, value); return error::kNoError; } @@ -2371,7 +2371,7 @@ error::Error GLES2DecoderImpl::HandleUniformMatrix4fvImmediate( if (value == NULL) { return error::kOutOfBounds; } - glUniformMatrix4fv(location, count, transpose, value); + DoUniformMatrix4fv(location, count, transpose, value); 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 5e4370e..89cae82 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc @@ -1138,7 +1138,6 @@ TEST_F(GLES2DecoderTest, GenerateMipmapWrongFormatsFails) { TEST_F(GLES2DecoderWithShaderTest, Uniform1iValidArgs) { EXPECT_CALL(*gl_, Uniform1i(kUniform1Location, 2)); - SpecializedSetup<Uniform1i, 0>(true); Uniform1i cmd; cmd.Init(kUniform1Location, 2); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); @@ -1147,27 +1146,24 @@ TEST_F(GLES2DecoderWithShaderTest, Uniform1iValidArgs) { TEST_F(GLES2DecoderWithShaderTest, Uniform1ivValidArgs) { EXPECT_CALL( *gl_, Uniform1iv( - kUniform1Location, 2, + kUniform1Location, 1, reinterpret_cast<const GLint*>(shared_memory_address_))); - SpecializedSetup<Uniform1iv, 0>(true); Uniform1iv cmd; - cmd.Init(kUniform1Location, 2, shared_memory_id_, shared_memory_offset_); + cmd.Init(kUniform1Location, 1, shared_memory_id_, shared_memory_offset_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); } TEST_F(GLES2DecoderWithShaderTest, Uniform1ivInvalidArgs2_0) { EXPECT_CALL(*gl_, Uniform1iv(_, _, _)).Times(0); - SpecializedSetup<Uniform1iv, 0>(false); Uniform1iv cmd; - cmd.Init(kUniform1Location, 2, kInvalidSharedMemoryId, 0); + cmd.Init(kUniform1Location, 1, kInvalidSharedMemoryId, 0); EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); } TEST_F(GLES2DecoderWithShaderTest, Uniform1ivInvalidArgs2_1) { EXPECT_CALL(*gl_, Uniform1iv(_, _, _)).Times(0); - SpecializedSetup<Uniform1iv, 0>(false); Uniform1iv cmd; - cmd.Init(kUniform1Location, 2, shared_memory_id_, kInvalidSharedMemoryOffset); + cmd.Init(kUniform1Location, 1, shared_memory_id_, kInvalidSharedMemoryOffset); EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); } @@ -1175,15 +1171,31 @@ TEST_F(GLES2DecoderWithShaderTest, Uniform1ivImmediateValidArgs) { Uniform1ivImmediate& cmd = *GetImmediateAs<Uniform1ivImmediate>(); EXPECT_CALL( *gl_, - Uniform1iv(kUniform1Location, 2, + Uniform1iv(kUniform1Location, 1, reinterpret_cast<GLint*>(ImmediateDataAddress(&cmd)))); - SpecializedSetup<Uniform1ivImmediate, 0>(true); GLint temp[1 * 2] = { 0, }; - cmd.Init(kUniform1Location, 2, &temp[0]); + cmd.Init(kUniform1Location, 1, &temp[0]); EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); } +TEST_F(GLES2DecoderWithShaderTest, Uniform1ivInvalidValidArgs) { + EXPECT_CALL(*gl_, Uniform1iv(_, _, _)).Times(0); + Uniform1iv cmd; + cmd.Init(kUniform1Location, 2, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_F(GLES2DecoderWithShaderTest, Uniform1ivZeroCount) { + EXPECT_CALL(*gl_, Uniform1iv(_, _, _)).Times(0); + Uniform1iv cmd; + cmd.Init(kUniform1Location, 0, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + + TEST_F(GLES2DecoderWithShaderTest, BindBufferToDifferentTargetFails) { // Bind the buffer to GL_ARRAY_BUFFER DoBindBuffer(GL_ARRAY_BUFFER, client_buffer_id_, kServiceBufferId); diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc index 2823379..8dd05f9 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -119,6 +119,17 @@ void GLES2DecoderTestBase::SpecializedSetup<Uniform1fvImmediate, 0>( }; template <> +void GLES2DecoderTestBase::SpecializedSetup<Uniform1iv, 0>(bool /* valid */) { + SetupShaderForUniform(); +}; + +template <> +void GLES2DecoderTestBase::SpecializedSetup<Uniform1ivImmediate, 0>( + bool /* valid */) { + SetupShaderForUniform(); +}; + +template <> void GLES2DecoderTestBase::SpecializedSetup<Uniform2f, 0>(bool /* valid */) { SetupShaderForUniform(); }; @@ -129,12 +140,23 @@ void GLES2DecoderTestBase::SpecializedSetup<Uniform2fv, 0>(bool /* valid */) { }; template <> +void GLES2DecoderTestBase::SpecializedSetup<Uniform2iv, 0>(bool /* valid */) { + SetupShaderForUniform(); +}; + +template <> void GLES2DecoderTestBase::SpecializedSetup<Uniform2fvImmediate, 0>( bool /* valid */) { SetupShaderForUniform(); }; template <> +void GLES2DecoderTestBase::SpecializedSetup<Uniform2ivImmediate, 0>( + bool /* valid */) { + SetupShaderForUniform(); +}; + +template <> void GLES2DecoderTestBase::SpecializedSetup<Uniform3f, 0>(bool /* valid */) { SetupShaderForUniform(); }; @@ -145,12 +167,23 @@ void GLES2DecoderTestBase::SpecializedSetup<Uniform3fv, 0>(bool /* valid */) { }; template <> +void GLES2DecoderTestBase::SpecializedSetup<Uniform3iv, 0>(bool /* valid */) { + SetupShaderForUniform(); +}; + +template <> void GLES2DecoderTestBase::SpecializedSetup<Uniform3fvImmediate, 0>( bool /* valid */) { SetupShaderForUniform(); }; template <> +void GLES2DecoderTestBase::SpecializedSetup<Uniform3ivImmediate, 0>( + bool /* valid */) { + SetupShaderForUniform(); +}; + +template <> void GLES2DecoderTestBase::SpecializedSetup<Uniform4f, 0>(bool /* valid */) { SetupShaderForUniform(); }; @@ -161,12 +194,59 @@ void GLES2DecoderTestBase::SpecializedSetup<Uniform4fv, 0>(bool /* valid */) { }; template <> +void GLES2DecoderTestBase::SpecializedSetup<Uniform4iv, 0>(bool /* valid */) { + SetupShaderForUniform(); +}; + +template <> void GLES2DecoderTestBase::SpecializedSetup<Uniform4fvImmediate, 0>( bool /* valid */) { SetupShaderForUniform(); }; template <> +void GLES2DecoderTestBase::SpecializedSetup<Uniform4ivImmediate, 0>( + bool /* valid */) { + SetupShaderForUniform(); +}; + +template <> +void GLES2DecoderTestBase::SpecializedSetup<UniformMatrix2fv, 0>( + bool /* valid */) { + SetupShaderForUniform(); +}; + +template <> +void GLES2DecoderTestBase::SpecializedSetup<UniformMatrix2fvImmediate, 0>( + bool /* valid */) { + SetupShaderForUniform(); +}; + +template <> +void GLES2DecoderTestBase::SpecializedSetup<UniformMatrix3fv, 0>( + bool /* valid */) { + SetupShaderForUniform(); +}; + +template <> +void GLES2DecoderTestBase::SpecializedSetup<UniformMatrix3fvImmediate, 0>( + bool /* valid */) { + SetupShaderForUniform(); +}; + +template <> +void GLES2DecoderTestBase::SpecializedSetup<UniformMatrix4fv, 0>( + bool /* valid */) { + SetupShaderForUniform(); +}; + +template <> +void GLES2DecoderTestBase::SpecializedSetup<UniformMatrix4fvImmediate, 0>( + bool /* valid */) { + SetupShaderForUniform(); +}; + +template <> void GLES2DecoderTestBase::SpecializedSetup<RenderbufferStorage, 0>( bool valid) { DoBindRenderbuffer(GL_RENDERBUFFER, client_renderbuffer_id_, diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h index 18ebb1b..350067d 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h @@ -727,6 +727,17 @@ TEST_F(GLES2DecoderTest2, Uniform1fvInvalidArgs2_1) { EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); } +TEST_F(GLES2DecoderTest2, Uniform1fvValidArgsCountTooLarge) { + EXPECT_CALL( + *gl_, Uniform1fv( + 3, 2, reinterpret_cast<const GLfloat*>(shared_memory_address_))); + SpecializedSetup<Uniform1fv, 0>(true); + Uniform1fv cmd; + cmd.Init(3, 5, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + TEST_F(GLES2DecoderTest2, Uniform1fvImmediateValidArgs) { Uniform1fvImmediate& cmd = *GetImmediateAs<Uniform1fvImmediate>(); EXPECT_CALL( @@ -789,6 +800,17 @@ TEST_F(GLES2DecoderTest2, Uniform2fvInvalidArgs2_1) { EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); } +TEST_F(GLES2DecoderTest2, Uniform2fvValidArgsCountTooLarge) { + EXPECT_CALL( + *gl_, Uniform2fv( + 3, 2, reinterpret_cast<const GLfloat*>(shared_memory_address_))); + SpecializedSetup<Uniform2fv, 0>(true); + Uniform2fv cmd; + cmd.Init(3, 5, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + TEST_F(GLES2DecoderTest2, Uniform2fvImmediateValidArgs) { Uniform2fvImmediate& cmd = *GetImmediateAs<Uniform2fvImmediate>(); EXPECT_CALL( @@ -848,6 +870,17 @@ TEST_F(GLES2DecoderTest2, Uniform2ivInvalidArgs2_1) { EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); } +TEST_F(GLES2DecoderTest2, Uniform2ivValidArgsCountTooLarge) { + EXPECT_CALL( + *gl_, Uniform2iv( + 3, 2, reinterpret_cast<const GLint*>(shared_memory_address_))); + SpecializedSetup<Uniform2iv, 0>(true); + Uniform2iv cmd; + cmd.Init(3, 5, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + TEST_F(GLES2DecoderTest2, Uniform2ivImmediateValidArgs) { Uniform2ivImmediate& cmd = *GetImmediateAs<Uniform2ivImmediate>(); EXPECT_CALL( @@ -907,6 +940,17 @@ TEST_F(GLES2DecoderTest2, Uniform3fvInvalidArgs2_1) { EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); } +TEST_F(GLES2DecoderTest2, Uniform3fvValidArgsCountTooLarge) { + EXPECT_CALL( + *gl_, Uniform3fv( + 3, 2, reinterpret_cast<const GLfloat*>(shared_memory_address_))); + SpecializedSetup<Uniform3fv, 0>(true); + Uniform3fv cmd; + cmd.Init(3, 5, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + TEST_F(GLES2DecoderTest2, Uniform3fvImmediateValidArgs) { Uniform3fvImmediate& cmd = *GetImmediateAs<Uniform3fvImmediate>(); EXPECT_CALL( @@ -966,6 +1010,17 @@ TEST_F(GLES2DecoderTest2, Uniform3ivInvalidArgs2_1) { EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); } +TEST_F(GLES2DecoderTest2, Uniform3ivValidArgsCountTooLarge) { + EXPECT_CALL( + *gl_, Uniform3iv( + 3, 2, reinterpret_cast<const GLint*>(shared_memory_address_))); + SpecializedSetup<Uniform3iv, 0>(true); + Uniform3iv cmd; + cmd.Init(3, 5, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + TEST_F(GLES2DecoderTest2, Uniform3ivImmediateValidArgs) { Uniform3ivImmediate& cmd = *GetImmediateAs<Uniform3ivImmediate>(); EXPECT_CALL( @@ -1025,6 +1080,17 @@ TEST_F(GLES2DecoderTest2, Uniform4fvInvalidArgs2_1) { EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); } +TEST_F(GLES2DecoderTest2, Uniform4fvValidArgsCountTooLarge) { + EXPECT_CALL( + *gl_, Uniform4fv( + 3, 2, reinterpret_cast<const GLfloat*>(shared_memory_address_))); + SpecializedSetup<Uniform4fv, 0>(true); + Uniform4fv cmd; + cmd.Init(3, 5, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + TEST_F(GLES2DecoderTest2, Uniform4fvImmediateValidArgs) { Uniform4fvImmediate& cmd = *GetImmediateAs<Uniform4fvImmediate>(); EXPECT_CALL( @@ -1084,6 +1150,17 @@ TEST_F(GLES2DecoderTest2, Uniform4ivInvalidArgs2_1) { EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); } +TEST_F(GLES2DecoderTest2, Uniform4ivValidArgsCountTooLarge) { + EXPECT_CALL( + *gl_, Uniform4iv( + 3, 2, reinterpret_cast<const GLint*>(shared_memory_address_))); + SpecializedSetup<Uniform4iv, 0>(true); + Uniform4iv cmd; + cmd.Init(3, 5, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + TEST_F(GLES2DecoderTest2, Uniform4ivImmediateValidArgs) { Uniform4ivImmediate& cmd = *GetImmediateAs<Uniform4ivImmediate>(); EXPECT_CALL( @@ -1144,6 +1221,18 @@ TEST_F(GLES2DecoderTest2, UniformMatrix2fvInvalidArgs3_1) { EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); } +TEST_F(GLES2DecoderTest2, UniformMatrix2fvValidArgsCountTooLarge) { + EXPECT_CALL( + *gl_, UniformMatrix2fv( + 3, 2, false, reinterpret_cast<const GLfloat*>( + shared_memory_address_))); + SpecializedSetup<UniformMatrix2fv, 0>(true); + UniformMatrix2fv cmd; + cmd.Init(3, 5, false, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + TEST_F(GLES2DecoderTest2, UniformMatrix2fvImmediateValidArgs) { UniformMatrix2fvImmediate& cmd = *GetImmediateAs<UniformMatrix2fvImmediate>(); @@ -1217,6 +1306,18 @@ TEST_F(GLES2DecoderTest2, UniformMatrix3fvInvalidArgs3_1) { EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); } +TEST_F(GLES2DecoderTest2, UniformMatrix3fvValidArgsCountTooLarge) { + EXPECT_CALL( + *gl_, UniformMatrix3fv( + 3, 2, false, reinterpret_cast<const GLfloat*>( + shared_memory_address_))); + SpecializedSetup<UniformMatrix3fv, 0>(true); + UniformMatrix3fv cmd; + cmd.Init(3, 5, false, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + TEST_F(GLES2DecoderTest2, UniformMatrix3fvImmediateValidArgs) { UniformMatrix3fvImmediate& cmd = *GetImmediateAs<UniformMatrix3fvImmediate>(); @@ -1290,6 +1391,18 @@ TEST_F(GLES2DecoderTest2, UniformMatrix4fvInvalidArgs3_1) { EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); } +TEST_F(GLES2DecoderTest2, UniformMatrix4fvValidArgsCountTooLarge) { + EXPECT_CALL( + *gl_, UniformMatrix4fv( + 3, 2, false, reinterpret_cast<const GLfloat*>( + shared_memory_address_))); + SpecializedSetup<UniformMatrix4fv, 0>(true); + UniformMatrix4fv cmd; + cmd.Init(3, 5, false, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + TEST_F(GLES2DecoderTest2, UniformMatrix4fvImmediateValidArgs) { UniformMatrix4fvImmediate& cmd = *GetImmediateAs<UniformMatrix4fvImmediate>(); 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 ebab9ba..f302aa3 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc @@ -337,7 +337,7 @@ void GLES2DecoderTestBase::SetupShaderForUniform() { { "foo", 1, GL_FLOAT, 1, }, }; static UniformInfo uniforms[] = { - { "bar", 1, GL_INT, 1, }, + { "bar", 3, GL_INT, 1, }, }; const GLuint kClientVertexShaderId = 5001; const GLuint kServiceVertexShaderId = 6001; diff --git a/gpu/command_buffer/service/program_manager.cc b/gpu/command_buffer/service/program_manager.cc index b52c017..ed52341 100644 --- a/gpu/command_buffer/service/program_manager.cc +++ b/gpu/command_buffer/service/program_manager.cc @@ -61,7 +61,7 @@ void ProgramManager::ProgramInfo::Reset() { uniform_infos_.clear(); sampler_indices_.clear(); attrib_location_to_index_map_.clear(); - uniform_location_to_index_map_.clear(); + location_infos_.clear(); UpdateLogInfo(); } @@ -157,14 +157,14 @@ void ProgramManager::ProgramInfo::Update() { } } // Create uniform location to index map. - uniform_location_to_index_map_.resize(max_location + 1); + location_infos_.resize(max_location + 1); for (GLint ii = 0; ii <= max_location; ++ii) { - uniform_location_to_index_map_[ii] = -1; + location_infos_[ii] = LocationInfo(-1, -1); } for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) { const UniformInfo& info = uniform_infos_[ii]; for (size_t jj = 0; jj < info.element_locations.size(); ++jj) { - uniform_location_to_index_map_[info.element_locations[jj]] = ii; + location_infos_[info.element_locations[jj]] = LocationInfo(ii, jj); } } valid_ = true; @@ -217,17 +217,18 @@ GLint ProgramManager::ProgramInfo::GetAttribLocation( return -1; } -bool ProgramManager::ProgramInfo::GetUniformTypeByLocation( - GLint location, GLenum* type) const { - if (location >= 0 && - static_cast<size_t>(location) < uniform_location_to_index_map_.size()) { - GLint index = uniform_location_to_index_map_[location]; - if (index >= 0) { - *type = uniform_infos_[index].type; - return true; +const ProgramManager::ProgramInfo::UniformInfo* + ProgramManager::ProgramInfo::GetUniformInfoByLocation( + GLint location, GLint* array_index) const { + DCHECK(array_index); + if (location >= 0 && static_cast<size_t>(location) < location_infos_.size()) { + const LocationInfo& info = location_infos_[location]; + if (info.uniform_index >= 0) { + *array_index = info.array_index; + return &uniform_infos_[info.uniform_index]; } } - return false; + return NULL; } // Note: This is only valid to call right after a program has been linked @@ -313,13 +314,14 @@ const ProgramManager::ProgramInfo::UniformInfo* bool ProgramManager::ProgramInfo::SetSamplers( GLint location, GLsizei count, const GLint* value) { - if (location >= 0 && - static_cast<size_t>(location) < uniform_location_to_index_map_.size()) { - GLint index = uniform_location_to_index_map_[location]; - if (index >= 0) { - UniformInfo& info = uniform_infos_[index]; - if (info.IsSampler() && count <= info.size) { - std::copy(value, value + count, info.texture_units.begin()); + if (location >= 0 && static_cast<size_t>(location) < location_infos_.size()) { + const LocationInfo& location_info = location_infos_[location]; + if (location_info.uniform_index >= 0) { + UniformInfo& info = uniform_infos_[location_info.uniform_index]; + count = std::min(info.size - location_info.array_index, count); + if (info.IsSampler() && count > 0) { + std::copy(value, value + count, + info.texture_units.begin() + location_info.array_index); return true; } } diff --git a/gpu/command_buffer/service/program_manager.h b/gpu/command_buffer/service/program_manager.h index 51a9bf8..5114753 100644 --- a/gpu/command_buffer/service/program_manager.h +++ b/gpu/command_buffer/service/program_manager.h @@ -111,8 +111,9 @@ class ProgramManager { // Gets the location of a uniform by name. GLint GetUniformLocation(const std::string& name) const; - // Gets the type of a uniform by location. - bool GetUniformTypeByLocation(GLint location, GLenum* type) const; + // Gets the UniformInfo of a uniform by location. + const UniformInfo* GetUniformInfoByLocation( + GLint location, GLint* array_index) const; // Sets the sampler values for a uniform. // This is safe to call for any location. If the location is not @@ -155,6 +156,20 @@ class ProgramManager { friend class base::RefCounted<ProgramInfo>; friend class ProgramManager; + // Info for each location + struct LocationInfo { + LocationInfo() + : uniform_index(-1), + array_index(-1) { + } + LocationInfo(GLint _uniform_index, GLint _array_index) + : uniform_index(_uniform_index), + array_index(_array_index) { + } + GLint uniform_index; // index of UniformInfo in uniform_infos_. + GLint array_index; // index of location when used in array. + }; + ~ProgramInfo(); void IncUseCount() { @@ -198,8 +213,8 @@ class ProgramManager { // Uniform info by index. UniformInfoVector uniform_infos_; - // Uniform location to index. - std::vector<GLint> uniform_location_to_index_map_; + // Info for each location. + std::vector<LocationInfo> location_infos_; // The indices of the uniforms that are samplers. SamplerIndices sampler_indices_; diff --git a/gpu/command_buffer/service/program_manager_unittest.cc b/gpu/command_buffer/service/program_manager_unittest.cc index 6e10a38..bec2426 100644 --- a/gpu/command_buffer/service/program_manager_unittest.cc +++ b/gpu/command_buffer/service/program_manager_unittest.cc @@ -511,18 +511,27 @@ TEST_F(ProgramManagerWithShaderTest, GetUniformLocation) { program_info->GetUniformLocation("uniform3[2]")); } -TEST_F(ProgramManagerWithShaderTest, GetUniformTypeByLocation) { +TEST_F(ProgramManagerWithShaderTest, GetUniformInfoByLocation) { const GLint kInvalidLocation = 1234; - GLenum type = 0u; + const ProgramManager::ProgramInfo::UniformInfo* info; const ProgramManager::ProgramInfo* program_info = manager_.GetProgramInfo(kClientProgramId); + GLint array_index = -1; ASSERT_TRUE(program_info != NULL); - EXPECT_TRUE(program_info->GetUniformTypeByLocation(kUniform2Location, &type)); - EXPECT_EQ(kUniform2Type, type); - type = 0u; - EXPECT_FALSE(program_info->GetUniformTypeByLocation( - kInvalidLocation, &type)); - EXPECT_EQ(0u, type); + info = program_info->GetUniformInfoByLocation( + kUniform2Location, &array_index); + EXPECT_EQ(0, array_index); + ASSERT_TRUE(info != NULL); + EXPECT_EQ(kUniform2Type, info->type); + array_index = -1; + info = program_info->GetUniformInfoByLocation( + kInvalidLocation, &array_index); + EXPECT_TRUE(info == NULL); + EXPECT_EQ(-1, array_index); + GLint loc = program_info->GetUniformLocation("uniform2[2]"); + info = program_info->GetUniformInfoByLocation(loc, &array_index); + ASSERT_TRUE(info != NULL); + EXPECT_EQ(2, array_index); } // Some GL drivers incorrectly return gl_DepthRange and possibly other uniforms |