summaryrefslogtreecommitdiffstats
path: root/gpu
diff options
context:
space:
mode:
authorerikchen <erikchen@chromium.org>2016-03-21 17:58:26 -0700
committerCommit bot <commit-bot@chromium.org>2016-03-22 01:00:41 +0000
commit2acd56014bdf216b9808e2b07c4db0a5cbbcf137 (patch)
treed9a1bb89bdfc9aea0d1afed289cadc90cea13103 /gpu
parent4c88276f8f1fdcb0a921bfb979e22cd2acf241bb (diff)
downloadchromium_src-2acd56014bdf216b9808e2b07c4db0a5cbbcf137.zip
chromium_src-2acd56014bdf216b9808e2b07c4db0a5cbbcf137.tar.gz
chromium_src-2acd56014bdf216b9808e2b07c4db0a5cbbcf137.tar.bz2
Make a command buffer workaround for glReadPixels on IOSurface backed textures.
The workaround previously existed in GLRenderer. This CL moves the workaround into the command buffer. BUG=581777 CQ_INCLUDE_TRYBOTS=tryserver.chromium.win:win_optional_gpu_tests_rel Review URL: https://codereview.chromium.org/1806753003 Cr-Commit-Position: refs/heads/master@{#382466}
Diffstat (limited to 'gpu')
-rw-r--r--gpu/BUILD.gn1
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc85
-rw-r--r--gpu/command_buffer/tests/gl_iosurface_readback_workaround_unittest.cc91
-rw-r--r--gpu/config/gpu_driver_bug_list_json.cc13
-rw-r--r--gpu/config/gpu_driver_bug_workaround_type.h2
-rw-r--r--gpu/gpu.gyp1
6 files changed, 192 insertions, 1 deletions
diff --git a/gpu/BUILD.gn b/gpu/BUILD.gn
index cfa2e4a..8ae7915 100644
--- a/gpu/BUILD.gn
+++ b/gpu/BUILD.gn
@@ -160,6 +160,7 @@ test("gl_tests") {
"command_buffer/tests/gl_ext_srgb_unittest.cc",
"command_buffer/tests/gl_fence_sync_unittest.cc",
"command_buffer/tests/gl_gpu_memory_buffer_unittest.cc",
+ "command_buffer/tests/gl_iosurface_readback_workaround_unittest.cc",
"command_buffer/tests/gl_lose_context_chromium_unittest.cc",
"command_buffer/tests/gl_manager.cc",
"command_buffer/tests/gl_manager.h",
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) {
diff --git a/gpu/command_buffer/tests/gl_iosurface_readback_workaround_unittest.cc b/gpu/command_buffer/tests/gl_iosurface_readback_workaround_unittest.cc
new file mode 100644
index 0000000..6a1a7c6
--- /dev/null
+++ b/gpu/command_buffer/tests/gl_iosurface_readback_workaround_unittest.cc
@@ -0,0 +1,91 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GL_GLEXT_PROTOTYPES
+#define GL_GLEXT_PROTOTYPES
+#endif
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <GLES2/gl2extchromium.h>
+
+#include "base/command_line.h"
+#include "base/strings/string_number_conversions.h"
+#include "build/build_config.h"
+#include "gpu/command_buffer/tests/gl_manager.h"
+#include "gpu/command_buffer/tests/gl_test_utils.h"
+#include "gpu/config/gpu_switches.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace gpu {
+
+#if defined(OS_MACOSX)
+// A test that exercises the glReadPixels workaround for IOSurface backed
+// textures.
+class GLIOSurfaceReadbackWorkaroundTest : public testing::Test {
+ public:
+ GLIOSurfaceReadbackWorkaroundTest() {}
+
+ protected:
+ void SetUp() override {
+ base::CommandLine command_line(0, NULL);
+ command_line.AppendSwitchASCII(
+ switches::kGpuDriverBugWorkarounds,
+ base::IntToString(gpu::IOSURFACE_READBACK_WORKAROUND));
+ gl_.InitializeWithCommandLine(GLManager::Options(), &command_line);
+ gl_.set_use_iosurface_memory_buffers(true);
+ DCHECK(gl_.workarounds().iosurface_readback_workaround);
+ }
+
+ void TearDown() override {
+ GLTestHelper::CheckGLError("no errors", __LINE__);
+ gl_.Destroy();
+ }
+
+ GLManager gl_;
+};
+
+TEST_F(GLIOSurfaceReadbackWorkaroundTest, ReadPixels) {
+ int width = 1;
+ int height = 1;
+ GLuint source_texture = 0;
+ GLenum source_target = GL_TEXTURE_RECTANGLE_ARB;
+ glGenTextures(1, &source_texture);
+ glBindTexture(source_target, source_texture);
+ glTexParameteri(source_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(source_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ GLuint image_id = glCreateGpuMemoryBufferImageCHROMIUM(
+ width, height, GL_BGRA_EXT, GL_READ_WRITE_CHROMIUM);
+ ASSERT_NE(0u, image_id);
+ glBindTexImage2DCHROMIUM(source_target, image_id);
+
+ GLuint framebuffer = 0;
+ glGenFramebuffers(1, &framebuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
+ glFramebufferTexture2D(
+ GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, source_target, source_texture, 0);
+ EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
+ glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+ glClearColor(33.0 / 255.0, 44.0 / 255.0, 55.0 / 255.0, 66.0 / 255.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ const uint8_t expected[4] = {33, 44, 55, 66};
+ EXPECT_TRUE(
+ GLTestHelper::CheckPixels(0, 0, 1, 1, 1 /* tolerance */, expected));
+
+ glClearColor(14.0 / 255.0, 15.0 / 255.0, 16.0 / 255.0, 17.0 / 255.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ const uint8_t expected2[4] = {14, 15, 16, 17};
+ EXPECT_TRUE(
+ GLTestHelper::CheckPixels(0, 0, 1, 1, 1 /* tolerance */, expected2));
+
+ glReleaseTexImage2DCHROMIUM(source_target, image_id);
+ glDestroyImageCHROMIUM(image_id);
+ glDeleteTextures(1, &source_texture);
+ glDeleteFramebuffers(1, &framebuffer);
+}
+
+#endif // defined(OS_MACOSX)
+
+} // namespace gpu
diff --git a/gpu/config/gpu_driver_bug_list_json.cc b/gpu/config/gpu_driver_bug_list_json.cc
index c2dd212..b3840b2 100644
--- a/gpu/config/gpu_driver_bug_list_json.cc
+++ b/gpu/config/gpu_driver_bug_list_json.cc
@@ -19,7 +19,7 @@ const char kGpuDriverBugListJson[] = LONG_STRING_CONST(
{
"name": "gpu driver bug list",
// Please update the version number whenever you change this file.
- "version": "8.52",
+ "version": "8.53",
"entries": [
{
"id": 1,
@@ -1844,6 +1844,17 @@ LONG_STRING_CONST(
"features": [
"disable_multisampled_render_to_texture"
]
+ },
+ {
+ "id": 154,
+ "cr_bugs": [581777],
+ "description": "glReadPixels does not work on IOSurface backed textures",
+ "os": {
+ "type": "macosx"
+ },
+ "features": [
+ "iosurface_readback_workaround"
+ ]
}
]
}
diff --git a/gpu/config/gpu_driver_bug_workaround_type.h b/gpu/config/gpu_driver_bug_workaround_type.h
index 959f780..da2acc9 100644
--- a/gpu/config/gpu_driver_bug_workaround_type.h
+++ b/gpu/config/gpu_driver_bug_workaround_type.h
@@ -140,6 +140,8 @@
unfold_short_circuit_as_ternary_operation) \
GPU_OP(UNPACK_ALIGNMENT_WORKAROUND_WITH_UNPACK_BUFFER, \
unpack_alignment_workaround_with_unpack_buffer) \
+ GPU_OP(IOSURFACE_READBACK_WORKAROUND, \
+ iosurface_readback_workaround) \
GPU_OP(UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX, \
unroll_for_loop_with_sampler_array_index) \
GPU_OP(USE_CLIENT_SIDE_ARRAYS_FOR_STREAM_BUFFERS, \
diff --git a/gpu/gpu.gyp b/gpu/gpu.gyp
index 1bd8d2f..690c329 100644
--- a/gpu/gpu.gyp
+++ b/gpu/gpu.gyp
@@ -362,6 +362,7 @@
'command_buffer/tests/gl_ext_srgb_unittest.cc',
'command_buffer/tests/gl_fence_sync_unittest.cc',
'command_buffer/tests/gl_gpu_memory_buffer_unittest.cc',
+ 'command_buffer/tests/gl_iosurface_readback_workaround_unittest.cc',
'command_buffer/tests/gl_lose_context_chromium_unittest.cc',
'command_buffer/tests/gl_manager.cc',
'command_buffer/tests/gl_manager.h',