15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/backing_store_gtk.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cairo-xlib.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <gtk/gtk.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/ipc.h>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/shm.h>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/extensions/sync.h>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_OPENBSD) || defined(OS_FREEBSD)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/endian.h>
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <limits>
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <queue>
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <utility>
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/singleton.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
27eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/render_process_host_impl.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "skia/ext/platform_canvas.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/gtk/gtk_signal.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/x/x11_util.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/x/x11_util_internal.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/rect.h"
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/rect_conversions.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/surface/transport_dib.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Assume that somewhere along the line, someone will do width * height * 4
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// with signed numbers. If the maximum value is 2**31, then 2**31 / 4 =
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 2**29 and floor(sqrt(2**29)) = 23170.
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Max height and width for layers
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kMaxVideoLayerSize = 23170;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// X Backing Stores:
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Unlike Windows, where the backing store is kept in heap memory, we keep our
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// backing store in the X server, as a pixmap. Thus expose events just require
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// instructing the X server to copy from the backing store to the window.
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The backing store is in the same format as the visual which our main window
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is using. Bitmaps from the renderer are uploaded to the X server, either via
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// shared memory or over the wire, and XRENDER is used to convert them to the
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// correct format for the backing store.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Destroys the image and the associated shared memory structures. This is a
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// helper function for code using shared memory.
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DestroySharedImage(Display* display,
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        XImage* image,
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        XShmSegmentInfo* shminfo) {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XShmDetach(display, shminfo);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XDestroyImage(image);
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  shmdt(shminfo->shmaddr);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// So we don't don't want to call XSync(), which can block the UI loop for
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ~100ms on first paint and is generally slow. We optionally use the
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// XSyncExtension to push a callback into the X11 event queue and get a
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// callback instead of blocking until the event queue is cleared.
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(erg): If ui::GetXDisplay() ever gets fixed to handle multiple Displays,
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this must be modified to be per Display instead of a Singleton.
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class XSyncHandler {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static XSyncHandler* GetInstance() {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return Singleton<XSyncHandler>::get();
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Enabled() {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return loaded_extension_;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void PushPaintCounter(TransportDIB* dib,
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        Display* display,
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        Picture picture,
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        Pixmap pixmap,
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const base::Closure& completion_callback);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend struct DefaultSingletonTraits<XSyncHandler>;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A struct that has cleanup and callback tasks that were queued into the
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // future and are run on |g_backing_store_sync_alarm| firing.
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct BackingStoreEvents {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BackingStoreEvents(TransportDIB* dib, Display* d, Picture pic, Pixmap pix,
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const base::Closure& c)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        : dib(dib),
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          display(d),
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          picture(pic),
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          pixmap(pix),
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          closure(c) {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dib->IncreaseInFlightCounter();
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TransportDIB* dib;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The display we're running on.
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Display* display;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Data to delete.
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Picture picture;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Pixmap pixmap;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Callback once everything else is done.
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::Closure closure;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XSyncHandler();
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~XSyncHandler();
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // An event filter notified about all XEvents. We then filter out XSync
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // events that are on counters that we made.
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHROMEG_CALLBACK_1(XSyncHandler, GdkFilterReturn, OnEvent, GdkXEvent*,
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     GdkEvent*);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Whether we successfully loaded XSyncExtension.
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool loaded_extension_;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The event ids returned to us by XSyncQueryExtension().
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int xsync_event_base_;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int xsync_error_base_;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XSyncCounter backing_store_sync_counter_;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XSyncAlarm backing_store_sync_alarm_;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A queue of pending paints that we clean up after as alarms fire.
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::queue<BackingStoreEvents*> backing_store_events_;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void XSyncHandler::PushPaintCounter(TransportDIB* dib,
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    Display* display,
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    Picture picture,
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    Pixmap pixmap,
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    const base::Closure& completion_callback) {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  backing_store_events_.push(new BackingStoreEvents(
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dib, display, picture, pixmap, completion_callback));
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Push a change counter event into the X11 event queue that will trigger our
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // alarm when it is processed.
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XSyncValue value;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XSyncIntToValue(&value, 1);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XSyncChangeCounter(ui::GetXDisplay(),
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     backing_store_sync_counter_,
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     value);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)XSyncHandler::XSyncHandler()
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : loaded_extension_(false),
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      xsync_event_base_(0),
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      xsync_error_base_(0),
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      backing_store_sync_counter_(0),
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      backing_store_sync_alarm_(0) {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Display* display = ui::GetXDisplay();
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (XSyncQueryExtension(display,
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          &xsync_event_base_,
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          &xsync_error_base_)) {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Create our monotonically increasing counter.
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XSyncValue value;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XSyncIntToValue(&value, 0);
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    backing_store_sync_counter_ = XSyncCreateCounter(display, value);
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Cerate our alarm that watches for changes to our counter.
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XSyncAlarmAttributes attributes;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    attributes.trigger.counter = backing_store_sync_counter_;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    backing_store_sync_alarm_ = XSyncCreateAlarm(display,
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 XSyncCACounter,
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 &attributes);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Add our filter to the message loop to handle alarm triggers.
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gdk_window_add_filter(NULL, &OnEventThunk, this);
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    loaded_extension_ = true;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)XSyncHandler::~XSyncHandler() {
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (loaded_extension_)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gdk_window_remove_filter(NULL, &OnEventThunk, this);
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XSync(ui::GetXDisplay(), False);
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (!backing_store_events_.empty()) {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We delete the X11 resources we're holding onto. We don't run the
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // callbacks because we are shutting down.
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BackingStoreEvents* data = backing_store_events_.front();
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    backing_store_events_.pop();
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XRenderFreePicture(data->display, data->picture);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XFreePixmap(data->display, data->pixmap);
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data->dib->DecreaseInFlightCounter();
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete data;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GdkFilterReturn XSyncHandler::OnEvent(GdkXEvent* gdkxevent,
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      GdkEvent* event) {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XEvent* xevent = reinterpret_cast<XEvent*>(gdkxevent);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (xevent->type == xsync_event_base_ + XSyncAlarmNotify) {
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XSyncAlarmNotifyEvent* alarm_event =
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reinterpret_cast<XSyncAlarmNotifyEvent*>(xevent);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (alarm_event->alarm == backing_store_sync_alarm_) {
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (alarm_event->counter_value.hi == 0 &&
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          alarm_event->counter_value.lo == 0) {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // We receive an event about the initial state of the counter during
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // alarm creation. We must ignore this event instead of responding to
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // it.
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return GDK_FILTER_REMOVE;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(!backing_store_events_.empty());
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BackingStoreEvents* data = backing_store_events_.front();
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      backing_store_events_.pop();
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We are responsible for deleting all the data in the struct now that
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // we are finished with it.
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      XRenderFreePicture(data->display, data->picture);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      XFreePixmap(data->display, data->pixmap);
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Dispatch the closure we were given.
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data->closure.Run();
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data->dib->DecreaseInFlightCounter();
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete data;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return GDK_FILTER_REMOVE;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GDK_FILTER_CONTINUE;
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BackingStoreGtk::BackingStoreGtk(RenderWidgetHost* widget,
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const gfx::Size& size,
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 void* visual,
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 int depth)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : BackingStore(widget, size),
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      display_(ui::GetXDisplay()),
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      shared_memory_support_(ui::QuerySharedMemorySupport(display_)),
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      use_render_(ui::QueryRenderSupport(display_)),
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      visual_(visual),
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      visual_depth_(depth),
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      root_window_(ui::GetX11RootWindow()) {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_OPENBSD) || defined(OS_FREEBSD)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  COMPILE_ASSERT(_BYTE_ORDER == _LITTLE_ENDIAN, assumes_little_endian);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  COMPILE_ASSERT(__BYTE_ORDER == __LITTLE_ENDIAN, assumes_little_endian);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pixmap_ = XCreatePixmap(display_, root_window_,
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          size.width(), size.height(), depth);
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (use_render_) {
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    picture_ = XRenderCreatePicture(
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        display_, pixmap_,
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ui::GetRenderVisualFormat(display_,
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  static_cast<Visual*>(visual)),
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  0, NULL);
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pixmap_bpp_ = 0;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    picture_ = 0;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pixmap_bpp_ = ui::BitsPerPixelForPixmapDepth(display_, depth);
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pixmap_gc_ = XCreateGC(display_, pixmap_, 0, NULL);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BackingStoreGtk::BackingStoreGtk(RenderWidgetHost* widget,
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const gfx::Size& size)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : BackingStore(widget, size),
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      display_(NULL),
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      shared_memory_support_(ui::SHARED_MEMORY_NONE),
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      use_render_(false),
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pixmap_bpp_(0),
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      visual_(NULL),
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      visual_depth_(-1),
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      root_window_(0),
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pixmap_(0),
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      picture_(0),
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pixmap_gc_(NULL) {
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BackingStoreGtk::~BackingStoreGtk() {
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In unit tests, display_ may be NULL.
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!display_)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XRenderFreePicture(display_, picture_);
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XFreePixmap(display_, pixmap_);
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XFreeGC(display_, static_cast<GC>(pixmap_gc_));
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t BackingStoreGtk::MemorySize() {
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!use_render_)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return size().GetArea() * (pixmap_bpp_ / 8);
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return size().GetArea() * 4;
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BackingStoreGtk::PaintRectWithoutXrender(
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TransportDIB* bitmap,
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Rect& bitmap_rect,
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<gfx::Rect>& copy_rects) {
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int width = bitmap_rect.width();
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int height = bitmap_rect.height();
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Pixmap pixmap = XCreatePixmap(display_, root_window_, width, height,
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                visual_depth_);
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Draw ARGB transport DIB onto our pixmap.
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ui::PutARGBImage(display_, visual_, visual_depth_, pixmap,
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   pixmap_gc_, static_cast<uint8*>(bitmap->memory()),
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   width, height);
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < copy_rects.size(); i++) {
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Rect& copy_rect = copy_rects[i];
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XCopyArea(display_,
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              pixmap,                           // src
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              pixmap_,                          // dest
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              static_cast<GC>(pixmap_gc_),      // gc
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              copy_rect.x() - bitmap_rect.x(),  // src_x
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              copy_rect.y() - bitmap_rect.y(),  // src_y
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              copy_rect.width(),                // width
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              copy_rect.height(),               // height
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              copy_rect.x(),                    // dest_x
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              copy_rect.y());                   // dest_y
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XFreePixmap(display_, pixmap);
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BackingStoreGtk::PaintToBackingStore(
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RenderProcessHost* process,
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TransportDIB::Id bitmap,
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Rect& bitmap_rect,
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<gfx::Rect>& copy_rects,
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    float scale_factor,
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Closure& completion_callback,
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool* scheduled_completion_callback) {
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *scheduled_completion_callback = false;
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!display_)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (bitmap_rect.IsEmpty())
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect pixel_bitmap_rect = gfx::ToEnclosedRect(
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gfx::ScaleRect(bitmap_rect, scale_factor));
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int width = pixel_bitmap_rect.width();
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int height = pixel_bitmap_rect.height();
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (width <= 0 || width > kMaxVideoLayerSize ||
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      height <= 0 || height > kMaxVideoLayerSize)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransportDIB* dib = process->GetTransportDIB(bitmap);
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!dib)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!use_render_)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PaintRectWithoutXrender(dib, bitmap_rect, copy_rects);
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Picture picture;
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Pixmap pixmap;
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (shared_memory_support_ == ui::SHARED_MEMORY_PIXMAP) {
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XShmSegmentInfo shminfo = {0};
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    shminfo.shmseg = dib->MapToX(display_);
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The NULL in the following is the |data| pointer: this is an artifact of
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Xlib trying to be helpful, rather than just exposing the X protocol. It
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // assumes that we have the shared memory segment mapped into our memory,
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // which we don't, and it's trying to calculate an offset by taking the
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // difference between the |data| pointer and the address of the mapping in
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // |shminfo|. Since both are NULL, the offset will be calculated to be 0,
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // which is correct for us.
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pixmap = XShmCreatePixmap(display_, root_window_, NULL, &shminfo,
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              width, height, 32);
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We don't have shared memory pixmaps.  Fall back to creating a pixmap
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // ourselves and putting an image on it.
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pixmap = XCreatePixmap(display_, root_window_, width, height, 32);
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GC gc = XCreateGC(display_, pixmap, 0, NULL);
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (shared_memory_support_ == ui::SHARED_MEMORY_PUTIMAGE) {
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const XID shmseg = dib->MapToX(display_);
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      XShmSegmentInfo shminfo;
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memset(&shminfo, 0, sizeof(shminfo));
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      shminfo.shmseg = shmseg;
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      shminfo.shmaddr = static_cast<char*>(dib->memory());
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      XImage* image = XShmCreateImage(display_, static_cast<Visual*>(visual_),
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      32, ZPixmap,
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      shminfo.shmaddr, &shminfo,
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      width, height);
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This code path is important for performance and we have found that
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // different techniques work better on different platforms. See
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // http://code.google.com/p/chromium/issues/detail?id=44124.
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      //
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Checking for ARM is an approximation, but it seems to be a good one so
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // far.
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(ARCH_CPU_ARM_FAMILY)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (size_t i = 0; i < copy_rects.size(); i++) {
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const gfx::Rect& copy_rect = copy_rects[i];
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        gfx::Rect pixel_copy_rect = gfx::ToEnclosedRect(
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            gfx::ScaleRect(copy_rect, scale_factor));
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        XShmPutImage(display_, pixmap, gc, image,
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     pixel_copy_rect.x() - pixel_bitmap_rect.x(), /* source x */
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     pixel_copy_rect.y() - pixel_bitmap_rect.y(), /* source y */
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     pixel_copy_rect.x() - pixel_bitmap_rect.x(), /* dest x */
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     pixel_copy_rect.y() - pixel_bitmap_rect.y(), /* dest y */
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     pixel_copy_rect.width(), pixel_copy_rect.height(),
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     False /* send_event */);
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      XShmPutImage(display_, pixmap, gc, image,
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   0, 0 /* source x, y */, 0, 0 /* dest x, y */,
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   width, height, False /* send_event */);
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      XDestroyImage(image);
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {  // case SHARED_MEMORY_NONE
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // No shared memory support, we have to copy the bitmap contents
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // to the X server. Xlib wraps the underlying PutImage call
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // behind several layers of functions which try to convert the
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // image into the format which the X server expects. The
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // following values hopefully disable all conversions.
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      XImage image;
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memset(&image, 0, sizeof(image));
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      image.width = width;
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      image.height = height;
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      image.depth = 32;
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      image.bits_per_pixel = 32;
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      image.format = ZPixmap;
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      image.byte_order = LSBFirst;
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      image.bitmap_unit = 8;
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      image.bitmap_bit_order = LSBFirst;
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      image.bytes_per_line = width * 4;
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      image.red_mask = 0xff;
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      image.green_mask = 0xff00;
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      image.blue_mask = 0xff0000;
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      image.data = static_cast<char*>(dib->memory());
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      XPutImage(display_, pixmap, gc, &image,
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                0, 0 /* source x, y */, 0, 0 /* dest x, y */,
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                width, height);
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XFreeGC(display_, gc);
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  picture = ui::CreatePictureFromSkiaPixmap(display_, pixmap);
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (scale_factor != 1.0) {
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    float up_scale = 1.0 / scale_factor;
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    XTransform scaling = { {
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        { XDoubleToFixed(1), XDoubleToFixed(0), XDoubleToFixed(0) },
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        { XDoubleToFixed(0), XDoubleToFixed(1), XDoubleToFixed(0) },
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        { XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(up_scale) }
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        } };
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    XRenderSetPictureTransform(display_, picture, &scaling);
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    XRenderSetPictureFilter(display_, picture, FilterGood, NULL, 0);
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < copy_rects.size(); i++) {
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Rect& copy_rect = copy_rects[i];
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XRenderComposite(display_,
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     PictOpSrc,                        // op
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     picture,                          // src
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     0,                                // mask
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     picture_,                         // dest
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     copy_rect.x() - bitmap_rect.x(),  // src_x
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     copy_rect.y() - bitmap_rect.y(),  // src_y
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     0,                                // mask_x
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     0,                                // mask_y
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     copy_rect.x(),                    // dest_x
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     copy_rect.y(),                    // dest_y
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     copy_rect.width(),                // width
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     copy_rect.height());              // height
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In the case of shared memory, we wait for the composite to complete so that
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we are sure that the X server has finished reading from the shared memory
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // segment.
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (shared_memory_support_ != ui::SHARED_MEMORY_NONE) {
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XSyncHandler* handler = XSyncHandler::GetInstance();
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (handler->Enabled()) {
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *scheduled_completion_callback = true;
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      handler->PushPaintCounter(
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          dib, display_, picture, pixmap, completion_callback);
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      XSync(display_, False);
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (*scheduled_completion_callback == false) {
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If we didn't schedule a callback, we need to delete our resources now.
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XRenderFreePicture(display_, picture);
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XFreePixmap(display_, pixmap);
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BackingStoreGtk::CopyFromBackingStore(const gfx::Rect& rect,
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           skia::PlatformBitmap* output) {
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeTicks begin_time = base::TimeTicks::Now();
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (visual_depth_ < 24) {
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // CopyFromBackingStore() copies pixels out of the XImage
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // in a way that assumes that each component (red, green,
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // blue) is a byte.  This doesn't work on visuals which
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // encode a pixel color with less than a byte per color.
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int width = std::min(size().width(), rect.width());
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int height = std::min(size().height(), rect.height());
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XImage* image;
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XShmSegmentInfo shminfo;  // Used only when shared memory is enabled.
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (shared_memory_support_ != ui::SHARED_MEMORY_NONE) {
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Use shared memory for faster copies when it's available.
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Visual* visual = static_cast<Visual*>(visual_);
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(&shminfo, 0, sizeof(shminfo));
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image = XShmCreateImage(display_, visual, 32,
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            ZPixmap, NULL, &shminfo, width, height);
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!image) {
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Create the shared memory segment for the image and map it.
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (image->bytes_per_line == 0 || image->height == 0 ||
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        static_cast<size_t>(image->height) >
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (std::numeric_limits<size_t>::max() / image->bytes_per_line)) {
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      XDestroyImage(image);
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    shminfo.shmid = shmget(IPC_PRIVATE, image->bytes_per_line * image->height,
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           IPC_CREAT|0600);
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (shminfo.shmid == -1) {
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      XDestroyImage(image);
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Failed to get shared memory segment. "
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      "Performance may be degraded.";
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VLOG(1) << "Got shared memory segment " << shminfo.shmid;
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* mapped_memory = shmat(shminfo.shmid, NULL, SHM_RDONLY);
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    shmctl(shminfo.shmid, IPC_RMID, 0);
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (mapped_memory == (void*)-1) {
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      XDestroyImage(image);
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    shminfo.shmaddr = image->data = static_cast<char*>(mapped_memory);
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!XShmAttach(display_, &shminfo) ||
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        !XShmGetImage(display_, pixmap_, image, rect.x(), rect.y(),
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      AllPlanes)) {
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DestroySharedImage(display_, image, &shminfo);
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "X failed to get shared memory segment. "
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      "Performance may be degraded.";
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Using X shared memory segment " << shminfo.shmid;
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Not using X shared memory.";
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Non-shared memory case just copy the image from the server.
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image = XGetImage(display_, pixmap_,
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      rect.x(), rect.y(), width, height,
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      AllPlanes, ZPixmap);
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(jhawkins): Need to convert the image data if the image bits per pixel
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is not 32.
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that this also initializes the output bitmap as opaque.
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!output->Allocate(width, height, true) ||
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      image->bits_per_pixel != 32) {
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (shared_memory_support_ != ui::SHARED_MEMORY_NONE)
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DestroySharedImage(display_, image, &shminfo);
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      XDestroyImage(image);
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The X image might have a different row stride, so iterate through
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it and copy each row out, only up to the pixels we're actually
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // using.  This code assumes a visual mode where a pixel is
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // represented using a 32-bit unsigned int, with a byte per component.
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SkBitmap& bitmap = output->GetBitmap();
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkAutoLockPixels alp(bitmap);
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int y = 0; y < height; y++) {
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const uint32* src_row = reinterpret_cast<uint32*>(
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &image->data[image->bytes_per_line * y]);
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32* dest_row = bitmap.getAddr32(0, y);
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int x = 0; x < width; ++x, ++dest_row) {
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Force alpha to be 0xff, because otherwise it causes rendering problems.
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *dest_row = src_row[x] | 0xff000000;
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (shared_memory_support_ != ui::SHARED_MEMORY_NONE)
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DestroySharedImage(display_, image, &shminfo);
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XDestroyImage(image);
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HISTOGRAM_TIMES("BackingStore.RetrievalFromX",
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  base::TimeTicks::Now() - begin_time);
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BackingStoreGtk::ScrollBackingStore(const gfx::Vector2d& delta,
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const gfx::Rect& clip_rect,
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const gfx::Size& view_size) {
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!display_)
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We only support scrolling in one direction at a time.
6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(delta.x() == 0 || delta.y() == 0);
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (delta.y()) {
6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Positive values of |delta|.y() scroll up
6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (abs(delta.y()) < clip_rect.height()) {
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      XCopyArea(display_, pixmap_, pixmap_, static_cast<GC>(pixmap_gc_),
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                clip_rect.x() /* source x */,
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                std::max(clip_rect.y(), clip_rect.y() - delta.y()),
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                clip_rect.width(),
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                clip_rect.height() - abs(delta.y()),
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                clip_rect.x() /* dest x */,
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                std::max(clip_rect.y(), clip_rect.y() + delta.y()) /* dest y */
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                );
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (delta.x()) {
6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Positive values of |delta|.x() scroll right
6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (abs(delta.x()) < clip_rect.width()) {
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      XCopyArea(display_, pixmap_, pixmap_, static_cast<GC>(pixmap_gc_),
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                std::max(clip_rect.x(), clip_rect.x() - delta.x()),
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                clip_rect.y() /* source y */,
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                clip_rect.width() - abs(delta.x()),
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                clip_rect.height(),
6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                std::max(clip_rect.x(), clip_rect.x() + delta.x()) /* dest x */,
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                clip_rect.y() /* dest x */);
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BackingStoreGtk::XShowRect(const gfx::Point &origin,
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const gfx::Rect& rect, XID target) {
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XCopyArea(display_, pixmap_, target, static_cast<GC>(pixmap_gc_),
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            rect.x(), rect.y(), rect.width(), rect.height(),
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            rect.x() + origin.x(), rect.y() + origin.y());
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(TOOLKIT_GTK)
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BackingStoreGtk::PaintToRect(const gfx::Rect& rect, GdkDrawable* target) {
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cairo_surface_t* surface = cairo_xlib_surface_create(
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      display_, pixmap_, static_cast<Visual*>(visual_),
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      size().width(), size().height());
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cairo_t* cr = gdk_cairo_create(target);
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cairo_translate(cr, rect.x(), rect.y());
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double x_scale = static_cast<double>(rect.width()) / size().width();
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double y_scale = static_cast<double>(rect.height()) / size().height();
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cairo_scale(cr, x_scale, y_scale);
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cairo_pattern_t* pattern = cairo_pattern_create_for_surface(surface);
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cairo_pattern_set_filter(pattern, CAIRO_FILTER_BEST);
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cairo_set_source(cr, pattern);
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cairo_pattern_destroy(pattern);
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cairo_identity_matrix(cr);
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cairo_fill(cr);
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cairo_destroy(cr);
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
693