summaryrefslogtreecommitdiffstats
path: root/gpu
diff options
context:
space:
mode:
authorgman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-25 18:35:36 +0000
committergman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-25 18:35:36 +0000
commit43c2f1f8071ddcf6ef9c4402d248e63375cda943 (patch)
treee38d7d14722630bcaa73c781c4d0d4d917cc45e6 /gpu
parentca82a57b77b455e132feaf8f010643f91af07759 (diff)
downloadchromium_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')
-rwxr-xr-xgpu/command_buffer/build_gles2_cmd_buffer.py82
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc130
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_autogen.h24
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc34
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc82
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h113
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc2
-rw-r--r--gpu/command_buffer/service/program_manager.cc42
-rw-r--r--gpu/command_buffer/service/program_manager.h23
-rw-r--r--gpu/command_buffer/service/program_manager_unittest.cc25
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