Make Command Buffer limit count for glUniformXXv calls.
TEST=unit tests
BUG=77233
[email protected],
Review URL: http://codereview.chromium.org/6713094
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@79421 0039d316-1c4b-4281-b951-d872f2087c98
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 @@
// 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 @@
// 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 @@
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 @@
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 @@
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::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::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::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::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 @@
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");