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