OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/renderer_host/backing_store.h" | 5 #include "chrome/browser/renderer_host/backing_store.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
| 9 #include "base/compiler_specific.h" |
9 #include "base/logging.h" | 10 #include "base/logging.h" |
10 #include "chrome/common/transport_dib.h" | 11 #include "chrome/common/transport_dib.h" |
11 #include "chrome/common/x11_util.h" | 12 #include "chrome/common/x11_util.h" |
12 #include "chrome/common/x11_util_internal.h" | 13 #include "chrome/common/x11_util_internal.h" |
13 | 14 |
14 // X Backing Stores: | 15 // X Backing Stores: |
15 // | 16 // |
16 // Unlike Windows, where the backing store is kept in heap memory, we keep our | 17 // 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 // 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 // instructing the X server to copy from the backing store to the window. |
19 // | 20 // |
20 // The backing store is in the same format as the visual which our main window | 21 // 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 // 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 // shared memory or over the wire, and XRENDER is used to convert them to the |
23 // correct format for the backing store. | 24 // correct format for the backing store. |
24 | 25 |
25 BackingStore::BackingStore(const gfx::Size& size, | 26 BackingStore::BackingStore(const gfx::Size& size, |
26 Display* display, | 27 Display* display, |
27 int depth, | 28 int depth, |
28 void* visual, | 29 void* visual, |
29 Drawable root_window, | 30 Drawable root_window, |
| 31 bool use_render, |
30 bool use_shared_memory) | 32 bool use_shared_memory) |
31 : size_(size), | 33 : size_(size), |
32 display_(display), | 34 display_(display), |
33 use_shared_memory_(use_shared_memory), | 35 use_shared_memory_(use_shared_memory), |
| 36 use_render_(use_render), |
| 37 visual_depth_(depth), |
34 root_window_(root_window) { | 38 root_window_(root_window) { |
35 const int width = size.width(); | 39 const int width = size.width(); |
36 const int height = size.height(); | 40 const int height = size.height(); |
37 | 41 |
| 42 COMPILE_ASSERT(__BYTE_ORDER == __LITTLE_ENDIAN, assumes_little_endian); |
| 43 |
38 pixmap_ = XCreatePixmap(display_, root_window, width, height, depth); | 44 pixmap_ = XCreatePixmap(display_, root_window, width, height, depth); |
39 picture_ = XRenderCreatePicture( | 45 |
40 display_, pixmap_, | 46 if (use_render_) { |
41 x11_util::GetRenderVisualFormat(display_, static_cast<Visual*>(visual)), | 47 picture_ = XRenderCreatePicture( |
42 0, NULL); | 48 display_, pixmap_, |
| 49 x11_util::GetRenderVisualFormat(display_, static_cast<Visual*>(visual)), |
| 50 0, NULL); |
| 51 } else { |
| 52 picture_ = 0; |
| 53 pixmap_bpp_ = x11_util::BitsPerPixelForPixmapDepth(display, depth); |
| 54 } |
| 55 |
43 pixmap_gc_ = XCreateGC(display_, pixmap_, 0, NULL); | 56 pixmap_gc_ = XCreateGC(display_, pixmap_, 0, NULL); |
44 } | 57 } |
45 | 58 |
46 BackingStore::BackingStore(const gfx::Size& size) | 59 BackingStore::BackingStore(const gfx::Size& size) |
47 : size_(size), | 60 : size_(size), |
48 display_(NULL), | 61 display_(NULL), |
49 use_shared_memory_(false), | 62 use_shared_memory_(false), |
| 63 use_render_(false), |
| 64 visual_depth_(-1), |
50 root_window_(0) { | 65 root_window_(0) { |
51 } | 66 } |
52 | 67 |
53 BackingStore::~BackingStore() { | 68 BackingStore::~BackingStore() { |
54 // In unit tests, display_ may be NULL. | 69 // In unit tests, display_ may be NULL. |
55 if (!display_) | 70 if (!display_) |
56 return; | 71 return; |
57 | 72 |
58 XRenderFreePicture(display_, picture_); | 73 XRenderFreePicture(display_, picture_); |
59 XFreePixmap(display_, pixmap_); | 74 XFreePixmap(display_, pixmap_); |
60 XFreeGC(display_, static_cast<GC>(pixmap_gc_)); | 75 XFreeGC(display_, static_cast<GC>(pixmap_gc_)); |
61 } | 76 } |
62 | 77 |
| 78 void BackingStore::PaintRectWithoutXrender(TransportDIB* bitmap, |
| 79 const gfx::Rect &bitmap_rect) { |
| 80 const int width = bitmap_rect.width(); |
| 81 const int height = bitmap_rect.height(); |
| 82 Pixmap pixmap = XCreatePixmap(display_, root_window_, width, height, |
| 83 visual_depth_); |
| 84 |
| 85 XImage image; |
| 86 memset(&image, 0, sizeof(image)); |
| 87 |
| 88 image.width = width; |
| 89 image.height = height; |
| 90 image.format = ZPixmap; |
| 91 image.byte_order = LSBFirst; |
| 92 image.bitmap_unit = 8; |
| 93 image.bitmap_bit_order = LSBFirst; |
| 94 image.red_mask = 0xff; |
| 95 image.green_mask = 0xff00; |
| 96 image.blue_mask = 0xff0000; |
| 97 |
| 98 if (pixmap_bpp_ == 32) { |
| 99 // If the X server depth is already 32-bits, then our job is easy. |
| 100 image.depth = visual_depth_; |
| 101 image.bits_per_pixel = 32; |
| 102 image.bytes_per_line = width * 4; |
| 103 image.data = static_cast<char*>(bitmap->memory()); |
| 104 |
| 105 XPutImage(display_, pixmap, static_cast<GC>(pixmap_gc_), &image, |
| 106 0, 0 /* source x, y */, 0, 0 /* dest x, y */, |
| 107 width, height); |
| 108 } else if (pixmap_bpp_ == 24) { |
| 109 // In this case we just need to strip the alpha channel out of each |
| 110 // pixel. This is the case which covers VNC servers since they don't |
| 111 // support Xrender but typically have 24-bit visuals. |
| 112 // |
| 113 // It's possible to use some fancy SSE tricks here, but since this is the |
| 114 // slow path anyway, we do it slowly. |
| 115 |
| 116 uint8_t* bitmap24 = static_cast<uint8_t*>(malloc(3 * width * height)); |
| 117 const uint32_t* bitmap_in = static_cast<const uint32_t*>(bitmap->memory()); |
| 118 for (int y = 0; y < height; ++y) { |
| 119 for (int x = 0; x < width; ++x) { |
| 120 const uint32_t pixel = *(bitmap_in++); |
| 121 bitmap24[0] = (pixel >> 16) & 0xff; |
| 122 bitmap24[1] = (pixel >> 8) & 0xff; |
| 123 bitmap24[2] = pixel & 0xff; |
| 124 bitmap24 += 3; |
| 125 } |
| 126 } |
| 127 |
| 128 image.depth = visual_depth_; |
| 129 image.bits_per_pixel = 24; |
| 130 image.bytes_per_line = width * 3; |
| 131 image.data = reinterpret_cast<char*>(bitmap24); |
| 132 |
| 133 XPutImage(display_, pixmap, static_cast<GC>(pixmap_gc_), &image, |
| 134 0, 0 /* source x, y */, 0, 0 /* dest x, y */, |
| 135 width, height); |
| 136 |
| 137 free(bitmap24); |
| 138 } else { |
| 139 CHECK(false) << "Sorry, we don't support your visual depth without " |
| 140 "Xrender support (depth:" << visual_depth_ |
| 141 << " bpp:" << pixmap_bpp_ << ")"; |
| 142 } |
| 143 |
| 144 XCopyArea(display_, pixmap /* source */, pixmap_ /* target */, |
| 145 static_cast<GC>(pixmap_gc_), |
| 146 0, 0 /* source x, y */, bitmap_rect.width(), bitmap_rect.height(), |
| 147 bitmap_rect.x(), bitmap_rect.y() /* dest x, y */); |
| 148 |
| 149 XFreePixmap(display_, pixmap); |
| 150 } |
| 151 |
63 void BackingStore::PaintRect(base::ProcessHandle process, | 152 void BackingStore::PaintRect(base::ProcessHandle process, |
64 TransportDIB* bitmap, | 153 TransportDIB* bitmap, |
65 const gfx::Rect& bitmap_rect) { | 154 const gfx::Rect& bitmap_rect) { |
66 if (!display_) | 155 if (!display_) |
67 return; | 156 return; |
68 | 157 |
| 158 if (!use_render_) |
| 159 return PaintRectWithoutXrender(bitmap, bitmap_rect); |
| 160 |
69 const int width = bitmap_rect.width(); | 161 const int width = bitmap_rect.width(); |
70 const int height = bitmap_rect.height(); | 162 const int height = bitmap_rect.height(); |
71 Picture picture; | 163 Picture picture; |
72 Pixmap pixmap; | 164 Pixmap pixmap; |
73 | 165 |
74 if (use_shared_memory_) { | 166 if (use_shared_memory_) { |
75 const XID shmseg = bitmap->MapToX(display_); | 167 const XID shmseg = bitmap->MapToX(display_); |
76 | 168 |
77 XShmSegmentInfo shminfo; | 169 XShmSegmentInfo shminfo; |
78 memset(&shminfo, 0, sizeof(shminfo)); | 170 memset(&shminfo, 0, sizeof(shminfo)); |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 } | 252 } |
161 | 253 |
162 PaintRect(process, bitmap, bitmap_rect); | 254 PaintRect(process, bitmap, bitmap_rect); |
163 } | 255 } |
164 | 256 |
165 void BackingStore::ShowRect(const gfx::Rect& rect, XID target) { | 257 void BackingStore::ShowRect(const gfx::Rect& rect, XID target) { |
166 XCopyArea(display_, pixmap_, target, static_cast<GC>(pixmap_gc_), | 258 XCopyArea(display_, pixmap_, target, static_cast<GC>(pixmap_gc_), |
167 rect.x(), rect.y(), rect.width(), rect.height(), | 259 rect.x(), rect.y(), rect.width(), rect.height(), |
168 rect.x(), rect.y()); | 260 rect.x(), rect.y()); |
169 } | 261 } |
OLD | NEW |