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 20c4da8efce5dea9ded6e230dde087e69c9cf0b9..dbfbccf47229b6f4508658c548133146efa14a4c 100644 |
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc |
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc |
@@ -1202,6 +1202,11 @@ class GLES2DecoderImpl : public GLES2Decoder, |
// location is not -1. |
bool CheckCurrentProgramForUniform(GLint location, const char* function_name); |
+ // Checks if the current program samples a texture that is also the color |
+ // image of the current bound framebuffer, i.e., the source and destination |
+ // of the draw operation are the same. |
+ bool CheckDrawingFeedbackLoops(); |
+ |
// 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 |
@@ -5755,6 +5760,38 @@ bool GLES2DecoderImpl::CheckCurrentProgramForUniform( |
return location != -1; |
} |
+bool GLES2DecoderImpl::CheckDrawingFeedbackLoops() { |
Ken Russell (switch to Gerrit)
2014/10/16 21:08:30
Have you checked any benchmarks -- e.g. http://web
|
+ Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER); |
+ if (!framebuffer) |
+ return false; |
+ const Framebuffer::Attachment* attachment = |
+ framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0); |
+ if (!attachment) |
+ return false; |
+ |
+ DCHECK(state_.current_program.get()); |
+ const Program::SamplerIndices& sampler_indices = |
+ state_.current_program->sampler_indices(); |
+ for (size_t ii = 0; ii < sampler_indices.size(); ++ii) { |
+ const Program::UniformInfo* uniform_info = |
+ state_.current_program->GetUniformInfo(sampler_indices[ii]); |
+ DCHECK(uniform_info); |
+ if (uniform_info->type != GL_SAMPLER_2D) |
+ continue; |
+ for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) { |
+ GLuint texture_unit_index = uniform_info->texture_units[jj]; |
+ if (texture_unit_index >= state_.texture_units.size()) |
+ continue; |
+ TextureUnit& texture_unit = state_.texture_units[texture_unit_index]; |
+ TextureRef* texture_ref = |
+ texture_unit.GetInfoForSamplerType(GL_SAMPLER_2D).get(); |
+ if (attachment->IsTexture(texture_ref)) |
+ return true; |
+ } |
+ } |
+ return false; |
+} |
+ |
bool GLES2DecoderImpl::PrepForSetUniformByLocation( |
GLint fake_location, |
const char* function_name, |
@@ -6251,6 +6288,13 @@ bool GLES2DecoderImpl::IsDrawValid( |
return false; |
} |
+ if (CheckDrawingFeedbackLoops()) { |
+ LOCAL_SET_GL_ERROR( |
+ GL_INVALID_OPERATION, function_name, |
+ "Source and destination textures of the draw are the same."); |
+ return false; |
+ } |
+ |
return state_.vertex_attrib_manager |
->ValidateBindings(function_name, |
this, |