summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorccameron@chromium.org <ccameron@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-23 22:26:47 +0000
committerccameron@chromium.org <ccameron@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-23 22:26:47 +0000
commitba2a3366f2f3029913177d9e6526eb0181b36402 (patch)
tree5972b2258cd887c8fb3c91d740a077db9adf7237
parent59c4c2d1d830a216e56e039ab489d479f69eb1c5 (diff)
downloadchromium_src-ba2a3366f2f3029913177d9e6526eb0181b36402.zip
chromium_src-ba2a3366f2f3029913177d9e6526eb0181b36402.tar.gz
chromium_src-ba2a3366f2f3029913177d9e6526eb0181b36402.tar.bz2
Make cross-process CALayers work on Mac
Add a header file for the remote layer API and a helper function to determine if it is supported at runtime. Add a mechanism for disambiguating if a "surface handle" refers to an IOSurfaceID or a CAContextID (the thing that is passed across processes to do cross-process CALayer drawing). Add support in RenderWidgetHostViewMac to put in a CALayerHost from another process's CAContextID. In the process of this, make the root CALayer hanging off of the RenderWidgetHostViewMac have flipped geometry, and update LayoutLayers to take this into account. This is working surprisingly well, but needs a bit more work before it can be turned on. We still need to: * exert GPU back-pressure from the GPU process' -[ImageTransportLayer drawInCGLContext] function (it's an open loop now). * use the isAsynchronous property to make 60fps animation not jerky. * ensure that these resources' lifetimes are being managed reasonably and aren't eating tons of GPU * ensure that not rounding texture sizes to the nearest 64 pixels (as is done for the IOSurface scheme) isn't causing fragmentation. BUG=312462 Review URL: https://codereview.chromium.org/347653005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@279200 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--content/browser/renderer_host/render_widget_helper_mac.mm5
-rw-r--r--content/browser/renderer_host/render_widget_host_view_mac.h4
-rw-r--r--content/browser/renderer_host/render_widget_host_view_mac.mm57
-rw-r--r--content/common/gpu/image_transport_surface_calayer_mac.h48
-rw-r--r--content/common/gpu/image_transport_surface_calayer_mac.mm177
-rw-r--r--content/common/gpu/image_transport_surface_fbo_mac.cc8
-rw-r--r--content/common/gpu/image_transport_surface_fbo_mac.h6
-rw-r--r--content/common/gpu/image_transport_surface_iosurface_mac.cc22
-rw-r--r--content/common/gpu/image_transport_surface_iosurface_mac.h6
-rw-r--r--content/common/gpu/image_transport_surface_mac.mm3
-rw-r--r--content/common/gpu/surface_handle_types_mac.cc53
-rw-r--r--content/common/gpu/surface_handle_types_mac.h34
-rw-r--r--content/content_common.gypi4
-rw-r--r--ui/base/cocoa/remote_layer_api.h59
-rw-r--r--ui/base/cocoa/remote_layer_api.mm43
-rw-r--r--ui/base/ui_base.gyp2
16 files changed, 502 insertions, 29 deletions
diff --git a/content/browser/renderer_host/render_widget_helper_mac.mm b/content/browser/renderer_host/render_widget_helper_mac.mm
index 824b2265..945b182 100644
--- a/content/browser/renderer_host/render_widget_helper_mac.mm
+++ b/content/browser/renderer_host/render_widget_helper_mac.mm
@@ -12,6 +12,7 @@
#include "content/browser/gpu/gpu_process_host.h"
#include "content/browser/gpu/gpu_surface_tracker.h"
#include "content/common/gpu/gpu_messages.h"
+#include "content/common/gpu/surface_handle_types_mac.h"
namespace {
@@ -21,9 +22,9 @@ void OnNativeSurfaceBuffersSwappedOnUIThread(
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
gfx::AcceleratedWidget native_widget =
content::GpuSurfaceTracker::Get()->AcquireNativeWidget(params.surface_id);
- IOSurfaceID io_surface_handle = static_cast<IOSurfaceID>(
+ IOSurfaceID io_surface_id = content::IOSurfaceIDFromSurfaceHandle(
params.surface_handle);
- [native_widget gotAcceleratedIOSurfaceFrame:io_surface_handle
+ [native_widget gotAcceleratedIOSurfaceFrame:io_surface_id
withOutputSurfaceID:params.surface_id
withPixelSize:params.size
withScaleFactor:params.scale_factor];
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.h b/content/browser/renderer_host/render_widget_host_view_mac.h
index b370e02..cb4efdb 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.h
+++ b/content/browser/renderer_host/render_widget_host_view_mac.h
@@ -30,6 +30,7 @@
#include "ipc/ipc_sender.h"
#include "third_party/WebKit/public/web/WebCompositionUnderline.h"
#include "ui/base/cocoa/base_view.h"
+#include "ui/base/cocoa/remote_layer_api.h"
struct ViewHostMsg_TextInputState_Params;
@@ -420,6 +421,9 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// The compositing or software layers will be added as sublayers to this.
base::scoped_nsobject<CALayer> background_layer_;
+ // The CoreAnimation layer hosted by the GPU process.
+ base::scoped_nsobject<CALayerHost> remote_layer_host_;
+
// The CoreAnimation layer for software compositing. This should be NULL
// when software compositing is not in use.
base::scoped_nsobject<SoftwareLayer> software_layer_;
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm
index 6d382ae..f48e893 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -44,6 +44,7 @@
#include "content/common/accessibility_messages.h"
#include "content/common/edit_command.h"
#include "content/common/gpu/gpu_messages.h"
+#include "content/common/gpu/surface_handle_types_mac.h"
#include "content/common/input_messages.h"
#include "content/common/view_messages.h"
#include "content/common/webplugin_geometry.h"
@@ -474,6 +475,10 @@ RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget)
background_layer_.reset([[CALayer alloc] init]);
[background_layer_
setBackgroundColor:CGColorGetConstantColor(kCGColorWhite)];
+ [background_layer_
+ setAutoresizingMask:kCALayerWidthSizable|kCALayerHeightSizable];
+ [background_layer_ setGeometryFlipped:YES];
+ [background_layer_ setContentsGravity:kCAGravityTopLeft];
[cocoa_view_ setLayer:background_layer_];
[cocoa_view_ setWantsLayer:YES];
@@ -1666,16 +1671,48 @@ void RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped(
"RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped");
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- IOSurfaceID io_surface_handle =
- static_cast<IOSurfaceID>(params.surface_handle);
AddPendingSwapAck(params.route_id,
gpu_host_id,
compositing_iosurface_ ?
compositing_iosurface_->GetRendererID() : 0);
- CompositorSwapBuffers(io_surface_handle,
- params.size,
- params.scale_factor,
- params.latency_info);
+
+ switch (GetSurfaceHandleType(params.surface_handle)) {
+ case kSurfaceHandleTypeIOSurface: {
+ IOSurfaceID io_surface_id = IOSurfaceIDFromSurfaceHandle(
+ params.surface_handle);
+
+ CompositorSwapBuffers(io_surface_id,
+ params.size,
+ params.scale_factor,
+ params.latency_info);
+ } break;
+ case kSurfaceHandleTypeCAContext: {
+ // Disable the fade-out animation as the layer is added.
+ ScopedCAActionDisabler disabler;
+
+ CAContextID context_id = CAContextIDFromSurfaceHandle(
+ params.surface_handle);
+
+ // If if the layer has changed put the new layer in the hierarchy and
+ // take the old one out.
+ if ([remote_layer_host_ contextId] != context_id) {
+ [remote_layer_host_ removeFromSuperlayer];
+
+ remote_layer_host_.reset([[CALayerHost alloc] init]);
+ [remote_layer_host_ setContextId:context_id];
+ [remote_layer_host_
+ setAutoresizingMask:kCALayerMaxXMargin|kCALayerMaxYMargin];
+ [background_layer_ addSublayer:remote_layer_host_];
+ }
+
+ // Ack the frame immediately. Any GPU back pressure will be applied by
+ // the remote layer from within the GPU process.
+ SendPendingSwapAck();
+ } break;
+ default:
+ LOG(ERROR) << "Invalid surface handle type.";
+ break;
+ }
}
void RenderWidgetHostViewMac::AcceleratedSurfacePostSubBuffer(
@@ -1685,13 +1722,11 @@ void RenderWidgetHostViewMac::AcceleratedSurfacePostSubBuffer(
"RenderWidgetHostViewMac::AcceleratedSurfacePostSubBuffer");
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- IOSurfaceID io_surface_handle =
- static_cast<IOSurfaceID>(params.surface_handle);
AddPendingSwapAck(params.route_id,
gpu_host_id,
compositing_iosurface_ ?
compositing_iosurface_->GetRendererID() : 0);
- CompositorSwapBuffers(io_surface_handle,
+ CompositorSwapBuffers(IOSurfaceIDFromSurfaceHandle(params.surface_handle),
params.surface_size,
params.surface_scale_factor,
params.latency_info);
@@ -2213,12 +2248,8 @@ void RenderWidgetHostViewMac::LayoutLayers() {
0,
compositing_iosurface_->dip_io_surface_size().width(),
compositing_iosurface_->dip_io_surface_size().height());
- CGPoint layer_position = CGPointMake(
- 0,
- CGRectGetHeight(new_background_frame) - CGRectGetHeight(layer_bounds));
bool bounds_changed = !CGRectEqualToRect(
layer_bounds, [compositing_iosurface_layer_ bounds]);
- [compositing_iosurface_layer_ setPosition:layer_position];
[compositing_iosurface_layer_ setBounds:layer_bounds];
// If the bounds changed, then draw the frame immediately, to ensure that
diff --git a/content/common/gpu/image_transport_surface_calayer_mac.h b/content/common/gpu/image_transport_surface_calayer_mac.h
new file mode 100644
index 0000000..e8e2af0
--- /dev/null
+++ b/content/common/gpu/image_transport_surface_calayer_mac.h
@@ -0,0 +1,48 @@
+// 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 CONTENT_COMMON_GPU_IMAGE_TRANSPORT_SURFACE_CALAYER_MAC_H_
+#define CONTENT_COMMON_GPU_IMAGE_TRANSPORT_SURFACE_CALAYER_MAC_H_
+
+#include "base/mac/scoped_nsobject.h"
+#include "content/common/gpu/image_transport_surface_fbo_mac.h"
+#include "ui/base/cocoa/remote_layer_api.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/scoped_cgl.h"
+
+@interface ImageTransportLayer : CAOpenGLLayer {
+ base::ScopedTypeRef<CGLContextObj> shareContext_;
+ GLuint texture_;
+ gfx::Size pixelSize_;
+}
+@end
+
+namespace content {
+
+// Allocate CAOpenGLLayer-backed storage for an FBO image transport surface.
+class CALayerStorageProvider
+ : public ImageTransportSurfaceFBO::StorageProvider {
+ public:
+ CALayerStorageProvider();
+ virtual ~CALayerStorageProvider();
+
+ // ImageTransportSurfaceFBO::StorageProvider implementation:
+ virtual gfx::Size GetRoundedSize(gfx::Size size) OVERRIDE;
+ virtual bool AllocateColorBufferStorage(
+ CGLContextObj context, GLuint texture,
+ gfx::Size pixel_size, float scale_factor) OVERRIDE;
+ virtual void FreeColorBufferStorage() OVERRIDE;
+ virtual uint64 GetSurfaceHandle() const OVERRIDE;
+ virtual void WillSwapBuffers() OVERRIDE;
+
+ private:
+ base::scoped_nsobject<CAContext> context_;
+ base::scoped_nsobject<ImageTransportLayer> layer_;
+
+ DISALLOW_COPY_AND_ASSIGN(CALayerStorageProvider);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_GPU_IMAGE_TRANSPORT_CALAYER_MAC_H_
diff --git a/content/common/gpu/image_transport_surface_calayer_mac.mm b/content/common/gpu/image_transport_surface_calayer_mac.mm
new file mode 100644
index 0000000..4ad8f92
--- /dev/null
+++ b/content/common/gpu/image_transport_surface_calayer_mac.mm
@@ -0,0 +1,177 @@
+// 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 "content/common/gpu/image_transport_surface_calayer_mac.h"
+
+#include "base/mac/sdk_forward_declarations.h"
+#include "content/common/gpu/surface_handle_types_mac.h"
+#include "ui/base/cocoa/animation_utils.h"
+#include "ui/gfx/geometry/size_conversions.h"
+
+@interface ImageTransportLayer (Private) {
+}
+@end
+
+@implementation ImageTransportLayer
+
+- (id)initWithContext:(CGLContextObj)context
+ withTexture:(GLuint)texture
+ withPixelSize:(gfx::Size)pixelSize
+ withScaleFactor:(float)scaleFactor {
+ if (self = [super init]) {
+ shareContext_.reset(CGLRetainContext(context));
+ texture_ = texture;
+ pixelSize_ = pixelSize;
+
+ gfx::Size dipSize(gfx::ToFlooredSize(gfx::ScaleSize(
+ pixelSize_, 1.0f / scaleFactor)));
+ [self setContentsScale:scaleFactor];
+ [self setFrame:CGRectMake(0, 0, dipSize.width(), dipSize.height())];
+ }
+ return self;
+}
+
+- (CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask {
+ return CGLRetainPixelFormat(CGLGetPixelFormat(shareContext_));
+}
+
+- (CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat {
+ CGLContextObj context = NULL;
+ CGLError error = CGLCreateContext(pixelFormat, shareContext_, &context);
+ if (error != kCGLNoError)
+ DLOG(ERROR) << "CGLCreateContext failed with CGL error: " << error;
+ return context;
+}
+
+- (BOOL)canDrawInCGLContext:(CGLContextObj)glContext
+ pixelFormat:(CGLPixelFormatObj)pixelFormat
+ forLayerTime:(CFTimeInterval)timeInterval
+ displayTime:(const CVTimeStamp*)timeStamp {
+ return YES;
+}
+
+- (void)drawInCGLContext:(CGLContextObj)glContext
+ pixelFormat:(CGLPixelFormatObj)pixelFormat
+ forLayerTime:(CFTimeInterval)timeInterval
+ displayTime:(const CVTimeStamp*)timeStamp {
+ glClearColor(1, 0, 1, 1);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ GLint viewport[4] = {0, 0, 0, 0};
+ glGetIntegerv(GL_VIEWPORT, viewport);
+ gfx::Size viewportSize(viewport[2], viewport[3]);
+
+ // Set the coordinate system to be one-to-one with pixels.
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0, viewportSize.width(), 0, viewportSize.height(), -1, 1);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ // Draw a fullscreen quad.
+ glColor4f(1, 1, 1, 1);
+ glEnable(GL_TEXTURE_RECTANGLE_ARB);
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_);
+ glBegin(GL_QUADS);
+ {
+ glTexCoord2f(0, 0);
+ glVertex2f(0, 0);
+
+ glTexCoord2f(0, pixelSize_.height());
+ glVertex2f(0, pixelSize_.height());
+
+ glTexCoord2f(pixelSize_.width(), pixelSize_.height());
+ glVertex2f(pixelSize_.width(), pixelSize_.height());
+
+ glTexCoord2f(pixelSize_.width(), 0);
+ glVertex2f(pixelSize_.width(), 0);
+ }
+ glEnd();
+ glBindTexture(0, texture_);
+ glDisable(GL_TEXTURE_RECTANGLE_ARB);
+
+ [super drawInCGLContext:glContext
+ pixelFormat:pixelFormat
+ forLayerTime:timeInterval
+ displayTime:timeStamp];
+}
+
+@end
+
+namespace content {
+
+CALayerStorageProvider::CALayerStorageProvider() {
+ base::scoped_nsobject<NSDictionary> dict([[NSDictionary alloc] init]);
+ CGSConnectionID connection_id = CGSMainConnectionID();
+ context_.reset([CAContext contextWithCGSConnection:connection_id
+ options:dict]);
+ [context_ retain];
+}
+
+CALayerStorageProvider::~CALayerStorageProvider() {
+}
+
+gfx::Size CALayerStorageProvider::GetRoundedSize(gfx::Size size) {
+ return size;
+}
+
+bool CALayerStorageProvider::AllocateColorBufferStorage(
+ CGLContextObj context, GLuint texture,
+ gfx::Size pixel_size, float scale_factor) {
+ // Allocate an ordinary OpenGL texture to back the FBO.
+ GLenum error;
+ while ((error = glGetError()) != GL_NO_ERROR) {
+ DLOG(ERROR) << "Error found (and ignored) before allocating buffer "
+ << "storage: " << error;
+ }
+ glTexImage2D(GL_TEXTURE_RECTANGLE_ARB,
+ 0,
+ GL_RGBA,
+ pixel_size.width(),
+ pixel_size.height(),
+ 0,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ NULL);
+ error = glGetError();
+ if (error != GL_NO_ERROR) {
+ DLOG(ERROR) << "glTexImage failed with GL error: " << error;
+ return false;
+ }
+ glFlush();
+
+ // Disable the fade-in animation as the layer is changed.
+ ScopedCAActionDisabler disabler;
+
+ // Resize the CAOpenGLLayer to match the size needed, and change it to be the
+ // hosted layer.
+ layer_.reset([[ImageTransportLayer alloc] initWithContext:context
+ withTexture:texture
+ withPixelSize:pixel_size
+ withScaleFactor:scale_factor]);
+ return true;
+}
+
+void CALayerStorageProvider::FreeColorBufferStorage() {
+ [context_ setLayer:nil];
+ layer_.reset();
+}
+
+uint64 CALayerStorageProvider::GetSurfaceHandle() const {
+ return SurfaceHandleFromCAContextID([context_ contextId]);
+}
+
+void CALayerStorageProvider::WillSwapBuffers() {
+ // Don't add the layer to the CAContext until a SwapBuffers is going to be
+ // called, because the texture does not have any content until the
+ // SwapBuffers call is about to be made.
+ if ([context_ layer] != layer_.get())
+ [context_ setLayer:layer_];
+
+ // TODO(ccameron): Use the isAsynchronous property to ensure smooth
+ // animation.
+ [layer_ setNeedsDisplay];
+}
+
+} // namespace content
diff --git a/content/common/gpu/image_transport_surface_fbo_mac.cc b/content/common/gpu/image_transport_surface_fbo_mac.cc
index 79ec8db..3e86a48 100644
--- a/content/common/gpu/image_transport_surface_fbo_mac.cc
+++ b/content/common/gpu/image_transport_surface_fbo_mac.cc
@@ -135,6 +135,8 @@ bool ImageTransportSurfaceFBO::SwapBuffers() {
DCHECK(!is_swap_buffers_pending_);
is_swap_buffers_pending_ = true;
+
+ storage_provider_->WillSwapBuffers();
return true;
}
@@ -158,6 +160,8 @@ bool ImageTransportSurfaceFBO::PostSubBuffer(
DCHECK(!is_swap_buffers_pending_);
is_swap_buffers_pending_ = true;
+
+ storage_provider_->WillSwapBuffers();
return true;
}
@@ -321,8 +325,8 @@ void ImageTransportSurfaceFBO::CreateFramebuffer() {
}
bool allocated_color_buffer = storage_provider_->AllocateColorBufferStorage(
- static_cast<CGLContextObj>(context_->GetHandle()),
- rounded_size_);
+ static_cast<CGLContextObj>(context_->GetHandle()), texture_id_,
+ rounded_size_, scale_factor_);
if (!allocated_color_buffer) {
DLOG(ERROR) << "Failed to allocate color buffer storage.";
DestroyFramebuffer();
diff --git a/content/common/gpu/image_transport_surface_fbo_mac.h b/content/common/gpu/image_transport_surface_fbo_mac.h
index 1302cfe..3587e21 100644
--- a/content/common/gpu/image_transport_surface_fbo_mac.h
+++ b/content/common/gpu/image_transport_surface_fbo_mac.h
@@ -34,7 +34,8 @@ class ImageTransportSurfaceFBO
// Allocate the storage for the color buffer. The specified context is
// current, and there is a texture bound to GL_TEXTURE_RECTANGLE_ARB.
virtual bool AllocateColorBufferStorage(
- CGLContextObj context, gfx::Size size) = 0;
+ CGLContextObj context, GLuint texture,
+ gfx::Size size, float scale_factor) = 0;
// Free the storage allocated in the AllocateColorBufferStorage call. The
// GL texture that was bound has already been deleted by the caller.
@@ -43,6 +44,9 @@ class ImageTransportSurfaceFBO
// Retrieve the handle for the surface to send to the browser process to
// display.
virtual uint64 GetSurfaceHandle() const = 0;
+
+ // Called when a frame is about to be sent to the browser process.
+ virtual void WillSwapBuffers() = 0;
};
ImageTransportSurfaceFBO(StorageProvider* storage_provider,
diff --git a/content/common/gpu/image_transport_surface_iosurface_mac.cc b/content/common/gpu/image_transport_surface_iosurface_mac.cc
index 5d0dded..49aa4cd 100644
--- a/content/common/gpu/image_transport_surface_iosurface_mac.cc
+++ b/content/common/gpu/image_transport_surface_iosurface_mac.cc
@@ -5,6 +5,7 @@
#include "content/common/gpu/image_transport_surface_iosurface_mac.h"
#include "content/common/gpu/gpu_messages.h"
+#include "content/common/gpu/surface_handle_types_mac.h"
namespace content {
namespace {
@@ -51,8 +52,8 @@ gfx::Size IOSurfaceStorageProvider::GetRoundedSize(gfx::Size size) {
}
bool IOSurfaceStorageProvider::AllocateColorBufferStorage(
- CGLContextObj context,
- gfx::Size size) {
+ CGLContextObj context, GLuint texture,
+ gfx::Size pixel_size, float scale_factor) {
// Allocate a new IOSurface, which is the GPU resource that can be
// shared across processes.
base::ScopedCFTypeRef<CFMutableDictionaryRef> properties;
@@ -62,10 +63,10 @@ bool IOSurfaceStorageProvider::AllocateColorBufferStorage(
&kCFTypeDictionaryValueCallBacks));
AddIntegerValue(properties,
kIOSurfaceWidth,
- size.width());
+ pixel_size.width());
AddIntegerValue(properties,
kIOSurfaceHeight,
- size.height());
+ pixel_size.height());
AddIntegerValue(properties,
kIOSurfaceBytesPerElement, 4);
AddBooleanValue(properties,
@@ -74,7 +75,7 @@ bool IOSurfaceStorageProvider::AllocateColorBufferStorage(
// synchronizing with the browser process because they are
// ultimately reference counted by the operating system.
io_surface_.reset(IOSurfaceCreate(properties));
- io_surface_handle_ = IOSurfaceGetID(io_surface_);
+ io_surface_id_ = IOSurfaceGetID(io_surface_);
// Don't think we need to identify a plane.
GLuint plane = 0;
@@ -82,8 +83,8 @@ bool IOSurfaceStorageProvider::AllocateColorBufferStorage(
context,
GL_TEXTURE_RECTANGLE_ARB,
GL_RGBA,
- size.width(),
- size.height(),
+ pixel_size.width(),
+ pixel_size.height(),
GL_BGRA,
GL_UNSIGNED_INT_8_8_8_8_REV,
io_surface_.get(),
@@ -99,11 +100,14 @@ bool IOSurfaceStorageProvider::AllocateColorBufferStorage(
void IOSurfaceStorageProvider::FreeColorBufferStorage() {
io_surface_.reset();
- io_surface_handle_ = 0;
+ io_surface_id_ = 0;
}
uint64 IOSurfaceStorageProvider::GetSurfaceHandle() const {
- return io_surface_handle_;
+ return SurfaceHandleFromIOSurfaceID(io_surface_id_);
+}
+
+void IOSurfaceStorageProvider::WillSwapBuffers() {
}
} // namespace content
diff --git a/content/common/gpu/image_transport_surface_iosurface_mac.h b/content/common/gpu/image_transport_surface_iosurface_mac.h
index ccd0a4c..5470ce3 100644
--- a/content/common/gpu/image_transport_surface_iosurface_mac.h
+++ b/content/common/gpu/image_transport_surface_iosurface_mac.h
@@ -23,15 +23,17 @@ class IOSurfaceStorageProvider
// ImageTransportSurfaceFBO::StorageProvider implementation:
virtual gfx::Size GetRoundedSize(gfx::Size size) OVERRIDE;
virtual bool AllocateColorBufferStorage(
- CGLContextObj context, gfx::Size size) OVERRIDE;
+ CGLContextObj context, GLuint texture,
+ gfx::Size pixel_size, float scale_factor) OVERRIDE;
virtual void FreeColorBufferStorage() OVERRIDE;
virtual uint64 GetSurfaceHandle() const OVERRIDE;
+ virtual void WillSwapBuffers() OVERRIDE;
private:
base::ScopedCFTypeRef<IOSurfaceRef> io_surface_;
// The id of |io_surface_| or 0 if that's NULL.
- IOSurfaceID io_surface_handle_;
+ IOSurfaceID io_surface_id_;
DISALLOW_COPY_AND_ASSIGN(IOSurfaceStorageProvider);
};
diff --git a/content/common/gpu/image_transport_surface_mac.mm b/content/common/gpu/image_transport_surface_mac.mm
index 9ab2272..3cfda14 100644
--- a/content/common/gpu/image_transport_surface_mac.mm
+++ b/content/common/gpu/image_transport_surface_mac.mm
@@ -6,6 +6,7 @@
#include "content/common/gpu/gpu_messages.h"
#include "content/common/gpu/image_transport_surface_iosurface_mac.h"
+#include "content/common/gpu/image_transport_surface_calayer_mac.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_implementation.h"
@@ -48,6 +49,8 @@ scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateNativeSurface(
switch (gfx::GetGLImplementation()) {
case gfx::kGLImplementationDesktopGL:
case gfx::kGLImplementationAppleGL:
+ // TODO(ccameron): If the remote layer API is supported on this system,
+ // use a CALayerStorageProvider instead of an IOSurfaceStorageProvider.
return scoped_refptr<gfx::GLSurface>(new ImageTransportSurfaceFBO(
new IOSurfaceStorageProvider, manager, stub, surface_handle.handle));
default:
diff --git a/content/common/gpu/surface_handle_types_mac.cc b/content/common/gpu/surface_handle_types_mac.cc
new file mode 100644
index 0000000..ef72542
--- /dev/null
+++ b/content/common/gpu/surface_handle_types_mac.cc
@@ -0,0 +1,53 @@
+// 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 "content/common/gpu/surface_handle_types_mac.h"
+
+#include "base/logging.h"
+
+namespace content {
+namespace {
+
+// The type of the handle is stored in the upper 64 bits.
+const uint64 kTypeMask = 0xFFFFFFFFull << 32;
+
+const uint64 kTypeIOSurface = 0x01010101ull << 32;
+const uint64 kTypeCAContext = 0x02020202ull << 32;
+
+// To make it a bit less likely that we'll just cast off the top bits of the
+// handle to get the ID, XOR lower bits with a type-specific mask.
+const uint32 kXORMaskIOSurface = 0x01010101;
+const uint32 kXORMaskCAContext = 0x02020202;
+
+} // namespace
+
+SurfaceHandleType GetSurfaceHandleType(uint64 surface_handle) {
+ switch(surface_handle & kTypeMask) {
+ case kTypeIOSurface:
+ return kSurfaceHandleTypeIOSurface;
+ case kTypeCAContext:
+ return kSurfaceHandleTypeCAContext;
+ }
+ return kSurfaceHandleTypeInvalid;
+}
+
+IOSurfaceID IOSurfaceIDFromSurfaceHandle(uint64 surface_handle) {
+ DCHECK_EQ(kSurfaceHandleTypeIOSurface, GetSurfaceHandleType(surface_handle));
+ return static_cast<uint32>(surface_handle) ^ kXORMaskIOSurface;
+}
+
+CAContextID CAContextIDFromSurfaceHandle(uint64 surface_handle) {
+ DCHECK_EQ(kSurfaceHandleTypeCAContext, GetSurfaceHandleType(surface_handle));
+ return static_cast<uint32>(surface_handle) ^ kXORMaskCAContext;
+}
+
+uint64 SurfaceHandleFromIOSurfaceID(IOSurfaceID io_surface_id) {
+ return kTypeIOSurface | (io_surface_id ^ kXORMaskIOSurface);
+}
+
+uint64 SurfaceHandleFromCAContextID(CAContextID ca_context_id) {
+ return kTypeCAContext | (ca_context_id ^ kXORMaskCAContext);
+}
+
+} // namespace content
diff --git a/content/common/gpu/surface_handle_types_mac.h b/content/common/gpu/surface_handle_types_mac.h
new file mode 100644
index 0000000..b3ca1af
--- /dev/null
+++ b/content/common/gpu/surface_handle_types_mac.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 CONTENT_COMMON_GPU_SURFACE_HANDLE_TYPES_MAC_H_
+#define CONTENT_COMMON_GPU_SURFACE_HANDLE_TYPES_MAC_H_
+
+#include <OpenGL/CGLIOSurface.h>
+
+#include "base/basictypes.h"
+#include "ui/base/cocoa/remote_layer_api.h"
+
+namespace content {
+
+// The surface handle passed between the GPU and browser process may refer to
+// an IOSurface or a CAContext. These helper functions must be used to identify
+// and translate between the types.
+enum SurfaceHandleType {
+ kSurfaceHandleTypeInvalid,
+ kSurfaceHandleTypeIOSurface,
+ kSurfaceHandleTypeCAContext,
+};
+
+SurfaceHandleType GetSurfaceHandleType(uint64 surface_handle);
+
+CAContextID CAContextIDFromSurfaceHandle(uint64 surface_handle);
+IOSurfaceID IOSurfaceIDFromSurfaceHandle(uint64 surface_handle);
+
+uint64 SurfaceHandleFromIOSurfaceID(IOSurfaceID io_surface_id);
+uint64 SurfaceHandleFromCAContextID(CAContextID ca_context_id);
+
+} // namespace content
+
+#endif // CONTENT_COMMON_GPU_HANDLE_TYPES_MAC_H_
diff --git a/content/content_common.gypi b/content/content_common.gypi
index d74a4ac..ad69557 100644
--- a/content/content_common.gypi
+++ b/content/content_common.gypi
@@ -277,6 +277,8 @@
'common/gpu/image_transport_surface.cc',
'common/gpu/image_transport_surface.h',
'common/gpu/image_transport_surface_android.cc',
+ 'common/gpu/image_transport_surface_calayer_mac.mm',
+ 'common/gpu/image_transport_surface_calayer_mac.h',
'common/gpu/image_transport_surface_fbo_mac.cc',
'common/gpu/image_transport_surface_fbo_mac.h',
'common/gpu/image_transport_surface_linux.cc',
@@ -290,6 +292,8 @@
'common/gpu/media/gpu_video_encode_accelerator.h',
'common/gpu/stream_texture_android.cc',
'common/gpu/stream_texture_android.h',
+ 'common/gpu/surface_handle_types_mac.cc',
+ 'common/gpu/surface_handle_types_mac.h',
'common/gpu/sync_point_manager.cc',
'common/gpu/sync_point_manager.h',
'common/gpu/texture_image_transport_surface.cc',
diff --git a/ui/base/cocoa/remote_layer_api.h b/ui/base/cocoa/remote_layer_api.h
new file mode 100644
index 0000000..8d704af
--- /dev/null
+++ b/ui/base/cocoa/remote_layer_api.h
@@ -0,0 +1,59 @@
+// 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_BASE_COCOA_REMOTE_LAYER_API_H_
+#define UI_BASE_COCOA_REMOTE_LAYER_API_H_
+
+#if defined(__OBJC__)
+#import <Cocoa/Cocoa.h>
+#endif // __OBJC__
+
+#include "ui/base/ui_base_export.h"
+
+// The CGSConnectionID is used to create the CAContext in the process that is
+// going to share the CALayers that it is rendering to another process to
+// display.
+extern "C" {
+typedef uint32_t CGSConnectionID;
+CGSConnectionID CGSMainConnectionID(void);
+};
+
+// The CAContextID type identifies a CAContext across processes. This is the
+// token that is passed from the process that is sharing the CALayer that it is
+// rendering to the process that will be displaying that CALayer.
+typedef uint32_t CAContextID;
+
+#if defined(__OBJC__)
+
+// The CAContext has a static CAContextID which can be sent to another process.
+// When a CALayerHost is created using that CAContextID in another process, the
+// content displayed by that CALayerHost will be the content of the CALayer
+// that is set as the |layer| property on the CAContext.
+@interface CAContext : NSObject
++ (id)contextWithCGSConnection:(CAContextID)contextId
+ options:(NSDictionary*)optionsDict;
+@property(readonly) CAContextID contextId;
+@property(retain) CALayer *layer;
+@end
+
+// The CALayerHost is created in the process that will display the content
+// being rendered by another process. Setting the |contextId| property on
+// an object of this class will make this layer display the content of the
+// CALayer that is set to the CAContext with that CAContextID in the layer
+// sharing process.
+@interface CALayerHost : CALayer
+@property CAContextID contextId;
+@end
+
+#endif // __OBJC__
+
+namespace ui {
+
+// This function will check if all of the interfaces listed above are supported
+// on the system, and return true if they are.
+bool UI_BASE_EXPORT RemoteLayerAPISupported();
+
+} // namespace ui
+
+#endif // UI_BASE_COCOA_REMOTE_LAYER_API_H_
diff --git a/ui/base/cocoa/remote_layer_api.mm b/ui/base/cocoa/remote_layer_api.mm
new file mode 100644
index 0000000..c58402f
--- /dev/null
+++ b/ui/base/cocoa/remote_layer_api.mm
@@ -0,0 +1,43 @@
+// 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/base/cocoa/remote_layer_api.h"
+
+#include <objc/runtime.h>
+
+namespace ui {
+
+bool RemoteLayerAPISupported() {
+ // Verify the GPU process interfaces are present.
+ static Class caContextClass = NSClassFromString(@"CAContext");
+ if (!caContextClass)
+ return false;
+
+ // Note that because the contextId and layer properties are dynamic,
+ // instancesRespondToSelector will return NO for them.
+ static bool caContextClassValid =
+ [caContextClass respondsToSelector:
+ @selector(contextWithCGSConnection:options:)] &&
+ class_getProperty(caContextClass, "contextId") &&
+ class_getProperty(caContextClass, "layer");
+ if (!caContextClassValid)
+ return false;
+
+ // Verify the browser process interfaces are present.
+ static Class caLayerHostClass = NSClassFromString(@"CALayerHost");
+ if (!caLayerHostClass)
+ return false;
+
+ static bool caLayerHostClassValid =
+ [caLayerHostClass instancesRespondToSelector:@selector(contextId)] &&
+ [caLayerHostClass instancesRespondToSelector:@selector(setContextId:)];
+ if (!caLayerHostClassValid)
+ return false;
+
+ // If everything is there, we should be able to use the API.
+ return true;
+}
+
+} // namespace
+
diff --git a/ui/base/ui_base.gyp b/ui/base/ui_base.gyp
index e5ddcd7..d733be4 100644
--- a/ui/base/ui_base.gyp
+++ b/ui/base/ui_base.gyp
@@ -107,6 +107,8 @@
'cocoa/nib_loading.mm',
'cocoa/nsgraphics_context_additions.h',
'cocoa/nsgraphics_context_additions.mm',
+ 'cocoa/remote_layer_api.h',
+ 'cocoa/remote_layer_api.mm',
'cocoa/tracking_area.h',
'cocoa/tracking_area.mm',
'cocoa/underlay_opengl_hosting_window.h',