diff options
Diffstat (limited to 'webkit/glue')
-rw-r--r-- | webkit/glue/plugins/mac_gpu_plugin_container.cc | 104 | ||||
-rw-r--r-- | webkit/glue/plugins/mac_gpu_plugin_container.h | 98 | ||||
-rw-r--r-- | webkit/glue/plugins/mac_gpu_plugin_container_manager.cc | 89 | ||||
-rw-r--r-- | webkit/glue/plugins/mac_gpu_plugin_container_manager.h | 70 | ||||
-rw-r--r-- | webkit/glue/plugins/webplugin_delegate_impl.h | 16 | ||||
-rw-r--r-- | webkit/glue/webplugin.h | 9 | ||||
-rw-r--r-- | webkit/glue/webplugin_impl.cc | 18 |
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) { |