diff options
author | tschmelcher@chromium.org <tschmelcher@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-25 22:13:52 +0000 |
---|---|---|
committer | tschmelcher@chromium.org <tschmelcher@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-25 22:13:52 +0000 |
commit | 9cf755682fcff0aa79e64c6f4fcb7ced80547d67 (patch) | |
tree | 227975248d1e781ac949dcde1a2291c11919d838 /content/plugin | |
parent | b8fede4e01b906a65ca9eb816e2cab0694810270 (diff) | |
download | chromium_src-9cf755682fcff0aa79e64c6f4fcb7ced80547d67.zip chromium_src-9cf755682fcff0aa79e64c6f4fcb7ced80547d67.tar.gz chromium_src-9cf755682fcff0aa79e64c6f4fcb7ced80547d67.tar.bz2 |
Avoid double-buffering windowless plugins and instead use buffer flipping when feasible. This can significantly reduce the CPU usage of pages that host windowless plugins (down by ~15% absolute CPU usage on my old MacBookPro, or about a 40% relative decrease).
Also simplify the OS X code for managing TransportDIBs by creating them in uncached mode and transfering the FileDescriptors using dup+auto-close.
TEST=(OS X 10.5) Google voice and video chat (O3D), YouTube, www.dkmsoftware.com/Yubotu.htm, and trailers.apple.com, incl. with violent resizing, and analyzed perf with Shark; (OS X 10.5, OS X 10.6, Linux, Windows) http://www.communitymx.com/content/source/E5141/wmodeopaque.htm, http://www.communitymx.com/content/source/E5141/wmodetrans.htm, http://www.communitymx.com/content/source/E5141/wmodenone.htm, hand-crafted perf test using Flash with wmode=opaque, analyzed perf with Activity Monitor / top / Process Explorer, verified in the debugger that buffer flips do not cause NPP_SetWindow calls
BUG=none
Review URL: http://codereview.chromium.org/7171024
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@93970 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/plugin')
-rw-r--r-- | content/plugin/webplugin_delegate_stub.cc | 10 | ||||
-rw-r--r-- | content/plugin/webplugin_proxy.cc | 340 | ||||
-rw-r--r-- | content/plugin/webplugin_proxy.h | 80 |
3 files changed, 270 insertions, 160 deletions
diff --git a/content/plugin/webplugin_delegate_stub.cc b/content/plugin/webplugin_delegate_stub.cc index 00987b2..87e8fda 100644 --- a/content/plugin/webplugin_delegate_stub.cc +++ b/content/plugin/webplugin_delegate_stub.cc @@ -266,13 +266,9 @@ void WebPluginDelegateStub::OnUpdateGeometry( const PluginMsg_UpdateGeometry_Param& param) { webplugin_->UpdateGeometry( param.window_rect, param.clip_rect, - param.windowless_buffer, param.background_buffer, - param.transparent -#if defined(OS_MACOSX) - , - param.ack_key -#endif - ); + param.windowless_buffer0, param.windowless_buffer1, + param.windowless_buffer_index, param.background_buffer, + param.transparent); } void WebPluginDelegateStub::OnGetPluginScriptableObject(int* route_id) { diff --git a/content/plugin/webplugin_proxy.cc b/content/plugin/webplugin_proxy.cc index 84d6d0d..a54f73a 100644 --- a/content/plugin/webplugin_proxy.cc +++ b/content/plugin/webplugin_proxy.cc @@ -60,33 +60,37 @@ WebPluginProxy::WebPluginProxy( containing_window_(containing_window), page_url_(page_url), transparent_(false), + windowless_buffer_index_(0), host_render_view_routing_id_(host_render_view_routing_id), ALLOW_THIS_IN_INITIALIZER_LIST(runnable_method_factory_(this)) { #if defined(USE_X11) - windowless_shm_pixmap_ = None; - use_shm_pixmap_ = false; - - // If the X server supports SHM pixmaps - // and the color depth and masks match, - // then consider using SHM pixmaps for windowless plugin painting. - Display* display = ui::GetXDisplay(); - if (ui::QuerySharedMemorySupport(display) == ui::SHARED_MEMORY_PIXMAP && - ui::BitsPerPixelForPixmapDepth( - display, DefaultDepth(display, 0)) == 32) { - Visual* vis = DefaultVisual(display, 0); - - if (vis->red_mask == 0xff0000 && - vis->green_mask == 0xff00 && - vis->blue_mask == 0xff) - use_shm_pixmap_ = true; - } + windowless_shm_pixmaps_[0] = None; + windowless_shm_pixmaps_[1] = None; + use_shm_pixmap_ = false; + + // If the X server supports SHM pixmaps + // and the color depth and masks match, + // then consider using SHM pixmaps for windowless plugin painting. + Display* display = ui::GetXDisplay(); + if (ui::QuerySharedMemorySupport(display) == ui::SHARED_MEMORY_PIXMAP && + ui::BitsPerPixelForPixmapDepth( + display, DefaultDepth(display, 0)) == 32) { + Visual* vis = DefaultVisual(display, 0); + + if (vis->red_mask == 0xff0000 && + vis->green_mask == 0xff00 && + vis->blue_mask == 0xff) + use_shm_pixmap_ = true; + } #endif } WebPluginProxy::~WebPluginProxy() { #if defined(USE_X11) - if (windowless_shm_pixmap_ != None) - XFreePixmap(ui::GetXDisplay(), windowless_shm_pixmap_); + if (windowless_shm_pixmaps_[0] != None) + XFreePixmap(ui::GetXDisplay(), windowless_shm_pixmaps_[0]); + if (windowless_shm_pixmaps_[1] != None) + XFreePixmap(ui::GetXDisplay(), windowless_shm_pixmaps_[1]); #endif #if defined(OS_MACOSX) @@ -159,7 +163,7 @@ void WebPluginProxy::InvalidateRect(const gfx::Rect& rect) { #if defined(OS_MACOSX) // If this is a Core Animation plugin, all we need to do is inform the // delegate. - if (!windowless_context_.get()) { + if (!windowless_context()) { delegate_->PluginDidInvalidate(); return; } @@ -328,10 +332,10 @@ void WebPluginProxy::HandleURLRequest(const char* url, void WebPluginProxy::Paint(const gfx::Rect& rect) { #if defined(OS_MACOSX) - if (!windowless_context_.get()) + if (!windowless_context()) return; #else - if (!windowless_canvas_.get()) + if (!windowless_canvas()) return; #endif @@ -340,13 +344,17 @@ void WebPluginProxy::Paint(const gfx::Rect& rect) { gfx::Rect offset_rect = rect; offset_rect.Offset(delegate_->GetRect().origin()); #if defined(OS_MACOSX) - CGContextSaveGState(windowless_context_); - // It is possible for windowless_context_ to change during plugin painting + CGContextSaveGState(windowless_context()); + // It is possible for windowless_contexts_ to change during plugin painting // (since the plugin can make a synchronous call during paint event handling), - // in which case we don't want to try to restore it later. Not an owning ref + // in which case we don't want to try to restore later. Not an owning ref // since owning the ref without owning the shared backing memory doesn't make // sense, so this should only be used for pointer comparisons. - CGContextRef saved_context_weak = windowless_context_.get(); + CGContextRef saved_context_weak = windowless_context(); + // We also save the buffer index for the comparison because if we flip buffers + // but haven't reallocated them then we do need to restore the context because + // it is going to continue to be used. + int saved_index = windowless_buffer_index_; if (background_context_.get()) { base::mac::ScopedCFTypeRef<CGImageRef> image( @@ -356,69 +364,66 @@ void WebPluginProxy::Paint(const gfx::Rect& rect) { source_rect.origin.y = CGImageGetHeight(image) - rect.y() - rect.height(); base::mac::ScopedCFTypeRef<CGImageRef> sub_image( CGImageCreateWithImageInRect(image, source_rect)); - CGContextDrawImage(windowless_context_, rect.ToCGRect(), sub_image); + CGContextDrawImage(windowless_context(), rect.ToCGRect(), sub_image); } else if (transparent_) { - CGContextClearRect(windowless_context_, rect.ToCGRect()); + CGContextClearRect(windowless_context(), rect.ToCGRect()); } - CGContextClipToRect(windowless_context_, rect.ToCGRect()); + CGContextClipToRect(windowless_context(), rect.ToCGRect()); // TODO(caryclark): This is a temporary workaround to allow the Darwin / Skia // port to share code with the Darwin / CG port. All ports will eventually use // the common code below. - delegate_->CGPaint(windowless_context_, rect); - if (windowless_context_.get() == saved_context_weak) - CGContextRestoreGState(windowless_context_); + delegate_->CGPaint(windowless_context(), rect); + if (windowless_contexts_[saved_index].get() == saved_context_weak) + CGContextRestoreGState(windowless_contexts_[saved_index]); #else - windowless_canvas_->save(); + windowless_canvas()->save(); // The given clip rect is relative to the plugin coordinate system. SkRect sk_rect = { SkIntToScalar(rect.x()), SkIntToScalar(rect.y()), SkIntToScalar(rect.right()), SkIntToScalar(rect.bottom()) }; - windowless_canvas_->clipRect(sk_rect); + windowless_canvas()->clipRect(sk_rect); // Setup the background. if (background_canvas_.get()) { // When a background canvas is given, we're in transparent mode. This means // the plugin wants to have the image of the page in the canvas it's drawing - // into (which is windowless_canvas_) so it can do blending. So we copy the - // background bitmap into the windowless_canvas_. + // into (which is windowless_canvases_) so it can do blending. So we copy + // the background bitmap into the windowless canvas. const SkBitmap& background_bitmap = skia::GetTopDevice(*background_canvas_)->accessBitmap(false); - windowless_canvas_->drawBitmap(background_bitmap, 0, 0); + windowless_canvas()->drawBitmap(background_bitmap, 0, 0); } else { // In non-transparent mode, the plugin doesn't care what's underneath, so we // can just give it black. SkPaint black_fill_paint; black_fill_paint.setARGB(0xFF, 0x00, 0x00, 0x00); - windowless_canvas_->drawPaint(black_fill_paint); + windowless_canvas()->drawPaint(black_fill_paint); } - // Bring the windowless_canvas_ into the window coordinate system, which is + // Bring the windowless canvas into the window coordinate system, which is // how the plugin expects to draw (since the windowless API was originally // designed just for scribbling over the web page). - windowless_canvas_->translate(SkIntToScalar(-delegate_->GetRect().x()), - SkIntToScalar(-delegate_->GetRect().y())); + windowless_canvas()->translate(SkIntToScalar(-delegate_->GetRect().x()), + SkIntToScalar(-delegate_->GetRect().y())); // Before we send the invalidate, paint so that renderer uses the updated // bitmap. - delegate_->Paint(windowless_canvas_.get(), offset_rect); + delegate_->Paint(windowless_canvas(), offset_rect); - windowless_canvas_->restore(); + windowless_canvas()->restore(); #endif } void WebPluginProxy::UpdateGeometry( const gfx::Rect& window_rect, const gfx::Rect& clip_rect, - const TransportDIB::Handle& windowless_buffer, + const TransportDIB::Handle& windowless_buffer0, + const TransportDIB::Handle& windowless_buffer1, + int windowless_buffer_index, const TransportDIB::Handle& background_buffer, - bool transparent -#if defined(OS_MACOSX) - , - int ack_key -#endif - ) { + bool transparent) { gfx::Rect old = delegate_->GetRect(); gfx::Rect old_clip_rect = delegate_->GetClipRect(); transparent_ = transparent; @@ -426,14 +431,23 @@ void WebPluginProxy::UpdateGeometry( // Update the buffers before doing anything that could call into plugin code, // so that we don't process buffer changes out of order if plugins make // synchronous calls that lead to nested UpdateGeometry calls. - if (TransportDIB::is_valid_handle(windowless_buffer)) { - // The plugin's rect changed, so now we have a new buffer to draw into. - SetWindowlessBuffer(windowless_buffer, background_buffer, window_rect); + if (TransportDIB::is_valid_handle(windowless_buffer0)) { + // The plugin's rect changed, so now we have new buffers to draw into. + SetWindowlessBuffers(windowless_buffer0, + windowless_buffer1, + background_buffer, + window_rect); } + DCHECK(0 <= windowless_buffer_index && windowless_buffer_index <= 1); + windowless_buffer_index_ = windowless_buffer_index; +#if defined(USE_X11) + delegate_->SetWindowlessShmPixmap(windowless_shm_pixmap()); +#endif + #if defined(OS_MACOSX) - delegate_->UpdateGeometryAndContext(window_rect, clip_rect, - windowless_context_); + delegate_->UpdateGeometryAndContext( + window_rect, clip_rect, windowless_context()); #else delegate_->UpdateGeometry(window_rect, clip_rect); #endif @@ -444,45 +458,58 @@ void WebPluginProxy::UpdateGeometry( !damaged_rect_.IsEmpty()) { InvalidateRect(damaged_rect_); } - -#if defined(OS_MACOSX) - // The renderer is expecting an ACK message if ack_key is not -1. - if (ack_key != -1) { - Send(new PluginHostMsg_UpdateGeometry_ACK(route_id_, ack_key)); - } -#endif } #if defined(OS_WIN) -void WebPluginProxy::SetWindowlessBuffer( - const TransportDIB::Handle& windowless_buffer, - const TransportDIB::Handle& background_buffer, - const gfx::Rect& window_rect) { + +void WebPluginProxy::CreateCanvasFromHandle( + const TransportDIB::Handle& dib_handle, + const gfx::Rect& window_rect, + scoped_ptr<skia::PlatformCanvas>* canvas_out) { // Create a canvas that will reference the shared bits. We have to handle // errors here since we're mapping a large amount of memory that may not fit // in our address space, or go wrong in some other way. - windowless_canvas_.reset(new skia::PlatformCanvas); - if (!windowless_canvas_->initialize( + scoped_ptr<skia::PlatformCanvas> canvas(new skia::PlatformCanvas); + if (!canvas->initialize( window_rect.width(), window_rect.height(), true, - chrome::GetSectionFromProcess(windowless_buffer, + chrome::GetSectionFromProcess(dib_handle, channel_->renderer_handle(), false))) { - windowless_canvas_.reset(); + canvas.reset(); + } + canvas_out->reset(canvas.release()); +} + +void WebPluginProxy::SetWindowlessBuffers( + const TransportDIB::Handle& windowless_buffer0, + const TransportDIB::Handle& windowless_buffer1, + const TransportDIB::Handle& background_buffer, + const gfx::Rect& window_rect) { + CreateCanvasFromHandle(windowless_buffer0, + window_rect, + &windowless_canvases_[0]); + if (!windowless_canvases_[0].get()) { + windowless_canvases_[1].reset(); + background_canvas_.reset(); + return; + } + CreateCanvasFromHandle(windowless_buffer1, + window_rect, + &windowless_canvases_[1]); + if (!windowless_canvases_[1].get()) { + windowless_canvases_[0].reset(); background_canvas_.reset(); return; } if (background_buffer) { - background_canvas_.reset(new skia::PlatformCanvas); - if (!background_canvas_->initialize( - window_rect.width(), - window_rect.height(), - true, - chrome::GetSectionFromProcess(background_buffer, - channel_->renderer_handle(), false))) { - windowless_canvas_.reset(); - background_canvas_.reset(); + CreateCanvasFromHandle(background_buffer, + window_rect, + &background_canvas_); + if (!background_canvas_.get()) { + windowless_canvases_[0].reset(); + windowless_canvases_[1].reset(); return; } } @@ -490,79 +517,116 @@ void WebPluginProxy::SetWindowlessBuffer( #elif defined(OS_MACOSX) -void WebPluginProxy::SetWindowlessBuffer( - const TransportDIB::Handle& windowless_buffer, - const TransportDIB::Handle& background_buffer, - const gfx::Rect& window_rect) { +void WebPluginProxy::CreateDIBAndCGContextFromHandle( + const TransportDIB::Handle& dib_handle, + const gfx::Rect& window_rect, + scoped_ptr<TransportDIB>* dib_out, + base::mac::ScopedCFTypeRef<CGContextRef>* cg_context_out) { // Convert the shared memory handle to a handle that works in our process, // and then use that to create a CGContextRef. - windowless_dib_.reset(TransportDIB::Map(windowless_buffer)); - background_dib_.reset(TransportDIB::Map(background_buffer)); - windowless_context_.reset(CGBitmapContextCreate( - windowless_dib_->memory(), - window_rect.width(), - window_rect.height(), - 8, 4 * window_rect.width(), - base::mac::GetSystemColorSpace(), - kCGImageAlphaPremultipliedFirst | - kCGBitmapByteOrder32Host)); - CGContextTranslateCTM(windowless_context_, 0, window_rect.height()); - CGContextScaleCTM(windowless_context_, 1, -1); - if (background_dib_.get()) { - background_context_.reset(CGBitmapContextCreate( - background_dib_->memory(), + TransportDIB* dib = TransportDIB::Map(dib_handle); + CGContextRef cg_context = NULL; + if (dib) { + cg_context = CGBitmapContextCreate( + dib->memory(), window_rect.width(), window_rect.height(), - 8, 4 * window_rect.width(), + 8, + 4 * window_rect.width(), base::mac::GetSystemColorSpace(), - kCGImageAlphaPremultipliedFirst | - kCGBitmapByteOrder32Host)); - CGContextTranslateCTM(background_context_, 0, window_rect.height()); - CGContextScaleCTM(background_context_, 1, -1); + kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host); + CGContextTranslateCTM(cg_context, 0, window_rect.height()); + CGContextScaleCTM(cg_context, 1, -1); } + dib_out->reset(dib); + cg_context_out->reset(cg_context); } -#elif defined(USE_X11) - -void WebPluginProxy::SetWindowlessBuffer( - const TransportDIB::Handle& windowless_buffer, +void WebPluginProxy::SetWindowlessBuffers( + const TransportDIB::Handle& windowless_buffer0, + const TransportDIB::Handle& windowless_buffer1, const TransportDIB::Handle& background_buffer, const gfx::Rect& window_rect) { - int width = window_rect.width(); - int height = window_rect.height(); - windowless_dib_.reset(TransportDIB::Map(windowless_buffer)); - if (windowless_dib_.get()) { - windowless_canvas_.reset(windowless_dib_->GetPlatformCanvas(width, height)); - } else { - // This can happen if the renderer has already destroyed the TransportDIB - // by the time we receive the handle, e.g. in case of multiple resizes. - windowless_canvas_.reset(); - } - background_dib_.reset(TransportDIB::Map(background_buffer)); - if (background_dib_.get()) { - background_canvas_.reset(background_dib_->GetPlatformCanvas(width, height)); - } else { - background_canvas_.reset(); + CreateDIBAndCGContextFromHandle(windowless_buffer0, + window_rect, + &windowless_dibs_[0], + &windowless_contexts_[0]); + CreateDIBAndCGContextFromHandle(windowless_buffer1, + window_rect, + &windowless_dibs_[1], + &windowless_contexts_[1]); + CreateDIBAndCGContextFromHandle(background_buffer, + window_rect, + &background_dib_, + &background_context_); +} + +#elif defined(USE_X11) + +void WebPluginProxy::CreateDIBAndCanvasFromHandle( + const TransportDIB::Handle& dib_handle, + const gfx::Rect& window_rect, + scoped_ptr<TransportDIB>* dib_out, + scoped_ptr<skia::PlatformCanvas>* canvas_out) { + TransportDIB* dib = TransportDIB::Map(dib_handle); + skia::PlatformCanvas* canvas = NULL; + // dib may be NULL if the renderer has already destroyed the TransportDIB by + // the time we receive the handle, e.g. in case of multiple resizes. + if (dib) { + canvas = dib->GetPlatformCanvas(window_rect.width(), window_rect.height()); } + dib_out->reset(dib); + canvas_out->reset(canvas); +} - // If SHM pixmaps support is available, create a SHM pixmap and - // pass it to the delegate for windowless plugin painting. - if (delegate_->IsWindowless() && use_shm_pixmap_ && windowless_dib_.get()) { +void WebPluginProxy::CreateShmPixmapFromDIB( + TransportDIB* dib, + const gfx::Rect& window_rect, + XID* pixmap_out) { + if (dib) { Display* display = ui::GetXDisplay(); XID root_window = ui::GetX11RootWindow(); XShmSegmentInfo shminfo = {0}; - if (windowless_shm_pixmap_ != None) - XFreePixmap(display, windowless_shm_pixmap_); + if (*pixmap_out != None) + XFreePixmap(display, *pixmap_out); - shminfo.shmseg = windowless_dib_->MapToX(display); + shminfo.shmseg = dib->MapToX(display); // Create a shared memory pixmap based on the image buffer. - windowless_shm_pixmap_ = XShmCreatePixmap(display, root_window, - NULL, &shminfo, - width, height, - DefaultDepth(display, 0)); + *pixmap_out = XShmCreatePixmap(display, root_window, + NULL, &shminfo, + window_rect.width(), window_rect.height(), + DefaultDepth(display, 0)); + } +} - delegate_->SetWindowlessShmPixmap(windowless_shm_pixmap_); +void WebPluginProxy::SetWindowlessBuffers( + const TransportDIB::Handle& windowless_buffer0, + const TransportDIB::Handle& windowless_buffer1, + const TransportDIB::Handle& background_buffer, + const gfx::Rect& window_rect) { + CreateDIBAndCanvasFromHandle(windowless_buffer0, + window_rect, + &windowless_dibs_[0], + &windowless_canvases_[0]); + CreateDIBAndCanvasFromHandle(windowless_buffer1, + window_rect, + &windowless_dibs_[1], + &windowless_canvases_[1]); + CreateDIBAndCanvasFromHandle(background_buffer, + window_rect, + &background_dib_, + &background_canvas_); + + // If SHM pixmaps support is available, create SHM pixmaps to pass to the + // delegate for windowless plugin painting. + if (delegate_->IsWindowless() && use_shm_pixmap_) { + CreateShmPixmapFromDIB(windowless_dibs_[0].get(), + window_rect, + &windowless_shm_pixmaps_[0]); + CreateShmPixmapFromDIB(windowless_dibs_[1].get(), + window_rect, + &windowless_shm_pixmaps_[1]); } } @@ -644,7 +708,15 @@ void WebPluginProxy::OnPaint(const gfx::Rect& damaged_rect) { content::GetContentClient()->SetActiveURL(page_url_); Paint(damaged_rect); - Send(new PluginHostMsg_InvalidateRect(route_id_, damaged_rect)); + bool allow_buffer_flipping; +#if defined(OS_MACOSX) + allow_buffer_flipping = delegate_->AllowBufferFlipping(); +#else + allow_buffer_flipping = true; +#endif + Send(new PluginHostMsg_InvalidateRect(route_id_, + damaged_rect, + allow_buffer_flipping)); } bool WebPluginProxy::IsOffTheRecord() { diff --git a/content/plugin/webplugin_proxy.h b/content/plugin/webplugin_proxy.h index a06d810..fee1ee0 100644 --- a/content/plugin/webplugin_proxy.h +++ b/content/plugin/webplugin_proxy.h @@ -110,14 +110,11 @@ class WebPluginProxy : public webkit::npapi::WebPlugin { bool notify_redirects); void UpdateGeometry(const gfx::Rect& window_rect, const gfx::Rect& clip_rect, - const TransportDIB::Handle& windowless_buffer, + const TransportDIB::Handle& windowless_buffer0, + const TransportDIB::Handle& windowless_buffer1, + int windowless_buffer_index, const TransportDIB::Handle& background_buffer, - bool transparent -#if defined(OS_MACOSX) - , - int ack_key -#endif - ); + bool transparent); virtual void CancelDocumentLoad(); virtual void InitiateHTTPRangeRequest( const char* url, const char* range_info, int range_request_id); @@ -173,10 +170,51 @@ class WebPluginProxy : public webkit::npapi::WebPlugin { // Handler for sending over the paint event to the plugin. void OnPaint(const gfx::Rect& damaged_rect); - // Updates the shared memory section where windowless plugins paint. - void SetWindowlessBuffer(const TransportDIB::Handle& windowless_buffer, - const TransportDIB::Handle& background_buffer, - const gfx::Rect& window_rect); +#if defined(OS_WIN) + void CreateCanvasFromHandle(const TransportDIB::Handle& dib_handle, + const gfx::Rect& window_rect, + scoped_ptr<skia::PlatformCanvas>* canvas_out); +#elif defined(OS_MACOSX) + static void CreateDIBAndCGContextFromHandle( + const TransportDIB::Handle& dib_handle, + const gfx::Rect& window_rect, + scoped_ptr<TransportDIB>* dib_out, + base::mac::ScopedCFTypeRef<CGContextRef>* cg_context_out); +#elif defined(USE_X11) + static void CreateDIBAndCanvasFromHandle( + const TransportDIB::Handle& dib_handle, + const gfx::Rect& window_rect, + scoped_ptr<TransportDIB>* dib_out, + scoped_ptr<skia::PlatformCanvas>* canvas_out); + + static void CreateShmPixmapFromDIB( + TransportDIB* dib, + const gfx::Rect& window_rect, + XID* pixmap_out); +#endif + + // Updates the shared memory sections where windowless plugins paint. + void SetWindowlessBuffers(const TransportDIB::Handle& windowless_buffer0, + const TransportDIB::Handle& windowless_buffer1, + const TransportDIB::Handle& background_buffer, + const gfx::Rect& window_rect); + +#if defined(OS_MACOSX) + CGContextRef windowless_context() const { + return windowless_contexts_[windowless_buffer_index_].get(); + } +#else + skia::PlatformCanvas* windowless_canvas() const { + return windowless_canvases_[windowless_buffer_index_].get(); + } + +#if defined(USE_X11) + XID windowless_shm_pixmap() const { + return windowless_shm_pixmaps_[windowless_buffer_index_]; + } +#endif + +#endif typedef base::hash_map<int, webkit::npapi::WebPluginResourceClient*> ResourceClientMap; @@ -193,26 +231,30 @@ class WebPluginProxy : public webkit::npapi::WebPlugin { // The url of the main frame hosting the plugin. GURL page_url_; - // Variables used for desynchronized windowless plugin painting. See note in - // webplugin_delegate_proxy.h for how this works. + // Variables used for desynchronized windowless plugin painting. See note in + // webplugin_delegate_proxy.h for how this works. The two sets of windowless_* + // fields are for the front-buffer and back-buffer of a buffer flipping system + // and windowless_buffer_index_ identifies which set we are using as the + // back-buffer at any given time. bool transparent_; + int windowless_buffer_index_; #if defined(OS_MACOSX) - scoped_ptr<TransportDIB> windowless_dib_; + scoped_ptr<TransportDIB> windowless_dibs_[2]; scoped_ptr<TransportDIB> background_dib_; - base::mac::ScopedCFTypeRef<CGContextRef> windowless_context_; + base::mac::ScopedCFTypeRef<CGContextRef> windowless_contexts_[2]; base::mac::ScopedCFTypeRef<CGContextRef> background_context_; scoped_ptr<WebPluginAcceleratedSurfaceProxy> accelerated_surface_; #else - scoped_ptr<skia::PlatformCanvas> windowless_canvas_; + scoped_ptr<skia::PlatformCanvas> windowless_canvases_[2]; scoped_ptr<skia::PlatformCanvas> background_canvas_; #if defined(USE_X11) - scoped_ptr<TransportDIB> windowless_dib_; + scoped_ptr<TransportDIB> windowless_dibs_[2]; scoped_ptr<TransportDIB> background_dib_; // If we can use SHM pixmaps for windowless plugin painting or not. bool use_shm_pixmap_; - // The SHM pixmap for windowless plugin painting. - XID windowless_shm_pixmap_; + // The SHM pixmaps for windowless plugin painting. + XID windowless_shm_pixmaps_[2]; #endif #endif |