diff options
author | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-21 00:49:13 +0000 |
---|---|---|
committer | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-21 00:49:13 +0000 |
commit | a0c3e97d31ec8cad60f4ae355c36032a58cb8f64 (patch) | |
tree | 628d4c2ff01edd2b125a307513c39b95a50a43da /gpu | |
parent | 15406b6ab2f2c701d6e82c8e53c22d1c570c739a (diff) | |
download | chromium_src-a0c3e97d31ec8cad60f4ae355c36032a58cb8f64.zip chromium_src-a0c3e97d31ec8cad60f4ae355c36032a58cb8f64.tar.gz chromium_src-a0c3e97d31ec8cad60f4ae355c36032a58cb8f64.tar.bz2 |
Some GL drivers incorrectly return "gl_DepthRange.far" as
a uniform when querying the uniforms. This CL checks for
that condition and hides that from the client programs.
TEST=unit tests
BUG=none
Review URL: http://codereview.chromium.org/1700002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@45131 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
-rwxr-xr-x | gpu/command_buffer/build_gles2_cmd_buffer.py | 6 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder.cc | 16 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder_autogen.h | 2 | ||||
-rw-r--r-- | gpu/command_buffer/service/program_manager.cc | 81 | ||||
-rw-r--r-- | gpu/command_buffer/service/program_manager.h | 36 | ||||
-rw-r--r-- | gpu/command_buffer/service/program_manager_unittest.cc | 52 |
6 files changed, 143 insertions, 50 deletions
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index 7b9c86e..b2782cb 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py @@ -1120,7 +1120,11 @@ _FUNCTION_INFO = { 'result': ['GLuint'], 'unit_test': False, }, - 'GetProgramiv': {'type': 'GETn', 'result': ['SizedResult<GLint>']}, + 'GetProgramiv': { + 'type': 'GETn', + 'decoder_func': 'DoGetProgramiv', + 'result': ['SizedResult<GLint>'], + }, 'GetProgramInfoLog': { 'type': 'STRn', 'get_len_func': 'glGetProgramiv', diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 2b35aa0..3cc59e6 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -700,13 +700,17 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, void DoGetFramebufferAttachmentParameteriv( GLenum target, GLenum attachment, GLenum pname, GLint* params); - // Wrapper for DoGetIntegerv. + // Wrapper for glGetIntegerv. void DoGetIntegerv(GLenum pname, GLint* params); // Gets the max value in a range in a buffer. GLuint DoGetMaxValueInBuffer( GLuint buffer_id, GLsizei count, GLenum type, GLuint offset); + // Wrapper for glGetProgramiv. + void DoGetProgramiv( + GLuint program_id, GLenum pname, GLint* params); + // Wrapper for glRenderbufferParameteriv. void DoGetRenderbufferParameteriv( GLenum target, GLenum pname, GLint* params); @@ -1985,6 +1989,16 @@ void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) { } } +void GLES2DecoderImpl::DoGetProgramiv( + GLuint program_id, GLenum pname, GLint* params) { + ProgramManager::ProgramInfo* info = GetProgramInfo(program_id); + if (!info) { + SetGLError(GL_INVALID_OPERATION); + return; + } + info->GetProgramiv(pname, params); +} + error::Error GLES2DecoderImpl::HandleBindAttribLocation( uint32 immediate_data_size, const gles2::BindAttribLocation& c) { GLuint program; diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h index 0bda376..fd0c9f8 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h @@ -1176,7 +1176,7 @@ error::Error GLES2DecoderImpl::HandleGetProgramiv( return error::kInvalidArguments; } CopyRealGLErrorsToWrapper(); - glGetProgramiv(program, pname, params); + DoGetProgramiv(program, pname, params); GLenum error = glGetError(); if (error == GL_NO_ERROR) { result->SetNumResults(num_values); diff --git a/gpu/command_buffer/service/program_manager.cc b/gpu/command_buffer/service/program_manager.cc index 88dd714..43b0148 100644 --- a/gpu/command_buffer/service/program_manager.cc +++ b/gpu/command_buffer/service/program_manager.cc @@ -21,29 +21,36 @@ bool ProgramManager::IsInvalidPrefix(const char* name, size_t length) { void ProgramManager::ProgramInfo::Update() { GLint num_attribs = 0; GLint max_len = 0; + max_uniform_name_length_ = 0; + max_attrib_name_length_ = 0; glGetProgramiv(program_id_, GL_ACTIVE_ATTRIBUTES, &num_attribs); - attrib_infos_.resize(num_attribs); glGetProgramiv(program_id_, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_len); // TODO(gman): Should we check for error? scoped_array<char> name_buffer(new char[max_len]); + attrib_infos_.clear(); for (GLint ii = 0; ii < num_attribs; ++ii) { GLsizei length; GLsizei size; GLenum type; glGetActiveAttrib( program_id_, ii, max_len, &length, &size, &type, name_buffer.get()); - // TODO(gman): Should we check for error? - GLint location = IsInvalidPrefix(name_buffer.get(), length) ? -1 : - glGetAttribLocation(program_id_, name_buffer.get()); - SetAttributeInfo(ii, size, type, location, name_buffer.get()); + if (!IsInvalidPrefix(name_buffer.get(), length)) { + // TODO(gman): Should we check for error? + GLint location = glGetAttribLocation(program_id_, name_buffer.get()); + attrib_infos_.push_back( + VertexAttribInfo(size, type, name_buffer.get(), location)); + max_attrib_name_length_ = std::max(max_attrib_name_length_, length); + } } + GLint num_uniforms; glGetProgramiv(program_id_, GL_ACTIVE_UNIFORMS, &num_uniforms); - uniform_infos_.resize(num_uniforms); + uniform_infos_.clear(); sampler_indices_.clear(); glGetProgramiv(program_id_, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_len); name_buffer.reset(new char[max_len]); GLint max_location = -1; + int index = 0; // this index tracks valid uniforms. for (GLint ii = 0; ii < num_uniforms; ++ii) { GLsizei length; GLsizei size; @@ -51,17 +58,22 @@ void ProgramManager::ProgramInfo::Update() { glGetActiveUniform( program_id_, ii, max_len, &length, &size, &type, name_buffer.get()); // TODO(gman): Should we check for error? - GLint location = IsInvalidPrefix(name_buffer.get(), length) ? -1 : - glGetUniformLocation(program_id_, name_buffer.get()); - SetUniformInfo(ii, size, type, location, name_buffer.get()); - const UniformInfo& info = uniform_infos_[ii]; - for (size_t jj = 0; jj < info.element_locations.size(); ++jj) { - if (info.element_locations[jj] > max_location) { - max_location = info.element_locations[jj]; + if (!IsInvalidPrefix(name_buffer.get(), length)) { + GLint location = glGetUniformLocation(program_id_, name_buffer.get()); + const UniformInfo* info = + AddUniformInfo(size, type, location, name_buffer.get()); + for (size_t jj = 0; jj < info->element_locations.size(); ++jj) { + if (info->element_locations[jj] > max_location) { + max_location = info->element_locations[jj]; + } } - } - if (info.IsSampler()) { - sampler_indices_.push_back(ii); + if (info->IsSampler()) { + sampler_indices_.push_back(index); + } + max_uniform_name_length_ = + std::max(max_uniform_name_length_, + static_cast<GLsizei>(info->name.size())); + ++index; } } // Create location to index map. @@ -69,7 +81,7 @@ void ProgramManager::ProgramInfo::Update() { for (GLint ii = 0; ii <= max_location; ++ii) { location_to_index_map_[ii] = -1; } - for (GLint ii = 0; ii < num_uniforms; ++ii) { + 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) { location_to_index_map_[info.element_locations[jj]] = ii; @@ -137,15 +149,12 @@ bool ProgramManager::ProgramInfo::GetUniformTypeByLocation( return false; } -void ProgramManager::ProgramInfo::SetUniformInfo( - GLint index, GLsizei size, GLenum type, GLint location, - const std::string& name) { - DCHECK(static_cast<unsigned>(index) < uniform_infos_.size()); +const ProgramManager::ProgramInfo::UniformInfo* + ProgramManager::ProgramInfo::AddUniformInfo( + GLsizei size, GLenum type, GLint location, const std::string& name) { const char* kArraySpec = "[0]"; - UniformInfo& info = uniform_infos_[index]; - info.size = size; - info.type = type; - info.name = name; + uniform_infos_.push_back(UniformInfo(size, type, name)); + UniformInfo& info = uniform_infos_.back(); info.element_locations.resize(size); info.element_locations[0] = location; size_t num_texture_units = info.IsSampler() ? size : 0u; @@ -178,6 +187,8 @@ void ProgramManager::ProgramInfo::SetUniformInfo( (size > 1 || (info.name.size() > 3 && info.name.rfind(kArraySpec) == info.name.size() - 3)); + + return &info; } bool ProgramManager::ProgramInfo::SetSamplers( @@ -196,6 +207,26 @@ bool ProgramManager::ProgramInfo::SetSamplers( return false; } +void ProgramManager::ProgramInfo::GetProgramiv(GLenum pname, GLint* params) { + switch (pname) { + case GL_ACTIVE_ATTRIBUTES: + *params = attrib_infos_.size(); + break; + case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH: + *params = max_attrib_name_length_; + break; + case GL_ACTIVE_UNIFORMS: + *params = uniform_infos_.size(); + break; + case GL_ACTIVE_UNIFORM_MAX_LENGTH: + *params = max_uniform_name_length_; + break; + default: + glGetProgramiv(program_id_, pname, params); + break; + } +} + void ProgramManager::CreateProgramInfo(GLuint program_id) { std::pair<ProgramInfoMap::iterator, bool> result = program_infos_.insert( diff --git a/gpu/command_buffer/service/program_manager.h b/gpu/command_buffer/service/program_manager.h index c890d21..48c5440 100644 --- a/gpu/command_buffer/service/program_manager.h +++ b/gpu/command_buffer/service/program_manager.h @@ -30,6 +30,11 @@ class ProgramManager { typedef scoped_refptr<ProgramInfo> Ref; struct UniformInfo { + UniformInfo(GLsizei _size, GLenum _type, const std::string& _name) + : size(_size), + type(_type), + name(_name) { + } bool IsSampler() const { return type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE; } @@ -42,6 +47,13 @@ class ProgramManager { std::vector<GLuint> texture_units; }; struct VertexAttribInfo { + VertexAttribInfo(GLsizei _size, GLenum _type, const std::string& _name, + GLint _location) + : size(_size), + type(_type), + location(_location), + name(_name) { + } GLsizei size; GLenum type; GLint location; @@ -53,7 +65,9 @@ class ProgramManager { typedef std::vector<int> SamplerIndices; explicit ProgramInfo(GLuint program_id) - : program_id_(program_id) { + : max_attrib_name_length_(0), + max_uniform_name_length_(0), + program_id_(program_id) { } const SamplerIndices& sampler_indices() { @@ -93,6 +107,8 @@ class ProgramManager { return program_id_ == 0; } + void GetProgramiv(GLenum pname, GLint* params); + private: friend class base::RefCounted<ProgramInfo>; friend class ProgramManager; @@ -103,23 +119,15 @@ class ProgramManager { program_id_ = 0; } - void SetAttributeInfo( - GLint index, GLsizei size, GLenum type, GLint location, - const std::string& name) { - DCHECK(static_cast<unsigned>(index) < attrib_infos_.size()); - VertexAttribInfo& info = attrib_infos_[index]; - info.size = size; - info.type = type; - info.name = name; - info.location = location; - } + const UniformInfo* AddUniformInfo( + GLsizei size, GLenum type, GLint location, const std::string& name); - void SetUniformInfo( - GLint index, GLsizei size, GLenum type, GLint location, - const std::string& name); + GLsizei max_attrib_name_length_; AttribInfoVector attrib_infos_; + GLsizei max_uniform_name_length_; + // Uniform info by index. UniformInfoVector uniform_infos_; diff --git a/gpu/command_buffer/service/program_manager_unittest.cc b/gpu/command_buffer/service/program_manager_unittest.cc index 32d5a5a..c0f1409 100644 --- a/gpu/command_buffer/service/program_manager_unittest.cc +++ b/gpu/command_buffer/service/program_manager_unittest.cc @@ -64,7 +64,6 @@ class ProgramManagerWithShaderTest : public testing::Test { static const GLuint kProgramId = 123; - static const GLint kMaxAttribLength = 10; static const char* kAttrib1Name; static const char* kAttrib2Name; static const char* kAttrib3Name; @@ -80,7 +79,6 @@ class ProgramManagerWithShaderTest : public testing::Test { static const GLint kInvalidAttribLocation = 30; static const GLint kBadAttribIndex = kNumVertexAttribs; - static const GLint kMaxUniformLength = 12; static const char* kUniform1Name; static const char* kUniform2Name; static const char* kUniform3Name; @@ -133,15 +131,20 @@ class ProgramManagerWithShaderTest : public testing::Test { GetProgramiv(service_id, GL_ACTIVE_ATTRIBUTES, _)) .WillOnce(SetArgumentPointee<2>(num_attribs)) .RetiresOnSaturation(); + size_t max_attrib_len = 0; + for (size_t ii = 0; ii < num_attribs; ++ii) { + size_t len = strlen(attribs[ii].name) + 1; + max_attrib_len = std::max(max_attrib_len, len); + } EXPECT_CALL(*gl_, GetProgramiv(service_id, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, _)) - .WillOnce(SetArgumentPointee<2>(kMaxAttribLength)) + .WillOnce(SetArgumentPointee<2>(max_attrib_len)) .RetiresOnSaturation(); for (size_t ii = 0; ii < num_attribs; ++ii) { const AttribInfo& info = attribs[ii]; EXPECT_CALL(*gl_, GetActiveAttrib(service_id, ii, - kMaxAttribLength, _, _, _, _)) + max_attrib_len, _, _, _, _)) .WillOnce(DoAll( SetArgumentPointee<3>(strlen(info.name)), SetArgumentPointee<4>(info.size), @@ -160,15 +163,20 @@ class ProgramManagerWithShaderTest : public testing::Test { GetProgramiv(service_id, GL_ACTIVE_UNIFORMS, _)) .WillOnce(SetArgumentPointee<2>(num_uniforms)) .RetiresOnSaturation(); + size_t max_uniform_len = 0; + for (size_t ii = 0; ii < num_uniforms; ++ii) { + size_t len = strlen(uniforms[ii].name) + 1; + max_uniform_len = std::max(max_uniform_len, len); + } EXPECT_CALL(*gl_, GetProgramiv(service_id, GL_ACTIVE_UNIFORM_MAX_LENGTH, _)) - .WillOnce(SetArgumentPointee<2>(kMaxUniformLength)) + .WillOnce(SetArgumentPointee<2>(max_uniform_len)) .RetiresOnSaturation(); for (size_t ii = 0; ii < num_uniforms; ++ii) { const UniformInfo& info = uniforms[ii]; EXPECT_CALL(*gl_, GetActiveUniform(service_id, ii, - kMaxUniformLength, _, _, _, _)) + max_uniform_len, _, _, _, _)) .WillOnce(DoAll( SetArgumentPointee<3>(strlen(info.name)), SetArgumentPointee<4>(info.size), @@ -225,7 +233,6 @@ ProgramManagerWithShaderTest::AttribInfo #ifndef COMPILER_MSVC const GLint ProgramManagerWithShaderTest::kNumVertexAttribs; const GLuint ProgramManagerWithShaderTest::kProgramId; -const GLint ProgramManagerWithShaderTest::kMaxAttribLength; const GLint ProgramManagerWithShaderTest::kAttrib1Size; const GLint ProgramManagerWithShaderTest::kAttrib2Size; const GLint ProgramManagerWithShaderTest::kAttrib3Size; @@ -237,7 +244,6 @@ const GLenum ProgramManagerWithShaderTest::kAttrib2Type; const GLenum ProgramManagerWithShaderTest::kAttrib3Type; const GLint ProgramManagerWithShaderTest::kInvalidAttribLocation; const GLint ProgramManagerWithShaderTest::kBadAttribIndex; -const GLint ProgramManagerWithShaderTest::kMaxUniformLength; const GLint ProgramManagerWithShaderTest::kUniform1Size; const GLint ProgramManagerWithShaderTest::kUniform2Size; const GLint ProgramManagerWithShaderTest::kUniform3Size; @@ -384,6 +390,36 @@ TEST_F(ProgramManagerWithShaderTest, GetUniformTypeByLocation) { EXPECT_EQ(0u, type); } +// Some GL drivers incorrectly return gl_DepthRange and possibly other uniforms +// that start with "gl_". Our implementation catches these and does not allow +// them back to client. +TEST_F(ProgramManagerWithShaderTest, GLDriverReturnsGLUnderscoreUniform) { + static const char* kUniform2Name = "gl_longNameWeCanCheckFor"; + static ProgramManagerWithShaderTest::UniformInfo kUniforms[] = { + { kUniform1Name, kUniform1Size, kUniform1Type, kUniform1Location, }, + { kUniform2Name, kUniform2Size, kUniform2Type, kUniform2Location, }, + { kUniform3Name, kUniform3Size, kUniform3Type, kUniform3Location, }, + }; + const size_t kNumUniforms = arraysize(kUniforms); + static const GLuint kProgramId = 1234; + SetupShader(kAttribs, kNumAttribs, kUniforms, kNumUniforms, kProgramId); + manager_.CreateProgramInfo(kProgramId); + ProgramManager::ProgramInfo* program_info = + manager_.GetProgramInfo(kProgramId); + ASSERT_TRUE(program_info != NULL); + program_info->Update(); + GLint value = 0; + program_info->GetProgramiv(GL_ACTIVE_ATTRIBUTES, &value); + EXPECT_EQ(3, value); + // Check that we skipped the "gl_" uniform. + program_info->GetProgramiv(GL_ACTIVE_UNIFORMS, &value); + EXPECT_EQ(2, value); + // Check that our max length adds room for the array spec and is not as long + // as the "gl_" uniform we skipped. + program_info->GetProgramiv(GL_ACTIVE_UNIFORM_MAX_LENGTH, &value); + EXPECT_EQ(strlen(kUniform3Name) + 3u, static_cast<size_t>(value)); +} + } // namespace gles2 } // namespace gpu |