| 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 |