diff options
Diffstat (limited to 'chrome')
6 files changed, 455 insertions, 1 deletions
diff --git a/chrome/browser/renderer_host/gpu_plugin_container_mac.cc b/chrome/browser/renderer_host/gpu_plugin_container_mac.cc new file mode 100644 index 0000000..a2b69f4 --- /dev/null +++ b/chrome/browser/renderer_host/gpu_plugin_container_mac.cc @@ -0,0 +1,158 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/renderer_host/gpu_plugin_container_mac.h" + +#include "base/logging.h" +#include "chrome/browser/renderer_host/gpu_plugin_container_manager_mac.h" +#include "chrome/common/io_surface_support_mac.h" +#include "webkit/glue/webplugin.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::SetSizeAndIOSurface( + 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::SetSizeAndTransportDIB( + int32 width, + int32 height, + TransportDIB::Handle transport_dib, + MacGPUPluginContainerManager* manager) { + if (TransportDIB::is_valid(transport_dib)) { + transport_dib_.reset(TransportDIB::Map(transport_dib)); + EnqueueTextureForDeletion(manager); + width_ = width; + height_ = height; + } +} + +void MacGPUPluginContainer::MoveTo( + const webkit_glue::WebPluginGeometry& geom) { + x_ = geom.window_rect.x(); + y_ = geom.window_rect.y(); + // TODO(kbr): may need to pay attention to cutout rects. + clipRect_ = geom.clip_rect; +} + +void MacGPUPluginContainer::Draw(CGLContextObj context) { + IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize(); + GLenum target = GL_TEXTURE_RECTANGLE_ARB; + if (!texture_) { + if ((io_surface_support && !surface_) || + (!io_surface_support && !transport_dib_.get())) + return; + glGenTextures(1, &texture_); + glBindTexture(target, texture_); + glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + // When using an IOSurface, the texture does not need to be repeatedly + // uploaded, so bind the IOSurface once during texture gen in this case. + if (io_surface_support) { + DCHECK(surface_); + // 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); + } else { + // Reserve space on the card for the actual texture upload, done with the + // glTexSubImage2D() call, below. + glTexImage2D(target, + 0, // mipmap level 0 + GL_RGBA, // internal format + width_, + height_, + 0, // no border + GL_BGRA, // The GPU plugin read BGRA pixels + GL_UNSIGNED_INT_8_8_8_8_REV, + NULL); // No data, this call just reserves room. + } + } + + // If using TransportDIBs, the texture needs to be uploaded every frame. + if (transport_dib_.get() != NULL) { + void* pixel_memory = transport_dib_->memory(); + if (pixel_memory) { + glBindTexture(target, texture_); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // Needed for NPOT textures. + glTexSubImage2D(target, + 0, // mipmap level 0 + 0, // x-offset + 0, // y-offset + width_, + height_, + GL_BGRA, // The GPU plugin gave us BGRA pixels + GL_UNSIGNED_INT_8_8_8_8_REV, + pixel_memory); + } + } + + if (texture_) { + // TODO(kbr): convert this to use only OpenGL ES 2.0 functionality + glBindTexture(target, texture_); + glEnable(target); + glBegin(GL_TRIANGLE_STRIP); + // TODO(kbr): may need to pay attention to cutout rects. + int clipX = clipRect_.x(); + int clipY = clipRect_.y(); + int clipWidth = clipRect_.width(); + int clipHeight = clipRect_.height(); + int x = x_ + clipX; + int y = y_ + clipY; + glTexCoord2f(clipX, height_ - clipY); + glVertex3f(x, y, 0); + glTexCoord2f(clipX + clipWidth, height_ - clipY); + glVertex3f(x + clipWidth, y, 0); + glTexCoord2f(clipX, height_ - clipY - clipHeight); + glVertex3f(x, y + clipHeight, 0); + glTexCoord2f(clipX + clipWidth, height_ - clipY - clipHeight); + glVertex3f(x + clipWidth, y + clipHeight, 0); + glEnd(); + glDisable(target); + } +} + +void MacGPUPluginContainer::EnqueueTextureForDeletion( + MacGPUPluginContainerManager* manager) { + manager->EnqueueTextureForDeletion(texture_); + texture_ = 0; +} + diff --git a/chrome/browser/renderer_host/gpu_plugin_container_mac.h b/chrome/browser/renderer_host/gpu_plugin_container_mac.h new file mode 100644 index 0000000..b985147 --- /dev/null +++ b/chrome/browser/renderer_host/gpu_plugin_container_mac.h @@ -0,0 +1,114 @@ +// 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_BROWSER_RENDERER_HOST_GPU_PLUGIN_CONTAINER_MAC_H_ +#define CHROME_BROWSER_RENDERER_HOST_GPU_PLUGIN_CONTAINER_MAC_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" +#include "base/scoped_ptr.h" +#include "base/gfx/rect.h" +#include "chrome/common/transport_dib.h" + +namespace webkit_glue { +struct WebPluginGeometry; +} + +class MacGPUPluginContainerManager; + +class MacGPUPluginContainer { + public: + MacGPUPluginContainer(); + virtual ~MacGPUPluginContainer(); + + // Sets the backing store and size of this plugin container. There are two + // versions: the IOSurface version is used on systems where the IOSurface + // API is supported (Mac OS X 10.6 and later); the TransportDIB is used on + // Mac OS X 10.5 and earlier. + void SetSizeAndIOSurface(int32 width, + int32 height, + uint64 io_surface_identifier, + MacGPUPluginContainerManager* manager); + void SetSizeAndTransportDIB(int32 width, + int32 height, + TransportDIB::Handle transport_dib, + 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. + 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 TransportDIB which is used in pre-10.6 systems where the IOSurface + // API is not supported. This is a weak reference to the actual TransportDIB + // whic is owned by the GPU process. + scoped_ptr<TransportDIB> transport_dib_; + + // The width and height of the surface. + int32 width_; + int32 height_; + + // The clip rectangle, relative to the (x_, y_) origin. + gfx::Rect clipRect_; + + // 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 // CHROME_BROWSER_RENDERER_HOST_GPU_PLUGIN_CONTAINER_MAC_H_ + diff --git a/chrome/browser/renderer_host/gpu_plugin_container_manager_mac.cc b/chrome/browser/renderer_host/gpu_plugin_container_manager_mac.cc new file mode 100644 index 0000000..8eae393 --- /dev/null +++ b/chrome/browser/renderer_host/gpu_plugin_container_manager_mac.cc @@ -0,0 +1,100 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/renderer_host/gpu_plugin_container_manager_mac.h" + +#include "base/logging.h" +#include "chrome/browser/renderer_host/gpu_plugin_container_mac.h" +#include "webkit/glue/webplugin.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::SetSizeAndIOSurface( + gfx::PluginWindowHandle id, + int32 width, + int32 height, + uint64 io_surface_identifier) { + MacGPUPluginContainer* container = MapIDToContainer(id); + if (container) + container->SetSizeAndIOSurface(width, height, + io_surface_identifier, this); +} + +void MacGPUPluginContainerManager::SetSizeAndTransportDIB( + gfx::PluginWindowHandle id, + int32 width, + int32 height, + TransportDIB::Handle transport_dib) { + MacGPUPluginContainer* container = MapIDToContainer(id); + if (container) + container->SetSizeAndTransportDIB(width, height, + transport_dib, 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/chrome/browser/renderer_host/gpu_plugin_container_manager_mac.h b/chrome/browser/renderer_host/gpu_plugin_container_manager_mac.h new file mode 100644 index 0000000..89e8620 --- /dev/null +++ b/chrome/browser/renderer_host/gpu_plugin_container_manager_mac.h @@ -0,0 +1,78 @@ +// 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_BROWSER_RENDERER_HOST_GPU_PLUGIN_CONTAINER_MANAGER_MAC_H_ +#define CHROME_BROWSER_RENDERER_HOST_GPU_PLUGIN_CONTAINER_MANAGER_MAC_H_ + +#include <OpenGL/OpenGL.h> +#include <map> +#include <vector> + +#include "app/gfx/native_widget_types.h" +#include "base/basictypes.h" +#include "chrome/common/transport_dib.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. There are two + // versions: the IOSurface version is used on systems where the IOSurface + // API is supported (Mac OS X 10.6 and later); the TransportDIB is used on + // Mac OS X 10.5 and earlier. + void SetSizeAndIOSurface(gfx::PluginWindowHandle id, + int32 width, + int32 height, + uint64 io_surface_identifier); + void SetSizeAndTransportDIB(gfx::PluginWindowHandle id, + int32 width, + int32 height, + TransportDIB::Handle transport_dib); + + // 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 // CHROME_BROWSER_RENDERER_HOST_GPU_PLUGIN_CONTAINER_MANAGER_MAC_H_ + 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 c8e4078..6433653 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_mac.h +++ b/chrome/browser/renderer_host/render_widget_host_view_mac.h @@ -13,10 +13,10 @@ #include "base/task.h" #include "base/time.h" #include "chrome/browser/cocoa/base_view.h" +#include "chrome/browser/renderer_host/gpu_plugin_container_manager_mac.h" #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; diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index af3fcb8..6bb8d74 100755 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -1658,6 +1658,10 @@ 'browser/renderer_host/global_request_id.h', 'browser/renderer_host/gpu_view_host.cc', 'browser/renderer_host/gpu_view_host.h', + 'browser/renderer_host/gpu_plugin_container_mac.cc', + 'browser/renderer_host/gpu_plugin_container_mac.h', + 'browser/renderer_host/gpu_plugin_container_manager_mac.cc', + 'browser/renderer_host/gpu_plugin_container_manager_mac.h', 'browser/renderer_host/gtk_im_context_wrapper.cc', 'browser/renderer_host/gtk_im_context_wrapper.h', 'browser/renderer_host/gtk_key_bindings_handler.cc', |