Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(283)

Unified Diff: gpu/command_buffer/service/gles2_cmd_decoder.cc

Issue 2142353002: Validate fbo color image format and fragment shader output variable type. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « gpu/command_buffer/service/framebuffer_manager.cc ('k') | gpu/command_buffer/service/program_manager.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 6df7f6a2f816a89bb6e37149101e0a60c27a2da4..8b9ad5bb70bf0ca55a4519189207168e4876e78d 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -1366,6 +1366,16 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient {
// of the draw operation are the same.
bool CheckDrawingFeedbackLoops();
+ // Checks if a draw buffer's format and its corresponding fragment shader
+ // output's type are compatible, i.e., a signed integer typed variable is
+ // incompatible with a float or unsigned integer buffer.
+ // If incompaticle, generates an INVALID_OPERATION to avoid undefined buffer
+ // contents and return false.
+ // Otherwise, filter out the draw buffers that are not written to but are not
+ // NONE through DrawBuffers, to be on the safe side; set |adjusted| to true
+ // if such adjustments happen. Return true.
+ bool ValidateAndAdjustDrawBuffers(const char* function_name, bool* adjusted);
+
// 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
@@ -7096,7 +7106,7 @@ void GLES2DecoderImpl::ClearUnclearedAttachments(
if (cleared_int_renderbuffers || clear_bits) {
if (reset_draw_buffers)
- framebuffer->RestoreDrawBuffersAfterClear();
+ framebuffer->RestoreDrawBuffers();
RestoreClearState();
if (target == GL_READ_FRAMEBUFFER && draw_framebuffer != framebuffer) {
GLuint service_id = draw_framebuffer ? draw_framebuffer->service_id() :
@@ -8026,6 +8036,58 @@ bool GLES2DecoderImpl::CheckDrawingFeedbackLoops() {
return false;
}
+bool GLES2DecoderImpl::ValidateAndAdjustDrawBuffers(
+ const char* function_name, bool* adjusted) {
+ bool validation = true;
+ bool my_adjusted = false;
+ switch (feature_info_->context_type()) {
+ case CONTEXT_TYPE_OPENGLES2:
+ case CONTEXT_TYPE_WEBGL1:
+ // Int and unsigned int formats are not available in ES2/WebGL1.
+ validation = false;
+ break;
+ default:
+ break;
+ }
+ Framebuffer* framebuffer = framebuffer_state_.bound_draw_framebuffer.get();
+ if (!state_.current_program.get() || !framebuffer) {
+ return true;
+ }
+ const std::vector<ShaderVariableBaseType>& fragment_output_base_types =
+ state_.current_program->GetFragmentOutputBaseTypes();
+ const std::vector<ShaderVariableBaseType>& color_attachment_base_types =
+ framebuffer->GetColorAttachmentBaseTypes();
+ DCHECK_EQ(fragment_output_base_types.size(),
+ color_attachment_base_types.size());
+ size_t count = color_attachment_base_types.size();
+ std::unique_ptr<GLenum[]> adjusted_draw_buffers(new GLenum[count]);
+ for (size_t ii = 0; ii < count; ++ii) {
+ adjusted_draw_buffers[ii] =
+ framebuffer->GetDrawBuffer(GL_DRAW_BUFFER0 + ii);
+ if (adjusted_draw_buffers[ii] == GL_NONE)
+ continue;
+ if (fragment_output_base_types[ii] == SHADER_VARIABLE_UNDEFINED_TYPE) {
+ adjusted_draw_buffers[ii] = GL_NONE;
Corentin Wallez 2016/07/13 14:50:07 This looks like it will be doing an allocation for
+ my_adjusted = true;
+ continue;
+ }
+ if (!validation)
+ continue;
+ if (color_attachment_base_types[ii] == SHADER_VARIABLE_UNDEFINED_TYPE)
+ continue;
+ if (fragment_output_base_types[ii] != color_attachment_base_types[ii]) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
+ "buffer format and fragment output variable type incompatible");
+ return false;
+ }
+ }
+ if (my_adjusted) {
+ glDrawBuffersARB(count, adjusted_draw_buffers.get());
+ }
+ *adjusted = my_adjusted;
+ return true;
+}
+
bool GLES2DecoderImpl::CheckUniformForApiType(
const Program::UniformInfo* info,
const char* function_name,
@@ -9053,11 +9115,19 @@ error::Error GLES2DecoderImpl::DoDrawArrays(
primcount)) {
bool textures_set = !PrepareTexturesForRender();
ApplyDirtyState();
+ bool adjusted = false;
+ if (!ValidateAndAdjustDrawBuffers(function_name, &adjusted)) {
+ return error::kNoError;
+ }
if (!instanced) {
glDrawArrays(mode, first, count);
} else {
glDrawArraysInstancedANGLE(mode, first, count, primcount);
}
+ if (adjusted) {
+ DCHECK(framebuffer_state_.bound_draw_framebuffer.get());
+ framebuffer_state_.bound_draw_framebuffer->RestoreDrawBuffers();
+ }
if (textures_set) {
RestoreStateForTextures();
}
@@ -9194,14 +9264,16 @@ error::Error GLES2DecoderImpl::DoDrawElements(const char* function_name,
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
indices = element_array_buffer->GetRange(offset, 0);
}
-
+ bool adjusted = false;
+ if (!ValidateAndAdjustDrawBuffers(function_name, &adjusted)) {
+ return error::kNoError;
+ }
if (state_.enable_flags.primitive_restart_fixed_index &&
feature_info_->feature_flags().
emulate_primitive_restart_fixed_index) {
glEnable(GL_PRIMITIVE_RESTART);
buffer_manager()->SetPrimitiveRestartFixedIndexIfNecessary(type);
}
-
if (!instanced) {
glDrawElements(mode, count, type, indices);
} else {
@@ -9212,12 +9284,14 @@ error::Error GLES2DecoderImpl::DoDrawElements(const char* function_name,
emulate_primitive_restart_fixed_index) {
glDisable(GL_PRIMITIVE_RESTART);
}
-
+ if (adjusted) {
+ DCHECK(framebuffer_state_.bound_draw_framebuffer.get());
+ framebuffer_state_.bound_draw_framebuffer->RestoreDrawBuffers();
+ }
if (used_client_side_array) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
element_array_buffer->service_id());
}
-
if (textures_set) {
RestoreStateForTextures();
}
« no previous file with comments | « gpu/command_buffer/service/framebuffer_manager.cc ('k') | gpu/command_buffer/service/program_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698