Index: skia/ext/bitmap_platform_device_linux.cc |
diff --git a/skia/ext/bitmap_platform_device_linux.cc b/skia/ext/bitmap_platform_device_linux.cc |
index f6a0e6d07b80e11cb2b8570400a17c2fba5cc84a..310c867bf7612b98489458ebea2f5fc27860218a 100644 |
--- a/skia/ext/bitmap_platform_device_linux.cc |
+++ b/skia/ext/bitmap_platform_device_linux.cc |
@@ -5,6 +5,9 @@ |
#include "skia/ext/bitmap_platform_device_linux.h" |
#include <cairo/cairo.h> |
+#include <cairo/cairo-xlib.h> |
+#include <gdk/gdk.h> |
+#include <gdk/gdkx.h> |
namespace skia { |
@@ -18,15 +21,31 @@ class BitmapPlatformDeviceLinux::BitmapPlatformDeviceLinuxData |
: public base::RefCounted<BitmapPlatformDeviceLinuxData> { |
public: |
explicit BitmapPlatformDeviceLinuxData(cairo_surface_t* surface) |
- : surface_(surface) { } |
+ : surface_(surface), pixmap_(NULL) { } |
cairo_surface_t* surface() const { return surface_; } |
+ // We can optionally track a pixmap that is temporarily holding the |
+ // content of our surface. This is only necessary for plugin |
+ // rendering. Takes ownership of the pixmap. |
+ void set_pixmap(GdkPixmap* pixmap) { pixmap_ = pixmap; } |
+ GdkPixmap* pixmap() const { return pixmap_; } |
+ |
+ void FreePixmap() { |
+ if (pixmap_) { |
+ g_object_unref(pixmap_); |
+ pixmap_ = NULL; |
+ } |
+ } |
+ |
protected: |
cairo_surface_t *const surface_; |
+ GdkPixmap* pixmap_; |
+ |
friend class base::RefCounted<BitmapPlatformDeviceLinuxData>; |
~BitmapPlatformDeviceLinuxData() { |
+ FreePixmap(); |
cairo_surface_destroy(surface_); |
} |
@@ -96,6 +115,52 @@ BitmapPlatformDeviceLinux::BitmapPlatformDeviceLinux( |
BitmapPlatformDeviceLinux::~BitmapPlatformDeviceLinux() { |
} |
+PlatformDeviceLinux::XDrawable BitmapPlatformDeviceLinux::GetXDrawable() { |
+ // We've been asked to provide an XDrawable representing our surface. |
+ // We create one and copy our content into it. |
+ |
+ data_->FreePixmap(); |
+ |
+ // sys_visual is owned by gdk; we shouldn't free it. |
+ GdkVisual* sys_visual = gdk_visual_get_system(); |
+ GdkPixmap* pixmap = |
+ gdk_pixmap_new(NULL, // use width/height/depth params |
+ cairo_image_surface_get_width(data_->surface()), |
+ cairo_image_surface_get_height(data_->surface()), |
+ sys_visual->depth); |
+ // XXX we leak the colormap. |
+ GdkColormap* colormap = gdk_colormap_new(gdk_visual_get_system(), |
+ FALSE); |
+ gdk_drawable_set_colormap(GDK_DRAWABLE(pixmap), colormap); |
+ cairo_t* pix_cairo = gdk_cairo_create(GDK_DRAWABLE(pixmap)); |
+ |
+ // Copy the current content to the pixmap. |
+ cairo_set_source_surface(pix_cairo, data_->surface(), 0, 0); |
+ cairo_paint(pix_cairo); |
+ |
+ cairo_destroy(pix_cairo); |
+ |
+ data_->set_pixmap(pixmap); |
+ return GDK_PIXMAP_XID(pixmap); |
+} |
+ |
+void BitmapPlatformDeviceLinux::onAccessBitmap(SkBitmap* bitmap) { |
+ // TODO(evanm): OPTIMIZATION: We should only flush if we know a drawing |
+ // operation has occurred on our pixmap. (This note is copied over from |
+ // the Windows code). |
+ if (!data_->pixmap()) |
+ return; |
+ |
+ // The plugin has finished its drawing over our pixmap; we need to |
+ // copy it back into our backing buffer. |
+ cairo_t* cairo = cairo_create(data_->surface()); |
+ gdk_cairo_set_source_pixmap(cairo, data_->pixmap(), |
+ 0, 0); // destination (x, y) |
+ cairo_paint(cairo); |
+ cairo_destroy(cairo); |
+ data_->FreePixmap(); |
+} |
+ |
cairo_surface_t* BitmapPlatformDeviceLinux::surface() const { |
return data_->surface(); |
} |