summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--app/gfx/native_widget_types.h11
-rw-r--r--build/common.gypi11
-rw-r--r--chrome/browser/renderer_host/render_widget_host.cc44
-rw-r--r--chrome/browser/renderer_host/render_widget_host.h8
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view.h16
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_mac.h19
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_mac.mm123
-rw-r--r--chrome/browser/renderer_host/test/test_render_view_host.cc23
-rw-r--r--chrome/browser/renderer_host/test/test_render_view_host.h8
-rwxr-xr-xchrome/chrome.gyp2
-rwxr-xr-xchrome/chrome_browser.gypi1
-rw-r--r--chrome/chrome_common.gypi2
-rwxr-xr-xchrome/chrome_renderer.gypi2
-rw-r--r--chrome/common/command_buffer_messages_internal.h11
-rw-r--r--chrome/common/gpu_plugin.cc2
-rw-r--r--chrome/common/io_surface_support_mac.cc242
-rw-r--r--chrome/common/io_surface_support_mac.h66
-rw-r--r--chrome/common/plugin_messages_internal.h32
-rw-r--r--chrome/common/render_messages_internal.h35
-rw-r--r--chrome/plugin/command_buffer_stub.cc29
-rw-r--r--chrome/plugin/command_buffer_stub.h9
-rw-r--r--chrome/plugin/webplugin_delegate_stub.cc15
-rw-r--r--chrome/plugin/webplugin_delegate_stub.h8
-rw-r--r--chrome/renderer/command_buffer_proxy.cc7
-rw-r--r--chrome/renderer/command_buffer_proxy.h4
-rw-r--r--chrome/renderer/render_view.cc27
-rw-r--r--chrome/renderer/render_view.h12
-rw-r--r--chrome/renderer/webplugin_delegate_pepper.cc16
-rw-r--r--chrome/renderer/webplugin_delegate_proxy.cc46
-rw-r--r--chrome/renderer/webplugin_delegate_proxy.h5
-rw-r--r--gpu/DEPS4
-rw-r--r--gpu/command_buffer/client/gles2_demo_cc.cc40
-rw-r--r--gpu/command_buffer/common/cmd_buffer_common.cc6
-rw-r--r--gpu/command_buffer/common/cmd_buffer_common.h2
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc255
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.h6
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_mock.h1
-rw-r--r--gpu/command_buffer/service/gpu_processor.cc11
-rw-r--r--gpu/command_buffer/service/gpu_processor.h13
-rw-r--r--gpu/command_buffer/service/gpu_processor_mac.cc39
-rw-r--r--gpu/gpu.gyp16
-rw-r--r--gpu/gpu_plugin/gpu_plugin.cc4
-rw-r--r--gpu/gpu_plugin/gpu_plugin.h2
-rw-r--r--webkit/glue/plugins/mac_gpu_plugin_container.cc104
-rw-r--r--webkit/glue/plugins/mac_gpu_plugin_container.h98
-rw-r--r--webkit/glue/plugins/mac_gpu_plugin_container_manager.cc89
-rw-r--r--webkit/glue/plugins/mac_gpu_plugin_container_manager.h70
-rw-r--r--webkit/glue/plugins/webplugin_delegate_impl.h16
-rw-r--r--webkit/glue/webplugin.h9
-rw-r--r--webkit/glue/webplugin_impl.cc18
-rw-r--r--webkit/tools/pepper_test_plugin/pepper_test_plugin.gyp12
-rw-r--r--webkit/tools/pepper_test_plugin/plugin_object.cc12
-rw-r--r--webkit/tools/pepper_test_plugin/test_page.html4
-rw-r--r--webkit/tools/test_shell/mac/test_webview_delegate.mm8
-rw-r--r--webkit/webkit.gyp9
55 files changed, 1638 insertions, 46 deletions
diff --git a/app/gfx/native_widget_types.h b/app/gfx/native_widget_types.h
index ba845a0..af5baa9 100644
--- a/app/gfx/native_widget_types.h
+++ b/app/gfx/native_widget_types.h
@@ -140,8 +140,15 @@ NativeViewId IdFromNativeView(NativeView view);
// On OS X we don't have windowed plugins.
// We use a NULL/0 PluginWindowHandle in shared code to indicate there
// is no window present, so mirror that behavior here.
- typedef bool PluginWindowHandle;
- const PluginWindowHandle kNullPluginWindow = false;
+ //
+ // The GPU plugin is currently an exception to this rule. As of this
+ // writing it uses some NPAPI infrastructure, and minimally we need
+ // to identify the plugin instance via this window handle. When the
+ // GPU plugin becomes a full-on GPU process, this typedef can be
+ // returned to a bool. For now we use a type large enough to hold a
+ // pointer on 64-bit architectures in case we need this capability.
+ typedef uint64 PluginWindowHandle;
+ const PluginWindowHandle kNullPluginWindow = 0;
#endif
} // namespace gfx
diff --git a/build/common.gypi b/build/common.gypi
index e8fd690..a100fa1 100644
--- a/build/common.gypi
+++ b/build/common.gypi
@@ -280,6 +280,15 @@
'NACL_WIN64',
],
}],
+ # Compute based on OS and target architecture whether the GPU
+ # plugin / process is supported.
+ [ 'OS=="win" or (OS=="linux" and target_arch!="arm") or OS=="mac"', {
+ # Enable a variable used elsewhere throughout the GYP files to determine
+ # whether to compile in the sources for the GPU plugin / process.
+ 'enable_gpu%': 1,
+ }, { # GPU plugin not supported
+ 'enable_gpu%': 0,
+ }],
],
# NOTE: When these end up in the Mac bundle, we need to replace '-' for '_'
@@ -346,7 +355,7 @@
}],
],
}],
- ['OS=="win" or (OS=="linux" and target_arch!="arm")', {
+ ['enable_gpu==1', {
'defines': [
'ENABLE_GPU=1',
],
diff --git a/chrome/browser/renderer_host/render_widget_host.cc b/chrome/browser/renderer_host/render_widget_host.cc
index cde8932..6a20f26 100644
--- a/chrome/browser/renderer_host/render_widget_host.cc
+++ b/chrome/browser/renderer_host/render_widget_host.cc
@@ -143,6 +143,15 @@ void RenderWidgetHost::OnMessageReceived(const IPC::Message &msg) {
IPC_MESSAGE_HANDLER(ViewHostMsg_GetScreenInfo, OnMsgGetScreenInfo)
IPC_MESSAGE_HANDLER(ViewHostMsg_GetWindowRect, OnMsgGetWindowRect)
IPC_MESSAGE_HANDLER(ViewHostMsg_GetRootWindowRect, OnMsgGetRootWindowRect)
+ // The following messages are only used on 10.6 and later
+ IPC_MESSAGE_HANDLER(ViewHostMsg_AllocateFakePluginWindowHandle,
+ OnAllocateFakePluginWindowHandle)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_DestroyFakePluginWindowHandle,
+ OnDestroyFakePluginWindowHandle)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_GPUPluginSetIOSurface,
+ OnGPUPluginSetIOSurface)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_GPUPluginBuffersSwapped,
+ OnGPUPluginBuffersSwapped)
#endif
IPC_MESSAGE_UNHANDLED_ERROR()
IPC_END_MESSAGE_MAP_EX()
@@ -874,6 +883,41 @@ void RenderWidgetHost::OnMsgGetRootWindowRect(gfx::NativeViewId window_id,
}
}
+void RenderWidgetHost::OnAllocateFakePluginWindowHandle(
+ gfx::PluginWindowHandle* id) {
+ // TODO(kbr): similar potential issue here as in OnMsgCreatePluginContainer.
+ // Possibly less of an issue because this is only used for the GPU plugin.
+ if (view_) {
+ *id = view_->AllocateFakePluginWindowHandle();
+ } else {
+ NOTIMPLEMENTED();
+ }
+}
+
+void RenderWidgetHost::OnDestroyFakePluginWindowHandle(
+ gfx::PluginWindowHandle id) {
+ if (view_) {
+ view_->DestroyFakePluginWindowHandle(id);
+ } else {
+ NOTIMPLEMENTED();
+ }
+}
+
+void RenderWidgetHost::OnGPUPluginSetIOSurface(gfx::PluginWindowHandle window,
+ int32 width,
+ int32 height,
+ uint64 mach_port) {
+ if (view_) {
+ view_->GPUPluginSetIOSurface(window, width, height, mach_port);
+ }
+}
+
+void RenderWidgetHost::OnGPUPluginBuffersSwapped(
+ gfx::PluginWindowHandle window) {
+ if (view_) {
+ view_->GPUPluginBuffersSwapped(window);
+ }
+}
#endif
void RenderWidgetHost::PaintBackingStoreRect(
diff --git a/chrome/browser/renderer_host/render_widget_host.h b/chrome/browser/renderer_host/render_widget_host.h
index f08dee3..ea6c843 100644
--- a/chrome/browser/renderer_host/render_widget_host.h
+++ b/chrome/browser/renderer_host/render_widget_host.h
@@ -444,6 +444,14 @@ class RenderWidgetHost : public IPC::Channel::Listener,
WebKit::WebScreenInfo* results);
void OnMsgGetWindowRect(gfx::NativeViewId window_id, gfx::Rect* results);
void OnMsgGetRootWindowRect(gfx::NativeViewId window_id, gfx::Rect* results);
+ // The following handlers are only used on 10.6 and later
+ void OnAllocateFakePluginWindowHandle(gfx::PluginWindowHandle* id);
+ void OnDestroyFakePluginWindowHandle(gfx::PluginWindowHandle id);
+ void OnGPUPluginSetIOSurface(gfx::PluginWindowHandle window,
+ int32 width,
+ int32 height,
+ uint64 mach_port);
+ void OnGPUPluginBuffersSwapped(gfx::PluginWindowHandle window);
#endif
// Paints the given bitmap to the current backing store at the given location.
diff --git a/chrome/browser/renderer_host/render_widget_host_view.h b/chrome/browser/renderer_host/render_widget_host_view.h
index 0a87d3d..ccb1b31 100644
--- a/chrome/browser/renderer_host/render_widget_host_view.h
+++ b/chrome/browser/renderer_host/render_widget_host_view.h
@@ -5,6 +5,10 @@
#ifndef CHROME_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_VIEW_H_
#define CHROME_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_VIEW_H_
+#if defined(OS_MACOSX)
+#include <OpenGL/OpenGL.h>
+#endif
+
#include "app/gfx/native_widget_types.h"
#include "base/shared_memory.h"
#include "third_party/skia/include/core/SkBitmap.h"
@@ -166,6 +170,18 @@ class RenderWidgetHostView {
// message and renderer-side handling) can be removed in favor of using
// WasHidden/DidBecomeSelected.
virtual void SetWindowVisibility(bool visible) = 0;
+
+ // Methods associated with GPU plugin instances
+ virtual gfx::PluginWindowHandle AllocateFakePluginWindowHandle() = 0;
+ virtual void DestroyFakePluginWindowHandle(
+ gfx::PluginWindowHandle window) = 0;
+ virtual void GPUPluginSetIOSurface(gfx::PluginWindowHandle window,
+ int32 width,
+ int32 height,
+ uint64 io_surface_identifier) = 0;
+ virtual void GPUPluginBuffersSwapped(gfx::PluginWindowHandle window) = 0;
+ // Draws the current GPU plugin instances into the given context.
+ virtual void DrawGPUPluginInstances(CGLContextObj context) = 0;
#endif
#if defined(OS_LINUX)
diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.h b/chrome/browser/renderer_host/render_widget_host_view_mac.h
index 4edfa1ef..c9834bf 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_mac.h
+++ b/chrome/browser/renderer_host/render_widget_host_view_mac.h
@@ -6,6 +6,7 @@
#define CHROME_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_VIEW_MAC_H_
#import <Cocoa/Cocoa.h>
+#import <QuartzCore/CALayer.h>
#include "base/scoped_nsobject.h"
#include "base/scoped_ptr.h"
@@ -15,6 +16,7 @@
#include "chrome/browser/renderer_host/render_widget_host_view.h"
#include "webkit/glue/webcursor.h"
#include "webkit/glue/webmenuitem.h"
+#include "webkit/glue/plugins/mac_gpu_plugin_container_manager.h"
class RenderWidgetHostViewMac;
class RWHVMEditCommandHelper;
@@ -112,6 +114,17 @@ class RenderWidgetHostViewMac : public RenderWidgetHostView {
virtual void SetWindowVisibility(bool visible);
virtual void SetBackground(const SkBitmap& background);
+ // Methods associated with GPU plugin instances
+ virtual gfx::PluginWindowHandle AllocateFakePluginWindowHandle();
+ virtual void DestroyFakePluginWindowHandle(gfx::PluginWindowHandle window);
+ virtual void GPUPluginSetIOSurface(gfx::PluginWindowHandle window,
+ int32 width,
+ int32 height,
+ uint64 io_surface_identifier);
+ virtual void GPUPluginBuffersSwapped(gfx::PluginWindowHandle window);
+ // Draws the current GPU plugin instances into the given context.
+ virtual void DrawGPUPluginInstances(CGLContextObj context);
+
void KillSelf();
void set_parent_view(BaseView* parent_view) { parent_view_ = parent_view; }
@@ -181,6 +194,9 @@ class RenderWidgetHostViewMac : public RenderWidgetHostView {
// methods needs it.
NSRect im_caret_rect_;
+ // The Core Animation layer, if any, hosting the GPU plugins' output.
+ scoped_nsobject<CALayer> gpu_plugin_layer_;
+
private:
// Updates the display cursor to the current cursor if the cursor is over this
// render view.
@@ -220,6 +236,9 @@ class RenderWidgetHostViewMac : public RenderWidgetHostView {
// Used for positioning a popup menu.
BaseView* parent_view_;
+ // Helper class for managing instances of the GPU plugin.
+ MacGPUPluginContainerManager plugin_container_manager_;
+
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewMac);
};
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 a20ff65..db78a46 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/chrome/browser/renderer_host/render_widget_host_view_mac.mm
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <QuartzCore/CAOpenGLLayer.h>
+
#include "chrome/browser/renderer_host/render_widget_host_view_mac.h"
#import "base/chrome_application_mac.h"
@@ -20,6 +22,7 @@
#include "chrome/common/edit_command.h"
#include "chrome/common/plugin_messages.h"
#include "chrome/common/render_messages.h"
+#include "chrome/common/io_surface_support_mac.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/WebKit/WebKit/chromium/public/mac/WebInputEventFactory.h"
#include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h"
@@ -53,6 +56,35 @@ const size_t kMaxTooltipLength = 1024;
}
+// GPUPluginLayer --------------------------------------------------------------
+
+// This subclass of CAOpenGLLayer hosts the output of the GPU plugins
+// on the page.
+
+@interface GPUPluginLayer : CAOpenGLLayer {
+ RenderWidgetHostViewMac* renderWidgetHostView_; // weak
+}
+
+- (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r;
+@end
+
+@implementation GPUPluginLayer
+- (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r {
+ self = [super init];
+ if (self != nil) {
+ renderWidgetHostView_ = r;
+ }
+ return self;
+}
+
+-(void)drawInCGLContext:(CGLContextObj)glContext
+ pixelFormat:(CGLPixelFormatObj)pixelFormat
+ forLayerTime:(CFTimeInterval)timeInterval
+ displayTime:(const CVTimeStamp *)timeStamp {
+ renderWidgetHostView_->DrawGPUPluginInstances(glContext);
+}
+@end
+
// RenderWidgetHostView --------------------------------------------------------
// static
@@ -174,6 +206,26 @@ gfx::NativeView RenderWidgetHostViewMac::GetNativeView() {
void RenderWidgetHostViewMac::MovePluginWindows(
const std::vector<webkit_glue::WebPluginGeometry>& moves) {
+ // The only case we need to notice plugin window moves is the case
+ // of the GPU plugin. As soon as the GPU plugin becomes the GPU
+ // process all of this code will go away.
+ if (moves.size() > 0) {
+ for (std::vector<webkit_glue::WebPluginGeometry>::const_iterator iter =
+ moves.begin();
+ iter != moves.end();
+ ++iter) {
+ webkit_glue::WebPluginGeometry geom = *iter;
+ // Ignore bogus moves which claim to move the plugin to (0, 0)
+ // with width and height (0, 0)
+ if (geom.window_rect.x() != 0 ||
+ geom.window_rect.y() != 0 ||
+ geom.window_rect.width() != 0 ||
+ geom.window_rect.height() != 0) {
+ plugin_container_manager_.MovePluginContainer(geom);
+ }
+ }
+ }
+
// All plugin stuff is TBD. TODO(avi,awalker): fill in
// http://crbug.com/8192
}
@@ -440,6 +492,73 @@ void RenderWidgetHostViewMac::KillSelf() {
}
}
+gfx::PluginWindowHandle
+RenderWidgetHostViewMac::AllocateFakePluginWindowHandle() {
+ // We currently only support the GPU plugin on 10.6 and later.
+ if (!IOSurfaceSupport::Initialize())
+ return 0;
+
+ // If we don't already have a GPUPluginLayer allocated for our view,
+ // set one up now.
+ if (gpu_plugin_layer_.get() == nil) {
+ RenderWidgetHostViewCocoa* our_view = native_view();
+ // Try to get AppKit to allocate the layer
+ [our_view setWantsLayer:YES];
+ CALayer* root_layer = [our_view layer];
+ if (root_layer == nil) {
+ root_layer = [CALayer layer];
+ [our_view setLayer:root_layer];
+ }
+
+ GPUPluginLayer* gpu_layer =
+ [[GPUPluginLayer alloc] initWithRenderWidgetHostViewMac:this];
+
+ // Make our layer resize to fit the superlayer
+ gpu_layer.autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable;
+ // Set up its initial size
+ [gpu_layer setFrame:NSRectToCGRect([our_view bounds])];
+
+ [root_layer addSublayer:gpu_layer];
+ gpu_plugin_layer_.reset(gpu_layer);
+ }
+
+ return plugin_container_manager_.AllocateFakePluginWindowHandle();
+}
+
+void RenderWidgetHostViewMac::DestroyFakePluginWindowHandle(
+ gfx::PluginWindowHandle window) {
+ plugin_container_manager_.DestroyFakePluginWindowHandle(window);
+}
+
+void RenderWidgetHostViewMac::GPUPluginSetIOSurface(
+ gfx::PluginWindowHandle window,
+ int32 width,
+ int32 height,
+ uint64 io_surface_identifier) {
+ plugin_container_manager_.SetSizeAndBackingStore(window,
+ width,
+ height,
+ io_surface_identifier);
+}
+
+void RenderWidgetHostViewMac::GPUPluginBuffersSwapped(
+ gfx::PluginWindowHandle window) {
+ [gpu_plugin_layer_.get() setNeedsDisplay];
+}
+
+void RenderWidgetHostViewMac::DrawGPUPluginInstances(CGLContextObj context) {
+ CGLSetCurrentContext(context);
+ gfx::Rect rect = GetWindowRect();
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ // Note that we place the origin at the upper left corner with +y
+ // going down
+ glOrtho(0, rect.width(), rect.height(), 0, -1, 1);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ plugin_container_manager_.Draw(context);
+}
+
void RenderWidgetHostViewMac::ShutdownHost() {
shutdown_factory_.RevokeAll();
render_widget_host_->Shutdown();
@@ -870,6 +989,10 @@ void RenderWidgetHostViewMac::SetBackground(const SkBitmap& background) {
if (renderWidgetHostView_->whiteout_start_time_.is_null())
renderWidgetHostView_->whiteout_start_time_ = base::TimeTicks::Now();
}
+
+ // This helps keep the GPU plugins' output in better sync with the
+ // window as it resizes.
+ [renderWidgetHostView_->gpu_plugin_layer_.get() setNeedsDisplay];
}
- (BOOL)canBecomeKeyView {
diff --git a/chrome/browser/renderer_host/test/test_render_view_host.cc b/chrome/browser/renderer_host/test/test_render_view_host.cc
index 95c5b7b..776ef53 100644
--- a/chrome/browser/renderer_host/test/test_render_view_host.cc
+++ b/chrome/browser/renderer_host/test/test_render_view_host.cc
@@ -91,6 +91,29 @@ gfx::Rect TestRenderWidgetHostView::GetRootWindowRect() {
void TestRenderWidgetHostView::SetActive(bool active) {
// <viettrungluu@gmail.com>: Do I need to do anything here?
}
+
+gfx::PluginWindowHandle
+TestRenderWidgetHostView::AllocateFakePluginWindowHandle() {
+ return NULL;
+}
+
+void TestRenderWidgetHostView::DestroyFakePluginWindowHandle(
+ gfx::PluginWindowHandle window) {
+}
+
+void TestRenderWidgetHostView::GPUPluginSetIOSurface(
+ gfx::PluginWindowHandle window,
+ int32 width,
+ int32 height,
+ uint64 io_surface_identifier) {
+}
+
+void TestRenderWidgetHostView::GPUPluginBuffersSwapped(
+ gfx::PluginWindowHandle window) {
+}
+
+void TestRenderWidgetHostView::DrawGPUPluginInstances(CGLContextObj context) {
+}
#endif
void RenderViewHostTestHarness::NavigateAndCommit(const GURL& url) {
diff --git a/chrome/browser/renderer_host/test/test_render_view_host.h b/chrome/browser/renderer_host/test/test_render_view_host.h
index 7ec1304..fde21b5 100644
--- a/chrome/browser/renderer_host/test/test_render_view_host.h
+++ b/chrome/browser/renderer_host/test/test_render_view_host.h
@@ -78,6 +78,14 @@ class TestRenderWidgetHostView : public RenderWidgetHostView {
virtual gfx::Rect GetRootWindowRect();
virtual void SetActive(bool active);
virtual void SetWindowVisibility(bool visible) {}
+ virtual gfx::PluginWindowHandle AllocateFakePluginWindowHandle();
+ virtual void DestroyFakePluginWindowHandle(gfx::PluginWindowHandle window);
+ virtual void GPUPluginSetIOSurface(gfx::PluginWindowHandle window,
+ int32 width,
+ int32 height,
+ uint64 io_surface_identifier);
+ virtual void GPUPluginBuffersSwapped(gfx::PluginWindowHandle window);
+ virtual void DrawGPUPluginInstances(CGLContextObj context);
#endif
#if defined(OS_LINUX)
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 72c1349..1c6d346 100755
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -526,7 +526,7 @@
'third_party/wtl/include',
],
}],
- ['OS=="win" or (OS=="linux" and target_arch!="arm")', {
+ ['enable_gpu==1', {
'dependencies': [
'../gpu/gpu.gyp:command_buffer_service',
],
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index c181704e..88cf2aa 100755
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -2179,6 +2179,7 @@
'libraries': [
'$(SDKROOT)/System/Library/Frameworks/SecurityInterface.framework',
'$(SDKROOT)/System/Library/Frameworks/QuartzCore.framework',
+ '$(SDKROOT)/System/Library/Frameworks/OpenGL.framework',
],
'mac_bundle_resources': [
'browser/utility.sb',
diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi
index e928f01..c7b405f 100644
--- a/chrome/chrome_common.gypi
+++ b/chrome/chrome_common.gypi
@@ -57,6 +57,8 @@
'common/devtools_messages_internal.h',
'common/gpu_messages.h',
'common/gpu_messages_internal.h',
+ 'common/io_surface_support_mac.cc',
+ 'common/io_surface_support_mac.h',
'common/logging_chrome.cc',
'common/logging_chrome.h',
'common/main_function_params.h',
diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi
index a15c82b..1a41678 100755
--- a/chrome/chrome_renderer.gypi
+++ b/chrome/chrome_renderer.gypi
@@ -185,7 +185,7 @@
}],
],
}],
- ['OS=="win" or (OS=="linux" and target_arch!="arm")', {
+ ['enable_gpu==1', {
'sources': [
'renderer/command_buffer_proxy.cc',
'renderer/command_buffer_proxy.h',
diff --git a/chrome/common/command_buffer_messages_internal.h b/chrome/common/command_buffer_messages_internal.h
index 274223b5..f6fb423 100644
--- a/chrome/common/command_buffer_messages_internal.h
+++ b/chrome/common/command_buffer_messages_internal.h
@@ -41,4 +41,15 @@ IPC_BEGIN_MESSAGES(CommandBuffer)
base::SharedMemoryHandle /* transfer_buffer */,
size_t /* size */)
+#if defined(OS_MACOSX)
+ // On Mac OS X the GPU plugin must be offscreen, because there is no
+ // true cross-process window hierarchy. For this reason we must send
+ // resize events explicitly to the command buffer stub so it can
+ // reallocate its backing store and send the new one back to the
+ // browser. This message is currently used only on 10.6 and later.
+ IPC_MESSAGE_ROUTED2(CommandBufferMsg_SetWindowSize,
+ int32 /* width */,
+ int32 /* height */)
+#endif
+
IPC_END_MESSAGES(CommandBuffer)
diff --git a/chrome/common/gpu_plugin.cc b/chrome/common/gpu_plugin.cc
index fc79cbb..d9d67db 100644
--- a/chrome/common/gpu_plugin.cc
+++ b/chrome/common/gpu_plugin.cc
@@ -27,7 +27,7 @@ void RegisterInternalGPUPlugin() {
L"",
L"",
{
-#if !defined(OS_LINUX)
+#if !defined(OS_POSIX) || defined(OS_MACOSX)
gpu_plugin::NP_GetEntryPoints,
#endif
gpu_plugin::NP_Initialize,
diff --git a/chrome/common/io_surface_support_mac.cc b/chrome/common/io_surface_support_mac.cc
new file mode 100644
index 0000000..80b2539
--- /dev/null
+++ b/chrome/common/io_surface_support_mac.cc
@@ -0,0 +1,242 @@
+// 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 <dlfcn.h>
+
+#include "base/singleton.h"
+#include "chrome/common/io_surface_support_mac.h"
+
+typedef CFTypeRef (*IOSurfaceCreateProcPtr)(CFDictionaryRef properties);
+typedef uint32 (*IOSurfaceGetIDProcPtr)(CFTypeRef io_surface);
+typedef CFTypeRef (*IOSurfaceLookupProcPtr)(uint32 io_surface_id);
+typedef mach_port_t (*IOSurfaceCreateMachPortProcPtr)(CFTypeRef io_surface);
+typedef CFTypeRef (*IOSurfaceLookupFromMachPortProcPtr)(mach_port_t port);
+typedef CGLError (*CGLTexImageIOSurface2DProcPtr)(CGLContextObj ctx,
+ GLenum target,
+ GLenum internal_format,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ CFTypeRef io_surface,
+ GLuint plane);
+
+class IOSurfaceSupportImpl : public IOSurfaceSupport {
+ public:
+ static IOSurfaceSupportImpl* Initialize();
+
+ bool InitializedSuccessfully() {
+ return initialized_successfully_;
+ }
+
+ virtual CFStringRef GetKIOSurfaceWidth();
+ virtual CFStringRef GetKIOSurfaceHeight();
+ virtual CFStringRef GetKIOSurfaceBytesPerElement();
+ virtual CFStringRef GetKIOSurfaceIsGlobal();
+
+ virtual CFTypeRef IOSurfaceCreate(CFDictionaryRef properties);
+ virtual uint32 IOSurfaceGetID(CFTypeRef io_surface);
+ virtual CFTypeRef IOSurfaceLookup(uint32 io_surface_id);
+ virtual mach_port_t IOSurfaceCreateMachPort(CFTypeRef io_surface);
+ virtual CFTypeRef IOSurfaceLookupFromMachPort(mach_port_t port);
+
+ virtual CGLError CGLTexImageIOSurface2D(CGLContextObj ctx,
+ GLenum target,
+ GLenum internal_format,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ CFTypeRef io_surface,
+ GLuint plane);
+
+ private:
+ IOSurfaceSupportImpl();
+ ~IOSurfaceSupportImpl();
+
+ void* iosurface_handle_;
+ void* opengl_handle_;
+ CFStringRef k_io_surface_width_;
+ CFStringRef k_io_surface_height_;
+ CFStringRef k_io_surface_bytes_per_element_;
+ CFStringRef k_io_surface_is_global_;
+ IOSurfaceCreateProcPtr io_surface_create_;
+ IOSurfaceGetIDProcPtr io_surface_get_id_;
+ IOSurfaceLookupProcPtr io_surface_lookup_;
+ IOSurfaceCreateMachPortProcPtr io_surface_create_mach_port_;
+ IOSurfaceLookupFromMachPortProcPtr io_surface_lookup_from_mach_port_;
+ CGLTexImageIOSurface2DProcPtr cgl_tex_image_io_surface_2d_;
+ bool initialized_successfully_;
+
+ friend struct DefaultSingletonTraits<IOSurfaceSupportImpl>;
+ DISALLOW_EVIL_CONSTRUCTORS(IOSurfaceSupportImpl);
+};
+
+static Singleton<IOSurfaceSupportImpl> sole_instance_;
+
+IOSurfaceSupportImpl* IOSurfaceSupportImpl::Initialize() {
+ IOSurfaceSupportImpl* impl = sole_instance_.get();
+ if (impl->InitializedSuccessfully())
+ return impl;
+ return NULL;
+}
+
+CFStringRef IOSurfaceSupportImpl::GetKIOSurfaceWidth() {
+ return k_io_surface_width_;
+}
+
+CFStringRef IOSurfaceSupportImpl::GetKIOSurfaceHeight() {
+ return k_io_surface_height_;
+}
+
+CFStringRef IOSurfaceSupportImpl::GetKIOSurfaceBytesPerElement() {
+ return k_io_surface_bytes_per_element_;
+}
+
+CFStringRef IOSurfaceSupportImpl::GetKIOSurfaceIsGlobal() {
+ return k_io_surface_is_global_;
+}
+
+CFTypeRef IOSurfaceSupportImpl::IOSurfaceCreate(CFDictionaryRef properties) {
+ return io_surface_create_(properties);
+}
+
+uint32 IOSurfaceSupportImpl::IOSurfaceGetID(
+ CFTypeRef io_surface) {
+ return io_surface_get_id_(io_surface);
+}
+
+CFTypeRef IOSurfaceSupportImpl::IOSurfaceLookup(uint32 io_surface_id) {
+ return io_surface_lookup_(io_surface_id);
+}
+
+mach_port_t IOSurfaceSupportImpl::IOSurfaceCreateMachPort(
+ CFTypeRef io_surface) {
+ return io_surface_create_mach_port_(io_surface);
+}
+
+CFTypeRef IOSurfaceSupportImpl::IOSurfaceLookupFromMachPort(mach_port_t port) {
+ return io_surface_lookup_from_mach_port_(port);
+}
+
+CGLError IOSurfaceSupportImpl::CGLTexImageIOSurface2D(CGLContextObj ctx,
+ GLenum target,
+ GLenum internal_format,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ CFTypeRef io_surface,
+ GLuint plane) {
+ return cgl_tex_image_io_surface_2d_(ctx,
+ target,
+ internal_format,
+ width,
+ height,
+ format,
+ type,
+ io_surface,
+ plane);
+}
+
+IOSurfaceSupportImpl::IOSurfaceSupportImpl()
+ : iosurface_handle_(NULL),
+ opengl_handle_(NULL),
+ k_io_surface_width_(NULL),
+ k_io_surface_height_(NULL),
+ k_io_surface_bytes_per_element_(NULL),
+ k_io_surface_is_global_(NULL),
+ io_surface_create_(NULL),
+ io_surface_get_id_(NULL),
+ io_surface_lookup_(NULL),
+ io_surface_create_mach_port_(NULL),
+ io_surface_lookup_from_mach_port_(NULL),
+ cgl_tex_image_io_surface_2d_(NULL),
+ initialized_successfully_(false) {
+ iosurface_handle_ = dlopen(
+ "/System/Library/Frameworks/IOSurface.framework/IOSurface",
+ RTLD_LAZY | RTLD_LOCAL);
+ if (!iosurface_handle_)
+ return;
+ opengl_handle_ = dlopen(
+ "/System/Library/Frameworks/OpenGL.framework/OpenGL",
+ RTLD_LAZY | RTLD_LOCAL);
+ if (!opengl_handle_) {
+ dlclose(iosurface_handle_);
+ iosurface_handle_ = NULL;
+ return;
+ }
+
+ void* surface_width_ptr = dlsym(iosurface_handle_, "kIOSurfaceWidth");
+ void* surface_height_ptr = dlsym(iosurface_handle_, "kIOSurfaceHeight");
+ void* surface_bytes_per_element_ptr =
+ dlsym(iosurface_handle_, "kIOSurfaceBytesPerElement");
+ void* surface_is_global_ptr =
+ dlsym(iosurface_handle_, "kIOSurfaceIsGlobal");
+ void* surface_create_ptr = dlsym(iosurface_handle_, "IOSurfaceCreate");
+ void* surface_get_id_ptr = dlsym(iosurface_handle_, "IOSurfaceGetID");
+ void* surface_lookup_ptr = dlsym(iosurface_handle_, "IOSurfaceLookup");
+ void* surface_create_mach_port_ptr =
+ dlsym(iosurface_handle_, "IOSurfaceCreateMachPort");
+ void* surface_lookup_from_mach_port_ptr =
+ dlsym(iosurface_handle_, "IOSurfaceLookupFromMachPort");
+ void* tex_image_io_surface_2d_ptr =
+ dlsym(opengl_handle_, "CGLTexImageIOSurface2D");
+ if (!surface_width_ptr ||
+ !surface_height_ptr ||
+ !surface_bytes_per_element_ptr ||
+ !surface_is_global_ptr ||
+ !surface_create_ptr ||
+ !surface_get_id_ptr ||
+ !surface_lookup_ptr ||
+ !surface_create_mach_port_ptr ||
+ !surface_lookup_from_mach_port_ptr ||
+ !tex_image_io_surface_2d_ptr) {
+ dlclose(iosurface_handle_);
+ iosurface_handle_ = NULL;
+ dlclose(opengl_handle_);
+ opengl_handle_ = NULL;
+ return;
+ }
+
+ k_io_surface_width_ = *static_cast<CFStringRef*>(surface_width_ptr);
+ k_io_surface_height_ = *static_cast<CFStringRef*>(surface_height_ptr);
+ k_io_surface_bytes_per_element_ =
+ *static_cast<CFStringRef*>(surface_bytes_per_element_ptr);
+ k_io_surface_is_global_ = *static_cast<CFStringRef*>(surface_is_global_ptr);
+ io_surface_create_ = reinterpret_cast<IOSurfaceCreateProcPtr>(
+ surface_create_ptr);
+ io_surface_get_id_ =
+ reinterpret_cast<IOSurfaceGetIDProcPtr>(surface_get_id_ptr);
+ io_surface_lookup_ =
+ reinterpret_cast<IOSurfaceLookupProcPtr>(surface_lookup_ptr);
+ io_surface_create_mach_port_ =
+ reinterpret_cast<IOSurfaceCreateMachPortProcPtr>(
+ surface_create_mach_port_ptr);
+ io_surface_lookup_from_mach_port_ =
+ reinterpret_cast<IOSurfaceLookupFromMachPortProcPtr>(
+ surface_lookup_from_mach_port_ptr);
+ cgl_tex_image_io_surface_2d_ =
+ reinterpret_cast<CGLTexImageIOSurface2DProcPtr>(
+ tex_image_io_surface_2d_ptr);
+ initialized_successfully_ = true;
+}
+
+IOSurfaceSupportImpl::~IOSurfaceSupportImpl() {
+ if (iosurface_handle_)
+ dlclose(iosurface_handle_);
+ if (opengl_handle_)
+ dlclose(opengl_handle_);
+}
+
+IOSurfaceSupport* IOSurfaceSupport::Initialize() {
+ return IOSurfaceSupportImpl::Initialize();
+}
+
+IOSurfaceSupport::IOSurfaceSupport() {
+}
+
+IOSurfaceSupport::~IOSurfaceSupport() {
+}
+
diff --git a/chrome/common/io_surface_support_mac.h b/chrome/common/io_surface_support_mac.h
new file mode 100644
index 0000000..6ad116f
--- /dev/null
+++ b/chrome/common/io_surface_support_mac.h
@@ -0,0 +1,66 @@
+// 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_IO_SURFACE_SUPPORT_MAC_H_
+#define CHROME_COMMON_IO_SURFACE_SUPPORT_MAC_H_
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <mach/mach.h>
+#include <OpenGL/OpenGL.h>
+
+#include "base/basictypes.h"
+
+// This Mac OS X-specific class provides dynamically-linked access to
+// IOSurface.framework, which is only available on 10.6 and later.
+// Since Chromium is built on 10.5 we must dynamically look up all of
+// the entry points we need in this framework.
+
+// See IOSurface/IOSurfaceAPI.h and OpenGL/CGLIOSurface.h on 10.6 for
+// documentation of the fields and methods of this class.
+
+class IOSurfaceSupport {
+ public:
+ // Returns an instance of the IOSurfaceSupport class if the
+ // operating system supports it, NULL otherwise. It is safe to call
+ // this multiple times.
+ static IOSurfaceSupport* Initialize();
+
+ virtual CFStringRef GetKIOSurfaceWidth() = 0;
+ virtual CFStringRef GetKIOSurfaceHeight() = 0;
+ virtual CFStringRef GetKIOSurfaceBytesPerElement() = 0;
+ virtual CFStringRef GetKIOSurfaceIsGlobal() = 0;
+
+ virtual CFTypeRef IOSurfaceCreate(CFDictionaryRef properties) = 0;
+
+ // The following two APIs assume the IOSurface was created with the
+ // kIOSurfaceIsGlobal key set to true
+ virtual uint32 IOSurfaceGetID(CFTypeRef io_surface) = 0;
+ virtual CFTypeRef IOSurfaceLookup(uint32 io_surface_id) = 0;
+
+ // The following two APIs are more robust and secure, but
+ // unfortunately it looks like it will be a lot of work to correctly
+ // transmit a mach port from process to process (possibly requiring
+ // a side channel for or extension of the Chrome IPC mechanism)
+ virtual mach_port_t IOSurfaceCreateMachPort(CFTypeRef io_surface) = 0;
+ virtual CFTypeRef IOSurfaceLookupFromMachPort(mach_port_t port) = 0;
+
+ virtual CGLError CGLTexImageIOSurface2D(CGLContextObj ctx,
+ GLenum target,
+ GLenum internal_format,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ CFTypeRef io_surface,
+ GLuint plane) = 0;
+
+ protected:
+ IOSurfaceSupport();
+ virtual ~IOSurfaceSupport();
+
+ DISALLOW_COPY_AND_ASSIGN(IOSurfaceSupport);
+};
+
+#endif // CHROME_COMMON_IO_SURFACE_SUPPORT_MAC_H_
+
diff --git a/chrome/common/plugin_messages_internal.h b/chrome/common/plugin_messages_internal.h
index aecccac..05e532b 100644
--- a/chrome/common/plugin_messages_internal.h
+++ b/chrome/common/plugin_messages_internal.h
@@ -291,6 +291,15 @@ IPC_BEGIN_MESSAGES(Plugin)
IPC_MESSAGE_CONTROL1(PluginMsg_ResetModalDialogEvent,
gfx::NativeViewId /* containing_window */)
+
+#if defined(OS_MACOSX)
+ // This message, used only on 10.6 and later, transmits the "fake"
+ // window handle allocated by the browser on behalf of the renderer
+ // to the GPU plugin.
+ IPC_MESSAGE_ROUTED1(PluginMsg_SetFakeGPUPluginWindowHandle,
+ gfx::PluginWindowHandle /* window */)
+#endif
+
IPC_END_MESSAGES(Plugin)
@@ -385,6 +394,29 @@ IPC_BEGIN_MESSAGES(PluginHost)
#if defined(OS_MACOSX)
IPC_MESSAGE_ROUTED1(PluginHostMsg_UpdateGeometry_ACK,
int /* ack_key */)
+
+ // 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
+ // height. This information is then forwarded on to the browser
+ // process.
+ //
+ // NOTE: the original intent was to pass a mach port as the
+ // IOSurface identifier but it looks like that will be a lot of
+ // work. For now we pass an ID from IOSurfaceGetID.
+ IPC_MESSAGE_ROUTED4(PluginHostMsg_GPUPluginSetIOSurface,
+ gfx::PluginWindowHandle /* window */,
+ int32 /* width */,
+ int32 /* height */,
+ uint64 /* identifier for IOSurface */)
+
+ // This message, currently used only on 10.6 and later, notifies the
+ // renderer process (and from there the browser process) that the
+ // GPU plugin swapped the buffers associated with the given
+ // "window", which should cause the browser to redraw the various
+ // GPU plugins' contents.
+ IPC_MESSAGE_ROUTED1(PluginHostMsg_GPUPluginBuffersSwapped,
+ gfx::PluginWindowHandle /* window */)
#endif
IPC_END_MESSAGES(PluginHost)
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index 1dcef7e..7b25b7a 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -1781,6 +1781,41 @@ IPC_BEGIN_MESSAGES(ViewHost)
// renderer is finished with them.
IPC_MESSAGE_CONTROL1(ViewHostMsg_FreeTransportDIB,
TransportDIB::Id /* DIB id */)
+
+ //---------------------------------------------------------------------------
+ // Messages related to the GPU plugin on Mac OS X 10.6 and later
+
+ // This is sent from the renderer to the browser to allocate a fake
+ // PluginWindowHandle on the browser side which is used to identify
+ // the plugin to the browser later when backing store is allocated
+ // or reallocated.
+ IPC_SYNC_MESSAGE_ROUTED0_1(ViewHostMsg_AllocateFakePluginWindowHandle,
+ gfx::PluginWindowHandle /* id */)
+
+ // Destroys a fake window handle previously allocated using
+ // AllocateFakePluginWindowHandle.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_DestroyFakePluginWindowHandle,
+ gfx::PluginWindowHandle /* id */)
+
+ // This message is sent from the renderer to the browser on behalf
+ // of the GPU plugin to indicate that a new backing store was
+ // allocated for that GPU plugin instance.
+ //
+ // NOTE: the original intent was to pass a mach port as the
+ // IOSurface identifier but it looks like that will be a lot of
+ // work. For now we pass an ID from IOSurfaceGetID.
+ IPC_MESSAGE_ROUTED4(ViewHostMsg_GPUPluginSetIOSurface,
+ gfx::PluginWindowHandle /* window */,
+ int32 /* width */,
+ int32 /* height */,
+ uint64 /* identifier for IOSurface */)
+
+ // This message notifies the browser process that the GPU plugin
+ // swapped the buffers associated with the given "window", which
+ // should cause the browser to redraw the various GPU plugins'
+ // contents.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_GPUPluginBuffersSwapped,
+ gfx::PluginWindowHandle /* window */)
#endif
// A renderer sends this to the browser process when it wants to create a
diff --git a/chrome/plugin/command_buffer_stub.cc b/chrome/plugin/command_buffer_stub.cc
index 4b062e8..b019b1f 100644
--- a/chrome/plugin/command_buffer_stub.cc
+++ b/chrome/plugin/command_buffer_stub.cc
@@ -5,14 +5,17 @@
#include "base/process_util.h"
#include "base/shared_memory.h"
#include "chrome/common/command_buffer_messages.h"
+#include "chrome/common/plugin_messages.h"
#include "chrome/plugin/command_buffer_stub.h"
#include "chrome/plugin/plugin_channel.h"
using gpu::Buffer;
CommandBufferStub::CommandBufferStub(PluginChannel* channel,
+ int plugin_host_route_id,
gfx::PluginWindowHandle window)
: channel_(channel),
+ plugin_host_route_id_(plugin_host_route_id),
window_(window) {
route_id_ = channel->GenerateRouteID();
channel->AddRoute(route_id_, this, false);
@@ -58,6 +61,11 @@ void CommandBufferStub::OnInitialize(int32 size,
command_buffer_->SetPutOffsetChangeCallback(
NewCallback(processor_.get(),
&gpu::GPUProcessor::ProcessCommands));
+#if defined(OS_MACOSX)
+ processor_->SetSwapBuffersCallback(
+ NewCallback(this,
+ &CommandBufferStub::SwapBuffersCallback));
+#endif
buffer.shared_memory->ShareToProcess(peer_handle, ring_buffer);
} else {
processor_ = NULL;
@@ -108,6 +116,24 @@ void CommandBufferStub::OnGetTransferBuffer(
base::CloseProcessHandle(peer_handle);
}
+#if defined(OS_MACOSX)
+void CommandBufferStub::OnSetWindowSize(int32 width, int32 height) {
+ uint64 new_backing_store = processor_->SetWindowSize(width, height);
+ if (new_backing_store) {
+ Send(new PluginHostMsg_GPUPluginSetIOSurface(plugin_host_route_id_,
+ window_,
+ width,
+ height,
+ new_backing_store));
+ }
+}
+
+void CommandBufferStub::SwapBuffersCallback() {
+ Send(new PluginHostMsg_GPUPluginBuffersSwapped(plugin_host_route_id_,
+ window_));
+}
+#endif
+
void CommandBufferStub::OnMessageReceived(const IPC::Message& msg) {
IPC_BEGIN_MESSAGE_MAP(CommandBufferStub, msg)
IPC_MESSAGE_HANDLER(CommandBufferMsg_Initialize, OnInitialize);
@@ -119,6 +145,9 @@ void CommandBufferStub::OnMessageReceived(const IPC::Message& msg) {
OnDestroyTransferBuffer);
IPC_MESSAGE_HANDLER(CommandBufferMsg_GetTransferBuffer,
OnGetTransferBuffer);
+#if defined(OS_MACOSX)
+ IPC_MESSAGE_HANDLER(CommandBufferMsg_SetWindowSize, OnSetWindowSize);
+#endif
IPC_MESSAGE_UNHANDLED_ERROR()
IPC_END_MESSAGE_MAP()
}
diff --git a/chrome/plugin/command_buffer_stub.h b/chrome/plugin/command_buffer_stub.h
index 1001ce9..7759392 100644
--- a/chrome/plugin/command_buffer_stub.h
+++ b/chrome/plugin/command_buffer_stub.h
@@ -22,7 +22,9 @@ class CommandBufferService;
class CommandBufferStub : public IPC::Channel::Listener,
public IPC::Message::Sender {
public:
- CommandBufferStub(PluginChannel* channel, gfx::PluginWindowHandle window);
+ CommandBufferStub(PluginChannel* channel,
+ int plugin_host_route_id,
+ gfx::PluginWindowHandle window);
virtual ~CommandBufferStub();
@@ -45,8 +47,13 @@ class CommandBufferStub : public IPC::Channel::Listener,
void OnGetTransferBuffer(int32 id,
base::SharedMemoryHandle* transfer_buffer,
size_t* size);
+#if defined(OS_MACOSX)
+ void OnSetWindowSize(int32 width, int32 height);
+ void SwapBuffersCallback();
+#endif
scoped_refptr<PluginChannel> channel_;
+ int plugin_host_route_id_;
gfx::PluginWindowHandle window_;
int route_id_;
scoped_ptr<gpu::CommandBufferService> command_buffer_;
diff --git a/chrome/plugin/webplugin_delegate_stub.cc b/chrome/plugin/webplugin_delegate_stub.cc
index cf6e842..80d6e62 100644
--- a/chrome/plugin/webplugin_delegate_stub.cc
+++ b/chrome/plugin/webplugin_delegate_stub.cc
@@ -139,6 +139,10 @@ void WebPluginDelegateStub::OnMessageReceived(const IPC::Message& msg) {
OnHTTPRangeRequestReply)
IPC_MESSAGE_HANDLER(PluginMsg_CreateCommandBuffer,
OnCreateCommandBuffer)
+#if defined(OS_MACOSX)
+ IPC_MESSAGE_HANDLER(PluginMsg_SetFakeGPUPluginWindowHandle,
+ OnSetFakeGPUPluginWindowHandle)
+#endif
IPC_MESSAGE_UNHANDLED_ERROR()
IPC_END_MESSAGE_MAP()
@@ -375,7 +379,8 @@ void WebPluginDelegateStub::OnInstallMissingPlugin() {
void WebPluginDelegateStub::OnCreateCommandBuffer(int* route_id) {
#if defined(ENABLE_GPU)
command_buffer_stub_.reset(new CommandBufferStub(
- static_cast<PluginChannel*>(PluginChannelBase::GetCurrentChannel()),
+ channel_,
+ instance_id_,
delegate_->windowed_handle()));
*route_id = command_buffer_stub_->route_id();
@@ -428,3 +433,11 @@ void WebPluginDelegateStub::OnHTTPRangeRequestReply(
delegate_->CreateSeekableResourceClient(resource_id, range_request_id);
webplugin_->OnResourceCreated(resource_id, resource_client);
}
+
+#if defined(OS_MACOSX)
+void WebPluginDelegateStub::OnSetFakeGPUPluginWindowHandle(
+ gfx::PluginWindowHandle window) {
+ delegate_->set_windowed_handle(window);
+}
+#endif
+
diff --git a/chrome/plugin/webplugin_delegate_stub.h b/chrome/plugin/webplugin_delegate_stub.h
index b783832..5a04758 100644
--- a/chrome/plugin/webplugin_delegate_stub.h
+++ b/chrome/plugin/webplugin_delegate_stub.h
@@ -115,6 +115,14 @@ class WebPluginDelegateStub : public IPC::Channel::Listener,
// If this is the GPU plugin, the stub object that forwards to the
// command buffer service.
scoped_ptr<CommandBufferStub> command_buffer_stub_;
+
+#if defined(OS_MACOSX)
+ // If this is the GPU plugin, we need to be receive a fake window
+ // handle which is used for subsequent communication back to the
+ // browser.
+ void OnSetFakeGPUPluginWindowHandle(gfx::PluginWindowHandle window);
+#endif
+
#endif
DISALLOW_IMPLICIT_CONSTRUCTORS(WebPluginDelegateStub);
diff --git a/chrome/renderer/command_buffer_proxy.cc b/chrome/renderer/command_buffer_proxy.cc
index 2b08090..9c337c9 100644
--- a/chrome/renderer/command_buffer_proxy.cc
+++ b/chrome/renderer/command_buffer_proxy.cc
@@ -169,3 +169,10 @@ void CommandBufferProxy::SetParseError(
// Not implemented in proxy.
NOTREACHED();
}
+
+#if defined(OS_MACOSX)
+void CommandBufferProxy::SetWindowSize(int32 width, int32 height) {
+ Send(new CommandBufferMsg_SetWindowSize(route_id_, width, height));
+}
+#endif
+
diff --git a/chrome/renderer/command_buffer_proxy.h b/chrome/renderer/command_buffer_proxy.h
index 077b0c5..b7bed4e 100644
--- a/chrome/renderer/command_buffer_proxy.h
+++ b/chrome/renderer/command_buffer_proxy.h
@@ -44,6 +44,10 @@ class CommandBufferProxy : public gpu::CommandBuffer,
virtual void SetToken(int32 token);
virtual void SetParseError(gpu::error::Error error);
+#if defined(OS_MACOSX)
+ virtual void SetWindowSize(int32 width, int32 height);
+#endif
+
private:
// As with the service, the client takes ownership of the ring buffer.
int32 size_;
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index 0594162..96b38c9 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -4234,3 +4234,30 @@ bool RenderView::SendAndRunNestedMessageLoop(IPC::SyncMessage* message) {
return rv;
}
+
+#if defined(OS_MACOSX)
+gfx::PluginWindowHandle RenderView::AllocateFakePluginWindowHandle() {
+ gfx::PluginWindowHandle window = NULL;
+ Send(new ViewHostMsg_AllocateFakePluginWindowHandle(
+ routing_id(), &window));
+ return window;
+}
+
+void RenderView::DestroyFakePluginWindowHandle(gfx::PluginWindowHandle window) {
+ if (window)
+ Send(new ViewHostMsg_DestroyFakePluginWindowHandle(routing_id(), window));
+}
+
+void RenderView::GPUPluginSetIOSurface(gfx::PluginWindowHandle window,
+ int32 width,
+ int32 height,
+ uint64 io_surface_identifier) {
+ Send(new ViewHostMsg_GPUPluginSetIOSurface(
+ routing_id(), window, width, height, io_surface_identifier));
+}
+
+void RenderView::GPUPluginBuffersSwapped(gfx::PluginWindowHandle window) {
+ Send(new ViewHostMsg_GPUPluginBuffersSwapped(routing_id(), window));
+}
+#endif
+
diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h
index 7545654..1bb7c97 100644
--- a/chrome/renderer/render_view.h
+++ b/chrome/renderer/render_view.h
@@ -469,6 +469,18 @@ class RenderView : public RenderWidget,
// 'zh-TW' for Traditional Chinse.
std::string DetectLanguage();
+#if defined(OS_MACOSX)
+ // Helper routines for GPU plugin support. Used by the
+ // WebPluginDelegateProxy, which has a pointer to the RenderView.
+ gfx::PluginWindowHandle AllocateFakePluginWindowHandle();
+ void DestroyFakePluginWindowHandle(gfx::PluginWindowHandle window);
+ void GPUPluginSetIOSurface(gfx::PluginWindowHandle window,
+ int32 width,
+ int32 height,
+ uint64 io_surface_identifier);
+ void GPUPluginBuffersSwapped(gfx::PluginWindowHandle window);
+#endif
+
protected:
// RenderWidget overrides:
virtual void Close();
diff --git a/chrome/renderer/webplugin_delegate_pepper.cc b/chrome/renderer/webplugin_delegate_pepper.cc
index 4a17fc8..4c02715 100644
--- a/chrome/renderer/webplugin_delegate_pepper.cc
+++ b/chrome/renderer/webplugin_delegate_pepper.cc
@@ -152,6 +152,18 @@ void WebPluginDelegatePepper::UpdateGeometry(
if (nested_delegate_)
nested_delegate_->UpdateGeometry(window_rect, clip_rect);
+#if defined(ENABLE_GPU)
+#if defined(OS_MACOSX)
+ // Send the new window size to the command buffer service code so it
+ // can allocate a new backing store. The handle to the new backing
+ // store is sent back to the browser asynchronously.
+ if (command_buffer_.get()) {
+ command_buffer_->SetWindowSize(window_rect_.width(),
+ window_rect_.height());
+ }
+#endif // OS_MACOSX
+#endif // ENABLE_GPU
+
if (!instance())
return;
@@ -350,6 +362,10 @@ NPError WebPluginDelegatePepper::Device3DInitializeContext(
// Ensure the service knows the window size before rendering anything.
nested_delegate_->UpdateGeometry(window_rect_, clip_rect_);
+#if defined(OS_MACOSX)
+ command_buffer_->SetWindowSize(window_rect_.width(),
+ window_rect_.height());
+#endif // OS_MACOSX
// Save the implementation information (the CommandBuffer).
Device3DImpl* impl = new Device3DImpl;
impl->command_buffer = command_buffer_.get();
diff --git a/chrome/renderer/webplugin_delegate_proxy.cc b/chrome/renderer/webplugin_delegate_proxy.cc
index b71798e..7059890 100644
--- a/chrome/renderer/webplugin_delegate_proxy.cc
+++ b/chrome/renderer/webplugin_delegate_proxy.cc
@@ -386,6 +386,11 @@ void WebPluginDelegateProxy::OnMessageReceived(const IPC::Message& msg) {
#if defined(OS_MACOSX)
IPC_MESSAGE_HANDLER(PluginHostMsg_UpdateGeometry_ACK,
OnUpdateGeometry_ACK)
+ // Used only on 10.6 and later
+ IPC_MESSAGE_HANDLER(PluginHostMsg_GPUPluginSetIOSurface,
+ OnGPUPluginSetIOSurface)
+ IPC_MESSAGE_HANDLER(PluginHostMsg_GPUPluginBuffersSwapped,
+ OnGPUPluginBuffersSwapped)
#endif
IPC_MESSAGE_UNHANDLED_ERROR()
@@ -891,6 +896,14 @@ void WebPluginDelegateProxy::OnSetWindow(gfx::PluginWindowHandle window) {
void WebPluginDelegateProxy::WillDestroyWindow() {
DCHECK(window_);
plugin_->WillDestroyWindow(window_);
+#if defined(OS_MACOSX)
+ if (window_) {
+ // This is actually a "fake" window handle only for the GPU
+ // plugin. Deallocate it on the browser side.
+ if (render_view_)
+ render_view_->DestroyFakePluginWindowHandle(window_);
+ }
+#endif
window_ = gfx::kNullPluginWindow;
}
@@ -1199,6 +1212,23 @@ WebPluginDelegateProxy::CreateSeekableResourceClient(
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.
+ 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;
+ OnSetWindow(fake_window);
+ if (!Send(new PluginMsg_SetFakeGPUPluginWindowHandle(instance_id_,
+ fake_window))) {
+ return NULL;
+ }
+#endif
+
int command_buffer_id;
if (!Send(new PluginMsg_CreateCommandBuffer(instance_id_,
&command_buffer_id))) {
@@ -1247,4 +1277,20 @@ void WebPluginDelegateProxy::OnUpdateGeometry_ACK(int ack_key) {
old_transport_dibs_.erase(iterator);
}
+
+void WebPluginDelegateProxy::OnGPUPluginSetIOSurface(
+ gfx::PluginWindowHandle window,
+ int32 width,
+ int32 height,
+ uint64 io_surface_identifier) {
+ if (render_view_)
+ render_view_->GPUPluginSetIOSurface(window, width, height,
+ io_surface_identifier);
+}
+
+void WebPluginDelegateProxy::OnGPUPluginBuffersSwapped(
+ gfx::PluginWindowHandle window) {
+ if (render_view_)
+ render_view_->GPUPluginBuffersSwapped(window);
+}
#endif
diff --git a/chrome/renderer/webplugin_delegate_proxy.h b/chrome/renderer/webplugin_delegate_proxy.h
index 6a71bdb..a56da38 100644
--- a/chrome/renderer/webplugin_delegate_proxy.h
+++ b/chrome/renderer/webplugin_delegate_proxy.h
@@ -145,6 +145,11 @@ class WebPluginDelegateProxy
#if defined(OS_MACOSX)
void OnUpdateGeometry_ACK(int ack_key);
+ void OnGPUPluginSetIOSurface(gfx::PluginWindowHandle window,
+ int32 width,
+ int32 height,
+ uint64 io_surface_identifier);
+ void OnGPUPluginBuffersSwapped(gfx::PluginWindowHandle window);
#endif
// Draw a graphic indicating a crashed plugin.
diff --git a/gpu/DEPS b/gpu/DEPS
index 2cdc222..5d1e2af 100644
--- a/gpu/DEPS
+++ b/gpu/DEPS
@@ -4,4 +4,8 @@ include_rules = [
# For gfx::PluginWindowHandle
"+app/gfx",
+
+ # For IOSurfaceSupport on Mac OS X, service-side code only.
+ # Can consider moving these files if this dependency is undesirable.
+ "+chrome/common",
]
diff --git a/gpu/command_buffer/client/gles2_demo_cc.cc b/gpu/command_buffer/client/gles2_demo_cc.cc
index 0478e32..2544f42 100644
--- a/gpu/command_buffer/client/gles2_demo_cc.cc
+++ b/gpu/command_buffer/client/gles2_demo_cc.cc
@@ -5,6 +5,7 @@
// This file is here so other GLES2 related files can have a common set of
// includes where appropriate.
+#include <math.h>
#include <GLES2/gl2.h>
#include "gpu/command_buffer/client/gles2_demo_cc.h"
@@ -13,8 +14,10 @@ namespace {
GLuint g_texture = 0;
int g_textureLoc = -1;
GLuint g_programObject = 0;
+GLuint g_worldMatrixLoc = 0;
GLuint g_vbo = 0;
GLsizei g_texCoordOffset = 0;
+int g_angle = 0;
void CheckGLError() {
GLenum error = glGetError();
@@ -49,12 +52,14 @@ GLuint LoadShader(GLenum type, const char* shaderSrc) {
void InitShaders() {
static const char* vShaderStr =
+ "uniform mat4 worldMatrix;\n"
"attribute vec3 g_Position;\n"
"attribute vec2 g_TexCoord0;\n"
"varying vec2 texCoord;\n"
"void main()\n"
"{\n"
- " gl_Position = vec4(g_Position.x, g_Position.y, g_Position.z, 1.0);\n"
+ " gl_Position = worldMatrix *\n"
+ " vec4(g_Position.x, g_Position.y, g_Position.z, 1.0);\n"
" texCoord = g_TexCoord0;\n"
"}\n";
static const char* fShaderStr =
@@ -94,6 +99,7 @@ void InitShaders() {
return;
}
g_programObject = programObject;
+ g_worldMatrixLoc = glGetUniformLocation(g_programObject, "worldMatrix");
g_textureLoc = glGetUniformLocation(g_programObject, "tex");
glGenBuffers(1, &g_vbo);
glBindBuffer(GL_ARRAY_BUFFER, g_vbo);
@@ -124,7 +130,36 @@ void InitShaders() {
CheckGLError();
}
+#define PI 3.1415926535897932384626433832795f
+
void Draw() {
+ // TODO(kbr): base the angle on time rather than on ticks
+ g_angle = (g_angle + 1) % 360;
+ // Rotate about the Z axis
+ GLfloat rot_matrix[16];
+ GLfloat cos_angle = cosf(static_cast<GLfloat>(g_angle) * PI / 180.0f);
+ GLfloat sin_angle = sinf(static_cast<GLfloat>(g_angle) * PI / 180.0f);
+ // OpenGL matrices are column-major
+ rot_matrix[0] = cos_angle;
+ rot_matrix[1] = sin_angle;
+ rot_matrix[2] = 0.0f;
+ rot_matrix[3] = 0.0f;
+
+ rot_matrix[4] = -sin_angle;
+ rot_matrix[5] = cos_angle;
+ rot_matrix[6] = 0.0f;
+ rot_matrix[7] = 0.0f;
+
+ rot_matrix[8] = 0.0f;
+ rot_matrix[9] = 0.0f;
+ rot_matrix[10] = 1.0f;
+ rot_matrix[11] = 0.0f;
+
+ rot_matrix[12] = 0.0f;
+ rot_matrix[13] = 0.0f;
+ rot_matrix[14] = 0.0f;
+ rot_matrix[15] = 1.0f;
+
// Note: the viewport is automatically set up to cover the entire Canvas.
// Clear the color buffer
glClear(GL_COLOR_BUFFER_BIT);
@@ -132,6 +167,9 @@ void Draw() {
// Use the program object
glUseProgram(g_programObject);
CheckGLError();
+ // Set up the model matrix
+ glUniformMatrix4fv(g_worldMatrixLoc, 1, GL_FALSE, rot_matrix);
+
// Load the vertex data
glBindBuffer(GL_ARRAY_BUFFER, g_vbo);
glEnableVertexAttribArray(0);
diff --git a/gpu/command_buffer/common/cmd_buffer_common.cc b/gpu/command_buffer/common/cmd_buffer_common.cc
index 936d67c..bf965cc 100644
--- a/gpu/command_buffer/common/cmd_buffer_common.cc
+++ b/gpu/command_buffer/common/cmd_buffer_common.cc
@@ -8,8 +8,10 @@
#include "gpu/command_buffer/common/cmd_buffer_common.h"
namespace gpu {
-const int32 CommandHeader::kMaxSize = (1 << 21) - 1;
-
+#if !defined(OS_WIN)
+// gcc needs this to link, but MSVC requires it not be present
+const int32 CommandHeader::kMaxSize;
+#endif
namespace cmd {
const char* GetCommandName(CommandId command_id) {
diff --git a/gpu/command_buffer/common/cmd_buffer_common.h b/gpu/command_buffer/common/cmd_buffer_common.h
index 7ae59e7..5b23620 100644
--- a/gpu/command_buffer/common/cmd_buffer_common.h
+++ b/gpu/command_buffer/common/cmd_buffer_common.h
@@ -38,7 +38,7 @@ struct CommandHeader {
Uint32 size:21;
Uint32 command:11;
- static const int32 kMaxSize;
+ static const int32 kMaxSize = (1 << 21) - 1;
void Init(uint32 _command, int32 _size) {
DCHECK_LE(_size, kMaxSize);
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index e708a69..ddfc358 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -17,9 +17,18 @@
#include "gpu/command_buffer/service/cmd_buffer_engine.h"
#include "gpu/command_buffer/service/gl_utils.h"
#include "gpu/command_buffer/service/gles2_cmd_validation.h"
-#if defined(OS_LINUX) && !defined(UNIT_TEST)
+#if defined(UNIT_TEST)
+#elif defined(OS_LINUX)
// XWindowWrapper is stubbed out for unit-tests.
#include "gpu/command_buffer/service/x_utils.h"
+#elif defined(OS_MACOSX)
+// The following two #includes CAN NOT go above the inclusion of
+// gl_utils.h and therefore glew.h regardless of what the Google C++
+// style guide says.
+#include <CoreFoundation/CoreFoundation.h> // NOLINT
+#include <OpenGL/OpenGL.h> // NOLINT
+#include "base/scoped_cftyperef.h"
+#include "chrome/common/io_surface_support_mac.h"
#endif
namespace gpu {
@@ -38,9 +47,11 @@ COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
GLfloat_not_same_size_as_float);
-namespace {
+// TODO(kbr): the use of this anonymous namespace core dumps the
+// linker on Mac OS X 10.6 when the symbol ordering file is used
+// namespace {
-size_t GetGLTypeSize(GLenum type) {
+static size_t GetGLTypeSize(GLenum type) {
switch (type) {
case GL_BYTE:
return sizeof(GLbyte); // NOLINT
@@ -147,7 +158,7 @@ GLenum GLErrorBitToGLError(uint32 error_bit) {
}
}
-} // anonymous namespace.
+// } // anonymous namespace.
#if defined(UNIT_TEST)
GLES2Decoder::GLES2Decoder()
@@ -551,6 +562,13 @@ class GLES2DecoderImpl : public GLES2Decoder {
virtual bool MakeCurrent();
virtual uint32 GetServiceIdForTesting(uint32 client_id);
+#if !defined(UNIT_TEST) && defined(OS_MACOSX)
+ // Overridden from GLES2Decoder.
+ virtual uint64 SetWindowSize(int32 width, int32 height);
+#endif
+
+ virtual void SetSwapBuffersCallback(Callback0::Type* callback);
+
// Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
// on glDeleteBuffers so we can make sure the user does not try to render
// with deleted buffers.
@@ -729,10 +747,25 @@ class GLES2DecoderImpl : public GLES2Decoder {
#elif defined(OS_WIN)
HDC device_context_;
HGLRC gl_context_;
+#elif defined(OS_MACOSX)
+ CGLContextObj gl_context_;
+ CGLPBufferObj pbuffer_;
+ scoped_cftyperef<CFTypeRef> io_surface_;
+ int32 surface_width_;
+ int32 surface_height_;
+ GLuint texture_;
+ GLuint fbo_;
+ GLuint depth_renderbuffer_;
+ // For tracking whether the default framebuffer / renderbuffer or
+ // ones created by the end user are currently bound
+ GLuint bound_fbo_;
+ GLuint bound_renderbuffer_;
#endif
bool anti_aliased_;
+ scoped_ptr<Callback0::Type> swap_buffers_callback_;
+
DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
};
@@ -754,6 +787,16 @@ GLES2DecoderImpl::GLES2DecoderImpl()
#elif defined(OS_WIN)
device_context_(NULL),
gl_context_(NULL),
+#elif defined(OS_MACOSX)
+ gl_context_(NULL),
+ pbuffer_(NULL),
+ surface_width_(0),
+ surface_height_(0),
+ texture_(0),
+ fbo_(0),
+ depth_renderbuffer_(0),
+ bound_fbo_(0),
+ bound_renderbuffer_(0),
#endif
anti_aliased_(false) {
}
@@ -790,7 +833,9 @@ bool GLES2DecoderImpl::Initialize() {
return success;
}
-namespace {
+// TODO(kbr): the use of this anonymous namespace core dumps the
+// linker on Mac OS X 10.6 when the symbol ordering file is used
+// namespace {
#if defined(UNIT_TEST)
#elif defined(OS_WIN)
@@ -1007,7 +1052,7 @@ void GLDeleteTexturesHelper(
glDeleteTextures(n, ids);
}
-} // anonymous namespace
+// } // anonymous namespace
bool GLES2DecoderImpl::MakeCurrent() {
#if defined(UNIT_TEST)
@@ -1024,6 +1069,14 @@ bool GLES2DecoderImpl::MakeCurrent() {
return true;
#elif defined(OS_LINUX)
return window()->MakeCurrent();
+#elif defined(OS_MACOSX)
+ if (CGLGetCurrentContext() != gl_context_) {
+ if (CGLSetCurrentContext(gl_context_) != kCGLNoError) {
+ DLOG(ERROR) << "Unable to make gl context current.";
+ return false;
+ }
+ }
+ return true;
#else
NOTREACHED();
return false;
@@ -1103,6 +1156,49 @@ bool GLES2DecoderImpl::InitPlatformSpecific() {
DCHECK(window());
if (!window()->Initialize())
return false;
+#elif defined(OS_MACOSX)
+ // Create a 1x1 pbuffer and associated context to bootstrap things
+ static const CGLPixelFormatAttribute attribs[] = {
+ (CGLPixelFormatAttribute) kCGLPFAPBuffer,
+ (CGLPixelFormatAttribute) 0
+ };
+ CGLPixelFormatObj pixelFormat;
+ GLint numPixelFormats;
+ if (CGLChoosePixelFormat(attribs,
+ &pixelFormat,
+ &numPixelFormats) != kCGLNoError) {
+ DLOG(ERROR) << "Error choosing pixel format.";
+ return false;
+ }
+ if (!pixelFormat) {
+ return false;
+ }
+ CGLContextObj context;
+ CGLError res = CGLCreateContext(pixelFormat, 0, &context);
+ CGLDestroyPixelFormat(pixelFormat);
+ 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.
#endif
return true;
@@ -1164,11 +1260,141 @@ bool GLES2DecoderImpl::InitGlew() {
return true;
}
+#if !defined(UNIT_TEST) && defined(OS_MACOSX)
+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);
+}
+
+uint64 GLES2DecoderImpl::SetWindowSize(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;
+
+ 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;
+
+ if (!texture_) {
+ // Generate the texture object.
+ glGenTextures(1, &texture_);
+ glBindTexture(target, texture_);
+ glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameterf(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_renderbuffer_);
+ }
+
+ // 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));
+
+ // Reallocate the depth buffer.
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_renderbuffer_);
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,
+ GL_DEPTH_COMPONENT,
+ width,
+ height);
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, bound_renderbuffer_);
+
+ // Reallocate the texture object.
+ glBindTexture(target, texture_);
+ // 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.
+ if (bound_fbo_ != fbo_) {
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_);
+ }
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
+ GL_COLOR_ATTACHMENT0_EXT,
+ target,
+ texture_,
+ 0);
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
+ GL_DEPTH_ATTACHMENT_EXT,
+ GL_RENDERBUFFER_EXT,
+ depth_renderbuffer_);
+ if (bound_fbo_ != fbo_) {
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_);
+ }
+
+ 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_);
+}
+#endif // !defined(UNIT_TEST) && defined(OS_MACOSX)
+
+void GLES2DecoderImpl::SetSwapBuffersCallback(Callback0::Type* callback) {
+ swap_buffers_callback_.reset(callback);
+}
+
void GLES2DecoderImpl::Destroy() {
#if defined(UNIT_TEST)
#elif defined(OS_LINUX)
DCHECK(window());
window()->Destroy();
+#elif defined(OS_MACOSX)
+ if (gl_context_)
+ CGLDestroyContext(gl_context_);
+ if (pbuffer_)
+ CGLDestroyPBuffer(pbuffer_);
#endif
}
@@ -1332,7 +1558,18 @@ void GLES2DecoderImpl::DoSwapBuffers() {
#elif defined(OS_LINUX)
DCHECK(window());
window()->SwapBuffers();
+#elif defined(OS_MACOSX)
+ if (bound_fbo_ == fbo_) {
+ // 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_);
+ }
#endif
+ if (swap_buffers_callback_.get()) {
+ swap_buffers_callback_->Run();
+ }
}
void GLES2DecoderImpl::DoUseProgram(GLuint program) {
@@ -1476,7 +1713,9 @@ error::Error GLES2DecoderImpl::HandleDrawElements(
return error::kNoError;
}
-namespace {
+// TODO(kbr): the use of this anonymous namespace core dumps the
+// linker on Mac OS X 10.6 when the symbol ordering file is used
+// namespace {
// Calls glShaderSource for the various versions of the ShaderSource command.
// Assumes that data / data_size points to a piece of memory that is in range
@@ -1505,7 +1744,7 @@ error::Error ShaderSourceHelper(
return error::kNoError;
}
-} // anonymous namespace.
+// } // anonymous namespace.
error::Error GLES2DecoderImpl::HandleShaderSource(
uint32 immediate_data_size, const gles2::ShaderSource& c) {
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.h b/gpu/command_buffer/service/gles2_cmd_decoder.h
index db91d55..9e6b9c8 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.h
@@ -11,6 +11,7 @@
#if defined(OS_WIN)
#include <windows.h>
#endif
+#include "base/task.h"
#include "gpu/command_buffer/service/common_decoder.h"
namespace gpu {
@@ -55,6 +56,8 @@ class GLES2Decoder : public CommonDecoder {
HWND hwnd() const {
return hwnd_;
}
+#elif !defined(UNIT_TEST) && defined(OS_MACOSX)
+ virtual uint64 SetWindowSize(int32 width, int32 height) = 0;
#endif
// Initializes the graphics context.
@@ -71,6 +74,9 @@ class GLES2Decoder : public CommonDecoder {
// Gets a service id by client id.
virtual uint32 GetServiceIdForTesting(uint32 client_id) = 0;
+ // Sets a callback which is called when a SwapBuffers command is processed.
+ virtual void SetSwapBuffersCallback(Callback0::Type* callback) = 0;
+
protected:
GLES2Decoder();
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
index dba1043..fa60d41 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
@@ -26,6 +26,7 @@ class MockGLES2Decoder : public GLES2Decoder {
MOCK_METHOD0(Destroy, void());
MOCK_METHOD0(MakeCurrent, bool());
MOCK_METHOD1(GetServiceIdForTesting, uint32(uint32 client_id));
+ MOCK_METHOD1(SetSwapBuffersCallback, void(Callback0::Type*));
MOCK_METHOD3(DoCommand, error::Error(unsigned int command,
unsigned int arg_count,
const void* cmd_data));
diff --git a/gpu/command_buffer/service/gpu_processor.cc b/gpu/command_buffer/service/gpu_processor.cc
index c9b8c6f..7272115 100644
--- a/gpu/command_buffer/service/gpu_processor.cc
+++ b/gpu/command_buffer/service/gpu_processor.cc
@@ -82,4 +82,15 @@ int32 GPUProcessor::GetGetOffset() {
return parser_->get();
}
+#if defined(OS_MACOSX)
+uint64 GPUProcessor::SetWindowSize(int32 width, int32 height) {
+ return decoder_->SetWindowSize(width, height);
+}
+#endif
+
+void GPUProcessor::SetSwapBuffersCallback(
+ Callback0::Type* callback) {
+ decoder_->SetSwapBuffersCallback(callback);
+}
+
} // namespace gpu
diff --git a/gpu/command_buffer/service/gpu_processor.h b/gpu/command_buffer/service/gpu_processor.h
index dd22ac4..f22f249 100644
--- a/gpu/command_buffer/service/gpu_processor.h
+++ b/gpu/command_buffer/service/gpu_processor.h
@@ -44,6 +44,19 @@ class GPUProcessor : public base::RefCounted<GPUProcessor>,
virtual bool SetGetOffset(int32 offset);
virtual int32 GetGetOffset();
+#if defined(OS_MACOSX)
+ // Needed only on Mac OS X, which does not render into an on-screen
+ // window and therefore requires the backing store to be resized
+ // manually. Returns an opaque identifier for the new backing store.
+ virtual uint64 SetWindowSize(int32 width, int32 height);
+
+#endif
+
+ // Sets a callback which is called when a SwapBuffers command is processed.
+ // Must be called after Initialize().
+ // It is not defined on which thread this callback is called.
+ virtual void SetSwapBuffersCallback(Callback0::Type* callback);
+
private:
// The GPUProcessor holds a weak reference to the CommandBuffer. The
// CommandBuffer owns the GPUProcessor and holds a strong reference to it
diff --git a/gpu/command_buffer/service/gpu_processor_mac.cc b/gpu/command_buffer/service/gpu_processor_mac.cc
new file mode 100644
index 0000000..a36560c
--- /dev/null
+++ b/gpu/command_buffer/service/gpu_processor_mac.cc
@@ -0,0 +1,39 @@
+// 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 "gpu/command_buffer/service/gpu_processor.h"
+
+using ::base::SharedMemory;
+
+namespace gpu {
+
+bool GPUProcessor::Initialize(gfx::PluginWindowHandle handle) {
+ // At this level we do not need the PluginWindowHandle. It is only
+ // needed at the CommandBufferStub level to identify which GPU
+ // plugin instance is creating a new backing store in response to a
+ // resize event.
+
+ // Map the ring buffer and create the parser.
+ Buffer ring_buffer = command_buffer_->GetRingBuffer();
+ if (ring_buffer.ptr) {
+ parser_.reset(new CommandParser(ring_buffer.ptr,
+ ring_buffer.size,
+ 0,
+ ring_buffer.size,
+ 0,
+ decoder_.get()));
+ } else {
+ parser_.reset(new CommandParser(NULL, 0, 0, 0, 0,
+ decoder_.get()));
+ }
+
+ // Initialize GAPI.
+ return decoder_->Initialize();
+}
+
+void GPUProcessor::Destroy() {
+ decoder_->Destroy();
+}
+} // namespace gpu
+
diff --git a/gpu/gpu.gyp b/gpu/gpu.gyp
index c20338e..df0a25f 100644
--- a/gpu/gpu.gyp
+++ b/gpu/gpu.gyp
@@ -19,9 +19,6 @@
'command_buffer/service/gl_utils.h',
],
},
- 'includes': [
- '../build/common.gypi',
- ],
'targets': [
{
'target_name': 'gl_libs',
@@ -138,6 +135,12 @@
'dependencies': [
'gles2_cmd_helper',
],
+ 'all_dependent_settings': {
+ 'include_dirs': [
+ # For GLES2/gl2.h
+ 'command_buffer/common',
+ ],
+ },
'sources': [
'command_buffer/client/gles2_implementation_autogen.h',
'command_buffer/client/gles2_implementation.cc',
@@ -266,6 +269,13 @@
],
},
],
+ ['OS == "mac"',
+ {
+ 'sources': [
+ 'command_buffer/service/gpu_processor_mac.cc',
+ ],
+ },
+ ],
],
},
{
diff --git a/gpu/gpu_plugin/gpu_plugin.cc b/gpu/gpu_plugin/gpu_plugin.cc
index 5bccbe4..d274936 100644
--- a/gpu/gpu_plugin/gpu_plugin.cc
+++ b/gpu/gpu_plugin/gpu_plugin.cc
@@ -120,7 +120,7 @@ NPError API_CALL NP_GetEntryPoints(NPPluginFuncs* funcs) {
return NPERR_NO_ERROR;
}
-#if defined(OS_LINUX)
+#if defined(OS_POSIX) && !defined(OS_MACOSX)
NPError API_CALL NP_Initialize(NPNetscapeFuncs *browser_funcs,
NPPluginFuncs* plugin_funcs) {
#else
@@ -129,7 +129,7 @@ NPError API_CALL NP_Initialize(NPNetscapeFuncs *browser_funcs) {
if (!browser_funcs)
return NPERR_INVALID_FUNCTABLE_ERROR;
-#if defined(OS_LINUX)
+#if defined(OS_POSIX) && !defined(OS_MACOSX)
NP_GetEntryPoints(plugin_funcs);
#endif
diff --git a/gpu/gpu_plugin/gpu_plugin.h b/gpu/gpu_plugin/gpu_plugin.h
index b6bfc89..b973d7cf 100644
--- a/gpu/gpu_plugin/gpu_plugin.h
+++ b/gpu/gpu_plugin/gpu_plugin.h
@@ -17,7 +17,7 @@ namespace gpu_plugin {
NPError API_CALL NP_GetEntryPoints(NPPluginFuncs* funcs);
-#if defined(OS_LINUX)
+#if defined(OS_POSIX) && !defined(OS_MACOSX)
NPError API_CALL NP_Initialize(NPNetscapeFuncs *browser_funcs,
NPPluginFuncs* plugin_funcs);
#else
diff --git a/webkit/glue/plugins/mac_gpu_plugin_container.cc b/webkit/glue/plugins/mac_gpu_plugin_container.cc
new file mode 100644
index 0000000..e38234f
--- /dev/null
+++ b/webkit/glue/plugins/mac_gpu_plugin_container.cc
@@ -0,0 +1,104 @@
+// 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 "webkit/glue/plugins/mac_gpu_plugin_container.h"
+
+#include "webkit/glue/webplugin.h"
+#include "webkit/glue/plugins/mac_gpu_plugin_container_manager.h"
+#include "chrome/common/io_surface_support_mac.h"
+
+MacGPUPluginContainer::MacGPUPluginContainer()
+ : x_(0),
+ y_(0),
+ surface_(NULL),
+ width_(0),
+ height_(0),
+ texture_(0) {
+}
+
+MacGPUPluginContainer::~MacGPUPluginContainer() {
+ ReleaseIOSurface();
+}
+
+void MacGPUPluginContainer::ReleaseIOSurface() {
+ if (surface_) {
+ CFRelease(surface_);
+ surface_ = NULL;
+ }
+}
+
+void MacGPUPluginContainer::SetSizeAndBackingStore(
+ int32 width,
+ int32 height,
+ uint64 io_surface_identifier,
+ MacGPUPluginContainerManager* manager) {
+ ReleaseIOSurface();
+ IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize();
+ if (io_surface_support) {
+ surface_ = io_surface_support->IOSurfaceLookup(
+ static_cast<uint32>(io_surface_identifier));
+ EnqueueTextureForDeletion(manager);
+ width_ = width;
+ height_ = height;
+ }
+}
+
+void MacGPUPluginContainer::MoveTo(
+ const webkit_glue::WebPluginGeometry& geom) {
+ // TODO(kbr): figure out whether additional information is necessary
+ // to keep around.
+ x_ = geom.window_rect.x();
+ y_ = geom.window_rect.y();
+}
+
+void MacGPUPluginContainer::Draw(CGLContextObj context) {
+ IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize();
+ if (!io_surface_support)
+ return;
+
+ GLenum target = GL_TEXTURE_RECTANGLE_ARB;
+ if (!texture_ && surface_) {
+ glGenTextures(1, &texture_);
+ glBindTexture(target, texture_);
+ glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ // Don't think we need to identify a plane.
+ GLuint plane = 0;
+ io_surface_support->CGLTexImageIOSurface2D(context,
+ target,
+ GL_RGBA,
+ width_,
+ height_,
+ GL_BGRA,
+ GL_UNSIGNED_INT_8_8_8_8_REV,
+ surface_,
+ plane);
+ }
+
+ if (texture_) {
+ // TODO(kbr): convert this to use only OpenGL ES 2.0 functionality
+ glBindTexture(target, texture_);
+ glEnable(target);
+ glBegin(GL_TRIANGLE_STRIP);
+ int x = x_;
+ int y = y_;
+ glTexCoord2f(0, height_);
+ glVertex3f(x, y, 0);
+ glTexCoord2f(width_, height_);
+ glVertex3f(x + width_, y, 0);
+ glTexCoord2f(0, 0);
+ glVertex3f(x, y + height_, 0);
+ glTexCoord2f(width_, 0);
+ glVertex3f(x + width_, y + height_, 0);
+ glDisable(target);
+ glEnd();
+ }
+}
+
+void MacGPUPluginContainer::EnqueueTextureForDeletion(
+ MacGPUPluginContainerManager* manager) {
+ manager->EnqueueTextureForDeletion(texture_);
+ texture_ = 0;
+}
+
diff --git a/webkit/glue/plugins/mac_gpu_plugin_container.h b/webkit/glue/plugins/mac_gpu_plugin_container.h
new file mode 100644
index 0000000..92e9fcb
--- /dev/null
+++ b/webkit/glue/plugins/mac_gpu_plugin_container.h
@@ -0,0 +1,98 @@
+// 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 WEBKIT_GLUE_PLUGINS_MAC_GPU_PLUGIN_CONTAINER_H_
+#define WEBKIT_GLUE_PLUGINS_MAC_GPU_PLUGIN_CONTAINER_H_
+
+// The "GPU plugin" is currently implemented as a special kind of
+// NPAPI plugin to provide high-performance on-screen 3D rendering for
+// Pepper 3D.
+//
+// On Windows and X11 platforms the GPU plugin relies on cross-process
+// parenting of windows, which is not supported via any public APIs in
+// the Mac OS X window system.
+//
+// To achieve full hardware acceleration we use the new IOSurface APIs
+// introduced in Mac OS X 10.6. The GPU plugin's process produces an
+// IOSurface and renders into it using OpenGL. It uses the
+// IOSurfaceGetID and IOSurfaceLookup APIs to pass a reference to this
+// surface to the browser process for on-screen rendering. The GPU
+// plugin essentially looks like a windowless plugin; the browser
+// process gets all of the mouse events, because the plugin process
+// does not have an on-screen window.
+//
+// This class encapsulates some of the management of these data
+// structures, in conjunction with the MacGPUPluginContainerManager.
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <OpenGL/OpenGL.h>
+
+#include "app/gfx/native_widget_types.h"
+#include "base/basictypes.h"
+
+namespace webkit_glue {
+struct WebPluginGeometry;
+}
+
+class MacGPUPluginContainerManager;
+
+class MacGPUPluginContainer {
+ public:
+ MacGPUPluginContainer();
+ virtual ~MacGPUPluginContainer();
+
+ // Sets the backing store and size of this plugin container.
+ void SetSizeAndBackingStore(int32 width,
+ int32 height,
+ uint64 io_surface_identifier,
+ MacGPUPluginContainerManager* manager);
+
+ // Tells the plugin container that it has moved relative to the
+ // origin of the window, for example because of a scroll event.
+ void MoveTo(const webkit_glue::WebPluginGeometry& geom);
+
+ // Draws this plugin's contents, texture mapped onto a quad in the
+ // given OpenGL context. TODO(kbr): figure out and define exactly
+ // how the coordinate system will work out.
+ void Draw(CGLContextObj context);
+
+ // Enqueue our texture for later deletion. Call this before deleting
+ // this object.
+ void EnqueueTextureForDeletion(MacGPUPluginContainerManager* manager);
+
+ private:
+ // We currently only have a viable implementation of this class on
+ // Snow Leopard. We need to think about fallback strategies that
+ // will work on Leopard.
+
+ // The x and y coordinates of the plugin window on the web page.
+ // TODO(kbr): see whether additional clipping information is
+ // necessary.
+ int x_;
+ int y_;
+
+ void ReleaseIOSurface();
+
+ // The IOSurfaceRef, if any, that has been handed from the GPU
+ // plugin process back to the browser process for drawing.
+ // This is held as a CFTypeRef because we can't refer to the
+ // IOSurfaceRef type when building on 10.5.
+ CFTypeRef surface_;
+
+ // The width and height of the surface.
+ int32 width_;
+ int32 height_;
+
+ // The "live" OpenGL texture referring to this IOSurfaceRef. Note
+ // that per the CGLTexImageIOSurface2D API we do not need to
+ // explicitly update this texture's contents once created. All we
+ // need to do is ensure it is re-bound before attempting to draw
+ // with it.
+ GLuint texture_;
+
+ DISALLOW_COPY_AND_ASSIGN(MacGPUPluginContainer);
+};
+
+#endif // WEBKIT_GLUE_PLUGINS_MAC_GPU_PLUGIN_CONTAINER_H_
+
diff --git a/webkit/glue/plugins/mac_gpu_plugin_container_manager.cc b/webkit/glue/plugins/mac_gpu_plugin_container_manager.cc
new file mode 100644
index 0000000..185754e
--- /dev/null
+++ b/webkit/glue/plugins/mac_gpu_plugin_container_manager.cc
@@ -0,0 +1,89 @@
+// 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 "webkit/glue/plugins/mac_gpu_plugin_container_manager.h"
+
+#include "base/logging.h"
+#include "webkit/glue/webplugin.h"
+#include "webkit/glue/plugins/mac_gpu_plugin_container.h"
+
+MacGPUPluginContainerManager::MacGPUPluginContainerManager()
+ : current_id_(0) {
+}
+
+gfx::PluginWindowHandle
+MacGPUPluginContainerManager::AllocateFakePluginWindowHandle() {
+ MacGPUPluginContainer* container = new MacGPUPluginContainer();
+ gfx::PluginWindowHandle res =
+ static_cast<gfx::PluginWindowHandle>(++current_id_);
+ plugin_window_to_container_map_.insert(std::make_pair(res, container));
+ return res;
+}
+
+void MacGPUPluginContainerManager::DestroyFakePluginWindowHandle(
+ gfx::PluginWindowHandle id) {
+ MacGPUPluginContainer* container = MapIDToContainer(id);
+ if (container)
+ delete container;
+ plugin_window_to_container_map_.erase(id);
+}
+
+void MacGPUPluginContainerManager::SetSizeAndBackingStore(
+ gfx::PluginWindowHandle id,
+ int32 width,
+ int32 height,
+ uint64 io_surface_identifier) {
+ MacGPUPluginContainer* container = MapIDToContainer(id);
+ if (container)
+ container->SetSizeAndBackingStore(width, height,
+ io_surface_identifier, this);
+}
+
+void MacGPUPluginContainerManager::MovePluginContainer(
+ const webkit_glue::WebPluginGeometry& move) {
+ MacGPUPluginContainer* container = MapIDToContainer(move.window);
+ if (container)
+ container->MoveTo(move);
+}
+
+void MacGPUPluginContainerManager::Draw(CGLContextObj context) {
+ glClearColor(0, 0, 0, 0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ GLenum target = GL_TEXTURE_RECTANGLE_ARB;
+ glTexEnvi(target, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+
+ for (PluginWindowToContainerMap::const_iterator i =
+ plugin_window_to_container_map_.begin();
+ i != plugin_window_to_container_map_.end(); ++i) {
+ MacGPUPluginContainer* container = i->second;
+ container->Draw(context);
+ }
+
+ // Unbind any texture from the texture target to ensure that the
+ // next time through we will have to re-bind the texture and thereby
+ // pick up modifications from the other process.
+ glBindTexture(target, 0);
+
+ glFlush();
+}
+
+void MacGPUPluginContainerManager::EnqueueTextureForDeletion(GLuint texture) {
+ if (texture) {
+ textures_pending_deletion_.push_back(texture);
+ }
+}
+
+MacGPUPluginContainer* MacGPUPluginContainerManager::MapIDToContainer(
+ gfx::PluginWindowHandle id) {
+ PluginWindowToContainerMap::const_iterator i =
+ plugin_window_to_container_map_.find(id);
+ if (i != plugin_window_to_container_map_.end())
+ return i->second;
+
+ LOG(ERROR) << "Request for plugin container for unknown window id " << id;
+
+ return NULL;
+}
+
diff --git a/webkit/glue/plugins/mac_gpu_plugin_container_manager.h b/webkit/glue/plugins/mac_gpu_plugin_container_manager.h
new file mode 100644
index 0000000..ed63f10
--- /dev/null
+++ b/webkit/glue/plugins/mac_gpu_plugin_container_manager.h
@@ -0,0 +1,70 @@
+// 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 WEBKIT_GLUE_PLUGINS_MAC_GPU_PLUGIN_CONTAINER_MANAGER_H_
+#define WEBKIT_GLUE_PLUGINS_MAC_GPU_PLUGIN_CONTAINER_MANAGER_H_
+
+#include <OpenGL/OpenGL.h>
+#include <map>
+#include <vector>
+
+#include "app/gfx/native_widget_types.h"
+#include "base/basictypes.h"
+
+namespace webkit_glue {
+struct WebPluginGeometry;
+}
+
+class MacGPUPluginContainer;
+
+// Helper class that manages the backing store and on-screen rendering
+// of instances of the GPU plugin on the Mac.
+class MacGPUPluginContainerManager {
+ public:
+ MacGPUPluginContainerManager();
+
+ // Allocates a new "fake" PluginWindowHandle, which is used as the
+ // key for the other operations.
+ gfx::PluginWindowHandle AllocateFakePluginWindowHandle();
+
+ // Destroys a fake PluginWindowHandle and associated storage.
+ void DestroyFakePluginWindowHandle(gfx::PluginWindowHandle id);
+
+ // Sets the size and backing store of the plugin instance.
+ void SetSizeAndBackingStore(gfx::PluginWindowHandle id,
+ int32 width,
+ int32 height,
+ uint64 io_surface_identifier);
+
+ // Takes an update from WebKit about a plugin's position and size and moves
+ // the plugin accordingly.
+ void MovePluginContainer(const webkit_glue::WebPluginGeometry& move);
+
+ // Draws all of the managed plugin containers into the given OpenGL
+ // context, which must already be current.
+ void Draw(CGLContextObj context);
+
+ // Called by the container to enqueue its OpenGL texture objects for
+ // deletion.
+ void EnqueueTextureForDeletion(GLuint texture);
+
+ private:
+ uint32 current_id_;
+
+ // Maps a "fake" plugin window handle to the corresponding container.
+ MacGPUPluginContainer* MapIDToContainer(gfx::PluginWindowHandle id);
+
+ // A map that associates plugin window handles with their containers.
+ typedef std::map<gfx::PluginWindowHandle, MacGPUPluginContainer*>
+ PluginWindowToContainerMap;
+ PluginWindowToContainerMap plugin_window_to_container_map_;
+
+ // A list of OpenGL textures waiting to be deleted
+ std::vector<GLuint> textures_pending_deletion_;
+
+ DISALLOW_COPY_AND_ASSIGN(MacGPUPluginContainerManager);
+};
+
+#endif // WEBKIT_GLUE_PLUGINS_MAC_GPU_PLUGIN_CONTAINER_MANAGER_H_
+
diff --git a/webkit/glue/plugins/webplugin_delegate_impl.h b/webkit/glue/plugins/webplugin_delegate_impl.h
index e6e5d20..32dca05 100644
--- a/webkit/glue/plugins/webplugin_delegate_impl.h
+++ b/webkit/glue/plugins/webplugin_delegate_impl.h
@@ -147,10 +147,16 @@ class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate {
#endif
#endif // OS_MACOSX
-#if !defined(OS_MACOSX)
gfx::PluginWindowHandle windowed_handle() const {
return windowed_handle_;
}
+
+#if defined(OS_MACOSX)
+ // On Mac OS X and for the GPU plugin only, this handle is a fake
+ // one and comes in from the outside world.
+ void set_windowed_handle(gfx::PluginWindowHandle handle) {
+ windowed_handle_ = handle;
+ }
#endif
private:
@@ -225,11 +231,15 @@ class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate {
// Closes down and destroys our plugin instance.
void DestroyInstance();
-#if !defined(OS_MACOSX)
+
// used for windowed plugins
+ // Note: on Mac OS X, the only time the windowed handle is non-zero
+ // is the case of the GPU plugin, which uses a fake window handle to
+ // identify itself back to the browser. It still performs all of its
+ // work offscreen.
gfx::PluginWindowHandle windowed_handle_;
gfx::Rect windowed_last_pos_;
-#endif
+
bool windowed_did_set_window_;
// TODO(dglazkov): No longer used by Windows, make sure the removal
diff --git a/webkit/glue/webplugin.h b/webkit/glue/webplugin.h
index 051eb2c..1c79876 100644
--- a/webkit/glue/webplugin.h
+++ b/webkit/glue/webplugin.h
@@ -39,6 +39,15 @@ struct WebPluginGeometry {
// On Windows, this is the plugin window in the plugin process.
// On X11, this is the XID of the plugin-side GtkPlug containing the
// GtkSocket hosting the actual plugin window.
+ //
+ // On Mac OS X, all of the plugin types are currently "windowless"
+ // (window == 0) except for the special case of the GPU plugin,
+ // which currently performs rendering on behalf of the Pepper 3D API
+ // and WebGL. The GPU plugin uses a simple integer for the
+ // PluginWindowHandle which is used to map to a side data structure
+ // containing information about the plugin. Soon this plugin will be
+ // generalized, at which point this mechanism will be rethought or
+ // removed.
gfx::PluginWindowHandle window;
gfx::Rect window_rect;
// Clip rect (include) and cutouts (excludes), relative to
diff --git a/webkit/glue/webplugin_impl.cc b/webkit/glue/webplugin_impl.cc
index ceb4239..20b86b4 100644
--- a/webkit/glue/webplugin_impl.cc
+++ b/webkit/glue/webplugin_impl.cc
@@ -406,6 +406,23 @@ WebPluginImpl::~WebPluginImpl() {
}
void WebPluginImpl::SetWindow(gfx::PluginWindowHandle window) {
+#if defined(OS_MACOSX)
+ // The only time this is called twice, and the second time with a
+ // non-zero PluginWindowHandle, is the case when this WebPluginImpl
+ // is created on behalf of the GPU plugin. This entire code path
+ // will go away soon, as soon as the GPU plugin becomes the GPU
+ // process, so it is being separated out for easy deletion.
+
+ // The logic we want here is: if (window) DCHECK(!window_);
+ DCHECK(!(window_ && window));
+ window_ = window;
+ // Lie to ourselves about being windowless even if we got a fake
+ // plugin window handle, so we continue to get input events.
+ windowless_ = true;
+ accepts_input_events_ = true;
+ // We do not really need to notify the page delegate that a plugin
+ // window was created -- so don't.
+#else
if (window) {
DCHECK(!windowless_);
window_ = window;
@@ -420,6 +437,7 @@ void WebPluginImpl::SetWindow(gfx::PluginWindowHandle window) {
windowless_ = true;
accepts_input_events_ = true;
}
+#endif
}
void WebPluginImpl::WillDestroyWindow(gfx::PluginWindowHandle window) {
diff --git a/webkit/tools/pepper_test_plugin/pepper_test_plugin.gyp b/webkit/tools/pepper_test_plugin/pepper_test_plugin.gyp
index f36abf7..0f799f5 100644
--- a/webkit/tools/pepper_test_plugin/pepper_test_plugin.gyp
+++ b/webkit/tools/pepper_test_plugin/pepper_test_plugin.gyp
@@ -58,25 +58,19 @@
'cflags': ['-fPIC'],
'defines': ['INDEPENDENT_PLUGIN'],
}, {
+ # Dependencies for all other OS/CPU combinations except the Linux ones above
'dependencies': [
'../../../base/base.gyp:base',
'../../../skia/skia.gyp:skia',
+ '../../../gpu/gpu.gyp:gles2_demo_lib',
+ '../../../gpu/gpu.gyp:pgl',
],
- 'conditions': [
- ['OS!="mac"', {
- 'dependencies': [
- '../../../gpu/gpu.gyp:gles2_demo_lib',
- '../../../gpu/gpu.gyp:pgl',
- ],
- }],
- ]
}],
['OS=="mac"', {
'type': 'loadable_module',
'mac_bundle': 1,
'product_name': 'PepperTestPlugin',
'product_extension': 'plugin',
- 'defines': ['INDEPENDENT_PLUGIN'],
'sources+': [
'Info.plist'
],
diff --git a/webkit/tools/pepper_test_plugin/plugin_object.cc b/webkit/tools/pepper_test_plugin/plugin_object.cc
index a2075ec..013702b 100644
--- a/webkit/tools/pepper_test_plugin/plugin_object.cc
+++ b/webkit/tools/pepper_test_plugin/plugin_object.cc
@@ -34,8 +34,9 @@
#define CHECK(x)
#else
#include "base/logging.h"
+#include "build/build_config.h"
#include "gpu/command_buffer/client/gles2_demo_cc.h"
-#include "gpu/command_buffer/common/GLES2/gl2.h"
+#include <GLES2/gl2.h> // NOLINT
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/effects/SkGradientShader.h"
@@ -308,7 +309,10 @@ PluginObject::PluginObject(NPP npp)
}
PluginObject::~PluginObject() {
+ // TODO(kbr): add audio portion of test
+#if !defined(OS_MACOSX)
deviceaudio_->destroyContext(npp_, &context_audio_);
+#endif
// FIXME(brettw) destroy the context.
browser->releaseobject(test_object_);
}
@@ -347,8 +351,11 @@ void PluginObject::New(NPMIMEType pluginType,
device3d_ = extensions->acquireDevice(npp_, NPPepper3DDevice);
CHECK(device3d_);
+ // TODO(kbr): add audio portion of test
+#if !defined(OS_MACOSX)
deviceaudio_ = extensions->acquireDevice(npp_, NPPepperAudioDevice);
CHECK(deviceaudio_);
+#endif
}
void PluginObject::SetWindow(const NPWindow& window) {
@@ -389,6 +396,8 @@ void PluginObject::SetWindow(const NPWindow& window) {
#endif
}
+ // TODO(kbr): put back in audio portion of test
+#if !defined(OS_MACOSX)
// testing any field would do
if (!context_audio_.config.callback) {
NPDeviceContextAudioConfig cfg;
@@ -401,6 +410,7 @@ void PluginObject::SetWindow(const NPWindow& window) {
cfg.callback = &SineWaveCallback<200, int16>;
deviceaudio_->initializeContext(npp_, &cfg, &context_audio_);
}
+#endif
}
void PluginObject::Draw3D() {
diff --git a/webkit/tools/pepper_test_plugin/test_page.html b/webkit/tools/pepper_test_plugin/test_page.html
index 5a3e609..5c20d6d 100644
--- a/webkit/tools/pepper_test_plugin/test_page.html
+++ b/webkit/tools/pepper_test_plugin/test_page.html
@@ -29,7 +29,7 @@ This page embeds a file declared as the pepper test plugins MIME type so that it
<table>
<tr>
<td valign="top" width="50%">
-<object id="plugin" type="pepper-application/x-pepper-test-plugin" width="400" height="400" dimensions="2" />
+<object id="plugin" type="pepper-application/x-pepper-test-plugin" width="400" height="400" dimensions="3" />
</td>
<td valign="top" style="background-color:Silver" width="50%">
<div id="event_text_box" style="width:400px; height:400px; overflow:auto">
@@ -39,4 +39,4 @@ This page embeds a file declared as the pepper test plugins MIME type so that it
</table>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/webkit/tools/test_shell/mac/test_webview_delegate.mm b/webkit/tools/test_shell/mac/test_webview_delegate.mm
index 483e776..cb2a392 100644
--- a/webkit/tools/test_shell/mac/test_webview_delegate.mm
+++ b/webkit/tools/test_shell/mac/test_webview_delegate.mm
@@ -171,7 +171,7 @@ webkit_glue::WebPluginDelegate* TestWebViewDelegate::CreatePluginDelegate(
WebWidgetHost *host = GetWidgetHost();
if (!host)
return NULL;
- gfx::NativeView view = host->view_handle();
+ gfx::PluginWindowHandle containing_view = NULL;
bool allow_wildcard = true;
WebPluginInfo info;
@@ -181,9 +181,11 @@ webkit_glue::WebPluginDelegate* TestWebViewDelegate::CreatePluginDelegate(
}
if (actual_mime_type && !actual_mime_type->empty())
- return WebPluginDelegateImpl::Create(info.path, *actual_mime_type, view);
+ return WebPluginDelegateImpl::Create(info.path, *actual_mime_type,
+ containing_view);
else
- return WebPluginDelegateImpl::Create(info.path, mime_type, view);
+ return WebPluginDelegateImpl::Create(info.path, mime_type,
+ containing_view);
}
void TestWebViewDelegate::CreatedPluginWindow(
diff --git a/webkit/webkit.gyp b/webkit/webkit.gyp
index 3270eac..0863370 100644
--- a/webkit/webkit.gyp
+++ b/webkit/webkit.gyp
@@ -262,6 +262,10 @@
'glue/plugins/gtk_plugin_container.cc',
'glue/plugins/gtk_plugin_container_manager.h',
'glue/plugins/gtk_plugin_container_manager.cc',
+ 'glue/plugins/mac_gpu_plugin_container.h',
+ 'glue/plugins/mac_gpu_plugin_container.cc',
+ 'glue/plugins/mac_gpu_plugin_container_manager.h',
+ 'glue/plugins/mac_gpu_plugin_container_manager.cc',
'glue/plugins/npapi_extension_thunk.cc',
'glue/plugins/npapi_extension_thunk.h',
'glue/plugins/plugin_constants_win.h',
@@ -416,9 +420,10 @@
['exclude', r'/gtk_']],
}],
['OS!="mac"', {
- 'sources/': [['exclude', '_mac\\.(cc|mm)$']],
+ 'sources/': [['exclude', '_mac\\.(cc|mm)$'],
+ ['exclude', r'/mac_']],
}],
- ['OS=="win" or (OS=="linux" and target_arch!="arm")', {
+ ['enable_gpu==1', {
'dependencies': [
'../gpu/gpu.gyp:gpu_plugin',
],