Home | History | Annotate | Download | only in renderer_host
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "content/browser/renderer_host/backing_store_gtk.h"
      6 
      7 #include <cairo-xlib.h>
      8 #include <gtk/gtk.h>
      9 #include <stdlib.h>
     10 #include <sys/ipc.h>
     11 #include <sys/shm.h>
     12 #include <X11/extensions/sync.h>
     13 
     14 #if defined(OS_OPENBSD) || defined(OS_FREEBSD)
     15 #include <sys/endian.h>
     16 #endif
     17 
     18 #include <algorithm>
     19 #include <limits>
     20 #include <queue>
     21 #include <utility>
     22 
     23 #include "base/compiler_specific.h"
     24 #include "base/logging.h"
     25 #include "base/memory/singleton.h"
     26 #include "base/metrics/histogram.h"
     27 #include "base/time/time.h"
     28 #include "content/browser/renderer_host/render_process_host_impl.h"
     29 #include "skia/ext/platform_canvas.h"
     30 #include "third_party/skia/include/core/SkBitmap.h"
     31 #include "ui/base/gtk/gtk_signal.h"
     32 #include "ui/base/x/x11_util.h"
     33 #include "ui/base/x/x11_util_internal.h"
     34 #include "ui/gfx/rect.h"
     35 #include "ui/gfx/rect_conversions.h"
     36 #include "ui/surface/transport_dib.h"
     37 
     38 namespace content {
     39 namespace {
     40 
     41 // Assume that somewhere along the line, someone will do width * height * 4
     42 // with signed numbers. If the maximum value is 2**31, then 2**31 / 4 =
     43 // 2**29 and floor(sqrt(2**29)) = 23170.
     44 
     45 // Max height and width for layers
     46 static const int kMaxVideoLayerSize = 23170;
     47 
     48 
     49 // X Backing Stores:
     50 //
     51 // Unlike Windows, where the backing store is kept in heap memory, we keep our
     52 // backing store in the X server, as a pixmap. Thus expose events just require
     53 // instructing the X server to copy from the backing store to the window.
     54 //
     55 // The backing store is in the same format as the visual which our main window
     56 // is using. Bitmaps from the renderer are uploaded to the X server, either via
     57 // shared memory or over the wire, and XRENDER is used to convert them to the
     58 // correct format for the backing store.
     59 
     60 // Destroys the image and the associated shared memory structures. This is a
     61 // helper function for code using shared memory.
     62 void DestroySharedImage(Display* display,
     63                         XImage* image,
     64                         XShmSegmentInfo* shminfo) {
     65   XShmDetach(display, shminfo);
     66   XDestroyImage(image);
     67   shmdt(shminfo->shmaddr);
     68 }
     69 
     70 // So we don't don't want to call XSync(), which can block the UI loop for
     71 // ~100ms on first paint and is generally slow. We optionally use the
     72 // XSyncExtension to push a callback into the X11 event queue and get a
     73 // callback instead of blocking until the event queue is cleared.
     74 //
     75 // TODO(erg): If ui::GetXDisplay() ever gets fixed to handle multiple Displays,
     76 // this must be modified to be per Display instead of a Singleton.
     77 class XSyncHandler {
     78  public:
     79   static XSyncHandler* GetInstance() {
     80     return Singleton<XSyncHandler>::get();
     81   }
     82 
     83   bool Enabled() {
     84     return loaded_extension_;
     85   }
     86 
     87   void PushPaintCounter(TransportDIB* dib,
     88                         Display* display,
     89                         Picture picture,
     90                         Pixmap pixmap,
     91                         const base::Closure& completion_callback);
     92 
     93  private:
     94   friend struct DefaultSingletonTraits<XSyncHandler>;
     95 
     96   // A struct that has cleanup and callback tasks that were queued into the
     97   // future and are run on |g_backing_store_sync_alarm| firing.
     98   struct BackingStoreEvents {
     99     BackingStoreEvents(TransportDIB* dib, Display* d, Picture pic, Pixmap pix,
    100                        const base::Closure& c)
    101         : dib(dib),
    102           display(d),
    103           picture(pic),
    104           pixmap(pix),
    105           closure(c) {
    106       dib->IncreaseInFlightCounter();
    107     }
    108 
    109     TransportDIB* dib;
    110 
    111     // The display we're running on.
    112     Display* display;
    113 
    114     // Data to delete.
    115     Picture picture;
    116     Pixmap pixmap;
    117 
    118     // Callback once everything else is done.
    119     base::Closure closure;
    120   };
    121 
    122   XSyncHandler();
    123   ~XSyncHandler();
    124 
    125   // An event filter notified about all XEvents. We then filter out XSync
    126   // events that are on counters that we made.
    127   CHROMEG_CALLBACK_1(XSyncHandler, GdkFilterReturn, OnEvent, GdkXEvent*,
    128                      GdkEvent*);
    129 
    130   // Whether we successfully loaded XSyncExtension.
    131   bool loaded_extension_;
    132 
    133   // The event ids returned to us by XSyncQueryExtension().
    134   int xsync_event_base_;
    135   int xsync_error_base_;
    136 
    137   XSyncCounter backing_store_sync_counter_;
    138   XSyncAlarm backing_store_sync_alarm_;
    139 
    140   // A queue of pending paints that we clean up after as alarms fire.
    141   std::queue<BackingStoreEvents*> backing_store_events_;
    142 };
    143 
    144 void XSyncHandler::PushPaintCounter(TransportDIB* dib,
    145                                     Display* display,
    146                                     Picture picture,
    147                                     Pixmap pixmap,
    148                                     const base::Closure& completion_callback) {
    149   backing_store_events_.push(new BackingStoreEvents(
    150         dib, display, picture, pixmap, completion_callback));
    151 
    152   // Push a change counter event into the X11 event queue that will trigger our
    153   // alarm when it is processed.
    154   XSyncValue value;
    155   XSyncIntToValue(&value, 1);
    156   XSyncChangeCounter(ui::GetXDisplay(),
    157                      backing_store_sync_counter_,
    158                      value);
    159 }
    160 
    161 XSyncHandler::XSyncHandler()
    162     : loaded_extension_(false),
    163       xsync_event_base_(0),
    164       xsync_error_base_(0),
    165       backing_store_sync_counter_(0),
    166       backing_store_sync_alarm_(0) {
    167   Display* display = ui::GetXDisplay();
    168   if (XSyncQueryExtension(display,
    169                           &xsync_event_base_,
    170                           &xsync_error_base_)) {
    171     // Create our monotonically increasing counter.
    172     XSyncValue value;
    173     XSyncIntToValue(&value, 0);
    174     backing_store_sync_counter_ = XSyncCreateCounter(display, value);
    175 
    176     // Cerate our alarm that watches for changes to our counter.
    177     XSyncAlarmAttributes attributes;
    178     attributes.trigger.counter = backing_store_sync_counter_;
    179     backing_store_sync_alarm_ = XSyncCreateAlarm(display,
    180                                                  XSyncCACounter,
    181                                                  &attributes);
    182 
    183     // Add our filter to the message loop to handle alarm triggers.
    184     gdk_window_add_filter(NULL, &OnEventThunk, this);
    185 
    186     loaded_extension_ = true;
    187   }
    188 }
    189 
    190 XSyncHandler::~XSyncHandler() {
    191   if (loaded_extension_)
    192     gdk_window_remove_filter(NULL, &OnEventThunk, this);
    193 
    194   XSync(ui::GetXDisplay(), False);
    195   while (!backing_store_events_.empty()) {
    196     // We delete the X11 resources we're holding onto. We don't run the
    197     // callbacks because we are shutting down.
    198     BackingStoreEvents* data = backing_store_events_.front();
    199     backing_store_events_.pop();
    200     XRenderFreePicture(data->display, data->picture);
    201     XFreePixmap(data->display, data->pixmap);
    202     data->dib->DecreaseInFlightCounter();
    203     delete data;
    204   }
    205 }
    206 
    207 GdkFilterReturn XSyncHandler::OnEvent(GdkXEvent* gdkxevent,
    208                                       GdkEvent* event) {
    209   XEvent* xevent = reinterpret_cast<XEvent*>(gdkxevent);
    210   if (xevent->type == xsync_event_base_ + XSyncAlarmNotify) {
    211     XSyncAlarmNotifyEvent* alarm_event =
    212         reinterpret_cast<XSyncAlarmNotifyEvent*>(xevent);
    213     if (alarm_event->alarm == backing_store_sync_alarm_) {
    214       if (alarm_event->counter_value.hi == 0 &&
    215           alarm_event->counter_value.lo == 0) {
    216         // We receive an event about the initial state of the counter during
    217         // alarm creation. We must ignore this event instead of responding to
    218         // it.
    219         return GDK_FILTER_REMOVE;
    220       }
    221 
    222       DCHECK(!backing_store_events_.empty());
    223       BackingStoreEvents* data = backing_store_events_.front();
    224       backing_store_events_.pop();
    225 
    226       // We are responsible for deleting all the data in the struct now that
    227       // we are finished with it.
    228       XRenderFreePicture(data->display, data->picture);
    229       XFreePixmap(data->display, data->pixmap);
    230 
    231       // Dispatch the closure we were given.
    232       data->closure.Run();
    233 
    234       data->dib->DecreaseInFlightCounter();
    235       delete data;
    236 
    237       return GDK_FILTER_REMOVE;
    238     }
    239   }
    240 
    241   return GDK_FILTER_CONTINUE;
    242 }
    243 
    244 }  // namespace
    245 
    246 BackingStoreGtk::BackingStoreGtk(RenderWidgetHost* widget,
    247                                  const gfx::Size& size,
    248                                  void* visual,
    249                                  int depth)
    250     : BackingStore(widget, size),
    251       display_(ui::GetXDisplay()),
    252       shared_memory_support_(ui::QuerySharedMemorySupport(display_)),
    253       use_render_(ui::QueryRenderSupport(display_)),
    254       visual_(visual),
    255       visual_depth_(depth),
    256       root_window_(ui::GetX11RootWindow()) {
    257 #if defined(OS_OPENBSD) || defined(OS_FREEBSD)
    258   COMPILE_ASSERT(_BYTE_ORDER == _LITTLE_ENDIAN, assumes_little_endian);
    259 #else
    260   COMPILE_ASSERT(__BYTE_ORDER == __LITTLE_ENDIAN, assumes_little_endian);
    261 #endif
    262 
    263   pixmap_ = XCreatePixmap(display_, root_window_,
    264                           size.width(), size.height(), depth);
    265 
    266   if (use_render_) {
    267     picture_ = XRenderCreatePicture(
    268         display_, pixmap_,
    269         ui::GetRenderVisualFormat(display_,
    270                                   static_cast<Visual*>(visual)),
    271                                   0, NULL);
    272     pixmap_bpp_ = 0;
    273   } else {
    274     picture_ = 0;
    275     pixmap_bpp_ = ui::BitsPerPixelForPixmapDepth(display_, depth);
    276   }
    277 
    278   pixmap_gc_ = XCreateGC(display_, pixmap_, 0, NULL);
    279 }
    280 
    281 BackingStoreGtk::BackingStoreGtk(RenderWidgetHost* widget,
    282                                  const gfx::Size& size)
    283     : BackingStore(widget, size),
    284       display_(NULL),
    285       shared_memory_support_(ui::SHARED_MEMORY_NONE),
    286       use_render_(false),
    287       pixmap_bpp_(0),
    288       visual_(NULL),
    289       visual_depth_(-1),
    290       root_window_(0),
    291       pixmap_(0),
    292       picture_(0),
    293       pixmap_gc_(NULL) {
    294 }
    295 
    296 BackingStoreGtk::~BackingStoreGtk() {
    297   // In unit tests, display_ may be NULL.
    298   if (!display_)
    299     return;
    300 
    301   XRenderFreePicture(display_, picture_);
    302   XFreePixmap(display_, pixmap_);
    303   XFreeGC(display_, static_cast<GC>(pixmap_gc_));
    304 }
    305 
    306 size_t BackingStoreGtk::MemorySize() {
    307   if (!use_render_)
    308     return size().GetArea() * (pixmap_bpp_ / 8);
    309   else
    310     return size().GetArea() * 4;
    311 }
    312 
    313 void BackingStoreGtk::PaintRectWithoutXrender(
    314     TransportDIB* bitmap,
    315     const gfx::Rect& bitmap_rect,
    316     const std::vector<gfx::Rect>& copy_rects) {
    317   const int width = bitmap_rect.width();
    318   const int height = bitmap_rect.height();
    319   Pixmap pixmap = XCreatePixmap(display_, root_window_, width, height,
    320                                 visual_depth_);
    321 
    322   // Draw ARGB transport DIB onto our pixmap.
    323   ui::PutARGBImage(display_, visual_, visual_depth_, pixmap,
    324                    pixmap_gc_, static_cast<uint8*>(bitmap->memory()),
    325                    width, height);
    326 
    327   for (size_t i = 0; i < copy_rects.size(); i++) {
    328     const gfx::Rect& copy_rect = copy_rects[i];
    329     XCopyArea(display_,
    330               pixmap,                           // src
    331               pixmap_,                          // dest
    332               static_cast<GC>(pixmap_gc_),      // gc
    333               copy_rect.x() - bitmap_rect.x(),  // src_x
    334               copy_rect.y() - bitmap_rect.y(),  // src_y
    335               copy_rect.width(),                // width
    336               copy_rect.height(),               // height
    337               copy_rect.x(),                    // dest_x
    338               copy_rect.y());                   // dest_y
    339   }
    340 
    341   XFreePixmap(display_, pixmap);
    342 }
    343 
    344 void BackingStoreGtk::PaintToBackingStore(
    345     RenderProcessHost* process,
    346     TransportDIB::Id bitmap,
    347     const gfx::Rect& bitmap_rect,
    348     const std::vector<gfx::Rect>& copy_rects,
    349     float scale_factor,
    350     const base::Closure& completion_callback,
    351     bool* scheduled_completion_callback) {
    352   *scheduled_completion_callback = false;
    353 
    354   if (!display_)
    355     return;
    356 
    357   if (bitmap_rect.IsEmpty())
    358     return;
    359 
    360   gfx::Rect pixel_bitmap_rect = gfx::ToEnclosedRect(
    361       gfx::ScaleRect(bitmap_rect, scale_factor));
    362   const int width = pixel_bitmap_rect.width();
    363   const int height = pixel_bitmap_rect.height();
    364 
    365   if (width <= 0 || width > kMaxVideoLayerSize ||
    366       height <= 0 || height > kMaxVideoLayerSize)
    367     return;
    368 
    369   TransportDIB* dib = process->GetTransportDIB(bitmap);
    370   if (!dib)
    371     return;
    372 
    373   if (!use_render_)
    374     return PaintRectWithoutXrender(dib, bitmap_rect, copy_rects);
    375 
    376   Picture picture;
    377   Pixmap pixmap;
    378 
    379   if (shared_memory_support_ == ui::SHARED_MEMORY_PIXMAP) {
    380     XShmSegmentInfo shminfo = {0};
    381     shminfo.shmseg = dib->MapToX(display_);
    382 
    383     // The NULL in the following is the |data| pointer: this is an artifact of
    384     // Xlib trying to be helpful, rather than just exposing the X protocol. It
    385     // assumes that we have the shared memory segment mapped into our memory,
    386     // which we don't, and it's trying to calculate an offset by taking the
    387     // difference between the |data| pointer and the address of the mapping in
    388     // |shminfo|. Since both are NULL, the offset will be calculated to be 0,
    389     // which is correct for us.
    390     pixmap = XShmCreatePixmap(display_, root_window_, NULL, &shminfo,
    391                               width, height, 32);
    392   } else {
    393     // We don't have shared memory pixmaps.  Fall back to creating a pixmap
    394     // ourselves and putting an image on it.
    395     pixmap = XCreatePixmap(display_, root_window_, width, height, 32);
    396     GC gc = XCreateGC(display_, pixmap, 0, NULL);
    397 
    398     if (shared_memory_support_ == ui::SHARED_MEMORY_PUTIMAGE) {
    399       const XID shmseg = dib->MapToX(display_);
    400 
    401       XShmSegmentInfo shminfo;
    402       memset(&shminfo, 0, sizeof(shminfo));
    403       shminfo.shmseg = shmseg;
    404       shminfo.shmaddr = static_cast<char*>(dib->memory());
    405 
    406       XImage* image = XShmCreateImage(display_, static_cast<Visual*>(visual_),
    407                                       32, ZPixmap,
    408                                       shminfo.shmaddr, &shminfo,
    409                                       width, height);
    410 
    411       // This code path is important for performance and we have found that
    412       // different techniques work better on different platforms. See
    413       // http://code.google.com/p/chromium/issues/detail?id=44124.
    414       //
    415       // Checking for ARM is an approximation, but it seems to be a good one so
    416       // far.
    417 #if defined(ARCH_CPU_ARM_FAMILY)
    418       for (size_t i = 0; i < copy_rects.size(); i++) {
    419         const gfx::Rect& copy_rect = copy_rects[i];
    420         gfx::Rect pixel_copy_rect = gfx::ToEnclosedRect(
    421             gfx::ScaleRect(copy_rect, scale_factor));
    422         XShmPutImage(display_, pixmap, gc, image,
    423                      pixel_copy_rect.x() - pixel_bitmap_rect.x(), /* source x */
    424                      pixel_copy_rect.y() - pixel_bitmap_rect.y(), /* source y */
    425                      pixel_copy_rect.x() - pixel_bitmap_rect.x(), /* dest x */
    426                      pixel_copy_rect.y() - pixel_bitmap_rect.y(), /* dest y */
    427                      pixel_copy_rect.width(), pixel_copy_rect.height(),
    428                      False /* send_event */);
    429       }
    430 #else
    431       XShmPutImage(display_, pixmap, gc, image,
    432                    0, 0 /* source x, y */, 0, 0 /* dest x, y */,
    433                    width, height, False /* send_event */);
    434 #endif
    435       XDestroyImage(image);
    436     } else {  // case SHARED_MEMORY_NONE
    437       // No shared memory support, we have to copy the bitmap contents
    438       // to the X server. Xlib wraps the underlying PutImage call
    439       // behind several layers of functions which try to convert the
    440       // image into the format which the X server expects. The
    441       // following values hopefully disable all conversions.
    442       XImage image;
    443       memset(&image, 0, sizeof(image));
    444 
    445       image.width = width;
    446       image.height = height;
    447       image.depth = 32;
    448       image.bits_per_pixel = 32;
    449       image.format = ZPixmap;
    450       image.byte_order = LSBFirst;
    451       image.bitmap_unit = 8;
    452       image.bitmap_bit_order = LSBFirst;
    453       image.bytes_per_line = width * 4;
    454       image.red_mask = 0xff;
    455       image.green_mask = 0xff00;
    456       image.blue_mask = 0xff0000;
    457       image.data = static_cast<char*>(dib->memory());
    458 
    459       XPutImage(display_, pixmap, gc, &image,
    460                 0, 0 /* source x, y */, 0, 0 /* dest x, y */,
    461                 width, height);
    462     }
    463     XFreeGC(display_, gc);
    464   }
    465 
    466   picture = ui::CreatePictureFromSkiaPixmap(display_, pixmap);
    467 
    468   if (scale_factor != 1.0) {
    469     float up_scale = 1.0 / scale_factor;
    470     XTransform scaling = { {
    471         { XDoubleToFixed(1), XDoubleToFixed(0), XDoubleToFixed(0) },
    472         { XDoubleToFixed(0), XDoubleToFixed(1), XDoubleToFixed(0) },
    473         { XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(up_scale) }
    474         } };
    475     XRenderSetPictureTransform(display_, picture, &scaling);
    476     XRenderSetPictureFilter(display_, picture, FilterGood, NULL, 0);
    477   }
    478   for (size_t i = 0; i < copy_rects.size(); i++) {
    479     const gfx::Rect& copy_rect = copy_rects[i];
    480     XRenderComposite(display_,
    481                      PictOpSrc,                        // op
    482                      picture,                          // src
    483                      0,                                // mask
    484                      picture_,                         // dest
    485                      copy_rect.x() - bitmap_rect.x(),  // src_x
    486                      copy_rect.y() - bitmap_rect.y(),  // src_y
    487                      0,                                // mask_x
    488                      0,                                // mask_y
    489                      copy_rect.x(),                    // dest_x
    490                      copy_rect.y(),                    // dest_y
    491                      copy_rect.width(),                // width
    492                      copy_rect.height());              // height
    493   }
    494 
    495   // In the case of shared memory, we wait for the composite to complete so that
    496   // we are sure that the X server has finished reading from the shared memory
    497   // segment.
    498   if (shared_memory_support_ != ui::SHARED_MEMORY_NONE) {
    499     XSyncHandler* handler = XSyncHandler::GetInstance();
    500     if (handler->Enabled()) {
    501       *scheduled_completion_callback = true;
    502       handler->PushPaintCounter(
    503           dib, display_, picture, pixmap, completion_callback);
    504     } else {
    505       XSync(display_, False);
    506     }
    507   }
    508 
    509   if (*scheduled_completion_callback == false) {
    510     // If we didn't schedule a callback, we need to delete our resources now.
    511     XRenderFreePicture(display_, picture);
    512     XFreePixmap(display_, pixmap);
    513   }
    514 }
    515 
    516 bool BackingStoreGtk::CopyFromBackingStore(const gfx::Rect& rect,
    517                                            skia::PlatformBitmap* output) {
    518   base::TimeTicks begin_time = base::TimeTicks::Now();
    519 
    520   if (visual_depth_ < 24) {
    521     // CopyFromBackingStore() copies pixels out of the XImage
    522     // in a way that assumes that each component (red, green,
    523     // blue) is a byte.  This doesn't work on visuals which
    524     // encode a pixel color with less than a byte per color.
    525     return false;
    526   }
    527 
    528   const int width = std::min(size().width(), rect.width());
    529   const int height = std::min(size().height(), rect.height());
    530 
    531   XImage* image;
    532   XShmSegmentInfo shminfo;  // Used only when shared memory is enabled.
    533   if (shared_memory_support_ != ui::SHARED_MEMORY_NONE) {
    534     // Use shared memory for faster copies when it's available.
    535     Visual* visual = static_cast<Visual*>(visual_);
    536     memset(&shminfo, 0, sizeof(shminfo));
    537     image = XShmCreateImage(display_, visual, 32,
    538                             ZPixmap, NULL, &shminfo, width, height);
    539     if (!image) {
    540       return false;
    541     }
    542     // Create the shared memory segment for the image and map it.
    543     if (image->bytes_per_line == 0 || image->height == 0 ||
    544         static_cast<size_t>(image->height) >
    545         (std::numeric_limits<size_t>::max() / image->bytes_per_line)) {
    546       XDestroyImage(image);
    547       return false;
    548     }
    549     shminfo.shmid = shmget(IPC_PRIVATE, image->bytes_per_line * image->height,
    550                            IPC_CREAT|0600);
    551     if (shminfo.shmid == -1) {
    552       XDestroyImage(image);
    553       LOG(WARNING) << "Failed to get shared memory segment. "
    554                       "Performance may be degraded.";
    555       return false;
    556     } else {
    557       VLOG(1) << "Got shared memory segment " << shminfo.shmid;
    558     }
    559 
    560     void* mapped_memory = shmat(shminfo.shmid, NULL, SHM_RDONLY);
    561     shmctl(shminfo.shmid, IPC_RMID, 0);
    562     if (mapped_memory == (void*)-1) {
    563       XDestroyImage(image);
    564       return false;
    565     }
    566     shminfo.shmaddr = image->data = static_cast<char*>(mapped_memory);
    567 
    568     if (!XShmAttach(display_, &shminfo) ||
    569         !XShmGetImage(display_, pixmap_, image, rect.x(), rect.y(),
    570                       AllPlanes)) {
    571       DestroySharedImage(display_, image, &shminfo);
    572       LOG(WARNING) << "X failed to get shared memory segment. "
    573                       "Performance may be degraded.";
    574       return false;
    575     }
    576 
    577     VLOG(1) << "Using X shared memory segment " << shminfo.shmid;
    578   } else {
    579     LOG(WARNING) << "Not using X shared memory.";
    580     // Non-shared memory case just copy the image from the server.
    581     image = XGetImage(display_, pixmap_,
    582                       rect.x(), rect.y(), width, height,
    583                       AllPlanes, ZPixmap);
    584   }
    585 
    586   // TODO(jhawkins): Need to convert the image data if the image bits per pixel
    587   // is not 32.
    588   // Note that this also initializes the output bitmap as opaque.
    589   if (!output->Allocate(width, height, true) ||
    590       image->bits_per_pixel != 32) {
    591     if (shared_memory_support_ != ui::SHARED_MEMORY_NONE)
    592       DestroySharedImage(display_, image, &shminfo);
    593     else
    594       XDestroyImage(image);
    595     return false;
    596   }
    597 
    598   // The X image might have a different row stride, so iterate through
    599   // it and copy each row out, only up to the pixels we're actually
    600   // using.  This code assumes a visual mode where a pixel is
    601   // represented using a 32-bit unsigned int, with a byte per component.
    602   const SkBitmap& bitmap = output->GetBitmap();
    603   SkAutoLockPixels alp(bitmap);
    604 
    605   for (int y = 0; y < height; y++) {
    606     const uint32* src_row = reinterpret_cast<uint32*>(
    607         &image->data[image->bytes_per_line * y]);
    608     uint32* dest_row = bitmap.getAddr32(0, y);
    609     for (int x = 0; x < width; ++x, ++dest_row) {
    610       // Force alpha to be 0xff, because otherwise it causes rendering problems.
    611       *dest_row = src_row[x] | 0xff000000;
    612     }
    613   }
    614 
    615   if (shared_memory_support_ != ui::SHARED_MEMORY_NONE)
    616     DestroySharedImage(display_, image, &shminfo);
    617   else
    618     XDestroyImage(image);
    619 
    620   HISTOGRAM_TIMES("BackingStore.RetrievalFromX",
    621                   base::TimeTicks::Now() - begin_time);
    622   return true;
    623 }
    624 
    625 void BackingStoreGtk::ScrollBackingStore(const gfx::Vector2d& delta,
    626                                          const gfx::Rect& clip_rect,
    627                                          const gfx::Size& view_size) {
    628   if (!display_)
    629     return;
    630 
    631   // We only support scrolling in one direction at a time.
    632   DCHECK(delta.x() == 0 || delta.y() == 0);
    633 
    634   if (delta.y()) {
    635     // Positive values of |delta|.y() scroll up
    636     if (abs(delta.y()) < clip_rect.height()) {
    637       XCopyArea(display_, pixmap_, pixmap_, static_cast<GC>(pixmap_gc_),
    638                 clip_rect.x() /* source x */,
    639                 std::max(clip_rect.y(), clip_rect.y() - delta.y()),
    640                 clip_rect.width(),
    641                 clip_rect.height() - abs(delta.y()),
    642                 clip_rect.x() /* dest x */,
    643                 std::max(clip_rect.y(), clip_rect.y() + delta.y()) /* dest y */
    644                 );
    645     }
    646   } else if (delta.x()) {
    647     // Positive values of |delta|.x() scroll right
    648     if (abs(delta.x()) < clip_rect.width()) {
    649       XCopyArea(display_, pixmap_, pixmap_, static_cast<GC>(pixmap_gc_),
    650                 std::max(clip_rect.x(), clip_rect.x() - delta.x()),
    651                 clip_rect.y() /* source y */,
    652                 clip_rect.width() - abs(delta.x()),
    653                 clip_rect.height(),
    654                 std::max(clip_rect.x(), clip_rect.x() + delta.x()) /* dest x */,
    655                 clip_rect.y() /* dest x */);
    656     }
    657   }
    658 }
    659 
    660 void BackingStoreGtk::XShowRect(const gfx::Point &origin,
    661                                 const gfx::Rect& rect, XID target) {
    662   XCopyArea(display_, pixmap_, target, static_cast<GC>(pixmap_gc_),
    663             rect.x(), rect.y(), rect.width(), rect.height(),
    664             rect.x() + origin.x(), rect.y() + origin.y());
    665 }
    666 
    667 #if defined(TOOLKIT_GTK)
    668 void BackingStoreGtk::PaintToRect(const gfx::Rect& rect, GdkDrawable* target) {
    669   cairo_surface_t* surface = cairo_xlib_surface_create(
    670       display_, pixmap_, static_cast<Visual*>(visual_),
    671       size().width(), size().height());
    672   cairo_t* cr = gdk_cairo_create(target);
    673 
    674   cairo_translate(cr, rect.x(), rect.y());
    675   double x_scale = static_cast<double>(rect.width()) / size().width();
    676   double y_scale = static_cast<double>(rect.height()) / size().height();
    677   cairo_scale(cr, x_scale, y_scale);
    678 
    679   cairo_pattern_t* pattern = cairo_pattern_create_for_surface(surface);
    680   cairo_pattern_set_filter(pattern, CAIRO_FILTER_BEST);
    681   cairo_set_source(cr, pattern);
    682   cairo_pattern_destroy(pattern);
    683 
    684   cairo_identity_matrix(cr);
    685 
    686   cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
    687   cairo_fill(cr);
    688   cairo_destroy(cr);
    689 }
    690 #endif
    691 
    692 }  // namespace content
    693