summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormiu <miu@chromium.org>2014-11-10 17:35:41 -0800
committerCommit bot <commit-bot@chromium.org>2014-11-11 01:37:00 +0000
commit50cef609bfd4cd9d6df305367af2b4ef0e7b511c (patch)
tree6d3c11c1e00f2cb2284328e80f3cad7c9f24483c
parent8e27ee01469c947ccb5d79ae4e1941f5a7fd872b (diff)
downloadchromium_src-50cef609bfd4cd9d6df305367af2b4ef0e7b511c.zip
chromium_src-50cef609bfd4cd9d6df305367af2b4ef0e7b511c.tar.gz
chromium_src-50cef609bfd4cd9d6df305367af2b4ef0e7b511c.tar.bz2
Add GL_APPLE_fence support, enabling asynchronous glReadPixels for Mac.
With the removal of the CompositingIOSurface code a few months back, all the support for using APPLE fences to support asynchronous GPU readback was deleted along with it. While the current GPU readback code path does support asynchronous glReadPixels operations, it is disabled on Mac for lack of fence support. This change adds back the necessary fence support. This change should be safe, given that the pre-Mountain Lion blacklist item, disable_async_readpixels, is still in-place; and so we will retain synchronous readback behavior on systems with known buggy drivers. BUG=430586 Review URL: https://codereview.chromium.org/701103003 Cr-Commit-Position: refs/heads/master@{#303567}
-rw-r--r--chrome/tab_capture_end2end_tests.isolate3
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc3
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc1
-rw-r--r--ui/gl/BUILD.gn2
-rwxr-xr-xui/gl/generate_bindings.py30
-rw-r--r--ui/gl/gl.gyp2
-rw-r--r--ui/gl/gl_fence.cc13
-rw-r--r--ui/gl/gl_fence_apple.cc47
-rw-r--r--ui/gl/gl_fence_apple.h34
9 files changed, 131 insertions, 4 deletions
diff --git a/chrome/tab_capture_end2end_tests.isolate b/chrome/tab_capture_end2end_tests.isolate
index 5f686e0..36412cf 100644
--- a/chrome/tab_capture_end2end_tests.isolate
+++ b/chrome/tab_capture_end2end_tests.isolate
@@ -14,9 +14,10 @@
'--test-launcher-bot-mode',
'--enable-gpu',
'--test-launcher-jobs=1',
- '--gtest_filter=TabCaptureApiPixelTest.EndToEnd*',
+ '--gtest_filter=CastStreamingApiTestWithPixelOutput.EndToEnd*:TabCaptureApiPixelTest.EndToEnd*',
],
'files': [
+ 'test/data/extensions/api_test/cast_streaming/',
'test/data/extensions/api_test/tab_capture/',
],
},
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 6905d2a..c7fab68 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -7748,7 +7748,7 @@ error::Error GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size,
}
} else {
if (async && features().use_async_readpixels) {
- GLuint buffer;
+ GLuint buffer = 0;
glGenBuffersARB(1, &buffer);
glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
glBufferData(GL_PIXEL_PACK_BUFFER_ARB, pixels_size, NULL, GL_STREAM_READ);
@@ -7767,6 +7767,7 @@ error::Error GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size,
} else {
// On error, unbind pack buffer and fall through to sync readpixels
glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
+ glDeleteBuffersARB(1, &buffer);
}
}
glReadPixels(x, y, width, height, format, type, pixels);
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc
index d555f28..789b48a 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc
@@ -772,6 +772,7 @@ TEST_P(GLES2DecoderManualInitTest, ReadPixelsAsyncError) {
ReadPixels(0, 0, kWidth, kHeight, GL_RGB, GL_UNSIGNED_BYTE, _))
.Times(1);
EXPECT_CALL(*gl_, GenBuffersARB(1, _)).Times(1);
+ EXPECT_CALL(*gl_, DeleteBuffersARB(1, _)).Times(1);
EXPECT_CALL(*gl_, BindBuffer(GL_PIXEL_PACK_BUFFER_ARB, _)).Times(2);
EXPECT_CALL(*gl_,
BufferData(GL_PIXEL_PACK_BUFFER_ARB, _, NULL, GL_STREAM_READ))
diff --git a/ui/gl/BUILD.gn b/ui/gl/BUILD.gn
index 641f51d..6968f2c 100644
--- a/ui/gl/BUILD.gn
+++ b/ui/gl/BUILD.gn
@@ -204,6 +204,8 @@ component("gl") {
sources += [
"gl_context_cgl.cc",
"gl_context_cgl.h",
+ "gl_fence_apple.cc",
+ "gl_fence_apple.h",
"gl_image_io_surface.cc",
"gl_image_io_surface.h",
"scoped_cgl.cc",
diff --git a/ui/gl/generate_bindings.py b/ui/gl/generate_bindings.py
index 3a61f57..0156806 100755
--- a/ui/gl/generate_bindings.py
+++ b/ui/gl/generate_bindings.py
@@ -188,6 +188,11 @@ GL_FUNCTIONS = [
'names': ['glDeleteBuffersARB', 'glDeleteBuffers'],
'arguments': 'GLsizei n, const GLuint* buffers', },
{ 'return_type': 'void',
+ 'known_as': 'glDeleteFencesAPPLE',
+ 'versions': [{ 'name': 'glDeleteFencesAPPLE',
+ 'extensions': ['GL_APPLE_fence'] }],
+ 'arguments': 'GLsizei n, const GLuint* fences', },
+{ 'return_type': 'void',
'names': ['glDeleteFencesNV'],
'arguments': 'GLsizei n, const GLuint* fences', },
{ 'return_type': 'void',
@@ -304,6 +309,11 @@ GL_FUNCTIONS = [
'names': ['glFinish'],
'arguments': 'void', },
{ 'return_type': 'void',
+ 'known_as': 'glFinishFenceAPPLE',
+ 'versions': [{ 'name': 'glFinishFenceAPPLE',
+ 'extensions': ['GL_APPLE_fence'] }],
+ 'arguments': 'GLuint fence', },
+{ 'return_type': 'void',
'names': ['glFinishFenceNV'],
'arguments': 'GLuint fence', },
{ 'return_type': 'void',
@@ -342,6 +352,11 @@ GL_FUNCTIONS = [
'names': ['glGenerateMipmapEXT', 'glGenerateMipmap'],
'arguments': 'GLenum target', },
{ 'return_type': 'void',
+ 'known_as': 'glGenFencesAPPLE',
+ 'versions': [{ 'name': 'glGenFencesAPPLE',
+ 'extensions': ['GL_APPLE_fence'] }],
+ 'arguments': 'GLsizei n, GLuint* fences', },
+{ 'return_type': 'void',
'names': ['glGenFencesNV'],
'arguments': 'GLsizei n, GLuint* fences', },
{ 'return_type': 'void',
@@ -531,6 +546,11 @@ GL_FUNCTIONS = [
'names': ['glIsEnabled'],
'arguments': 'GLenum cap', },
{ 'return_type': 'GLboolean',
+ 'known_as': 'glIsFenceAPPLE',
+ 'versions': [{ 'name': 'glIsFenceAPPLE',
+ 'extensions': ['GL_APPLE_fence'] }],
+ 'arguments': 'GLuint fence', },
+{ 'return_type': 'GLboolean',
'names': ['glIsFenceNV'],
'arguments': 'GLuint fence', },
{ 'return_type': 'GLboolean',
@@ -684,6 +704,11 @@ GL_FUNCTIONS = [
'names': ['glScissor'],
'arguments': 'GLint x, GLint y, GLsizei width, GLsizei height', },
{ 'return_type': 'void',
+ 'known_as': 'glSetFenceAPPLE',
+ 'versions': [{ 'name': 'glSetFenceAPPLE',
+ 'extensions': ['GL_APPLE_fence'] }],
+ 'arguments': 'GLuint fence', },
+{ 'return_type': 'void',
'names': ['glSetFenceNV'],
'arguments': 'GLuint fence, GLenum condition', },
{ 'return_type': 'void',
@@ -729,6 +754,11 @@ GL_FUNCTIONS = [
'names': ['glStencilOpSeparate'],
'arguments': 'GLenum face, GLenum fail, GLenum zfail, GLenum zpass', },
{ 'return_type': 'GLboolean',
+ 'known_as': 'glTestFenceAPPLE',
+ 'versions': [{ 'name': 'glTestFenceAPPLE',
+ 'extensions': ['GL_APPLE_fence'] }],
+ 'arguments': 'GLuint fence', },
+{ 'return_type': 'GLboolean',
'names': ['glTestFenceNV'],
'arguments': 'GLuint fence', },
{ 'return_type': 'void',
diff --git a/ui/gl/gl.gyp b/ui/gl/gl.gyp
index cd0a852..ce18e85 100644
--- a/ui/gl/gl.gyp
+++ b/ui/gl/gl.gyp
@@ -263,6 +263,8 @@
'sources': [
'gl_context_cgl.cc',
'gl_context_cgl.h',
+ 'gl_fence_apple.cc',
+ 'gl_fence_apple.h',
'gl_image_io_surface.cc',
'gl_image_io_surface.h',
'scoped_cgl.cc',
diff --git a/ui/gl/gl_fence.cc b/ui/gl/gl_fence.cc
index 5186f23..c254411 100644
--- a/ui/gl/gl_fence.cc
+++ b/ui/gl/gl_fence.cc
@@ -13,6 +13,10 @@
#include "ui/gl/gl_gl_api_implementation.h"
#include "ui/gl/gl_version_info.h"
+#if defined(OS_MACOSX)
+#include "ui/gl/gl_fence_apple.h"
+#endif
+
namespace gfx {
namespace {
@@ -27,7 +31,10 @@ GLFence* CreateFence(bool flush) {
if (g_driver_gl.ext.b_GL_ARB_sync ||
GetGLVersionInfo()->is_es3) {
fence.reset(new GLFenceARB(flush));
-#if !defined(OS_MACOSX)
+#if defined(OS_MACOSX)
+ } else if (g_driver_gl.ext.b_GL_APPLE_fence) {
+ fence.reset(new GLFenceAPPLE(flush));
+#else
} else if (g_driver_egl.ext.b_EGL_KHR_fence_sync) {
fence.reset(new GLFenceEGL(flush));
#endif
@@ -50,7 +57,9 @@ GLFence::~GLFence() {
bool GLFence::IsSupported() {
DCHECK(GetGLVersionInfo());
return g_driver_gl.ext.b_GL_ARB_sync || GetGLVersionInfo()->is_es3 ||
-#if !defined(OS_MACOSX)
+#if defined(OS_MACOSX)
+ g_driver_gl.ext.b_GL_APPLE_fence ||
+#else
g_driver_egl.ext.b_EGL_KHR_fence_sync ||
#endif
g_driver_gl.ext.b_GL_NV_fence;
diff --git a/ui/gl/gl_fence_apple.cc b/ui/gl/gl_fence_apple.cc
new file mode 100644
index 0000000..9df0cad
--- /dev/null
+++ b/ui/gl/gl_fence_apple.cc
@@ -0,0 +1,47 @@
+// Copyright 2014 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.
+
+#include "ui/gl/gl_fence_apple.h"
+
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context.h"
+
+namespace gfx {
+
+GLFenceAPPLE::GLFenceAPPLE(bool flush) {
+ glGenFencesAPPLE(1, &fence_);
+ glSetFenceAPPLE(fence_);
+ DCHECK(glIsFenceAPPLE(fence_));
+ if (flush) {
+ glFlush();
+ } else {
+ flush_event_ = GLContext::GetCurrent()->SignalFlush();
+ }
+}
+
+bool GLFenceAPPLE::HasCompleted() {
+ DCHECK(glIsFenceAPPLE(fence_));
+ return !!glTestFenceAPPLE(fence_);
+}
+
+void GLFenceAPPLE::ClientWait() {
+ DCHECK(glIsFenceAPPLE(fence_));
+ if (!flush_event_.get() || flush_event_->IsSignaled()) {
+ glFinishFenceAPPLE(fence_);
+ } else {
+ LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
+ }
+}
+
+void GLFenceAPPLE::ServerWait() {
+ DCHECK(glIsFenceAPPLE(fence_));
+ ClientWait();
+}
+
+GLFenceAPPLE::~GLFenceAPPLE() {
+ DCHECK(glIsFenceAPPLE(fence_));
+ glDeleteFencesAPPLE(1, &fence_);
+}
+
+} // namespace gfx
diff --git a/ui/gl/gl_fence_apple.h b/ui/gl/gl_fence_apple.h
new file mode 100644
index 0000000..6c8633d
--- /dev/null
+++ b/ui/gl/gl_fence_apple.h
@@ -0,0 +1,34 @@
+// Copyright 2014 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 UI_GL_GL_FENCE_APPLE_H_
+#define UI_GL_GL_FENCE_APPLE_H_
+
+#include "base/macros.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context.h"
+#include "ui/gl/gl_fence.h"
+
+namespace gfx {
+
+class GL_EXPORT GLFenceAPPLE : public GLFence {
+ public:
+ GLFenceAPPLE(bool flush);
+ ~GLFenceAPPLE() override;
+
+ // GLFence implementation:
+ bool HasCompleted() override;
+ void ClientWait() override;
+ void ServerWait() override;
+
+ private:
+ GLuint fence_;
+ scoped_refptr<GLContext::FlushEvent> flush_event_;
+
+ DISALLOW_COPY_AND_ASSIGN(GLFenceAPPLE);
+};
+
+} // namespace gfx
+
+#endif // UI_GL_GL_FENCE_APPLE_H_