summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_mac.mm7
-rw-r--r--chrome/chrome_common.gypi2
-rw-r--r--chrome/common/accelerated_surface_mac.cc334
-rw-r--r--chrome/common/accelerated_surface_mac.h108
-rw-r--r--chrome/common/plugin_messages_internal.h6
-rw-r--r--chrome/plugin/webplugin_delegate_stub.h2
-rw-r--r--chrome/plugin/webplugin_proxy.cc22
-rw-r--r--chrome/plugin/webplugin_proxy.h9
-rw-r--r--chrome/renderer/webplugin_delegate_proxy.cc29
-rw-r--r--chrome/renderer/webplugin_delegate_proxy.h8
10 files changed, 518 insertions, 9 deletions
diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.mm b/chrome/browser/renderer_host/render_widget_host_view_mac.mm
index 079cecd..0d20f6b 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/chrome/browser/renderer_host/render_widget_host_view_mac.mm
@@ -83,6 +83,10 @@ const size_t kMaxTooltipLength = 1024;
forLayerTime:(CFTimeInterval)timeInterval
displayTime:(const CVTimeStamp *)timeStamp {
renderWidgetHostView_->DrawGPUPluginInstances(glContext);
+ [super drawInCGLContext:glContext
+ pixelFormat:pixelFormat
+ forLayerTime:timeInterval
+ displayTime:timeStamp];
}
@end
@@ -579,6 +583,7 @@ void RenderWidgetHostViewMac::DrawGPUPluginInstances(CGLContextObj context) {
glOrtho(0, rect.width(), rect.height(), 0, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
+
plugin_container_manager_.Draw(context);
}
@@ -1469,7 +1474,7 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
// TODO(hbono): Even though many input method works without implementing
// this method, we need to save a copy of the string in the setMarkedText
// method and create a NSAttributedString with the given range.
- NOTIMPLEMENTED();
+ // http://crbug.com/37715
return nil;
}
diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi
index 934e097..4fb4c85 100644
--- a/chrome/chrome_common.gypi
+++ b/chrome/chrome_common.gypi
@@ -23,6 +23,8 @@
# .cc, .h, and .mm files under chrome/common that are used on all
# platforms, including both 32-bit and 64-bit Windows.
# Test files are not included.
+ 'common/accelerated_surface_mac.cc',
+ 'common/accelerated_surface_mac.h',
'common/app_mode_constants_mac.h',
'common/app_mode_constants_mac.mm',
'common/bindings_policy.h',
diff --git a/chrome/common/accelerated_surface_mac.cc b/chrome/common/accelerated_surface_mac.cc
new file mode 100644
index 0000000..d12ecb6
--- /dev/null
+++ b/chrome/common/accelerated_surface_mac.cc
@@ -0,0 +1,334 @@
+// Copyright (c) 2010 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 "chrome/common/accelerated_surface_mac.h"
+
+#include "base/gfx/rect.h"
+#include "base/logging.h"
+#include "chrome/common/io_surface_support_mac.h"
+
+AcceleratedSurface::AcceleratedSurface()
+ : gl_context_(NULL),
+ pbuffer_(NULL),
+ surface_width_(0),
+ surface_height_(0),
+ texture_(0),
+ fbo_(0),
+ depth_stencil_renderbuffer_(0),
+ bound_fbo_(0),
+ bound_renderbuffer_(0) {
+}
+
+bool AcceleratedSurface::Initialize() {
+ // Create a 1x1 pbuffer and associated context to bootstrap things
+ static const CGLPixelFormatAttribute attribs[] = {
+ (CGLPixelFormatAttribute) kCGLPFAPBuffer,
+ (CGLPixelFormatAttribute) 0
+ };
+ CGLPixelFormatObj pixel_format;
+ GLint num_pixel_formats;
+ if (CGLChoosePixelFormat(attribs,
+ &pixel_format,
+ &num_pixel_formats) != kCGLNoError) {
+ DLOG(ERROR) << "Error choosing pixel format.";
+ return false;
+ }
+ if (!pixel_format) {
+ return false;
+ }
+ CGLContextObj context;
+ CGLError res = CGLCreateContext(pixel_format, 0, &context);
+ CGLDestroyPixelFormat(pixel_format);
+ if (res != kCGLNoError) {
+ DLOG(ERROR) << "Error creating context.";
+ return false;
+ }
+ CGLPBufferObj pbuffer;
+ if (CGLCreatePBuffer(1, 1,
+ GL_TEXTURE_2D, GL_RGBA,
+ 0, &pbuffer) != kCGLNoError) {
+ CGLDestroyContext(context);
+ DLOG(ERROR) << "Error creating pbuffer.";
+ return false;
+ }
+ if (CGLSetPBuffer(context, pbuffer, 0, 0, 0) != kCGLNoError) {
+ CGLDestroyContext(context);
+ CGLDestroyPBuffer(pbuffer);
+ DLOG(ERROR) << "Error attaching pbuffer to context.";
+ return false;
+ }
+ gl_context_ = context;
+ pbuffer_ = pbuffer;
+ // Now we're ready to handle SetWindowSize calls, which will
+ // allocate and/or reallocate the IOSurface and associated offscreen
+ // OpenGL structures for rendering.
+ return true;
+}
+
+void AcceleratedSurface::Destroy() {
+ // Release the old TransportDIB in the browser.
+ if (dib_free_callback_.get() && transport_dib_.get()) {
+ dib_free_callback_->Run(transport_dib_->id());
+ }
+ transport_dib_.reset();
+ if (gl_context_)
+ CGLDestroyContext(gl_context_);
+ if (pbuffer_)
+ CGLDestroyPBuffer(pbuffer_);
+}
+
+// Call after making changes to the surface which require a visual update.
+// Makes the rendering show up in other processes.
+void AcceleratedSurface::SwapBuffers() {
+ if (bound_fbo_ != fbo_) {
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_);
+ }
+ if (io_surface_.get() != NULL) {
+ // Bind and unbind the framebuffer to make changes to the
+ // IOSurface show up in the other process.
+ glFlush();
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_);
+ } else if (transport_dib_.get() != NULL) {
+ // Pre-Mac OS X 10.6, fetch the rendered image from the FBO and copy it
+ // into the TransportDIB.
+ // TODO(dspringer): There are a couple of options that can speed this up.
+ // First is to use async reads into a PBO, second is to use SPI that
+ // allows many tasks to access the same CGSSurface.
+ void* pixel_memory = transport_dib_->memory();
+ if (pixel_memory) {
+ // Note that glReadPixels does an implicit glFlush().
+ glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
+ glReadPixels(0,
+ 0,
+ surface_width_,
+ surface_height_,
+ GL_BGRA, // This pixel format should have no conversion.
+ GL_UNSIGNED_INT_8_8_8_8_REV,
+ pixel_memory);
+ }
+ }
+ if (bound_fbo_ != fbo_) {
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_);
+ }
+}
+
+static void AddBooleanValue(CFMutableDictionaryRef dictionary,
+ const CFStringRef key,
+ bool value) {
+ CFDictionaryAddValue(dictionary, key,
+ (value ? kCFBooleanTrue : kCFBooleanFalse));
+}
+
+static void AddIntegerValue(CFMutableDictionaryRef dictionary,
+ const CFStringRef key,
+ int32 value) {
+ CFNumberRef number = CFNumberCreate(NULL, kCFNumberSInt32Type, &value);
+ CFDictionaryAddValue(dictionary, key, number);
+}
+
+void AcceleratedSurface::AllocateRenderBuffers(GLenum target,
+ int32 width, int32 height) {
+ if (!texture_) {
+ // Generate the texture object.
+ glGenTextures(1, &texture_);
+ glBindTexture(target, texture_);
+ glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ // Generate and bind the framebuffer object.
+ glGenFramebuffersEXT(1, &fbo_);
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_);
+ bound_fbo_ = fbo_;
+ // Generate (but don't bind) the depth buffer -- we don't need
+ // this bound in order to do offscreen rendering.
+ glGenRenderbuffersEXT(1, &depth_stencil_renderbuffer_);
+ }
+
+ // Reallocate the depth buffer.
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_stencil_renderbuffer_);
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,
+ GL_DEPTH24_STENCIL8_EXT,
+ width,
+ height);
+
+ // Unbind the renderbuffers.
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, bound_renderbuffer_);
+
+ // Make sure that subsequent set-up code affects the render texture.
+ glBindTexture(target, texture_);
+}
+
+bool AcceleratedSurface::SetupFrameBufferObject(GLenum target) {
+ if (bound_fbo_ != fbo_) {
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_);
+ }
+ GLenum fbo_status;
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
+ GL_COLOR_ATTACHMENT0_EXT,
+ target,
+ texture_,
+ 0);
+ fbo_status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
+ if (fbo_status == GL_FRAMEBUFFER_COMPLETE_EXT) {
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
+ GL_DEPTH_ATTACHMENT_EXT,
+ GL_RENDERBUFFER_EXT,
+ depth_stencil_renderbuffer_);
+ fbo_status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
+ }
+ // Attach the depth and stencil buffer.
+ if (fbo_status == GL_FRAMEBUFFER_COMPLETE_EXT) {
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
+ 0x8D20, // GL_STENCIL_ATTACHMENT,
+ GL_RENDERBUFFER_EXT,
+ depth_stencil_renderbuffer_);
+ fbo_status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
+ }
+ if (bound_fbo_ != fbo_) {
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_);
+ }
+ return fbo_status == GL_FRAMEBUFFER_COMPLETE_EXT;
+}
+
+bool AcceleratedSurface::MakeCurrent() {
+ if (CGLGetCurrentContext() != gl_context_) {
+ if (CGLSetCurrentContext(gl_context_) != kCGLNoError) {
+ DLOG(ERROR) << "Unable to make gl context current.";
+ return false;
+ }
+ }
+ return true;
+}
+
+void AcceleratedSurface::Clear(const gfx::Rect& rect) {
+ glClearColor(1.0, 1.0, 1.0, 1.0);
+ glViewport(0, 0, rect.width(), rect.height());
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0, rect.width(), 0, rect.height(), -1, 1);
+ glClear(GL_COLOR_BUFFER_BIT);
+}
+
+uint64 AcceleratedSurface::SetSurfaceSize(int32 width, int32 height) {
+ if (surface_width_ == width && surface_height_ == height) {
+ // Return 0 to indicate to the caller that no new backing store
+ // allocation occurred.
+ return 0;
+ }
+
+ IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize();
+ if (!io_surface_support)
+ return 0; // Caller can try using SetWindowSizeForTransportDIB().
+
+ if (!MakeCurrent())
+ return 0;
+
+ // GL_TEXTURE_RECTANGLE_ARB is the best supported render target on
+ // Mac OS X and is required for IOSurface interoperability.
+ GLenum target = GL_TEXTURE_RECTANGLE_ARB;
+ AllocateRenderBuffers(target, width, height);
+
+ // Allocate a new IOSurface, which is the GPU resource that can be
+ // shared across processes.
+ scoped_cftyperef<CFMutableDictionaryRef> properties;
+ properties.reset(CFDictionaryCreateMutable(kCFAllocatorDefault,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks));
+ AddIntegerValue(properties,
+ io_surface_support->GetKIOSurfaceWidth(), width);
+ AddIntegerValue(properties,
+ io_surface_support->GetKIOSurfaceHeight(), height);
+ AddIntegerValue(properties,
+ io_surface_support->GetKIOSurfaceBytesPerElement(), 4);
+ AddBooleanValue(properties,
+ io_surface_support->GetKIOSurfaceIsGlobal(), true);
+ // I believe we should be able to unreference the IOSurfaces without
+ // synchronizing with the browser process because they are
+ // ultimately reference counted by the operating system.
+ io_surface_.reset(io_surface_support->IOSurfaceCreate(properties));
+
+ // Don't think we need to identify a plane.
+ GLuint plane = 0;
+ io_surface_support->CGLTexImageIOSurface2D(gl_context_,
+ target,
+ GL_RGBA,
+ width,
+ height,
+ GL_BGRA,
+ GL_UNSIGNED_INT_8_8_8_8_REV,
+ io_surface_.get(),
+ plane);
+ // Set up the frame buffer object.
+ SetupFrameBufferObject(target);
+ surface_width_ = width;
+ surface_height_ = height;
+
+ // Now send back an identifier for the IOSurface. We originally
+ // intended to send back a mach port from IOSurfaceCreateMachPort
+ // but it looks like Chrome IPC would need to be modified to
+ // properly send mach ports between processes. For the time being we
+ // make our IOSurfaces global and send back their identifiers. On
+ // the browser process side the identifier is reconstituted into an
+ // IOSurface for on-screen rendering.
+ return io_surface_support->IOSurfaceGetID(io_surface_);
+}
+
+TransportDIB::Handle AcceleratedSurface::SetTransportDIBSize(
+ int32 width, int32 height) {
+ if (surface_width_ == width && surface_height_ == height) {
+ // Return an invalid handle to indicate to the caller that no new backing
+ // store allocation occurred.
+ return TransportDIB::DefaultHandleValue();
+ }
+ surface_width_ = width;
+ surface_height_ = height;
+
+ // Release the old TransportDIB in the browser.
+ if (dib_free_callback_.get() && transport_dib_.get()) {
+ dib_free_callback_->Run(transport_dib_->id());
+ }
+ transport_dib_.reset();
+
+ // Ask the renderer to create a TransportDIB.
+ size_t dib_size = width * 4 * height; // 4 bytes per pixel.
+ TransportDIB::Handle dib_handle;
+ if (dib_alloc_callback_.get()) {
+ dib_alloc_callback_->Run(dib_size, &dib_handle);
+ }
+ if (!TransportDIB::is_valid(dib_handle)) {
+ // If the allocator fails, it means the DIB was not created in the browser,
+ // so there is no need to run the deallocator here.
+ return TransportDIB::DefaultHandleValue();
+ }
+ transport_dib_.reset(TransportDIB::Map(dib_handle));
+ if (transport_dib_.get() == NULL) {
+ // TODO(dspringer): if the Map() fails, should the deallocator be run so
+ // that the DIB is deallocated in the browser?
+ return TransportDIB::DefaultHandleValue();
+ }
+
+ // Set up the render buffers and reserve enough space on the card for the
+ // framebuffer texture.
+ GLenum target = GL_TEXTURE_RECTANGLE_ARB;
+ AllocateRenderBuffers(target, width, height);
+ glTexImage2D(target,
+ 0, // mipmap level 0
+ GL_RGBA8, // internal pixel format
+ width,
+ height,
+ 0, // 0 border
+ GL_BGRA, // Used for consistency
+ GL_UNSIGNED_INT_8_8_8_8_REV,
+ NULL); // No data, just reserve room on the card.
+ SetupFrameBufferObject(target);
+ return transport_dib_->handle();
+}
+
+void AcceleratedSurface::SetTransportDIBAllocAndFree(
+ Callback2<size_t, TransportDIB::Handle*>::Type* allocator,
+ Callback1<TransportDIB::Id>::Type* deallocator) {
+ dib_alloc_callback_.reset(allocator);
+ dib_free_callback_.reset(deallocator);
+}
diff --git a/chrome/common/accelerated_surface_mac.h b/chrome/common/accelerated_surface_mac.h
new file mode 100644
index 0000000..e8c27af
--- /dev/null
+++ b/chrome/common/accelerated_surface_mac.h
@@ -0,0 +1,108 @@
+// Copyright (c) 2010 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 CHROME_COMMON_ACCELERATED_SURFACE_MAC_H_
+#define CHROME_COMMON_ACCELERATED_SURFACE_MAC_H_
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <OpenGL/OpenGL.h>
+
+#include "base/callback.h"
+#include "base/scoped_cftyperef.h"
+#include "base/scoped_ptr.h"
+#include "chrome/common/transport_dib.h"
+
+namespace gfx {
+class Rect;
+}
+
+// Encapsulates an accelerated GL surface that can be shared across processes
+// on systems that support it (10.6 and above). For systems that do not, it
+// uses a regular dib. There will either be a GL Context or a TransportDIB,
+// never both.
+
+class AcceleratedSurface {
+ public:
+ AcceleratedSurface();
+ virtual ~AcceleratedSurface() { }
+
+ // Set up internal buffers. Returns false upon failure.
+ bool Initialize();
+ // Tear down. Must be called before destructor to prevent leaks.
+ void Destroy();
+
+ // These methods are used only when there is a GL surface.
+
+ // Sets the accelerated surface to the given size, creating a new one if
+ // the height or width changes. Returns a unique id of the IOSurface to
+ // which the surface is bound, or 0 if no changes were made or an error
+ // occurred. MakeCurrent() will have been called on the new surface.
+ uint64 SetSurfaceSize(int32 width, int32 height);
+ // Sets the GL context to be the current one for drawing. Returns true if
+ // it succeeded.
+ bool MakeCurrent();
+ // Clear the surface to all white. Assumes the caller has already called
+ // MakeCurrent().
+ void Clear(const gfx::Rect& rect);
+ // Call after making changes to the surface which require a visual update.
+ // Makes the rendering show up in other processes.
+ void SwapBuffers();
+ CGLContextObj context() { return gl_context_; }
+
+ // These methods are only used when there is a transport DIB.
+
+ // Sets the transport DIB to the given size, creating a new one if the
+ // height or width changes. Returns a handle to the new DIB, or a default
+ // handle if no changes were made.
+ TransportDIB::Handle SetTransportDIBSize(int32 width, int32 height);
+ // Sets the methods to use for allocating and freeing memory for the
+ // transport DIB.
+ void SetTransportDIBAllocAndFree(
+ Callback2<size_t, TransportDIB::Handle*>::Type* allocator,
+ Callback1<TransportDIB::Id>::Type* deallocator);
+
+ private:
+ // Helper function to generate names for the backing texture, render buffers
+ // and FBO. On return, the resulting buffer names can be attached to |fbo_|.
+ // |target| is the target type for the color buffer.
+ void AllocateRenderBuffers(GLenum target, int32 width, int32 height);
+
+ // Helper function to attach the buffers previously allocated by a call to
+ // AllocateRenderBuffers(). On return, |fbo_| can be used for
+ // rendering. |target| must be the same value as used in the call to
+ // AllocateRenderBuffers(). Returns |true| if the resulting framebuffer
+ // object is valid.
+ bool SetupFrameBufferObject(GLenum target);
+
+ CGLContextObj gl_context_;
+ CGLPBufferObj pbuffer_;
+ // Either |io_surface_| or |transport_dib_| is a valid pointer, but not both.
+ // |io_surface_| is non-NULL if the IOSurface APIs are supported (Mac OS X
+ // 10.6 and later).
+ // TODO(dspringer,kbr): Should the GPU backing store be encapsulated in its
+ // own class so all this implementation detail is hidden?
+ scoped_cftyperef<CFTypeRef> io_surface_;
+ // TODO(dspringer): If we end up keeping this TransportDIB mechanism, this
+ // should really be a scoped_ptr_malloc<>, with a deallocate functor that
+ // runs |dib_free_callback_|. I was not able to figure out how to
+ // make this work (or even compile).
+ scoped_ptr<TransportDIB> transport_dib_;
+ int32 surface_width_;
+ int32 surface_height_;
+ GLuint texture_;
+ GLuint fbo_;
+ GLuint depth_stencil_renderbuffer_;
+ // For tracking whether the default framebuffer / renderbuffer or
+ // ones created by the end user are currently bound
+ // TODO(kbr): Need to property hook up and track the OpenGL state and hook
+ // up the notion of the currently bound FBO.
+ GLuint bound_fbo_;
+ GLuint bound_renderbuffer_;
+ // Allocate a TransportDIB in the renderer.
+ scoped_ptr<Callback2<size_t, TransportDIB::Handle*>::Type>
+ dib_alloc_callback_;
+ scoped_ptr<Callback1<TransportDIB::Id>::Type> dib_free_callback_;
+};
+
+#endif // CHROME_COMMON_ACCELERATED_SURFACE_MAC_H_
diff --git a/chrome/common/plugin_messages_internal.h b/chrome/common/plugin_messages_internal.h
index 3a5594c..08e1aba 100644
--- a/chrome/common/plugin_messages_internal.h
+++ b/chrome/common/plugin_messages_internal.h
@@ -416,6 +416,12 @@ IPC_BEGIN_MESSAGES(PluginHost)
int32 /* height */,
TransportDIB::Handle /* handle to the TransportDIB */)
+ // Synthesize a fake window handle for the plug-in to identify the instance
+ // to the browser, allowing mapping to a surface for hardware accelleration
+ // of plug-in content. The browser generates the handle which is then set on
+ // the plug-in.
+ IPC_MESSAGE_ROUTED0(PluginHostMsg_BindFakePluginWindowHandle)
+
// This message, used only on 10.6 and later, is sent from the
// plug-in process to the renderer process to indicate that the GPU
// plugin allocated a new IOSurface object of the given width and
diff --git a/chrome/plugin/webplugin_delegate_stub.h b/chrome/plugin/webplugin_delegate_stub.h
index 1bbd04d..64dea79d 100644
--- a/chrome/plugin/webplugin_delegate_stub.h
+++ b/chrome/plugin/webplugin_delegate_stub.h
@@ -33,7 +33,7 @@ class WebInputEvent;
class WebPluginDelegateImpl;
// Converts the IPC messages from WebPluginDelegateProxy into calls to the
-// actual WebPluginDelegate object.
+// actual WebPluginDelegateImpl object.
class WebPluginDelegateStub : public IPC::Channel::Listener,
public IPC::Message::Sender,
public base::RefCounted<WebPluginDelegateStub> {
diff --git a/chrome/plugin/webplugin_proxy.cc b/chrome/plugin/webplugin_proxy.cc
index ffda5c1..e7826fd 100644
--- a/chrome/plugin/webplugin_proxy.cc
+++ b/chrome/plugin/webplugin_proxy.cc
@@ -576,6 +576,28 @@ void WebPluginProxy::SetDeferResourceLoading(unsigned long resource_id,
Send(new PluginHostMsg_DeferResourceLoading(route_id_, resource_id, defer));
}
+#if defined(OS_MACOSX)
+void WebPluginProxy::BindFakePluginWindowHandle() {
+ Send(new PluginHostMsg_BindFakePluginWindowHandle(route_id_));
+}
+
+void WebPluginProxy::AcceleratedFrameBuffersDidSwap(
+ gfx::PluginWindowHandle window) {
+ // TODO(pinkerton): Rename this message.
+ Send(new PluginHostMsg_GPUPluginBuffersSwapped(route_id_, window));
+}
+
+void WebPluginProxy::SetAcceleratedSurface(gfx::PluginWindowHandle window,
+ int32 width,
+ int32 height,
+ uint64 accelerated_surface_identifier) {
+ // TODO(pinkerton): Rename this message.
+ Send(new PluginHostMsg_GPUPluginSetIOSurface(route_id_, window, width,
+ height,
+ accelerated_surface_identifier));
+}
+#endif
+
void WebPluginProxy::OnPaint(const gfx::Rect& damaged_rect) {
child_process_logging::SetActiveURL(page_url_);
diff --git a/chrome/plugin/webplugin_proxy.h b/chrome/plugin/webplugin_proxy.h
index 0beb9cb..9329d6c 100644
--- a/chrome/plugin/webplugin_proxy.h
+++ b/chrome/plugin/webplugin_proxy.h
@@ -132,6 +132,15 @@ class WebPluginProxy : public webkit_glue::WebPlugin {
webkit_glue::WebPluginResourceClient* resource_client);
gfx::NativeViewId containing_window() { return containing_window_; }
+#if defined(OS_MACOSX)
+ virtual void BindFakePluginWindowHandle();
+ virtual void AcceleratedFrameBuffersDidSwap(gfx::PluginWindowHandle window);
+ virtual void SetAcceleratedSurface(gfx::PluginWindowHandle window,
+ int32 width,
+ int32 height,
+ uint64 accelerated_surface_identifier);
+#endif
+
private:
bool Send(IPC::Message* msg);
diff --git a/chrome/renderer/webplugin_delegate_proxy.cc b/chrome/renderer/webplugin_delegate_proxy.cc
index b00f1b5..10bf1f8 100644
--- a/chrome/renderer/webplugin_delegate_proxy.cc
+++ b/chrome/renderer/webplugin_delegate_proxy.cc
@@ -402,6 +402,8 @@ void WebPluginDelegateProxy::OnMessageReceived(const IPC::Message& msg) {
OnDeferResourceLoading)
#if defined(OS_MACOSX)
+ IPC_MESSAGE_HANDLER(PluginHostMsg_BindFakePluginWindowHandle,
+ OnBindFakePluginWindowHandle);
IPC_MESSAGE_HANDLER(PluginHostMsg_UpdateGeometry_ACK,
OnUpdateGeometry_ACK)
// Used only on 10.6 and later.
@@ -1255,25 +1257,38 @@ WebPluginDelegateProxy::CreateSeekableResourceClient(
return proxy;
}
-CommandBufferProxy* WebPluginDelegateProxy::CreateCommandBuffer() {
-#if defined(ENABLE_GPU)
#if defined(OS_MACOSX)
- // We need to synthesize a fake window handle for this nested
- // delegate to identify the instance of the GPU plugin back to the
- // browser.
+void WebPluginDelegateProxy::OnBindFakePluginWindowHandle() {
+ BindFakePluginWindowHandle();
+}
+
+// Synthesize a fake window handle for the plug-in to identify the instance
+// to the browser, allowing mapping to a surface for hardware acceleration
+// of plug-in content. The browser generates the handle which is then set on
+// the plug-in. Returns true if it successfully sets the window handle on the
+// plug-in.
+bool WebPluginDelegateProxy::BindFakePluginWindowHandle() {
gfx::PluginWindowHandle fake_window = NULL;
if (render_view_)
fake_window = render_view_->AllocateFakePluginWindowHandle();
// If we aren't running on 10.6, this allocation will fail.
if (!fake_window)
- return NULL;
+ return false;
OnSetWindow(fake_window);
if (!Send(new PluginMsg_SetFakeGPUPluginWindowHandle(instance_id_,
fake_window))) {
- return NULL;
+ return false;
}
+ return true;
+}
#endif
+CommandBufferProxy* WebPluginDelegateProxy::CreateCommandBuffer() {
+#if defined(ENABLE_GPU)
+#if defined(OS_MACOSX)
+ if (!BindFakePluginWindowHandle())
+ return NULL;
+#endif
int command_buffer_id;
if (!Send(new PluginMsg_CreateCommandBuffer(instance_id_,
&command_buffer_id))) {
diff --git a/chrome/renderer/webplugin_delegate_proxy.h b/chrome/renderer/webplugin_delegate_proxy.h
index 212758e..cdeb62a 100644
--- a/chrome/renderer/webplugin_delegate_proxy.h
+++ b/chrome/renderer/webplugin_delegate_proxy.h
@@ -149,6 +149,7 @@ class WebPluginDelegateProxy
void OnDeferResourceLoading(unsigned long resource_id, bool defer);
#if defined(OS_MACOSX)
+ void OnBindFakePluginWindowHandle();
void OnUpdateGeometry_ACK(int ack_key);
void OnGPUPluginSetIOSurface(gfx::PluginWindowHandle window,
int32 width,
@@ -188,6 +189,13 @@ class WebPluginDelegateProxy
void WillDestroyWindow();
#if defined(OS_MACOSX)
+ // Synthesize a fake window handle for the plug-in to identify the instance
+ // to the browser, allowing mapping to a surface for hardware acceleration
+ // of plug-in content. The browser generates the handle which is then set on
+ // the plug-in. Returns true if it successfully sets the window handle on the
+ // plug-in.
+ bool BindFakePluginWindowHandle();
+
// The Mac TransportDIB implementation uses base::SharedMemory, which
// cannot be disposed of if an in-flight UpdateGeometry message refers to
// the shared memory file descriptor. The old_transport_dibs_ map holds