summaryrefslogtreecommitdiffstats
path: root/gpu
diff options
context:
space:
mode:
authorgman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-21 00:49:13 +0000
committergman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-21 00:49:13 +0000
commita0c3e97d31ec8cad60f4ae355c36032a58cb8f64 (patch)
tree628d4c2ff01edd2b125a307513c39b95a50a43da /gpu
parent15406b6ab2f2c701d6e82c8e53c22d1c570c739a (diff)
downloadchromium_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-xgpu/command_buffer/build_gles2_cmd_buffer.py6
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc16
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_autogen.h2
-rw-r--r--gpu/command_buffer/service/program_manager.cc81
-rw-r--r--gpu/command_buffer/service/program_manager.h36
-rw-r--r--gpu/command_buffer/service/program_manager_unittest.cc52
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