diff options
author | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-19 01:10:16 +0000 |
---|---|---|
committer | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-19 01:10:16 +0000 |
commit | ee77fcf1bab6f960d3b452ce86703af602bcb6d6 (patch) | |
tree | 2869b71ae6a0c797038c58e8737dae4d80137b17 /chrome/common | |
parent | 764627b3152582d2fa16168e1756ed3e83941c74 (diff) | |
download | chromium_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.cc | 97 | ||||
-rw-r--r-- | chrome/common/x11_util.h | 7 |
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); |