From cb632c310910db456fbc3083fcad1fce0e1a2197 Mon Sep 17 00:00:00 2001 From: "piman@chromium.org" Date: Thu, 5 Aug 2010 02:54:42 +0000 Subject: If SHM pixmaps support is available, for example, Intel drivers now support that (http://cgit.freedesktop.org/xorg/driver/xf86-video-intel/commit/?id=4b7142baa0b3bf6f38843d06aadc579d8624cefc), use SHM pixmaps support to accelerate windowless plugin painting. Modify WindowlessPaint to directly use Xlib interfaces for SHM pixmaps support, similarly to the way how backing_store_x handles different SHM support levels provided by X server. BUG=50912 TEST=Open the page "http://disney.go.com/official-sites/demi-lovato/albums" using Chromium browser, compare the CPU usage of browser and X server before and after the change, and confirm CPU usage is reduced with this change (for example, on an Atom N450 Netbook with MeeGo 1.0 and Chromium browser 6.0.417.0 there's >30% CPU usage reduction, especially X server CPU usage is reduced by half). Review URL: http://codereview.chromium.org/3052039 Patch from Yuqiang Xian . git-svn-id: svn://svn.chromium.org/chrome/trunk/src@55020 0039d316-1c4b-4281-b951-d872f2087c98 --- webkit/glue/plugins/webplugin_delegate_impl.h | 11 +++ webkit/glue/plugins/webplugin_delegate_impl_gtk.cc | 109 +++++++++++++++------ 2 files changed, 92 insertions(+), 28 deletions(-) (limited to 'webkit') diff --git a/webkit/glue/plugins/webplugin_delegate_impl.h b/webkit/glue/plugins/webplugin_delegate_impl.h index ebf5d3e..1c7ccb2 100644 --- a/webkit/glue/plugins/webplugin_delegate_impl.h +++ b/webkit/glue/plugins/webplugin_delegate_impl.h @@ -27,6 +27,8 @@ #endif #if defined(USE_X11) +#include "app/x11_util.h" + typedef struct _GdkDrawable GdkPixmap; #endif @@ -181,6 +183,12 @@ class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate { void set_windowed_handle(gfx::PluginWindowHandle handle); #endif +#if defined(USE_X11) + void SetWindowlessShmPixmap(XID shm_pixmap) { + windowless_shm_pixmap_ = shm_pixmap; + } +#endif + private: friend class DeleteTask; friend class webkit_glue::WebPluginDelegate; @@ -292,6 +300,9 @@ class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate { #endif // OS_WIN #if defined(USE_X11) + // The SHM pixmap for a windowless plugin. + XID windowless_shm_pixmap_; + // The pixmap we're drawing into, for a windowless plugin. GdkPixmap* pixmap_; double first_event_time_; diff --git a/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc b/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc index 18b1504..d4a98a8 100644 --- a/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc +++ b/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc @@ -44,6 +44,7 @@ WebPluginDelegateImpl::WebPluginDelegateImpl( windowless_(false), plugin_(NULL), instance_(instance), + windowless_shm_pixmap_(None), pixmap_(NULL), first_event_time_(-1.0), plug_(NULL), @@ -399,47 +400,99 @@ void WebPluginDelegateImpl::WindowlessPaint(cairo_t* context, pixmap_draw_rect.right(), pixmap_draw_rect.bottom()); - EnsurePixmapAtLeastSize(pixmap_rect.width(), pixmap_rect.height()); - - // Copy the current image into the pixmap, so the plugin can draw over - // this background. - cairo_t* cairo = gdk_cairo_create(pixmap_); - BlitContextToContext(cairo, pixmap_draw_rect, context, draw_rect.origin()); - cairo_destroy(cairo); - // Construct the paint message, targeting the pixmap. NPEvent np_event = {0}; XGraphicsExposeEvent &event = np_event.xgraphicsexpose; event.type = GraphicsExpose; - event.display = GDK_DISPLAY(); - event.drawable = GDK_PIXMAP_XID(pixmap_); event.x = pixmap_draw_rect.x(); event.y = pixmap_draw_rect.y(); event.width = pixmap_draw_rect.width(); event.height = pixmap_draw_rect.height(); + event.display = GDK_DISPLAY(); + + if (windowless_shm_pixmap_ != None) { + Pixmap pixmap = None; + GC xgc = NULL; + Display* display = event.display; + gfx::Rect plugin_draw_rect = draw_rect; + + // Make plugin_draw_rect relative to the plugin window. + plugin_draw_rect.Offset(-window_rect_.x(), -window_rect_.y()); + + // In case the drawing area does not start with the plugin window origin, + // we can not let the plugin directly draw over the shared memory pixmap. + if (plugin_draw_rect.x() != pixmap_draw_rect.x() || + plugin_draw_rect.y() != pixmap_draw_rect.y()) { + pixmap = XCreatePixmap(display, windowless_shm_pixmap_, + std::max(1, pixmap_rect.width()), + std::max(1, pixmap_rect.height()), + DefaultDepth(display, 0)); + xgc = XCreateGC(display, windowless_shm_pixmap_, 0, NULL); + // Copy the current image into the pixmap, so the plugin can draw over it. + XCopyArea(display, windowless_shm_pixmap_, pixmap, xgc, + plugin_draw_rect.x(), plugin_draw_rect.y(), + pixmap_draw_rect.width(), pixmap_draw_rect.height(), + pixmap_draw_rect.x(), pixmap_draw_rect.y()); + + event.drawable = pixmap; + } else { + event.drawable = windowless_shm_pixmap_; + } + + // Tell the plugin to paint into the pixmap. + static StatsRate plugin_paint("Plugin.Paint"); + StatsScope scope(plugin_paint); + NPError err = instance()->NPP_HandleEvent(&np_event); + DCHECK_EQ(err, NPERR_NO_ERROR); + + if (pixmap != None) { + // Copy the rendered image pixmap back into the shm pixmap + // and thus the drawing buffer. + XCopyArea(display, pixmap, windowless_shm_pixmap_, xgc, + pixmap_draw_rect.x(), pixmap_draw_rect.y(), + pixmap_draw_rect.width(), pixmap_draw_rect.height(), + plugin_draw_rect.x(), plugin_draw_rect.y()); + XSync(display, FALSE); + if (xgc) + XFreeGC(display, xgc); + XFreePixmap(display, pixmap); + } else { + XSync(display, FALSE); + } + } else { + EnsurePixmapAtLeastSize(pixmap_rect.width(), pixmap_rect.height()); - // Tell the plugin to paint into the pixmap. - static StatsRate plugin_paint("Plugin.Paint"); - StatsScope scope(plugin_paint); - NPError err = instance()->NPP_HandleEvent(&np_event); - DCHECK_EQ(err, NPERR_NO_ERROR); + // Copy the current image into the pixmap, so the plugin can draw over + // this background. + cairo_t* cairo = gdk_cairo_create(pixmap_); + BlitContextToContext(cairo, pixmap_draw_rect, context, draw_rect.origin()); + cairo_destroy(cairo); - cairo_save(context); - // Now copy the rendered image pixmap back into the drawing buffer. - gdk_cairo_set_source_pixmap(context, pixmap_, -offset_x, -offset_y); - cairo_rectangle(context, draw_rect.x(), draw_rect.y(), - draw_rect.width(), draw_rect.height()); - cairo_clip(context); - cairo_paint(context); + event.drawable = GDK_PIXMAP_XID(pixmap_); + + // Tell the plugin to paint into the pixmap. + static StatsRate plugin_paint("Plugin.Paint"); + StatsScope scope(plugin_paint); + NPError err = instance()->NPP_HandleEvent(&np_event); + DCHECK_EQ(err, NPERR_NO_ERROR); + + cairo_save(context); + // Now copy the rendered image pixmap back into the drawing buffer. + gdk_cairo_set_source_pixmap(context, pixmap_, -offset_x, -offset_y); + cairo_rectangle(context, draw_rect.x(), draw_rect.y(), + draw_rect.width(), draw_rect.height()); + cairo_clip(context); + cairo_paint(context); #ifdef DEBUG_RECTANGLES - // Draw some debugging rectangles. - // Pixmap rect = blue. - DrawDebugRectangle(context, pixmap_rect, 0, 0, 1); - // Drawing rect = red. - DrawDebugRectangle(context, draw_rect, 1, 0, 0); + // Draw some debugging rectangles. + // Pixmap rect = blue. + DrawDebugRectangle(context, pixmap_rect, 0, 0, 1); + // Drawing rect = red. + DrawDebugRectangle(context, draw_rect, 1, 0, 0); #endif - cairo_restore(context); + cairo_restore(context); + } } void WebPluginDelegateImpl::WindowlessSetWindow() { -- cgit v1.1