| 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
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..b4a7caed6f321d63ffa41c5b1c6e632814da601f
|
| --- /dev/null
|
| +++ b/chrome/browser/renderer_host/backing_store_x.cc
|
| @@ -0,0 +1,169 @@
|
| +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "chrome/browser/renderer_host/backing_store.h"
|
| +
|
| +#include <utility>
|
| +
|
| +#include "base/logging.h"
|
| +#include "chrome/common/transport_dib.h"
|
| +#include "chrome/common/x11_util.h"
|
| +#include "chrome/common/x11_util_internal.h"
|
| +
|
| +// X Backing Stores:
|
| +//
|
| +// Unlike Windows, where the backing store is kept in heap memory, we keep our
|
| +// backing store in the X server, as a pixmap. Thus expose events just require
|
| +// instructing the X server to copy from the backing store to the window.
|
| +//
|
| +// The backing store is in the same format as the visual which our main window
|
| +// is using. Bitmaps from the renderer are uploaded to the X server, either via
|
| +// shared memory or over the wire, and XRENDER is used to convert them to the
|
| +// correct format for the backing store.
|
| +
|
| +BackingStore::BackingStore(const gfx::Size& size,
|
| + Display* display,
|
| + int depth,
|
| + void* visual,
|
| + Drawable parent_window,
|
| + bool use_shared_memory)
|
| + : size_(size),
|
| + display_(display),
|
| + use_shared_memory_(use_shared_memory),
|
| + parent_window_(parent_window) {
|
| + const int width = size.width();
|
| + const int height = size.height();
|
| +
|
| + pixmap_ = XCreatePixmap(display_, parent_window, width, height, depth);
|
| + picture_ = XRenderCreatePicture(
|
| + display_, pixmap_,
|
| + x11_util::GetRenderVisualFormat(display_, static_cast<Visual*>(visual)),
|
| + 0, NULL);
|
| + pixmap_gc_ = XCreateGC(display_, pixmap_, 0, NULL);
|
| +}
|
| +
|
| +BackingStore::BackingStore(const gfx::Size& size)
|
| + : size_(size),
|
| + display_(NULL),
|
| + use_shared_memory_(false),
|
| + parent_window_(0) {
|
| +}
|
| +
|
| +BackingStore::~BackingStore() {
|
| + // In unit tests, display_ may be NULL.
|
| + if (!display_)
|
| + return;
|
| +
|
| + XRenderFreePicture(display_, picture_);
|
| + XFreePixmap(display_, pixmap_);
|
| + XFreeGC(display_, static_cast<GC>(pixmap_gc_));
|
| +}
|
| +
|
| +void BackingStore::PaintRect(base::ProcessHandle process,
|
| + TransportDIB* bitmap,
|
| + const gfx::Rect& bitmap_rect) {
|
| + if (!display_)
|
| + return;
|
| +
|
| + const int width = bitmap_rect.width();
|
| + const int height = bitmap_rect.height();
|
| + Picture picture;
|
| + Pixmap pixmap;
|
| +
|
| + if (use_shared_memory_) {
|
| + const XID shmseg = bitmap->MapToX(display_);
|
| +
|
| + XShmSegmentInfo shminfo;
|
| + memset(&shminfo, 0, sizeof(shminfo));
|
| + shminfo.shmseg = shmseg;
|
| +
|
| + // The NULL in the following is the |data| pointer: this is an artifact of
|
| + // Xlib trying to be helpful, rather than just exposing the X protocol. It
|
| + // assumes that we have the shared memory segment mapped into our memory,
|
| + // which we don't, and it's trying to calculate an offset by taking the
|
| + // 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_, parent_window_, NULL, &shminfo, width,
|
| + height, 32);
|
| + } 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
|
| + // functions which try to convert the image into the format which the X
|
| + // server expects. The following values hopefully disable all conversions.
|
| + XImage image;
|
| + memset(&image, 0, sizeof(image));
|
| +
|
| + image.width = width;
|
| + image.height = 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.red_mask = 0xff;
|
| + image.green_mask = 0xff00;
|
| + image.blue_mask = 0xff0000;
|
| + image.data = static_cast<char*>(bitmap->memory());
|
| +
|
| + pixmap = XCreatePixmap(display_, parent_window_, width, 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);
|
| + XFreeGC(display_, gc);
|
| + }
|
| +
|
| + picture = x11_util::CreatePictureFromSkiaPixmap(display_, pixmap);
|
| + XRenderComposite(display_, PictOpSrc, picture /* source */, 0 /* mask */,
|
| + picture_ /* dest */, 0, 0 /* source x, y */,
|
| + 0, 0 /* mask x, y */,
|
| + bitmap_rect.x(), bitmap_rect.y() /* target x, y */,
|
| + width, 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.
|
| + if (use_shared_memory_)
|
| + XSync(display_, False);
|
| +
|
| + XRenderFreePicture(display_, picture);
|
| + XFreePixmap(display_, pixmap);
|
| +}
|
| +
|
| +void BackingStore::ScrollRect(base::ProcessHandle process,
|
| + TransportDIB* bitmap,
|
| + const gfx::Rect& bitmap_rect,
|
| + int dx, int dy,
|
| + const gfx::Rect& clip_rect,
|
| + const gfx::Size& view_size) {
|
| + if (!display_)
|
| + return;
|
| +
|
| + // We only support scrolling in one direction at a time.
|
| + DCHECK(dx == 0 || dy == 0);
|
| +
|
| + if (dy) {
|
| + // Positive values of |dy| scroll up
|
| + XCopyArea(display_, pixmap_, pixmap_, static_cast<GC>(pixmap_gc_),
|
| + 0, std::max(0, -dy) /* source x, y */,
|
| + size_.width(), size_.height() - abs(dy),
|
| + 0, std::max(0, dy) /* dest x, y */);
|
| + } else if (dx) {
|
| + // Positive values of |dx| scroll right
|
| + XCopyArea(display_, pixmap_, pixmap_, static_cast<GC>(pixmap_gc_),
|
| + std::max(0, -dx), 0 /* source x, y */,
|
| + size_.width() - abs(dx), size_.height(),
|
| + std::max(0, dx), 0 /* dest x, y */);
|
| + }
|
| +
|
| + PaintRect(process, bitmap, bitmap_rect);
|
| +}
|
| +
|
| +void BackingStore::ShowRect(const gfx::Rect& rect) {
|
| + XCopyArea(display_, pixmap_, parent_window_, static_cast<GC>(pixmap_gc_),
|
| + rect.x(), rect.y(), rect.width(), rect.height(),
|
| + rect.x(), rect.y());
|
| +}
|
|
|