| Index: chrome/browser/renderer_host/backing_store_x.cc
|
| diff --git a/chrome/browser/renderer_host/backing_store_x.cc b/chrome/browser/renderer_host/backing_store_x.cc
|
| index e37fe77fa615249b147ca0a502070c4b3a3143bc..75406fa62e6ae74b451fadf7e9403aa48260471d 100644
|
| --- a/chrome/browser/renderer_host/backing_store_x.cc
|
| +++ b/chrome/browser/renderer_host/backing_store_x.cc
|
| @@ -6,6 +6,7 @@
|
|
|
| #include <utility>
|
|
|
| +#include "base/compiler_specific.h"
|
| #include "base/logging.h"
|
| #include "chrome/common/transport_dib.h"
|
| #include "chrome/common/x11_util.h"
|
| @@ -27,19 +28,31 @@ BackingStore::BackingStore(const gfx::Size& size,
|
| int depth,
|
| void* visual,
|
| Drawable root_window,
|
| + bool use_render,
|
| bool use_shared_memory)
|
| : size_(size),
|
| display_(display),
|
| use_shared_memory_(use_shared_memory),
|
| + use_render_(use_render),
|
| + visual_depth_(depth),
|
| root_window_(root_window) {
|
| const int width = size.width();
|
| const int height = size.height();
|
|
|
| + COMPILE_ASSERT(__BYTE_ORDER == __LITTLE_ENDIAN, assumes_little_endian);
|
| +
|
| pixmap_ = XCreatePixmap(display_, root_window, width, height, depth);
|
| - picture_ = XRenderCreatePicture(
|
| - display_, pixmap_,
|
| - x11_util::GetRenderVisualFormat(display_, static_cast<Visual*>(visual)),
|
| - 0, NULL);
|
| +
|
| + if (use_render_) {
|
| + picture_ = XRenderCreatePicture(
|
| + display_, pixmap_,
|
| + x11_util::GetRenderVisualFormat(display_, static_cast<Visual*>(visual)),
|
| + 0, NULL);
|
| + } else {
|
| + picture_ = 0;
|
| + pixmap_bpp_ = x11_util::BitsPerPixelForPixmapDepth(display, depth);
|
| + }
|
| +
|
| pixmap_gc_ = XCreateGC(display_, pixmap_, 0, NULL);
|
| }
|
|
|
| @@ -47,6 +60,8 @@ BackingStore::BackingStore(const gfx::Size& size)
|
| : size_(size),
|
| display_(NULL),
|
| use_shared_memory_(false),
|
| + use_render_(false),
|
| + visual_depth_(-1),
|
| root_window_(0) {
|
| }
|
|
|
| @@ -60,12 +75,89 @@ BackingStore::~BackingStore() {
|
| XFreeGC(display_, static_cast<GC>(pixmap_gc_));
|
| }
|
|
|
| +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_);
|
| +
|
| + XImage image;
|
| + memset(&image, 0, sizeof(image));
|
| +
|
| + image.width = width;
|
| + image.height = height;
|
| + image.format = ZPixmap;
|
| + image.byte_order = LSBFirst;
|
| + image.bitmap_unit = 8;
|
| + image.bitmap_bit_order = LSBFirst;
|
| + image.red_mask = 0xff;
|
| + image.green_mask = 0xff00;
|
| + image.blue_mask = 0xff0000;
|
| +
|
| + 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.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);
|
| + } 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
|
| + // support Xrender but typically have 24-bit visuals.
|
| + //
|
| + // 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));
|
| + 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 uint32_t pixel = *(bitmap_in++);
|
| + bitmap24[0] = (pixel >> 16) & 0xff;
|
| + bitmap24[1] = (pixel >> 8) & 0xff;
|
| + bitmap24[2] = pixel & 0xff;
|
| + bitmap24 += 3;
|
| + }
|
| + }
|
| +
|
| + image.depth = visual_depth_;
|
| + image.bits_per_pixel = 24;
|
| + image.bytes_per_line = 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);
|
| +
|
| + free(bitmap24);
|
| + } else {
|
| + CHECK(false) << "Sorry, we don't support your visual depth without "
|
| + "Xrender support (depth:" << visual_depth_
|
| + << " bpp:" << pixmap_bpp_ << ")";
|
| + }
|
| +
|
| + 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 */);
|
| +
|
| + XFreePixmap(display_, pixmap);
|
| +}
|
| +
|
| void BackingStore::PaintRect(base::ProcessHandle process,
|
| TransportDIB* bitmap,
|
| const gfx::Rect& bitmap_rect) {
|
| if (!display_)
|
| return;
|
|
|
| + if (!use_render_)
|
| + return PaintRectWithoutXrender(bitmap, bitmap_rect);
|
| +
|
| const int width = bitmap_rect.width();
|
| const int height = bitmap_rect.height();
|
| Picture picture;
|
|
|