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