summaryrefslogtreecommitdiffstats
path: root/content/plugin
diff options
context:
space:
mode:
authortschmelcher@chromium.org <tschmelcher@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-25 22:13:52 +0000
committertschmelcher@chromium.org <tschmelcher@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-25 22:13:52 +0000
commit9cf755682fcff0aa79e64c6f4fcb7ced80547d67 (patch)
tree227975248d1e781ac949dcde1a2291c11919d838 /content/plugin
parentb8fede4e01b906a65ca9eb816e2cab0694810270 (diff)
downloadchromium_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.cc10
-rw-r--r--content/plugin/webplugin_proxy.cc340
-rw-r--r--content/plugin/webplugin_proxy.h80
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