diff options
author | bajones@chromium.org <bajones@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-13 22:50:10 +0000 |
---|---|---|
committer | bajones@chromium.org <bajones@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-13 22:50:10 +0000 |
commit | 4a4c18b115d55e2ab6cccf3350b966c5020dbaee (patch) | |
tree | 1bde6e33d377d54e3cfb7f59a9891b0f8d0d7e83 /gpu | |
parent | 2aa05c8f3152e23f90631f137491fb78d4acdd92 (diff) | |
download | chromium_src-4a4c18b115d55e2ab6cccf3350b966c5020dbaee.zip chromium_src-4a4c18b115d55e2ab6cccf3350b966c5020dbaee.tar.gz chromium_src-4a4c18b115d55e2ab6cccf3350b966c5020dbaee.tar.bz2 |
Moved multisample buffer verification to the command buffer
BUG=290391
Review URL: https://chromiumcodereview.appspot.com/23876018
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@223154 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder.cc | 133 | ||||
-rw-r--r-- | gpu/config/gpu_driver_bug_list_json.cc | 13 | ||||
-rw-r--r-- | gpu/config/gpu_driver_bug_workaround_type.h | 2 |
3 files changed, 146 insertions, 2 deletions
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 747ce78..016fa4b 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -1291,6 +1291,12 @@ class GLES2DecoderImpl : public GLES2Decoder { GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); + // Verifies that the currently bound multisample renderbuffer is valid + // Very slow! Only done on platforms with driver bugs that return invalid + // buffers under memory pressure + bool VerifyMultisampleRenderbufferIntegrity( + GLuint renderbuffer, GLenum format); + // Wrapper for glReleaseShaderCompiler. void DoReleaseShaderCompiler() { } @@ -1669,6 +1675,11 @@ class GLES2DecoderImpl : public GLES2Decoder { std::queue<linked_ptr<FenceCallback> > pending_readpixel_fences_; + // Used to validate multisample renderbuffers if needed + GLuint validation_texture_; + GLuint validation_fbo_multisample_; + GLuint validation_fbo_; + DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl); }; @@ -2088,7 +2099,10 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group) service_logging_(CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableGPUServiceLoggingGPU)), viewport_max_width_(0), - viewport_max_height_(0) { + viewport_max_height_(0), + validation_texture_(0), + validation_fbo_multisample_(0), + validation_fbo_(0) { DCHECK(group); attrib_0_value_.v[0] = 0.0f; @@ -3096,6 +3110,12 @@ void GLES2DecoderImpl::Destroy(bool have_context) { glDeleteBuffersARB(1, &fixed_attrib_buffer_id_); } + if (validation_texture_) { + glDeleteTextures(1, &validation_texture_); + glDeleteFramebuffersEXT(1, &validation_fbo_multisample_); + glDeleteFramebuffersEXT(1, &validation_fbo_); + } + if (offscreen_target_frame_buffer_.get()) offscreen_target_frame_buffer_->Destroy(); if (offscreen_target_color_texture_.get()) @@ -5032,6 +5052,17 @@ void GLES2DecoderImpl::DoRenderbufferStorageMultisample( } GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisample"); if (error == GL_NO_ERROR) { + + if (workarounds().validate_multisample_buffer_allocation) { + if (!VerifyMultisampleRenderbufferIntegrity( + renderbuffer->service_id(), impl_format)) { + LOCAL_SET_GL_ERROR( + GL_OUT_OF_MEMORY, + "glRenderbufferStorageMultisample", "out of memory"); + return; + } + } + // TODO(gman): If renderbuffers tracked which framebuffers they were // attached to we could just mark those framebuffers as not complete. framebuffer_manager()->IncFramebufferStateChangeCount(); @@ -5040,6 +5071,106 @@ void GLES2DecoderImpl::DoRenderbufferStorageMultisample( } } +// This function validates the allocation of a multisampled renderbuffer +// by clearing it to a key color, blitting the contents to a texture, and +// reading back the color to ensure it matches the key. +bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity( + GLuint renderbuffer, GLenum format) { + + // Only validate color buffers. + // These formats have been selected because they are very common or are known + // to be used by the WebGL backbuffer. If problems are observed with other + // color formats they can be added here. + switch(format) { + case GL_RGB: + case GL_RGB8: + case GL_RGBA: + case GL_RGBA8: + break; + default: + return true; + } + + GLint draw_framebuffer, read_framebuffer; + + // Cache framebuffer and texture bindings. + glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_framebuffer); + glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer); + + if (!validation_texture_) { + GLint bound_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture); + + // Create additional resources needed for the verification. + glGenTextures(1, &validation_texture_); + glGenFramebuffersEXT(1, &validation_fbo_multisample_); + glGenFramebuffersEXT(1, &validation_fbo_); + + // Texture only needs to be 1x1. + glBindTexture(GL_TEXTURE_2D, validation_texture_); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, + GL_UNSIGNED_BYTE, NULL); + + glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, validation_texture_, 0); + + glBindTexture(GL_TEXTURE_2D, bound_texture); + } + + glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, renderbuffer); + + // Cache current state and reset it to the values we require. + GLboolean scissor_enabled = false; + glGetBooleanv(GL_SCISSOR_TEST, &scissor_enabled); + if (scissor_enabled) + glDisable(GL_SCISSOR_TEST); + + GLboolean color_mask[4] = {true, true, true, true}; + glGetBooleanv(GL_COLOR_WRITEMASK, color_mask); + glColorMask(true, true, true, true); + + GLfloat clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + glGetFloatv(GL_COLOR_CLEAR_VALUE, clear_color); + glClearColor(1.0f, 0.0f, 1.0f, 1.0f); + + // Clear the buffer to the desired key color. + glClear(GL_COLOR_BUFFER_BIT); + + // Blit from the multisample buffer to a standard texture. + glBindFramebufferEXT(GL_READ_FRAMEBUFFER, validation_fbo_multisample_); + glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, validation_fbo_); + + glBlitFramebufferEXT(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST); + + // Read a pixel from the buffer. + glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_); + + unsigned char pixel[3] = {0, 0, 0}; + glReadPixels(0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixel); + + // Detach the renderbuffer. + glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, 0); + + // Restore cached state. + if (scissor_enabled) + glEnable(GL_SCISSOR_TEST); + + glColorMask(color_mask[0], color_mask[1], color_mask[2], color_mask[3]); + glClearColor(clear_color[0], clear_color[1], clear_color[2], clear_color[3]); + glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, draw_framebuffer); + glBindFramebufferEXT(GL_READ_FRAMEBUFFER, read_framebuffer); + + // Return true if the pixel matched the desired key color. + return (pixel[0] == 0xFF && + pixel[1] == 0x00 && + pixel[2] == 0xFF); +} + void GLES2DecoderImpl::DoRenderbufferStorage( GLenum target, GLenum internalformat, GLsizei width, GLsizei height) { Renderbuffer* renderbuffer = diff --git a/gpu/config/gpu_driver_bug_list_json.cc b/gpu/config/gpu_driver_bug_list_json.cc index 79dc6c1..a115bf5 100644 --- a/gpu/config/gpu_driver_bug_list_json.cc +++ b/gpu/config/gpu_driver_bug_list_json.cc @@ -85,7 +85,7 @@ const char kGpuDriverBugListJson[] = LONG_STRING_CONST( { "name": "gpu driver bug list", // Please update the version number whenever you change this file. - "version": "2.13", + "version": "2.14", "entries": [ { "id": 1, @@ -594,6 +594,17 @@ const char kGpuDriverBugListJson[] = LONG_STRING_CONST( "features": [ "use_virtualized_gl_contexts" ] + }, + { + "id": 39, + "cr_bugs": [290391], + "description": "Multisampled renderbuffer allocation must be validated on some Macs", + "os": { + "type": "macosx" + }, + "features": [ + "validate_multisample_buffer_allocation" + ] } ] } diff --git a/gpu/config/gpu_driver_bug_workaround_type.h b/gpu/config/gpu_driver_bug_workaround_type.h index 79e8941..3934d15 100644 --- a/gpu/config/gpu_driver_bug_workaround_type.h +++ b/gpu/config/gpu_driver_bug_workaround_type.h @@ -68,6 +68,8 @@ use_non_zero_size_for_client_side_stream_buffers) \ GPU_OP(USE_VIRTUALIZED_GL_CONTEXTS, \ use_virtualized_gl_contexts) \ + GPU_OP(VALIDATE_MULTISAMPLE_BUFFER_ALLOCATION, \ + validate_multisample_buffer_allocation) \ namespace gpu { |