Index: gpu/command_buffer/service/gles2_cmd_decoder.cc |
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc |
index 0b8d68d80f362255cdd347cf5335a116dd0ed0b9..67cdf0aa7bb7438dccbc66154e4d209fda3fff8e 100644 |
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc |
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc |
@@ -943,6 +943,10 @@ class GLES2DecoderImpl : public GLES2Decoder, |
void DoCreateAndConsumeTextureCHROMIUM(GLenum target, const GLbyte* key, |
GLuint client_id); |
+ void DoSubscribeUniformCHROMIUM(GLint locaton, GLenum target); |
+ void DoUnsubscribeUniformCHROMIUM(GLint location); |
+ void DoPopulateSubscribedUniformsCHROMIUM(); |
+ |
void DoBindTexImage2DCHROMIUM( |
GLenum target, |
GLint image_id); |
@@ -1192,6 +1196,13 @@ class GLES2DecoderImpl : public GLES2Decoder, |
// of the draw operation are the same. |
bool CheckDrawingFeedbackLoops(); |
+ // Checks if |api_type| is valid for the given uniform |
+ // If the api type is not valid generates the appropriate GL |
+ // error. Returns true if |api_type| is valid for the uniform |
+ bool CheckUniformForApiType(const Program::UniformInfo* info, |
+ const char* function_name, |
+ Program::UniformApiType api_type); |
+ |
// 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. Adjusts count so it |
@@ -1203,6 +1214,8 @@ class GLES2DecoderImpl : public GLES2Decoder, |
GLenum* type, |
GLsizei* count); |
+ void PopulateSubscribedUniforms(Program* program); |
+ |
// Gets the service id for any simulated backbuffer fbo. |
GLuint GetBackbufferServiceId() const; |
@@ -1582,6 +1595,8 @@ class GLES2DecoderImpl : public GLES2Decoder, |
GLsizei width, GLsizei height, GLenum format, |
Texture* texture); |
+ bool ValidateSubscribeUniform(GLint fake_location, GLenum target); |
+ |
void RenderWarning(const char* filename, int line, const std::string& msg); |
void PerformanceWarning( |
const char* filename, int line, const std::string& msg); |
@@ -5772,6 +5787,19 @@ bool GLES2DecoderImpl::CheckDrawingFeedbackLoops() { |
return false; |
} |
+bool GLES2DecoderImpl::CheckUniformForApiType( |
+ const Program::UniformInfo* info, |
+ const char* function_name, |
+ Program::UniformApiType api_type) { |
+ DCHECK(info); |
+ if ((api_type & info->accepts_api_type) == 0) { |
+ LOCAL_SET_GL_ERROR( |
+ GL_INVALID_OPERATION, function_name, "wrong uniform function for type"); |
+ return false; |
+ } |
+ return true; |
+} |
+ |
bool GLES2DecoderImpl::PrepForSetUniformByLocation( |
GLint fake_location, |
const char* function_name, |
@@ -5795,11 +5823,7 @@ bool GLES2DecoderImpl::PrepForSetUniformByLocation( |
GL_INVALID_OPERATION, function_name, "unknown location"); |
return false; |
} |
- |
- if ((api_type & info->accepts_api_type) == 0) { |
- LOCAL_SET_GL_ERROR( |
- GL_INVALID_OPERATION, function_name, |
- "wrong uniform function for type"); |
+ if (!CheckUniformForApiType(info, function_name, api_type)) { |
return false; |
} |
if (*count > 1 && !info->is_array) { |
@@ -5815,6 +5839,16 @@ bool GLES2DecoderImpl::PrepForSetUniformByLocation( |
return true; |
} |
+void GLES2DecoderImpl::PopulateSubscribedUniforms(Program* program) { |
+ const Program::SubscriptionMap& subscription_map = |
+ program->subscription_map(); |
+ for (Program::SubscriptionMap::const_iterator it = subscription_map.begin(); |
+ it != subscription_map.end(); |
+ ++it) { |
+ // TODO(orglofch): |
+ } |
+} |
+ |
void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) { |
GLenum type = 0; |
GLsizei count = 1; |
@@ -6075,6 +6109,9 @@ void GLES2DecoderImpl::DoUseProgram(GLuint program_id) { |
program_manager()->UseProgram(state_.current_program.get()); |
if (workarounds().clear_uniforms_before_first_program_use) |
program_manager()->ClearUniforms(program); |
+ if (program->needs_update_subscriptions()) { |
+ PopulateSubscribedUniforms(program); |
+ } |
} |
} |
@@ -10673,6 +10710,63 @@ void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target, |
texture_ref = texture_manager()->Consume(client_id, texture); |
} |
+bool GLES2DecoderImpl::ValidateSubscribeUniform(GLint fake_location, |
+ GLenum target) { |
+ if (!CheckCurrentProgramForUniform(fake_location, |
+ "glSubscribeUniformCHROMIUM")) { |
+ return false; |
+ } |
+ GLint array_index = -1; |
+ GLint real_location = -1; |
+ const Program::UniformInfo* info = |
+ state_.current_program->GetUniformInfoByFakeLocation( |
+ fake_location, &real_location, &array_index); |
+ if (!info) { |
+ LOCAL_SET_GL_ERROR( |
+ GL_INVALID_OPERATION, "glSubscribeUniformCHROMIUM", "unknown location"); |
+ return false; |
+ } |
+ if (!CheckUniformForApiType( |
+ info, |
+ "glSubscribeUniformCHROMIUM", |
+ program_manager()->ApiTypeForSubscriptionTarget(target))) { |
+ return false; |
+ } |
+ return true; |
+} |
+ |
+void GLES2DecoderImpl::DoSubscribeUniformCHROMIUM(GLint location, |
+ GLenum target) { |
+ TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoSubscribeUniformCHROMIUM"); |
+ if (!ValidateSubscribeUniform(location, target)) { |
+ return; |
+ } |
+ if (state_.current_program.get()) { |
+ state_.current_program.get()->AddSubscription(location, target); |
+ } |
+} |
+ |
+void GLES2DecoderImpl::DoUnsubscribeUniformCHROMIUM(GLint location) { |
+ TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoUnsubscribeUniformCHROMIUM"); |
+ if (!CheckCurrentProgramForUniform(location, |
+ "glUnsubscribeUniformCHROMIUM")) { |
+ return; |
+ } |
+ if (state_.current_program.get()) { |
+ state_.current_program.get()->RemoveSubscription(location); |
+ } |
+} |
+ |
+void GLES2DecoderImpl::DoPopulateSubscribedUniformsCHROMIUM() { |
+ TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoPopulateSubscribedUniformsCHROMIUM"); |
+ program_manager()->ActivateUniformSubscriptionState(); |
+ // Defer population of other programs until calls to DoUseProgram |
+ if (state_.current_program.get() && |
+ state_.current_program.get()->needs_update_subscriptions()) { |
+ PopulateSubscribedUniforms(state_.current_program.get()); |
+ } |
+} |
+ |
void GLES2DecoderImpl::DoInsertEventMarkerEXT( |
GLsizei length, const GLchar* marker) { |
if (!marker) { |