diff options
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/renderer_host/render_widget_host_view_mac.mm | 7 | ||||
-rw-r--r-- | chrome/chrome_common.gypi | 2 | ||||
-rw-r--r-- | chrome/common/accelerated_surface_mac.cc | 334 | ||||
-rw-r--r-- | chrome/common/accelerated_surface_mac.h | 108 | ||||
-rw-r--r-- | chrome/common/plugin_messages_internal.h | 6 | ||||
-rw-r--r-- | chrome/plugin/webplugin_delegate_stub.h | 2 | ||||
-rw-r--r-- | chrome/plugin/webplugin_proxy.cc | 22 | ||||
-rw-r--r-- | chrome/plugin/webplugin_proxy.h | 9 | ||||
-rw-r--r-- | chrome/renderer/webplugin_delegate_proxy.cc | 29 | ||||
-rw-r--r-- | chrome/renderer/webplugin_delegate_proxy.h | 8 |
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 |