diff options
-rw-r--r-- | chrome/renderer/pepper_plugin_delegate_impl.cc | 17 | ||||
-rw-r--r-- | chrome/renderer/pepper_plugin_delegate_impl.h | 6 | ||||
-rw-r--r-- | chrome/renderer/render_view.cc | 5 | ||||
-rw-r--r-- | chrome/renderer/render_view.h | 2 | ||||
-rw-r--r-- | chrome/renderer/render_widget.cc | 27 | ||||
-rw-r--r-- | chrome/renderer/render_widget.h | 13 | ||||
-rw-r--r-- | webkit/glue/plugins/pepper_graphics_2d.cc | 18 | ||||
-rw-r--r-- | webkit/glue/plugins/pepper_graphics_2d.h | 6 | ||||
-rw-r--r-- | webkit/glue/plugins/pepper_image_data.h | 4 | ||||
-rw-r--r-- | webkit/glue/plugins/pepper_plugin_delegate.h | 4 | ||||
-rw-r--r-- | webkit/glue/plugins/pepper_plugin_instance.cc | 24 | ||||
-rw-r--r-- | webkit/glue/plugins/pepper_plugin_instance.h | 14 | ||||
-rw-r--r-- | webkit/glue/plugins/pepper_plugin_module.cc | 4 | ||||
-rw-r--r-- | webkit/glue/plugins/pepper_private2.cc | 32 | ||||
-rw-r--r-- | webkit/glue/plugins/pepper_private2.h | 23 | ||||
-rw-r--r-- | webkit/glue/plugins/ppb_private2.h | 21 | ||||
-rw-r--r-- | webkit/glue/webkit_glue.gypi | 2 |
17 files changed, 214 insertions, 8 deletions
diff --git a/chrome/renderer/pepper_plugin_delegate_impl.cc b/chrome/renderer/pepper_plugin_delegate_impl.cc index 3a866af..5f73ea7 100644 --- a/chrome/renderer/pepper_plugin_delegate_impl.cc +++ b/chrome/renderer/pepper_plugin_delegate_impl.cc @@ -53,6 +53,10 @@ class PlatformImage2DImpl : public pepper::PluginDelegate::PlatformImage2D { return reinterpret_cast<intptr_t>(dib_.get()); } + virtual TransportDIB* GetTransportDIB() const { + return dib_.get(); + } + private: int width_; int height_; @@ -520,6 +524,19 @@ void PepperPluginDelegateImpl::ViewFlushedPaint() { } } +bool PepperPluginDelegateImpl::GetBitmapForOptimizedPluginPaint( + gfx::Rect* bounds, + TransportDIB** dib) { + for (std::set<pepper::PluginInstance*>::iterator i = + active_instances_.begin(); + i != active_instances_.end(); ++i) { + pepper::PluginInstance* instance = *i; + if (instance->GetBitmapForOptimizedPluginPaint(bounds, dib)) + return true; + } + return false; +} + void PepperPluginDelegateImpl::InstanceCreated( pepper::PluginInstance* instance) { active_instances_.insert(instance); diff --git a/chrome/renderer/pepper_plugin_delegate_impl.h b/chrome/renderer/pepper_plugin_delegate_impl.h index 19f08b1c..0119148 100644 --- a/chrome/renderer/pepper_plugin_delegate_impl.h +++ b/chrome/renderer/pepper_plugin_delegate_impl.h @@ -29,6 +29,8 @@ class WebFileChooserCompletion; struct WebFileChooserParams; } +class TransportDIB; + class PepperPluginDelegateImpl : public pepper::PluginDelegate, public base::SupportsWeakPtr<PepperPluginDelegateImpl> { @@ -41,6 +43,10 @@ class PepperPluginDelegateImpl void ViewInitiatedPaint(); void ViewFlushedPaint(); + // Called by RenderView to implement the corresponding function in its base + // class RenderWidget (see that for more). + bool GetBitmapForOptimizedPluginPaint(gfx::Rect* bounds, TransportDIB** dib); + // Called by RenderView when ViewMsg_AsyncOpenFile_ACK. void OnAsyncFileOpened(base::PlatformFileError error_code, base::PlatformFile file, diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index ae155e8..98cc445 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -4717,6 +4717,11 @@ void RenderView::DidFlushPaint() { } } +bool RenderView::GetBitmapForOptimizedPluginPaint(gfx::Rect* bounds, + TransportDIB** dib) { + return pepper_delegate_.GetBitmapForOptimizedPluginPaint(bounds, dib); +} + void RenderView::OnClearFocusedNode() { if (webview()) webview()->clearFocusedNode(); diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h index 01f9655..1a733fe 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -608,6 +608,8 @@ class RenderView : public RenderWidget, const gfx::Rect& resizer_rect); virtual void DidInitiatePaint(); virtual void DidFlushPaint(); + virtual bool GetBitmapForOptimizedPluginPaint(gfx::Rect* bounds, + TransportDIB** dib); virtual void DidHandleKeyEvent(); virtual void DidHandleMouseEvent(const WebKit::WebMouseEvent& event); virtual void OnSetFocus(bool enable); diff --git a/chrome/renderer/render_widget.cc b/chrome/renderer/render_widget.cc index 3252097..95346c3 100644 --- a/chrome/renderer/render_widget.cc +++ b/chrome/renderer/render_widget.cc @@ -505,11 +505,21 @@ void RenderWidget::DoDeferredUpdate() { gfx::Rect scroll_damage = update.GetScrollDamage(); gfx::Rect bounds = update.GetPaintBounds().Union(scroll_damage); + // A plugin may be able to do an optimized paint. First check this, in which + // case we can skip all of the bitmap generation and regular paint code. + TransportDIB::Id dib_id; + TransportDIB* dib = NULL; std::vector<gfx::Rect> copy_rects; - if (!is_gpu_rendering_active_) { + if (update.scroll_rect.IsEmpty() && + !is_gpu_rendering_active_ && + GetBitmapForOptimizedPluginPaint(&bounds, &dib)) { + copy_rects.push_back(bounds); + dib_id = dib->id(); + } else if (!is_gpu_rendering_active_) { // Compute a buffer for painting and cache it. - scoped_ptr<skia::PlatformCanvas> canvas - (RenderProcess::current()->GetDrawingCanvas(¤t_paint_buf_, bounds)); + scoped_ptr<skia::PlatformCanvas> canvas( + RenderProcess::current()->GetDrawingCanvas(¤t_paint_buf_, + bounds)); if (!canvas.get()) { NOTREACHED(); return; @@ -538,6 +548,8 @@ void RenderWidget::DoDeferredUpdate() { for (size_t i = 0; i < copy_rects.size(); ++i) PaintRect(copy_rects[i], bounds.origin(), canvas.get()); + + dib_id = current_paint_buf_->id(); } else { // Accelerated compositing path // Begin painting. bool finish = next_paint_is_resize_ack(); @@ -546,8 +558,7 @@ void RenderWidget::DoDeferredUpdate() { // sending an ack to browser process that the paint is complete... ViewHostMsg_UpdateRect_Params params; - params.bitmap = - current_paint_buf_ ? current_paint_buf_->id() : TransportDIB::Id(); + params.bitmap = dib_id; params.bitmap_rect = bounds; params.dx = update.scroll_delta.x(); params.dy = update.scroll_delta.y(); @@ -889,6 +900,12 @@ void RenderWidget::OnSetTextDirection(WebTextDirection direction) { webwidget_->setTextDirection(direction); } +bool RenderWidget::GetBitmapForOptimizedPluginPaint(gfx::Rect* bounds, + TransportDIB** dib) { + // Normal RenderWidgets don't support optimized plugin painting. + return false; +} + void RenderWidget::SetHidden(bool hidden) { if (is_hidden_ == hidden) return; diff --git a/chrome/renderer/render_widget.h b/chrome/renderer/render_widget.h index 7f9e247..61abdee 100644 --- a/chrome/renderer/render_widget.h +++ b/chrome/renderer/render_widget.h @@ -197,6 +197,19 @@ class RenderWidget : public IPC::Channel::Listener, virtual void DidInitiatePaint() {} virtual void DidFlushPaint() {} + // Detects if a suitable opaque plugin covers |*bounds| with no compositing + // necessary. + // + // Returns true if the paint can be handled by just blitting the plugin + // bitmap. In this case, the |*dib| parameter will contain the TransportDIB + // and the |*bounds| will be updated to contain the rect on the page that + // contains the given DIB (this may go off the visible page). + // + // A return value of false means optimized painting can not be used and we + // should continue with the normal painting code path. + virtual bool GetBitmapForOptimizedPluginPaint(gfx::Rect* bounds, + TransportDIB** dib); + // Sets the "hidden" state of this widget. All accesses to is_hidden_ should // use this method so that we can properly inform the RenderThread of our // state. diff --git a/webkit/glue/plugins/pepper_graphics_2d.cc b/webkit/glue/plugins/pepper_graphics_2d.cc index 049c17d..5011f87 100644 --- a/webkit/glue/plugins/pepper_graphics_2d.cc +++ b/webkit/glue/plugins/pepper_graphics_2d.cc @@ -174,7 +174,8 @@ Graphics2D::Graphics2D(PluginModule* module) : Resource(module), bound_instance_(NULL), flushed_any_data_(false), - offscreen_flush_pending_(false) { + offscreen_flush_pending_(false), + is_always_opaque_(false) { } Graphics2D::~Graphics2D() { @@ -193,7 +194,7 @@ bool Graphics2D::Init(int width, int height, bool is_always_opaque) { image_data_ = NULL; return false; } - + is_always_opaque_ = is_always_opaque; return true; } @@ -445,13 +446,24 @@ void Graphics2D::Paint(WebKit::WebCanvas* canvas, bounds.size.width = backing_bitmap.width(); bounds.size.height = backing_bitmap.height(); + // TODO(brettw) bug 56673: do a direct memcpy instead of going through CG + // if the is_always_opaque_ flag is set. + CGContextDrawImage(canvas, bounds, image); CGContextRestoreGState(canvas); #else + SkPaint paint; + if (is_always_opaque_) { + // When we know the device is opaque, we can disable blending for slightly + // more optimized painting. + paint.setXfermodeMode(SkXfermode::kSrc_Mode); + } + gfx::Point origin(plugin_rect.origin().x(), plugin_rect.origin().y()); canvas->drawBitmap(backing_bitmap, SkIntToScalar(plugin_rect.origin().x()), - SkIntToScalar(plugin_rect.origin().y())); + SkIntToScalar(plugin_rect.origin().y()), + &paint); #endif } diff --git a/webkit/glue/plugins/pepper_graphics_2d.h b/webkit/glue/plugins/pepper_graphics_2d.h index c3fad68..3af84ded 100644 --- a/webkit/glue/plugins/pepper_graphics_2d.h +++ b/webkit/glue/plugins/pepper_graphics_2d.h @@ -36,6 +36,8 @@ class Graphics2D : public Resource { bool Init(int width, int height, bool is_always_opaque); + bool is_always_opaque() const { return is_always_opaque_; } + // Resource override. virtual Graphics2D* AsGraphics2D() { return this; } @@ -166,6 +168,10 @@ class Graphics2D : public Resource { // enforce the "only one pending flush at a time" constraint in the API. bool offscreen_flush_pending_; + // Set to true if the plugin declares that this device will always be opaque. + // This allows us to do more optimized painting in some cases. + bool is_always_opaque_; + DISALLOW_COPY_AND_ASSIGN(Graphics2D); }; diff --git a/webkit/glue/plugins/pepper_image_data.h b/webkit/glue/plugins/pepper_image_data.h index c5937b2..04d769c 100644 --- a/webkit/glue/plugins/pepper_image_data.h +++ b/webkit/glue/plugins/pepper_image_data.h @@ -37,6 +37,10 @@ class ImageData : public Resource { // invalid or not mapped. See ImageDataAutoMapper below. bool is_mapped() const { return !!mapped_canvas_.get(); } + PluginDelegate::PlatformImage2D* platform_image() const { + return platform_image_.get(); + } + // Returns a pointer to the interface implementing PPB_ImageData that is // exposed to the plugin. static const PPB_ImageData* GetInterface(); diff --git a/webkit/glue/plugins/pepper_plugin_delegate.h b/webkit/glue/plugins/pepper_plugin_delegate.h index d650fa9..3bd8897 100644 --- a/webkit/glue/plugins/pepper_plugin_delegate.h +++ b/webkit/glue/plugins/pepper_plugin_delegate.h @@ -44,6 +44,8 @@ struct PP_VideoCompressedDataBuffer_Dev; struct PP_VideoDecoderConfig_Dev; struct PP_VideoUncompressedDataBuffer_Dev; +class TransportDIB; + namespace pepper { class FileIO; @@ -67,6 +69,8 @@ class PluginDelegate { // this image. This is used by NativeClient to send the image to the // out-of-process plugin. Returns 0 on failure. virtual intptr_t GetSharedMemoryHandle() const = 0; + + virtual TransportDIB* GetTransportDIB() const = 0; }; class PlatformContext3D { diff --git a/webkit/glue/plugins/pepper_plugin_instance.cc b/webkit/glue/plugins/pepper_plugin_instance.cc index b246872..ae0cdcc 100644 --- a/webkit/glue/plugins/pepper_plugin_instance.cc +++ b/webkit/glue/plugins/pepper_plugin_instance.cc @@ -247,6 +247,7 @@ PluginInstance::PluginInstance(PluginDelegate* delegate, #endif // defined (OS_LINUX) plugin_print_interface_(NULL), plugin_graphics_3d_interface_(NULL), + always_on_top_(false), fullscreen_container_(NULL) { memset(¤t_print_settings_, 0, sizeof(current_print_settings_)); DCHECK(delegate); @@ -500,6 +501,29 @@ void PluginInstance::ViewFlushedPaint() { bound_graphics_2d_->ViewFlushedPaint(); } +bool PluginInstance::GetBitmapForOptimizedPluginPaint(gfx::Rect* bounds, + TransportDIB** dib) { + if (!always_on_top_) + return false; + if (!bound_graphics_2d_ || !bound_graphics_2d_->is_always_opaque()) + return false; + + // We specifically want to compare against the area covered by the backing + // store when seeing if we cover the given paint bounds, since the backing + // store could be smaller than the declared plugin area. + ImageData* image_data = bound_graphics_2d_->image_data(); + gfx::Rect plugin_backing_store_rect(position_.origin(), + gfx::Size(image_data->width(), + image_data->height())); + if (!plugin_backing_store_rect.Contains(*bounds)) + return false; + + // TODO(brettw) implement detection for always-on-top. + *bounds = plugin_backing_store_rect; + *dib = image_data->platform_image()->GetTransportDIB(); + return true; +} + string16 PluginInstance::GetSelectedText(bool html) { PP_Var rv = instance_interface_->GetSelectedText(GetPPInstance(), html); scoped_refptr<StringVar> string(StringVar::FromPPVar(rv)); diff --git a/webkit/glue/plugins/pepper_plugin_instance.h b/webkit/glue/plugins/pepper_plugin_instance.h index 0ed6ee6..8837193 100644 --- a/webkit/glue/plugins/pepper_plugin_instance.h +++ b/webkit/glue/plugins/pepper_plugin_instance.h @@ -30,6 +30,7 @@ struct PPP_Instance; struct PPP_Zoom_Dev; class SkBitmap; +class TransportDIB; namespace gfx { class Rect; @@ -77,6 +78,8 @@ class PluginInstance : public base::RefCounted<PluginInstance> { int find_identifier() const { return find_identifier_; } + void set_always_on_top(bool on_top) { always_on_top_ = on_top; } + PP_Instance GetPPInstance(); // Paints the current backing store to the web page. @@ -117,6 +120,13 @@ class PluginInstance : public base::RefCounted<PluginInstance> { void ViewInitiatedPaint(); void ViewFlushedPaint(); + // If this plugin can be painted merely by copying the backing store to the + // screen, and the plugin bounds encloses the given paint bounds, returns + // true. In this case, the bounds will be updated to enclose the area covering + // the backing store of the plugin, and the ID of the backing store will be + // placed in |*dib|. + bool GetBitmapForOptimizedPluginPaint(gfx::Rect* bounds, TransportDIB** dib); + string16 GetSelectedText(bool html); void Zoom(float factor, bool text_only); bool StartFind(const string16& search_text, @@ -218,6 +228,10 @@ class PluginInstance : public base::RefCounted<PluginInstance> { // Containes the cursor if it's set by the plugin. scoped_ptr<WebKit::WebCursorInfo> cursor_; + // Set to true if this plugin thinks it will always be on top. This allows us + // to use a more optimized painting path in some cases. + bool always_on_top_; + // Plugin container for fullscreen mode. NULL if not in fullscreen mode. FullscreenContainer* fullscreen_container_; diff --git a/webkit/glue/plugins/pepper_plugin_module.cc b/webkit/glue/plugins/pepper_plugin_module.cc index 7acf06239..e43735f 100644 --- a/webkit/glue/plugins/pepper_plugin_module.cc +++ b/webkit/glue/plugins/pepper_plugin_module.cc @@ -59,6 +59,7 @@ #include "webkit/glue/plugins/pepper_plugin_instance.h" #include "webkit/glue/plugins/pepper_plugin_object.h" #include "webkit/glue/plugins/pepper_private.h" +#include "webkit/glue/plugins/pepper_private2.h" #include "webkit/glue/plugins/pepper_resource_tracker.h" #include "webkit/glue/plugins/pepper_scrollbar.h" #include "webkit/glue/plugins/pepper_transport.h" @@ -70,6 +71,7 @@ #include "webkit/glue/plugins/pepper_video_decoder.h" #include "webkit/glue/plugins/pepper_widget.h" #include "webkit/glue/plugins/ppb_private.h" +#include "webkit/glue/plugins/ppb_private2.h" #ifdef ENABLE_GPU #include "webkit/glue/plugins/pepper_graphics_3d.h" @@ -257,6 +259,8 @@ const void* GetInterface(const char* name) { return UrlUtil::GetInterface(); if (strcmp(name, PPB_PRIVATE_INTERFACE) == 0) return Private::GetInterface(); + if (strcmp(name, PPB_PRIVATE2_INTERFACE) == 0) + return Private2::GetInterface(); if (strcmp(name, PPB_FILECHOOSER_DEV_INTERFACE) == 0) return FileChooser::GetInterface(); if (strcmp(name, PPB_VIDEODECODER_DEV_INTERFACE) == 0) diff --git a/webkit/glue/plugins/pepper_private2.cc b/webkit/glue/plugins/pepper_private2.cc new file mode 100644 index 0000000..9a740aa --- /dev/null +++ b/webkit/glue/plugins/pepper_private2.cc @@ -0,0 +1,32 @@ +// 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/pepper_private2.h" + +#include "webkit/glue/plugins/pepper_plugin_instance.h" +#include "webkit/glue/plugins/ppb_private2.h" + +namespace pepper { + +namespace { + +void SetInstanceAlwaysOnTop(PP_Instance pp_instance, bool on_top) { + PluginInstance* instance = PluginInstance::FromPPInstance(pp_instance); + if (!instance) + return; + instance->set_always_on_top(on_top); +} + +const PPB_Private2 ppb_private2 = { + &SetInstanceAlwaysOnTop +}; + +} // namespace + +// static +const PPB_Private2* Private2::GetInterface() { + return &ppb_private2; +} + +} // namespace pepper diff --git a/webkit/glue/plugins/pepper_private2.h b/webkit/glue/plugins/pepper_private2.h new file mode 100644 index 0000000..492669a --- /dev/null +++ b/webkit/glue/plugins/pepper_private2.h @@ -0,0 +1,23 @@ +// 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_PEPPER_PRIVATE2_H_ +#define WEBKIT_GLUE_PLUGINS_PEPPER_PRIVATE2_H_ + +#include "webkit/glue/plugins/pepper_resource.h" + +struct PPB_Private2; + +namespace pepper { + +class Private2 { + public: + // Returns a pointer to the interface implementing PPB_Private2 that is + // exposed to the plugin. + static const PPB_Private2* GetInterface(); +}; + +} // namespace pepper + +#endif // WEBKIT_GLUE_PLUGINS_PEPPER_PRIVATE2_H_ diff --git a/webkit/glue/plugins/ppb_private2.h b/webkit/glue/plugins/ppb_private2.h new file mode 100644 index 0000000..ca45471 --- /dev/null +++ b/webkit/glue/plugins/ppb_private2.h @@ -0,0 +1,21 @@ +// 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_PPB_PRIVATE2_H_ +#define WEBKIT_GLUE_PLUGINS_PPB_PRIVATE2_H_ + +#include "third_party/ppapi/c/pp_instance.h" +#include "third_party/ppapi/c/pp_module.h" +#include "third_party/ppapi/c/pp_var.h" + +#define PPB_PRIVATE2_INTERFACE "PPB_Private2;1" + +struct PPB_Private2 { + // Sets or clears the rendering hint that the given plugin instance is always + // on top of page content. Somewhat more optimized painting can be used in + // this case. + void (*SetInstanceAlwaysOnTop)(PP_Instance instance, bool on_top); +}; + +#endif // WEBKIT_GLUE_PLUGINS_PPB_PRIVATE2_H_ diff --git a/webkit/glue/webkit_glue.gypi b/webkit/glue/webkit_glue.gypi index e27f297..354b2d0 100644 --- a/webkit/glue/webkit_glue.gypi +++ b/webkit/glue/webkit_glue.gypi @@ -222,6 +222,8 @@ 'plugins/pepper_plugin_object.h', 'plugins/pepper_private.cc', 'plugins/pepper_private.h', + 'plugins/pepper_private2.cc', + 'plugins/pepper_private2.h', 'plugins/pepper_resource_tracker.cc', 'plugins/pepper_resource_tracker.h', 'plugins/pepper_resource.cc', |