summaryrefslogtreecommitdiffstats
path: root/chrome/common
diff options
context:
space:
mode:
authorscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-19 01:10:16 +0000
committerscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-19 01:10:16 +0000
commitee77fcf1bab6f960d3b452ce86703af602bcb6d6 (patch)
tree2869b71ae6a0c797038c58e8737dae4d80137b17 /chrome/common
parent764627b3152582d2fa16168e1756ed3e83941c74 (diff)
downloadchromium_src-ee77fcf1bab6f960d3b452ce86703af602bcb6d6.zip
chromium_src-ee77fcf1bab6f960d3b452ce86703af602bcb6d6.tar.gz
chromium_src-ee77fcf1bab6f960d3b452ce86703af602bcb6d6.tar.bz2
Extracted non-XRender painting path from BackingStoreX into PutARGBImage().
BUG=n/a TEST=everything should stay the same Review URL: http://codereview.chromium.org/647062 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@39410 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/common')
-rw-r--r--chrome/common/x11_util.cc97
-rw-r--r--chrome/common/x11_util.h7
2 files changed, 104 insertions, 0 deletions
diff --git a/chrome/common/x11_util.cc b/chrome/common/x11_util.cc
index d857870..27eb2d4 100644
--- a/chrome/common/x11_util.cc
+++ b/chrome/common/x11_util.cc
@@ -495,6 +495,103 @@ XID CreatePictureFromSkiaPixmap(Display* display, XID pixmap) {
return picture;
}
+void PutARGBImage(Display* display, void* visual, int depth, XID pixmap,
+ void* pixmap_gc, const uint8* data, int width, int height) {
+ // TODO(scherkus): potential performance impact... consider passing in as a
+ // parameter.
+ int pixmap_bpp = BitsPerPixelForPixmapDepth(display, 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.depth = depth;
+ image.bits_per_pixel = pixmap_bpp;
+ image.bytes_per_line = width * pixmap_bpp / 8;
+
+ if (pixmap_bpp == 32) {
+ image.red_mask = 0xff0000;
+ image.green_mask = 0xff00;
+ image.blue_mask = 0xff;
+
+ // If the X server depth is already 32-bits and the color masks match,
+ // then our job is easy.
+ Visual* vis = static_cast<Visual*>(visual);
+ if (image.red_mask == vis->red_mask &&
+ image.green_mask == vis->green_mask &&
+ image.blue_mask == vis->blue_mask) {
+ image.data = const_cast<char*>(reinterpret_cast<const char*>(data));
+ XPutImage(display, pixmap, static_cast<GC>(pixmap_gc), &image,
+ 0, 0 /* source x, y */, 0, 0 /* dest x, y */,
+ width, height);
+ } else {
+ // Otherwise, we need to shuffle the colors around. Assume red and blue
+ // need to be swapped.
+ //
+ // It's possible to use some fancy SSE tricks here, but since this is the
+ // slow path anyway, we do it slowly.
+
+ uint8_t* bitmap32 = static_cast<uint8_t*>(malloc(4 * width * height));
+ if (!bitmap32)
+ return;
+ uint8_t* const orig_bitmap32 = bitmap32;
+ const uint32_t* bitmap_in = reinterpret_cast<const uint32_t*>(data);
+ for (int y = 0; y < height; ++y) {
+ for (int x = 0; x < width; ++x) {
+ const uint32_t pixel = *(bitmap_in++);
+ bitmap32[0] = (pixel >> 16) & 0xff; // Red
+ bitmap32[1] = (pixel >> 8) & 0xff; // Green
+ bitmap32[2] = pixel & 0xff; // Blue
+ bitmap32[3] = (pixel >> 24) & 0xff; // Alpha
+ bitmap32 += 4;
+ }
+ }
+ image.data = reinterpret_cast<char*>(orig_bitmap32);
+ XPutImage(display, pixmap, static_cast<GC>(pixmap_gc), &image,
+ 0, 0 /* source x, y */, 0, 0 /* dest x, y */,
+ width, height);
+ free(orig_bitmap32);
+ }
+ } 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));
+ if (!bitmap16)
+ return;
+ uint16_t* const orig_bitmap16 = bitmap16;
+ const uint32_t* bitmap_in = reinterpret_cast<const uint32_t*>(data);
+ for (int y = 0; y < height; ++y) {
+ for (int x = 0; x < width; ++x) {
+ const uint32_t pixel = *(bitmap_in++);
+ uint16_t out_pixel = ((pixel >> 8) & 0xf800) |
+ ((pixel >> 5) & 0x07e0) |
+ ((pixel >> 3) & 0x001f);
+ *(bitmap16++) = out_pixel;
+ }
+ }
+
+ image.data = reinterpret_cast<char*>(orig_bitmap16);
+ image.red_mask = 0xf800;
+ image.green_mask = 0x07e0;
+ image.blue_mask = 0x001f;
+
+ XPutImage(display, pixmap, static_cast<GC>(pixmap_gc), &image,
+ 0, 0 /* source x, y */, 0, 0 /* dest x, y */,
+ width, height);
+ free(orig_bitmap16);
+ } else {
+ CHECK(false) << "Sorry, we don't support your visual depth without "
+ "Xrender support (depth:" << depth
+ << " bpp:" << pixmap_bpp << ")";
+ }
+}
+
void FreePicture(Display* display, XID picture) {
XRenderFreePicture(display, picture);
}
diff --git a/chrome/common/x11_util.h b/chrome/common/x11_util.h
index 769f941..02285f4 100644
--- a/chrome/common/x11_util.h
+++ b/chrome/common/x11_util.h
@@ -124,6 +124,13 @@ void DetachSharedMemory(Display* display, XSharedMemoryId shmseg);
// pixmap containing Skia ARGB data.
XID CreatePictureFromSkiaPixmap(Display* display, XID pixmap);
+// Draws ARGB data on the given pixmap using the given GC, converting to the
+// server side visual depth as needed. Destination is assumed to be the same
+// dimensions as |data| or larger. |data| is also assumed to be in row order
+// with each line being exactly |width| * 4 bytes long.
+void PutARGBImage(Display* display, void* visual, int depth, XID pixmap,
+ void* pixmap_gc, const uint8* data, int width, int height);
+
void FreePicture(Display* display, XID picture);
void FreePixmap(Display* display, XID pixmap);