Index: chrome/browser/renderer_host/backing_store_x.cc |
=================================================================== |
--- chrome/browser/renderer_host/backing_store_x.cc (revision 17347) |
+++ chrome/browser/renderer_host/backing_store_x.cc (working copy) |
@@ -77,17 +77,23 @@ |
} |
void BackingStore::PaintRectWithoutXrender(TransportDIB* bitmap, |
- const gfx::Rect &bitmap_rect) { |
- const int width = bitmap_rect.width(); |
- const int height = bitmap_rect.height(); |
- Pixmap pixmap = XCreatePixmap(display_, root_window_, width, height, |
- visual_depth_); |
+ const gfx::Rect& bitmap_rect, |
+ const gfx::Rect& paint_rect) { |
+ DCHECK(bitmap_rect.Contains(paint_rect) && |
+ paint_rect.x() < kMaxBitmapLengthAllowed && |
+ paint_rect.y() < kMaxBitmapLengthAllowed); |
+ const int paint_width = paint_rect.width(); |
+ const int paint_height = paint_rect.height(); |
+ Pixmap pixmap = XCreatePixmap(display_, root_window_, paint_width, |
+ paint_height, visual_depth_); |
+ const int bitmap_width = bitmap_rect.width(); |
+ const int bitmap_height = bitmap_rect.height(); |
XImage image; |
memset(&image, 0, sizeof(image)); |
- image.width = width; |
- image.height = height; |
+ image.width = bitmap_width; |
+ image.height = bitmap_height; |
image.format = ZPixmap; |
image.byte_order = LSBFirst; |
image.bitmap_unit = 8; |
@@ -96,16 +102,18 @@ |
image.green_mask = 0xff00; |
image.blue_mask = 0xff0000; |
+ const int x_offset = paint_rect.x() - bitmap_rect.x(); |
+ const int y_offset = paint_rect.y() - bitmap_rect.y(); |
if (pixmap_bpp_ == 32) { |
// If the X server depth is already 32-bits, then our job is easy. |
image.depth = visual_depth_; |
image.bits_per_pixel = 32; |
- image.bytes_per_line = width * 4; |
+ image.bytes_per_line = bitmap_width * 4; |
image.data = static_cast<char*>(bitmap->memory()); |
XPutImage(display_, pixmap, static_cast<GC>(pixmap_gc_), &image, |
- 0, 0 /* source x, y */, 0, 0 /* dest x, y */, |
- width, height); |
+ x_offset, y_offset /* source x, y */, 0, 0 /* dest x, y */, |
+ paint_width, paint_height); |
} else if (pixmap_bpp_ == 24) { |
// In this case we just need to strip the alpha channel out of each |
// pixel. This is the case which covers VNC servers since they don't |
@@ -114,48 +122,64 @@ |
// It's possible to use some fancy SSE tricks here, but since this is the |
// slow path anyway, we do it slowly. |
- uint8_t* bitmap24 = static_cast<uint8_t*>(malloc(3 * width * height)); |
+ uint8_t* bitmap24 = static_cast<uint8_t*>(malloc(3 * paint_width * |
+ paint_height)); |
const uint32_t* bitmap_in = static_cast<const uint32_t*>(bitmap->memory()); |
- for (int y = 0; y < height; ++y) { |
- for (int x = 0; x < width; ++x) { |
+ const int x_limit = paint_rect.right() - bitmap_rect.x(); |
+ const int y_limit = paint_rect.bottom() - bitmap_rect.y(); |
+ const int row_length = bitmap_width; |
+ bitmap_in += row_length * y_offset; |
+ for (int y = y_offset; y < y_limit; ++y) { |
+ bitmap_in += x_offset; |
+ for (int x = x_offset; x < x_limit; ++x) { |
const uint32_t pixel = *(bitmap_in++); |
bitmap24[0] = (pixel >> 16) & 0xff; |
bitmap24[1] = (pixel >> 8) & 0xff; |
bitmap24[2] = pixel & 0xff; |
bitmap24 += 3; |
} |
+ bitmap_in += row_length - x_limit; |
} |
+ image.width = paint_width; |
+ image.height = paint_height; |
image.depth = visual_depth_; |
image.bits_per_pixel = 24; |
- image.bytes_per_line = width * 3; |
+ image.bytes_per_line = paint_width * 3; |
image.data = reinterpret_cast<char*>(bitmap24); |
XPutImage(display_, pixmap, static_cast<GC>(pixmap_gc_), &image, |
0, 0 /* source x, y */, 0, 0 /* dest x, y */, |
- width, height); |
+ paint_width, paint_height); |
free(bitmap24); |
} else if (pixmap_bpp_ == 16) { |
// Some folks have VNC setups which still use 16-bit visuals and VNC |
// doesn't include Xrender. |
- uint16_t* bitmap16 = static_cast<uint16_t*>(malloc(2 * width * height)); |
+ uint16_t* bitmap16 = static_cast<uint16_t*>(malloc(2 * paint_width * |
+ paint_height)); |
uint16_t* const orig_bitmap16 = bitmap16; |
const uint32_t* bitmap_in = static_cast<const uint32_t*>(bitmap->memory()); |
- for (int y = 0; y < height; ++y) { |
- for (int x = 0; x < width; ++x) { |
+ const int x_limit = paint_rect.right() - bitmap_rect.x(); |
+ const int y_limit = paint_rect.bottom() - bitmap_rect.y(); |
+ const int row_length = bitmap_width; |
+ bitmap_in += row_length * y_offset; |
+ for (int y = y_offset; y < y_limit; ++y) { |
+ bitmap_in += x_offset; |
+ for (int x = x_offset; x < x_limit; ++x) { |
const uint32_t pixel = *(bitmap_in++); |
uint16_t out_pixel = ((pixel >> 8) & 0xf800) | |
((pixel >> 5) & 0x07e0) | |
((pixel >> 3) & 0x001f); |
*(bitmap16++) = out_pixel; |
} |
+ bitmap_in += row_length - x_limit; |
} |
image.depth = visual_depth_; |
image.bits_per_pixel = 16; |
- image.bytes_per_line = width * 2; |
+ image.bytes_per_line = paint_width * 2; |
image.data = reinterpret_cast<char*>(orig_bitmap16); |
image.red_mask = 0xf800; |
@@ -164,7 +188,7 @@ |
XPutImage(display_, pixmap, static_cast<GC>(pixmap_gc_), &image, |
0, 0 /* source x, y */, 0, 0 /* dest x, y */, |
- width, height); |
+ paint_width, paint_height); |
free(orig_bitmap16); |
} else { |
CHECK(false) << "Sorry, we don't support your visual depth without " |
@@ -174,15 +198,19 @@ |
XCopyArea(display_, pixmap /* source */, pixmap_ /* target */, |
static_cast<GC>(pixmap_gc_), |
- 0, 0 /* source x, y */, bitmap_rect.width(), bitmap_rect.height(), |
- bitmap_rect.x(), bitmap_rect.y() /* dest x, y */); |
+ 0, 0 /* source x, y */, paint_width, paint_height, |
+ paint_rect.x(), paint_rect.y() /* dest x, y */); |
XFreePixmap(display_, pixmap); |
} |
void BackingStore::PaintRect(base::ProcessHandle process, |
TransportDIB* bitmap, |
- const gfx::Rect& bitmap_rect) { |
+ const gfx::Rect& bitmap_rect, |
+ const gfx::Rect& paint_rect) { |
+ DCHECK(bitmap_rect.Contains(paint_rect) && |
+ paint_rect.x() < kMaxBitmapLengthAllowed && |
+ paint_rect.y() < kMaxBitmapLengthAllowed); |
if (!display_) |
return; |
@@ -190,10 +218,16 @@ |
return; |
if (!use_render_) |
- return PaintRectWithoutXrender(bitmap, bitmap_rect); |
+ return PaintRectWithoutXrender(bitmap, bitmap_rect, paint_rect); |
- const int width = bitmap_rect.width(); |
- const int height = bitmap_rect.height(); |
+ const int paint_width = paint_rect.width(); |
+ const int paint_height = paint_rect.height(); |
+ |
+ // The values for the position of the source rect within the bitmap when |
+ // we render the composite depends on the usage of shared memory or not. |
+ int src_x = 0; |
+ int src_y = 0; |
+ |
Picture picture; |
Pixmap pixmap; |
@@ -211,8 +245,11 @@ |
// difference between the |data| pointer and the address of the mapping in |
// |shminfo|. Since both are NULL, the offset will be calculated to be 0, |
// which is correct for us. |
- pixmap = XShmCreatePixmap(display_, root_window_, NULL, &shminfo, width, |
- height, 32); |
+ pixmap = XShmCreatePixmap(display_, root_window_, NULL, &shminfo, |
+ bitmap_rect.width(), bitmap_rect.height(), 32); |
+ // Since we use the whole source bitmap, we must offset the source. |
+ src_x = paint_rect.x() - bitmap_rect.x(); |
+ src_y = paint_rect.y() - bitmap_rect.y(); |
} else { |
// No shared memory support, we have to copy the bitmap contents to the X |
// server. Xlib wraps the underlying PutImage call behind several layers of |
@@ -221,34 +258,36 @@ |
XImage image; |
memset(&image, 0, sizeof(image)); |
- image.width = width; |
- image.height = height; |
+ image.width = paint_width; |
+ image.height = paint_height; |
image.depth = 32; |
image.bits_per_pixel = 32; |
image.format = ZPixmap; |
image.byte_order = LSBFirst; |
image.bitmap_unit = 8; |
image.bitmap_bit_order = LSBFirst; |
- image.bytes_per_line = width * 4; |
+ image.bytes_per_line = paint_width * 4; |
image.red_mask = 0xff; |
image.green_mask = 0xff00; |
image.blue_mask = 0xff0000; |
+ // TODO(agl): check if we can make this more efficient. |
image.data = static_cast<char*>(bitmap->memory()); |
- pixmap = XCreatePixmap(display_, root_window_, width, height, 32); |
+ pixmap = XCreatePixmap(display_, root_window_, paint_width, paint_height, |
+ 32); |
GC gc = XCreateGC(display_, pixmap, 0, NULL); |
- XPutImage(display_, pixmap, gc, &image, |
- 0, 0 /* source x, y */, 0, 0 /* dest x, y */, |
- width, height); |
+ XPutImage(display_, pixmap, gc, &image, paint_rect.x() - bitmap_rect.x(), |
+ paint_rect.y() - bitmap_rect.y() /* source x, y */, |
+ 0, 0 /* dest x, y */, paint_width, paint_height); |
XFreeGC(display_, gc); |
} |
picture = x11_util::CreatePictureFromSkiaPixmap(display_, pixmap); |
XRenderComposite(display_, PictOpSrc, picture /* source */, 0 /* mask */, |
- picture_ /* dest */, 0, 0 /* source x, y */, |
+ picture_ /* dest */, src_x, src_y /* source x, y */, |
0, 0 /* mask x, y */, |
- bitmap_rect.x(), bitmap_rect.y() /* target x, y */, |
- width, height); |
+ paint_rect.x(), paint_rect.y() /* target x, y */, |
+ paint_width, paint_height); |
// In the case of shared memory, we wait for the composite to complete so that |
// we are sure that the X server has finished reading. |
@@ -295,7 +334,7 @@ |
} |
} |
- PaintRect(process, bitmap, bitmap_rect); |
+ PaintRect(process, bitmap, bitmap_rect, bitmap_rect); |
} |
void BackingStore::ShowRect(const gfx::Rect& rect, XID target) { |