OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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_x.h" | 5 #include "chrome/browser/renderer_host/backing_store_x.h" |
6 | 6 |
7 #include <cairo-xlib.h> | 7 #include <cairo-xlib.h> |
8 #include <gtk/gtk.h> | 8 #include <gtk/gtk.h> |
9 #include <stdlib.h> | 9 #include <stdlib.h> |
10 #include <sys/ipc.h> | 10 #include <sys/ipc.h> |
11 #include <sys/shm.h> | 11 #include <sys/shm.h> |
12 | 12 |
13 #if defined(OS_OPENBSD) || defined(OS_FREEBSD) | 13 #if defined(OS_OPENBSD) || defined(OS_FREEBSD) |
14 #include <sys/endian.h> | 14 #include <sys/endian.h> |
15 #endif | 15 #endif |
16 | 16 |
17 #include <algorithm> | 17 #include <algorithm> |
18 #include <utility> | 18 #include <utility> |
19 #include <limits> | 19 #include <limits> |
20 | 20 |
21 #include "app/surface/transport_dib.h" | 21 #include "app/surface/transport_dib.h" |
22 #include "app/x11_util.h" | |
23 #include "app/x11_util_internal.h" | |
24 #include "base/compiler_specific.h" | 22 #include "base/compiler_specific.h" |
25 #include "base/logging.h" | 23 #include "base/logging.h" |
26 #include "base/metrics/histogram.h" | 24 #include "base/metrics/histogram.h" |
27 #include "base/time.h" | 25 #include "base/time.h" |
28 #include "chrome/browser/renderer_host/render_process_host.h" | 26 #include "chrome/browser/renderer_host/render_process_host.h" |
29 #include "gfx/rect.h" | 27 #include "gfx/rect.h" |
30 #include "skia/ext/platform_canvas.h" | 28 #include "skia/ext/platform_canvas.h" |
31 #include "third_party/skia/include/core/SkBitmap.h" | 29 #include "third_party/skia/include/core/SkBitmap.h" |
| 30 #include "ui/base/x/x11_util.h" |
| 31 #include "ui/base/x/x11_util_internal.h" |
32 | 32 |
33 // Assume that somewhere along the line, someone will do width * height * 4 | 33 // Assume that somewhere along the line, someone will do width * height * 4 |
34 // with signed numbers. If the maximum value is 2**31, then 2**31 / 4 = | 34 // with signed numbers. If the maximum value is 2**31, then 2**31 / 4 = |
35 // 2**29 and floor(sqrt(2**29)) = 23170. | 35 // 2**29 and floor(sqrt(2**29)) = 23170. |
36 | 36 |
37 // Max height and width for layers | 37 // Max height and width for layers |
38 static const int kMaxVideoLayerSize = 23170; | 38 static const int kMaxVideoLayerSize = 23170; |
39 | 39 |
40 | 40 |
41 // X Backing Stores: | 41 // X Backing Stores: |
(...skipping 15 matching lines...) Expand all Loading... |
57 XShmDetach(display, shminfo); | 57 XShmDetach(display, shminfo); |
58 XDestroyImage(image); | 58 XDestroyImage(image); |
59 shmdt(shminfo->shmaddr); | 59 shmdt(shminfo->shmaddr); |
60 } | 60 } |
61 | 61 |
62 BackingStoreX::BackingStoreX(RenderWidgetHost* widget, | 62 BackingStoreX::BackingStoreX(RenderWidgetHost* widget, |
63 const gfx::Size& size, | 63 const gfx::Size& size, |
64 void* visual, | 64 void* visual, |
65 int depth) | 65 int depth) |
66 : BackingStore(widget, size), | 66 : BackingStore(widget, size), |
67 display_(x11_util::GetXDisplay()), | 67 display_(ui::GetXDisplay()), |
68 shared_memory_support_(x11_util::QuerySharedMemorySupport(display_)), | 68 shared_memory_support_(ui::QuerySharedMemorySupport(display_)), |
69 use_render_(x11_util::QueryRenderSupport(display_)), | 69 use_render_(ui::QueryRenderSupport(display_)), |
70 visual_(visual), | 70 visual_(visual), |
71 visual_depth_(depth), | 71 visual_depth_(depth), |
72 root_window_(x11_util::GetX11RootWindow()) { | 72 root_window_(ui::GetX11RootWindow()) { |
73 #if defined(OS_OPENBSD) || defined(OS_FREEBSD) | 73 #if defined(OS_OPENBSD) || defined(OS_FREEBSD) |
74 COMPILE_ASSERT(_BYTE_ORDER == _LITTLE_ENDIAN, assumes_little_endian); | 74 COMPILE_ASSERT(_BYTE_ORDER == _LITTLE_ENDIAN, assumes_little_endian); |
75 #else | 75 #else |
76 COMPILE_ASSERT(__BYTE_ORDER == __LITTLE_ENDIAN, assumes_little_endian); | 76 COMPILE_ASSERT(__BYTE_ORDER == __LITTLE_ENDIAN, assumes_little_endian); |
77 #endif | 77 #endif |
78 | 78 |
79 pixmap_ = XCreatePixmap(display_, root_window_, | 79 pixmap_ = XCreatePixmap(display_, root_window_, |
80 size.width(), size.height(), depth); | 80 size.width(), size.height(), depth); |
81 | 81 |
82 if (use_render_) { | 82 if (use_render_) { |
83 picture_ = XRenderCreatePicture( | 83 picture_ = XRenderCreatePicture( |
84 display_, pixmap_, | 84 display_, pixmap_, |
85 x11_util::GetRenderVisualFormat(display_, | 85 ui::GetRenderVisualFormat(display_, |
86 static_cast<Visual*>(visual)), | 86 static_cast<Visual*>(visual)), |
87 0, NULL); | 87 0, NULL); |
88 pixmap_bpp_ = 0; | 88 pixmap_bpp_ = 0; |
89 } else { | 89 } else { |
90 picture_ = 0; | 90 picture_ = 0; |
91 pixmap_bpp_ = x11_util::BitsPerPixelForPixmapDepth(display_, depth); | 91 pixmap_bpp_ = ui::BitsPerPixelForPixmapDepth(display_, depth); |
92 } | 92 } |
93 | 93 |
94 pixmap_gc_ = XCreateGC(display_, pixmap_, 0, NULL); | 94 pixmap_gc_ = XCreateGC(display_, pixmap_, 0, NULL); |
95 } | 95 } |
96 | 96 |
97 BackingStoreX::BackingStoreX(RenderWidgetHost* widget, const gfx::Size& size) | 97 BackingStoreX::BackingStoreX(RenderWidgetHost* widget, const gfx::Size& size) |
98 : BackingStore(widget, size), | 98 : BackingStore(widget, size), |
99 display_(NULL), | 99 display_(NULL), |
100 shared_memory_support_(x11_util::SHARED_MEMORY_NONE), | 100 shared_memory_support_(ui::SHARED_MEMORY_NONE), |
101 use_render_(false), | 101 use_render_(false), |
102 pixmap_bpp_(0), | 102 pixmap_bpp_(0), |
103 visual_(NULL), | 103 visual_(NULL), |
104 visual_depth_(-1), | 104 visual_depth_(-1), |
105 root_window_(0), | 105 root_window_(0), |
106 pixmap_(0), | 106 pixmap_(0), |
107 picture_(0), | 107 picture_(0), |
108 pixmap_gc_(NULL) { | 108 pixmap_gc_(NULL) { |
109 } | 109 } |
110 | 110 |
(...skipping 17 matching lines...) Expand all Loading... |
128 void BackingStoreX::PaintRectWithoutXrender( | 128 void BackingStoreX::PaintRectWithoutXrender( |
129 TransportDIB* bitmap, | 129 TransportDIB* bitmap, |
130 const gfx::Rect& bitmap_rect, | 130 const gfx::Rect& bitmap_rect, |
131 const std::vector<gfx::Rect>& copy_rects) { | 131 const std::vector<gfx::Rect>& copy_rects) { |
132 const int width = bitmap_rect.width(); | 132 const int width = bitmap_rect.width(); |
133 const int height = bitmap_rect.height(); | 133 const int height = bitmap_rect.height(); |
134 Pixmap pixmap = XCreatePixmap(display_, root_window_, width, height, | 134 Pixmap pixmap = XCreatePixmap(display_, root_window_, width, height, |
135 visual_depth_); | 135 visual_depth_); |
136 | 136 |
137 // Draw ARGB transport DIB onto our pixmap. | 137 // Draw ARGB transport DIB onto our pixmap. |
138 x11_util::PutARGBImage(display_, visual_, visual_depth_, pixmap, | 138 ui::PutARGBImage(display_, visual_, visual_depth_, pixmap, |
139 pixmap_gc_, static_cast<uint8*>(bitmap->memory()), | 139 pixmap_gc_, static_cast<uint8*>(bitmap->memory()), |
140 width, height); | 140 width, height); |
141 | 141 |
142 for (size_t i = 0; i < copy_rects.size(); i++) { | 142 for (size_t i = 0; i < copy_rects.size(); i++) { |
143 const gfx::Rect& copy_rect = copy_rects[i]; | 143 const gfx::Rect& copy_rect = copy_rects[i]; |
144 XCopyArea(display_, | 144 XCopyArea(display_, |
145 pixmap, // src | 145 pixmap, // src |
146 pixmap_, // dest | 146 pixmap_, // dest |
147 static_cast<GC>(pixmap_gc_), // gc | 147 static_cast<GC>(pixmap_gc_), // gc |
148 copy_rect.x() - bitmap_rect.x(), // src_x | 148 copy_rect.x() - bitmap_rect.x(), // src_x |
149 copy_rect.y() - bitmap_rect.y(), // src_y | 149 copy_rect.y() - bitmap_rect.y(), // src_y |
150 copy_rect.width(), // width | 150 copy_rect.width(), // width |
(...skipping 26 matching lines...) Expand all Loading... |
177 TransportDIB* dib = process->GetTransportDIB(bitmap); | 177 TransportDIB* dib = process->GetTransportDIB(bitmap); |
178 if (!dib) | 178 if (!dib) |
179 return; | 179 return; |
180 | 180 |
181 if (!use_render_) | 181 if (!use_render_) |
182 return PaintRectWithoutXrender(dib, bitmap_rect, copy_rects); | 182 return PaintRectWithoutXrender(dib, bitmap_rect, copy_rects); |
183 | 183 |
184 Picture picture; | 184 Picture picture; |
185 Pixmap pixmap; | 185 Pixmap pixmap; |
186 | 186 |
187 if (shared_memory_support_ == x11_util::SHARED_MEMORY_PIXMAP) { | 187 if (shared_memory_support_ == ui::SHARED_MEMORY_PIXMAP) { |
188 XShmSegmentInfo shminfo = {0}; | 188 XShmSegmentInfo shminfo = {0}; |
189 shminfo.shmseg = dib->MapToX(display_); | 189 shminfo.shmseg = dib->MapToX(display_); |
190 | 190 |
191 // The NULL in the following is the |data| pointer: this is an artifact of | 191 // The NULL in the following is the |data| pointer: this is an artifact of |
192 // Xlib trying to be helpful, rather than just exposing the X protocol. It | 192 // Xlib trying to be helpful, rather than just exposing the X protocol. It |
193 // assumes that we have the shared memory segment mapped into our memory, | 193 // assumes that we have the shared memory segment mapped into our memory, |
194 // which we don't, and it's trying to calculate an offset by taking the | 194 // which we don't, and it's trying to calculate an offset by taking the |
195 // difference between the |data| pointer and the address of the mapping in | 195 // difference between the |data| pointer and the address of the mapping in |
196 // |shminfo|. Since both are NULL, the offset will be calculated to be 0, | 196 // |shminfo|. Since both are NULL, the offset will be calculated to be 0, |
197 // which is correct for us. | 197 // which is correct for us. |
198 pixmap = XShmCreatePixmap(display_, root_window_, NULL, &shminfo, | 198 pixmap = XShmCreatePixmap(display_, root_window_, NULL, &shminfo, |
199 width, height, 32); | 199 width, height, 32); |
200 } else { | 200 } else { |
201 // We don't have shared memory pixmaps. Fall back to creating a pixmap | 201 // We don't have shared memory pixmaps. Fall back to creating a pixmap |
202 // ourselves and putting an image on it. | 202 // ourselves and putting an image on it. |
203 pixmap = XCreatePixmap(display_, root_window_, width, height, 32); | 203 pixmap = XCreatePixmap(display_, root_window_, width, height, 32); |
204 GC gc = XCreateGC(display_, pixmap, 0, NULL); | 204 GC gc = XCreateGC(display_, pixmap, 0, NULL); |
205 | 205 |
206 if (shared_memory_support_ == x11_util::SHARED_MEMORY_PUTIMAGE) { | 206 if (shared_memory_support_ == ui::SHARED_MEMORY_PUTIMAGE) { |
207 const XID shmseg = dib->MapToX(display_); | 207 const XID shmseg = dib->MapToX(display_); |
208 | 208 |
209 XShmSegmentInfo shminfo; | 209 XShmSegmentInfo shminfo; |
210 memset(&shminfo, 0, sizeof(shminfo)); | 210 memset(&shminfo, 0, sizeof(shminfo)); |
211 shminfo.shmseg = shmseg; | 211 shminfo.shmseg = shmseg; |
212 shminfo.shmaddr = static_cast<char*>(dib->memory()); | 212 shminfo.shmaddr = static_cast<char*>(dib->memory()); |
213 | 213 |
214 XImage* image = XShmCreateImage(display_, static_cast<Visual*>(visual_), | 214 XImage* image = XShmCreateImage(display_, static_cast<Visual*>(visual_), |
215 32, ZPixmap, | 215 32, ZPixmap, |
216 shminfo.shmaddr, &shminfo, | 216 shminfo.shmaddr, &shminfo, |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
262 image.blue_mask = 0xff0000; | 262 image.blue_mask = 0xff0000; |
263 image.data = static_cast<char*>(dib->memory()); | 263 image.data = static_cast<char*>(dib->memory()); |
264 | 264 |
265 XPutImage(display_, pixmap, gc, &image, | 265 XPutImage(display_, pixmap, gc, &image, |
266 0, 0 /* source x, y */, 0, 0 /* dest x, y */, | 266 0, 0 /* source x, y */, 0, 0 /* dest x, y */, |
267 width, height); | 267 width, height); |
268 } | 268 } |
269 XFreeGC(display_, gc); | 269 XFreeGC(display_, gc); |
270 } | 270 } |
271 | 271 |
272 picture = x11_util::CreatePictureFromSkiaPixmap(display_, pixmap); | 272 picture = ui::CreatePictureFromSkiaPixmap(display_, pixmap); |
273 | 273 |
274 for (size_t i = 0; i < copy_rects.size(); i++) { | 274 for (size_t i = 0; i < copy_rects.size(); i++) { |
275 const gfx::Rect& copy_rect = copy_rects[i]; | 275 const gfx::Rect& copy_rect = copy_rects[i]; |
276 XRenderComposite(display_, | 276 XRenderComposite(display_, |
277 PictOpSrc, // op | 277 PictOpSrc, // op |
278 picture, // src | 278 picture, // src |
279 0, // mask | 279 0, // mask |
280 picture_, // dest | 280 picture_, // dest |
281 copy_rect.x() - bitmap_rect.x(), // src_x | 281 copy_rect.x() - bitmap_rect.x(), // src_x |
282 copy_rect.y() - bitmap_rect.y(), // src_y | 282 copy_rect.y() - bitmap_rect.y(), // src_y |
283 0, // mask_x | 283 0, // mask_x |
284 0, // mask_y | 284 0, // mask_y |
285 copy_rect.x(), // dest_x | 285 copy_rect.x(), // dest_x |
286 copy_rect.y(), // dest_y | 286 copy_rect.y(), // dest_y |
287 copy_rect.width(), // width | 287 copy_rect.width(), // width |
288 copy_rect.height()); // height | 288 copy_rect.height()); // height |
289 } | 289 } |
290 | 290 |
291 // In the case of shared memory, we wait for the composite to complete so that | 291 // In the case of shared memory, we wait for the composite to complete so that |
292 // we are sure that the X server has finished reading from the shared memory | 292 // we are sure that the X server has finished reading from the shared memory |
293 // segment. | 293 // segment. |
294 if (shared_memory_support_ != x11_util::SHARED_MEMORY_NONE) | 294 if (shared_memory_support_ != ui::SHARED_MEMORY_NONE) |
295 XSync(display_, False); | 295 XSync(display_, False); |
296 | 296 |
297 XRenderFreePicture(display_, picture); | 297 XRenderFreePicture(display_, picture); |
298 XFreePixmap(display_, pixmap); | 298 XFreePixmap(display_, pixmap); |
299 } | 299 } |
300 | 300 |
301 bool BackingStoreX::CopyFromBackingStore(const gfx::Rect& rect, | 301 bool BackingStoreX::CopyFromBackingStore(const gfx::Rect& rect, |
302 skia::PlatformCanvas* output) { | 302 skia::PlatformCanvas* output) { |
303 base::TimeTicks begin_time = base::TimeTicks::Now(); | 303 base::TimeTicks begin_time = base::TimeTicks::Now(); |
304 | 304 |
305 if (visual_depth_ < 24) { | 305 if (visual_depth_ < 24) { |
306 // CopyFromBackingStore() copies pixels out of the XImage | 306 // CopyFromBackingStore() copies pixels out of the XImage |
307 // in a way that assumes that each component (red, green, | 307 // in a way that assumes that each component (red, green, |
308 // blue) is a byte. This doesn't work on visuals which | 308 // blue) is a byte. This doesn't work on visuals which |
309 // encode a pixel color with less than a byte per color. | 309 // encode a pixel color with less than a byte per color. |
310 return false; | 310 return false; |
311 } | 311 } |
312 | 312 |
313 const int width = std::min(size().width(), rect.width()); | 313 const int width = std::min(size().width(), rect.width()); |
314 const int height = std::min(size().height(), rect.height()); | 314 const int height = std::min(size().height(), rect.height()); |
315 | 315 |
316 XImage* image; | 316 XImage* image; |
317 XShmSegmentInfo shminfo; // Used only when shared memory is enabled. | 317 XShmSegmentInfo shminfo; // Used only when shared memory is enabled. |
318 if (shared_memory_support_ != x11_util::SHARED_MEMORY_NONE) { | 318 if (shared_memory_support_ != ui::SHARED_MEMORY_NONE) { |
319 // Use shared memory for faster copies when it's available. | 319 // Use shared memory for faster copies when it's available. |
320 Visual* visual = static_cast<Visual*>(visual_); | 320 Visual* visual = static_cast<Visual*>(visual_); |
321 memset(&shminfo, 0, sizeof(shminfo)); | 321 memset(&shminfo, 0, sizeof(shminfo)); |
322 image = XShmCreateImage(display_, visual, 32, | 322 image = XShmCreateImage(display_, visual, 32, |
323 ZPixmap, NULL, &shminfo, width, height); | 323 ZPixmap, NULL, &shminfo, width, height); |
324 if (!image) { | 324 if (!image) { |
325 return false; | 325 return false; |
326 } | 326 } |
327 // Create the shared memory segment for the image and map it. | 327 // Create the shared memory segment for the image and map it. |
328 if (image->bytes_per_line == 0 || image->height == 0 || | 328 if (image->bytes_per_line == 0 || image->height == 0 || |
(...skipping 28 matching lines...) Expand all Loading... |
357 image = XGetImage(display_, pixmap_, | 357 image = XGetImage(display_, pixmap_, |
358 rect.x(), rect.y(), width, height, | 358 rect.x(), rect.y(), width, height, |
359 AllPlanes, ZPixmap); | 359 AllPlanes, ZPixmap); |
360 } | 360 } |
361 | 361 |
362 // TODO(jhawkins): Need to convert the image data if the image bits per pixel | 362 // TODO(jhawkins): Need to convert the image data if the image bits per pixel |
363 // is not 32. | 363 // is not 32. |
364 // Note that this also initializes the output bitmap as opaque. | 364 // Note that this also initializes the output bitmap as opaque. |
365 if (!output->initialize(width, height, true) || | 365 if (!output->initialize(width, height, true) || |
366 image->bits_per_pixel != 32) { | 366 image->bits_per_pixel != 32) { |
367 if (shared_memory_support_ != x11_util::SHARED_MEMORY_NONE) | 367 if (shared_memory_support_ != ui::SHARED_MEMORY_NONE) |
368 DestroySharedImage(display_, image, &shminfo); | 368 DestroySharedImage(display_, image, &shminfo); |
369 else | 369 else |
370 XDestroyImage(image); | 370 XDestroyImage(image); |
371 return false; | 371 return false; |
372 } | 372 } |
373 | 373 |
374 // The X image might have a different row stride, so iterate through | 374 // The X image might have a different row stride, so iterate through |
375 // it and copy each row out, only up to the pixels we're actually | 375 // it and copy each row out, only up to the pixels we're actually |
376 // using. This code assumes a visual mode where a pixel is | 376 // using. This code assumes a visual mode where a pixel is |
377 // represented using a 32-bit unsigned int, with a byte per component. | 377 // represented using a 32-bit unsigned int, with a byte per component. |
378 SkBitmap bitmap = output->getTopPlatformDevice().accessBitmap(true); | 378 SkBitmap bitmap = output->getTopPlatformDevice().accessBitmap(true); |
379 for (int y = 0; y < height; y++) { | 379 for (int y = 0; y < height; y++) { |
380 const uint32* src_row = reinterpret_cast<uint32*>( | 380 const uint32* src_row = reinterpret_cast<uint32*>( |
381 &image->data[image->bytes_per_line * y]); | 381 &image->data[image->bytes_per_line * y]); |
382 uint32* dest_row = bitmap.getAddr32(0, y); | 382 uint32* dest_row = bitmap.getAddr32(0, y); |
383 for (int x = 0; x < width; ++x, ++dest_row) { | 383 for (int x = 0; x < width; ++x, ++dest_row) { |
384 // Force alpha to be 0xff, because otherwise it causes rendering problems. | 384 // Force alpha to be 0xff, because otherwise it causes rendering problems. |
385 *dest_row = src_row[x] | 0xff000000; | 385 *dest_row = src_row[x] | 0xff000000; |
386 } | 386 } |
387 } | 387 } |
388 | 388 |
389 if (shared_memory_support_ != x11_util::SHARED_MEMORY_NONE) | 389 if (shared_memory_support_ != ui::SHARED_MEMORY_NONE) |
390 DestroySharedImage(display_, image, &shminfo); | 390 DestroySharedImage(display_, image, &shminfo); |
391 else | 391 else |
392 XDestroyImage(image); | 392 XDestroyImage(image); |
393 | 393 |
394 HISTOGRAM_TIMES("BackingStore.RetrievalFromX", | 394 HISTOGRAM_TIMES("BackingStore.RetrievalFromX", |
395 base::TimeTicks::Now() - begin_time); | 395 base::TimeTicks::Now() - begin_time); |
396 return true; | 396 return true; |
397 } | 397 } |
398 | 398 |
399 void BackingStoreX::ScrollBackingStore(int dx, int dy, | 399 void BackingStoreX::ScrollBackingStore(int dx, int dy, |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
468 cairo_set_source(cr, pattern); | 468 cairo_set_source(cr, pattern); |
469 cairo_pattern_destroy(pattern); | 469 cairo_pattern_destroy(pattern); |
470 | 470 |
471 cairo_identity_matrix(cr); | 471 cairo_identity_matrix(cr); |
472 | 472 |
473 cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height()); | 473 cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height()); |
474 cairo_fill(cr); | 474 cairo_fill(cr); |
475 cairo_destroy(cr); | 475 cairo_destroy(cr); |
476 } | 476 } |
477 #endif | 477 #endif |
OLD | NEW |