summaryrefslogtreecommitdiffstats
path: root/gpu
diff options
context:
space:
mode:
authorbajones@chromium.org <bajones@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-13 22:50:10 +0000
committerbajones@chromium.org <bajones@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-13 22:50:10 +0000
commit4a4c18b115d55e2ab6cccf3350b966c5020dbaee (patch)
tree1bde6e33d377d54e3cfb7f59a9891b0f8d0d7e83 /gpu
parent2aa05c8f3152e23f90631f137491fb78d4acdd92 (diff)
downloadchromium_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.cc133
-rw-r--r--gpu/config/gpu_driver_bug_list_json.cc13
-rw-r--r--gpu/config/gpu_driver_bug_workaround_type.h2
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 {