diff options
-rw-r--r-- | chrome/renderer/pepper_plugin_delegate_impl.cc | 20 | ||||
-rw-r--r-- | chrome/renderer/pepper_plugin_delegate_impl.h | 14 | ||||
-rw-r--r-- | chrome/renderer/render_view.cc | 9 | ||||
-rw-r--r-- | chrome/renderer/render_view.h | 5 | ||||
-rw-r--r-- | chrome/renderer/render_widget.cc | 33 | ||||
-rw-r--r-- | chrome/renderer/render_widget.h | 15 | ||||
-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 | 28 | ||||
-rw-r--r-- | webkit/glue/plugins/pepper_plugin_instance.h | 17 | ||||
-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, 247 insertions, 8 deletions
diff --git a/chrome/renderer/pepper_plugin_delegate_impl.cc b/chrome/renderer/pepper_plugin_delegate_impl.cc index 7ca9d4e..31b89ff 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,22 @@ void PepperPluginDelegateImpl::ViewFlushedPaint() { } } +bool PepperPluginDelegateImpl::GetBitmapForOptimizedPluginPaint( + const gfx::Rect& paint_bounds, + TransportDIB** dib, + gfx::Rect* location, + gfx::Rect* clip) { + for (std::set<pepper::PluginInstance*>::iterator i = + active_instances_.begin(); + i != active_instances_.end(); ++i) { + pepper::PluginInstance* instance = *i; + if (instance->GetBitmapForOptimizedPluginPaint( + paint_bounds, dib, location, clip)) + 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 a5808d5..8bacb44 100644 --- a/chrome/renderer/pepper_plugin_delegate_impl.h +++ b/chrome/renderer/pepper_plugin_delegate_impl.h @@ -19,6 +19,10 @@ class FilePath; class RenderView; +namespace gfx { +class Rect; +} + namespace pepper { class FileIO; class PluginInstance; @@ -29,6 +33,8 @@ class WebFileChooserCompletion; struct WebFileChooserParams; } +class TransportDIB; + class PepperPluginDelegateImpl : public pepper::PluginDelegate, public base::SupportsWeakPtr<PepperPluginDelegateImpl> { @@ -41,6 +47,14 @@ 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( + const gfx::Rect& paint_bounds, + TransportDIB** dib, + gfx::Rect* location, + gfx::Rect* clip); + // 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 9666b67..98fa378 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -4728,6 +4728,15 @@ void RenderView::DidFlushPaint() { } } +bool RenderView::GetBitmapForOptimizedPluginPaint( + const gfx::Rect& paint_bounds, + TransportDIB** dib, + gfx::Rect* location, + gfx::Rect* clip) { + return pepper_delegate_.GetBitmapForOptimizedPluginPaint( + paint_bounds, dib, location, clip); +} + void RenderView::OnClearFocusedNode() { if (webview()) webview()->clearFocusedNode(); diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h index f0dad4d4..f267de6 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -619,6 +619,11 @@ class RenderView : public RenderWidget, const gfx::Rect& resizer_rect); virtual void DidInitiatePaint(); virtual void DidFlushPaint(); + virtual bool GetBitmapForOptimizedPluginPaint( + const gfx::Rect& paint_bounds, + TransportDIB** dib, + gfx::Rect* location, + gfx::Rect* clip); 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..f5a7ebe 100644 --- a/chrome/renderer/render_widget.cc +++ b/chrome/renderer/render_widget.cc @@ -505,11 +505,24 @@ 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::Id(); + TransportDIB* dib = NULL; std::vector<gfx::Rect> copy_rects; - if (!is_gpu_rendering_active_) { + gfx::Rect optimized_copy_rect, optimized_copy_location; + if (update.scroll_rect.IsEmpty() && + !is_gpu_rendering_active_ && + GetBitmapForOptimizedPluginPaint(bounds, &dib, &optimized_copy_location, + &optimized_copy_rect)) { + bounds = optimized_copy_location; + copy_rects.push_back(optimized_copy_rect); + 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 +551,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 +561,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 +903,15 @@ void RenderWidget::OnSetTextDirection(WebTextDirection direction) { webwidget_->setTextDirection(direction); } +bool RenderWidget::GetBitmapForOptimizedPluginPaint( + const gfx::Rect& paint_bounds, + TransportDIB** dib, + gfx::Rect* location, + gfx::Rect* clip) { + // 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 6d80b62..e1dacf3 100644 --- a/chrome/renderer/render_widget.h +++ b/chrome/renderer/render_widget.h @@ -201,6 +201,21 @@ class RenderWidget : public IPC::Channel::Listener, virtual void DidInitiatePaint() {} virtual void DidFlushPaint() {} + // Detects if a suitable opaque plugin covers the given paint bounds with no + // compositing necessary. + // + // Returns true if the paint can be handled by just blitting the plugin + // bitmap. In this case, the location, clipping, and ID of the backing store + // will be filled into the given output parameters. + // + // 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( + const gfx::Rect& paint_bounds, + TransportDIB** dib, + gfx::Rect* location, + gfx::Rect* clip); + // 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 63ce5c3..b4ccd89 100644 --- a/webkit/glue/plugins/pepper_plugin_instance.cc +++ b/webkit/glue/plugins/pepper_plugin_instance.cc @@ -249,6 +249,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); @@ -518,6 +519,33 @@ void PluginInstance::ViewFlushedPaint() { bound_graphics_2d_->ViewFlushedPaint(); } +bool PluginInstance::GetBitmapForOptimizedPluginPaint( + const gfx::Rect& paint_bounds, + TransportDIB** dib, + gfx::Rect* location, + gfx::Rect* clip) { + 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())); + gfx::Rect plugin_paint_rect = plugin_backing_store_rect.Intersect(clip_); + if (!plugin_paint_rect.Contains(paint_bounds)) + return false; + + *dib = image_data->platform_image()->GetTransportDIB(); + *location = plugin_backing_store_rect; + *clip = clip_; + 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 902d95e..4eb956f 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. @@ -120,6 +123,16 @@ 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 location, clipping, and ID of the backing store + // will be filled into the given output parameters. + bool GetBitmapForOptimizedPluginPaint( + const gfx::Rect& paint_bounds, + TransportDIB** dib, + gfx::Rect* dib_bounds, + gfx::Rect* clip); + string16 GetSelectedText(bool html); void Zoom(float factor, bool text_only); bool StartFind(const string16& search_text, @@ -232,6 +245,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', |