diff options
author | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-11 00:25:22 +0000 |
---|---|---|
committer | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-11 00:25:22 +0000 |
commit | c7ebd253c9d06f1abeb44ca4acb0b26dd3752e7f (patch) | |
tree | 4d5b5faaba98606875ed296bf6bfea9b6d54098b /chrome/renderer | |
parent | 0dc78175ae33d022a8db10e8e010defe6ccc3623 (diff) | |
download | chromium_src-c7ebd253c9d06f1abeb44ca4acb0b26dd3752e7f.zip chromium_src-c7ebd253c9d06f1abeb44ca4acb0b26dd3752e7f.tar.gz chromium_src-c7ebd253c9d06f1abeb44ca4acb0b26dd3752e7f.tar.bz2 |
Rework painting to be something that will actually work. This allows plugins to
only paint portions of their backing store.
This also implements correct memory management on the chrome side. We can now
supply more than one backing store, and will delete them properly when requested
by the plugin.
TEST=none
BUG=none
Review URL: http://codereview.chromium.org/371093
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@31620 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/renderer')
-rw-r--r-- | chrome/renderer/webplugin_delegate_pepper.cc | 87 | ||||
-rw-r--r-- | chrome/renderer/webplugin_delegate_pepper.h | 19 |
2 files changed, 87 insertions, 19 deletions
diff --git a/chrome/renderer/webplugin_delegate_pepper.cc b/chrome/renderer/webplugin_delegate_pepper.cc index 1621406..b7ab0f5 100644 --- a/chrome/renderer/webplugin_delegate_pepper.cc +++ b/chrome/renderer/webplugin_delegate_pepper.cc @@ -130,13 +130,14 @@ void WebPluginDelegatePepper::UpdateGeometry( if (window_rect_ == window_rect) return; window_rect_ = window_rect; - uint32 buffer_size = window_rect.height() * - window_rect.width() * - kBytesPerPixel; - if (buffer_size_ < buffer_size) { - buffer_size_ = buffer_size; - plugin_buffer_ = TransportDIB::Create(buffer_size, ++next_buffer_id); - } + + // TODO(brettw) figure out how to tell the plugin that the size changed and it + // needs to repaint? + SkBitmap new_committed; + new_committed.setConfig(SkBitmap::kARGB_8888_Config, + window_rect_.width(), window_rect.height()); + new_committed.allocPixels(); + committed_bitmap_ = new_committed; if (!instance()) return; @@ -411,17 +412,25 @@ NPError WebPluginDelegatePepper::InitializeRenderContext( case NPRenderGraphicsRGBA: { int width = window_rect_.width(); int height = window_rect_.height(); - - plugin_canvas_.reset(plugin_buffer_->GetPlatformCanvas(width, height)); - if (!plugin_canvas_.get()) - return NPERR_GENERIC_ERROR; + uint32 buffer_size = width * height * kBytesPerPixel; + + // Allocate the transport DIB and the PlatformCanvas pointing to it. + scoped_ptr<OpenPaintContext> paint_context(new OpenPaintContext); + paint_context->transport_dib.reset( + TransportDIB::Create(buffer_size, ++next_buffer_id)); + if (!paint_context->transport_dib.get()) + return NPERR_OUT_OF_MEMORY_ERROR; + paint_context->canvas.reset( + paint_context->transport_dib->GetPlatformCanvas(width, height)); + if (!paint_context->canvas.get()) + return NPERR_OUT_OF_MEMORY_ERROR; // Note that we need to get the address out of the bitmap rather than // using plugin_buffer_->memory(). The memory() is when the bitmap data // has had "Map" called on it. For Windows, this is separate than making a // bitmap using the shared section. const SkBitmap& plugin_bitmap = - plugin_canvas_->getTopPlatformDevice().accessBitmap(true); + paint_context->canvas->getTopPlatformDevice().accessBitmap(true); SkAutoLockPixels locker(plugin_bitmap); // TODO(brettw) this theoretically shouldn't be necessary. But the @@ -429,8 +438,16 @@ NPError WebPluginDelegatePepper::InitializeRenderContext( // catch areas you didn't paint. plugin_bitmap.eraseARGB(0, 0, 0, 0); + // Save the canvas to the output context structure and save the + // OpenPaintContext for future reference. context->u.graphicsRgba.region = plugin_bitmap.getAddr32(0, 0); context->u.graphicsRgba.stride = width * kBytesPerPixel; + context->u.graphicsRgba.dirty.left = 0; + context->u.graphicsRgba.dirty.top = 0; + context->u.graphicsRgba.dirty.right = width; + context->u.graphicsRgba.dirty.bottom = height; + open_paint_contexts_[context->u.graphicsRgba.region] = + linked_ptr<OpenPaintContext>(paint_context.release()); return NPERR_NO_ERROR; } default: @@ -438,12 +455,48 @@ NPError WebPluginDelegatePepper::InitializeRenderContext( } } +NPError WebPluginDelegatePepper::DestroyRenderContext( + NPRenderContext* context) { + OpenPaintContextMap::iterator found = open_paint_contexts_.find( + context->u.graphicsRgba.region); + if (found == open_paint_contexts_.end()) + return NPERR_INVALID_PARAM; + + open_paint_contexts_.erase(found); + return NPERR_NO_ERROR; +} + NPError WebPluginDelegatePepper::FlushRenderContext(NPRenderContext* context) { - // TODO(brettw): we should have some kind of swapping of the canvases so we - // can double buffer while avoiding this deep copy. - if (!plugin_canvas_->getTopPlatformDevice().accessBitmap(false).copyTo( - &committed_bitmap_, SkBitmap::kARGB_8888_Config)) - return NPERR_OUT_OF_MEMORY_ERROR; + // Get the bitmap data associated with the incoming context. + OpenPaintContextMap::iterator found = open_paint_contexts_.find( + context->u.graphicsRgba.region); + if (found == open_paint_contexts_.end()) + return NPERR_INVALID_PARAM; + + OpenPaintContext* paint_context = found->second.get(); + + // Draw the bitmap to the backing store. + // + // TODO(brettw) we can optimize this in the case where the entire canvas is + // updated by actually taking ownership of the buffer and not telling the + // plugin we're done using it. This wat we can avoid the copy when the entire + // canvas has been updated. + SkIRect src_rect = { context->u.graphicsRgba.dirty.left, + context->u.graphicsRgba.dirty.top, + context->u.graphicsRgba.dirty.right, + context->u.graphicsRgba.dirty.bottom }; + SkRect dest_rect = { SkIntToScalar(context->u.graphicsRgba.dirty.left), + SkIntToScalar(context->u.graphicsRgba.dirty.top), + SkIntToScalar(context->u.graphicsRgba.dirty.right), + SkIntToScalar(context->u.graphicsRgba.dirty.bottom) }; + SkCanvas committed_canvas(committed_bitmap_); + + // We want to replace the contents of the bitmap rather than blend. + SkPaint paint; + paint.setXfermodeMode(SkXfermode::kSrc_Mode); + committed_canvas.drawBitmapRect( + paint_context->canvas->getTopPlatformDevice().accessBitmap(false), + &src_rect, dest_rect); committed_bitmap_.setIsOpaque(false); return NPERR_NO_ERROR; diff --git a/chrome/renderer/webplugin_delegate_pepper.h b/chrome/renderer/webplugin_delegate_pepper.h index caba02a..7e2f09b 100644 --- a/chrome/renderer/webplugin_delegate_pepper.h +++ b/chrome/renderer/webplugin_delegate_pepper.h @@ -7,12 +7,13 @@ #include "build/build_config.h" -#include <list> +#include <map> #include <string> #include <vector> #include "app/gfx/native_widget_types.h" #include "base/file_path.h" +#include "base/linked_ptr.h" #include "base/gfx/rect.h" #include "base/ref_counted.h" #include "base/scoped_ptr.h" @@ -97,6 +98,7 @@ class WebPluginDelegatePepper : public webkit_glue::WebPluginDelegate { // used for windowless plugins virtual NPError InitializeRenderContext(NPRenderType type, NPRenderContext* context); + virtual NPError DestroyRenderContext(NPRenderContext* context); virtual NPError FlushRenderContext(NPRenderContext* context); virtual NPError OpenFileInSandbox(const char* file_name, void** handle); @@ -126,9 +128,22 @@ class WebPluginDelegatePepper : public webkit_glue::WebPluginDelegate { size_t buffer_size_; TransportDIB* plugin_buffer_; static uint32 next_buffer_id; - scoped_ptr<skia::PlatformCanvas> plugin_canvas_; SkBitmap committed_bitmap_; + // Lists all contexts currently open for painting. These are ones requested by + // the plugin but not destroyed by it yet. The source pointer is the raw + // pixels. We use this to look up the corresponding transport DIB when the + // plugin tells us to flush or destroy it. + struct OpenPaintContext { + scoped_ptr<TransportDIB> transport_dib; + + // The canvas associated with the transport DIB, containing the mapped + // memory of the image. + scoped_ptr<skia::PlatformCanvas> canvas; + }; + typedef std::map< void*, linked_ptr<OpenPaintContext> > OpenPaintContextMap; + OpenPaintContextMap open_paint_contexts_; + // The url with which the plugin was instantiated. std::string plugin_url_; |