summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkbr@google.com <kbr@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-03 02:28:48 +0000
committerkbr@google.com <kbr@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-03 02:28:48 +0000
commit43f28f83bc268dea720843a2616058b64b3e8810 (patch)
tree3c3c4fc9c43dad15246fae82cb5b965e6b217281
parent2d48004e1f2c8cecd015144c179f993d883aba9c (diff)
downloadchromium_src-43f28f83bc268dea720843a2616058b64b3e8810.zip
chromium_src-43f28f83bc268dea720843a2616058b64b3e8810.tar.gz
chromium_src-43f28f83bc268dea720843a2616058b64b3e8810.tar.bz2
[GPU] Get GPU process running on the mac
Initial port of GPU process / plugin to Mac OS X. Uses new IOSurface APIs and therefore currently runs only on 10.6. Alternate strategy will need to be devised for 10.5. Slight UI issues remain such as GPU plugins initially showing up in the wrong place on the page. These will be fixed in follow-on bugs. Minimal changes made to command buffer code to get it to compile on Mac OS X. Commented out use of nested anonymous namespaces in gles2_cmd_decoder.cc which were causing the linker to crash with a seg fault. Refactored gyp files so the OS test enabling the GPU plugin is in one place, common.gypi, and other files test only the variable enable_gpu. Slight change to gles2_demo_cc.cc to add some simple animation to verify that updates from the GPU plugin are reaching the screen. Changed Pepper test plugin to use 3D view by default and commented out use of audio context because of recent issues. TEST=none (ran Pepper Test Plugin with 3D view enabled) BUG=http://crbug.com/25988 Review URL: http://codereview.chromium.org/558035 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@37934 0039d316-1c4b-4281-b951-d872f2087c98
-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',
],