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 <stdlib.h> | 7 #include <stdlib.h> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
70 // In unit tests, display_ may be NULL. | 70 // In unit tests, display_ may be NULL. |
71 if (!display_) | 71 if (!display_) |
72 return; | 72 return; |
73 | 73 |
74 XRenderFreePicture(display_, picture_); | 74 XRenderFreePicture(display_, picture_); |
75 XFreePixmap(display_, pixmap_); | 75 XFreePixmap(display_, pixmap_); |
76 XFreeGC(display_, static_cast<GC>(pixmap_gc_)); | 76 XFreeGC(display_, static_cast<GC>(pixmap_gc_)); |
77 } | 77 } |
78 | 78 |
79 void BackingStore::PaintRectWithoutXrender(TransportDIB* bitmap, | 79 void BackingStore::PaintRectWithoutXrender(TransportDIB* bitmap, |
80 const gfx::Rect &bitmap_rect) { | 80 const gfx::Rect& bitmap_rect, |
81 const int width = bitmap_rect.width(); | 81 const gfx::Rect& paint_rect) { |
82 const int height = bitmap_rect.height(); | 82 DCHECK(bitmap_rect.Contains(paint_rect) && |
83 Pixmap pixmap = XCreatePixmap(display_, root_window_, width, height, | 83 paint_rect.x() < kMaxBitmapLengthAllowed && |
84 visual_depth_); | 84 paint_rect.y() < kMaxBitmapLengthAllowed); |
| 85 const int paint_width = paint_rect.width(); |
| 86 const int paint_height = paint_rect.height(); |
| 87 Pixmap pixmap = XCreatePixmap(display_, root_window_, paint_width, |
| 88 paint_height, visual_depth_); |
85 | 89 |
| 90 const int bitmap_width = bitmap_rect.width(); |
| 91 const int bitmap_height = bitmap_rect.height(); |
86 XImage image; | 92 XImage image; |
87 memset(&image, 0, sizeof(image)); | 93 memset(&image, 0, sizeof(image)); |
88 | 94 |
89 image.width = width; | 95 image.width = bitmap_width; |
90 image.height = height; | 96 image.height = bitmap_height; |
91 image.format = ZPixmap; | 97 image.format = ZPixmap; |
92 image.byte_order = LSBFirst; | 98 image.byte_order = LSBFirst; |
93 image.bitmap_unit = 8; | 99 image.bitmap_unit = 8; |
94 image.bitmap_bit_order = LSBFirst; | 100 image.bitmap_bit_order = LSBFirst; |
95 image.red_mask = 0xff; | 101 image.red_mask = 0xff; |
96 image.green_mask = 0xff00; | 102 image.green_mask = 0xff00; |
97 image.blue_mask = 0xff0000; | 103 image.blue_mask = 0xff0000; |
98 | 104 |
| 105 const int x_offset = paint_rect.x() - bitmap_rect.x(); |
| 106 const int y_offset = paint_rect.y() - bitmap_rect.y(); |
99 if (pixmap_bpp_ == 32) { | 107 if (pixmap_bpp_ == 32) { |
100 // If the X server depth is already 32-bits, then our job is easy. | 108 // If the X server depth is already 32-bits, then our job is easy. |
101 image.depth = visual_depth_; | 109 image.depth = visual_depth_; |
102 image.bits_per_pixel = 32; | 110 image.bits_per_pixel = 32; |
103 image.bytes_per_line = width * 4; | 111 image.bytes_per_line = bitmap_width * 4; |
104 image.data = static_cast<char*>(bitmap->memory()); | 112 image.data = static_cast<char*>(bitmap->memory()); |
105 | 113 |
106 XPutImage(display_, pixmap, static_cast<GC>(pixmap_gc_), &image, | 114 XPutImage(display_, pixmap, static_cast<GC>(pixmap_gc_), &image, |
107 0, 0 /* source x, y */, 0, 0 /* dest x, y */, | 115 x_offset, y_offset /* source x, y */, 0, 0 /* dest x, y */, |
108 width, height); | 116 paint_width, paint_height); |
109 } else if (pixmap_bpp_ == 24) { | 117 } else if (pixmap_bpp_ == 24) { |
110 // In this case we just need to strip the alpha channel out of each | 118 // In this case we just need to strip the alpha channel out of each |
111 // pixel. This is the case which covers VNC servers since they don't | 119 // pixel. This is the case which covers VNC servers since they don't |
112 // support Xrender but typically have 24-bit visuals. | 120 // support Xrender but typically have 24-bit visuals. |
113 // | 121 // |
114 // It's possible to use some fancy SSE tricks here, but since this is the | 122 // It's possible to use some fancy SSE tricks here, but since this is the |
115 // slow path anyway, we do it slowly. | 123 // slow path anyway, we do it slowly. |
116 | 124 |
117 uint8_t* bitmap24 = static_cast<uint8_t*>(malloc(3 * width * height)); | 125 uint8_t* bitmap24 = static_cast<uint8_t*>(malloc(3 * paint_width * |
| 126 paint_height)); |
118 const uint32_t* bitmap_in = static_cast<const uint32_t*>(bitmap->memory()); | 127 const uint32_t* bitmap_in = static_cast<const uint32_t*>(bitmap->memory()); |
119 for (int y = 0; y < height; ++y) { | 128 const int x_limit = paint_rect.right() - bitmap_rect.x(); |
120 for (int x = 0; x < width; ++x) { | 129 const int y_limit = paint_rect.bottom() - bitmap_rect.y(); |
| 130 const int row_length = bitmap_width; |
| 131 bitmap_in += row_length * y_offset; |
| 132 for (int y = y_offset; y < y_limit; ++y) { |
| 133 bitmap_in += x_offset; |
| 134 for (int x = x_offset; x < x_limit; ++x) { |
121 const uint32_t pixel = *(bitmap_in++); | 135 const uint32_t pixel = *(bitmap_in++); |
122 bitmap24[0] = (pixel >> 16) & 0xff; | 136 bitmap24[0] = (pixel >> 16) & 0xff; |
123 bitmap24[1] = (pixel >> 8) & 0xff; | 137 bitmap24[1] = (pixel >> 8) & 0xff; |
124 bitmap24[2] = pixel & 0xff; | 138 bitmap24[2] = pixel & 0xff; |
125 bitmap24 += 3; | 139 bitmap24 += 3; |
126 } | 140 } |
| 141 bitmap_in += row_length - x_limit; |
127 } | 142 } |
128 | 143 |
| 144 image.width = paint_width; |
| 145 image.height = paint_height; |
129 image.depth = visual_depth_; | 146 image.depth = visual_depth_; |
130 image.bits_per_pixel = 24; | 147 image.bits_per_pixel = 24; |
131 image.bytes_per_line = width * 3; | 148 image.bytes_per_line = paint_width * 3; |
132 image.data = reinterpret_cast<char*>(bitmap24); | 149 image.data = reinterpret_cast<char*>(bitmap24); |
133 | 150 |
134 XPutImage(display_, pixmap, static_cast<GC>(pixmap_gc_), &image, | 151 XPutImage(display_, pixmap, static_cast<GC>(pixmap_gc_), &image, |
135 0, 0 /* source x, y */, 0, 0 /* dest x, y */, | 152 0, 0 /* source x, y */, 0, 0 /* dest x, y */, |
136 width, height); | 153 paint_width, paint_height); |
137 | 154 |
138 free(bitmap24); | 155 free(bitmap24); |
139 } else if (pixmap_bpp_ == 16) { | 156 } else if (pixmap_bpp_ == 16) { |
140 // Some folks have VNC setups which still use 16-bit visuals and VNC | 157 // Some folks have VNC setups which still use 16-bit visuals and VNC |
141 // doesn't include Xrender. | 158 // doesn't include Xrender. |
142 | 159 |
143 uint16_t* bitmap16 = static_cast<uint16_t*>(malloc(2 * width * height)); | 160 uint16_t* bitmap16 = static_cast<uint16_t*>(malloc(2 * paint_width * |
| 161 paint_height)); |
144 uint16_t* const orig_bitmap16 = bitmap16; | 162 uint16_t* const orig_bitmap16 = bitmap16; |
145 const uint32_t* bitmap_in = static_cast<const uint32_t*>(bitmap->memory()); | 163 const uint32_t* bitmap_in = static_cast<const uint32_t*>(bitmap->memory()); |
146 for (int y = 0; y < height; ++y) { | 164 const int x_limit = paint_rect.right() - bitmap_rect.x(); |
147 for (int x = 0; x < width; ++x) { | 165 const int y_limit = paint_rect.bottom() - bitmap_rect.y(); |
| 166 const int row_length = bitmap_width; |
| 167 bitmap_in += row_length * y_offset; |
| 168 for (int y = y_offset; y < y_limit; ++y) { |
| 169 bitmap_in += x_offset; |
| 170 for (int x = x_offset; x < x_limit; ++x) { |
148 const uint32_t pixel = *(bitmap_in++); | 171 const uint32_t pixel = *(bitmap_in++); |
149 uint16_t out_pixel = ((pixel >> 8) & 0xf800) | | 172 uint16_t out_pixel = ((pixel >> 8) & 0xf800) | |
150 ((pixel >> 5) & 0x07e0) | | 173 ((pixel >> 5) & 0x07e0) | |
151 ((pixel >> 3) & 0x001f); | 174 ((pixel >> 3) & 0x001f); |
152 *(bitmap16++) = out_pixel; | 175 *(bitmap16++) = out_pixel; |
153 } | 176 } |
| 177 bitmap_in += row_length - x_limit; |
154 } | 178 } |
155 | 179 |
156 image.depth = visual_depth_; | 180 image.depth = visual_depth_; |
157 image.bits_per_pixel = 16; | 181 image.bits_per_pixel = 16; |
158 image.bytes_per_line = width * 2; | 182 image.bytes_per_line = paint_width * 2; |
159 image.data = reinterpret_cast<char*>(orig_bitmap16); | 183 image.data = reinterpret_cast<char*>(orig_bitmap16); |
160 | 184 |
161 image.red_mask = 0xf800; | 185 image.red_mask = 0xf800; |
162 image.green_mask = 0x07e0; | 186 image.green_mask = 0x07e0; |
163 image.blue_mask = 0x001f; | 187 image.blue_mask = 0x001f; |
164 | 188 |
165 XPutImage(display_, pixmap, static_cast<GC>(pixmap_gc_), &image, | 189 XPutImage(display_, pixmap, static_cast<GC>(pixmap_gc_), &image, |
166 0, 0 /* source x, y */, 0, 0 /* dest x, y */, | 190 0, 0 /* source x, y */, 0, 0 /* dest x, y */, |
167 width, height); | 191 paint_width, paint_height); |
168 free(orig_bitmap16); | 192 free(orig_bitmap16); |
169 } else { | 193 } else { |
170 CHECK(false) << "Sorry, we don't support your visual depth without " | 194 CHECK(false) << "Sorry, we don't support your visual depth without " |
171 "Xrender support (depth:" << visual_depth_ | 195 "Xrender support (depth:" << visual_depth_ |
172 << " bpp:" << pixmap_bpp_ << ")"; | 196 << " bpp:" << pixmap_bpp_ << ")"; |
173 } | 197 } |
174 | 198 |
175 XCopyArea(display_, pixmap /* source */, pixmap_ /* target */, | 199 XCopyArea(display_, pixmap /* source */, pixmap_ /* target */, |
176 static_cast<GC>(pixmap_gc_), | 200 static_cast<GC>(pixmap_gc_), |
177 0, 0 /* source x, y */, bitmap_rect.width(), bitmap_rect.height(), | 201 0, 0 /* source x, y */, paint_width, paint_height, |
178 bitmap_rect.x(), bitmap_rect.y() /* dest x, y */); | 202 paint_rect.x(), paint_rect.y() /* dest x, y */); |
179 | 203 |
180 XFreePixmap(display_, pixmap); | 204 XFreePixmap(display_, pixmap); |
181 } | 205 } |
182 | 206 |
183 void BackingStore::PaintRect(base::ProcessHandle process, | 207 void BackingStore::PaintRect(base::ProcessHandle process, |
184 TransportDIB* bitmap, | 208 TransportDIB* bitmap, |
185 const gfx::Rect& bitmap_rect) { | 209 const gfx::Rect& bitmap_rect, |
| 210 const gfx::Rect& paint_rect) { |
| 211 DCHECK(bitmap_rect.Contains(paint_rect) && |
| 212 paint_rect.x() < kMaxBitmapLengthAllowed && |
| 213 paint_rect.y() < kMaxBitmapLengthAllowed); |
186 if (!display_) | 214 if (!display_) |
187 return; | 215 return; |
188 | 216 |
189 if (bitmap_rect.IsEmpty()) | 217 if (bitmap_rect.IsEmpty()) |
190 return; | 218 return; |
191 | 219 |
192 if (!use_render_) | 220 if (!use_render_) |
193 return PaintRectWithoutXrender(bitmap, bitmap_rect); | 221 return PaintRectWithoutXrender(bitmap, bitmap_rect, paint_rect); |
194 | 222 |
195 const int width = bitmap_rect.width(); | 223 const int paint_width = paint_rect.width(); |
196 const int height = bitmap_rect.height(); | 224 const int paint_height = paint_rect.height(); |
| 225 |
| 226 // The values for the position of the source rect within the bitmap when |
| 227 // we render the composite depends on the usage of shared memory or not. |
| 228 int src_x = 0; |
| 229 int src_y = 0; |
| 230 |
197 Picture picture; | 231 Picture picture; |
198 Pixmap pixmap; | 232 Pixmap pixmap; |
199 | 233 |
200 if (use_shared_memory_) { | 234 if (use_shared_memory_) { |
201 const XID shmseg = bitmap->MapToX(display_); | 235 const XID shmseg = bitmap->MapToX(display_); |
202 | 236 |
203 XShmSegmentInfo shminfo; | 237 XShmSegmentInfo shminfo; |
204 memset(&shminfo, 0, sizeof(shminfo)); | 238 memset(&shminfo, 0, sizeof(shminfo)); |
205 shminfo.shmseg = shmseg; | 239 shminfo.shmseg = shmseg; |
206 | 240 |
207 // The NULL in the following is the |data| pointer: this is an artifact of | 241 // The NULL in the following is the |data| pointer: this is an artifact of |
208 // Xlib trying to be helpful, rather than just exposing the X protocol. It | 242 // Xlib trying to be helpful, rather than just exposing the X protocol. It |
209 // assumes that we have the shared memory segment mapped into our memory, | 243 // assumes that we have the shared memory segment mapped into our memory, |
210 // which we don't, and it's trying to calculate an offset by taking the | 244 // which we don't, and it's trying to calculate an offset by taking the |
211 // difference between the |data| pointer and the address of the mapping in | 245 // difference between the |data| pointer and the address of the mapping in |
212 // |shminfo|. Since both are NULL, the offset will be calculated to be 0, | 246 // |shminfo|. Since both are NULL, the offset will be calculated to be 0, |
213 // which is correct for us. | 247 // which is correct for us. |
214 pixmap = XShmCreatePixmap(display_, root_window_, NULL, &shminfo, width, | 248 pixmap = XShmCreatePixmap(display_, root_window_, NULL, &shminfo, |
215 height, 32); | 249 bitmap_rect.width(), bitmap_rect.height(), 32); |
| 250 // Since we use the whole source bitmap, we must offset the source. |
| 251 src_x = paint_rect.x() - bitmap_rect.x(); |
| 252 src_y = paint_rect.y() - bitmap_rect.y(); |
216 } else { | 253 } else { |
217 // No shared memory support, we have to copy the bitmap contents to the X | 254 // No shared memory support, we have to copy the bitmap contents to the X |
218 // server. Xlib wraps the underlying PutImage call behind several layers of | 255 // server. Xlib wraps the underlying PutImage call behind several layers of |
219 // functions which try to convert the image into the format which the X | 256 // functions which try to convert the image into the format which the X |
220 // server expects. The following values hopefully disable all conversions. | 257 // server expects. The following values hopefully disable all conversions. |
221 XImage image; | 258 XImage image; |
222 memset(&image, 0, sizeof(image)); | 259 memset(&image, 0, sizeof(image)); |
223 | 260 |
224 image.width = width; | 261 image.width = paint_width; |
225 image.height = height; | 262 image.height = paint_height; |
226 image.depth = 32; | 263 image.depth = 32; |
227 image.bits_per_pixel = 32; | 264 image.bits_per_pixel = 32; |
228 image.format = ZPixmap; | 265 image.format = ZPixmap; |
229 image.byte_order = LSBFirst; | 266 image.byte_order = LSBFirst; |
230 image.bitmap_unit = 8; | 267 image.bitmap_unit = 8; |
231 image.bitmap_bit_order = LSBFirst; | 268 image.bitmap_bit_order = LSBFirst; |
232 image.bytes_per_line = width * 4; | 269 image.bytes_per_line = paint_width * 4; |
233 image.red_mask = 0xff; | 270 image.red_mask = 0xff; |
234 image.green_mask = 0xff00; | 271 image.green_mask = 0xff00; |
235 image.blue_mask = 0xff0000; | 272 image.blue_mask = 0xff0000; |
| 273 // TODO(agl): check if we can make this more efficient. |
236 image.data = static_cast<char*>(bitmap->memory()); | 274 image.data = static_cast<char*>(bitmap->memory()); |
237 | 275 |
238 pixmap = XCreatePixmap(display_, root_window_, width, height, 32); | 276 pixmap = XCreatePixmap(display_, root_window_, paint_width, paint_height, |
| 277 32); |
239 GC gc = XCreateGC(display_, pixmap, 0, NULL); | 278 GC gc = XCreateGC(display_, pixmap, 0, NULL); |
240 XPutImage(display_, pixmap, gc, &image, | 279 XPutImage(display_, pixmap, gc, &image, paint_rect.x() - bitmap_rect.x(), |
241 0, 0 /* source x, y */, 0, 0 /* dest x, y */, | 280 paint_rect.y() - bitmap_rect.y() /* source x, y */, |
242 width, height); | 281 0, 0 /* dest x, y */, paint_width, paint_height); |
243 XFreeGC(display_, gc); | 282 XFreeGC(display_, gc); |
244 } | 283 } |
245 | 284 |
246 picture = x11_util::CreatePictureFromSkiaPixmap(display_, pixmap); | 285 picture = x11_util::CreatePictureFromSkiaPixmap(display_, pixmap); |
247 XRenderComposite(display_, PictOpSrc, picture /* source */, 0 /* mask */, | 286 XRenderComposite(display_, PictOpSrc, picture /* source */, 0 /* mask */, |
248 picture_ /* dest */, 0, 0 /* source x, y */, | 287 picture_ /* dest */, src_x, src_y /* source x, y */, |
249 0, 0 /* mask x, y */, | 288 0, 0 /* mask x, y */, |
250 bitmap_rect.x(), bitmap_rect.y() /* target x, y */, | 289 paint_rect.x(), paint_rect.y() /* target x, y */, |
251 width, height); | 290 paint_width, paint_height); |
252 | 291 |
253 // In the case of shared memory, we wait for the composite to complete so that | 292 // In the case of shared memory, we wait for the composite to complete so that |
254 // we are sure that the X server has finished reading. | 293 // we are sure that the X server has finished reading. |
255 if (use_shared_memory_) | 294 if (use_shared_memory_) |
256 XSync(display_, False); | 295 XSync(display_, False); |
257 | 296 |
258 XRenderFreePicture(display_, picture); | 297 XRenderFreePicture(display_, picture); |
259 XFreePixmap(display_, pixmap); | 298 XFreePixmap(display_, pixmap); |
260 } | 299 } |
261 | 300 |
(...skipping 26 matching lines...) Expand all Loading... |
288 XCopyArea(display_, pixmap_, pixmap_, static_cast<GC>(pixmap_gc_), | 327 XCopyArea(display_, pixmap_, pixmap_, static_cast<GC>(pixmap_gc_), |
289 std::max(clip_rect.x(), clip_rect.x() - dx), | 328 std::max(clip_rect.x(), clip_rect.x() - dx), |
290 clip_rect.y() /* source y */, | 329 clip_rect.y() /* source y */, |
291 clip_rect.width() - abs(dx), | 330 clip_rect.width() - abs(dx), |
292 clip_rect.height(), | 331 clip_rect.height(), |
293 std::max(clip_rect.x(), clip_rect.x() + dx) /* dest x */, | 332 std::max(clip_rect.x(), clip_rect.x() + dx) /* dest x */, |
294 clip_rect.y() /* dest x */); | 333 clip_rect.y() /* dest x */); |
295 } | 334 } |
296 } | 335 } |
297 | 336 |
298 PaintRect(process, bitmap, bitmap_rect); | 337 PaintRect(process, bitmap, bitmap_rect, bitmap_rect); |
299 } | 338 } |
300 | 339 |
301 void BackingStore::ShowRect(const gfx::Rect& rect, XID target) { | 340 void BackingStore::ShowRect(const gfx::Rect& rect, XID target) { |
302 XCopyArea(display_, pixmap_, target, static_cast<GC>(pixmap_gc_), | 341 XCopyArea(display_, pixmap_, target, static_cast<GC>(pixmap_gc_), |
303 rect.x(), rect.y(), rect.width(), rect.height(), | 342 rect.x(), rect.y(), rect.width(), rect.height(), |
304 rect.x(), rect.y()); | 343 rect.x(), rect.y()); |
305 } | 344 } |
OLD | NEW |