summaryrefslogtreecommitdiffstats
path: root/gpu/command_buffer/service/gles2_cmd_decoder.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gpu/command_buffer/service/gles2_cmd_decoder.cc')
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc85
1 files changed, 85 insertions, 0 deletions
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index ac72097..7ecd8d5 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -388,6 +388,23 @@ class ScopedResolvedFrameBufferBinder {
DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
};
+// When an instance of this class is created, it uses copyTexImage2D to copy the
+// contents of the framebuffer into a texture. This texture is then bound to a
+// new framebuffer. When the instance is destroyed, the original texture and
+// framebuffer are restored.
+class ScopedFrameBufferReadPixelHelper {
+ public:
+ ScopedFrameBufferReadPixelHelper(ContextState* state,
+ GLES2DecoderImpl* decoder);
+ ~ScopedFrameBufferReadPixelHelper();
+
+ private:
+ GLuint temp_texture_id_ = 0;
+ GLuint temp_fbo_id_ = 0;
+ scoped_ptr<ScopedFrameBufferBinder> fbo_binder_;
+ DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferReadPixelHelper);
+};
+
// Encapsulates an OpenGL texture.
class BackTexture {
public:
@@ -702,6 +719,7 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient {
private:
friend class ScopedFrameBufferBinder;
+ friend class ScopedFrameBufferReadPixelHelper;
friend class ScopedResolvedFrameBufferBinder;
friend class BackFramebuffer;
@@ -1914,6 +1932,13 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient {
GLuint* source_texture_service_id,
GLenum* source_texture_target);
+ // On Mac OS X, calling glReadPixels() against an FBO whose color attachment
+ // is an IOSurface-backed texture causes corruption of future glReadPixels()
+ // calls, even those on different OpenGL contexts. It is believed that this
+ // is the root cause of top crasher
+ // http://crbug.com/99393. <rdar://problem/10949687>
+ bool NeedsIOSurfaceReadbackWorkaround();
+
// Generate a member function prototype for each command in an automated and
// typesafe way.
#define GLES2_CMD_OP(name) \
@@ -2280,6 +2305,41 @@ ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
}
}
+ScopedFrameBufferReadPixelHelper::ScopedFrameBufferReadPixelHelper(
+ ContextState* state,
+ GLES2DecoderImpl* decoder) {
+ DCHECK_EQ(static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE),
+ glCheckFramebufferStatusEXT(GL_FRAMEBUFFER));
+
+ const Framebuffer::Attachment* attachment =
+ decoder->GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT)
+ ->GetReadBufferAttachment();
+ GLsizei width = attachment->width();
+ GLsizei height = attachment->height();
+
+ glGenTextures(1, &temp_texture_id_);
+ glGenFramebuffersEXT(1, &temp_fbo_id_);
+ {
+ ScopedTextureBinder binder(state, temp_texture_id_, GL_TEXTURE_2D);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, width, height, 0);
+
+ fbo_binder_.reset(new ScopedFrameBufferBinder(decoder, temp_fbo_id_));
+ }
+
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+ temp_texture_id_, 0);
+}
+
+ScopedFrameBufferReadPixelHelper::~ScopedFrameBufferReadPixelHelper() {
+ fbo_binder_.reset();
+ glDeleteTextures(1, &temp_texture_id_);
+ glDeleteFramebuffersEXT(1, &temp_fbo_id_);
+}
+
BackTexture::BackTexture(
MemoryTracker* memory_tracker,
ContextState* state)
@@ -9467,6 +9527,9 @@ error::Error GLES2DecoderImpl::HandleReadPixels(uint32_t immediate_data_size,
LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
ScopedResolvedFrameBufferBinder binder(this, false, true);
+ scoped_ptr<ScopedFrameBufferReadPixelHelper> helper;
+ if (NeedsIOSurfaceReadbackWorkaround())
+ helper.reset(new ScopedFrameBufferReadPixelHelper(&state_, this));
gfx::Rect rect(x, y, width, height); // Safe before we checked above.
gfx::Rect max_rect(max_size);
@@ -16092,6 +16155,28 @@ bool GLES2DecoderImpl::NeedsCopyTextureImageWorkaround(
return true;
}
+bool GLES2DecoderImpl::NeedsIOSurfaceReadbackWorkaround() {
+ if (!workarounds().iosurface_readback_workaround)
+ return false;
+
+ Framebuffer* framebuffer =
+ GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
+ if (!framebuffer)
+ return false;
+
+ const Framebuffer::Attachment* attachment =
+ framebuffer->GetReadBufferAttachment();
+ if (!attachment)
+ return false;
+
+ if (!attachment->IsTextureAttachment())
+ return false;
+
+ TextureRef* texture =
+ texture_manager()->GetTexture(attachment->object_name());
+ return texture->texture()->HasImages();
+}
+
error::Error GLES2DecoderImpl::HandleBindFragmentInputLocationCHROMIUMBucket(
uint32_t immediate_data_size,
const void* cmd_data) {