summaryrefslogtreecommitdiffstats
path: root/gpu
diff options
context:
space:
mode:
authorgman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-28 01:09:54 +0000
committergman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-28 01:09:54 +0000
commit2df73893433f075f59c1090b1fc3eb3de876d2ad (patch)
treedf5d59eebea0742eb5f161d72ac83afd1093bfad /gpu
parent93bb08dd51c803739d5e964bc69299bf2b8a3f85 (diff)
downloadchromium_src-2df73893433f075f59c1090b1fc3eb3de876d2ad.zip
chromium_src-2df73893433f075f59c1090b1fc3eb3de876d2ad.tar.gz
chromium_src-2df73893433f075f59c1090b1fc3eb3de876d2ad.tar.bz2
Clear uniforms
TEST=unit tests BUG=124764 R=zmo@chromium.org Review URL: http://codereview.chromium.org/10246004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@134418 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc8
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc80
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h3
-rw-r--r--gpu/command_buffer/service/program_manager.cc89
-rw-r--r--gpu/command_buffer/service/program_manager.h14
5 files changed, 186 insertions, 8 deletions
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 4a8e752..cc864ab 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -4462,7 +4462,11 @@ void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
return;
}
- info->Link();
+ if (info->Link()) {
+ if (info == current_program_.get()) {
+ program_manager()->ClearUniforms(info);
+ }
+ }
};
void GLES2DecoderImpl::DoTexParameterf(
@@ -4776,10 +4780,10 @@ void GLES2DecoderImpl::DoUseProgram(GLuint program) {
program_manager()->UnuseProgram(shader_manager(), current_program_);
}
current_program_ = info;
+ glUseProgram(service_id);
if (current_program_) {
program_manager()->UseProgram(current_program_);
}
- glUseProgram(service_id);
}
GLenum GLES2DecoderImpl::GetGLError() {
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 c0b1e8c..40e98d4 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
@@ -1255,6 +1255,86 @@ void GLES2DecoderTestBase::SetupShader(
link_cmd.Init(program_client_id);
EXPECT_EQ(error::kNoError, ExecuteCmd(link_cmd));
+
+ // Assume the next command will be UseProgram.
+ SetupExpectationsForClearingUniforms(uniforms, num_uniforms);
+}
+
+void GLES2DecoderTestBase::SetupExpectationsForClearingUniforms(
+ UniformInfo* uniforms, size_t num_uniforms) {
+ for (size_t ii = 0; ii < num_uniforms; ++ii) {
+ const UniformInfo& info = uniforms[ii];
+ switch (info.type) {
+ case GL_FLOAT:
+ EXPECT_CALL(*gl_, Uniform1fv(info.real_location, info.size, _))
+ .Times(1)
+ .RetiresOnSaturation();
+ break;
+ case GL_FLOAT_VEC2:
+ EXPECT_CALL(*gl_, Uniform2fv(info.real_location, info.size, _))
+ .Times(1)
+ .RetiresOnSaturation();
+ break;
+ case GL_FLOAT_VEC3:
+ EXPECT_CALL(*gl_, Uniform3fv(info.real_location, info.size, _))
+ .Times(1)
+ .RetiresOnSaturation();
+ break;
+ case GL_FLOAT_VEC4:
+ EXPECT_CALL(*gl_, Uniform4fv(info.real_location, info.size, _))
+ .Times(1)
+ .RetiresOnSaturation();
+ break;
+ case GL_INT:
+ case GL_BOOL:
+ case GL_SAMPLER_2D:
+ case GL_SAMPLER_CUBE:
+ case GL_SAMPLER_EXTERNAL_OES:
+ EXPECT_CALL(*gl_, Uniform1iv(info.real_location, info.size, _))
+ .Times(1)
+ .RetiresOnSaturation();
+ break;
+ case GL_INT_VEC2:
+ case GL_BOOL_VEC2:
+ EXPECT_CALL(*gl_, Uniform2iv(info.real_location, info.size, _))
+ .Times(1)
+ .RetiresOnSaturation();
+ break;
+ case GL_INT_VEC3:
+ case GL_BOOL_VEC3:
+ EXPECT_CALL(*gl_, Uniform3iv(info.real_location, info.size, _))
+ .Times(1)
+ .RetiresOnSaturation();
+ break;
+ case GL_INT_VEC4:
+ case GL_BOOL_VEC4:
+ EXPECT_CALL(*gl_, Uniform4iv(info.real_location, info.size, _))
+ .Times(1)
+ .RetiresOnSaturation();
+ break;
+ case GL_FLOAT_MAT2:
+ EXPECT_CALL(*gl_, UniformMatrix2fv(
+ info.real_location, info.size, false, _))
+ .Times(1)
+ .RetiresOnSaturation();
+ break;
+ case GL_FLOAT_MAT3:
+ EXPECT_CALL(*gl_, UniformMatrix3fv(
+ info.real_location, info.size, false, _))
+ .Times(1)
+ .RetiresOnSaturation();
+ break;
+ case GL_FLOAT_MAT4:
+ EXPECT_CALL(*gl_, UniformMatrix4fv(
+ info.real_location, info.size, false, _))
+ .Times(1)
+ .RetiresOnSaturation();
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ }
}
void GLES2DecoderTestBase::DoEnableVertexAttribArray(GLint index) {
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
index 85bfe1d..64d47f6 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
@@ -176,6 +176,9 @@ class GLES2DecoderTestBase : public testing::Test {
GLuint vertex_shader_client_id, GLuint vertex_shader_service_id,
GLuint fragment_shader_client_id, GLuint fragment_shader_service_id);
+ void SetupExpectationsForClearingUniforms(
+ UniformInfo* uniforms, size_t num_uniforms);
+
// Setups up a shader for testing glUniform.
void SetupShaderForUniform();
void SetupDefaultProgram();
diff --git a/gpu/command_buffer/service/program_manager.cc b/gpu/command_buffer/service/program_manager.cc
index e40d23a..1669173 100644
--- a/gpu/command_buffer/service/program_manager.cc
+++ b/gpu/command_buffer/service/program_manager.cc
@@ -12,6 +12,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/string_number_conversions.h"
#include "gpu/command_buffer/common/gles2_cmd_format.h"
+#include "gpu/command_buffer/common/gles2_cmd_utils.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
namespace gpu {
@@ -58,7 +59,8 @@ ProgramManager::ProgramInfo::ProgramInfo(
service_id_(service_id),
deleted_(false),
valid_(false),
- link_status_(false) {
+ link_status_(false),
+ uniforms_cleared_(false) {
manager_->StartTracking(this);
}
@@ -88,10 +90,80 @@ void ProgramManager::ProgramInfo::UpdateLogInfo() {
set_log_info(std::string(temp.get(), len).c_str());
}
+void ProgramManager::ProgramInfo::ClearUniforms(
+ std::vector<uint8>* zero_buffer) {
+ DCHECK(zero_buffer);
+ if (uniforms_cleared_) {
+ return;
+ }
+ uniforms_cleared_ = true;
+ for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) {
+ const UniformInfo& uniform_info = uniform_infos_[ii];
+ GLint location = uniform_info.element_locations[0];
+ GLsizei size = uniform_info.size;
+ uint32 unit_size = GLES2Util::GetGLDataTypeSizeForUniforms(
+ uniform_info.type);
+ uint32 size_needed = size * unit_size;
+ if (size_needed > zero_buffer->size()) {
+ zero_buffer->resize(size_needed, 0u);
+ }
+ const void* zero = &(*zero_buffer)[0];
+ switch (uniform_info.type) {
+ case GL_FLOAT:
+ glUniform1fv(location, size, reinterpret_cast<const GLfloat*>(zero));
+ break;
+ case GL_FLOAT_VEC2:
+ glUniform2fv(location, size, reinterpret_cast<const GLfloat*>(zero));
+ break;
+ case GL_FLOAT_VEC3:
+ glUniform3fv(location, size, reinterpret_cast<const GLfloat*>(zero));
+ break;
+ case GL_FLOAT_VEC4:
+ glUniform4fv(location, size, reinterpret_cast<const GLfloat*>(zero));
+ break;
+ case GL_INT:
+ case GL_BOOL:
+ case GL_SAMPLER_2D:
+ case GL_SAMPLER_CUBE:
+ case GL_SAMPLER_EXTERNAL_OES:
+ glUniform1iv(location, size, reinterpret_cast<const GLint*>(zero));
+ break;
+ case GL_INT_VEC2:
+ case GL_BOOL_VEC2:
+ glUniform2iv(location, size, reinterpret_cast<const GLint*>(zero));
+ break;
+ case GL_INT_VEC3:
+ case GL_BOOL_VEC3:
+ glUniform3iv(location, size, reinterpret_cast<const GLint*>(zero));
+ break;
+ case GL_INT_VEC4:
+ case GL_BOOL_VEC4:
+ glUniform4iv(location, size, reinterpret_cast<const GLint*>(zero));
+ break;
+ case GL_FLOAT_MAT2:
+ glUniformMatrix2fv(
+ location, size, false, reinterpret_cast<const GLfloat*>(zero));
+ break;
+ case GL_FLOAT_MAT3:
+ glUniformMatrix3fv(
+ location, size, false, reinterpret_cast<const GLfloat*>(zero));
+ break;
+ case GL_FLOAT_MAT4:
+ glUniformMatrix4fv(
+ location, size, false, reinterpret_cast<const GLfloat*>(zero));
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ }
+}
+
void ProgramManager::ProgramInfo::Update() {
Reset();
UpdateLogInfo();
link_status_ = true;
+ uniforms_cleared_ = false;
GLint num_attribs = 0;
GLint max_len = 0;
GLint max_location = -1;
@@ -177,25 +249,26 @@ void ProgramManager::ProgramInfo::ExecuteBindAttribLocationCalls() {
}
}
-void ProgramManager::ProgramInfo::Link() {
+bool ProgramManager::ProgramInfo::Link() {
ClearLinkStatus();
if (!CanLink()) {
set_log_info("missing shaders");
- return;
+ return false;
}
if (DetectAttribLocationBindingConflicts()) {
set_log_info("glBindAttribLocation() conflicts");
- return;
+ return false;
}
ExecuteBindAttribLocationCalls();
glLinkProgram(service_id());
GLint success = 0;
glGetProgramiv(service_id(), GL_LINK_STATUS, &success);
- if (success) {
+ if (success == GL_TRUE) {
Update();
} else {
UpdateLogInfo();
}
+ return success == GL_TRUE;
}
void ProgramManager::ProgramInfo::Validate() {
@@ -692,6 +765,7 @@ void ProgramManager::UseProgram(ProgramManager::ProgramInfo* info) {
DCHECK(info);
DCHECK(IsOwned(info));
info->IncUseCount();
+ ClearUniforms(info);
}
void ProgramManager::UnuseProgram(
@@ -704,6 +778,11 @@ void ProgramManager::UnuseProgram(
RemoveProgramInfoIfUnused(shader_manager, info);
}
+void ProgramManager::ClearUniforms(ProgramManager::ProgramInfo* info) {
+ DCHECK(info);
+ info->ClearUniforms(&zero_);
+}
+
// Swizzles the locations to prevent developers from assuming they
// can do math on uniforms. According to the OpenGL ES 2.0 spec
// the location of "someuniform[1]" is not 'n' more than "someuniform[0]".
diff --git a/gpu/command_buffer/service/program_manager.h b/gpu/command_buffer/service/program_manager.h
index 232db91..43433f8 100644
--- a/gpu/command_buffer/service/program_manager.h
+++ b/gpu/command_buffer/service/program_manager.h
@@ -144,7 +144,7 @@ class GPU_EXPORT ProgramManager {
bool CanLink() const;
// Performs glLinkProgram and related activities.
- void Link();
+ bool Link();
// Performs glValidateProgram and related activities.
void Validate();
@@ -211,6 +211,9 @@ class GPU_EXPORT ProgramManager {
// Updates the program log info from GL
void UpdateLogInfo();
+ // Clears all the uniforms.
+ void ClearUniforms(std::vector<uint8>* zero_buffer);
+
// If long attribate names are mapped during shader translation, call
// glBindAttribLocation() again with the mapped names.
// This is called right before the glLink() call, but after shaders are
@@ -272,6 +275,9 @@ class GPU_EXPORT ProgramManager {
// This is true if glLinkProgram was successful last time it was called.
bool link_status_;
+ // True if the uniforms have been cleared.
+ bool uniforms_cleared_;
+
// Log info
scoped_ptr<std::string> log_info_;
@@ -303,6 +309,9 @@ class GPU_EXPORT ProgramManager {
// Makes a program as unused. If deleted the program info will be removed.
void UnuseProgram(ShaderManager* shader_manager, ProgramInfo* info);
+ // Clears the uniforms for this program.
+ void ClearUniforms(ProgramInfo* info);
+
// Returns true if prefix is invalid for gl.
static bool IsInvalidPrefix(const char* name, size_t length);
@@ -329,6 +338,9 @@ class GPU_EXPORT ProgramManager {
bool have_context_;
+ // Used to clear uniforms.
+ std::vector<uint8> zero_;
+
void RemoveProgramInfoIfUnused(
ShaderManager* shader_manager, ProgramInfo* info);