summaryrefslogtreecommitdiffstats
path: root/webkit/glue
diff options
context:
space:
mode:
Diffstat (limited to 'webkit/glue')
-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
7 files changed, 401 insertions, 3 deletions
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) {