OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "chrome/browser/renderer_host/backing_store.h" |
| 6 |
| 7 #include <utility> |
| 8 |
| 9 #include "base/logging.h" |
| 10 #include "chrome/common/transport_dib.h" |
| 11 #include "chrome/common/x11_util.h" |
| 12 #include "chrome/common/x11_util_internal.h" |
| 13 |
| 14 // X Backing Stores: |
| 15 // |
| 16 // Unlike Windows, where the backing store is kept in heap memory, we keep our |
| 17 // backing store in the X server, as a pixmap. Thus expose events just require |
| 18 // instructing the X server to copy from the backing store to the window. |
| 19 // |
| 20 // The backing store is in the same format as the visual which our main window |
| 21 // is using. Bitmaps from the renderer are uploaded to the X server, either via |
| 22 // shared memory or over the wire, and XRENDER is used to convert them to the |
| 23 // correct format for the backing store. |
| 24 |
| 25 BackingStore::BackingStore(const gfx::Size& size, |
| 26 Display* display, |
| 27 int depth, |
| 28 void* visual, |
| 29 Drawable parent_window, |
| 30 bool use_shared_memory) |
| 31 : size_(size), |
| 32 display_(display), |
| 33 use_shared_memory_(use_shared_memory), |
| 34 parent_window_(parent_window) { |
| 35 const int width = size.width(); |
| 36 const int height = size.height(); |
| 37 |
| 38 pixmap_ = XCreatePixmap(display_, parent_window, width, height, depth); |
| 39 picture_ = XRenderCreatePicture( |
| 40 display_, pixmap_, |
| 41 x11_util::GetRenderVisualFormat(display_, static_cast<Visual*>(visual)), |
| 42 0, NULL); |
| 43 pixmap_gc_ = XCreateGC(display_, pixmap_, 0, NULL); |
| 44 } |
| 45 |
| 46 BackingStore::BackingStore(const gfx::Size& size) |
| 47 : size_(size), |
| 48 display_(NULL), |
| 49 use_shared_memory_(false), |
| 50 parent_window_(0) { |
| 51 } |
| 52 |
| 53 BackingStore::~BackingStore() { |
| 54 // In unit tests, display_ may be NULL. |
| 55 if (!display_) |
| 56 return; |
| 57 |
| 58 XRenderFreePicture(display_, picture_); |
| 59 XFreePixmap(display_, pixmap_); |
| 60 XFreeGC(display_, static_cast<GC>(pixmap_gc_)); |
| 61 } |
| 62 |
| 63 void BackingStore::PaintRect(base::ProcessHandle process, |
| 64 TransportDIB* bitmap, |
| 65 const gfx::Rect& bitmap_rect) { |
| 66 if (!display_) |
| 67 return; |
| 68 |
| 69 const int width = bitmap_rect.width(); |
| 70 const int height = bitmap_rect.height(); |
| 71 Picture picture; |
| 72 Pixmap pixmap; |
| 73 |
| 74 if (use_shared_memory_) { |
| 75 const XID shmseg = bitmap->MapToX(display_); |
| 76 |
| 77 XShmSegmentInfo shminfo; |
| 78 memset(&shminfo, 0, sizeof(shminfo)); |
| 79 shminfo.shmseg = shmseg; |
| 80 |
| 81 // The NULL in the following is the |data| pointer: this is an artifact of |
| 82 // Xlib trying to be helpful, rather than just exposing the X protocol. It |
| 83 // assumes that we have the shared memory segment mapped into our memory, |
| 84 // which we don't, and it's trying to calculate an offset by taking the |
| 85 // difference between the |data| pointer and the address of the mapping in |
| 86 // |shminfo|. Since both are NULL, the offset will be calculated to be 0, |
| 87 // which is correct for us. |
| 88 pixmap = XShmCreatePixmap(display_, parent_window_, NULL, &shminfo, width, |
| 89 height, 32); |
| 90 } else { |
| 91 // No shared memory support, we have to copy the bitmap contents to the X |
| 92 // server. Xlib wraps the underlying PutImage call behind several layers of |
| 93 // functions which try to convert the image into the format which the X |
| 94 // server expects. The following values hopefully disable all conversions. |
| 95 XImage image; |
| 96 memset(&image, 0, sizeof(image)); |
| 97 |
| 98 image.width = width; |
| 99 image.height = height; |
| 100 image.depth = 32; |
| 101 image.bits_per_pixel = 32; |
| 102 image.format = ZPixmap; |
| 103 image.byte_order = LSBFirst; |
| 104 image.bitmap_unit = 8; |
| 105 image.bitmap_bit_order = LSBFirst; |
| 106 image.bytes_per_line = width * 4; |
| 107 image.red_mask = 0xff; |
| 108 image.green_mask = 0xff00; |
| 109 image.blue_mask = 0xff0000; |
| 110 image.data = static_cast<char*>(bitmap->memory()); |
| 111 |
| 112 pixmap = XCreatePixmap(display_, parent_window_, width, height, 32); |
| 113 GC gc = XCreateGC(display_, pixmap, 0, NULL); |
| 114 XPutImage(display_, pixmap, gc, &image, |
| 115 0, 0 /* source x, y */, 0, 0 /* dest x, y */, |
| 116 width, height); |
| 117 XFreeGC(display_, gc); |
| 118 } |
| 119 |
| 120 picture = x11_util::CreatePictureFromSkiaPixmap(display_, pixmap); |
| 121 XRenderComposite(display_, PictOpSrc, picture /* source */, 0 /* mask */, |
| 122 picture_ /* dest */, 0, 0 /* source x, y */, |
| 123 0, 0 /* mask x, y */, |
| 124 bitmap_rect.x(), bitmap_rect.y() /* target x, y */, |
| 125 width, height); |
| 126 |
| 127 // In the case of shared memory, we wait for the composite to complete so that |
| 128 // we are sure that the X server has finished reading. |
| 129 if (use_shared_memory_) |
| 130 XSync(display_, False); |
| 131 |
| 132 XRenderFreePicture(display_, picture); |
| 133 XFreePixmap(display_, pixmap); |
| 134 } |
| 135 |
| 136 void BackingStore::ScrollRect(base::ProcessHandle process, |
| 137 TransportDIB* bitmap, |
| 138 const gfx::Rect& bitmap_rect, |
| 139 int dx, int dy, |
| 140 const gfx::Rect& clip_rect, |
| 141 const gfx::Size& view_size) { |
| 142 if (!display_) |
| 143 return; |
| 144 |
| 145 // We only support scrolling in one direction at a time. |
| 146 DCHECK(dx == 0 || dy == 0); |
| 147 |
| 148 if (dy) { |
| 149 // Positive values of |dy| scroll up |
| 150 XCopyArea(display_, pixmap_, pixmap_, static_cast<GC>(pixmap_gc_), |
| 151 0, std::max(0, -dy) /* source x, y */, |
| 152 size_.width(), size_.height() - abs(dy), |
| 153 0, std::max(0, dy) /* dest x, y */); |
| 154 } else if (dx) { |
| 155 // Positive values of |dx| scroll right |
| 156 XCopyArea(display_, pixmap_, pixmap_, static_cast<GC>(pixmap_gc_), |
| 157 std::max(0, -dx), 0 /* source x, y */, |
| 158 size_.width() - abs(dx), size_.height(), |
| 159 std::max(0, dx), 0 /* dest x, y */); |
| 160 } |
| 161 |
| 162 PaintRect(process, bitmap, bitmap_rect); |
| 163 } |
| 164 |
| 165 void BackingStore::ShowRect(const gfx::Rect& rect) { |
| 166 XCopyArea(display_, pixmap_, parent_window_, static_cast<GC>(pixmap_gc_), |
| 167 rect.x(), rect.y(), rect.width(), rect.height(), |
| 168 rect.x(), rect.y()); |
| 169 } |
OLD | NEW |