From 272e57235cd60a2e65ac8258d96a02eb3939b687 Mon Sep 17 00:00:00 2001 From: marha Date: Fri, 25 Mar 2011 10:41:05 +0000 Subject: git update until 25 Mar 2011 xserver fontconfig glproto libXau libXft libXmu libfontenc libxcb mesa mkfontscale pixman randrproto xkeyboard-config xtrans xwininfo updated following packages: xproto-7.0.21 xineramaproto-1.2.1 libXt-1.1.1 libxkbfile-1.0.7 libXpm-3.5.9 libXfont-1.4.3 libXaw-1.0.9 bdftopcf-1.0.3 encodings-1.0.4 fixesproto-5.0 font-adobe-100dpi-1.0.3 font-adobe-75dpi-1.0.3 font-adobe-utopia-100dpi-1.0.4 font-adobe-utopia-75dpi-1.0.4 font-adobe-utopia-type1-1.0.4 font-alias-1.0.3 font-arabic-misc-1.0.3 font-bh-100dpi-1.0.3 font-bh-75dpi-1.0.3 font-bh-lucidatypewriter-100dpi-1.0.3 font-bh-lucidatypewriter-75dpi-1.0.3 font-bh-ttf-1.0.3 font-bh-type1-1.0.3 font-bitstream-100dpi-1.0.3 font-bitstream-75dpi-1.0.3 font-bitstream-speedo-1.0.2 font-bitstream-type1-1.0.3 font-cronyx-cyrillic-1.0.3 font-cursor-misc-1.0.3 font-daewoo-misc-1.0.3 font-dec-misc-1.0.3 font-ibm-type1-1.0.3 font-isas-misc-1.0.3 font-jis-misc-1.0.3 font-micro-misc-1.0.3 font-misc-cyrillic-1.0.3 font-misc-ethiopic-1.0.3 font-misc-meltho-1.0.3 font-misc-misc-1.1.2 font-mutt-misc-1.0.3 font-schumacher-misc-1.1.2 font-screen-cyrillic-1.0.4 font-sony-misc-1.0.3 font-sun-misc-1.0.3 font-util-1.2.0 font-winitzki-cyrillic-1.0.3 font-xfree86-type1-1.0.4 --- pixman/pixman/pixman-access.c | 6075 +++++++++++++++++++++-------------------- pixman/pixman/pixman.c | 2428 ++++++++-------- pixman/pixman/pixman.h | 1976 +++++++------- pixman/test/blitters-test.c | 839 +++--- pixman/test/composite.c | 17 +- pixman/test/fetch-test.c | 10 + pixman/test/stress-test.c | 2 + 7 files changed, 5740 insertions(+), 5607 deletions(-) (limited to 'pixman') diff --git a/pixman/pixman/pixman-access.c b/pixman/pixman/pixman-access.c index 8dc770081..32c4d8b2c 100644 --- a/pixman/pixman/pixman-access.c +++ b/pixman/pixman/pixman-access.c @@ -1,2989 +1,3086 @@ -/* - * - * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc. - * 2005 Lars Knoll & Zack Rusin, Trolltech - * 2008 Aaron Plattner, NVIDIA Corporation - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Keith Packard not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Keith Packard makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include - -#include "pixman-private.h" -#include "pixman-accessor.h" - -#define CONVERT_RGB24_TO_Y15(s) \ - (((((s) >> 16) & 0xff) * 153 + \ - (((s) >> 8) & 0xff) * 301 + \ - (((s) ) & 0xff) * 58) >> 2) - -#define CONVERT_RGB24_TO_RGB15(s) \ - ((((s) >> 3) & 0x001f) | \ - (((s) >> 6) & 0x03e0) | \ - (((s) >> 9) & 0x7c00)) - -#define RGB15_TO_ENTRY(mif,rgb15) \ - ((mif)->ent[rgb15]) - -#define RGB24_TO_ENTRY(mif,rgb24) \ - RGB15_TO_ENTRY (mif,CONVERT_RGB24_TO_RGB15 (rgb24)) - -#define RGB24_TO_ENTRY_Y(mif,rgb24) \ - ((mif)->ent[CONVERT_RGB24_TO_Y15 (rgb24)]) - -/* - * YV12 setup and access macros - */ - -#define YV12_SETUP(image) \ - bits_image_t *__bits_image = (bits_image_t *)image; \ - uint32_t *bits = __bits_image->bits; \ - int stride = __bits_image->rowstride; \ - int offset0 = stride < 0 ? \ - ((-stride) >> 1) * ((__bits_image->height - 1) >> 1) - stride : \ - stride * __bits_image->height; \ - int offset1 = stride < 0 ? \ - offset0 + ((-stride) >> 1) * ((__bits_image->height) >> 1) : \ - offset0 + (offset0 >> 2) - -/* Note no trailing semicolon on the above macro; if it's there, then - * the typical usage of YV12_SETUP(image); will have an extra trailing ; - * that some compilers will interpret as a statement -- and then any further - * variable declarations will cause an error. - */ - -#define YV12_Y(line) \ - ((uint8_t *) ((bits) + (stride) * (line))) - -#define YV12_U(line) \ - ((uint8_t *) ((bits) + offset1 + \ - ((stride) >> 1) * ((line) >> 1))) - -#define YV12_V(line) \ - ((uint8_t *) ((bits) + offset0 + \ - ((stride) >> 1) * ((line) >> 1))) - -/********************************** Fetch ************************************/ - -static void -fetch_scanline_a8r8g8b8 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - - MEMCPY_WRAPPED (image, - buffer, (const uint32_t *)bits + x, - width * sizeof(uint32_t)); -} - -static void -fetch_scanline_x8r8g8b8 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - const uint32_t *pixel = (const uint32_t *)bits + x; - const uint32_t *end = pixel + width; - - while (pixel < end) - *buffer++ = READ (image, pixel++) | 0xff000000; -} - -static void -fetch_scanline_a8b8g8r8 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - const uint32_t *pixel = (uint32_t *)bits + x; - const uint32_t *end = pixel + width; - - while (pixel < end) - { - uint32_t p = READ (image, pixel++); - - *buffer++ = (p & 0xff00ff00) | - ((p >> 16) & 0xff) | - ((p & 0xff) << 16); - } -} - -static void -fetch_scanline_x8b8g8r8 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - const uint32_t *pixel = (uint32_t *)bits + x; - const uint32_t *end = pixel + width; - - while (pixel < end) - { - uint32_t p = READ (image, pixel++); - - *buffer++ = 0xff000000 | - (p & 0x0000ff00) | - ((p >> 16) & 0xff) | - ((p & 0xff) << 16); - } -} - -static void -fetch_scanline_b8g8r8a8 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - const uint32_t *pixel = (uint32_t *)bits + x; - const uint32_t *end = pixel + width; - - while (pixel < end) - { - uint32_t p = READ (image, pixel++); - - *buffer++ = (((p & 0xff000000) >> 24) | - ((p & 0x00ff0000) >> 8) | - ((p & 0x0000ff00) << 8) | - ((p & 0x000000ff) << 24)); - } -} - -static void -fetch_scanline_b8g8r8x8 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - const uint32_t *pixel = (uint32_t *)bits + x; - const uint32_t *end = pixel + width; - - while (pixel < end) - { - uint32_t p = READ (image, pixel++); - - *buffer++ = (0xff000000 | - ((p & 0xff000000) >> 24) | - ((p & 0x00ff0000) >> 8) | - ((p & 0x0000ff00) << 8)); - } -} - -static void -fetch_scanline_x14r6g6b6 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - const uint32_t *pixel = (const uint32_t *)bits + x; - const uint32_t *end = pixel + width; - - while (pixel < end) - { - uint32_t p = READ (image, pixel++); - uint32_t r, g, b; - - r = ((p & 0x3f000) << 6) | ((p & 0x30000)); - g = ((p & 0x00fc0) << 4) | ((p & 0x00c00) >> 2); - b = ((p & 0x0003f) << 2) | ((p & 0x00030) >> 4); - - *buffer++ = 0xff000000 | r | g | b; - } -} - -/* Expects a uint64_t buffer */ -static void -fetch_scanline_a2r10g10b10 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * b, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - const uint32_t *pixel = bits + x; - const uint32_t *end = pixel + width; - uint64_t *buffer = (uint64_t *)b; - - while (pixel < end) - { - uint32_t p = READ (image, pixel++); - uint64_t a = p >> 30; - uint64_t r = (p >> 20) & 0x3ff; - uint64_t g = (p >> 10) & 0x3ff; - uint64_t b = p & 0x3ff; - - r = r << 6 | r >> 4; - g = g << 6 | g >> 4; - b = b << 6 | b >> 4; - - a <<= 14; - a |= a >> 2; - a |= a >> 4; - a |= a >> 8; - - *buffer++ = a << 48 | r << 32 | g << 16 | b; - } -} - -/* Expects a uint64_t buffer */ -static void -fetch_scanline_x2r10g10b10 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * b, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - const uint32_t *pixel = (uint32_t *)bits + x; - const uint32_t *end = pixel + width; - uint64_t *buffer = (uint64_t *)b; - - while (pixel < end) - { - uint32_t p = READ (image, pixel++); - uint64_t r = (p >> 20) & 0x3ff; - uint64_t g = (p >> 10) & 0x3ff; - uint64_t b = p & 0x3ff; - - r = r << 6 | r >> 4; - g = g << 6 | g >> 4; - b = b << 6 | b >> 4; - - *buffer++ = 0xffffULL << 48 | r << 32 | g << 16 | b; - } -} - -/* Expects a uint64_t buffer */ -static void -fetch_scanline_a2b10g10r10 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * b, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - const uint32_t *pixel = bits + x; - const uint32_t *end = pixel + width; - uint64_t *buffer = (uint64_t *)b; - - while (pixel < end) - { - uint32_t p = READ (image, pixel++); - uint64_t a = p >> 30; - uint64_t b = (p >> 20) & 0x3ff; - uint64_t g = (p >> 10) & 0x3ff; - uint64_t r = p & 0x3ff; - - r = r << 6 | r >> 4; - g = g << 6 | g >> 4; - b = b << 6 | b >> 4; - - a <<= 14; - a |= a >> 2; - a |= a >> 4; - a |= a >> 8; - - *buffer++ = a << 48 | r << 32 | g << 16 | b; - } -} - -/* Expects a uint64_t buffer */ -static void -fetch_scanline_x2b10g10r10 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * b, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - const uint32_t *pixel = (uint32_t *)bits + x; - const uint32_t *end = pixel + width; - uint64_t *buffer = (uint64_t *)b; - - while (pixel < end) - { - uint32_t p = READ (image, pixel++); - uint64_t b = (p >> 20) & 0x3ff; - uint64_t g = (p >> 10) & 0x3ff; - uint64_t r = p & 0x3ff; - - r = r << 6 | r >> 4; - g = g << 6 | g >> 4; - b = b << 6 | b >> 4; - - *buffer++ = 0xffffULL << 48 | r << 32 | g << 16 | b; - } -} - -static void -fetch_scanline_r8g8b8 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - const uint8_t *pixel = (const uint8_t *)bits + 3 * x; - const uint8_t *end = pixel + 3 * width; - - while (pixel < end) - { - uint32_t b = 0xff000000; - -#ifdef WORDS_BIGENDIAN - b |= (READ (image, pixel++) << 16); - b |= (READ (image, pixel++) << 8); - b |= (READ (image, pixel++)); -#else - b |= (READ (image, pixel++)); - b |= (READ (image, pixel++) << 8); - b |= (READ (image, pixel++) << 16); -#endif - - *buffer++ = b; - } -} - -static void -fetch_scanline_b8g8r8 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - const uint8_t *pixel = (const uint8_t *)bits + 3 * x; - const uint8_t *end = pixel + 3 * width; - - while (pixel < end) - { - uint32_t b = 0xff000000; -#ifdef WORDS_BIGENDIAN - b |= (READ (image, pixel++)); - b |= (READ (image, pixel++) << 8); - b |= (READ (image, pixel++) << 16); -#else - b |= (READ (image, pixel++) << 16); - b |= (READ (image, pixel++) << 8); - b |= (READ (image, pixel++)); -#endif - *buffer++ = b; - } -} - -static void -fetch_scanline_r5g6b5 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - const uint16_t *pixel = (const uint16_t *)bits + x; - const uint16_t *end = pixel + width; - - while (pixel < end) - { - uint32_t p = READ (image, pixel++); - uint32_t r = (((p) << 3) & 0xf8) | - (((p) << 5) & 0xfc00) | - (((p) << 8) & 0xf80000); - - r |= (r >> 5) & 0x70007; - r |= (r >> 6) & 0x300; - - *buffer++ = 0xff000000 | r; - } -} - -static void -fetch_scanline_b5g6r5 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - const uint16_t *pixel = (const uint16_t *)bits + x; - const uint16_t *end = pixel + width; - - while (pixel < end) - { - uint32_t p = READ (image, pixel++); - uint32_t r, g, b; - - b = ((p & 0xf800) | ((p & 0xe000) >> 5)) >> 8; - g = ((p & 0x07e0) | ((p & 0x0600) >> 6)) << 5; - r = ((p & 0x001c) | ((p & 0x001f) << 5)) << 14; - - *buffer++ = 0xff000000 | r | g | b; - } -} - -static void -fetch_scanline_a1r5g5b5 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - const uint16_t *pixel = (const uint16_t *)bits + x; - const uint16_t *end = pixel + width; - - while (pixel < end) - { - uint32_t p = READ (image, pixel++); - uint32_t r, g, b, a; - - a = (uint32_t) ((uint8_t) (0 - ((p & 0x8000) >> 15))) << 24; - r = ((p & 0x7c00) | ((p & 0x7000) >> 5)) << 9; - g = ((p & 0x03e0) | ((p & 0x0380) >> 5)) << 6; - b = ((p & 0x001c) | ((p & 0x001f) << 5)) >> 2; - - *buffer++ = a | r | g | b; - } -} - -static void -fetch_scanline_x1r5g5b5 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - const uint16_t *pixel = (const uint16_t *)bits + x; - const uint16_t *end = pixel + width; - - while (pixel < end) - { - uint32_t p = READ (image, pixel++); - uint32_t r, g, b; - - r = ((p & 0x7c00) | ((p & 0x7000) >> 5)) << 9; - g = ((p & 0x03e0) | ((p & 0x0380) >> 5)) << 6; - b = ((p & 0x001c) | ((p & 0x001f) << 5)) >> 2; - - *buffer++ = 0xff000000 | r | g | b; - } -} - -static void -fetch_scanline_a1b5g5r5 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - const uint16_t *pixel = (const uint16_t *)bits + x; - const uint16_t *end = pixel + width; - uint32_t r, g, b, a; - - while (pixel < end) - { - uint32_t p = READ (image, pixel++); - - a = (uint32_t) ((uint8_t) (0 - ((p & 0x8000) >> 15))) << 24; - b = ((p & 0x7c00) | ((p & 0x7000) >> 5)) >> 7; - g = ((p & 0x03e0) | ((p & 0x0380) >> 5)) << 6; - r = ((p & 0x001c) | ((p & 0x001f) << 5)) << 14; - - *buffer++ = a | r | g | b; - } -} - -static void -fetch_scanline_x1b5g5r5 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - const uint16_t *pixel = (const uint16_t *)bits + x; - const uint16_t *end = pixel + width; - - while (pixel < end) - { - uint32_t p = READ (image, pixel++); - uint32_t r, g, b; - - b = ((p & 0x7c00) | ((p & 0x7000) >> 5)) >> 7; - g = ((p & 0x03e0) | ((p & 0x0380) >> 5)) << 6; - r = ((p & 0x001c) | ((p & 0x001f) << 5)) << 14; - - *buffer++ = 0xff000000 | r | g | b; - } -} - -static void -fetch_scanline_a4r4g4b4 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - const uint16_t *pixel = (const uint16_t *)bits + x; - const uint16_t *end = pixel + width; - - while (pixel < end) - { - uint32_t p = READ (image, pixel++); - uint32_t r, g, b, a; - - a = ((p & 0xf000) | ((p & 0xf000) >> 4)) << 16; - r = ((p & 0x0f00) | ((p & 0x0f00) >> 4)) << 12; - g = ((p & 0x00f0) | ((p & 0x00f0) >> 4)) << 8; - b = ((p & 0x000f) | ((p & 0x000f) << 4)); - - *buffer++ = a | r | g | b; - } -} - -static void -fetch_scanline_x4r4g4b4 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - const uint16_t *pixel = (const uint16_t *)bits + x; - const uint16_t *end = pixel + width; - - while (pixel < end) - { - uint32_t p = READ (image, pixel++); - uint32_t r, g, b; - - r = ((p & 0x0f00) | ((p & 0x0f00) >> 4)) << 12; - g = ((p & 0x00f0) | ((p & 0x00f0) >> 4)) << 8; - b = ((p & 0x000f) | ((p & 0x000f) << 4)); - - *buffer++ = 0xff000000 | r | g | b; - } -} - -static void -fetch_scanline_a4b4g4r4 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - const uint16_t *pixel = (const uint16_t *)bits + x; - const uint16_t *end = pixel + width; - - while (pixel < end) - { - uint32_t p = READ (image, pixel++); - uint32_t r, g, b, a; - - a = ((p & 0xf000) | ((p & 0xf000) >> 4)) << 16; - b = ((p & 0x0f00) | ((p & 0x0f00) >> 4)) >> 4; - g = ((p & 0x00f0) | ((p & 0x00f0) >> 4)) << 8; - r = ((p & 0x000f) | ((p & 0x000f) << 4)) << 16; - - *buffer++ = a | r | g | b; - } -} - -static void -fetch_scanline_x4b4g4r4 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - const uint16_t *pixel = (const uint16_t *)bits + x; - const uint16_t *end = pixel + width; - - while (pixel < end) - { - uint32_t p = READ (image, pixel++); - uint32_t r, g, b; - - b = ((p & 0x0f00) | ((p & 0x0f00) >> 4)) >> 4; - g = ((p & 0x00f0) | ((p & 0x00f0) >> 4)) << 8; - r = ((p & 0x000f) | ((p & 0x000f) << 4)) << 16; - - *buffer++ = 0xff000000 | r | g | b; - } -} - -static void -fetch_scanline_a8 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - const uint8_t *pixel = (const uint8_t *)bits + x; - const uint8_t *end = pixel + width; - - while (pixel < end) - *buffer++ = READ (image, pixel++) << 24; -} - -static void -fetch_scanline_r3g3b2 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - const uint8_t *pixel = (const uint8_t *)bits + x; - const uint8_t *end = pixel + width; - - while (pixel < end) - { - uint32_t p = READ (image, pixel++); - uint32_t r, g, b; - - r = ((p & 0xe0) | ((p & 0xe0) >> 3) | ((p & 0xc0) >> 6)) << 16; - g = ((p & 0x1c) | ((p & 0x18) >> 3) | ((p & 0x1c) << 3)) << 8; - b = (((p & 0x03) ) | - ((p & 0x03) << 2) | - ((p & 0x03) << 4) | - ((p & 0x03) << 6)); - - *buffer++ = 0xff000000 | r | g | b; - } -} - -static void -fetch_scanline_b2g3r3 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - const uint8_t *pixel = (const uint8_t *)bits + x; - const uint8_t *end = pixel + width; - - while (pixel < end) - { - uint32_t p = READ (image, pixel++); - uint32_t r, g, b; - - b = p & 0xc0; - b |= b >> 2; - b |= b >> 4; - b &= 0xff; - - g = (p & 0x38) << 10; - g |= g >> 3; - g |= g >> 6; - g &= 0xff00; - - r = (p & 0x7) << 21; - r |= r >> 3; - r |= r >> 6; - r &= 0xff0000; - - *buffer++ = 0xff000000 | r | g | b; - } -} - -static void -fetch_scanline_a2r2g2b2 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - const uint8_t *pixel = (const uint8_t *)bits + x; - const uint8_t *end = pixel + width; - - while (pixel < end) - { - uint32_t p = READ (image, pixel++); - uint32_t a, r, g, b; - - a = ((p & 0xc0) * 0x55) << 18; - r = ((p & 0x30) * 0x55) << 12; - g = ((p & 0x0c) * 0x55) << 6; - b = ((p & 0x03) * 0x55); - - *buffer++ = a | r | g | b; - } -} - -static void -fetch_scanline_a2b2g2r2 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - const uint8_t *pixel = (const uint8_t *)bits + x; - const uint8_t *end = pixel + width; - - while (pixel < end) - { - uint32_t p = READ (image, pixel++); - uint32_t a, r, g, b; - - a = ((p & 0xc0) * 0x55) << 18; - b = ((p & 0x30) * 0x55) >> 4; - g = ((p & 0x0c) * 0x55) << 6; - r = ((p & 0x03) * 0x55) << 16; - - *buffer++ = a | r | g | b; - } -} - -static void -fetch_scanline_c8 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - const pixman_indexed_t * indexed = image->bits.indexed; - const uint8_t *pixel = (const uint8_t *)bits + x; - const uint8_t *end = pixel + width; - - while (pixel < end) - { - uint32_t p = READ (image, pixel++); - - *buffer++ = indexed->rgba[p]; - } -} - -static void -fetch_scanline_x4a4 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - const uint8_t *pixel = (const uint8_t *)bits + x; - const uint8_t *end = pixel + width; - - while (pixel < end) - { - uint8_t p = READ (image, pixel++) & 0xf; - - *buffer++ = (p | (p << 4)) << 24; - } -} - -#define FETCH_8(img,l,o) (READ (img, (((uint8_t *)(l)) + ((o) >> 3)))) -#ifdef WORDS_BIGENDIAN -#define FETCH_4(img,l,o) \ - (((4 * (o)) & 4) ? (FETCH_8 (img,l, 4 * (o)) & 0xf) : (FETCH_8 (img,l,(4 * (o))) >> 4)) -#else -#define FETCH_4(img,l,o) \ - (((4 * (o)) & 4) ? (FETCH_8 (img, l, 4 * (o)) >> 4) : (FETCH_8 (img, l, (4 * (o))) & 0xf)) -#endif - -static void -fetch_scanline_a4 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - int i; - - for (i = 0; i < width; ++i) - { - uint32_t p = FETCH_4 (image, bits, i + x); - - p |= p << 4; - - *buffer++ = p << 24; - } -} - -static void -fetch_scanline_r1g2b1 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - int i; - - for (i = 0; i < width; ++i) - { - uint32_t p = FETCH_4 (image, bits, i + x); - uint32_t r, g, b; - - r = ((p & 0x8) * 0xff) << 13; - g = ((p & 0x6) * 0x55) << 7; - b = ((p & 0x1) * 0xff); - - *buffer++ = 0xff000000 | r | g | b; - } -} - -static void -fetch_scanline_b1g2r1 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - int i; - - for (i = 0; i < width; ++i) - { - uint32_t p = FETCH_4 (image, bits, i + x); - uint32_t r, g, b; - - b = ((p & 0x8) * 0xff) >> 3; - g = ((p & 0x6) * 0x55) << 7; - r = ((p & 0x1) * 0xff) << 16; - - *buffer++ = 0xff000000 | r | g | b; - } -} - -static void -fetch_scanline_a1r1g1b1 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) -{ - uint32_t a, r, g, b; - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - int i; - - for (i = 0; i < width; ++i) - { - uint32_t p = FETCH_4 (image, bits, i + x); - - a = ((p & 0x8) * 0xff) << 21; - r = ((p & 0x4) * 0xff) << 14; - g = ((p & 0x2) * 0xff) << 7; - b = ((p & 0x1) * 0xff); - - *buffer++ = a | r | g | b; - } -} - -static void -fetch_scanline_a1b1g1r1 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - int i; - - for (i = 0; i < width; ++i) - { - uint32_t p = FETCH_4 (image, bits, i + x); - uint32_t a, r, g, b; - - a = ((p & 0x8) * 0xff) << 21; - b = ((p & 0x4) * 0xff) >> 2; - g = ((p & 0x2) * 0xff) << 7; - r = ((p & 0x1) * 0xff) << 16; - - *buffer++ = a | r | g | b; - } -} - -static void -fetch_scanline_c4 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - const pixman_indexed_t * indexed = image->bits.indexed; - int i; - - for (i = 0; i < width; ++i) - { - uint32_t p = FETCH_4 (image, bits, i + x); - - *buffer++ = indexed->rgba[p]; - } -} - -static void -fetch_scanline_a1 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - int i; - - for (i = 0; i < width; ++i) - { - uint32_t p = READ (image, bits + ((i + x) >> 5)); - uint32_t a; - -#ifdef WORDS_BIGENDIAN - a = p >> (0x1f - ((i + x) & 0x1f)); -#else - a = p >> ((i + x) & 0x1f); -#endif - a = a & 1; - a |= a << 1; - a |= a << 2; - a |= a << 4; - - *buffer++ = a << 24; - } -} - -static void -fetch_scanline_g1 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; - const pixman_indexed_t * indexed = image->bits.indexed; - int i; - - for (i = 0; i < width; ++i) - { - uint32_t p = READ (image, bits + ((i + x) >> 5)); - uint32_t a; - -#ifdef WORDS_BIGENDIAN - a = p >> (0x1f - ((i + x) & 0x1f)); -#else - a = p >> ((i + x) & 0x1f); -#endif - a = a & 1; - - *buffer++ = indexed->rgba[a]; - } -} - -static void -fetch_scanline_yuy2 (pixman_image_t *image, - int x, - int line, - int width, - uint32_t * buffer, - const uint32_t *mask) -{ - const uint32_t *bits = image->bits.bits + image->bits.rowstride * line; - int i; - - for (i = 0; i < width; i++) - { - int16_t y, u, v; - int32_t r, g, b; - - y = ((uint8_t *) bits)[(x + i) << 1] - 16; - u = ((uint8_t *) bits)[(((x + i) << 1) & - 4) + 1] - 128; - v = ((uint8_t *) bits)[(((x + i) << 1) & - 4) + 3] - 128; - - /* R = 1.164(Y - 16) + 1.596(V - 128) */ - r = 0x012b27 * y + 0x019a2e * v; - /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */ - g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u; - /* B = 1.164(Y - 16) + 2.018(U - 128) */ - b = 0x012b27 * y + 0x0206a2 * u; - - *buffer++ = 0xff000000 | - (r >= 0 ? r < 0x1000000 ? r & 0xff0000 : 0xff0000 : 0) | - (g >= 0 ? g < 0x1000000 ? (g >> 8) & 0x00ff00 : 0x00ff00 : 0) | - (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0); - } -} - -static void -fetch_scanline_yv12 (pixman_image_t *image, - int x, - int line, - int width, - uint32_t * buffer, - const uint32_t *mask) -{ - YV12_SETUP (image); - uint8_t *y_line = YV12_Y (line); - uint8_t *u_line = YV12_U (line); - uint8_t *v_line = YV12_V (line); - int i; - - for (i = 0; i < width; i++) - { - int16_t y, u, v; - int32_t r, g, b; - - y = y_line[x + i] - 16; - u = u_line[(x + i) >> 1] - 128; - v = v_line[(x + i) >> 1] - 128; - - /* R = 1.164(Y - 16) + 1.596(V - 128) */ - r = 0x012b27 * y + 0x019a2e * v; - /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */ - g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u; - /* B = 1.164(Y - 16) + 2.018(U - 128) */ - b = 0x012b27 * y + 0x0206a2 * u; - - *buffer++ = 0xff000000 | - (r >= 0 ? r < 0x1000000 ? r & 0xff0000 : 0xff0000 : 0) | - (g >= 0 ? g < 0x1000000 ? (g >> 8) & 0x00ff00 : 0x00ff00 : 0) | - (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0); - } -} - -/**************************** Pixel wise fetching *****************************/ - -/* Despite the type, expects a uint64_t buffer */ -static uint64_t -fetch_pixel_a2r10g10b10 (bits_image_t *image, - int offset, - int line) -{ - uint32_t *bits = image->bits + line * image->rowstride; - uint32_t p = READ (image, bits + offset); - uint64_t a = p >> 30; - uint64_t r = (p >> 20) & 0x3ff; - uint64_t g = (p >> 10) & 0x3ff; - uint64_t b = p & 0x3ff; - - r = r << 6 | r >> 4; - g = g << 6 | g >> 4; - b = b << 6 | b >> 4; - - a <<= 14; - a |= a >> 2; - a |= a >> 4; - a |= a >> 8; - - return a << 48 | r << 32 | g << 16 | b; -} - -/* Despite the type, this function expects a uint64_t buffer */ -static uint64_t -fetch_pixel_x2r10g10b10 (bits_image_t *image, - int offset, - int line) -{ - uint32_t *bits = image->bits + line * image->rowstride; - uint32_t p = READ (image, bits + offset); - uint64_t r = (p >> 20) & 0x3ff; - uint64_t g = (p >> 10) & 0x3ff; - uint64_t b = p & 0x3ff; - - r = r << 6 | r >> 4; - g = g << 6 | g >> 4; - b = b << 6 | b >> 4; - - return 0xffffULL << 48 | r << 32 | g << 16 | b; -} - -/* Despite the type, expects a uint64_t buffer */ -static uint64_t -fetch_pixel_a2b10g10r10 (bits_image_t *image, - int offset, - int line) -{ - uint32_t *bits = image->bits + line * image->rowstride; - uint32_t p = READ (image, bits + offset); - uint64_t a = p >> 30; - uint64_t b = (p >> 20) & 0x3ff; - uint64_t g = (p >> 10) & 0x3ff; - uint64_t r = p & 0x3ff; - - r = r << 6 | r >> 4; - g = g << 6 | g >> 4; - b = b << 6 | b >> 4; - - a <<= 14; - a |= a >> 2; - a |= a >> 4; - a |= a >> 8; - - return a << 48 | r << 32 | g << 16 | b; -} - -/* Despite the type, this function expects a uint64_t buffer */ -static uint64_t -fetch_pixel_x2b10g10r10 (bits_image_t *image, - int offset, - int line) -{ - uint32_t *bits = image->bits + line * image->rowstride; - uint32_t p = READ (image, bits + offset); - uint64_t b = (p >> 20) & 0x3ff; - uint64_t g = (p >> 10) & 0x3ff; - uint64_t r = p & 0x3ff; - - r = r << 6 | r >> 4; - g = g << 6 | g >> 4; - b = b << 6 | b >> 4; - - return 0xffffULL << 48 | r << 32 | g << 16 | b; -} - -static uint32_t -fetch_pixel_a8r8g8b8 (bits_image_t *image, - int offset, - int line) -{ - uint32_t *bits = image->bits + line * image->rowstride; - return READ (image, (uint32_t *)bits + offset); -} - -static uint32_t -fetch_pixel_x8r8g8b8 (bits_image_t *image, - int offset, - int line) -{ - uint32_t *bits = image->bits + line * image->rowstride; - - return READ (image, (uint32_t *)bits + offset) | 0xff000000; -} - -static uint32_t -fetch_pixel_a8b8g8r8 (bits_image_t *image, - int offset, - int line) -{ - uint32_t *bits = image->bits + line * image->rowstride; - uint32_t pixel = READ (image, (uint32_t *)bits + offset); - - return ((pixel & 0xff000000) | - ((pixel >> 16) & 0xff) | - (pixel & 0x0000ff00) | - ((pixel & 0xff) << 16)); -} - -static uint32_t -fetch_pixel_x8b8g8r8 (bits_image_t *image, - int offset, - int line) -{ - uint32_t *bits = image->bits + line * image->rowstride; - uint32_t pixel = READ (image, (uint32_t *)bits + offset); - - return ((0xff000000) | - ((pixel >> 16) & 0xff) | - (pixel & 0x0000ff00) | - ((pixel & 0xff) << 16)); -} - -static uint32_t -fetch_pixel_b8g8r8a8 (bits_image_t *image, - int offset, - int line) -{ - uint32_t *bits = image->bits + line * image->rowstride; - uint32_t pixel = READ (image, (uint32_t *)bits + offset); - - return ((pixel & 0xff000000) >> 24 | - (pixel & 0x00ff0000) >> 8 | - (pixel & 0x0000ff00) << 8 | - (pixel & 0x000000ff) << 24); -} - -static uint32_t -fetch_pixel_b8g8r8x8 (bits_image_t *image, - int offset, - int line) -{ - uint32_t *bits = image->bits + line * image->rowstride; - uint32_t pixel = READ (image, (uint32_t *)bits + offset); - - return ((0xff000000) | - (pixel & 0xff000000) >> 24 | - (pixel & 0x00ff0000) >> 8 | - (pixel & 0x0000ff00) << 8); -} - -static uint32_t -fetch_pixel_x14r6g6b6 (bits_image_t *image, - int offset, - int line) -{ - uint32_t *bits = image->bits + line * image->rowstride; - uint32_t pixel = READ (image, (uint32_t *) bits + offset); - uint32_t r, g, b; - - r = ((pixel & 0x3f000) << 6) | ((pixel & 0x30000)); - g = ((pixel & 0x00fc0) << 4) | ((pixel & 0x00c00) >> 2); - b = ((pixel & 0x0003f) << 2) | ((pixel & 0x00030) >> 4); - - return 0xff000000 | r | g | b; -} - -static uint32_t -fetch_pixel_r8g8b8 (bits_image_t *image, - int offset, - int line) -{ - uint32_t *bits = image->bits + line * image->rowstride; - uint8_t *pixel = ((uint8_t *) bits) + (offset * 3); - -#ifdef WORDS_BIGENDIAN - return (0xff000000 | - (READ (image, pixel + 0) << 16) | - (READ (image, pixel + 1) << 8) | - (READ (image, pixel + 2))); -#else - return (0xff000000 | - (READ (image, pixel + 2) << 16) | - (READ (image, pixel + 1) << 8) | - (READ (image, pixel + 0))); -#endif -} - -static uint32_t -fetch_pixel_b8g8r8 (bits_image_t *image, - int offset, - int line) -{ - uint32_t *bits = image->bits + line * image->rowstride; - uint8_t *pixel = ((uint8_t *) bits) + (offset * 3); -#ifdef WORDS_BIGENDIAN - return (0xff000000 | - (READ (image, pixel + 2) << 16) | - (READ (image, pixel + 1) << 8) | - (READ (image, pixel + 0))); -#else - return (0xff000000 | - (READ (image, pixel + 0) << 16) | - (READ (image, pixel + 1) << 8) | - (READ (image, pixel + 2))); -#endif -} - -static uint32_t -fetch_pixel_r5g6b5 (bits_image_t *image, - int offset, - int line) -{ - uint32_t *bits = image->bits + line * image->rowstride; - uint32_t pixel = READ (image, (uint16_t *) bits + offset); - uint32_t r, g, b; - - r = ((pixel & 0xf800) | ((pixel & 0xe000) >> 5)) << 8; - g = ((pixel & 0x07e0) | ((pixel & 0x0600) >> 6)) << 5; - b = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) >> 2; - - return (0xff000000 | r | g | b); -} - -static uint32_t -fetch_pixel_b5g6r5 (bits_image_t *image, - int offset, - int line) -{ - uint32_t r, g, b; - uint32_t *bits = image->bits + line * image->rowstride; - uint32_t pixel = READ (image, (uint16_t *) bits + offset); - - b = ((pixel & 0xf800) | ((pixel & 0xe000) >> 5)) >> 8; - g = ((pixel & 0x07e0) | ((pixel & 0x0600) >> 6)) << 5; - r = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) << 14; - - return (0xff000000 | r | g | b); -} - -static uint32_t -fetch_pixel_a1r5g5b5 (bits_image_t *image, - int offset, - int line) -{ - uint32_t *bits = image->bits + line * image->rowstride; - uint32_t pixel = READ (image, (uint16_t *) bits + offset); - uint32_t a, r, g, b; - - a = (uint32_t) ((uint8_t) (0 - ((pixel & 0x8000) >> 15))) << 24; - r = ((pixel & 0x7c00) | ((pixel & 0x7000) >> 5)) << 9; - g = ((pixel & 0x03e0) | ((pixel & 0x0380) >> 5)) << 6; - b = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) >> 2; - - return (a | r | g | b); -} - -static uint32_t -fetch_pixel_x1r5g5b5 (bits_image_t *image, - int offset, - int line) -{ - uint32_t *bits = image->bits + line * image->rowstride; - uint32_t pixel = READ (image, (uint16_t *) bits + offset); - uint32_t r, g, b; - - r = ((pixel & 0x7c00) | ((pixel & 0x7000) >> 5)) << 9; - g = ((pixel & 0x03e0) | ((pixel & 0x0380) >> 5)) << 6; - b = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) >> 2; - - return (0xff000000 | r | g | b); -} - -static uint32_t -fetch_pixel_a1b5g5r5 (bits_image_t *image, - int offset, - int line) -{ - uint32_t *bits = image->bits + line * image->rowstride; - uint32_t pixel = READ (image, (uint16_t *) bits + offset); - uint32_t a, r, g, b; - - a = (uint32_t) ((uint8_t) (0 - ((pixel & 0x8000) >> 15))) << 24; - b = ((pixel & 0x7c00) | ((pixel & 0x7000) >> 5)) >> 7; - g = ((pixel & 0x03e0) | ((pixel & 0x0380) >> 5)) << 6; - r = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) << 14; - - return (a | r | g | b); -} - -static uint32_t -fetch_pixel_x1b5g5r5 (bits_image_t *image, - int offset, - int line) -{ - uint32_t *bits = image->bits + line * image->rowstride; - uint32_t pixel = READ (image, (uint16_t *) bits + offset); - uint32_t r, g, b; - - b = ((pixel & 0x7c00) | ((pixel & 0x7000) >> 5)) >> 7; - g = ((pixel & 0x03e0) | ((pixel & 0x0380) >> 5)) << 6; - r = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) << 14; - - return (0xff000000 | r | g | b); -} - -static uint32_t -fetch_pixel_a4r4g4b4 (bits_image_t *image, - int offset, - int line) -{ - uint32_t *bits = image->bits + line * image->rowstride; - uint32_t pixel = READ (image, (uint16_t *) bits + offset); - uint32_t a, r, g, b; - - a = ((pixel & 0xf000) | ((pixel & 0xf000) >> 4)) << 16; - r = ((pixel & 0x0f00) | ((pixel & 0x0f00) >> 4)) << 12; - g = ((pixel & 0x00f0) | ((pixel & 0x00f0) >> 4)) << 8; - b = ((pixel & 0x000f) | ((pixel & 0x000f) << 4)); - - return (a | r | g | b); -} - -static uint32_t -fetch_pixel_x4r4g4b4 (bits_image_t *image, - int offset, - int line) -{ - uint32_t *bits = image->bits + line * image->rowstride; - uint32_t pixel = READ (image, (uint16_t *) bits + offset); - uint32_t r, g, b; - - r = ((pixel & 0x0f00) | ((pixel & 0x0f00) >> 4)) << 12; - g = ((pixel & 0x00f0) | ((pixel & 0x00f0) >> 4)) << 8; - b = ((pixel & 0x000f) | ((pixel & 0x000f) << 4)); - - return (0xff000000 | r | g | b); -} - -static uint32_t -fetch_pixel_a4b4g4r4 (bits_image_t *image, - int offset, - int line) -{ - uint32_t *bits = image->bits + line * image->rowstride; - uint32_t pixel = READ (image, (uint16_t *) bits + offset); - uint32_t a, r, g, b; - - a = ((pixel & 0xf000) | ((pixel & 0xf000) >> 4)) << 16; - b = ((pixel & 0x0f00) | ((pixel & 0x0f00) >> 4)) >> 4; - g = ((pixel & 0x00f0) | ((pixel & 0x00f0) >> 4)) << 8; - r = ((pixel & 0x000f) | ((pixel & 0x000f) << 4)) << 16; - - return (a | r | g | b); -} - -static uint32_t -fetch_pixel_x4b4g4r4 (bits_image_t *image, - int offset, - int line) -{ - uint32_t *bits = image->bits + line * image->rowstride; - uint32_t pixel = READ (image, (uint16_t *) bits + offset); - uint32_t r, g, b; - - b = ((pixel & 0x0f00) | ((pixel & 0x0f00) >> 4)) >> 4; - g = ((pixel & 0x00f0) | ((pixel & 0x00f0) >> 4)) << 8; - r = ((pixel & 0x000f) | ((pixel & 0x000f) << 4)) << 16; - - return (0xff000000 | r | g | b); -} - -static uint32_t -fetch_pixel_a8 (bits_image_t *image, - int offset, - int line) -{ - uint32_t *bits = image->bits + line * image->rowstride; - uint32_t pixel = READ (image, (uint8_t *) bits + offset); - - return pixel << 24; -} - -static uint32_t -fetch_pixel_r3g3b2 (bits_image_t *image, - int offset, - int line) -{ - uint32_t *bits = image->bits + line * image->rowstride; - uint32_t pixel = READ (image, (uint8_t *) bits + offset); - uint32_t r, g, b; - - r = ((pixel & 0xe0) | - ((pixel & 0xe0) >> 3) | - ((pixel & 0xc0) >> 6)) << 16; - - g = ((pixel & 0x1c) | - ((pixel & 0x18) >> 3) | - ((pixel & 0x1c) << 3)) << 8; - - b = (((pixel & 0x03) ) | - ((pixel & 0x03) << 2) | - ((pixel & 0x03) << 4) | - ((pixel & 0x03) << 6)); - - return (0xff000000 | r | g | b); -} - -static uint32_t -fetch_pixel_b2g3r3 (bits_image_t *image, - int offset, - int line) -{ - uint32_t *bits = image->bits + line * image->rowstride; - uint32_t p = READ (image, (uint8_t *) bits + offset); - uint32_t r, g, b; - - b = p & 0xc0; - b |= b >> 2; - b |= b >> 4; - b &= 0xff; - - g = (p & 0x38) << 10; - g |= g >> 3; - g |= g >> 6; - g &= 0xff00; - - r = (p & 0x7) << 21; - r |= r >> 3; - r |= r >> 6; - r &= 0xff0000; - - return 0xff000000 | r | g | b; -} - -static uint32_t -fetch_pixel_a2r2g2b2 (bits_image_t *image, - int offset, - int line) -{ - uint32_t *bits = image->bits + line * image->rowstride; - uint32_t pixel = READ (image, (uint8_t *) bits + offset); - uint32_t a, r, g, b; - - a = ((pixel & 0xc0) * 0x55) << 18; - r = ((pixel & 0x30) * 0x55) << 12; - g = ((pixel & 0x0c) * 0x55) << 6; - b = ((pixel & 0x03) * 0x55); - - return a | r | g | b; -} - -static uint32_t -fetch_pixel_a2b2g2r2 (bits_image_t *image, - int offset, - int line) -{ - uint32_t *bits = image->bits + line * image->rowstride; - uint32_t pixel = READ (image, (uint8_t *) bits + offset); - uint32_t a, r, g, b; - - a = ((pixel & 0xc0) * 0x55) << 18; - b = ((pixel & 0x30) * 0x55) >> 4; - g = ((pixel & 0x0c) * 0x55) << 6; - r = ((pixel & 0x03) * 0x55) << 16; - - return a | r | g | b; -} - -static uint32_t -fetch_pixel_c8 (bits_image_t *image, - int offset, - int line) -{ - uint32_t *bits = image->bits + line * image->rowstride; - uint32_t pixel = READ (image, (uint8_t *) bits + offset); - const pixman_indexed_t * indexed = image->indexed; - - return indexed->rgba[pixel]; -} - -static uint32_t -fetch_pixel_x4a4 (bits_image_t *image, - int offset, - int line) -{ - uint32_t *bits = image->bits + line * image->rowstride; - uint32_t pixel = READ (image, (uint8_t *) bits + offset); - - return ((pixel & 0xf) | ((pixel & 0xf) << 4)) << 24; -} - -static uint32_t -fetch_pixel_a4 (bits_image_t *image, - int offset, - int line) -{ - uint32_t *bits = image->bits + line * image->rowstride; - uint32_t pixel = FETCH_4 (image, bits, offset); - - pixel |= pixel << 4; - return pixel << 24; -} - -static uint32_t -fetch_pixel_r1g2b1 (bits_image_t *image, - int offset, - int line) -{ - uint32_t *bits = image->bits + line * image->rowstride; - uint32_t pixel = FETCH_4 (image, bits, offset); - uint32_t r, g, b; - - r = ((pixel & 0x8) * 0xff) << 13; - g = ((pixel & 0x6) * 0x55) << 7; - b = ((pixel & 0x1) * 0xff); - - return 0xff000000 | r | g | b; -} - -static uint32_t -fetch_pixel_b1g2r1 (bits_image_t *image, - int offset, - int line) -{ - uint32_t *bits = image->bits + line * image->rowstride; - uint32_t pixel = FETCH_4 (image, bits, offset); - uint32_t r, g, b; - - b = ((pixel & 0x8) * 0xff) >> 3; - g = ((pixel & 0x6) * 0x55) << 7; - r = ((pixel & 0x1) * 0xff) << 16; - - return 0xff000000 | r | g | b; -} - -static uint32_t -fetch_pixel_a1r1g1b1 (bits_image_t *image, - int offset, - int line) -{ - uint32_t *bits = image->bits + line * image->rowstride; - uint32_t pixel = FETCH_4 (image, bits, offset); - uint32_t a, r, g, b; - - a = ((pixel & 0x8) * 0xff) << 21; - r = ((pixel & 0x4) * 0xff) << 14; - g = ((pixel & 0x2) * 0xff) << 7; - b = ((pixel & 0x1) * 0xff); - - return a | r | g | b; -} - -static uint32_t -fetch_pixel_a1b1g1r1 (bits_image_t *image, - int offset, - int line) -{ - uint32_t *bits = image->bits + line * image->rowstride; - uint32_t pixel = FETCH_4 (image, bits, offset); - uint32_t a, r, g, b; - - a = ((pixel & 0x8) * 0xff) << 21; - b = ((pixel & 0x4) * 0xff) >> 2; - g = ((pixel & 0x2) * 0xff) << 7; - r = ((pixel & 0x1) * 0xff) << 16; - - return a | r | g | b; -} - -static uint32_t -fetch_pixel_c4 (bits_image_t *image, - int offset, - int line) -{ - uint32_t *bits = image->bits + line * image->rowstride; - uint32_t pixel = FETCH_4 (image, bits, offset); - const pixman_indexed_t * indexed = image->indexed; - - return indexed->rgba[pixel]; -} - -static uint32_t -fetch_pixel_a1 (bits_image_t *image, - int offset, - int line) -{ - uint32_t *bits = image->bits + line * image->rowstride; - uint32_t pixel = READ (image, bits + (offset >> 5)); - uint32_t a; - -#ifdef WORDS_BIGENDIAN - a = pixel >> (0x1f - (offset & 0x1f)); -#else - a = pixel >> (offset & 0x1f); -#endif - a = a & 1; - a |= a << 1; - a |= a << 2; - a |= a << 4; - - return a << 24; -} - -static uint32_t -fetch_pixel_g1 (bits_image_t *image, - int offset, - int line) -{ - uint32_t *bits = image->bits + line * image->rowstride; - uint32_t pixel = READ (image, bits + (offset >> 5)); - const pixman_indexed_t * indexed = image->indexed; - uint32_t a; - -#ifdef WORDS_BIGENDIAN - a = pixel >> (0x1f - (offset & 0x1f)); -#else - a = pixel >> (offset & 0x1f); -#endif - a = a & 1; - - return indexed->rgba[a]; -} - -static uint32_t -fetch_pixel_yuy2 (bits_image_t *image, - int offset, - int line) -{ - const uint32_t *bits = image->bits + image->rowstride * line; - - int16_t y, u, v; - int32_t r, g, b; - - y = ((uint8_t *) bits)[offset << 1] - 16; - u = ((uint8_t *) bits)[((offset << 1) & - 4) + 1] - 128; - v = ((uint8_t *) bits)[((offset << 1) & - 4) + 3] - 128; - - /* R = 1.164(Y - 16) + 1.596(V - 128) */ - r = 0x012b27 * y + 0x019a2e * v; - - /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */ - g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u; - - /* B = 1.164(Y - 16) + 2.018(U - 128) */ - b = 0x012b27 * y + 0x0206a2 * u; - - return 0xff000000 | - (r >= 0 ? r < 0x1000000 ? r & 0xff0000 : 0xff0000 : 0) | - (g >= 0 ? g < 0x1000000 ? (g >> 8) & 0x00ff00 : 0x00ff00 : 0) | - (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0); -} - -static uint32_t -fetch_pixel_yv12 (bits_image_t *image, - int offset, - int line) -{ - YV12_SETUP (image); - int16_t y = YV12_Y (line)[offset] - 16; - int16_t u = YV12_U (line)[offset >> 1] - 128; - int16_t v = YV12_V (line)[offset >> 1] - 128; - int32_t r, g, b; - - /* R = 1.164(Y - 16) + 1.596(V - 128) */ - r = 0x012b27 * y + 0x019a2e * v; - - /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */ - g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u; - - /* B = 1.164(Y - 16) + 2.018(U - 128) */ - b = 0x012b27 * y + 0x0206a2 * u; - - return 0xff000000 | - (r >= 0 ? r < 0x1000000 ? r & 0xff0000 : 0xff0000 : 0) | - (g >= 0 ? g < 0x1000000 ? (g >> 8) & 0x00ff00 : 0x00ff00 : 0) | - (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0); -} - -/*********************************** Store ************************************/ - -#define SPLIT_A(v) \ - uint32_t a = ((v) >> 24), \ - r = ((v) >> 16) & 0xff, \ - g = ((v) >> 8) & 0xff, \ - b = (v) & 0xff - -#define SPLIT(v) \ - uint32_t r = ((v) >> 16) & 0xff, \ - g = ((v) >> 8) & 0xff, \ - b = (v) & 0xff - -static void -store_scanline_a2r10g10b10 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *v) -{ - uint32_t *bits = image->bits + image->rowstride * y; - uint32_t *pixel = bits + x; - uint64_t *values = (uint64_t *)v; - int i; - - for (i = 0; i < width; ++i) - { - WRITE (image, pixel++, - ((values[i] >> 32) & 0xc0000000) | - ((values[i] >> 18) & 0x3ff00000) | - ((values[i] >> 12) & 0xffc00) | - ((values[i] >> 6) & 0x3ff)); - } -} - -static void -store_scanline_x2r10g10b10 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *v) -{ - uint32_t *bits = image->bits + image->rowstride * y; - uint64_t *values = (uint64_t *)v; - uint32_t *pixel = bits + x; - int i; - - for (i = 0; i < width; ++i) - { - WRITE (image, pixel++, - ((values[i] >> 18) & 0x3ff00000) | - ((values[i] >> 12) & 0xffc00) | - ((values[i] >> 6) & 0x3ff)); - } -} - -static void -store_scanline_a2b10g10r10 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *v) -{ - uint32_t *bits = image->bits + image->rowstride * y; - uint32_t *pixel = bits + x; - uint64_t *values = (uint64_t *)v; - int i; - - for (i = 0; i < width; ++i) - { - WRITE (image, pixel++, - ((values[i] >> 32) & 0xc0000000) | - ((values[i] >> 38) & 0x3ff) | - ((values[i] >> 12) & 0xffc00) | - ((values[i] << 14) & 0x3ff00000)); - } -} - -static void -store_scanline_x2b10g10r10 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *v) -{ - uint32_t *bits = image->bits + image->rowstride * y; - uint64_t *values = (uint64_t *)v; - uint32_t *pixel = bits + x; - int i; - - for (i = 0; i < width; ++i) - { - WRITE (image, pixel++, - ((values[i] >> 38) & 0x3ff) | - ((values[i] >> 12) & 0xffc00) | - ((values[i] << 14) & 0x3ff00000)); - } -} - -static void -store_scanline_a8r8g8b8 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *values) -{ - uint32_t *bits = image->bits + image->rowstride * y; - - MEMCPY_WRAPPED (image, ((uint32_t *)bits) + x, values, - width * sizeof(uint32_t)); -} - -static void -store_scanline_x8r8g8b8 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *values) -{ - uint32_t *bits = image->bits + image->rowstride * y; - uint32_t *pixel = (uint32_t *)bits + x; - int i; - - for (i = 0; i < width; ++i) - WRITE (image, pixel++, values[i] & 0xffffff); -} - -static void -store_scanline_a8b8g8r8 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *values) -{ - uint32_t *bits = image->bits + image->rowstride * y; - uint32_t *pixel = (uint32_t *)bits + x; - int i; - - for (i = 0; i < width; ++i) - { - WRITE (image, pixel++, - (values[i] & 0xff00ff00) | - ((values[i] >> 16) & 0xff) | - ((values[i] & 0xff) << 16)); - } -} - -static void -store_scanline_x8b8g8r8 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *values) -{ - uint32_t *bits = image->bits + image->rowstride * y; - uint32_t *pixel = (uint32_t *)bits + x; - int i; - - for (i = 0; i < width; ++i) - { - WRITE (image, pixel++, - (values[i] & 0x0000ff00) | - ((values[i] >> 16) & 0xff) | - ((values[i] & 0xff) << 16)); - } -} - -static void -store_scanline_b8g8r8a8 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *values) -{ - uint32_t *bits = image->bits + image->rowstride * y; - uint32_t *pixel = (uint32_t *)bits + x; - int i; - - for (i = 0; i < width; ++i) - { - WRITE (image, pixel++, - ((values[i] >> 24) & 0x000000ff) | - ((values[i] >> 8) & 0x0000ff00) | - ((values[i] << 8) & 0x00ff0000) | - ((values[i] << 24) & 0xff000000)); - } -} - -static void -store_scanline_b8g8r8x8 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *values) -{ - uint32_t *bits = image->bits + image->rowstride * y; - uint32_t *pixel = (uint32_t *)bits + x; - int i; - - for (i = 0; i < width; ++i) - { - WRITE (image, pixel++, - ((values[i] >> 8) & 0x0000ff00) | - ((values[i] << 8) & 0x00ff0000) | - ((values[i] << 24) & 0xff000000)); - } -} - -static void -store_scanline_x14r6g6b6 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *values) -{ - uint32_t *bits = image->bits + image->rowstride * y; - uint32_t *pixel = ((uint32_t *) bits) + x; - int i; - - for (i = 0; i < width; ++i) - { - uint32_t s = values[i]; - uint32_t r, g, b; - - r = (s & 0xfc0000) >> 6; - g = (s & 0x00fc00) >> 4; - b = (s & 0x0000fc) >> 2; - - WRITE (image, pixel++, r | g | b); - } -} - -static void -store_scanline_r8g8b8 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *values) -{ - uint32_t *bits = image->bits + image->rowstride * y; - uint8_t *pixel = ((uint8_t *) bits) + 3 * x; - int i; - - for (i = 0; i < width; ++i) - { - uint32_t val = values[i]; - -#ifdef WORDS_BIGENDIAN - WRITE (image, pixel++, (val & 0x00ff0000) >> 16); - WRITE (image, pixel++, (val & 0x0000ff00) >> 8); - WRITE (image, pixel++, (val & 0x000000ff) >> 0); -#else - WRITE (image, pixel++, (val & 0x000000ff) >> 0); - WRITE (image, pixel++, (val & 0x0000ff00) >> 8); - WRITE (image, pixel++, (val & 0x00ff0000) >> 16); -#endif - } -} - -static void -store_scanline_b8g8r8 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *values) -{ - uint32_t *bits = image->bits + image->rowstride * y; - uint8_t *pixel = ((uint8_t *) bits) + 3 * x; - int i; - - for (i = 0; i < width; ++i) - { - uint32_t val = values[i]; - -#ifdef WORDS_BIGENDIAN - WRITE (image, pixel++, (val & 0x000000ff) >> 0); - WRITE (image, pixel++, (val & 0x0000ff00) >> 8); - WRITE (image, pixel++, (val & 0x00ff0000) >> 16); -#else - WRITE (image, pixel++, (val & 0x00ff0000) >> 16); - WRITE (image, pixel++, (val & 0x0000ff00) >> 8); - WRITE (image, pixel++, (val & 0x000000ff) >> 0); -#endif - } -} - -static void -store_scanline_r5g6b5 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *values) -{ - uint32_t *bits = image->bits + image->rowstride * y; - uint16_t *pixel = ((uint16_t *) bits) + x; - int i; - - for (i = 0; i < width; ++i) - { - uint32_t s = values[i]; - - WRITE (image, pixel++, - ((s >> 3) & 0x001f) | - ((s >> 5) & 0x07e0) | - ((s >> 8) & 0xf800)); - } -} - -static void -store_scanline_b5g6r5 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *values) -{ - uint32_t *bits = image->bits + image->rowstride * y; - uint16_t *pixel = ((uint16_t *) bits) + x; - int i; - - for (i = 0; i < width; ++i) - { - SPLIT (values[i]); - - WRITE (image, pixel++, - ((b << 8) & 0xf800) | - ((g << 3) & 0x07e0) | - ((r >> 3) )); - } -} - -static void -store_scanline_a1r5g5b5 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *values) -{ - uint32_t *bits = image->bits + image->rowstride * y; - uint16_t *pixel = ((uint16_t *) bits) + x; - int i; - - for (i = 0; i < width; ++i) - { - SPLIT_A (values[i]); - - WRITE (image, pixel++, - ((a << 8) & 0x8000) | - ((r << 7) & 0x7c00) | - ((g << 2) & 0x03e0) | - ((b >> 3) )); - } -} - -static void -store_scanline_x1r5g5b5 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *values) -{ - uint32_t *bits = image->bits + image->rowstride * y; - uint16_t *pixel = ((uint16_t *) bits) + x; - int i; - - for (i = 0; i < width; ++i) - { - SPLIT (values[i]); - - WRITE (image, pixel++, - ((r << 7) & 0x7c00) | - ((g << 2) & 0x03e0) | - ((b >> 3) )); - } -} - -static void -store_scanline_a1b5g5r5 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *values) -{ - uint32_t *bits = image->bits + image->rowstride * y; - uint16_t *pixel = ((uint16_t *) bits) + x; - int i; - - for (i = 0; i < width; ++i) - { - SPLIT_A (values[i]); - - WRITE (image, pixel++, - ((a << 8) & 0x8000) | - ((b << 7) & 0x7c00) | - ((g << 2) & 0x03e0) | - ((r >> 3) )); - } -} - -static void -store_scanline_x1b5g5r5 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *values) -{ - uint32_t *bits = image->bits + image->rowstride * y; - uint16_t *pixel = ((uint16_t *) bits) + x; - int i; - - for (i = 0; i < width; ++i) - { - SPLIT (values[i]); - - WRITE (image, pixel++, ((b << 7) & 0x7c00) | - ((g << 2) & 0x03e0) | - ((r >> 3) )); - } -} - -static void -store_scanline_a4r4g4b4 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *values) -{ - uint32_t *bits = image->bits + image->rowstride * y; - uint16_t *pixel = ((uint16_t *) bits) + x; - int i; - - for (i = 0; i < width; ++i) - { - SPLIT_A (values[i]); - - WRITE (image, pixel++, - ((a << 8) & 0xf000) | - ((r << 4) & 0x0f00) | - ((g ) & 0x00f0) | - ((b >> 4) )); - } -} - -static void -store_scanline_x4r4g4b4 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *values) -{ - uint32_t *bits = image->bits + image->rowstride * y; - uint16_t *pixel = ((uint16_t *) bits) + x; - int i; - - for (i = 0; i < width; ++i) - { - SPLIT (values[i]); - - WRITE (image, pixel++, - ((r << 4) & 0x0f00) | - ((g ) & 0x00f0) | - ((b >> 4) )); - } -} - -static void -store_scanline_a4b4g4r4 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *values) -{ - uint32_t *bits = image->bits + image->rowstride * y; - uint16_t *pixel = ((uint16_t *) bits) + x; - int i; - - for (i = 0; i < width; ++i) - { - SPLIT_A (values[i]); - WRITE (image, pixel++, ((a << 8) & 0xf000) | - ((b << 4) & 0x0f00) | - ((g ) & 0x00f0) | - ((r >> 4) )); - } -} - -static void -store_scanline_x4b4g4r4 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *values) -{ - uint32_t *bits = image->bits + image->rowstride * y; - uint16_t *pixel = ((uint16_t *) bits) + x; - int i; - - for (i = 0; i < width; ++i) - { - SPLIT (values[i]); - - WRITE (image, pixel++, - ((b << 4) & 0x0f00) | - ((g ) & 0x00f0) | - ((r >> 4) )); - } -} - -static void -store_scanline_a8 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *values) -{ - uint32_t *bits = image->bits + image->rowstride * y; - uint8_t *pixel = ((uint8_t *) bits) + x; - int i; - - for (i = 0; i < width; ++i) - { - WRITE (image, pixel++, values[i] >> 24); - } -} - -static void -store_scanline_r3g3b2 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *values) -{ - uint32_t *bits = image->bits + image->rowstride * y; - uint8_t *pixel = ((uint8_t *) bits) + x; - int i; - - for (i = 0; i < width; ++i) - { - SPLIT (values[i]); - - WRITE (image, pixel++, - ((r ) & 0xe0) | - ((g >> 3) & 0x1c) | - ((b >> 6) )); - } -} - -static void -store_scanline_b2g3r3 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *values) -{ - uint32_t *bits = image->bits + image->rowstride * y; - uint8_t *pixel = ((uint8_t *) bits) + x; - int i; - - for (i = 0; i < width; ++i) - { - SPLIT (values[i]); - - WRITE (image, pixel++, - ((b ) & 0xc0) | - ((g >> 2) & 0x38) | - ((r >> 5) )); - } -} - -static void -store_scanline_a2r2g2b2 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *values) -{ - uint32_t *bits = image->bits + image->rowstride * y; - uint8_t *pixel = ((uint8_t *) bits) + x; - int i; - - for (i = 0; i < width; ++i) - { - SPLIT_A (values[i]); - - WRITE (image, pixel++, - ((a ) & 0xc0) | - ((r >> 2) & 0x30) | - ((g >> 4) & 0x0c) | - ((b >> 6) )); - } -} - -static void -store_scanline_a2b2g2r2 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *values) -{ - uint32_t *bits = image->bits + image->rowstride * y; - uint8_t *pixel = ((uint8_t *) bits) + x; - int i; - - for (i = 0; i < width; ++i) - { - SPLIT_A (values[i]); - - WRITE (image, pixel++, - ((a ) & 0xc0) | - ((b >> 2) & 0x30) | - ((g >> 4) & 0x0c) | - ((r >> 6) )); - } -} - -static void -store_scanline_c8 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *values) -{ - uint32_t *bits = image->bits + image->rowstride * y; - uint8_t *pixel = ((uint8_t *) bits) + x; - const pixman_indexed_t *indexed = image->indexed; - int i; - - for (i = 0; i < width; ++i) - WRITE (image, pixel++, RGB24_TO_ENTRY (indexed,values[i])); -} - -static void -store_scanline_g8 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *values) -{ - uint32_t *bits = image->bits + image->rowstride * y; - uint8_t *pixel = ((uint8_t *) bits) + x; - const pixman_indexed_t *indexed = image->indexed; - int i; - - for (i = 0; i < width; ++i) - WRITE (image, pixel++, RGB24_TO_ENTRY_Y (indexed,values[i])); -} - -static void -store_scanline_x4a4 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *values) -{ - uint32_t *bits = image->bits + image->rowstride * y; - uint8_t *pixel = ((uint8_t *) bits) + x; - int i; - - for (i = 0; i < width; ++i) - WRITE (image, pixel++, values[i] >> 28); -} - -#define STORE_8(img,l,o,v) (WRITE (img, (uint8_t *)(l) + ((o) >> 3), (v))) -#ifdef WORDS_BIGENDIAN - -#define STORE_4(img,l,o,v) \ - do \ - { \ - int bo = 4 * (o); \ - int v4 = (v) & 0x0f; \ - \ - STORE_8 (img, l, bo, ( \ - bo & 4 ? \ - (FETCH_8 (img, l, bo) & 0xf0) | (v4) : \ - (FETCH_8 (img, l, bo) & 0x0f) | (v4 << 4))); \ - } while (0) -#else - -#define STORE_4(img,l,o,v) \ - do \ - { \ - int bo = 4 * (o); \ - int v4 = (v) & 0x0f; \ - \ - STORE_8 (img, l, bo, ( \ - bo & 4 ? \ - (FETCH_8 (img, l, bo) & 0x0f) | (v4 << 4) : \ - (FETCH_8 (img, l, bo) & 0xf0) | (v4))); \ - } while (0) -#endif - -static void -store_scanline_a4 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *values) -{ - uint32_t *bits = image->bits + image->rowstride * y; - int i; - - for (i = 0; i < width; ++i) - STORE_4 (image, bits, i + x, values[i] >> 28); -} - -static void -store_scanline_r1g2b1 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *values) -{ - uint32_t *bits = image->bits + image->rowstride * y; - int i; - - for (i = 0; i < width; ++i) - { - uint32_t pixel; - - SPLIT (values[i]); - pixel = (((r >> 4) & 0x8) | - ((g >> 5) & 0x6) | - ((b >> 7) )); - STORE_4 (image, bits, i + x, pixel); - } -} - -static void -store_scanline_b1g2r1 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *values) -{ - uint32_t *bits = image->bits + image->rowstride * y; - int i; - - for (i = 0; i < width; ++i) - { - uint32_t pixel; - - SPLIT (values[i]); - pixel = (((b >> 4) & 0x8) | - ((g >> 5) & 0x6) | - ((r >> 7) )); - STORE_4 (image, bits, i + x, pixel); - } -} - -static void -store_scanline_a1r1g1b1 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *values) -{ - uint32_t *bits = image->bits + image->rowstride * y; - int i; - - for (i = 0; i < width; ++i) - { - uint32_t pixel; - - SPLIT_A (values[i]); - pixel = (((a >> 4) & 0x8) | - ((r >> 5) & 0x4) | - ((g >> 6) & 0x2) | - ((b >> 7) )); - - STORE_4 (image, bits, i + x, pixel); - } -} - -static void -store_scanline_a1b1g1r1 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *values) -{ - uint32_t *bits = image->bits + image->rowstride * y; - int i; - - for (i = 0; i < width; ++i) - { - uint32_t pixel; - - SPLIT_A (values[i]); - pixel = (((a >> 4) & 0x8) | - ((b >> 5) & 0x4) | - ((g >> 6) & 0x2) | - ((r >> 7) )); - - STORE_4 (image, bits, i + x, pixel); - } -} - -static void -store_scanline_c4 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *values) -{ - uint32_t *bits = image->bits + image->rowstride * y; - const pixman_indexed_t *indexed = image->indexed; - int i; - - for (i = 0; i < width; ++i) - { - uint32_t pixel; - - pixel = RGB24_TO_ENTRY (indexed, values[i]); - STORE_4 (image, bits, i + x, pixel); - } -} - -static void -store_scanline_g4 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *values) -{ - uint32_t *bits = image->bits + image->rowstride * y; - const pixman_indexed_t *indexed = image->indexed; - int i; - - for (i = 0; i < width; ++i) - { - uint32_t pixel; - - pixel = RGB24_TO_ENTRY_Y (indexed, values[i]); - STORE_4 (image, bits, i + x, pixel); - } -} - -static void -store_scanline_a1 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *values) -{ - uint32_t *bits = image->bits + image->rowstride * y; - int i; - - for (i = 0; i < width; ++i) - { - uint32_t *pixel = ((uint32_t *) bits) + ((i + x) >> 5); - uint32_t mask, v; - -#ifdef WORDS_BIGENDIAN - mask = 1 << (0x1f - ((i + x) & 0x1f)); -#else - mask = 1 << ((i + x) & 0x1f); -#endif - v = values[i] & 0x80000000 ? mask : 0; - - WRITE (image, pixel, (READ (image, pixel) & ~mask) | v); - } -} - -static void -store_scanline_g1 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *values) -{ - uint32_t *bits = image->bits + image->rowstride * y; - const pixman_indexed_t *indexed = image->indexed; - int i; - - for (i = 0; i < width; ++i) - { - uint32_t *pixel = ((uint32_t *) bits) + ((i + x) >> 5); - uint32_t mask, v; - -#ifdef WORDS_BIGENDIAN - mask = 1 << (0x1f - ((i + x) & 0x1f)); -#else - mask = 1 << ((i + x) & 0x1f); -#endif - v = RGB24_TO_ENTRY_Y (indexed, values[i]) & 0x1 ? mask : 0; - - WRITE (image, pixel, (READ (image, pixel) & ~mask) | v); - } -} - -/* - * Contracts a 64bpp image to 32bpp and then stores it using a regular 32-bit - * store proc. Despite the type, this function expects a uint64_t buffer. - */ -static void -store_scanline_generic_64 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *values) -{ - uint32_t *argb8_pixels; - - assert (image->common.type == BITS); - - argb8_pixels = pixman_malloc_ab (width, sizeof(uint32_t)); - if (!argb8_pixels) - return; - - /* Contract the scanline. We could do this in place if values weren't - * const. - */ - pixman_contract (argb8_pixels, (uint64_t *)values, width); - - image->store_scanline_32 (image, x, y, width, argb8_pixels); - - free (argb8_pixels); -} - -/* Despite the type, this function expects both buffer - * and mask to be uint64_t - */ -static void -fetch_scanline_generic_64 (pixman_image_t *image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t *mask) -{ - pixman_format_code_t format; - - /* Fetch the pixels into the first half of buffer and then expand them in - * place. - */ - image->bits.fetch_scanline_32 (image, x, y, width, buffer, NULL); - - format = image->bits.format; - if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR || - PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_GRAY) - { - /* Indexed formats are mapped to a8r8g8b8 with full - * precision, so when expanding we shouldn't correct - * for the width of the channels - */ - - format = PIXMAN_a8r8g8b8; - } - - pixman_expand ((uint64_t *)buffer, buffer, format, width); -} - -/* Despite the type, this function expects a uint64_t *buffer */ -static uint64_t -fetch_pixel_generic_64 (bits_image_t *image, - int offset, - int line) -{ - uint32_t pixel32 = image->fetch_pixel_32 (image, offset, line); - uint64_t result; - pixman_format_code_t format; - - format = image->format; - if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR || - PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_GRAY) - { - /* Indexed formats are mapped to a8r8g8b8 with full - * precision, so when expanding we shouldn't correct - * for the width of the channels - */ - - format = PIXMAN_a8r8g8b8; - } - - pixman_expand ((uint64_t *)&result, &pixel32, format, 1); - - return result; -} - -/* - * XXX: The transformed fetch path only works at 32-bpp so far. When all - * paths have wide versions, this can be removed. - * - * WARNING: This function loses precision! - */ -static uint32_t -fetch_pixel_generic_lossy_32 (bits_image_t *image, - int offset, - int line) -{ - uint64_t pixel64 = image->fetch_pixel_64 (image, offset, line); - uint32_t result; - - pixman_contract (&result, &pixel64, 1); - - return result; -} - -typedef struct -{ - pixman_format_code_t format; - fetch_scanline_t fetch_scanline_32; - fetch_scanline_t fetch_scanline_64; - fetch_pixel_32_t fetch_pixel_32; - fetch_pixel_64_t fetch_pixel_64; - store_scanline_t store_scanline_32; - store_scanline_t store_scanline_64; -} format_info_t; - -#define FORMAT_INFO(format) \ - { \ - PIXMAN_ ## format, \ - fetch_scanline_ ## format, \ - fetch_scanline_generic_64, \ - fetch_pixel_ ## format, fetch_pixel_generic_64, \ - store_scanline_ ## format, store_scanline_generic_64 \ - } - -static const format_info_t accessors[] = -{ -/* 32 bpp formats */ - FORMAT_INFO (a8r8g8b8), - FORMAT_INFO (x8r8g8b8), - FORMAT_INFO (a8b8g8r8), - FORMAT_INFO (x8b8g8r8), - FORMAT_INFO (b8g8r8a8), - FORMAT_INFO (b8g8r8x8), - FORMAT_INFO (x14r6g6b6), - -/* 24bpp formats */ - FORMAT_INFO (r8g8b8), - FORMAT_INFO (b8g8r8), - -/* 16bpp formats */ - FORMAT_INFO (r5g6b5), - FORMAT_INFO (b5g6r5), - - FORMAT_INFO (a1r5g5b5), - FORMAT_INFO (x1r5g5b5), - FORMAT_INFO (a1b5g5r5), - FORMAT_INFO (x1b5g5r5), - FORMAT_INFO (a4r4g4b4), - FORMAT_INFO (x4r4g4b4), - FORMAT_INFO (a4b4g4r4), - FORMAT_INFO (x4b4g4r4), - -/* 8bpp formats */ - FORMAT_INFO (a8), - FORMAT_INFO (r3g3b2), - FORMAT_INFO (b2g3r3), - FORMAT_INFO (a2r2g2b2), - FORMAT_INFO (a2b2g2r2), - - FORMAT_INFO (c8), - -#define fetch_scanline_g8 fetch_scanline_c8 -#define fetch_pixel_g8 fetch_pixel_c8 - FORMAT_INFO (g8), - -#define fetch_scanline_x4c4 fetch_scanline_c8 -#define fetch_pixel_x4c4 fetch_pixel_c8 -#define store_scanline_x4c4 store_scanline_c8 - FORMAT_INFO (x4c4), - -#define fetch_scanline_x4g4 fetch_scanline_c8 -#define fetch_pixel_x4g4 fetch_pixel_c8 -#define store_scanline_x4g4 store_scanline_g8 - FORMAT_INFO (x4g4), - - FORMAT_INFO (x4a4), - -/* 4bpp formats */ - FORMAT_INFO (a4), - FORMAT_INFO (r1g2b1), - FORMAT_INFO (b1g2r1), - FORMAT_INFO (a1r1g1b1), - FORMAT_INFO (a1b1g1r1), - - FORMAT_INFO (c4), - -#define fetch_scanline_g4 fetch_scanline_c4 -#define fetch_pixel_g4 fetch_pixel_c4 - FORMAT_INFO (g4), - -/* 1bpp formats */ - FORMAT_INFO (a1), - FORMAT_INFO (g1), - -/* Wide formats */ - - { PIXMAN_a2r10g10b10, - NULL, fetch_scanline_a2r10g10b10, - fetch_pixel_generic_lossy_32, fetch_pixel_a2r10g10b10, - NULL, store_scanline_a2r10g10b10 }, - - { PIXMAN_x2r10g10b10, - NULL, fetch_scanline_x2r10g10b10, - fetch_pixel_generic_lossy_32, fetch_pixel_x2r10g10b10, - NULL, store_scanline_x2r10g10b10 }, - - { PIXMAN_a2b10g10r10, - NULL, fetch_scanline_a2b10g10r10, - fetch_pixel_generic_lossy_32, fetch_pixel_a2b10g10r10, - NULL, store_scanline_a2b10g10r10 }, - - { PIXMAN_x2b10g10r10, - NULL, fetch_scanline_x2b10g10r10, - fetch_pixel_generic_lossy_32, fetch_pixel_x2b10g10r10, - NULL, store_scanline_x2b10g10r10 }, - -/* YUV formats */ - { PIXMAN_yuy2, - fetch_scanline_yuy2, fetch_scanline_generic_64, - fetch_pixel_yuy2, fetch_pixel_generic_64, - NULL, NULL }, - - { PIXMAN_yv12, - fetch_scanline_yv12, fetch_scanline_generic_64, - fetch_pixel_yv12, fetch_pixel_generic_64, - NULL, NULL }, - - { PIXMAN_null }, -}; - -static void -setup_accessors (bits_image_t *image) -{ - const format_info_t *info = accessors; - - while (info->format != PIXMAN_null) - { - if (info->format == image->format) - { - image->fetch_scanline_32 = info->fetch_scanline_32; - image->fetch_scanline_64 = info->fetch_scanline_64; - image->fetch_pixel_32 = info->fetch_pixel_32; - image->fetch_pixel_64 = info->fetch_pixel_64; - image->store_scanline_32 = info->store_scanline_32; - image->store_scanline_64 = info->store_scanline_64; - - return; - } - - info++; - } -} - -#ifndef PIXMAN_FB_ACCESSORS -void -_pixman_bits_image_setup_accessors_accessors (bits_image_t *image); - -void -_pixman_bits_image_setup_accessors (bits_image_t *image) -{ - if (image->read_func || image->write_func) - _pixman_bits_image_setup_accessors_accessors (image); - else - setup_accessors (image); -} - -#else - -void -_pixman_bits_image_setup_accessors_accessors (bits_image_t *image) -{ - setup_accessors (image); -} - -#endif +/* + * + * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc. + * 2005 Lars Knoll & Zack Rusin, Trolltech + * 2008 Aaron Plattner, NVIDIA Corporation + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include "pixman-private.h" +#include "pixman-accessor.h" + +#define CONVERT_RGB24_TO_Y15(s) \ + (((((s) >> 16) & 0xff) * 153 + \ + (((s) >> 8) & 0xff) * 301 + \ + (((s) ) & 0xff) * 58) >> 2) + +#define CONVERT_RGB24_TO_RGB15(s) \ + ((((s) >> 3) & 0x001f) | \ + (((s) >> 6) & 0x03e0) | \ + (((s) >> 9) & 0x7c00)) + +#define RGB15_TO_ENTRY(mif,rgb15) \ + ((mif)->ent[rgb15]) + +#define RGB24_TO_ENTRY(mif,rgb24) \ + RGB15_TO_ENTRY (mif,CONVERT_RGB24_TO_RGB15 (rgb24)) + +#define RGB24_TO_ENTRY_Y(mif,rgb24) \ + ((mif)->ent[CONVERT_RGB24_TO_Y15 (rgb24)]) + +/* + * YV12 setup and access macros + */ + +#define YV12_SETUP(image) \ + bits_image_t *__bits_image = (bits_image_t *)image; \ + uint32_t *bits = __bits_image->bits; \ + int stride = __bits_image->rowstride; \ + int offset0 = stride < 0 ? \ + ((-stride) >> 1) * ((__bits_image->height - 1) >> 1) - stride : \ + stride * __bits_image->height; \ + int offset1 = stride < 0 ? \ + offset0 + ((-stride) >> 1) * ((__bits_image->height) >> 1) : \ + offset0 + (offset0 >> 2) + +/* Note no trailing semicolon on the above macro; if it's there, then + * the typical usage of YV12_SETUP(image); will have an extra trailing ; + * that some compilers will interpret as a statement -- and then any further + * variable declarations will cause an error. + */ + +#define YV12_Y(line) \ + ((uint8_t *) ((bits) + (stride) * (line))) + +#define YV12_U(line) \ + ((uint8_t *) ((bits) + offset1 + \ + ((stride) >> 1) * ((line) >> 1))) + +#define YV12_V(line) \ + ((uint8_t *) ((bits) + offset0 + \ + ((stride) >> 1) * ((line) >> 1))) + +/********************************** Fetch ************************************/ + +static void +fetch_scanline_a8r8g8b8 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + + MEMCPY_WRAPPED (image, + buffer, (const uint32_t *)bits + x, + width * sizeof(uint32_t)); +} + +static void +fetch_scanline_x8r8g8b8 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint32_t *pixel = (const uint32_t *)bits + x; + const uint32_t *end = pixel + width; + + while (pixel < end) + *buffer++ = READ (image, pixel++) | 0xff000000; +} + +static void +fetch_scanline_a8b8g8r8 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint32_t *pixel = (uint32_t *)bits + x; + const uint32_t *end = pixel + width; + + while (pixel < end) + { + uint32_t p = READ (image, pixel++); + + *buffer++ = (p & 0xff00ff00) | + ((p >> 16) & 0xff) | + ((p & 0xff) << 16); + } +} + +static void +fetch_scanline_x8b8g8r8 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint32_t *pixel = (uint32_t *)bits + x; + const uint32_t *end = pixel + width; + + while (pixel < end) + { + uint32_t p = READ (image, pixel++); + + *buffer++ = 0xff000000 | + (p & 0x0000ff00) | + ((p >> 16) & 0xff) | + ((p & 0xff) << 16); + } +} + +static void +fetch_scanline_b8g8r8a8 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint32_t *pixel = (uint32_t *)bits + x; + const uint32_t *end = pixel + width; + + while (pixel < end) + { + uint32_t p = READ (image, pixel++); + + *buffer++ = (((p & 0xff000000) >> 24) | + ((p & 0x00ff0000) >> 8) | + ((p & 0x0000ff00) << 8) | + ((p & 0x000000ff) << 24)); + } +} + +static void +fetch_scanline_b8g8r8x8 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint32_t *pixel = (uint32_t *)bits + x; + const uint32_t *end = pixel + width; + + while (pixel < end) + { + uint32_t p = READ (image, pixel++); + + *buffer++ = (0xff000000 | + ((p & 0xff000000) >> 24) | + ((p & 0x00ff0000) >> 8) | + ((p & 0x0000ff00) << 8)); + } +} + +static void +fetch_scanline_r8g8b8a8 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint32_t *pixel = (uint32_t *)bits + x; + const uint32_t *end = pixel + width; + + while (pixel < end) + { + uint32_t p = READ (image, pixel++); + + *buffer++ = (((p & 0x000000ff) << 24) | (p >> 8)); + } +} + +static void +fetch_scanline_r8g8b8x8 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint32_t *pixel = (uint32_t *)bits + x; + const uint32_t *end = pixel + width; + + while (pixel < end) + { + uint32_t p = READ (image, pixel++); + + *buffer++ = (0xff000000 | (p >> 8)); + } +} + +static void +fetch_scanline_x14r6g6b6 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint32_t *pixel = (const uint32_t *)bits + x; + const uint32_t *end = pixel + width; + + while (pixel < end) + { + uint32_t p = READ (image, pixel++); + uint32_t r, g, b; + + r = ((p & 0x3f000) << 6) | ((p & 0x30000)); + g = ((p & 0x00fc0) << 4) | ((p & 0x00c00) >> 2); + b = ((p & 0x0003f) << 2) | ((p & 0x00030) >> 4); + + *buffer++ = 0xff000000 | r | g | b; + } +} + +/* Expects a uint64_t buffer */ +static void +fetch_scanline_a2r10g10b10 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * b, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint32_t *pixel = bits + x; + const uint32_t *end = pixel + width; + uint64_t *buffer = (uint64_t *)b; + + while (pixel < end) + { + uint32_t p = READ (image, pixel++); + uint64_t a = p >> 30; + uint64_t r = (p >> 20) & 0x3ff; + uint64_t g = (p >> 10) & 0x3ff; + uint64_t b = p & 0x3ff; + + r = r << 6 | r >> 4; + g = g << 6 | g >> 4; + b = b << 6 | b >> 4; + + a <<= 14; + a |= a >> 2; + a |= a >> 4; + a |= a >> 8; + + *buffer++ = a << 48 | r << 32 | g << 16 | b; + } +} + +/* Expects a uint64_t buffer */ +static void +fetch_scanline_x2r10g10b10 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * b, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint32_t *pixel = (uint32_t *)bits + x; + const uint32_t *end = pixel + width; + uint64_t *buffer = (uint64_t *)b; + + while (pixel < end) + { + uint32_t p = READ (image, pixel++); + uint64_t r = (p >> 20) & 0x3ff; + uint64_t g = (p >> 10) & 0x3ff; + uint64_t b = p & 0x3ff; + + r = r << 6 | r >> 4; + g = g << 6 | g >> 4; + b = b << 6 | b >> 4; + + *buffer++ = 0xffffULL << 48 | r << 32 | g << 16 | b; + } +} + +/* Expects a uint64_t buffer */ +static void +fetch_scanline_a2b10g10r10 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * b, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint32_t *pixel = bits + x; + const uint32_t *end = pixel + width; + uint64_t *buffer = (uint64_t *)b; + + while (pixel < end) + { + uint32_t p = READ (image, pixel++); + uint64_t a = p >> 30; + uint64_t b = (p >> 20) & 0x3ff; + uint64_t g = (p >> 10) & 0x3ff; + uint64_t r = p & 0x3ff; + + r = r << 6 | r >> 4; + g = g << 6 | g >> 4; + b = b << 6 | b >> 4; + + a <<= 14; + a |= a >> 2; + a |= a >> 4; + a |= a >> 8; + + *buffer++ = a << 48 | r << 32 | g << 16 | b; + } +} + +/* Expects a uint64_t buffer */ +static void +fetch_scanline_x2b10g10r10 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * b, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint32_t *pixel = (uint32_t *)bits + x; + const uint32_t *end = pixel + width; + uint64_t *buffer = (uint64_t *)b; + + while (pixel < end) + { + uint32_t p = READ (image, pixel++); + uint64_t b = (p >> 20) & 0x3ff; + uint64_t g = (p >> 10) & 0x3ff; + uint64_t r = p & 0x3ff; + + r = r << 6 | r >> 4; + g = g << 6 | g >> 4; + b = b << 6 | b >> 4; + + *buffer++ = 0xffffULL << 48 | r << 32 | g << 16 | b; + } +} + +static void +fetch_scanline_r8g8b8 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint8_t *pixel = (const uint8_t *)bits + 3 * x; + const uint8_t *end = pixel + 3 * width; + + while (pixel < end) + { + uint32_t b = 0xff000000; + +#ifdef WORDS_BIGENDIAN + b |= (READ (image, pixel++) << 16); + b |= (READ (image, pixel++) << 8); + b |= (READ (image, pixel++)); +#else + b |= (READ (image, pixel++)); + b |= (READ (image, pixel++) << 8); + b |= (READ (image, pixel++) << 16); +#endif + + *buffer++ = b; + } +} + +static void +fetch_scanline_b8g8r8 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint8_t *pixel = (const uint8_t *)bits + 3 * x; + const uint8_t *end = pixel + 3 * width; + + while (pixel < end) + { + uint32_t b = 0xff000000; +#ifdef WORDS_BIGENDIAN + b |= (READ (image, pixel++)); + b |= (READ (image, pixel++) << 8); + b |= (READ (image, pixel++) << 16); +#else + b |= (READ (image, pixel++) << 16); + b |= (READ (image, pixel++) << 8); + b |= (READ (image, pixel++)); +#endif + *buffer++ = b; + } +} + +static void +fetch_scanline_r5g6b5 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint16_t *pixel = (const uint16_t *)bits + x; + const uint16_t *end = pixel + width; + + while (pixel < end) + { + uint32_t p = READ (image, pixel++); + uint32_t r = (((p) << 3) & 0xf8) | + (((p) << 5) & 0xfc00) | + (((p) << 8) & 0xf80000); + + r |= (r >> 5) & 0x70007; + r |= (r >> 6) & 0x300; + + *buffer++ = 0xff000000 | r; + } +} + +static void +fetch_scanline_b5g6r5 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint16_t *pixel = (const uint16_t *)bits + x; + const uint16_t *end = pixel + width; + + while (pixel < end) + { + uint32_t p = READ (image, pixel++); + uint32_t r, g, b; + + b = ((p & 0xf800) | ((p & 0xe000) >> 5)) >> 8; + g = ((p & 0x07e0) | ((p & 0x0600) >> 6)) << 5; + r = ((p & 0x001c) | ((p & 0x001f) << 5)) << 14; + + *buffer++ = 0xff000000 | r | g | b; + } +} + +static void +fetch_scanline_a1r5g5b5 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint16_t *pixel = (const uint16_t *)bits + x; + const uint16_t *end = pixel + width; + + while (pixel < end) + { + uint32_t p = READ (image, pixel++); + uint32_t r, g, b, a; + + a = (uint32_t) ((uint8_t) (0 - ((p & 0x8000) >> 15))) << 24; + r = ((p & 0x7c00) | ((p & 0x7000) >> 5)) << 9; + g = ((p & 0x03e0) | ((p & 0x0380) >> 5)) << 6; + b = ((p & 0x001c) | ((p & 0x001f) << 5)) >> 2; + + *buffer++ = a | r | g | b; + } +} + +static void +fetch_scanline_x1r5g5b5 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint16_t *pixel = (const uint16_t *)bits + x; + const uint16_t *end = pixel + width; + + while (pixel < end) + { + uint32_t p = READ (image, pixel++); + uint32_t r, g, b; + + r = ((p & 0x7c00) | ((p & 0x7000) >> 5)) << 9; + g = ((p & 0x03e0) | ((p & 0x0380) >> 5)) << 6; + b = ((p & 0x001c) | ((p & 0x001f) << 5)) >> 2; + + *buffer++ = 0xff000000 | r | g | b; + } +} + +static void +fetch_scanline_a1b5g5r5 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint16_t *pixel = (const uint16_t *)bits + x; + const uint16_t *end = pixel + width; + uint32_t r, g, b, a; + + while (pixel < end) + { + uint32_t p = READ (image, pixel++); + + a = (uint32_t) ((uint8_t) (0 - ((p & 0x8000) >> 15))) << 24; + b = ((p & 0x7c00) | ((p & 0x7000) >> 5)) >> 7; + g = ((p & 0x03e0) | ((p & 0x0380) >> 5)) << 6; + r = ((p & 0x001c) | ((p & 0x001f) << 5)) << 14; + + *buffer++ = a | r | g | b; + } +} + +static void +fetch_scanline_x1b5g5r5 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint16_t *pixel = (const uint16_t *)bits + x; + const uint16_t *end = pixel + width; + + while (pixel < end) + { + uint32_t p = READ (image, pixel++); + uint32_t r, g, b; + + b = ((p & 0x7c00) | ((p & 0x7000) >> 5)) >> 7; + g = ((p & 0x03e0) | ((p & 0x0380) >> 5)) << 6; + r = ((p & 0x001c) | ((p & 0x001f) << 5)) << 14; + + *buffer++ = 0xff000000 | r | g | b; + } +} + +static void +fetch_scanline_a4r4g4b4 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint16_t *pixel = (const uint16_t *)bits + x; + const uint16_t *end = pixel + width; + + while (pixel < end) + { + uint32_t p = READ (image, pixel++); + uint32_t r, g, b, a; + + a = ((p & 0xf000) | ((p & 0xf000) >> 4)) << 16; + r = ((p & 0x0f00) | ((p & 0x0f00) >> 4)) << 12; + g = ((p & 0x00f0) | ((p & 0x00f0) >> 4)) << 8; + b = ((p & 0x000f) | ((p & 0x000f) << 4)); + + *buffer++ = a | r | g | b; + } +} + +static void +fetch_scanline_x4r4g4b4 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint16_t *pixel = (const uint16_t *)bits + x; + const uint16_t *end = pixel + width; + + while (pixel < end) + { + uint32_t p = READ (image, pixel++); + uint32_t r, g, b; + + r = ((p & 0x0f00) | ((p & 0x0f00) >> 4)) << 12; + g = ((p & 0x00f0) | ((p & 0x00f0) >> 4)) << 8; + b = ((p & 0x000f) | ((p & 0x000f) << 4)); + + *buffer++ = 0xff000000 | r | g | b; + } +} + +static void +fetch_scanline_a4b4g4r4 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint16_t *pixel = (const uint16_t *)bits + x; + const uint16_t *end = pixel + width; + + while (pixel < end) + { + uint32_t p = READ (image, pixel++); + uint32_t r, g, b, a; + + a = ((p & 0xf000) | ((p & 0xf000) >> 4)) << 16; + b = ((p & 0x0f00) | ((p & 0x0f00) >> 4)) >> 4; + g = ((p & 0x00f0) | ((p & 0x00f0) >> 4)) << 8; + r = ((p & 0x000f) | ((p & 0x000f) << 4)) << 16; + + *buffer++ = a | r | g | b; + } +} + +static void +fetch_scanline_x4b4g4r4 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint16_t *pixel = (const uint16_t *)bits + x; + const uint16_t *end = pixel + width; + + while (pixel < end) + { + uint32_t p = READ (image, pixel++); + uint32_t r, g, b; + + b = ((p & 0x0f00) | ((p & 0x0f00) >> 4)) >> 4; + g = ((p & 0x00f0) | ((p & 0x00f0) >> 4)) << 8; + r = ((p & 0x000f) | ((p & 0x000f) << 4)) << 16; + + *buffer++ = 0xff000000 | r | g | b; + } +} + +static void +fetch_scanline_a8 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint8_t *pixel = (const uint8_t *)bits + x; + const uint8_t *end = pixel + width; + + while (pixel < end) + *buffer++ = READ (image, pixel++) << 24; +} + +static void +fetch_scanline_r3g3b2 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint8_t *pixel = (const uint8_t *)bits + x; + const uint8_t *end = pixel + width; + + while (pixel < end) + { + uint32_t p = READ (image, pixel++); + uint32_t r, g, b; + + r = ((p & 0xe0) | ((p & 0xe0) >> 3) | ((p & 0xc0) >> 6)) << 16; + g = ((p & 0x1c) | ((p & 0x18) >> 3) | ((p & 0x1c) << 3)) << 8; + b = (((p & 0x03) ) | + ((p & 0x03) << 2) | + ((p & 0x03) << 4) | + ((p & 0x03) << 6)); + + *buffer++ = 0xff000000 | r | g | b; + } +} + +static void +fetch_scanline_b2g3r3 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint8_t *pixel = (const uint8_t *)bits + x; + const uint8_t *end = pixel + width; + + while (pixel < end) + { + uint32_t p = READ (image, pixel++); + uint32_t r, g, b; + + b = p & 0xc0; + b |= b >> 2; + b |= b >> 4; + b &= 0xff; + + g = (p & 0x38) << 10; + g |= g >> 3; + g |= g >> 6; + g &= 0xff00; + + r = (p & 0x7) << 21; + r |= r >> 3; + r |= r >> 6; + r &= 0xff0000; + + *buffer++ = 0xff000000 | r | g | b; + } +} + +static void +fetch_scanline_a2r2g2b2 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint8_t *pixel = (const uint8_t *)bits + x; + const uint8_t *end = pixel + width; + + while (pixel < end) + { + uint32_t p = READ (image, pixel++); + uint32_t a, r, g, b; + + a = ((p & 0xc0) * 0x55) << 18; + r = ((p & 0x30) * 0x55) << 12; + g = ((p & 0x0c) * 0x55) << 6; + b = ((p & 0x03) * 0x55); + + *buffer++ = a | r | g | b; + } +} + +static void +fetch_scanline_a2b2g2r2 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint8_t *pixel = (const uint8_t *)bits + x; + const uint8_t *end = pixel + width; + + while (pixel < end) + { + uint32_t p = READ (image, pixel++); + uint32_t a, r, g, b; + + a = ((p & 0xc0) * 0x55) << 18; + b = ((p & 0x30) * 0x55) >> 4; + g = ((p & 0x0c) * 0x55) << 6; + r = ((p & 0x03) * 0x55) << 16; + + *buffer++ = a | r | g | b; + } +} + +static void +fetch_scanline_c8 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const pixman_indexed_t * indexed = image->bits.indexed; + const uint8_t *pixel = (const uint8_t *)bits + x; + const uint8_t *end = pixel + width; + + while (pixel < end) + { + uint32_t p = READ (image, pixel++); + + *buffer++ = indexed->rgba[p]; + } +} + +static void +fetch_scanline_x4a4 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint8_t *pixel = (const uint8_t *)bits + x; + const uint8_t *end = pixel + width; + + while (pixel < end) + { + uint8_t p = READ (image, pixel++) & 0xf; + + *buffer++ = (p | (p << 4)) << 24; + } +} + +#define FETCH_8(img,l,o) (READ (img, (((uint8_t *)(l)) + ((o) >> 3)))) +#ifdef WORDS_BIGENDIAN +#define FETCH_4(img,l,o) \ + (((4 * (o)) & 4) ? (FETCH_8 (img,l, 4 * (o)) & 0xf) : (FETCH_8 (img,l,(4 * (o))) >> 4)) +#else +#define FETCH_4(img,l,o) \ + (((4 * (o)) & 4) ? (FETCH_8 (img, l, 4 * (o)) >> 4) : (FETCH_8 (img, l, (4 * (o))) & 0xf)) +#endif + +static void +fetch_scanline_a4 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + int i; + + for (i = 0; i < width; ++i) + { + uint32_t p = FETCH_4 (image, bits, i + x); + + p |= p << 4; + + *buffer++ = p << 24; + } +} + +static void +fetch_scanline_r1g2b1 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + int i; + + for (i = 0; i < width; ++i) + { + uint32_t p = FETCH_4 (image, bits, i + x); + uint32_t r, g, b; + + r = ((p & 0x8) * 0xff) << 13; + g = ((p & 0x6) * 0x55) << 7; + b = ((p & 0x1) * 0xff); + + *buffer++ = 0xff000000 | r | g | b; + } +} + +static void +fetch_scanline_b1g2r1 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + int i; + + for (i = 0; i < width; ++i) + { + uint32_t p = FETCH_4 (image, bits, i + x); + uint32_t r, g, b; + + b = ((p & 0x8) * 0xff) >> 3; + g = ((p & 0x6) * 0x55) << 7; + r = ((p & 0x1) * 0xff) << 16; + + *buffer++ = 0xff000000 | r | g | b; + } +} + +static void +fetch_scanline_a1r1g1b1 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + uint32_t a, r, g, b; + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + int i; + + for (i = 0; i < width; ++i) + { + uint32_t p = FETCH_4 (image, bits, i + x); + + a = ((p & 0x8) * 0xff) << 21; + r = ((p & 0x4) * 0xff) << 14; + g = ((p & 0x2) * 0xff) << 7; + b = ((p & 0x1) * 0xff); + + *buffer++ = a | r | g | b; + } +} + +static void +fetch_scanline_a1b1g1r1 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + int i; + + for (i = 0; i < width; ++i) + { + uint32_t p = FETCH_4 (image, bits, i + x); + uint32_t a, r, g, b; + + a = ((p & 0x8) * 0xff) << 21; + b = ((p & 0x4) * 0xff) >> 2; + g = ((p & 0x2) * 0xff) << 7; + r = ((p & 0x1) * 0xff) << 16; + + *buffer++ = a | r | g | b; + } +} + +static void +fetch_scanline_c4 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const pixman_indexed_t * indexed = image->bits.indexed; + int i; + + for (i = 0; i < width; ++i) + { + uint32_t p = FETCH_4 (image, bits, i + x); + + *buffer++ = indexed->rgba[p]; + } +} + +static void +fetch_scanline_a1 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + int i; + + for (i = 0; i < width; ++i) + { + uint32_t p = READ (image, bits + ((i + x) >> 5)); + uint32_t a; + +#ifdef WORDS_BIGENDIAN + a = p >> (0x1f - ((i + x) & 0x1f)); +#else + a = p >> ((i + x) & 0x1f); +#endif + a = a & 1; + a |= a << 1; + a |= a << 2; + a |= a << 4; + + *buffer++ = a << 24; + } +} + +static void +fetch_scanline_g1 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const pixman_indexed_t * indexed = image->bits.indexed; + int i; + + for (i = 0; i < width; ++i) + { + uint32_t p = READ (image, bits + ((i + x) >> 5)); + uint32_t a; + +#ifdef WORDS_BIGENDIAN + a = p >> (0x1f - ((i + x) & 0x1f)); +#else + a = p >> ((i + x) & 0x1f); +#endif + a = a & 1; + + *buffer++ = indexed->rgba[a]; + } +} + +static void +fetch_scanline_yuy2 (pixman_image_t *image, + int x, + int line, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + image->bits.rowstride * line; + int i; + + for (i = 0; i < width; i++) + { + int16_t y, u, v; + int32_t r, g, b; + + y = ((uint8_t *) bits)[(x + i) << 1] - 16; + u = ((uint8_t *) bits)[(((x + i) << 1) & - 4) + 1] - 128; + v = ((uint8_t *) bits)[(((x + i) << 1) & - 4) + 3] - 128; + + /* R = 1.164(Y - 16) + 1.596(V - 128) */ + r = 0x012b27 * y + 0x019a2e * v; + /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */ + g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u; + /* B = 1.164(Y - 16) + 2.018(U - 128) */ + b = 0x012b27 * y + 0x0206a2 * u; + + *buffer++ = 0xff000000 | + (r >= 0 ? r < 0x1000000 ? r & 0xff0000 : 0xff0000 : 0) | + (g >= 0 ? g < 0x1000000 ? (g >> 8) & 0x00ff00 : 0x00ff00 : 0) | + (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0); + } +} + +static void +fetch_scanline_yv12 (pixman_image_t *image, + int x, + int line, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + YV12_SETUP (image); + uint8_t *y_line = YV12_Y (line); + uint8_t *u_line = YV12_U (line); + uint8_t *v_line = YV12_V (line); + int i; + + for (i = 0; i < width; i++) + { + int16_t y, u, v; + int32_t r, g, b; + + y = y_line[x + i] - 16; + u = u_line[(x + i) >> 1] - 128; + v = v_line[(x + i) >> 1] - 128; + + /* R = 1.164(Y - 16) + 1.596(V - 128) */ + r = 0x012b27 * y + 0x019a2e * v; + /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */ + g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u; + /* B = 1.164(Y - 16) + 2.018(U - 128) */ + b = 0x012b27 * y + 0x0206a2 * u; + + *buffer++ = 0xff000000 | + (r >= 0 ? r < 0x1000000 ? r & 0xff0000 : 0xff0000 : 0) | + (g >= 0 ? g < 0x1000000 ? (g >> 8) & 0x00ff00 : 0x00ff00 : 0) | + (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0); + } +} + +/**************************** Pixel wise fetching *****************************/ + +/* Despite the type, expects a uint64_t buffer */ +static uint64_t +fetch_pixel_a2r10g10b10 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t p = READ (image, bits + offset); + uint64_t a = p >> 30; + uint64_t r = (p >> 20) & 0x3ff; + uint64_t g = (p >> 10) & 0x3ff; + uint64_t b = p & 0x3ff; + + r = r << 6 | r >> 4; + g = g << 6 | g >> 4; + b = b << 6 | b >> 4; + + a <<= 14; + a |= a >> 2; + a |= a >> 4; + a |= a >> 8; + + return a << 48 | r << 32 | g << 16 | b; +} + +/* Despite the type, this function expects a uint64_t buffer */ +static uint64_t +fetch_pixel_x2r10g10b10 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t p = READ (image, bits + offset); + uint64_t r = (p >> 20) & 0x3ff; + uint64_t g = (p >> 10) & 0x3ff; + uint64_t b = p & 0x3ff; + + r = r << 6 | r >> 4; + g = g << 6 | g >> 4; + b = b << 6 | b >> 4; + + return 0xffffULL << 48 | r << 32 | g << 16 | b; +} + +/* Despite the type, expects a uint64_t buffer */ +static uint64_t +fetch_pixel_a2b10g10r10 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t p = READ (image, bits + offset); + uint64_t a = p >> 30; + uint64_t b = (p >> 20) & 0x3ff; + uint64_t g = (p >> 10) & 0x3ff; + uint64_t r = p & 0x3ff; + + r = r << 6 | r >> 4; + g = g << 6 | g >> 4; + b = b << 6 | b >> 4; + + a <<= 14; + a |= a >> 2; + a |= a >> 4; + a |= a >> 8; + + return a << 48 | r << 32 | g << 16 | b; +} + +/* Despite the type, this function expects a uint64_t buffer */ +static uint64_t +fetch_pixel_x2b10g10r10 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t p = READ (image, bits + offset); + uint64_t b = (p >> 20) & 0x3ff; + uint64_t g = (p >> 10) & 0x3ff; + uint64_t r = p & 0x3ff; + + r = r << 6 | r >> 4; + g = g << 6 | g >> 4; + b = b << 6 | b >> 4; + + return 0xffffULL << 48 | r << 32 | g << 16 | b; +} + +static uint32_t +fetch_pixel_a8r8g8b8 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + return READ (image, (uint32_t *)bits + offset); +} + +static uint32_t +fetch_pixel_x8r8g8b8 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + + return READ (image, (uint32_t *)bits + offset) | 0xff000000; +} + +static uint32_t +fetch_pixel_a8b8g8r8 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t pixel = READ (image, (uint32_t *)bits + offset); + + return ((pixel & 0xff000000) | + ((pixel >> 16) & 0xff) | + (pixel & 0x0000ff00) | + ((pixel & 0xff) << 16)); +} + +static uint32_t +fetch_pixel_x8b8g8r8 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t pixel = READ (image, (uint32_t *)bits + offset); + + return ((0xff000000) | + ((pixel >> 16) & 0xff) | + (pixel & 0x0000ff00) | + ((pixel & 0xff) << 16)); +} + +static uint32_t +fetch_pixel_b8g8r8a8 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t pixel = READ (image, (uint32_t *)bits + offset); + + return ((pixel & 0xff000000) >> 24 | + (pixel & 0x00ff0000) >> 8 | + (pixel & 0x0000ff00) << 8 | + (pixel & 0x000000ff) << 24); +} + +static uint32_t +fetch_pixel_b8g8r8x8 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t pixel = READ (image, (uint32_t *)bits + offset); + + return ((0xff000000) | + (pixel & 0xff000000) >> 24 | + (pixel & 0x00ff0000) >> 8 | + (pixel & 0x0000ff00) << 8); +} + +static uint32_t +fetch_pixel_r8g8b8a8 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t pixel = READ (image, (uint32_t *)bits + offset); + + return (((pixel & 0x000000ff) << 24) | (pixel >> 8)); +} + +static uint32_t +fetch_pixel_r8g8b8x8 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t pixel = READ (image, (uint32_t *)bits + offset); + + return (0xff000000 | (pixel >> 8)); +} + +static uint32_t +fetch_pixel_x14r6g6b6 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t pixel = READ (image, (uint32_t *) bits + offset); + uint32_t r, g, b; + + r = ((pixel & 0x3f000) << 6) | ((pixel & 0x30000)); + g = ((pixel & 0x00fc0) << 4) | ((pixel & 0x00c00) >> 2); + b = ((pixel & 0x0003f) << 2) | ((pixel & 0x00030) >> 4); + + return 0xff000000 | r | g | b; +} + +static uint32_t +fetch_pixel_r8g8b8 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint8_t *pixel = ((uint8_t *) bits) + (offset * 3); + +#ifdef WORDS_BIGENDIAN + return (0xff000000 | + (READ (image, pixel + 0) << 16) | + (READ (image, pixel + 1) << 8) | + (READ (image, pixel + 2))); +#else + return (0xff000000 | + (READ (image, pixel + 2) << 16) | + (READ (image, pixel + 1) << 8) | + (READ (image, pixel + 0))); +#endif +} + +static uint32_t +fetch_pixel_b8g8r8 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint8_t *pixel = ((uint8_t *) bits) + (offset * 3); +#ifdef WORDS_BIGENDIAN + return (0xff000000 | + (READ (image, pixel + 2) << 16) | + (READ (image, pixel + 1) << 8) | + (READ (image, pixel + 0))); +#else + return (0xff000000 | + (READ (image, pixel + 0) << 16) | + (READ (image, pixel + 1) << 8) | + (READ (image, pixel + 2))); +#endif +} + +static uint32_t +fetch_pixel_r5g6b5 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t pixel = READ (image, (uint16_t *) bits + offset); + uint32_t r, g, b; + + r = ((pixel & 0xf800) | ((pixel & 0xe000) >> 5)) << 8; + g = ((pixel & 0x07e0) | ((pixel & 0x0600) >> 6)) << 5; + b = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) >> 2; + + return (0xff000000 | r | g | b); +} + +static uint32_t +fetch_pixel_b5g6r5 (bits_image_t *image, + int offset, + int line) +{ + uint32_t r, g, b; + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t pixel = READ (image, (uint16_t *) bits + offset); + + b = ((pixel & 0xf800) | ((pixel & 0xe000) >> 5)) >> 8; + g = ((pixel & 0x07e0) | ((pixel & 0x0600) >> 6)) << 5; + r = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) << 14; + + return (0xff000000 | r | g | b); +} + +static uint32_t +fetch_pixel_a1r5g5b5 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t pixel = READ (image, (uint16_t *) bits + offset); + uint32_t a, r, g, b; + + a = (uint32_t) ((uint8_t) (0 - ((pixel & 0x8000) >> 15))) << 24; + r = ((pixel & 0x7c00) | ((pixel & 0x7000) >> 5)) << 9; + g = ((pixel & 0x03e0) | ((pixel & 0x0380) >> 5)) << 6; + b = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) >> 2; + + return (a | r | g | b); +} + +static uint32_t +fetch_pixel_x1r5g5b5 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t pixel = READ (image, (uint16_t *) bits + offset); + uint32_t r, g, b; + + r = ((pixel & 0x7c00) | ((pixel & 0x7000) >> 5)) << 9; + g = ((pixel & 0x03e0) | ((pixel & 0x0380) >> 5)) << 6; + b = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) >> 2; + + return (0xff000000 | r | g | b); +} + +static uint32_t +fetch_pixel_a1b5g5r5 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t pixel = READ (image, (uint16_t *) bits + offset); + uint32_t a, r, g, b; + + a = (uint32_t) ((uint8_t) (0 - ((pixel & 0x8000) >> 15))) << 24; + b = ((pixel & 0x7c00) | ((pixel & 0x7000) >> 5)) >> 7; + g = ((pixel & 0x03e0) | ((pixel & 0x0380) >> 5)) << 6; + r = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) << 14; + + return (a | r | g | b); +} + +static uint32_t +fetch_pixel_x1b5g5r5 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t pixel = READ (image, (uint16_t *) bits + offset); + uint32_t r, g, b; + + b = ((pixel & 0x7c00) | ((pixel & 0x7000) >> 5)) >> 7; + g = ((pixel & 0x03e0) | ((pixel & 0x0380) >> 5)) << 6; + r = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) << 14; + + return (0xff000000 | r | g | b); +} + +static uint32_t +fetch_pixel_a4r4g4b4 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t pixel = READ (image, (uint16_t *) bits + offset); + uint32_t a, r, g, b; + + a = ((pixel & 0xf000) | ((pixel & 0xf000) >> 4)) << 16; + r = ((pixel & 0x0f00) | ((pixel & 0x0f00) >> 4)) << 12; + g = ((pixel & 0x00f0) | ((pixel & 0x00f0) >> 4)) << 8; + b = ((pixel & 0x000f) | ((pixel & 0x000f) << 4)); + + return (a | r | g | b); +} + +static uint32_t +fetch_pixel_x4r4g4b4 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t pixel = READ (image, (uint16_t *) bits + offset); + uint32_t r, g, b; + + r = ((pixel & 0x0f00) | ((pixel & 0x0f00) >> 4)) << 12; + g = ((pixel & 0x00f0) | ((pixel & 0x00f0) >> 4)) << 8; + b = ((pixel & 0x000f) | ((pixel & 0x000f) << 4)); + + return (0xff000000 | r | g | b); +} + +static uint32_t +fetch_pixel_a4b4g4r4 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t pixel = READ (image, (uint16_t *) bits + offset); + uint32_t a, r, g, b; + + a = ((pixel & 0xf000) | ((pixel & 0xf000) >> 4)) << 16; + b = ((pixel & 0x0f00) | ((pixel & 0x0f00) >> 4)) >> 4; + g = ((pixel & 0x00f0) | ((pixel & 0x00f0) >> 4)) << 8; + r = ((pixel & 0x000f) | ((pixel & 0x000f) << 4)) << 16; + + return (a | r | g | b); +} + +static uint32_t +fetch_pixel_x4b4g4r4 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t pixel = READ (image, (uint16_t *) bits + offset); + uint32_t r, g, b; + + b = ((pixel & 0x0f00) | ((pixel & 0x0f00) >> 4)) >> 4; + g = ((pixel & 0x00f0) | ((pixel & 0x00f0) >> 4)) << 8; + r = ((pixel & 0x000f) | ((pixel & 0x000f) << 4)) << 16; + + return (0xff000000 | r | g | b); +} + +static uint32_t +fetch_pixel_a8 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t pixel = READ (image, (uint8_t *) bits + offset); + + return pixel << 24; +} + +static uint32_t +fetch_pixel_r3g3b2 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t pixel = READ (image, (uint8_t *) bits + offset); + uint32_t r, g, b; + + r = ((pixel & 0xe0) | + ((pixel & 0xe0) >> 3) | + ((pixel & 0xc0) >> 6)) << 16; + + g = ((pixel & 0x1c) | + ((pixel & 0x18) >> 3) | + ((pixel & 0x1c) << 3)) << 8; + + b = (((pixel & 0x03) ) | + ((pixel & 0x03) << 2) | + ((pixel & 0x03) << 4) | + ((pixel & 0x03) << 6)); + + return (0xff000000 | r | g | b); +} + +static uint32_t +fetch_pixel_b2g3r3 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t p = READ (image, (uint8_t *) bits + offset); + uint32_t r, g, b; + + b = p & 0xc0; + b |= b >> 2; + b |= b >> 4; + b &= 0xff; + + g = (p & 0x38) << 10; + g |= g >> 3; + g |= g >> 6; + g &= 0xff00; + + r = (p & 0x7) << 21; + r |= r >> 3; + r |= r >> 6; + r &= 0xff0000; + + return 0xff000000 | r | g | b; +} + +static uint32_t +fetch_pixel_a2r2g2b2 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t pixel = READ (image, (uint8_t *) bits + offset); + uint32_t a, r, g, b; + + a = ((pixel & 0xc0) * 0x55) << 18; + r = ((pixel & 0x30) * 0x55) << 12; + g = ((pixel & 0x0c) * 0x55) << 6; + b = ((pixel & 0x03) * 0x55); + + return a | r | g | b; +} + +static uint32_t +fetch_pixel_a2b2g2r2 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t pixel = READ (image, (uint8_t *) bits + offset); + uint32_t a, r, g, b; + + a = ((pixel & 0xc0) * 0x55) << 18; + b = ((pixel & 0x30) * 0x55) >> 4; + g = ((pixel & 0x0c) * 0x55) << 6; + r = ((pixel & 0x03) * 0x55) << 16; + + return a | r | g | b; +} + +static uint32_t +fetch_pixel_c8 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t pixel = READ (image, (uint8_t *) bits + offset); + const pixman_indexed_t * indexed = image->indexed; + + return indexed->rgba[pixel]; +} + +static uint32_t +fetch_pixel_x4a4 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t pixel = READ (image, (uint8_t *) bits + offset); + + return ((pixel & 0xf) | ((pixel & 0xf) << 4)) << 24; +} + +static uint32_t +fetch_pixel_a4 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t pixel = FETCH_4 (image, bits, offset); + + pixel |= pixel << 4; + return pixel << 24; +} + +static uint32_t +fetch_pixel_r1g2b1 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t pixel = FETCH_4 (image, bits, offset); + uint32_t r, g, b; + + r = ((pixel & 0x8) * 0xff) << 13; + g = ((pixel & 0x6) * 0x55) << 7; + b = ((pixel & 0x1) * 0xff); + + return 0xff000000 | r | g | b; +} + +static uint32_t +fetch_pixel_b1g2r1 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t pixel = FETCH_4 (image, bits, offset); + uint32_t r, g, b; + + b = ((pixel & 0x8) * 0xff) >> 3; + g = ((pixel & 0x6) * 0x55) << 7; + r = ((pixel & 0x1) * 0xff) << 16; + + return 0xff000000 | r | g | b; +} + +static uint32_t +fetch_pixel_a1r1g1b1 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t pixel = FETCH_4 (image, bits, offset); + uint32_t a, r, g, b; + + a = ((pixel & 0x8) * 0xff) << 21; + r = ((pixel & 0x4) * 0xff) << 14; + g = ((pixel & 0x2) * 0xff) << 7; + b = ((pixel & 0x1) * 0xff); + + return a | r | g | b; +} + +static uint32_t +fetch_pixel_a1b1g1r1 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t pixel = FETCH_4 (image, bits, offset); + uint32_t a, r, g, b; + + a = ((pixel & 0x8) * 0xff) << 21; + b = ((pixel & 0x4) * 0xff) >> 2; + g = ((pixel & 0x2) * 0xff) << 7; + r = ((pixel & 0x1) * 0xff) << 16; + + return a | r | g | b; +} + +static uint32_t +fetch_pixel_c4 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t pixel = FETCH_4 (image, bits, offset); + const pixman_indexed_t * indexed = image->indexed; + + return indexed->rgba[pixel]; +} + +static uint32_t +fetch_pixel_a1 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t pixel = READ (image, bits + (offset >> 5)); + uint32_t a; + +#ifdef WORDS_BIGENDIAN + a = pixel >> (0x1f - (offset & 0x1f)); +#else + a = pixel >> (offset & 0x1f); +#endif + a = a & 1; + a |= a << 1; + a |= a << 2; + a |= a << 4; + + return a << 24; +} + +static uint32_t +fetch_pixel_g1 (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t pixel = READ (image, bits + (offset >> 5)); + const pixman_indexed_t * indexed = image->indexed; + uint32_t a; + +#ifdef WORDS_BIGENDIAN + a = pixel >> (0x1f - (offset & 0x1f)); +#else + a = pixel >> (offset & 0x1f); +#endif + a = a & 1; + + return indexed->rgba[a]; +} + +static uint32_t +fetch_pixel_yuy2 (bits_image_t *image, + int offset, + int line) +{ + const uint32_t *bits = image->bits + image->rowstride * line; + + int16_t y, u, v; + int32_t r, g, b; + + y = ((uint8_t *) bits)[offset << 1] - 16; + u = ((uint8_t *) bits)[((offset << 1) & - 4) + 1] - 128; + v = ((uint8_t *) bits)[((offset << 1) & - 4) + 3] - 128; + + /* R = 1.164(Y - 16) + 1.596(V - 128) */ + r = 0x012b27 * y + 0x019a2e * v; + + /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */ + g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u; + + /* B = 1.164(Y - 16) + 2.018(U - 128) */ + b = 0x012b27 * y + 0x0206a2 * u; + + return 0xff000000 | + (r >= 0 ? r < 0x1000000 ? r & 0xff0000 : 0xff0000 : 0) | + (g >= 0 ? g < 0x1000000 ? (g >> 8) & 0x00ff00 : 0x00ff00 : 0) | + (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0); +} + +static uint32_t +fetch_pixel_yv12 (bits_image_t *image, + int offset, + int line) +{ + YV12_SETUP (image); + int16_t y = YV12_Y (line)[offset] - 16; + int16_t u = YV12_U (line)[offset >> 1] - 128; + int16_t v = YV12_V (line)[offset >> 1] - 128; + int32_t r, g, b; + + /* R = 1.164(Y - 16) + 1.596(V - 128) */ + r = 0x012b27 * y + 0x019a2e * v; + + /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */ + g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u; + + /* B = 1.164(Y - 16) + 2.018(U - 128) */ + b = 0x012b27 * y + 0x0206a2 * u; + + return 0xff000000 | + (r >= 0 ? r < 0x1000000 ? r & 0xff0000 : 0xff0000 : 0) | + (g >= 0 ? g < 0x1000000 ? (g >> 8) & 0x00ff00 : 0x00ff00 : 0) | + (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0); +} + +/*********************************** Store ************************************/ + +#define SPLIT_A(v) \ + uint32_t a = ((v) >> 24), \ + r = ((v) >> 16) & 0xff, \ + g = ((v) >> 8) & 0xff, \ + b = (v) & 0xff + +#define SPLIT(v) \ + uint32_t r = ((v) >> 16) & 0xff, \ + g = ((v) >> 8) & 0xff, \ + b = (v) & 0xff + +static void +store_scanline_a2r10g10b10 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *v) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint32_t *pixel = bits + x; + uint64_t *values = (uint64_t *)v; + int i; + + for (i = 0; i < width; ++i) + { + WRITE (image, pixel++, + ((values[i] >> 32) & 0xc0000000) | + ((values[i] >> 18) & 0x3ff00000) | + ((values[i] >> 12) & 0xffc00) | + ((values[i] >> 6) & 0x3ff)); + } +} + +static void +store_scanline_x2r10g10b10 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *v) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint64_t *values = (uint64_t *)v; + uint32_t *pixel = bits + x; + int i; + + for (i = 0; i < width; ++i) + { + WRITE (image, pixel++, + ((values[i] >> 18) & 0x3ff00000) | + ((values[i] >> 12) & 0xffc00) | + ((values[i] >> 6) & 0x3ff)); + } +} + +static void +store_scanline_a2b10g10r10 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *v) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint32_t *pixel = bits + x; + uint64_t *values = (uint64_t *)v; + int i; + + for (i = 0; i < width; ++i) + { + WRITE (image, pixel++, + ((values[i] >> 32) & 0xc0000000) | + ((values[i] >> 38) & 0x3ff) | + ((values[i] >> 12) & 0xffc00) | + ((values[i] << 14) & 0x3ff00000)); + } +} + +static void +store_scanline_x2b10g10r10 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *v) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint64_t *values = (uint64_t *)v; + uint32_t *pixel = bits + x; + int i; + + for (i = 0; i < width; ++i) + { + WRITE (image, pixel++, + ((values[i] >> 38) & 0x3ff) | + ((values[i] >> 12) & 0xffc00) | + ((values[i] << 14) & 0x3ff00000)); + } +} + +static void +store_scanline_a8r8g8b8 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *bits = image->bits + image->rowstride * y; + + MEMCPY_WRAPPED (image, ((uint32_t *)bits) + x, values, + width * sizeof(uint32_t)); +} + +static void +store_scanline_x8r8g8b8 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint32_t *pixel = (uint32_t *)bits + x; + int i; + + for (i = 0; i < width; ++i) + WRITE (image, pixel++, values[i] & 0xffffff); +} + +static void +store_scanline_a8b8g8r8 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint32_t *pixel = (uint32_t *)bits + x; + int i; + + for (i = 0; i < width; ++i) + { + WRITE (image, pixel++, + (values[i] & 0xff00ff00) | + ((values[i] >> 16) & 0xff) | + ((values[i] & 0xff) << 16)); + } +} + +static void +store_scanline_x8b8g8r8 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint32_t *pixel = (uint32_t *)bits + x; + int i; + + for (i = 0; i < width; ++i) + { + WRITE (image, pixel++, + (values[i] & 0x0000ff00) | + ((values[i] >> 16) & 0xff) | + ((values[i] & 0xff) << 16)); + } +} + +static void +store_scanline_b8g8r8a8 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint32_t *pixel = (uint32_t *)bits + x; + int i; + + for (i = 0; i < width; ++i) + { + WRITE (image, pixel++, + ((values[i] >> 24) & 0x000000ff) | + ((values[i] >> 8) & 0x0000ff00) | + ((values[i] << 8) & 0x00ff0000) | + ((values[i] << 24) & 0xff000000)); + } +} + +static void +store_scanline_b8g8r8x8 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint32_t *pixel = (uint32_t *)bits + x; + int i; + + for (i = 0; i < width; ++i) + { + WRITE (image, pixel++, + ((values[i] >> 8) & 0x0000ff00) | + ((values[i] << 8) & 0x00ff0000) | + ((values[i] << 24) & 0xff000000)); + } +} + +static void +store_scanline_r8g8b8a8 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint32_t *pixel = (uint32_t *)bits + x; + int i; + + for (i = 0; i < width; ++i) + { + WRITE (image, pixel++, + ((values[i] >> 24) & 0x000000ff) | (values[i] << 8)); + } +} + +static void +store_scanline_r8g8b8x8 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint32_t *pixel = (uint32_t *)bits + x; + int i; + + for (i = 0; i < width; ++i) + WRITE (image, pixel++, (values[i] << 8)); +} + +static void +store_scanline_x14r6g6b6 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint32_t *pixel = ((uint32_t *) bits) + x; + int i; + + for (i = 0; i < width; ++i) + { + uint32_t s = values[i]; + uint32_t r, g, b; + + r = (s & 0xfc0000) >> 6; + g = (s & 0x00fc00) >> 4; + b = (s & 0x0000fc) >> 2; + + WRITE (image, pixel++, r | g | b); + } +} + +static void +store_scanline_r8g8b8 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint8_t *pixel = ((uint8_t *) bits) + 3 * x; + int i; + + for (i = 0; i < width; ++i) + { + uint32_t val = values[i]; + +#ifdef WORDS_BIGENDIAN + WRITE (image, pixel++, (val & 0x00ff0000) >> 16); + WRITE (image, pixel++, (val & 0x0000ff00) >> 8); + WRITE (image, pixel++, (val & 0x000000ff) >> 0); +#else + WRITE (image, pixel++, (val & 0x000000ff) >> 0); + WRITE (image, pixel++, (val & 0x0000ff00) >> 8); + WRITE (image, pixel++, (val & 0x00ff0000) >> 16); +#endif + } +} + +static void +store_scanline_b8g8r8 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint8_t *pixel = ((uint8_t *) bits) + 3 * x; + int i; + + for (i = 0; i < width; ++i) + { + uint32_t val = values[i]; + +#ifdef WORDS_BIGENDIAN + WRITE (image, pixel++, (val & 0x000000ff) >> 0); + WRITE (image, pixel++, (val & 0x0000ff00) >> 8); + WRITE (image, pixel++, (val & 0x00ff0000) >> 16); +#else + WRITE (image, pixel++, (val & 0x00ff0000) >> 16); + WRITE (image, pixel++, (val & 0x0000ff00) >> 8); + WRITE (image, pixel++, (val & 0x000000ff) >> 0); +#endif + } +} + +static void +store_scanline_r5g6b5 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint16_t *pixel = ((uint16_t *) bits) + x; + int i; + + for (i = 0; i < width; ++i) + { + uint32_t s = values[i]; + + WRITE (image, pixel++, + ((s >> 3) & 0x001f) | + ((s >> 5) & 0x07e0) | + ((s >> 8) & 0xf800)); + } +} + +static void +store_scanline_b5g6r5 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint16_t *pixel = ((uint16_t *) bits) + x; + int i; + + for (i = 0; i < width; ++i) + { + SPLIT (values[i]); + + WRITE (image, pixel++, + ((b << 8) & 0xf800) | + ((g << 3) & 0x07e0) | + ((r >> 3) )); + } +} + +static void +store_scanline_a1r5g5b5 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint16_t *pixel = ((uint16_t *) bits) + x; + int i; + + for (i = 0; i < width; ++i) + { + SPLIT_A (values[i]); + + WRITE (image, pixel++, + ((a << 8) & 0x8000) | + ((r << 7) & 0x7c00) | + ((g << 2) & 0x03e0) | + ((b >> 3) )); + } +} + +static void +store_scanline_x1r5g5b5 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint16_t *pixel = ((uint16_t *) bits) + x; + int i; + + for (i = 0; i < width; ++i) + { + SPLIT (values[i]); + + WRITE (image, pixel++, + ((r << 7) & 0x7c00) | + ((g << 2) & 0x03e0) | + ((b >> 3) )); + } +} + +static void +store_scanline_a1b5g5r5 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint16_t *pixel = ((uint16_t *) bits) + x; + int i; + + for (i = 0; i < width; ++i) + { + SPLIT_A (values[i]); + + WRITE (image, pixel++, + ((a << 8) & 0x8000) | + ((b << 7) & 0x7c00) | + ((g << 2) & 0x03e0) | + ((r >> 3) )); + } +} + +static void +store_scanline_x1b5g5r5 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint16_t *pixel = ((uint16_t *) bits) + x; + int i; + + for (i = 0; i < width; ++i) + { + SPLIT (values[i]); + + WRITE (image, pixel++, ((b << 7) & 0x7c00) | + ((g << 2) & 0x03e0) | + ((r >> 3) )); + } +} + +static void +store_scanline_a4r4g4b4 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint16_t *pixel = ((uint16_t *) bits) + x; + int i; + + for (i = 0; i < width; ++i) + { + SPLIT_A (values[i]); + + WRITE (image, pixel++, + ((a << 8) & 0xf000) | + ((r << 4) & 0x0f00) | + ((g ) & 0x00f0) | + ((b >> 4) )); + } +} + +static void +store_scanline_x4r4g4b4 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint16_t *pixel = ((uint16_t *) bits) + x; + int i; + + for (i = 0; i < width; ++i) + { + SPLIT (values[i]); + + WRITE (image, pixel++, + ((r << 4) & 0x0f00) | + ((g ) & 0x00f0) | + ((b >> 4) )); + } +} + +static void +store_scanline_a4b4g4r4 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint16_t *pixel = ((uint16_t *) bits) + x; + int i; + + for (i = 0; i < width; ++i) + { + SPLIT_A (values[i]); + WRITE (image, pixel++, ((a << 8) & 0xf000) | + ((b << 4) & 0x0f00) | + ((g ) & 0x00f0) | + ((r >> 4) )); + } +} + +static void +store_scanline_x4b4g4r4 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint16_t *pixel = ((uint16_t *) bits) + x; + int i; + + for (i = 0; i < width; ++i) + { + SPLIT (values[i]); + + WRITE (image, pixel++, + ((b << 4) & 0x0f00) | + ((g ) & 0x00f0) | + ((r >> 4) )); + } +} + +static void +store_scanline_a8 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint8_t *pixel = ((uint8_t *) bits) + x; + int i; + + for (i = 0; i < width; ++i) + { + WRITE (image, pixel++, values[i] >> 24); + } +} + +static void +store_scanline_r3g3b2 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint8_t *pixel = ((uint8_t *) bits) + x; + int i; + + for (i = 0; i < width; ++i) + { + SPLIT (values[i]); + + WRITE (image, pixel++, + ((r ) & 0xe0) | + ((g >> 3) & 0x1c) | + ((b >> 6) )); + } +} + +static void +store_scanline_b2g3r3 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint8_t *pixel = ((uint8_t *) bits) + x; + int i; + + for (i = 0; i < width; ++i) + { + SPLIT (values[i]); + + WRITE (image, pixel++, + ((b ) & 0xc0) | + ((g >> 2) & 0x38) | + ((r >> 5) )); + } +} + +static void +store_scanline_a2r2g2b2 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint8_t *pixel = ((uint8_t *) bits) + x; + int i; + + for (i = 0; i < width; ++i) + { + SPLIT_A (values[i]); + + WRITE (image, pixel++, + ((a ) & 0xc0) | + ((r >> 2) & 0x30) | + ((g >> 4) & 0x0c) | + ((b >> 6) )); + } +} + +static void +store_scanline_a2b2g2r2 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint8_t *pixel = ((uint8_t *) bits) + x; + int i; + + for (i = 0; i < width; ++i) + { + SPLIT_A (values[i]); + + WRITE (image, pixel++, + ((a ) & 0xc0) | + ((b >> 2) & 0x30) | + ((g >> 4) & 0x0c) | + ((r >> 6) )); + } +} + +static void +store_scanline_c8 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint8_t *pixel = ((uint8_t *) bits) + x; + const pixman_indexed_t *indexed = image->indexed; + int i; + + for (i = 0; i < width; ++i) + WRITE (image, pixel++, RGB24_TO_ENTRY (indexed,values[i])); +} + +static void +store_scanline_g8 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint8_t *pixel = ((uint8_t *) bits) + x; + const pixman_indexed_t *indexed = image->indexed; + int i; + + for (i = 0; i < width; ++i) + WRITE (image, pixel++, RGB24_TO_ENTRY_Y (indexed,values[i])); +} + +static void +store_scanline_x4a4 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint8_t *pixel = ((uint8_t *) bits) + x; + int i; + + for (i = 0; i < width; ++i) + WRITE (image, pixel++, values[i] >> 28); +} + +#define STORE_8(img,l,o,v) (WRITE (img, (uint8_t *)(l) + ((o) >> 3), (v))) +#ifdef WORDS_BIGENDIAN + +#define STORE_4(img,l,o,v) \ + do \ + { \ + int bo = 4 * (o); \ + int v4 = (v) & 0x0f; \ + \ + STORE_8 (img, l, bo, ( \ + bo & 4 ? \ + (FETCH_8 (img, l, bo) & 0xf0) | (v4) : \ + (FETCH_8 (img, l, bo) & 0x0f) | (v4 << 4))); \ + } while (0) +#else + +#define STORE_4(img,l,o,v) \ + do \ + { \ + int bo = 4 * (o); \ + int v4 = (v) & 0x0f; \ + \ + STORE_8 (img, l, bo, ( \ + bo & 4 ? \ + (FETCH_8 (img, l, bo) & 0x0f) | (v4 << 4) : \ + (FETCH_8 (img, l, bo) & 0xf0) | (v4))); \ + } while (0) +#endif + +static void +store_scanline_a4 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *bits = image->bits + image->rowstride * y; + int i; + + for (i = 0; i < width; ++i) + STORE_4 (image, bits, i + x, values[i] >> 28); +} + +static void +store_scanline_r1g2b1 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *bits = image->bits + image->rowstride * y; + int i; + + for (i = 0; i < width; ++i) + { + uint32_t pixel; + + SPLIT (values[i]); + pixel = (((r >> 4) & 0x8) | + ((g >> 5) & 0x6) | + ((b >> 7) )); + STORE_4 (image, bits, i + x, pixel); + } +} + +static void +store_scanline_b1g2r1 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *bits = image->bits + image->rowstride * y; + int i; + + for (i = 0; i < width; ++i) + { + uint32_t pixel; + + SPLIT (values[i]); + pixel = (((b >> 4) & 0x8) | + ((g >> 5) & 0x6) | + ((r >> 7) )); + STORE_4 (image, bits, i + x, pixel); + } +} + +static void +store_scanline_a1r1g1b1 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *bits = image->bits + image->rowstride * y; + int i; + + for (i = 0; i < width; ++i) + { + uint32_t pixel; + + SPLIT_A (values[i]); + pixel = (((a >> 4) & 0x8) | + ((r >> 5) & 0x4) | + ((g >> 6) & 0x2) | + ((b >> 7) )); + + STORE_4 (image, bits, i + x, pixel); + } +} + +static void +store_scanline_a1b1g1r1 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *bits = image->bits + image->rowstride * y; + int i; + + for (i = 0; i < width; ++i) + { + uint32_t pixel; + + SPLIT_A (values[i]); + pixel = (((a >> 4) & 0x8) | + ((b >> 5) & 0x4) | + ((g >> 6) & 0x2) | + ((r >> 7) )); + + STORE_4 (image, bits, i + x, pixel); + } +} + +static void +store_scanline_c4 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *bits = image->bits + image->rowstride * y; + const pixman_indexed_t *indexed = image->indexed; + int i; + + for (i = 0; i < width; ++i) + { + uint32_t pixel; + + pixel = RGB24_TO_ENTRY (indexed, values[i]); + STORE_4 (image, bits, i + x, pixel); + } +} + +static void +store_scanline_g4 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *bits = image->bits + image->rowstride * y; + const pixman_indexed_t *indexed = image->indexed; + int i; + + for (i = 0; i < width; ++i) + { + uint32_t pixel; + + pixel = RGB24_TO_ENTRY_Y (indexed, values[i]); + STORE_4 (image, bits, i + x, pixel); + } +} + +static void +store_scanline_a1 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *bits = image->bits + image->rowstride * y; + int i; + + for (i = 0; i < width; ++i) + { + uint32_t *pixel = ((uint32_t *) bits) + ((i + x) >> 5); + uint32_t mask, v; + +#ifdef WORDS_BIGENDIAN + mask = 1 << (0x1f - ((i + x) & 0x1f)); +#else + mask = 1 << ((i + x) & 0x1f); +#endif + v = values[i] & 0x80000000 ? mask : 0; + + WRITE (image, pixel, (READ (image, pixel) & ~mask) | v); + } +} + +static void +store_scanline_g1 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *bits = image->bits + image->rowstride * y; + const pixman_indexed_t *indexed = image->indexed; + int i; + + for (i = 0; i < width; ++i) + { + uint32_t *pixel = ((uint32_t *) bits) + ((i + x) >> 5); + uint32_t mask, v; + +#ifdef WORDS_BIGENDIAN + mask = 1 << (0x1f - ((i + x) & 0x1f)); +#else + mask = 1 << ((i + x) & 0x1f); +#endif + v = RGB24_TO_ENTRY_Y (indexed, values[i]) & 0x1 ? mask : 0; + + WRITE (image, pixel, (READ (image, pixel) & ~mask) | v); + } +} + +/* + * Contracts a 64bpp image to 32bpp and then stores it using a regular 32-bit + * store proc. Despite the type, this function expects a uint64_t buffer. + */ +static void +store_scanline_generic_64 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *argb8_pixels; + + assert (image->common.type == BITS); + + argb8_pixels = pixman_malloc_ab (width, sizeof(uint32_t)); + if (!argb8_pixels) + return; + + /* Contract the scanline. We could do this in place if values weren't + * const. + */ + pixman_contract (argb8_pixels, (uint64_t *)values, width); + + image->store_scanline_32 (image, x, y, width, argb8_pixels); + + free (argb8_pixels); +} + +/* Despite the type, this function expects both buffer + * and mask to be uint64_t + */ +static void +fetch_scanline_generic_64 (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + pixman_format_code_t format; + + /* Fetch the pixels into the first half of buffer and then expand them in + * place. + */ + image->bits.fetch_scanline_32 (image, x, y, width, buffer, NULL); + + format = image->bits.format; + if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR || + PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_GRAY) + { + /* Indexed formats are mapped to a8r8g8b8 with full + * precision, so when expanding we shouldn't correct + * for the width of the channels + */ + + format = PIXMAN_a8r8g8b8; + } + + pixman_expand ((uint64_t *)buffer, buffer, format, width); +} + +/* Despite the type, this function expects a uint64_t *buffer */ +static uint64_t +fetch_pixel_generic_64 (bits_image_t *image, + int offset, + int line) +{ + uint32_t pixel32 = image->fetch_pixel_32 (image, offset, line); + uint64_t result; + pixman_format_code_t format; + + format = image->format; + if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR || + PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_GRAY) + { + /* Indexed formats are mapped to a8r8g8b8 with full + * precision, so when expanding we shouldn't correct + * for the width of the channels + */ + + format = PIXMAN_a8r8g8b8; + } + + pixman_expand ((uint64_t *)&result, &pixel32, format, 1); + + return result; +} + +/* + * XXX: The transformed fetch path only works at 32-bpp so far. When all + * paths have wide versions, this can be removed. + * + * WARNING: This function loses precision! + */ +static uint32_t +fetch_pixel_generic_lossy_32 (bits_image_t *image, + int offset, + int line) +{ + uint64_t pixel64 = image->fetch_pixel_64 (image, offset, line); + uint32_t result; + + pixman_contract (&result, &pixel64, 1); + + return result; +} + +typedef struct +{ + pixman_format_code_t format; + fetch_scanline_t fetch_scanline_32; + fetch_scanline_t fetch_scanline_64; + fetch_pixel_32_t fetch_pixel_32; + fetch_pixel_64_t fetch_pixel_64; + store_scanline_t store_scanline_32; + store_scanline_t store_scanline_64; +} format_info_t; + +#define FORMAT_INFO(format) \ + { \ + PIXMAN_ ## format, \ + fetch_scanline_ ## format, \ + fetch_scanline_generic_64, \ + fetch_pixel_ ## format, fetch_pixel_generic_64, \ + store_scanline_ ## format, store_scanline_generic_64 \ + } + +static const format_info_t accessors[] = +{ +/* 32 bpp formats */ + FORMAT_INFO (a8r8g8b8), + FORMAT_INFO (x8r8g8b8), + FORMAT_INFO (a8b8g8r8), + FORMAT_INFO (x8b8g8r8), + FORMAT_INFO (b8g8r8a8), + FORMAT_INFO (b8g8r8x8), + FORMAT_INFO (r8g8b8a8), + FORMAT_INFO (r8g8b8x8), + FORMAT_INFO (x14r6g6b6), + +/* 24bpp formats */ + FORMAT_INFO (r8g8b8), + FORMAT_INFO (b8g8r8), + +/* 16bpp formats */ + FORMAT_INFO (r5g6b5), + FORMAT_INFO (b5g6r5), + + FORMAT_INFO (a1r5g5b5), + FORMAT_INFO (x1r5g5b5), + FORMAT_INFO (a1b5g5r5), + FORMAT_INFO (x1b5g5r5), + FORMAT_INFO (a4r4g4b4), + FORMAT_INFO (x4r4g4b4), + FORMAT_INFO (a4b4g4r4), + FORMAT_INFO (x4b4g4r4), + +/* 8bpp formats */ + FORMAT_INFO (a8), + FORMAT_INFO (r3g3b2), + FORMAT_INFO (b2g3r3), + FORMAT_INFO (a2r2g2b2), + FORMAT_INFO (a2b2g2r2), + + FORMAT_INFO (c8), + +#define fetch_scanline_g8 fetch_scanline_c8 +#define fetch_pixel_g8 fetch_pixel_c8 + FORMAT_INFO (g8), + +#define fetch_scanline_x4c4 fetch_scanline_c8 +#define fetch_pixel_x4c4 fetch_pixel_c8 +#define store_scanline_x4c4 store_scanline_c8 + FORMAT_INFO (x4c4), + +#define fetch_scanline_x4g4 fetch_scanline_c8 +#define fetch_pixel_x4g4 fetch_pixel_c8 +#define store_scanline_x4g4 store_scanline_g8 + FORMAT_INFO (x4g4), + + FORMAT_INFO (x4a4), + +/* 4bpp formats */ + FORMAT_INFO (a4), + FORMAT_INFO (r1g2b1), + FORMAT_INFO (b1g2r1), + FORMAT_INFO (a1r1g1b1), + FORMAT_INFO (a1b1g1r1), + + FORMAT_INFO (c4), + +#define fetch_scanline_g4 fetch_scanline_c4 +#define fetch_pixel_g4 fetch_pixel_c4 + FORMAT_INFO (g4), + +/* 1bpp formats */ + FORMAT_INFO (a1), + FORMAT_INFO (g1), + +/* Wide formats */ + + { PIXMAN_a2r10g10b10, + NULL, fetch_scanline_a2r10g10b10, + fetch_pixel_generic_lossy_32, fetch_pixel_a2r10g10b10, + NULL, store_scanline_a2r10g10b10 }, + + { PIXMAN_x2r10g10b10, + NULL, fetch_scanline_x2r10g10b10, + fetch_pixel_generic_lossy_32, fetch_pixel_x2r10g10b10, + NULL, store_scanline_x2r10g10b10 }, + + { PIXMAN_a2b10g10r10, + NULL, fetch_scanline_a2b10g10r10, + fetch_pixel_generic_lossy_32, fetch_pixel_a2b10g10r10, + NULL, store_scanline_a2b10g10r10 }, + + { PIXMAN_x2b10g10r10, + NULL, fetch_scanline_x2b10g10r10, + fetch_pixel_generic_lossy_32, fetch_pixel_x2b10g10r10, + NULL, store_scanline_x2b10g10r10 }, + +/* YUV formats */ + { PIXMAN_yuy2, + fetch_scanline_yuy2, fetch_scanline_generic_64, + fetch_pixel_yuy2, fetch_pixel_generic_64, + NULL, NULL }, + + { PIXMAN_yv12, + fetch_scanline_yv12, fetch_scanline_generic_64, + fetch_pixel_yv12, fetch_pixel_generic_64, + NULL, NULL }, + + { PIXMAN_null }, +}; + +static void +setup_accessors (bits_image_t *image) +{ + const format_info_t *info = accessors; + + while (info->format != PIXMAN_null) + { + if (info->format == image->format) + { + image->fetch_scanline_32 = info->fetch_scanline_32; + image->fetch_scanline_64 = info->fetch_scanline_64; + image->fetch_pixel_32 = info->fetch_pixel_32; + image->fetch_pixel_64 = info->fetch_pixel_64; + image->store_scanline_32 = info->store_scanline_32; + image->store_scanline_64 = info->store_scanline_64; + + return; + } + + info++; + } +} + +#ifndef PIXMAN_FB_ACCESSORS +void +_pixman_bits_image_setup_accessors_accessors (bits_image_t *image); + +void +_pixman_bits_image_setup_accessors (bits_image_t *image) +{ + if (image->read_func || image->write_func) + _pixman_bits_image_setup_accessors_accessors (image); + else + setup_accessors (image); +} + +#else + +void +_pixman_bits_image_setup_accessors_accessors (bits_image_t *image) +{ + setup_accessors (image); +} + +#endif diff --git a/pixman/pixman/pixman.c b/pixman/pixman/pixman.c index 8b24849af..f21af2f36 100644 --- a/pixman/pixman/pixman.c +++ b/pixman/pixman/pixman.c @@ -1,1211 +1,1217 @@ -/* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */ -/* - * Copyright © 2000 SuSE, Inc. - * Copyright © 2007 Red Hat, Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of SuSE not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. SuSE makes no representations about the - * suitability of this software for any purpose. It is provided "as is" - * without express or implied warranty. - * - * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE - * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Author: Keith Packard, SuSE, Inc. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif -#include "pixman-private.h" - -#include - -static pixman_implementation_t *global_implementation; - -#ifdef TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR -static void __attribute__((constructor)) -pixman_constructor (void) -{ - global_implementation = _pixman_choose_implementation (); -} -#endif - -static force_inline pixman_implementation_t * -get_implementation (void) -{ -#ifndef TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR - if (!global_implementation) - global_implementation = _pixman_choose_implementation (); -#endif - return global_implementation; -} - -typedef struct operator_info_t operator_info_t; - -struct operator_info_t -{ - uint8_t opaque_info[4]; -}; - -#define PACK(neither, src, dest, both) \ - {{ (uint8_t)PIXMAN_OP_ ## neither, \ - (uint8_t)PIXMAN_OP_ ## src, \ - (uint8_t)PIXMAN_OP_ ## dest, \ - (uint8_t)PIXMAN_OP_ ## both }} - -static const operator_info_t operator_table[] = -{ - /* Neither Opaque Src Opaque Dst Opaque Both Opaque */ - PACK (CLEAR, CLEAR, CLEAR, CLEAR), - PACK (SRC, SRC, SRC, SRC), - PACK (DST, DST, DST, DST), - PACK (OVER, SRC, OVER, SRC), - PACK (OVER_REVERSE, OVER_REVERSE, DST, DST), - PACK (IN, IN, SRC, SRC), - PACK (IN_REVERSE, DST, IN_REVERSE, DST), - PACK (OUT, OUT, CLEAR, CLEAR), - PACK (OUT_REVERSE, CLEAR, OUT_REVERSE, CLEAR), - PACK (ATOP, IN, OVER, SRC), - PACK (ATOP_REVERSE, OVER_REVERSE, IN_REVERSE, DST), - PACK (XOR, OUT, OUT_REVERSE, CLEAR), - PACK (ADD, ADD, ADD, ADD), - PACK (SATURATE, OVER_REVERSE, DST, DST), - - {{ 0 /* 0x0e */ }}, - {{ 0 /* 0x0f */ }}, - - PACK (CLEAR, CLEAR, CLEAR, CLEAR), - PACK (SRC, SRC, SRC, SRC), - PACK (DST, DST, DST, DST), - PACK (DISJOINT_OVER, DISJOINT_OVER, DISJOINT_OVER, DISJOINT_OVER), - PACK (DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE), - PACK (DISJOINT_IN, DISJOINT_IN, DISJOINT_IN, DISJOINT_IN), - PACK (DISJOINT_IN_REVERSE, DISJOINT_IN_REVERSE, DISJOINT_IN_REVERSE, DISJOINT_IN_REVERSE), - PACK (DISJOINT_OUT, DISJOINT_OUT, DISJOINT_OUT, DISJOINT_OUT), - PACK (DISJOINT_OUT_REVERSE, DISJOINT_OUT_REVERSE, DISJOINT_OUT_REVERSE, DISJOINT_OUT_REVERSE), - PACK (DISJOINT_ATOP, DISJOINT_ATOP, DISJOINT_ATOP, DISJOINT_ATOP), - PACK (DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE), - PACK (DISJOINT_XOR, DISJOINT_XOR, DISJOINT_XOR, DISJOINT_XOR), - - {{ 0 /* 0x1c */ }}, - {{ 0 /* 0x1d */ }}, - {{ 0 /* 0x1e */ }}, - {{ 0 /* 0x1f */ }}, - - PACK (CLEAR, CLEAR, CLEAR, CLEAR), - PACK (SRC, SRC, SRC, SRC), - PACK (DST, DST, DST, DST), - PACK (CONJOINT_OVER, CONJOINT_OVER, CONJOINT_OVER, CONJOINT_OVER), - PACK (CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE), - PACK (CONJOINT_IN, CONJOINT_IN, CONJOINT_IN, CONJOINT_IN), - PACK (CONJOINT_IN_REVERSE, CONJOINT_IN_REVERSE, CONJOINT_IN_REVERSE, CONJOINT_IN_REVERSE), - PACK (CONJOINT_OUT, CONJOINT_OUT, CONJOINT_OUT, CONJOINT_OUT), - PACK (CONJOINT_OUT_REVERSE, CONJOINT_OUT_REVERSE, CONJOINT_OUT_REVERSE, CONJOINT_OUT_REVERSE), - PACK (CONJOINT_ATOP, CONJOINT_ATOP, CONJOINT_ATOP, CONJOINT_ATOP), - PACK (CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE), - PACK (CONJOINT_XOR, CONJOINT_XOR, CONJOINT_XOR, CONJOINT_XOR), - - {{ 0 /* 0x2c */ }}, - {{ 0 /* 0x2d */ }}, - {{ 0 /* 0x2e */ }}, - {{ 0 /* 0x2f */ }}, - - PACK (MULTIPLY, MULTIPLY, MULTIPLY, MULTIPLY), - PACK (SCREEN, SCREEN, SCREEN, SCREEN), - PACK (OVERLAY, OVERLAY, OVERLAY, OVERLAY), - PACK (DARKEN, DARKEN, DARKEN, DARKEN), - PACK (LIGHTEN, LIGHTEN, LIGHTEN, LIGHTEN), - PACK (COLOR_DODGE, COLOR_DODGE, COLOR_DODGE, COLOR_DODGE), - PACK (COLOR_BURN, COLOR_BURN, COLOR_BURN, COLOR_BURN), - PACK (HARD_LIGHT, HARD_LIGHT, HARD_LIGHT, HARD_LIGHT), - PACK (SOFT_LIGHT, SOFT_LIGHT, SOFT_LIGHT, SOFT_LIGHT), - PACK (DIFFERENCE, DIFFERENCE, DIFFERENCE, DIFFERENCE), - PACK (EXCLUSION, EXCLUSION, EXCLUSION, EXCLUSION), - PACK (HSL_HUE, HSL_HUE, HSL_HUE, HSL_HUE), - PACK (HSL_SATURATION, HSL_SATURATION, HSL_SATURATION, HSL_SATURATION), - PACK (HSL_COLOR, HSL_COLOR, HSL_COLOR, HSL_COLOR), - PACK (HSL_LUMINOSITY, HSL_LUMINOSITY, HSL_LUMINOSITY, HSL_LUMINOSITY), -}; - -/* - * Optimize the current operator based on opacity of source or destination - * The output operator should be mathematically equivalent to the source. - */ -static pixman_op_t -optimize_operator (pixman_op_t op, - uint32_t src_flags, - uint32_t mask_flags, - uint32_t dst_flags) -{ - pixman_bool_t is_source_opaque, is_dest_opaque; - -#define OPAQUE_SHIFT 13 - - COMPILE_TIME_ASSERT (FAST_PATH_IS_OPAQUE == (1 << OPAQUE_SHIFT)); - - is_dest_opaque = (dst_flags & FAST_PATH_IS_OPAQUE); - is_source_opaque = ((src_flags & mask_flags) & FAST_PATH_IS_OPAQUE); - - is_dest_opaque >>= OPAQUE_SHIFT - 1; - is_source_opaque >>= OPAQUE_SHIFT; - - return operator_table[op].opaque_info[is_dest_opaque | is_source_opaque]; -} - -/* - * Computing composite region - */ -static inline pixman_bool_t -clip_general_image (pixman_region32_t * region, - pixman_region32_t * clip, - int dx, - int dy) -{ - if (pixman_region32_n_rects (region) == 1 && - pixman_region32_n_rects (clip) == 1) - { - pixman_box32_t * rbox = pixman_region32_rectangles (region, NULL); - pixman_box32_t * cbox = pixman_region32_rectangles (clip, NULL); - int v; - - if (rbox->x1 < (v = cbox->x1 + dx)) - rbox->x1 = v; - if (rbox->x2 > (v = cbox->x2 + dx)) - rbox->x2 = v; - if (rbox->y1 < (v = cbox->y1 + dy)) - rbox->y1 = v; - if (rbox->y2 > (v = cbox->y2 + dy)) - rbox->y2 = v; - if (rbox->x1 >= rbox->x2 || rbox->y1 >= rbox->y2) - { - pixman_region32_init (region); - return FALSE; - } - } - else if (!pixman_region32_not_empty (clip)) - { - return FALSE; - } - else - { - if (dx || dy) - pixman_region32_translate (region, -dx, -dy); - - if (!pixman_region32_intersect (region, region, clip)) - return FALSE; - - if (dx || dy) - pixman_region32_translate (region, dx, dy); - } - - return pixman_region32_not_empty (region); -} - -static inline pixman_bool_t -clip_source_image (pixman_region32_t * region, - pixman_image_t * image, - int dx, - int dy) -{ - /* Source clips are ignored, unless they are explicitly turned on - * and the clip in question was set by an X client. (Because if - * the clip was not set by a client, then it is a hierarchy - * clip and those should always be ignored for sources). - */ - if (!image->common.clip_sources || !image->common.client_clip) - return TRUE; - - return clip_general_image (region, - &image->common.clip_region, - dx, dy); -} - -/* - * returns FALSE if the final region is empty. Indistinguishable from - * an allocation failure, but rendering ignores those anyways. - */ -static pixman_bool_t -pixman_compute_composite_region32 (pixman_region32_t * region, - pixman_image_t * src_image, - pixman_image_t * mask_image, - pixman_image_t * dst_image, - int32_t src_x, - int32_t src_y, - int32_t mask_x, - int32_t mask_y, - int32_t dest_x, - int32_t dest_y, - int32_t width, - int32_t height) -{ - region->extents.x1 = dest_x; - region->extents.x2 = dest_x + width; - region->extents.y1 = dest_y; - region->extents.y2 = dest_y + height; - - region->extents.x1 = MAX (region->extents.x1, 0); - region->extents.y1 = MAX (region->extents.y1, 0); - region->extents.x2 = MIN (region->extents.x2, dst_image->bits.width); - region->extents.y2 = MIN (region->extents.y2, dst_image->bits.height); - - region->data = 0; - - /* Check for empty operation */ - if (region->extents.x1 >= region->extents.x2 || - region->extents.y1 >= region->extents.y2) - { - region->extents.x1 = 0; - region->extents.x2 = 0; - region->extents.y1 = 0; - region->extents.y2 = 0; - return FALSE; - } - - if (dst_image->common.have_clip_region) - { - if (!clip_general_image (region, &dst_image->common.clip_region, 0, 0)) - return FALSE; - } - - if (dst_image->common.alpha_map) - { - if (!pixman_region32_intersect_rect (region, region, - dst_image->common.alpha_origin_x, - dst_image->common.alpha_origin_y, - dst_image->common.alpha_map->width, - dst_image->common.alpha_map->height)) - { - return FALSE; - } - if (!pixman_region32_not_empty (region)) - return FALSE; - if (dst_image->common.alpha_map->common.have_clip_region) - { - if (!clip_general_image (region, &dst_image->common.alpha_map->common.clip_region, - -dst_image->common.alpha_origin_x, - -dst_image->common.alpha_origin_y)) - { - return FALSE; - } - } - } - - /* clip against src */ - if (src_image->common.have_clip_region) - { - if (!clip_source_image (region, src_image, dest_x - src_x, dest_y - src_y)) - return FALSE; - } - if (src_image->common.alpha_map && src_image->common.alpha_map->common.have_clip_region) - { - if (!clip_source_image (region, (pixman_image_t *)src_image->common.alpha_map, - dest_x - (src_x - src_image->common.alpha_origin_x), - dest_y - (src_y - src_image->common.alpha_origin_y))) - { - return FALSE; - } - } - /* clip against mask */ - if (mask_image && mask_image->common.have_clip_region) - { - if (!clip_source_image (region, mask_image, dest_x - mask_x, dest_y - mask_y)) - return FALSE; - - if (mask_image->common.alpha_map && mask_image->common.alpha_map->common.have_clip_region) - { - if (!clip_source_image (region, (pixman_image_t *)mask_image->common.alpha_map, - dest_x - (mask_x - mask_image->common.alpha_origin_x), - dest_y - (mask_y - mask_image->common.alpha_origin_y))) - { - return FALSE; - } - } - } - - return TRUE; -} - -#define N_CACHED_FAST_PATHS 8 - -typedef struct -{ - struct - { - pixman_implementation_t * imp; - pixman_fast_path_t fast_path; - } cache [N_CACHED_FAST_PATHS]; -} cache_t; - -PIXMAN_DEFINE_THREAD_LOCAL (cache_t, fast_path_cache); - -static force_inline pixman_bool_t -lookup_composite_function (pixman_op_t op, - pixman_format_code_t src_format, - uint32_t src_flags, - pixman_format_code_t mask_format, - uint32_t mask_flags, - pixman_format_code_t dest_format, - uint32_t dest_flags, - pixman_implementation_t **out_imp, - pixman_composite_func_t *out_func) -{ - pixman_implementation_t *imp; - cache_t *cache; - int i; - - /* Check cache for fast paths */ - cache = PIXMAN_GET_THREAD_LOCAL (fast_path_cache); - - for (i = 0; i < N_CACHED_FAST_PATHS; ++i) - { - const pixman_fast_path_t *info = &(cache->cache[i].fast_path); - - /* Note that we check for equality here, not whether - * the cached fast path matches. This is to prevent - * us from selecting an overly general fast path - * when a more specific one would work. - */ - if (info->op == op && - info->src_format == src_format && - info->mask_format == mask_format && - info->dest_format == dest_format && - info->src_flags == src_flags && - info->mask_flags == mask_flags && - info->dest_flags == dest_flags && - info->func) - { - *out_imp = cache->cache[i].imp; - *out_func = cache->cache[i].fast_path.func; - - goto update_cache; - } - } - - for (imp = get_implementation (); imp != NULL; imp = imp->delegate) - { - const pixman_fast_path_t *info = imp->fast_paths; - - while (info->op != PIXMAN_OP_NONE) - { - if ((info->op == op || info->op == PIXMAN_OP_any) && - /* Formats */ - ((info->src_format == src_format) || - (info->src_format == PIXMAN_any)) && - ((info->mask_format == mask_format) || - (info->mask_format == PIXMAN_any)) && - ((info->dest_format == dest_format) || - (info->dest_format == PIXMAN_any)) && - /* Flags */ - (info->src_flags & src_flags) == info->src_flags && - (info->mask_flags & mask_flags) == info->mask_flags && - (info->dest_flags & dest_flags) == info->dest_flags) - { - *out_imp = imp; - *out_func = info->func; - - /* Set i to the last spot in the cache so that the - * move-to-front code below will work - */ - i = N_CACHED_FAST_PATHS - 1; - - goto update_cache; - } - - ++info; - } - } - return FALSE; - -update_cache: - if (i) - { - while (i--) - cache->cache[i + 1] = cache->cache[i]; - - cache->cache[0].imp = *out_imp; - cache->cache[0].fast_path.op = op; - cache->cache[0].fast_path.src_format = src_format; - cache->cache[0].fast_path.src_flags = src_flags; - cache->cache[0].fast_path.mask_format = mask_format; - cache->cache[0].fast_path.mask_flags = mask_flags; - cache->cache[0].fast_path.dest_format = dest_format; - cache->cache[0].fast_path.dest_flags = dest_flags; - cache->cache[0].fast_path.func = *out_func; - } - - return TRUE; -} - -static pixman_bool_t -compute_sample_extents (pixman_transform_t *transform, - pixman_box32_t *extents, int x, int y, - pixman_fixed_t x_off, pixman_fixed_t y_off, - pixman_fixed_t width, pixman_fixed_t height) -{ - pixman_fixed_t x1, y1, x2, y2; - pixman_fixed_48_16_t tx1, ty1, tx2, ty2; - - /* We have checked earlier that (extents->x1 - x) etc. fit in a pixman_fixed_t */ - x1 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->x1 - x) + pixman_fixed_1 / 2; - y1 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->y1 - y) + pixman_fixed_1 / 2; - x2 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->x2 - x) - pixman_fixed_1 / 2; - y2 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->y2 - y) - pixman_fixed_1 / 2; - - if (!transform) - { - tx1 = (pixman_fixed_48_16_t)x1; - ty1 = (pixman_fixed_48_16_t)y1; - tx2 = (pixman_fixed_48_16_t)x2; - ty2 = (pixman_fixed_48_16_t)y2; - } - else - { - int i; - - /* Silence GCC */ - tx1 = ty1 = tx2 = ty2 = 0; - - for (i = 0; i < 4; ++i) - { - pixman_fixed_48_16_t tx, ty; - pixman_vector_t v; - - v.vector[0] = (i & 0x01)? x1 : x2; - v.vector[1] = (i & 0x02)? y1 : y2; - v.vector[2] = pixman_fixed_1; - - if (!pixman_transform_point (transform, &v)) - return FALSE; - - tx = (pixman_fixed_48_16_t)v.vector[0]; - ty = (pixman_fixed_48_16_t)v.vector[1]; - - if (i == 0) - { - tx1 = tx; - ty1 = ty; - tx2 = tx; - ty2 = ty; - } - else - { - if (tx < tx1) - tx1 = tx; - if (ty < ty1) - ty1 = ty; - if (tx > tx2) - tx2 = tx; - if (ty > ty2) - ty2 = ty; - } - } - } - - /* Expand the source area by a tiny bit so account of different rounding that - * may happen during sampling. Note that (8 * pixman_fixed_e) is very far from - * 0.5 so this won't cause the area computed to be overly pessimistic. - */ - tx1 += x_off - 8 * pixman_fixed_e; - ty1 += y_off - 8 * pixman_fixed_e; - tx2 += x_off + width + 8 * pixman_fixed_e; - ty2 += y_off + height + 8 * pixman_fixed_e; - - if (tx1 < pixman_min_fixed_48_16 || tx1 > pixman_max_fixed_48_16 || - ty1 < pixman_min_fixed_48_16 || ty1 > pixman_max_fixed_48_16 || - tx2 < pixman_min_fixed_48_16 || tx2 > pixman_max_fixed_48_16 || - ty2 < pixman_min_fixed_48_16 || ty2 > pixman_max_fixed_48_16) - { - return FALSE; - } - else - { - extents->x1 = pixman_fixed_to_int (tx1); - extents->y1 = pixman_fixed_to_int (ty1); - extents->x2 = pixman_fixed_to_int (tx2) + 1; - extents->y2 = pixman_fixed_to_int (ty2) + 1; - - return TRUE; - } -} - -#define IS_16BIT(x) (((x) >= INT16_MIN) && ((x) <= INT16_MAX)) - -static pixman_bool_t -analyze_extent (pixman_image_t *image, int x, int y, - const pixman_box32_t *extents, uint32_t *flags) -{ - pixman_transform_t *transform; - pixman_fixed_t *params; - pixman_fixed_t x_off, y_off; - pixman_fixed_t width, height; - pixman_box32_t ex; - - if (!image) - return TRUE; - - /* Some compositing functions walk one step - * outside the destination rectangle, so we - * check here that the expanded-by-one source - * extents in destination space fits in 16 bits - */ - if (!IS_16BIT (extents->x1 - x - 1) || - !IS_16BIT (extents->y1 - y - 1) || - !IS_16BIT (extents->x2 - x + 1) || - !IS_16BIT (extents->y2 - y + 1)) - { - return FALSE; - } - - transform = image->common.transform; - if (image->common.type == BITS) - { - /* During repeat mode calculations we might convert the - * width/height of an image to fixed 16.16, so we need - * them to be smaller than 16 bits. - */ - if (image->bits.width >= 0x7fff || image->bits.height >= 0x7fff) - return FALSE; - -#define ID_AND_NEAREST (FAST_PATH_ID_TRANSFORM | FAST_PATH_NEAREST_FILTER) - - if ((image->common.flags & ID_AND_NEAREST) == ID_AND_NEAREST && - extents->x1 - x >= 0 && - extents->y1 - y >= 0 && - extents->x2 - x <= image->bits.width && - extents->y2 - y <= image->bits.height) - { - *flags |= FAST_PATH_SAMPLES_COVER_CLIP; - return TRUE; - } - - switch (image->common.filter) - { - case PIXMAN_FILTER_CONVOLUTION: - params = image->common.filter_params; - x_off = - pixman_fixed_e - ((params[0] - pixman_fixed_1) >> 1); - y_off = - pixman_fixed_e - ((params[1] - pixman_fixed_1) >> 1); - width = params[0]; - height = params[1]; - break; - - case PIXMAN_FILTER_GOOD: - case PIXMAN_FILTER_BEST: - case PIXMAN_FILTER_BILINEAR: - x_off = - pixman_fixed_1 / 2; - y_off = - pixman_fixed_1 / 2; - width = pixman_fixed_1; - height = pixman_fixed_1; - break; - - case PIXMAN_FILTER_FAST: - case PIXMAN_FILTER_NEAREST: - x_off = - pixman_fixed_e; - y_off = - pixman_fixed_e; - width = 0; - height = 0; - break; - - default: - return FALSE; - } - - /* Check whether the non-expanded, transformed extent is entirely within - * the source image, and set the FAST_PATH_SAMPLES_COVER_CLIP if it is. - */ - ex = *extents; - if (compute_sample_extents (transform, &ex, x, y, x_off, y_off, width, height) && - ex.x1 >= 0 && ex.y1 >= 0 && - ex.x2 <= image->bits.width && ex.y2 <= image->bits.height) - { - *flags |= FAST_PATH_SAMPLES_COVER_CLIP; - } - } - else - { - x_off = 0; - y_off = 0; - width = 0; - height = 0; - } - - /* Check that the extents expanded by one don't overflow. This ensures that - * compositing functions can simply walk the source space using 16.16 - * variables without worrying about overflow. - */ - ex.x1 = extents->x1 - 1; - ex.y1 = extents->y1 - 1; - ex.x2 = extents->x2 + 1; - ex.y2 = extents->y2 + 1; - - if (!compute_sample_extents (transform, &ex, x, y, x_off, y_off, width, height)) - return FALSE; - - return TRUE; -} - -/* - * Work around GCC bug causing crashes in Mozilla with SSE2 - * - * When using -msse, gcc generates movdqa instructions assuming that - * the stack is 16 byte aligned. Unfortunately some applications, such - * as Mozilla and Mono, end up aligning the stack to 4 bytes, which - * causes the movdqa instructions to fail. - * - * The __force_align_arg_pointer__ makes gcc generate a prologue that - * realigns the stack pointer to 16 bytes. - * - * On x86-64 this is not necessary because the standard ABI already - * calls for a 16 byte aligned stack. - * - * See https://bugs.freedesktop.org/show_bug.cgi?id=15693 - */ -#if defined (USE_SSE2) && defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__) -__attribute__((__force_align_arg_pointer__)) -#endif -PIXMAN_EXPORT void -pixman_image_composite32 (pixman_op_t op, - pixman_image_t * src, - pixman_image_t * mask, - pixman_image_t * dest, - int32_t src_x, - int32_t src_y, - int32_t mask_x, - int32_t mask_y, - int32_t dest_x, - int32_t dest_y, - int32_t width, - int32_t height) -{ - pixman_format_code_t src_format, mask_format, dest_format; - uint32_t src_flags, mask_flags, dest_flags; - pixman_region32_t region; - pixman_box32_t *extents; - pixman_implementation_t *imp; - pixman_composite_func_t func; - - _pixman_image_validate (src); - if (mask) - _pixman_image_validate (mask); - _pixman_image_validate (dest); - - src_format = src->common.extended_format_code; - src_flags = src->common.flags; - - if (mask) - { - mask_format = mask->common.extended_format_code; - mask_flags = mask->common.flags; - } - else - { - mask_format = PIXMAN_null; - mask_flags = FAST_PATH_IS_OPAQUE; - } - - dest_format = dest->common.extended_format_code; - dest_flags = dest->common.flags; - - /* Check for pixbufs */ - if ((mask_format == PIXMAN_a8r8g8b8 || mask_format == PIXMAN_a8b8g8r8) && - (src->type == BITS && src->bits.bits == mask->bits.bits) && - (src->common.repeat == mask->common.repeat) && - (src_x == mask_x && src_y == mask_y)) - { - if (src_format == PIXMAN_x8b8g8r8) - src_format = mask_format = PIXMAN_pixbuf; - else if (src_format == PIXMAN_x8r8g8b8) - src_format = mask_format = PIXMAN_rpixbuf; - } - - pixman_region32_init (®ion); - - if (!pixman_compute_composite_region32 ( - ®ion, src, mask, dest, - src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height)) - { - goto out; - } - - extents = pixman_region32_extents (®ion); - - if (!analyze_extent (src, dest_x - src_x, dest_y - src_y, extents, &src_flags)) - goto out; - - if (!analyze_extent (mask, dest_x - mask_x, dest_y - mask_y, extents, &mask_flags)) - goto out; - - /* If the clip is within the source samples, and the samples are opaque, - * then the source is effectively opaque. - */ -#define BOTH (FAST_PATH_SAMPLES_OPAQUE | FAST_PATH_SAMPLES_COVER_CLIP) - - if ((src_flags & BOTH) == BOTH) - src_flags |= FAST_PATH_IS_OPAQUE; - - if ((mask_flags & BOTH) == BOTH) - mask_flags |= FAST_PATH_IS_OPAQUE; - - /* - * Check if we can replace our operator by a simpler one - * if the src or dest are opaque. The output operator should be - * mathematically equivalent to the source. - */ - op = optimize_operator (op, src_flags, mask_flags, dest_flags); - if (op == PIXMAN_OP_DST) - goto out; - - if (lookup_composite_function (op, - src_format, src_flags, - mask_format, mask_flags, - dest_format, dest_flags, - &imp, &func)) - { - const pixman_box32_t *pbox; - int n; - - pbox = pixman_region32_rectangles (®ion, &n); - - while (n--) - { - func (imp, op, - src, mask, dest, - pbox->x1 + src_x - dest_x, - pbox->y1 + src_y - dest_y, - pbox->x1 + mask_x - dest_x, - pbox->y1 + mask_y - dest_y, - pbox->x1, - pbox->y1, - pbox->x2 - pbox->x1, - pbox->y2 - pbox->y1); - - pbox++; - } - } - -out: - pixman_region32_fini (®ion); -} - -PIXMAN_EXPORT void -pixman_image_composite (pixman_op_t op, - pixman_image_t * src, - pixman_image_t * mask, - pixman_image_t * dest, - int16_t src_x, - int16_t src_y, - int16_t mask_x, - int16_t mask_y, - int16_t dest_x, - int16_t dest_y, - uint16_t width, - uint16_t height) -{ - pixman_image_composite32 (op, src, mask, dest, src_x, src_y, - mask_x, mask_y, dest_x, dest_y, width, height); -} - -PIXMAN_EXPORT pixman_bool_t -pixman_blt (uint32_t *src_bits, - uint32_t *dst_bits, - int src_stride, - int dst_stride, - int src_bpp, - int dst_bpp, - int src_x, - int src_y, - int dst_x, - int dst_y, - int width, - int height) -{ - return _pixman_implementation_blt (get_implementation(), - src_bits, dst_bits, src_stride, dst_stride, - src_bpp, dst_bpp, - src_x, src_y, - dst_x, dst_y, - width, height); -} - -PIXMAN_EXPORT pixman_bool_t -pixman_fill (uint32_t *bits, - int stride, - int bpp, - int x, - int y, - int width, - int height, - uint32_t xor) -{ - return _pixman_implementation_fill ( - get_implementation(), bits, stride, bpp, x, y, width, height, xor); -} - -static uint32_t -color_to_uint32 (const pixman_color_t *color) -{ - return - (color->alpha >> 8 << 24) | - (color->red >> 8 << 16) | - (color->green & 0xff00) | - (color->blue >> 8); -} - -static pixman_bool_t -color_to_pixel (pixman_color_t * color, - uint32_t * pixel, - pixman_format_code_t format) -{ - uint32_t c = color_to_uint32 (color); - - if (!(format == PIXMAN_a8r8g8b8 || - format == PIXMAN_x8r8g8b8 || - format == PIXMAN_a8b8g8r8 || - format == PIXMAN_x8b8g8r8 || - format == PIXMAN_b8g8r8a8 || - format == PIXMAN_b8g8r8x8 || - format == PIXMAN_r5g6b5 || - format == PIXMAN_b5g6r5 || - format == PIXMAN_a8 || - format == PIXMAN_a1)) - { - return FALSE; - } - - if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_ABGR) - { - c = ((c & 0xff000000) >> 0) | - ((c & 0x00ff0000) >> 16) | - ((c & 0x0000ff00) >> 0) | - ((c & 0x000000ff) << 16); - } - if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_BGRA) - { - c = ((c & 0xff000000) >> 24) | - ((c & 0x00ff0000) >> 8) | - ((c & 0x0000ff00) << 8) | - ((c & 0x000000ff) << 24); - } - - if (format == PIXMAN_a1) - c = c >> 31; - else if (format == PIXMAN_a8) - c = c >> 24; - else if (format == PIXMAN_r5g6b5 || - format == PIXMAN_b5g6r5) - c = CONVERT_8888_TO_0565 (c); - -#if 0 - printf ("color: %x %x %x %x\n", color->alpha, color->red, color->green, color->blue); - printf ("pixel: %x\n", c); -#endif - - *pixel = c; - return TRUE; -} - -PIXMAN_EXPORT pixman_bool_t -pixman_image_fill_rectangles (pixman_op_t op, - pixman_image_t * dest, - pixman_color_t * color, - int n_rects, - const pixman_rectangle16_t *rects) -{ - pixman_box32_t stack_boxes[6]; - pixman_box32_t *boxes; - pixman_bool_t result; - int i; - - if (n_rects > 6) - { - boxes = pixman_malloc_ab (sizeof (pixman_box32_t), n_rects); - if (boxes == NULL) - return FALSE; - } - else - { - boxes = stack_boxes; - } - - for (i = 0; i < n_rects; ++i) - { - boxes[i].x1 = rects[i].x; - boxes[i].y1 = rects[i].y; - boxes[i].x2 = boxes[i].x1 + rects[i].width; - boxes[i].y2 = boxes[i].y1 + rects[i].height; - } - - result = pixman_image_fill_boxes (op, dest, color, n_rects, boxes); - - if (boxes != stack_boxes) - free (boxes); - - return result; -} - -PIXMAN_EXPORT pixman_bool_t -pixman_image_fill_boxes (pixman_op_t op, - pixman_image_t * dest, - pixman_color_t * color, - int n_boxes, - const pixman_box32_t *boxes) -{ - pixman_image_t *solid; - pixman_color_t c; - int i; - - _pixman_image_validate (dest); - - if (color->alpha == 0xffff) - { - if (op == PIXMAN_OP_OVER) - op = PIXMAN_OP_SRC; - } - - if (op == PIXMAN_OP_CLEAR) - { - c.red = 0; - c.green = 0; - c.blue = 0; - c.alpha = 0; - - color = &c; - - op = PIXMAN_OP_SRC; - } - - if (op == PIXMAN_OP_SRC) - { - uint32_t pixel; - - if (color_to_pixel (color, &pixel, dest->bits.format)) - { - pixman_region32_t fill_region; - int n_rects, j; - pixman_box32_t *rects; - - if (!pixman_region32_init_rects (&fill_region, boxes, n_boxes)) - return FALSE; - - if (dest->common.have_clip_region) - { - if (!pixman_region32_intersect (&fill_region, - &fill_region, - &dest->common.clip_region)) - return FALSE; - } - - rects = pixman_region32_rectangles (&fill_region, &n_rects); - for (j = 0; j < n_rects; ++j) - { - const pixman_box32_t *rect = &(rects[j]); - pixman_fill (dest->bits.bits, dest->bits.rowstride, PIXMAN_FORMAT_BPP (dest->bits.format), - rect->x1, rect->y1, rect->x2 - rect->x1, rect->y2 - rect->y1, - pixel); - } - - pixman_region32_fini (&fill_region); - return TRUE; - } - } - - solid = pixman_image_create_solid_fill (color); - if (!solid) - return FALSE; - - for (i = 0; i < n_boxes; ++i) - { - const pixman_box32_t *box = &(boxes[i]); - - pixman_image_composite32 (op, solid, NULL, dest, - 0, 0, 0, 0, - box->x1, box->y1, - box->x2 - box->x1, box->y2 - box->y1); - } - - pixman_image_unref (solid); - - return TRUE; -} - -/** - * pixman_version: - * - * Returns the version of the pixman library encoded in a single - * integer as per %PIXMAN_VERSION_ENCODE. The encoding ensures that - * later versions compare greater than earlier versions. - * - * A run-time comparison to check that pixman's version is greater than - * or equal to version X.Y.Z could be performed as follows: - * - * - * if (pixman_version() >= PIXMAN_VERSION_ENCODE(X,Y,Z)) {...} - * - * - * See also pixman_version_string() as well as the compile-time - * equivalents %PIXMAN_VERSION and %PIXMAN_VERSION_STRING. - * - * Return value: the encoded version. - **/ -PIXMAN_EXPORT int -pixman_version (void) -{ - return PIXMAN_VERSION; -} - -/** - * pixman_version_string: - * - * Returns the version of the pixman library as a human-readable string - * of the form "X.Y.Z". - * - * See also pixman_version() as well as the compile-time equivalents - * %PIXMAN_VERSION_STRING and %PIXMAN_VERSION. - * - * Return value: a string containing the version. - **/ -PIXMAN_EXPORT const char* -pixman_version_string (void) -{ - return PIXMAN_VERSION_STRING; -} - -/** - * pixman_format_supported_source: - * @format: A pixman_format_code_t format - * - * Return value: whether the provided format code is a supported - * format for a pixman surface used as a source in - * rendering. - * - * Currently, all pixman_format_code_t values are supported. - **/ -PIXMAN_EXPORT pixman_bool_t -pixman_format_supported_source (pixman_format_code_t format) -{ - switch (format) - { - /* 32 bpp formats */ - case PIXMAN_a2b10g10r10: - case PIXMAN_x2b10g10r10: - case PIXMAN_a2r10g10b10: - case PIXMAN_x2r10g10b10: - case PIXMAN_a8r8g8b8: - case PIXMAN_x8r8g8b8: - case PIXMAN_a8b8g8r8: - case PIXMAN_x8b8g8r8: - case PIXMAN_b8g8r8a8: - case PIXMAN_b8g8r8x8: - case PIXMAN_r8g8b8: - case PIXMAN_b8g8r8: - case PIXMAN_r5g6b5: - case PIXMAN_b5g6r5: - case PIXMAN_x14r6g6b6: - /* 16 bpp formats */ - case PIXMAN_a1r5g5b5: - case PIXMAN_x1r5g5b5: - case PIXMAN_a1b5g5r5: - case PIXMAN_x1b5g5r5: - case PIXMAN_a4r4g4b4: - case PIXMAN_x4r4g4b4: - case PIXMAN_a4b4g4r4: - case PIXMAN_x4b4g4r4: - /* 8bpp formats */ - case PIXMAN_a8: - case PIXMAN_r3g3b2: - case PIXMAN_b2g3r3: - case PIXMAN_a2r2g2b2: - case PIXMAN_a2b2g2r2: - case PIXMAN_c8: - case PIXMAN_g8: - case PIXMAN_x4a4: - /* Collides with PIXMAN_c8 - case PIXMAN_x4c4: - */ - /* Collides with PIXMAN_g8 - case PIXMAN_x4g4: - */ - /* 4bpp formats */ - case PIXMAN_a4: - case PIXMAN_r1g2b1: - case PIXMAN_b1g2r1: - case PIXMAN_a1r1g1b1: - case PIXMAN_a1b1g1r1: - case PIXMAN_c4: - case PIXMAN_g4: - /* 1bpp formats */ - case PIXMAN_a1: - case PIXMAN_g1: - /* YUV formats */ - case PIXMAN_yuy2: - case PIXMAN_yv12: - return TRUE; - - default: - return FALSE; - } -} - -/** - * pixman_format_supported_destination: - * @format: A pixman_format_code_t format - * - * Return value: whether the provided format code is a supported - * format for a pixman surface used as a destination in - * rendering. - * - * Currently, all pixman_format_code_t values are supported - * except for the YUV formats. - **/ -PIXMAN_EXPORT pixman_bool_t -pixman_format_supported_destination (pixman_format_code_t format) -{ - /* YUV formats cannot be written to at the moment */ - if (format == PIXMAN_yuy2 || format == PIXMAN_yv12) - return FALSE; - - return pixman_format_supported_source (format); -} - -PIXMAN_EXPORT pixman_bool_t -pixman_compute_composite_region (pixman_region16_t * region, - pixman_image_t * src_image, - pixman_image_t * mask_image, - pixman_image_t * dst_image, - int16_t src_x, - int16_t src_y, - int16_t mask_x, - int16_t mask_y, - int16_t dest_x, - int16_t dest_y, - uint16_t width, - uint16_t height) -{ - pixman_region32_t r32; - pixman_bool_t retval; - - pixman_region32_init (&r32); - - retval = pixman_compute_composite_region32 ( - &r32, src_image, mask_image, dst_image, - src_x, src_y, mask_x, mask_y, dest_x, dest_y, - width, height); - - if (retval) - { - if (!pixman_region16_copy_from_region32 (region, &r32)) - retval = FALSE; - } - - pixman_region32_fini (&r32); - return retval; -} +/* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */ +/* + * Copyright © 2000 SuSE, Inc. + * Copyright © 2007 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include "pixman-private.h" + +#include + +static pixman_implementation_t *global_implementation; + +#ifdef TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR +static void __attribute__((constructor)) +pixman_constructor (void) +{ + global_implementation = _pixman_choose_implementation (); +} +#endif + +static force_inline pixman_implementation_t * +get_implementation (void) +{ +#ifndef TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR + if (!global_implementation) + global_implementation = _pixman_choose_implementation (); +#endif + return global_implementation; +} + +typedef struct operator_info_t operator_info_t; + +struct operator_info_t +{ + uint8_t opaque_info[4]; +}; + +#define PACK(neither, src, dest, both) \ + {{ (uint8_t)PIXMAN_OP_ ## neither, \ + (uint8_t)PIXMAN_OP_ ## src, \ + (uint8_t)PIXMAN_OP_ ## dest, \ + (uint8_t)PIXMAN_OP_ ## both }} + +static const operator_info_t operator_table[] = +{ + /* Neither Opaque Src Opaque Dst Opaque Both Opaque */ + PACK (CLEAR, CLEAR, CLEAR, CLEAR), + PACK (SRC, SRC, SRC, SRC), + PACK (DST, DST, DST, DST), + PACK (OVER, SRC, OVER, SRC), + PACK (OVER_REVERSE, OVER_REVERSE, DST, DST), + PACK (IN, IN, SRC, SRC), + PACK (IN_REVERSE, DST, IN_REVERSE, DST), + PACK (OUT, OUT, CLEAR, CLEAR), + PACK (OUT_REVERSE, CLEAR, OUT_REVERSE, CLEAR), + PACK (ATOP, IN, OVER, SRC), + PACK (ATOP_REVERSE, OVER_REVERSE, IN_REVERSE, DST), + PACK (XOR, OUT, OUT_REVERSE, CLEAR), + PACK (ADD, ADD, ADD, ADD), + PACK (SATURATE, OVER_REVERSE, DST, DST), + + {{ 0 /* 0x0e */ }}, + {{ 0 /* 0x0f */ }}, + + PACK (CLEAR, CLEAR, CLEAR, CLEAR), + PACK (SRC, SRC, SRC, SRC), + PACK (DST, DST, DST, DST), + PACK (DISJOINT_OVER, DISJOINT_OVER, DISJOINT_OVER, DISJOINT_OVER), + PACK (DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE), + PACK (DISJOINT_IN, DISJOINT_IN, DISJOINT_IN, DISJOINT_IN), + PACK (DISJOINT_IN_REVERSE, DISJOINT_IN_REVERSE, DISJOINT_IN_REVERSE, DISJOINT_IN_REVERSE), + PACK (DISJOINT_OUT, DISJOINT_OUT, DISJOINT_OUT, DISJOINT_OUT), + PACK (DISJOINT_OUT_REVERSE, DISJOINT_OUT_REVERSE, DISJOINT_OUT_REVERSE, DISJOINT_OUT_REVERSE), + PACK (DISJOINT_ATOP, DISJOINT_ATOP, DISJOINT_ATOP, DISJOINT_ATOP), + PACK (DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE), + PACK (DISJOINT_XOR, DISJOINT_XOR, DISJOINT_XOR, DISJOINT_XOR), + + {{ 0 /* 0x1c */ }}, + {{ 0 /* 0x1d */ }}, + {{ 0 /* 0x1e */ }}, + {{ 0 /* 0x1f */ }}, + + PACK (CLEAR, CLEAR, CLEAR, CLEAR), + PACK (SRC, SRC, SRC, SRC), + PACK (DST, DST, DST, DST), + PACK (CONJOINT_OVER, CONJOINT_OVER, CONJOINT_OVER, CONJOINT_OVER), + PACK (CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE), + PACK (CONJOINT_IN, CONJOINT_IN, CONJOINT_IN, CONJOINT_IN), + PACK (CONJOINT_IN_REVERSE, CONJOINT_IN_REVERSE, CONJOINT_IN_REVERSE, CONJOINT_IN_REVERSE), + PACK (CONJOINT_OUT, CONJOINT_OUT, CONJOINT_OUT, CONJOINT_OUT), + PACK (CONJOINT_OUT_REVERSE, CONJOINT_OUT_REVERSE, CONJOINT_OUT_REVERSE, CONJOINT_OUT_REVERSE), + PACK (CONJOINT_ATOP, CONJOINT_ATOP, CONJOINT_ATOP, CONJOINT_ATOP), + PACK (CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE), + PACK (CONJOINT_XOR, CONJOINT_XOR, CONJOINT_XOR, CONJOINT_XOR), + + {{ 0 /* 0x2c */ }}, + {{ 0 /* 0x2d */ }}, + {{ 0 /* 0x2e */ }}, + {{ 0 /* 0x2f */ }}, + + PACK (MULTIPLY, MULTIPLY, MULTIPLY, MULTIPLY), + PACK (SCREEN, SCREEN, SCREEN, SCREEN), + PACK (OVERLAY, OVERLAY, OVERLAY, OVERLAY), + PACK (DARKEN, DARKEN, DARKEN, DARKEN), + PACK (LIGHTEN, LIGHTEN, LIGHTEN, LIGHTEN), + PACK (COLOR_DODGE, COLOR_DODGE, COLOR_DODGE, COLOR_DODGE), + PACK (COLOR_BURN, COLOR_BURN, COLOR_BURN, COLOR_BURN), + PACK (HARD_LIGHT, HARD_LIGHT, HARD_LIGHT, HARD_LIGHT), + PACK (SOFT_LIGHT, SOFT_LIGHT, SOFT_LIGHT, SOFT_LIGHT), + PACK (DIFFERENCE, DIFFERENCE, DIFFERENCE, DIFFERENCE), + PACK (EXCLUSION, EXCLUSION, EXCLUSION, EXCLUSION), + PACK (HSL_HUE, HSL_HUE, HSL_HUE, HSL_HUE), + PACK (HSL_SATURATION, HSL_SATURATION, HSL_SATURATION, HSL_SATURATION), + PACK (HSL_COLOR, HSL_COLOR, HSL_COLOR, HSL_COLOR), + PACK (HSL_LUMINOSITY, HSL_LUMINOSITY, HSL_LUMINOSITY, HSL_LUMINOSITY), +}; + +/* + * Optimize the current operator based on opacity of source or destination + * The output operator should be mathematically equivalent to the source. + */ +static pixman_op_t +optimize_operator (pixman_op_t op, + uint32_t src_flags, + uint32_t mask_flags, + uint32_t dst_flags) +{ + pixman_bool_t is_source_opaque, is_dest_opaque; + +#define OPAQUE_SHIFT 13 + + COMPILE_TIME_ASSERT (FAST_PATH_IS_OPAQUE == (1 << OPAQUE_SHIFT)); + + is_dest_opaque = (dst_flags & FAST_PATH_IS_OPAQUE); + is_source_opaque = ((src_flags & mask_flags) & FAST_PATH_IS_OPAQUE); + + is_dest_opaque >>= OPAQUE_SHIFT - 1; + is_source_opaque >>= OPAQUE_SHIFT; + + return operator_table[op].opaque_info[is_dest_opaque | is_source_opaque]; +} + +/* + * Computing composite region + */ +static inline pixman_bool_t +clip_general_image (pixman_region32_t * region, + pixman_region32_t * clip, + int dx, + int dy) +{ + if (pixman_region32_n_rects (region) == 1 && + pixman_region32_n_rects (clip) == 1) + { + pixman_box32_t * rbox = pixman_region32_rectangles (region, NULL); + pixman_box32_t * cbox = pixman_region32_rectangles (clip, NULL); + int v; + + if (rbox->x1 < (v = cbox->x1 + dx)) + rbox->x1 = v; + if (rbox->x2 > (v = cbox->x2 + dx)) + rbox->x2 = v; + if (rbox->y1 < (v = cbox->y1 + dy)) + rbox->y1 = v; + if (rbox->y2 > (v = cbox->y2 + dy)) + rbox->y2 = v; + if (rbox->x1 >= rbox->x2 || rbox->y1 >= rbox->y2) + { + pixman_region32_init (region); + return FALSE; + } + } + else if (!pixman_region32_not_empty (clip)) + { + return FALSE; + } + else + { + if (dx || dy) + pixman_region32_translate (region, -dx, -dy); + + if (!pixman_region32_intersect (region, region, clip)) + return FALSE; + + if (dx || dy) + pixman_region32_translate (region, dx, dy); + } + + return pixman_region32_not_empty (region); +} + +static inline pixman_bool_t +clip_source_image (pixman_region32_t * region, + pixman_image_t * image, + int dx, + int dy) +{ + /* Source clips are ignored, unless they are explicitly turned on + * and the clip in question was set by an X client. (Because if + * the clip was not set by a client, then it is a hierarchy + * clip and those should always be ignored for sources). + */ + if (!image->common.clip_sources || !image->common.client_clip) + return TRUE; + + return clip_general_image (region, + &image->common.clip_region, + dx, dy); +} + +/* + * returns FALSE if the final region is empty. Indistinguishable from + * an allocation failure, but rendering ignores those anyways. + */ +static pixman_bool_t +pixman_compute_composite_region32 (pixman_region32_t * region, + pixman_image_t * src_image, + pixman_image_t * mask_image, + pixman_image_t * dst_image, + int32_t src_x, + int32_t src_y, + int32_t mask_x, + int32_t mask_y, + int32_t dest_x, + int32_t dest_y, + int32_t width, + int32_t height) +{ + region->extents.x1 = dest_x; + region->extents.x2 = dest_x + width; + region->extents.y1 = dest_y; + region->extents.y2 = dest_y + height; + + region->extents.x1 = MAX (region->extents.x1, 0); + region->extents.y1 = MAX (region->extents.y1, 0); + region->extents.x2 = MIN (region->extents.x2, dst_image->bits.width); + region->extents.y2 = MIN (region->extents.y2, dst_image->bits.height); + + region->data = 0; + + /* Check for empty operation */ + if (region->extents.x1 >= region->extents.x2 || + region->extents.y1 >= region->extents.y2) + { + region->extents.x1 = 0; + region->extents.x2 = 0; + region->extents.y1 = 0; + region->extents.y2 = 0; + return FALSE; + } + + if (dst_image->common.have_clip_region) + { + if (!clip_general_image (region, &dst_image->common.clip_region, 0, 0)) + return FALSE; + } + + if (dst_image->common.alpha_map) + { + if (!pixman_region32_intersect_rect (region, region, + dst_image->common.alpha_origin_x, + dst_image->common.alpha_origin_y, + dst_image->common.alpha_map->width, + dst_image->common.alpha_map->height)) + { + return FALSE; + } + if (!pixman_region32_not_empty (region)) + return FALSE; + if (dst_image->common.alpha_map->common.have_clip_region) + { + if (!clip_general_image (region, &dst_image->common.alpha_map->common.clip_region, + -dst_image->common.alpha_origin_x, + -dst_image->common.alpha_origin_y)) + { + return FALSE; + } + } + } + + /* clip against src */ + if (src_image->common.have_clip_region) + { + if (!clip_source_image (region, src_image, dest_x - src_x, dest_y - src_y)) + return FALSE; + } + if (src_image->common.alpha_map && src_image->common.alpha_map->common.have_clip_region) + { + if (!clip_source_image (region, (pixman_image_t *)src_image->common.alpha_map, + dest_x - (src_x - src_image->common.alpha_origin_x), + dest_y - (src_y - src_image->common.alpha_origin_y))) + { + return FALSE; + } + } + /* clip against mask */ + if (mask_image && mask_image->common.have_clip_region) + { + if (!clip_source_image (region, mask_image, dest_x - mask_x, dest_y - mask_y)) + return FALSE; + + if (mask_image->common.alpha_map && mask_image->common.alpha_map->common.have_clip_region) + { + if (!clip_source_image (region, (pixman_image_t *)mask_image->common.alpha_map, + dest_x - (mask_x - mask_image->common.alpha_origin_x), + dest_y - (mask_y - mask_image->common.alpha_origin_y))) + { + return FALSE; + } + } + } + + return TRUE; +} + +#define N_CACHED_FAST_PATHS 8 + +typedef struct +{ + struct + { + pixman_implementation_t * imp; + pixman_fast_path_t fast_path; + } cache [N_CACHED_FAST_PATHS]; +} cache_t; + +PIXMAN_DEFINE_THREAD_LOCAL (cache_t, fast_path_cache); + +static force_inline pixman_bool_t +lookup_composite_function (pixman_op_t op, + pixman_format_code_t src_format, + uint32_t src_flags, + pixman_format_code_t mask_format, + uint32_t mask_flags, + pixman_format_code_t dest_format, + uint32_t dest_flags, + pixman_implementation_t **out_imp, + pixman_composite_func_t *out_func) +{ + pixman_implementation_t *imp; + cache_t *cache; + int i; + + /* Check cache for fast paths */ + cache = PIXMAN_GET_THREAD_LOCAL (fast_path_cache); + + for (i = 0; i < N_CACHED_FAST_PATHS; ++i) + { + const pixman_fast_path_t *info = &(cache->cache[i].fast_path); + + /* Note that we check for equality here, not whether + * the cached fast path matches. This is to prevent + * us from selecting an overly general fast path + * when a more specific one would work. + */ + if (info->op == op && + info->src_format == src_format && + info->mask_format == mask_format && + info->dest_format == dest_format && + info->src_flags == src_flags && + info->mask_flags == mask_flags && + info->dest_flags == dest_flags && + info->func) + { + *out_imp = cache->cache[i].imp; + *out_func = cache->cache[i].fast_path.func; + + goto update_cache; + } + } + + for (imp = get_implementation (); imp != NULL; imp = imp->delegate) + { + const pixman_fast_path_t *info = imp->fast_paths; + + while (info->op != PIXMAN_OP_NONE) + { + if ((info->op == op || info->op == PIXMAN_OP_any) && + /* Formats */ + ((info->src_format == src_format) || + (info->src_format == PIXMAN_any)) && + ((info->mask_format == mask_format) || + (info->mask_format == PIXMAN_any)) && + ((info->dest_format == dest_format) || + (info->dest_format == PIXMAN_any)) && + /* Flags */ + (info->src_flags & src_flags) == info->src_flags && + (info->mask_flags & mask_flags) == info->mask_flags && + (info->dest_flags & dest_flags) == info->dest_flags) + { + *out_imp = imp; + *out_func = info->func; + + /* Set i to the last spot in the cache so that the + * move-to-front code below will work + */ + i = N_CACHED_FAST_PATHS - 1; + + goto update_cache; + } + + ++info; + } + } + return FALSE; + +update_cache: + if (i) + { + while (i--) + cache->cache[i + 1] = cache->cache[i]; + + cache->cache[0].imp = *out_imp; + cache->cache[0].fast_path.op = op; + cache->cache[0].fast_path.src_format = src_format; + cache->cache[0].fast_path.src_flags = src_flags; + cache->cache[0].fast_path.mask_format = mask_format; + cache->cache[0].fast_path.mask_flags = mask_flags; + cache->cache[0].fast_path.dest_format = dest_format; + cache->cache[0].fast_path.dest_flags = dest_flags; + cache->cache[0].fast_path.func = *out_func; + } + + return TRUE; +} + +static pixman_bool_t +compute_sample_extents (pixman_transform_t *transform, + pixman_box32_t *extents, int x, int y, + pixman_fixed_t x_off, pixman_fixed_t y_off, + pixman_fixed_t width, pixman_fixed_t height) +{ + pixman_fixed_t x1, y1, x2, y2; + pixman_fixed_48_16_t tx1, ty1, tx2, ty2; + + /* We have checked earlier that (extents->x1 - x) etc. fit in a pixman_fixed_t */ + x1 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->x1 - x) + pixman_fixed_1 / 2; + y1 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->y1 - y) + pixman_fixed_1 / 2; + x2 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->x2 - x) - pixman_fixed_1 / 2; + y2 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->y2 - y) - pixman_fixed_1 / 2; + + if (!transform) + { + tx1 = (pixman_fixed_48_16_t)x1; + ty1 = (pixman_fixed_48_16_t)y1; + tx2 = (pixman_fixed_48_16_t)x2; + ty2 = (pixman_fixed_48_16_t)y2; + } + else + { + int i; + + /* Silence GCC */ + tx1 = ty1 = tx2 = ty2 = 0; + + for (i = 0; i < 4; ++i) + { + pixman_fixed_48_16_t tx, ty; + pixman_vector_t v; + + v.vector[0] = (i & 0x01)? x1 : x2; + v.vector[1] = (i & 0x02)? y1 : y2; + v.vector[2] = pixman_fixed_1; + + if (!pixman_transform_point (transform, &v)) + return FALSE; + + tx = (pixman_fixed_48_16_t)v.vector[0]; + ty = (pixman_fixed_48_16_t)v.vector[1]; + + if (i == 0) + { + tx1 = tx; + ty1 = ty; + tx2 = tx; + ty2 = ty; + } + else + { + if (tx < tx1) + tx1 = tx; + if (ty < ty1) + ty1 = ty; + if (tx > tx2) + tx2 = tx; + if (ty > ty2) + ty2 = ty; + } + } + } + + /* Expand the source area by a tiny bit so account of different rounding that + * may happen during sampling. Note that (8 * pixman_fixed_e) is very far from + * 0.5 so this won't cause the area computed to be overly pessimistic. + */ + tx1 += x_off - 8 * pixman_fixed_e; + ty1 += y_off - 8 * pixman_fixed_e; + tx2 += x_off + width + 8 * pixman_fixed_e; + ty2 += y_off + height + 8 * pixman_fixed_e; + + if (tx1 < pixman_min_fixed_48_16 || tx1 > pixman_max_fixed_48_16 || + ty1 < pixman_min_fixed_48_16 || ty1 > pixman_max_fixed_48_16 || + tx2 < pixman_min_fixed_48_16 || tx2 > pixman_max_fixed_48_16 || + ty2 < pixman_min_fixed_48_16 || ty2 > pixman_max_fixed_48_16) + { + return FALSE; + } + else + { + extents->x1 = pixman_fixed_to_int (tx1); + extents->y1 = pixman_fixed_to_int (ty1); + extents->x2 = pixman_fixed_to_int (tx2) + 1; + extents->y2 = pixman_fixed_to_int (ty2) + 1; + + return TRUE; + } +} + +#define IS_16BIT(x) (((x) >= INT16_MIN) && ((x) <= INT16_MAX)) + +static pixman_bool_t +analyze_extent (pixman_image_t *image, int x, int y, + const pixman_box32_t *extents, uint32_t *flags) +{ + pixman_transform_t *transform; + pixman_fixed_t *params; + pixman_fixed_t x_off, y_off; + pixman_fixed_t width, height; + pixman_box32_t ex; + + if (!image) + return TRUE; + + /* Some compositing functions walk one step + * outside the destination rectangle, so we + * check here that the expanded-by-one source + * extents in destination space fits in 16 bits + */ + if (!IS_16BIT (extents->x1 - x - 1) || + !IS_16BIT (extents->y1 - y - 1) || + !IS_16BIT (extents->x2 - x + 1) || + !IS_16BIT (extents->y2 - y + 1)) + { + return FALSE; + } + + transform = image->common.transform; + if (image->common.type == BITS) + { + /* During repeat mode calculations we might convert the + * width/height of an image to fixed 16.16, so we need + * them to be smaller than 16 bits. + */ + if (image->bits.width >= 0x7fff || image->bits.height >= 0x7fff) + return FALSE; + +#define ID_AND_NEAREST (FAST_PATH_ID_TRANSFORM | FAST_PATH_NEAREST_FILTER) + + if ((image->common.flags & ID_AND_NEAREST) == ID_AND_NEAREST && + extents->x1 - x >= 0 && + extents->y1 - y >= 0 && + extents->x2 - x <= image->bits.width && + extents->y2 - y <= image->bits.height) + { + *flags |= FAST_PATH_SAMPLES_COVER_CLIP; + return TRUE; + } + + switch (image->common.filter) + { + case PIXMAN_FILTER_CONVOLUTION: + params = image->common.filter_params; + x_off = - pixman_fixed_e - ((params[0] - pixman_fixed_1) >> 1); + y_off = - pixman_fixed_e - ((params[1] - pixman_fixed_1) >> 1); + width = params[0]; + height = params[1]; + break; + + case PIXMAN_FILTER_GOOD: + case PIXMAN_FILTER_BEST: + case PIXMAN_FILTER_BILINEAR: + x_off = - pixman_fixed_1 / 2; + y_off = - pixman_fixed_1 / 2; + width = pixman_fixed_1; + height = pixman_fixed_1; + break; + + case PIXMAN_FILTER_FAST: + case PIXMAN_FILTER_NEAREST: + x_off = - pixman_fixed_e; + y_off = - pixman_fixed_e; + width = 0; + height = 0; + break; + + default: + return FALSE; + } + + /* Check whether the non-expanded, transformed extent is entirely within + * the source image, and set the FAST_PATH_SAMPLES_COVER_CLIP if it is. + */ + ex = *extents; + if (compute_sample_extents (transform, &ex, x, y, x_off, y_off, width, height) && + ex.x1 >= 0 && ex.y1 >= 0 && + ex.x2 <= image->bits.width && ex.y2 <= image->bits.height) + { + *flags |= FAST_PATH_SAMPLES_COVER_CLIP; + } + } + else + { + x_off = 0; + y_off = 0; + width = 0; + height = 0; + } + + /* Check that the extents expanded by one don't overflow. This ensures that + * compositing functions can simply walk the source space using 16.16 + * variables without worrying about overflow. + */ + ex.x1 = extents->x1 - 1; + ex.y1 = extents->y1 - 1; + ex.x2 = extents->x2 + 1; + ex.y2 = extents->y2 + 1; + + if (!compute_sample_extents (transform, &ex, x, y, x_off, y_off, width, height)) + return FALSE; + + return TRUE; +} + +/* + * Work around GCC bug causing crashes in Mozilla with SSE2 + * + * When using -msse, gcc generates movdqa instructions assuming that + * the stack is 16 byte aligned. Unfortunately some applications, such + * as Mozilla and Mono, end up aligning the stack to 4 bytes, which + * causes the movdqa instructions to fail. + * + * The __force_align_arg_pointer__ makes gcc generate a prologue that + * realigns the stack pointer to 16 bytes. + * + * On x86-64 this is not necessary because the standard ABI already + * calls for a 16 byte aligned stack. + * + * See https://bugs.freedesktop.org/show_bug.cgi?id=15693 + */ +#if defined (USE_SSE2) && defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__) +__attribute__((__force_align_arg_pointer__)) +#endif +PIXMAN_EXPORT void +pixman_image_composite32 (pixman_op_t op, + pixman_image_t * src, + pixman_image_t * mask, + pixman_image_t * dest, + int32_t src_x, + int32_t src_y, + int32_t mask_x, + int32_t mask_y, + int32_t dest_x, + int32_t dest_y, + int32_t width, + int32_t height) +{ + pixman_format_code_t src_format, mask_format, dest_format; + uint32_t src_flags, mask_flags, dest_flags; + pixman_region32_t region; + pixman_box32_t *extents; + pixman_implementation_t *imp; + pixman_composite_func_t func; + + _pixman_image_validate (src); + if (mask) + _pixman_image_validate (mask); + _pixman_image_validate (dest); + + src_format = src->common.extended_format_code; + src_flags = src->common.flags; + + if (mask) + { + mask_format = mask->common.extended_format_code; + mask_flags = mask->common.flags; + } + else + { + mask_format = PIXMAN_null; + mask_flags = FAST_PATH_IS_OPAQUE; + } + + dest_format = dest->common.extended_format_code; + dest_flags = dest->common.flags; + + /* Check for pixbufs */ + if ((mask_format == PIXMAN_a8r8g8b8 || mask_format == PIXMAN_a8b8g8r8) && + (src->type == BITS && src->bits.bits == mask->bits.bits) && + (src->common.repeat == mask->common.repeat) && + (src_x == mask_x && src_y == mask_y)) + { + if (src_format == PIXMAN_x8b8g8r8) + src_format = mask_format = PIXMAN_pixbuf; + else if (src_format == PIXMAN_x8r8g8b8) + src_format = mask_format = PIXMAN_rpixbuf; + } + + pixman_region32_init (®ion); + + if (!pixman_compute_composite_region32 ( + ®ion, src, mask, dest, + src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height)) + { + goto out; + } + + extents = pixman_region32_extents (®ion); + + if (!analyze_extent (src, dest_x - src_x, dest_y - src_y, extents, &src_flags)) + goto out; + + if (!analyze_extent (mask, dest_x - mask_x, dest_y - mask_y, extents, &mask_flags)) + goto out; + + /* If the clip is within the source samples, and the samples are opaque, + * then the source is effectively opaque. + */ +#define BOTH (FAST_PATH_SAMPLES_OPAQUE | FAST_PATH_SAMPLES_COVER_CLIP) + + if ((src_flags & BOTH) == BOTH) + src_flags |= FAST_PATH_IS_OPAQUE; + + if ((mask_flags & BOTH) == BOTH) + mask_flags |= FAST_PATH_IS_OPAQUE; + + /* + * Check if we can replace our operator by a simpler one + * if the src or dest are opaque. The output operator should be + * mathematically equivalent to the source. + */ + op = optimize_operator (op, src_flags, mask_flags, dest_flags); + if (op == PIXMAN_OP_DST) + goto out; + + if (lookup_composite_function (op, + src_format, src_flags, + mask_format, mask_flags, + dest_format, dest_flags, + &imp, &func)) + { + const pixman_box32_t *pbox; + int n; + + pbox = pixman_region32_rectangles (®ion, &n); + + while (n--) + { + func (imp, op, + src, mask, dest, + pbox->x1 + src_x - dest_x, + pbox->y1 + src_y - dest_y, + pbox->x1 + mask_x - dest_x, + pbox->y1 + mask_y - dest_y, + pbox->x1, + pbox->y1, + pbox->x2 - pbox->x1, + pbox->y2 - pbox->y1); + + pbox++; + } + } + +out: + pixman_region32_fini (®ion); +} + +PIXMAN_EXPORT void +pixman_image_composite (pixman_op_t op, + pixman_image_t * src, + pixman_image_t * mask, + pixman_image_t * dest, + int16_t src_x, + int16_t src_y, + int16_t mask_x, + int16_t mask_y, + int16_t dest_x, + int16_t dest_y, + uint16_t width, + uint16_t height) +{ + pixman_image_composite32 (op, src, mask, dest, src_x, src_y, + mask_x, mask_y, dest_x, dest_y, width, height); +} + +PIXMAN_EXPORT pixman_bool_t +pixman_blt (uint32_t *src_bits, + uint32_t *dst_bits, + int src_stride, + int dst_stride, + int src_bpp, + int dst_bpp, + int src_x, + int src_y, + int dst_x, + int dst_y, + int width, + int height) +{ + return _pixman_implementation_blt (get_implementation(), + src_bits, dst_bits, src_stride, dst_stride, + src_bpp, dst_bpp, + src_x, src_y, + dst_x, dst_y, + width, height); +} + +PIXMAN_EXPORT pixman_bool_t +pixman_fill (uint32_t *bits, + int stride, + int bpp, + int x, + int y, + int width, + int height, + uint32_t xor) +{ + return _pixman_implementation_fill ( + get_implementation(), bits, stride, bpp, x, y, width, height, xor); +} + +static uint32_t +color_to_uint32 (const pixman_color_t *color) +{ + return + (color->alpha >> 8 << 24) | + (color->red >> 8 << 16) | + (color->green & 0xff00) | + (color->blue >> 8); +} + +static pixman_bool_t +color_to_pixel (pixman_color_t * color, + uint32_t * pixel, + pixman_format_code_t format) +{ + uint32_t c = color_to_uint32 (color); + + if (!(format == PIXMAN_a8r8g8b8 || + format == PIXMAN_x8r8g8b8 || + format == PIXMAN_a8b8g8r8 || + format == PIXMAN_x8b8g8r8 || + format == PIXMAN_b8g8r8a8 || + format == PIXMAN_b8g8r8x8 || + format == PIXMAN_r8g8b8a8 || + format == PIXMAN_r8g8b8x8 || + format == PIXMAN_r5g6b5 || + format == PIXMAN_b5g6r5 || + format == PIXMAN_a8 || + format == PIXMAN_a1)) + { + return FALSE; + } + + if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_ABGR) + { + c = ((c & 0xff000000) >> 0) | + ((c & 0x00ff0000) >> 16) | + ((c & 0x0000ff00) >> 0) | + ((c & 0x000000ff) << 16); + } + if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_BGRA) + { + c = ((c & 0xff000000) >> 24) | + ((c & 0x00ff0000) >> 8) | + ((c & 0x0000ff00) << 8) | + ((c & 0x000000ff) << 24); + } + if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_RGBA) + c = ((c & 0xff000000) >> 24) | (c << 8); + + if (format == PIXMAN_a1) + c = c >> 31; + else if (format == PIXMAN_a8) + c = c >> 24; + else if (format == PIXMAN_r5g6b5 || + format == PIXMAN_b5g6r5) + c = CONVERT_8888_TO_0565 (c); + +#if 0 + printf ("color: %x %x %x %x\n", color->alpha, color->red, color->green, color->blue); + printf ("pixel: %x\n", c); +#endif + + *pixel = c; + return TRUE; +} + +PIXMAN_EXPORT pixman_bool_t +pixman_image_fill_rectangles (pixman_op_t op, + pixman_image_t * dest, + pixman_color_t * color, + int n_rects, + const pixman_rectangle16_t *rects) +{ + pixman_box32_t stack_boxes[6]; + pixman_box32_t *boxes; + pixman_bool_t result; + int i; + + if (n_rects > 6) + { + boxes = pixman_malloc_ab (sizeof (pixman_box32_t), n_rects); + if (boxes == NULL) + return FALSE; + } + else + { + boxes = stack_boxes; + } + + for (i = 0; i < n_rects; ++i) + { + boxes[i].x1 = rects[i].x; + boxes[i].y1 = rects[i].y; + boxes[i].x2 = boxes[i].x1 + rects[i].width; + boxes[i].y2 = boxes[i].y1 + rects[i].height; + } + + result = pixman_image_fill_boxes (op, dest, color, n_rects, boxes); + + if (boxes != stack_boxes) + free (boxes); + + return result; +} + +PIXMAN_EXPORT pixman_bool_t +pixman_image_fill_boxes (pixman_op_t op, + pixman_image_t * dest, + pixman_color_t * color, + int n_boxes, + const pixman_box32_t *boxes) +{ + pixman_image_t *solid; + pixman_color_t c; + int i; + + _pixman_image_validate (dest); + + if (color->alpha == 0xffff) + { + if (op == PIXMAN_OP_OVER) + op = PIXMAN_OP_SRC; + } + + if (op == PIXMAN_OP_CLEAR) + { + c.red = 0; + c.green = 0; + c.blue = 0; + c.alpha = 0; + + color = &c; + + op = PIXMAN_OP_SRC; + } + + if (op == PIXMAN_OP_SRC) + { + uint32_t pixel; + + if (color_to_pixel (color, &pixel, dest->bits.format)) + { + pixman_region32_t fill_region; + int n_rects, j; + pixman_box32_t *rects; + + if (!pixman_region32_init_rects (&fill_region, boxes, n_boxes)) + return FALSE; + + if (dest->common.have_clip_region) + { + if (!pixman_region32_intersect (&fill_region, + &fill_region, + &dest->common.clip_region)) + return FALSE; + } + + rects = pixman_region32_rectangles (&fill_region, &n_rects); + for (j = 0; j < n_rects; ++j) + { + const pixman_box32_t *rect = &(rects[j]); + pixman_fill (dest->bits.bits, dest->bits.rowstride, PIXMAN_FORMAT_BPP (dest->bits.format), + rect->x1, rect->y1, rect->x2 - rect->x1, rect->y2 - rect->y1, + pixel); + } + + pixman_region32_fini (&fill_region); + return TRUE; + } + } + + solid = pixman_image_create_solid_fill (color); + if (!solid) + return FALSE; + + for (i = 0; i < n_boxes; ++i) + { + const pixman_box32_t *box = &(boxes[i]); + + pixman_image_composite32 (op, solid, NULL, dest, + 0, 0, 0, 0, + box->x1, box->y1, + box->x2 - box->x1, box->y2 - box->y1); + } + + pixman_image_unref (solid); + + return TRUE; +} + +/** + * pixman_version: + * + * Returns the version of the pixman library encoded in a single + * integer as per %PIXMAN_VERSION_ENCODE. The encoding ensures that + * later versions compare greater than earlier versions. + * + * A run-time comparison to check that pixman's version is greater than + * or equal to version X.Y.Z could be performed as follows: + * + * + * if (pixman_version() >= PIXMAN_VERSION_ENCODE(X,Y,Z)) {...} + * + * + * See also pixman_version_string() as well as the compile-time + * equivalents %PIXMAN_VERSION and %PIXMAN_VERSION_STRING. + * + * Return value: the encoded version. + **/ +PIXMAN_EXPORT int +pixman_version (void) +{ + return PIXMAN_VERSION; +} + +/** + * pixman_version_string: + * + * Returns the version of the pixman library as a human-readable string + * of the form "X.Y.Z". + * + * See also pixman_version() as well as the compile-time equivalents + * %PIXMAN_VERSION_STRING and %PIXMAN_VERSION. + * + * Return value: a string containing the version. + **/ +PIXMAN_EXPORT const char* +pixman_version_string (void) +{ + return PIXMAN_VERSION_STRING; +} + +/** + * pixman_format_supported_source: + * @format: A pixman_format_code_t format + * + * Return value: whether the provided format code is a supported + * format for a pixman surface used as a source in + * rendering. + * + * Currently, all pixman_format_code_t values are supported. + **/ +PIXMAN_EXPORT pixman_bool_t +pixman_format_supported_source (pixman_format_code_t format) +{ + switch (format) + { + /* 32 bpp formats */ + case PIXMAN_a2b10g10r10: + case PIXMAN_x2b10g10r10: + case PIXMAN_a2r10g10b10: + case PIXMAN_x2r10g10b10: + case PIXMAN_a8r8g8b8: + case PIXMAN_x8r8g8b8: + case PIXMAN_a8b8g8r8: + case PIXMAN_x8b8g8r8: + case PIXMAN_b8g8r8a8: + case PIXMAN_b8g8r8x8: + case PIXMAN_r8g8b8a8: + case PIXMAN_r8g8b8x8: + case PIXMAN_r8g8b8: + case PIXMAN_b8g8r8: + case PIXMAN_r5g6b5: + case PIXMAN_b5g6r5: + case PIXMAN_x14r6g6b6: + /* 16 bpp formats */ + case PIXMAN_a1r5g5b5: + case PIXMAN_x1r5g5b5: + case PIXMAN_a1b5g5r5: + case PIXMAN_x1b5g5r5: + case PIXMAN_a4r4g4b4: + case PIXMAN_x4r4g4b4: + case PIXMAN_a4b4g4r4: + case PIXMAN_x4b4g4r4: + /* 8bpp formats */ + case PIXMAN_a8: + case PIXMAN_r3g3b2: + case PIXMAN_b2g3r3: + case PIXMAN_a2r2g2b2: + case PIXMAN_a2b2g2r2: + case PIXMAN_c8: + case PIXMAN_g8: + case PIXMAN_x4a4: + /* Collides with PIXMAN_c8 + case PIXMAN_x4c4: + */ + /* Collides with PIXMAN_g8 + case PIXMAN_x4g4: + */ + /* 4bpp formats */ + case PIXMAN_a4: + case PIXMAN_r1g2b1: + case PIXMAN_b1g2r1: + case PIXMAN_a1r1g1b1: + case PIXMAN_a1b1g1r1: + case PIXMAN_c4: + case PIXMAN_g4: + /* 1bpp formats */ + case PIXMAN_a1: + case PIXMAN_g1: + /* YUV formats */ + case PIXMAN_yuy2: + case PIXMAN_yv12: + return TRUE; + + default: + return FALSE; + } +} + +/** + * pixman_format_supported_destination: + * @format: A pixman_format_code_t format + * + * Return value: whether the provided format code is a supported + * format for a pixman surface used as a destination in + * rendering. + * + * Currently, all pixman_format_code_t values are supported + * except for the YUV formats. + **/ +PIXMAN_EXPORT pixman_bool_t +pixman_format_supported_destination (pixman_format_code_t format) +{ + /* YUV formats cannot be written to at the moment */ + if (format == PIXMAN_yuy2 || format == PIXMAN_yv12) + return FALSE; + + return pixman_format_supported_source (format); +} + +PIXMAN_EXPORT pixman_bool_t +pixman_compute_composite_region (pixman_region16_t * region, + pixman_image_t * src_image, + pixman_image_t * mask_image, + pixman_image_t * dst_image, + int16_t src_x, + int16_t src_y, + int16_t mask_x, + int16_t mask_y, + int16_t dest_x, + int16_t dest_y, + uint16_t width, + uint16_t height) +{ + pixman_region32_t r32; + pixman_bool_t retval; + + pixman_region32_init (&r32); + + retval = pixman_compute_composite_region32 ( + &r32, src_image, mask_image, dst_image, + src_x, src_y, mask_x, mask_y, dest_x, dest_y, + width, height); + + if (retval) + { + if (!pixman_region16_copy_from_region32 (region, &r32)) + retval = FALSE; + } + + pixman_region32_fini (&r32); + return retval; +} diff --git a/pixman/pixman/pixman.h b/pixman/pixman/pixman.h index 855575a30..59d076089 100644 --- a/pixman/pixman/pixman.h +++ b/pixman/pixman/pixman.h @@ -1,986 +1,990 @@ -/*********************************************************** - -Copyright 1987, 1998 The Open Group - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation. - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from The Open Group. - -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -******************************************************************/ -/* - * Copyright © 1998, 2004 Keith Packard - * Copyright 2007 Red Hat, Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Keith Packard not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Keith Packard makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef PIXMAN_H__ -#define PIXMAN_H__ - -#include - -#ifdef __cplusplus -#define PIXMAN_BEGIN_DECLS extern "C" { -#define PIXMAN_END_DECLS } -#else -#define PIXMAN_BEGIN_DECLS -#define PIXMAN_END_DECLS -#endif - -PIXMAN_BEGIN_DECLS - -/* - * Standard integers - */ - -#if !defined (PIXMAN_DONT_DEFINE_STDINT) - -#if defined (_SVR4) || defined (SVR4) || defined (__OpenBSD__) || defined (_sgi) || defined (__sun) || defined (sun) || defined (__digital__) || defined (__HP_cc) -# include -/* VS 2010 (_MSC_VER 1600) has stdint.h */ -#elif defined (_MSC_VER) && _MSC_VER < 1600 -typedef __int8 int8_t; -typedef unsigned __int8 uint8_t; -typedef __int16 int16_t; -typedef unsigned __int16 uint16_t; -typedef __int32 int32_t; -typedef unsigned __int32 uint32_t; -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; -#elif defined (_AIX) -# include -#else -# include -#endif - -#endif - -/* - * Boolean - */ -typedef int pixman_bool_t; - -/* - * Fixpoint numbers - */ -typedef int64_t pixman_fixed_32_32_t; -typedef pixman_fixed_32_32_t pixman_fixed_48_16_t; -typedef uint32_t pixman_fixed_1_31_t; -typedef uint32_t pixman_fixed_1_16_t; -typedef int32_t pixman_fixed_16_16_t; -typedef pixman_fixed_16_16_t pixman_fixed_t; - -#define pixman_fixed_e ((pixman_fixed_t) 1) -#define pixman_fixed_1 (pixman_int_to_fixed(1)) -#define pixman_fixed_1_minus_e (pixman_fixed_1 - pixman_fixed_e) -#define pixman_fixed_minus_1 (pixman_int_to_fixed(-1)) -#define pixman_fixed_to_int(f) ((int) ((f) >> 16)) -#define pixman_int_to_fixed(i) ((pixman_fixed_t) ((i) << 16)) -#define pixman_fixed_to_double(f) (double) ((f) / (double) pixman_fixed_1) -#define pixman_double_to_fixed(d) ((pixman_fixed_t) ((d) * 65536.0)) -#define pixman_fixed_frac(f) ((f) & pixman_fixed_1_minus_e) -#define pixman_fixed_floor(f) ((f) & ~pixman_fixed_1_minus_e) -#define pixman_fixed_ceil(f) pixman_fixed_floor ((f) + pixman_fixed_1_minus_e) -#define pixman_fixed_fraction(f) ((f) & pixman_fixed_1_minus_e) -#define pixman_fixed_mod_2(f) ((f) & (pixman_fixed1 | pixman_fixed_1_minus_e)) -#define pixman_max_fixed_48_16 ((pixman_fixed_48_16_t) 0x7fffffff) -#define pixman_min_fixed_48_16 (-((pixman_fixed_48_16_t) 1 << 31)) - -/* - * Misc structs - */ -typedef struct pixman_color pixman_color_t; -typedef struct pixman_point_fixed pixman_point_fixed_t; -typedef struct pixman_line_fixed pixman_line_fixed_t; -typedef struct pixman_vector pixman_vector_t; -typedef struct pixman_transform pixman_transform_t; - -struct pixman_color -{ - uint16_t red; - uint16_t green; - uint16_t blue; - uint16_t alpha; -}; - -struct pixman_point_fixed -{ - pixman_fixed_t x; - pixman_fixed_t y; -}; - -struct pixman_line_fixed -{ - pixman_point_fixed_t p1, p2; -}; - -/* - * Fixed point matrices - */ - -struct pixman_vector -{ - pixman_fixed_t vector[3]; -}; - -struct pixman_transform -{ - pixman_fixed_t matrix[3][3]; -}; - -/* forward declaration (sorry) */ -struct pixman_box16; -typedef union pixman_image pixman_image_t; - -void pixman_transform_init_identity (struct pixman_transform *matrix); -pixman_bool_t pixman_transform_point_3d (const struct pixman_transform *transform, - struct pixman_vector *vector); -pixman_bool_t pixman_transform_point (const struct pixman_transform *transform, - struct pixman_vector *vector); -pixman_bool_t pixman_transform_multiply (struct pixman_transform *dst, - const struct pixman_transform *l, - const struct pixman_transform *r); -void pixman_transform_init_scale (struct pixman_transform *t, - pixman_fixed_t sx, - pixman_fixed_t sy); -pixman_bool_t pixman_transform_scale (struct pixman_transform *forward, - struct pixman_transform *reverse, - pixman_fixed_t sx, - pixman_fixed_t sy); -void pixman_transform_init_rotate (struct pixman_transform *t, - pixman_fixed_t cos, - pixman_fixed_t sin); -pixman_bool_t pixman_transform_rotate (struct pixman_transform *forward, - struct pixman_transform *reverse, - pixman_fixed_t c, - pixman_fixed_t s); -void pixman_transform_init_translate (struct pixman_transform *t, - pixman_fixed_t tx, - pixman_fixed_t ty); -pixman_bool_t pixman_transform_translate (struct pixman_transform *forward, - struct pixman_transform *reverse, - pixman_fixed_t tx, - pixman_fixed_t ty); -pixman_bool_t pixman_transform_bounds (const struct pixman_transform *matrix, - struct pixman_box16 *b); -pixman_bool_t pixman_transform_invert (struct pixman_transform *dst, - const struct pixman_transform *src); -pixman_bool_t pixman_transform_is_identity (const struct pixman_transform *t); -pixman_bool_t pixman_transform_is_scale (const struct pixman_transform *t); -pixman_bool_t pixman_transform_is_int_translate (const struct pixman_transform *t); -pixman_bool_t pixman_transform_is_inverse (const struct pixman_transform *a, - const struct pixman_transform *b); - -/* - * Floating point matrices - */ -struct pixman_f_vector -{ - double v[3]; -}; - -struct pixman_f_transform -{ - double m[3][3]; -}; - -pixman_bool_t pixman_transform_from_pixman_f_transform (struct pixman_transform *t, - const struct pixman_f_transform *ft); -void pixman_f_transform_from_pixman_transform (struct pixman_f_transform *ft, - const struct pixman_transform *t); -pixman_bool_t pixman_f_transform_invert (struct pixman_f_transform *dst, - const struct pixman_f_transform *src); -pixman_bool_t pixman_f_transform_point (const struct pixman_f_transform *t, - struct pixman_f_vector *v); -void pixman_f_transform_point_3d (const struct pixman_f_transform *t, - struct pixman_f_vector *v); -void pixman_f_transform_multiply (struct pixman_f_transform *dst, - const struct pixman_f_transform *l, - const struct pixman_f_transform *r); -void pixman_f_transform_init_scale (struct pixman_f_transform *t, - double sx, - double sy); -pixman_bool_t pixman_f_transform_scale (struct pixman_f_transform *forward, - struct pixman_f_transform *reverse, - double sx, - double sy); -void pixman_f_transform_init_rotate (struct pixman_f_transform *t, - double cos, - double sin); -pixman_bool_t pixman_f_transform_rotate (struct pixman_f_transform *forward, - struct pixman_f_transform *reverse, - double c, - double s); -void pixman_f_transform_init_translate (struct pixman_f_transform *t, - double tx, - double ty); -pixman_bool_t pixman_f_transform_translate (struct pixman_f_transform *forward, - struct pixman_f_transform *reverse, - double tx, - double ty); -pixman_bool_t pixman_f_transform_bounds (const struct pixman_f_transform *t, - struct pixman_box16 *b); -void pixman_f_transform_init_identity (struct pixman_f_transform *t); - -typedef enum -{ - PIXMAN_REPEAT_NONE, - PIXMAN_REPEAT_NORMAL, - PIXMAN_REPEAT_PAD, - PIXMAN_REPEAT_REFLECT -} pixman_repeat_t; - -typedef enum -{ - PIXMAN_FILTER_FAST, - PIXMAN_FILTER_GOOD, - PIXMAN_FILTER_BEST, - PIXMAN_FILTER_NEAREST, - PIXMAN_FILTER_BILINEAR, - PIXMAN_FILTER_CONVOLUTION -} pixman_filter_t; - -typedef enum -{ - PIXMAN_OP_CLEAR = 0x00, - PIXMAN_OP_SRC = 0x01, - PIXMAN_OP_DST = 0x02, - PIXMAN_OP_OVER = 0x03, - PIXMAN_OP_OVER_REVERSE = 0x04, - PIXMAN_OP_IN = 0x05, - PIXMAN_OP_IN_REVERSE = 0x06, - PIXMAN_OP_OUT = 0x07, - PIXMAN_OP_OUT_REVERSE = 0x08, - PIXMAN_OP_ATOP = 0x09, - PIXMAN_OP_ATOP_REVERSE = 0x0a, - PIXMAN_OP_XOR = 0x0b, - PIXMAN_OP_ADD = 0x0c, - PIXMAN_OP_SATURATE = 0x0d, - - PIXMAN_OP_DISJOINT_CLEAR = 0x10, - PIXMAN_OP_DISJOINT_SRC = 0x11, - PIXMAN_OP_DISJOINT_DST = 0x12, - PIXMAN_OP_DISJOINT_OVER = 0x13, - PIXMAN_OP_DISJOINT_OVER_REVERSE = 0x14, - PIXMAN_OP_DISJOINT_IN = 0x15, - PIXMAN_OP_DISJOINT_IN_REVERSE = 0x16, - PIXMAN_OP_DISJOINT_OUT = 0x17, - PIXMAN_OP_DISJOINT_OUT_REVERSE = 0x18, - PIXMAN_OP_DISJOINT_ATOP = 0x19, - PIXMAN_OP_DISJOINT_ATOP_REVERSE = 0x1a, - PIXMAN_OP_DISJOINT_XOR = 0x1b, - - PIXMAN_OP_CONJOINT_CLEAR = 0x20, - PIXMAN_OP_CONJOINT_SRC = 0x21, - PIXMAN_OP_CONJOINT_DST = 0x22, - PIXMAN_OP_CONJOINT_OVER = 0x23, - PIXMAN_OP_CONJOINT_OVER_REVERSE = 0x24, - PIXMAN_OP_CONJOINT_IN = 0x25, - PIXMAN_OP_CONJOINT_IN_REVERSE = 0x26, - PIXMAN_OP_CONJOINT_OUT = 0x27, - PIXMAN_OP_CONJOINT_OUT_REVERSE = 0x28, - PIXMAN_OP_CONJOINT_ATOP = 0x29, - PIXMAN_OP_CONJOINT_ATOP_REVERSE = 0x2a, - PIXMAN_OP_CONJOINT_XOR = 0x2b, - - PIXMAN_OP_MULTIPLY = 0x30, - PIXMAN_OP_SCREEN = 0x31, - PIXMAN_OP_OVERLAY = 0x32, - PIXMAN_OP_DARKEN = 0x33, - PIXMAN_OP_LIGHTEN = 0x34, - PIXMAN_OP_COLOR_DODGE = 0x35, - PIXMAN_OP_COLOR_BURN = 0x36, - PIXMAN_OP_HARD_LIGHT = 0x37, - PIXMAN_OP_SOFT_LIGHT = 0x38, - PIXMAN_OP_DIFFERENCE = 0x39, - PIXMAN_OP_EXCLUSION = 0x3a, - PIXMAN_OP_HSL_HUE = 0x3b, - PIXMAN_OP_HSL_SATURATION = 0x3c, - PIXMAN_OP_HSL_COLOR = 0x3d, - PIXMAN_OP_HSL_LUMINOSITY = 0x3e - -#ifdef PIXMAN_USE_INTERNAL_API - , - PIXMAN_N_OPERATORS, - PIXMAN_OP_NONE = PIXMAN_N_OPERATORS -#endif -} pixman_op_t; - -/* - * Regions - */ -typedef struct pixman_region16_data pixman_region16_data_t; -typedef struct pixman_box16 pixman_box16_t; -typedef struct pixman_rectangle16 pixman_rectangle16_t; -typedef struct pixman_region16 pixman_region16_t; - -struct pixman_region16_data { - long size; - long numRects; -/* pixman_box16_t rects[size]; in memory but not explicitly declared */ -}; - -struct pixman_rectangle16 -{ - int16_t x, y; - uint16_t width, height; -}; - -struct pixman_box16 -{ - int16_t x1, y1, x2, y2; -}; - -struct pixman_region16 -{ - pixman_box16_t extents; - pixman_region16_data_t *data; -}; - -typedef enum -{ - PIXMAN_REGION_OUT, - PIXMAN_REGION_IN, - PIXMAN_REGION_PART -} pixman_region_overlap_t; - -/* This function exists only to make it possible to preserve - * the X ABI - it should go away at first opportunity. - */ -void pixman_region_set_static_pointers (pixman_box16_t *empty_box, - pixman_region16_data_t *empty_data, - pixman_region16_data_t *broken_data); - -/* creation/destruction */ -void pixman_region_init (pixman_region16_t *region); -void pixman_region_init_rect (pixman_region16_t *region, - int x, - int y, - unsigned int width, - unsigned int height); -pixman_bool_t pixman_region_init_rects (pixman_region16_t *region, - const pixman_box16_t *boxes, - int count); -void pixman_region_init_with_extents (pixman_region16_t *region, - pixman_box16_t *extents); -void pixman_region_init_from_image (pixman_region16_t *region, - pixman_image_t *image); -void pixman_region_fini (pixman_region16_t *region); - - -/* manipulation */ -void pixman_region_translate (pixman_region16_t *region, - int x, - int y); -pixman_bool_t pixman_region_copy (pixman_region16_t *dest, - pixman_region16_t *source); -pixman_bool_t pixman_region_intersect (pixman_region16_t *new_reg, - pixman_region16_t *reg1, - pixman_region16_t *reg2); -pixman_bool_t pixman_region_union (pixman_region16_t *new_reg, - pixman_region16_t *reg1, - pixman_region16_t *reg2); -pixman_bool_t pixman_region_union_rect (pixman_region16_t *dest, - pixman_region16_t *source, - int x, - int y, - unsigned int width, - unsigned int height); -pixman_bool_t pixman_region_intersect_rect (pixman_region16_t *dest, - pixman_region16_t *source, - int x, - int y, - unsigned int width, - unsigned int height); -pixman_bool_t pixman_region_subtract (pixman_region16_t *reg_d, - pixman_region16_t *reg_m, - pixman_region16_t *reg_s); -pixman_bool_t pixman_region_inverse (pixman_region16_t *new_reg, - pixman_region16_t *reg1, - pixman_box16_t *inv_rect); -pixman_bool_t pixman_region_contains_point (pixman_region16_t *region, - int x, - int y, - pixman_box16_t *box); -pixman_region_overlap_t pixman_region_contains_rectangle (pixman_region16_t *region, - pixman_box16_t *prect); -pixman_bool_t pixman_region_not_empty (pixman_region16_t *region); -pixman_box16_t * pixman_region_extents (pixman_region16_t *region); -int pixman_region_n_rects (pixman_region16_t *region); -pixman_box16_t * pixman_region_rectangles (pixman_region16_t *region, - int *n_rects); -pixman_bool_t pixman_region_equal (pixman_region16_t *region1, - pixman_region16_t *region2); -pixman_bool_t pixman_region_selfcheck (pixman_region16_t *region); -void pixman_region_reset (pixman_region16_t *region, - pixman_box16_t *box); -/* - * 32 bit regions - */ -typedef struct pixman_region32_data pixman_region32_data_t; -typedef struct pixman_box32 pixman_box32_t; -typedef struct pixman_rectangle32 pixman_rectangle32_t; -typedef struct pixman_region32 pixman_region32_t; - -struct pixman_region32_data { - long size; - long numRects; -/* pixman_box32_t rects[size]; in memory but not explicitly declared */ -}; - -struct pixman_rectangle32 -{ - int32_t x, y; - uint32_t width, height; -}; - -struct pixman_box32 -{ - int32_t x1, y1, x2, y2; -}; - -struct pixman_region32 -{ - pixman_box32_t extents; - pixman_region32_data_t *data; -}; - -/* creation/destruction */ -void pixman_region32_init (pixman_region32_t *region); -void pixman_region32_init_rect (pixman_region32_t *region, - int x, - int y, - unsigned int width, - unsigned int height); -pixman_bool_t pixman_region32_init_rects (pixman_region32_t *region, - const pixman_box32_t *boxes, - int count); -void pixman_region32_init_with_extents (pixman_region32_t *region, - pixman_box32_t *extents); -void pixman_region32_init_from_image (pixman_region32_t *region, - pixman_image_t *image); -void pixman_region32_fini (pixman_region32_t *region); - - -/* manipulation */ -void pixman_region32_translate (pixman_region32_t *region, - int x, - int y); -pixman_bool_t pixman_region32_copy (pixman_region32_t *dest, - pixman_region32_t *source); -pixman_bool_t pixman_region32_intersect (pixman_region32_t *new_reg, - pixman_region32_t *reg1, - pixman_region32_t *reg2); -pixman_bool_t pixman_region32_union (pixman_region32_t *new_reg, - pixman_region32_t *reg1, - pixman_region32_t *reg2); -pixman_bool_t pixman_region32_intersect_rect (pixman_region32_t *dest, - pixman_region32_t *source, - int x, - int y, - unsigned int width, - unsigned int height); -pixman_bool_t pixman_region32_union_rect (pixman_region32_t *dest, - pixman_region32_t *source, - int x, - int y, - unsigned int width, - unsigned int height); -pixman_bool_t pixman_region32_subtract (pixman_region32_t *reg_d, - pixman_region32_t *reg_m, - pixman_region32_t *reg_s); -pixman_bool_t pixman_region32_inverse (pixman_region32_t *new_reg, - pixman_region32_t *reg1, - pixman_box32_t *inv_rect); -pixman_bool_t pixman_region32_contains_point (pixman_region32_t *region, - int x, - int y, - pixman_box32_t *box); -pixman_region_overlap_t pixman_region32_contains_rectangle (pixman_region32_t *region, - pixman_box32_t *prect); -pixman_bool_t pixman_region32_not_empty (pixman_region32_t *region); -pixman_box32_t * pixman_region32_extents (pixman_region32_t *region); -int pixman_region32_n_rects (pixman_region32_t *region); -pixman_box32_t * pixman_region32_rectangles (pixman_region32_t *region, - int *n_rects); -pixman_bool_t pixman_region32_equal (pixman_region32_t *region1, - pixman_region32_t *region2); -pixman_bool_t pixman_region32_selfcheck (pixman_region32_t *region); -void pixman_region32_reset (pixman_region32_t *region, - pixman_box32_t *box); - - -/* Copy / Fill / Misc */ -pixman_bool_t pixman_blt (uint32_t *src_bits, - uint32_t *dst_bits, - int src_stride, - int dst_stride, - int src_bpp, - int dst_bpp, - int src_x, - int src_y, - int dst_x, - int dst_y, - int width, - int height); -pixman_bool_t pixman_fill (uint32_t *bits, - int stride, - int bpp, - int x, - int y, - int width, - int height, - uint32_t _xor); - -int pixman_version (void); -const char* pixman_version_string (void); - -/* - * Images - */ -typedef struct pixman_indexed pixman_indexed_t; -typedef struct pixman_gradient_stop pixman_gradient_stop_t; - -typedef uint32_t (* pixman_read_memory_func_t) (const void *src, int size); -typedef void (* pixman_write_memory_func_t) (void *dst, uint32_t value, int size); - -typedef void (* pixman_image_destroy_func_t) (pixman_image_t *image, void *data); - -struct pixman_gradient_stop { - pixman_fixed_t x; - pixman_color_t color; -}; - -#define PIXMAN_MAX_INDEXED 256 /* XXX depth must be <= 8 */ - -#if PIXMAN_MAX_INDEXED <= 256 -typedef uint8_t pixman_index_type; -#endif - -struct pixman_indexed -{ - pixman_bool_t color; - uint32_t rgba[PIXMAN_MAX_INDEXED]; - pixman_index_type ent[32768]; -}; - -/* - * While the protocol is generous in format support, the - * sample implementation allows only packed RGB and GBR - * representations for data to simplify software rendering, - */ -#define PIXMAN_FORMAT(bpp,type,a,r,g,b) (((bpp) << 24) | \ - ((type) << 16) | \ - ((a) << 12) | \ - ((r) << 8) | \ - ((g) << 4) | \ - ((b))) - -#define PIXMAN_FORMAT_BPP(f) (((f) >> 24) ) -#define PIXMAN_FORMAT_TYPE(f) (((f) >> 16) & 0xff) -#define PIXMAN_FORMAT_A(f) (((f) >> 12) & 0x0f) -#define PIXMAN_FORMAT_R(f) (((f) >> 8) & 0x0f) -#define PIXMAN_FORMAT_G(f) (((f) >> 4) & 0x0f) -#define PIXMAN_FORMAT_B(f) (((f) ) & 0x0f) -#define PIXMAN_FORMAT_RGB(f) (((f) ) & 0xfff) -#define PIXMAN_FORMAT_VIS(f) (((f) ) & 0xffff) -#define PIXMAN_FORMAT_DEPTH(f) (PIXMAN_FORMAT_A(f) + \ - PIXMAN_FORMAT_R(f) + \ - PIXMAN_FORMAT_G(f) + \ - PIXMAN_FORMAT_B(f)) - -#define PIXMAN_TYPE_OTHER 0 -#define PIXMAN_TYPE_A 1 -#define PIXMAN_TYPE_ARGB 2 -#define PIXMAN_TYPE_ABGR 3 -#define PIXMAN_TYPE_COLOR 4 -#define PIXMAN_TYPE_GRAY 5 -#define PIXMAN_TYPE_YUY2 6 -#define PIXMAN_TYPE_YV12 7 -#define PIXMAN_TYPE_BGRA 8 - -#define PIXMAN_FORMAT_COLOR(f) \ - (PIXMAN_FORMAT_TYPE(f) == PIXMAN_TYPE_ARGB || \ - PIXMAN_FORMAT_TYPE(f) == PIXMAN_TYPE_ABGR || \ - PIXMAN_FORMAT_TYPE(f) == PIXMAN_TYPE_BGRA) - -/* 32bpp formats */ -typedef enum { - PIXMAN_a8r8g8b8 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ARGB,8,8,8,8), - PIXMAN_x8r8g8b8 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ARGB,0,8,8,8), - PIXMAN_a8b8g8r8 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ABGR,8,8,8,8), - PIXMAN_x8b8g8r8 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ABGR,0,8,8,8), - PIXMAN_b8g8r8a8 = PIXMAN_FORMAT(32,PIXMAN_TYPE_BGRA,8,8,8,8), - PIXMAN_b8g8r8x8 = PIXMAN_FORMAT(32,PIXMAN_TYPE_BGRA,0,8,8,8), - PIXMAN_x14r6g6b6 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ARGB,0,6,6,6), - PIXMAN_x2r10g10b10 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ARGB,0,10,10,10), - PIXMAN_a2r10g10b10 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ARGB,2,10,10,10), - PIXMAN_x2b10g10r10 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ABGR,0,10,10,10), - PIXMAN_a2b10g10r10 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ABGR,2,10,10,10), - -/* 24bpp formats */ - PIXMAN_r8g8b8 = PIXMAN_FORMAT(24,PIXMAN_TYPE_ARGB,0,8,8,8), - PIXMAN_b8g8r8 = PIXMAN_FORMAT(24,PIXMAN_TYPE_ABGR,0,8,8,8), - -/* 16bpp formats */ - PIXMAN_r5g6b5 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ARGB,0,5,6,5), - PIXMAN_b5g6r5 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ABGR,0,5,6,5), - - PIXMAN_a1r5g5b5 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ARGB,1,5,5,5), - PIXMAN_x1r5g5b5 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ARGB,0,5,5,5), - PIXMAN_a1b5g5r5 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ABGR,1,5,5,5), - PIXMAN_x1b5g5r5 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ABGR,0,5,5,5), - PIXMAN_a4r4g4b4 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ARGB,4,4,4,4), - PIXMAN_x4r4g4b4 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ARGB,0,4,4,4), - PIXMAN_a4b4g4r4 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ABGR,4,4,4,4), - PIXMAN_x4b4g4r4 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ABGR,0,4,4,4), - -/* 8bpp formats */ - PIXMAN_a8 = PIXMAN_FORMAT(8,PIXMAN_TYPE_A,8,0,0,0), - PIXMAN_r3g3b2 = PIXMAN_FORMAT(8,PIXMAN_TYPE_ARGB,0,3,3,2), - PIXMAN_b2g3r3 = PIXMAN_FORMAT(8,PIXMAN_TYPE_ABGR,0,3,3,2), - PIXMAN_a2r2g2b2 = PIXMAN_FORMAT(8,PIXMAN_TYPE_ARGB,2,2,2,2), - PIXMAN_a2b2g2r2 = PIXMAN_FORMAT(8,PIXMAN_TYPE_ABGR,2,2,2,2), - - PIXMAN_c8 = PIXMAN_FORMAT(8,PIXMAN_TYPE_COLOR,0,0,0,0), - PIXMAN_g8 = PIXMAN_FORMAT(8,PIXMAN_TYPE_GRAY,0,0,0,0), - - PIXMAN_x4a4 = PIXMAN_FORMAT(8,PIXMAN_TYPE_A,4,0,0,0), - - PIXMAN_x4c4 = PIXMAN_FORMAT(8,PIXMAN_TYPE_COLOR,0,0,0,0), - PIXMAN_x4g4 = PIXMAN_FORMAT(8,PIXMAN_TYPE_GRAY,0,0,0,0), - -/* 4bpp formats */ - PIXMAN_a4 = PIXMAN_FORMAT(4,PIXMAN_TYPE_A,4,0,0,0), - PIXMAN_r1g2b1 = PIXMAN_FORMAT(4,PIXMAN_TYPE_ARGB,0,1,2,1), - PIXMAN_b1g2r1 = PIXMAN_FORMAT(4,PIXMAN_TYPE_ABGR,0,1,2,1), - PIXMAN_a1r1g1b1 = PIXMAN_FORMAT(4,PIXMAN_TYPE_ARGB,1,1,1,1), - PIXMAN_a1b1g1r1 = PIXMAN_FORMAT(4,PIXMAN_TYPE_ABGR,1,1,1,1), - - PIXMAN_c4 = PIXMAN_FORMAT(4,PIXMAN_TYPE_COLOR,0,0,0,0), - PIXMAN_g4 = PIXMAN_FORMAT(4,PIXMAN_TYPE_GRAY,0,0,0,0), - -/* 1bpp formats */ - PIXMAN_a1 = PIXMAN_FORMAT(1,PIXMAN_TYPE_A,1,0,0,0), - - PIXMAN_g1 = PIXMAN_FORMAT(1,PIXMAN_TYPE_GRAY,0,0,0,0), - -/* YUV formats */ - PIXMAN_yuy2 = PIXMAN_FORMAT(16,PIXMAN_TYPE_YUY2,0,0,0,0), - PIXMAN_yv12 = PIXMAN_FORMAT(12,PIXMAN_TYPE_YV12,0,0,0,0) -} pixman_format_code_t; - -/* Querying supported format values. */ -pixman_bool_t pixman_format_supported_destination (pixman_format_code_t format); -pixman_bool_t pixman_format_supported_source (pixman_format_code_t format); - -/* Constructors */ -pixman_image_t *pixman_image_create_solid_fill (pixman_color_t *color); -pixman_image_t *pixman_image_create_linear_gradient (pixman_point_fixed_t *p1, - pixman_point_fixed_t *p2, - const pixman_gradient_stop_t *stops, - int n_stops); -pixman_image_t *pixman_image_create_radial_gradient (pixman_point_fixed_t *inner, - pixman_point_fixed_t *outer, - pixman_fixed_t inner_radius, - pixman_fixed_t outer_radius, - const pixman_gradient_stop_t *stops, - int n_stops); -pixman_image_t *pixman_image_create_conical_gradient (pixman_point_fixed_t *center, - pixman_fixed_t angle, - const pixman_gradient_stop_t *stops, - int n_stops); -pixman_image_t *pixman_image_create_bits (pixman_format_code_t format, - int width, - int height, - uint32_t *bits, - int rowstride_bytes); - -/* Destructor */ -pixman_image_t *pixman_image_ref (pixman_image_t *image); -pixman_bool_t pixman_image_unref (pixman_image_t *image); - -void pixman_image_set_destroy_function (pixman_image_t *image, - pixman_image_destroy_func_t function, - void *data); -void * pixman_image_get_destroy_data (pixman_image_t *image); - -/* Set properties */ -pixman_bool_t pixman_image_set_clip_region (pixman_image_t *image, - pixman_region16_t *region); -pixman_bool_t pixman_image_set_clip_region32 (pixman_image_t *image, - pixman_region32_t *region); -void pixman_image_set_has_client_clip (pixman_image_t *image, - pixman_bool_t clien_clip); -pixman_bool_t pixman_image_set_transform (pixman_image_t *image, - const pixman_transform_t *transform); -void pixman_image_set_repeat (pixman_image_t *image, - pixman_repeat_t repeat); -pixman_bool_t pixman_image_set_filter (pixman_image_t *image, - pixman_filter_t filter, - const pixman_fixed_t *filter_params, - int n_filter_params); -void pixman_image_set_source_clipping (pixman_image_t *image, - pixman_bool_t source_clipping); -void pixman_image_set_alpha_map (pixman_image_t *image, - pixman_image_t *alpha_map, - int16_t x, - int16_t y); -void pixman_image_set_component_alpha (pixman_image_t *image, - pixman_bool_t component_alpha); -pixman_bool_t pixman_image_get_component_alpha (pixman_image_t *image); -void pixman_image_set_accessors (pixman_image_t *image, - pixman_read_memory_func_t read_func, - pixman_write_memory_func_t write_func); -void pixman_image_set_indexed (pixman_image_t *image, - const pixman_indexed_t *indexed); -uint32_t *pixman_image_get_data (pixman_image_t *image); -int pixman_image_get_width (pixman_image_t *image); -int pixman_image_get_height (pixman_image_t *image); -int pixman_image_get_stride (pixman_image_t *image); /* in bytes */ -int pixman_image_get_depth (pixman_image_t *image); -pixman_format_code_t pixman_image_get_format (pixman_image_t *image); -pixman_bool_t pixman_image_fill_rectangles (pixman_op_t op, - pixman_image_t *image, - pixman_color_t *color, - int n_rects, - const pixman_rectangle16_t *rects); -pixman_bool_t pixman_image_fill_boxes (pixman_op_t op, - pixman_image_t *dest, - pixman_color_t *color, - int n_boxes, - const pixman_box32_t *boxes); - -/* Composite */ -pixman_bool_t pixman_compute_composite_region (pixman_region16_t *region, - pixman_image_t *src_image, - pixman_image_t *mask_image, - pixman_image_t *dst_image, - int16_t src_x, - int16_t src_y, - int16_t mask_x, - int16_t mask_y, - int16_t dest_x, - int16_t dest_y, - uint16_t width, - uint16_t height); -void pixman_image_composite (pixman_op_t op, - pixman_image_t *src, - pixman_image_t *mask, - pixman_image_t *dest, - int16_t src_x, - int16_t src_y, - int16_t mask_x, - int16_t mask_y, - int16_t dest_x, - int16_t dest_y, - uint16_t width, - uint16_t height); -void pixman_image_composite32 (pixman_op_t op, - pixman_image_t *src, - pixman_image_t *mask, - pixman_image_t *dest, - int32_t src_x, - int32_t src_y, - int32_t mask_x, - int32_t mask_y, - int32_t dest_x, - int32_t dest_y, - int32_t width, - int32_t height); - -/* Executive Summary: This function is a no-op that only exists - * for historical reasons. - * - * There used to be a bug in the X server where it would rely on - * out-of-bounds accesses when it was asked to composite with a - * window as the source. It would create a pixman image pointing - * to some bogus position in memory, but then set a clip region - * to the position where the actual bits were. - * - * Due to a bug in old versions of pixman, where it would not clip - * against the image bounds when a clip region was set, this would - * actually work. So when the pixman bug was fixed, a workaround was - * added to allow certain out-of-bound accesses. This function disabled - * those workarounds. - * - * Since 0.21.2, pixman doesn't do these workarounds anymore, so now this - * function is a no-op. - */ -void pixman_disable_out_of_bounds_workaround (void); - -/* - * Trapezoids - */ -typedef struct pixman_edge pixman_edge_t; -typedef struct pixman_trapezoid pixman_trapezoid_t; -typedef struct pixman_trap pixman_trap_t; -typedef struct pixman_span_fix pixman_span_fix_t; -typedef struct pixman_triangle pixman_triangle_t; - -/* - * An edge structure. This represents a single polygon edge - * and can be quickly stepped across small or large gaps in the - * sample grid - */ -struct pixman_edge -{ - pixman_fixed_t x; - pixman_fixed_t e; - pixman_fixed_t stepx; - pixman_fixed_t signdx; - pixman_fixed_t dy; - pixman_fixed_t dx; - - pixman_fixed_t stepx_small; - pixman_fixed_t stepx_big; - pixman_fixed_t dx_small; - pixman_fixed_t dx_big; -}; - -struct pixman_trapezoid -{ - pixman_fixed_t top, bottom; - pixman_line_fixed_t left, right; -}; - -struct pixman_triangle -{ - pixman_point_fixed_t p1, p2, p3; -}; - -/* whether 't' is a well defined not obviously empty trapezoid */ -#define pixman_trapezoid_valid(t) \ - ((t)->left.p1.y != (t)->left.p2.y && \ - (t)->right.p1.y != (t)->right.p2.y && \ - (int) ((t)->bottom - (t)->top) > 0) - -struct pixman_span_fix -{ - pixman_fixed_t l, r, y; -}; - -struct pixman_trap -{ - pixman_span_fix_t top, bot; -}; - -pixman_fixed_t pixman_sample_ceil_y (pixman_fixed_t y, - int bpp); -pixman_fixed_t pixman_sample_floor_y (pixman_fixed_t y, - int bpp); -void pixman_edge_step (pixman_edge_t *e, - int n); -void pixman_edge_init (pixman_edge_t *e, - int bpp, - pixman_fixed_t y_start, - pixman_fixed_t x_top, - pixman_fixed_t y_top, - pixman_fixed_t x_bot, - pixman_fixed_t y_bot); -void pixman_line_fixed_edge_init (pixman_edge_t *e, - int bpp, - pixman_fixed_t y, - const pixman_line_fixed_t *line, - int x_off, - int y_off); -void pixman_rasterize_edges (pixman_image_t *image, - pixman_edge_t *l, - pixman_edge_t *r, - pixman_fixed_t t, - pixman_fixed_t b); -void pixman_add_traps (pixman_image_t *image, - int16_t x_off, - int16_t y_off, - int ntrap, - pixman_trap_t *traps); -void pixman_add_trapezoids (pixman_image_t *image, - int16_t x_off, - int y_off, - int ntraps, - const pixman_trapezoid_t *traps); -void pixman_rasterize_trapezoid (pixman_image_t *image, - const pixman_trapezoid_t *trap, - int x_off, - int y_off); -void pixman_composite_trapezoids (pixman_op_t op, - pixman_image_t * src, - pixman_image_t * dst, - pixman_format_code_t mask_format, - int x_src, - int y_src, - int x_dst, - int y_dst, - int n_traps, - const pixman_trapezoid_t * traps); -void pixman_composite_triangles (pixman_op_t op, - pixman_image_t * src, - pixman_image_t * dst, - pixman_format_code_t mask_format, - int x_src, - int y_src, - int x_dst, - int y_dst, - int n_tris, - const pixman_triangle_t * tris); -void pixman_add_triangles (pixman_image_t *image, - int32_t x_off, - int32_t y_off, - int n_tris, - const pixman_triangle_t *tris); - -PIXMAN_END_DECLS - -#endif /* PIXMAN_H__ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/* + * Copyright © 1998, 2004 Keith Packard + * Copyright 2007 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef PIXMAN_H__ +#define PIXMAN_H__ + +#include + +#ifdef __cplusplus +#define PIXMAN_BEGIN_DECLS extern "C" { +#define PIXMAN_END_DECLS } +#else +#define PIXMAN_BEGIN_DECLS +#define PIXMAN_END_DECLS +#endif + +PIXMAN_BEGIN_DECLS + +/* + * Standard integers + */ + +#if !defined (PIXMAN_DONT_DEFINE_STDINT) + +#if defined (_SVR4) || defined (SVR4) || defined (__OpenBSD__) || defined (_sgi) || defined (__sun) || defined (sun) || defined (__digital__) || defined (__HP_cc) +# include +/* VS 2010 (_MSC_VER 1600) has stdint.h */ +#elif defined (_MSC_VER) && _MSC_VER < 1600 +typedef __int8 int8_t; +typedef unsigned __int8 uint8_t; +typedef __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +#elif defined (_AIX) +# include +#else +# include +#endif + +#endif + +/* + * Boolean + */ +typedef int pixman_bool_t; + +/* + * Fixpoint numbers + */ +typedef int64_t pixman_fixed_32_32_t; +typedef pixman_fixed_32_32_t pixman_fixed_48_16_t; +typedef uint32_t pixman_fixed_1_31_t; +typedef uint32_t pixman_fixed_1_16_t; +typedef int32_t pixman_fixed_16_16_t; +typedef pixman_fixed_16_16_t pixman_fixed_t; + +#define pixman_fixed_e ((pixman_fixed_t) 1) +#define pixman_fixed_1 (pixman_int_to_fixed(1)) +#define pixman_fixed_1_minus_e (pixman_fixed_1 - pixman_fixed_e) +#define pixman_fixed_minus_1 (pixman_int_to_fixed(-1)) +#define pixman_fixed_to_int(f) ((int) ((f) >> 16)) +#define pixman_int_to_fixed(i) ((pixman_fixed_t) ((i) << 16)) +#define pixman_fixed_to_double(f) (double) ((f) / (double) pixman_fixed_1) +#define pixman_double_to_fixed(d) ((pixman_fixed_t) ((d) * 65536.0)) +#define pixman_fixed_frac(f) ((f) & pixman_fixed_1_minus_e) +#define pixman_fixed_floor(f) ((f) & ~pixman_fixed_1_minus_e) +#define pixman_fixed_ceil(f) pixman_fixed_floor ((f) + pixman_fixed_1_minus_e) +#define pixman_fixed_fraction(f) ((f) & pixman_fixed_1_minus_e) +#define pixman_fixed_mod_2(f) ((f) & (pixman_fixed1 | pixman_fixed_1_minus_e)) +#define pixman_max_fixed_48_16 ((pixman_fixed_48_16_t) 0x7fffffff) +#define pixman_min_fixed_48_16 (-((pixman_fixed_48_16_t) 1 << 31)) + +/* + * Misc structs + */ +typedef struct pixman_color pixman_color_t; +typedef struct pixman_point_fixed pixman_point_fixed_t; +typedef struct pixman_line_fixed pixman_line_fixed_t; +typedef struct pixman_vector pixman_vector_t; +typedef struct pixman_transform pixman_transform_t; + +struct pixman_color +{ + uint16_t red; + uint16_t green; + uint16_t blue; + uint16_t alpha; +}; + +struct pixman_point_fixed +{ + pixman_fixed_t x; + pixman_fixed_t y; +}; + +struct pixman_line_fixed +{ + pixman_point_fixed_t p1, p2; +}; + +/* + * Fixed point matrices + */ + +struct pixman_vector +{ + pixman_fixed_t vector[3]; +}; + +struct pixman_transform +{ + pixman_fixed_t matrix[3][3]; +}; + +/* forward declaration (sorry) */ +struct pixman_box16; +typedef union pixman_image pixman_image_t; + +void pixman_transform_init_identity (struct pixman_transform *matrix); +pixman_bool_t pixman_transform_point_3d (const struct pixman_transform *transform, + struct pixman_vector *vector); +pixman_bool_t pixman_transform_point (const struct pixman_transform *transform, + struct pixman_vector *vector); +pixman_bool_t pixman_transform_multiply (struct pixman_transform *dst, + const struct pixman_transform *l, + const struct pixman_transform *r); +void pixman_transform_init_scale (struct pixman_transform *t, + pixman_fixed_t sx, + pixman_fixed_t sy); +pixman_bool_t pixman_transform_scale (struct pixman_transform *forward, + struct pixman_transform *reverse, + pixman_fixed_t sx, + pixman_fixed_t sy); +void pixman_transform_init_rotate (struct pixman_transform *t, + pixman_fixed_t cos, + pixman_fixed_t sin); +pixman_bool_t pixman_transform_rotate (struct pixman_transform *forward, + struct pixman_transform *reverse, + pixman_fixed_t c, + pixman_fixed_t s); +void pixman_transform_init_translate (struct pixman_transform *t, + pixman_fixed_t tx, + pixman_fixed_t ty); +pixman_bool_t pixman_transform_translate (struct pixman_transform *forward, + struct pixman_transform *reverse, + pixman_fixed_t tx, + pixman_fixed_t ty); +pixman_bool_t pixman_transform_bounds (const struct pixman_transform *matrix, + struct pixman_box16 *b); +pixman_bool_t pixman_transform_invert (struct pixman_transform *dst, + const struct pixman_transform *src); +pixman_bool_t pixman_transform_is_identity (const struct pixman_transform *t); +pixman_bool_t pixman_transform_is_scale (const struct pixman_transform *t); +pixman_bool_t pixman_transform_is_int_translate (const struct pixman_transform *t); +pixman_bool_t pixman_transform_is_inverse (const struct pixman_transform *a, + const struct pixman_transform *b); + +/* + * Floating point matrices + */ +struct pixman_f_vector +{ + double v[3]; +}; + +struct pixman_f_transform +{ + double m[3][3]; +}; + +pixman_bool_t pixman_transform_from_pixman_f_transform (struct pixman_transform *t, + const struct pixman_f_transform *ft); +void pixman_f_transform_from_pixman_transform (struct pixman_f_transform *ft, + const struct pixman_transform *t); +pixman_bool_t pixman_f_transform_invert (struct pixman_f_transform *dst, + const struct pixman_f_transform *src); +pixman_bool_t pixman_f_transform_point (const struct pixman_f_transform *t, + struct pixman_f_vector *v); +void pixman_f_transform_point_3d (const struct pixman_f_transform *t, + struct pixman_f_vector *v); +void pixman_f_transform_multiply (struct pixman_f_transform *dst, + const struct pixman_f_transform *l, + const struct pixman_f_transform *r); +void pixman_f_transform_init_scale (struct pixman_f_transform *t, + double sx, + double sy); +pixman_bool_t pixman_f_transform_scale (struct pixman_f_transform *forward, + struct pixman_f_transform *reverse, + double sx, + double sy); +void pixman_f_transform_init_rotate (struct pixman_f_transform *t, + double cos, + double sin); +pixman_bool_t pixman_f_transform_rotate (struct pixman_f_transform *forward, + struct pixman_f_transform *reverse, + double c, + double s); +void pixman_f_transform_init_translate (struct pixman_f_transform *t, + double tx, + double ty); +pixman_bool_t pixman_f_transform_translate (struct pixman_f_transform *forward, + struct pixman_f_transform *reverse, + double tx, + double ty); +pixman_bool_t pixman_f_transform_bounds (const struct pixman_f_transform *t, + struct pixman_box16 *b); +void pixman_f_transform_init_identity (struct pixman_f_transform *t); + +typedef enum +{ + PIXMAN_REPEAT_NONE, + PIXMAN_REPEAT_NORMAL, + PIXMAN_REPEAT_PAD, + PIXMAN_REPEAT_REFLECT +} pixman_repeat_t; + +typedef enum +{ + PIXMAN_FILTER_FAST, + PIXMAN_FILTER_GOOD, + PIXMAN_FILTER_BEST, + PIXMAN_FILTER_NEAREST, + PIXMAN_FILTER_BILINEAR, + PIXMAN_FILTER_CONVOLUTION +} pixman_filter_t; + +typedef enum +{ + PIXMAN_OP_CLEAR = 0x00, + PIXMAN_OP_SRC = 0x01, + PIXMAN_OP_DST = 0x02, + PIXMAN_OP_OVER = 0x03, + PIXMAN_OP_OVER_REVERSE = 0x04, + PIXMAN_OP_IN = 0x05, + PIXMAN_OP_IN_REVERSE = 0x06, + PIXMAN_OP_OUT = 0x07, + PIXMAN_OP_OUT_REVERSE = 0x08, + PIXMAN_OP_ATOP = 0x09, + PIXMAN_OP_ATOP_REVERSE = 0x0a, + PIXMAN_OP_XOR = 0x0b, + PIXMAN_OP_ADD = 0x0c, + PIXMAN_OP_SATURATE = 0x0d, + + PIXMAN_OP_DISJOINT_CLEAR = 0x10, + PIXMAN_OP_DISJOINT_SRC = 0x11, + PIXMAN_OP_DISJOINT_DST = 0x12, + PIXMAN_OP_DISJOINT_OVER = 0x13, + PIXMAN_OP_DISJOINT_OVER_REVERSE = 0x14, + PIXMAN_OP_DISJOINT_IN = 0x15, + PIXMAN_OP_DISJOINT_IN_REVERSE = 0x16, + PIXMAN_OP_DISJOINT_OUT = 0x17, + PIXMAN_OP_DISJOINT_OUT_REVERSE = 0x18, + PIXMAN_OP_DISJOINT_ATOP = 0x19, + PIXMAN_OP_DISJOINT_ATOP_REVERSE = 0x1a, + PIXMAN_OP_DISJOINT_XOR = 0x1b, + + PIXMAN_OP_CONJOINT_CLEAR = 0x20, + PIXMAN_OP_CONJOINT_SRC = 0x21, + PIXMAN_OP_CONJOINT_DST = 0x22, + PIXMAN_OP_CONJOINT_OVER = 0x23, + PIXMAN_OP_CONJOINT_OVER_REVERSE = 0x24, + PIXMAN_OP_CONJOINT_IN = 0x25, + PIXMAN_OP_CONJOINT_IN_REVERSE = 0x26, + PIXMAN_OP_CONJOINT_OUT = 0x27, + PIXMAN_OP_CONJOINT_OUT_REVERSE = 0x28, + PIXMAN_OP_CONJOINT_ATOP = 0x29, + PIXMAN_OP_CONJOINT_ATOP_REVERSE = 0x2a, + PIXMAN_OP_CONJOINT_XOR = 0x2b, + + PIXMAN_OP_MULTIPLY = 0x30, + PIXMAN_OP_SCREEN = 0x31, + PIXMAN_OP_OVERLAY = 0x32, + PIXMAN_OP_DARKEN = 0x33, + PIXMAN_OP_LIGHTEN = 0x34, + PIXMAN_OP_COLOR_DODGE = 0x35, + PIXMAN_OP_COLOR_BURN = 0x36, + PIXMAN_OP_HARD_LIGHT = 0x37, + PIXMAN_OP_SOFT_LIGHT = 0x38, + PIXMAN_OP_DIFFERENCE = 0x39, + PIXMAN_OP_EXCLUSION = 0x3a, + PIXMAN_OP_HSL_HUE = 0x3b, + PIXMAN_OP_HSL_SATURATION = 0x3c, + PIXMAN_OP_HSL_COLOR = 0x3d, + PIXMAN_OP_HSL_LUMINOSITY = 0x3e + +#ifdef PIXMAN_USE_INTERNAL_API + , + PIXMAN_N_OPERATORS, + PIXMAN_OP_NONE = PIXMAN_N_OPERATORS +#endif +} pixman_op_t; + +/* + * Regions + */ +typedef struct pixman_region16_data pixman_region16_data_t; +typedef struct pixman_box16 pixman_box16_t; +typedef struct pixman_rectangle16 pixman_rectangle16_t; +typedef struct pixman_region16 pixman_region16_t; + +struct pixman_region16_data { + long size; + long numRects; +/* pixman_box16_t rects[size]; in memory but not explicitly declared */ +}; + +struct pixman_rectangle16 +{ + int16_t x, y; + uint16_t width, height; +}; + +struct pixman_box16 +{ + int16_t x1, y1, x2, y2; +}; + +struct pixman_region16 +{ + pixman_box16_t extents; + pixman_region16_data_t *data; +}; + +typedef enum +{ + PIXMAN_REGION_OUT, + PIXMAN_REGION_IN, + PIXMAN_REGION_PART +} pixman_region_overlap_t; + +/* This function exists only to make it possible to preserve + * the X ABI - it should go away at first opportunity. + */ +void pixman_region_set_static_pointers (pixman_box16_t *empty_box, + pixman_region16_data_t *empty_data, + pixman_region16_data_t *broken_data); + +/* creation/destruction */ +void pixman_region_init (pixman_region16_t *region); +void pixman_region_init_rect (pixman_region16_t *region, + int x, + int y, + unsigned int width, + unsigned int height); +pixman_bool_t pixman_region_init_rects (pixman_region16_t *region, + const pixman_box16_t *boxes, + int count); +void pixman_region_init_with_extents (pixman_region16_t *region, + pixman_box16_t *extents); +void pixman_region_init_from_image (pixman_region16_t *region, + pixman_image_t *image); +void pixman_region_fini (pixman_region16_t *region); + + +/* manipulation */ +void pixman_region_translate (pixman_region16_t *region, + int x, + int y); +pixman_bool_t pixman_region_copy (pixman_region16_t *dest, + pixman_region16_t *source); +pixman_bool_t pixman_region_intersect (pixman_region16_t *new_reg, + pixman_region16_t *reg1, + pixman_region16_t *reg2); +pixman_bool_t pixman_region_union (pixman_region16_t *new_reg, + pixman_region16_t *reg1, + pixman_region16_t *reg2); +pixman_bool_t pixman_region_union_rect (pixman_region16_t *dest, + pixman_region16_t *source, + int x, + int y, + unsigned int width, + unsigned int height); +pixman_bool_t pixman_region_intersect_rect (pixman_region16_t *dest, + pixman_region16_t *source, + int x, + int y, + unsigned int width, + unsigned int height); +pixman_bool_t pixman_region_subtract (pixman_region16_t *reg_d, + pixman_region16_t *reg_m, + pixman_region16_t *reg_s); +pixman_bool_t pixman_region_inverse (pixman_region16_t *new_reg, + pixman_region16_t *reg1, + pixman_box16_t *inv_rect); +pixman_bool_t pixman_region_contains_point (pixman_region16_t *region, + int x, + int y, + pixman_box16_t *box); +pixman_region_overlap_t pixman_region_contains_rectangle (pixman_region16_t *region, + pixman_box16_t *prect); +pixman_bool_t pixman_region_not_empty (pixman_region16_t *region); +pixman_box16_t * pixman_region_extents (pixman_region16_t *region); +int pixman_region_n_rects (pixman_region16_t *region); +pixman_box16_t * pixman_region_rectangles (pixman_region16_t *region, + int *n_rects); +pixman_bool_t pixman_region_equal (pixman_region16_t *region1, + pixman_region16_t *region2); +pixman_bool_t pixman_region_selfcheck (pixman_region16_t *region); +void pixman_region_reset (pixman_region16_t *region, + pixman_box16_t *box); +/* + * 32 bit regions + */ +typedef struct pixman_region32_data pixman_region32_data_t; +typedef struct pixman_box32 pixman_box32_t; +typedef struct pixman_rectangle32 pixman_rectangle32_t; +typedef struct pixman_region32 pixman_region32_t; + +struct pixman_region32_data { + long size; + long numRects; +/* pixman_box32_t rects[size]; in memory but not explicitly declared */ +}; + +struct pixman_rectangle32 +{ + int32_t x, y; + uint32_t width, height; +}; + +struct pixman_box32 +{ + int32_t x1, y1, x2, y2; +}; + +struct pixman_region32 +{ + pixman_box32_t extents; + pixman_region32_data_t *data; +}; + +/* creation/destruction */ +void pixman_region32_init (pixman_region32_t *region); +void pixman_region32_init_rect (pixman_region32_t *region, + int x, + int y, + unsigned int width, + unsigned int height); +pixman_bool_t pixman_region32_init_rects (pixman_region32_t *region, + const pixman_box32_t *boxes, + int count); +void pixman_region32_init_with_extents (pixman_region32_t *region, + pixman_box32_t *extents); +void pixman_region32_init_from_image (pixman_region32_t *region, + pixman_image_t *image); +void pixman_region32_fini (pixman_region32_t *region); + + +/* manipulation */ +void pixman_region32_translate (pixman_region32_t *region, + int x, + int y); +pixman_bool_t pixman_region32_copy (pixman_region32_t *dest, + pixman_region32_t *source); +pixman_bool_t pixman_region32_intersect (pixman_region32_t *new_reg, + pixman_region32_t *reg1, + pixman_region32_t *reg2); +pixman_bool_t pixman_region32_union (pixman_region32_t *new_reg, + pixman_region32_t *reg1, + pixman_region32_t *reg2); +pixman_bool_t pixman_region32_intersect_rect (pixman_region32_t *dest, + pixman_region32_t *source, + int x, + int y, + unsigned int width, + unsigned int height); +pixman_bool_t pixman_region32_union_rect (pixman_region32_t *dest, + pixman_region32_t *source, + int x, + int y, + unsigned int width, + unsigned int height); +pixman_bool_t pixman_region32_subtract (pixman_region32_t *reg_d, + pixman_region32_t *reg_m, + pixman_region32_t *reg_s); +pixman_bool_t pixman_region32_inverse (pixman_region32_t *new_reg, + pixman_region32_t *reg1, + pixman_box32_t *inv_rect); +pixman_bool_t pixman_region32_contains_point (pixman_region32_t *region, + int x, + int y, + pixman_box32_t *box); +pixman_region_overlap_t pixman_region32_contains_rectangle (pixman_region32_t *region, + pixman_box32_t *prect); +pixman_bool_t pixman_region32_not_empty (pixman_region32_t *region); +pixman_box32_t * pixman_region32_extents (pixman_region32_t *region); +int pixman_region32_n_rects (pixman_region32_t *region); +pixman_box32_t * pixman_region32_rectangles (pixman_region32_t *region, + int *n_rects); +pixman_bool_t pixman_region32_equal (pixman_region32_t *region1, + pixman_region32_t *region2); +pixman_bool_t pixman_region32_selfcheck (pixman_region32_t *region); +void pixman_region32_reset (pixman_region32_t *region, + pixman_box32_t *box); + + +/* Copy / Fill / Misc */ +pixman_bool_t pixman_blt (uint32_t *src_bits, + uint32_t *dst_bits, + int src_stride, + int dst_stride, + int src_bpp, + int dst_bpp, + int src_x, + int src_y, + int dst_x, + int dst_y, + int width, + int height); +pixman_bool_t pixman_fill (uint32_t *bits, + int stride, + int bpp, + int x, + int y, + int width, + int height, + uint32_t _xor); + +int pixman_version (void); +const char* pixman_version_string (void); + +/* + * Images + */ +typedef struct pixman_indexed pixman_indexed_t; +typedef struct pixman_gradient_stop pixman_gradient_stop_t; + +typedef uint32_t (* pixman_read_memory_func_t) (const void *src, int size); +typedef void (* pixman_write_memory_func_t) (void *dst, uint32_t value, int size); + +typedef void (* pixman_image_destroy_func_t) (pixman_image_t *image, void *data); + +struct pixman_gradient_stop { + pixman_fixed_t x; + pixman_color_t color; +}; + +#define PIXMAN_MAX_INDEXED 256 /* XXX depth must be <= 8 */ + +#if PIXMAN_MAX_INDEXED <= 256 +typedef uint8_t pixman_index_type; +#endif + +struct pixman_indexed +{ + pixman_bool_t color; + uint32_t rgba[PIXMAN_MAX_INDEXED]; + pixman_index_type ent[32768]; +}; + +/* + * While the protocol is generous in format support, the + * sample implementation allows only packed RGB and GBR + * representations for data to simplify software rendering, + */ +#define PIXMAN_FORMAT(bpp,type,a,r,g,b) (((bpp) << 24) | \ + ((type) << 16) | \ + ((a) << 12) | \ + ((r) << 8) | \ + ((g) << 4) | \ + ((b))) + +#define PIXMAN_FORMAT_BPP(f) (((f) >> 24) ) +#define PIXMAN_FORMAT_TYPE(f) (((f) >> 16) & 0xff) +#define PIXMAN_FORMAT_A(f) (((f) >> 12) & 0x0f) +#define PIXMAN_FORMAT_R(f) (((f) >> 8) & 0x0f) +#define PIXMAN_FORMAT_G(f) (((f) >> 4) & 0x0f) +#define PIXMAN_FORMAT_B(f) (((f) ) & 0x0f) +#define PIXMAN_FORMAT_RGB(f) (((f) ) & 0xfff) +#define PIXMAN_FORMAT_VIS(f) (((f) ) & 0xffff) +#define PIXMAN_FORMAT_DEPTH(f) (PIXMAN_FORMAT_A(f) + \ + PIXMAN_FORMAT_R(f) + \ + PIXMAN_FORMAT_G(f) + \ + PIXMAN_FORMAT_B(f)) + +#define PIXMAN_TYPE_OTHER 0 +#define PIXMAN_TYPE_A 1 +#define PIXMAN_TYPE_ARGB 2 +#define PIXMAN_TYPE_ABGR 3 +#define PIXMAN_TYPE_COLOR 4 +#define PIXMAN_TYPE_GRAY 5 +#define PIXMAN_TYPE_YUY2 6 +#define PIXMAN_TYPE_YV12 7 +#define PIXMAN_TYPE_BGRA 8 +#define PIXMAN_TYPE_RGBA 9 + +#define PIXMAN_FORMAT_COLOR(f) \ + (PIXMAN_FORMAT_TYPE(f) == PIXMAN_TYPE_ARGB || \ + PIXMAN_FORMAT_TYPE(f) == PIXMAN_TYPE_ABGR || \ + PIXMAN_FORMAT_TYPE(f) == PIXMAN_TYPE_BGRA || \ + PIXMAN_FORMAT_TYPE(f) == PIXMAN_TYPE_RGBA) + +/* 32bpp formats */ +typedef enum { + PIXMAN_a8r8g8b8 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ARGB,8,8,8,8), + PIXMAN_x8r8g8b8 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ARGB,0,8,8,8), + PIXMAN_a8b8g8r8 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ABGR,8,8,8,8), + PIXMAN_x8b8g8r8 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ABGR,0,8,8,8), + PIXMAN_b8g8r8a8 = PIXMAN_FORMAT(32,PIXMAN_TYPE_BGRA,8,8,8,8), + PIXMAN_b8g8r8x8 = PIXMAN_FORMAT(32,PIXMAN_TYPE_BGRA,0,8,8,8), + PIXMAN_r8g8b8a8 = PIXMAN_FORMAT(32,PIXMAN_TYPE_RGBA,8,8,8,8), + PIXMAN_r8g8b8x8 = PIXMAN_FORMAT(32,PIXMAN_TYPE_RGBA,0,8,8,8), + PIXMAN_x14r6g6b6 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ARGB,0,6,6,6), + PIXMAN_x2r10g10b10 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ARGB,0,10,10,10), + PIXMAN_a2r10g10b10 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ARGB,2,10,10,10), + PIXMAN_x2b10g10r10 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ABGR,0,10,10,10), + PIXMAN_a2b10g10r10 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ABGR,2,10,10,10), + +/* 24bpp formats */ + PIXMAN_r8g8b8 = PIXMAN_FORMAT(24,PIXMAN_TYPE_ARGB,0,8,8,8), + PIXMAN_b8g8r8 = PIXMAN_FORMAT(24,PIXMAN_TYPE_ABGR,0,8,8,8), + +/* 16bpp formats */ + PIXMAN_r5g6b5 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ARGB,0,5,6,5), + PIXMAN_b5g6r5 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ABGR,0,5,6,5), + + PIXMAN_a1r5g5b5 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ARGB,1,5,5,5), + PIXMAN_x1r5g5b5 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ARGB,0,5,5,5), + PIXMAN_a1b5g5r5 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ABGR,1,5,5,5), + PIXMAN_x1b5g5r5 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ABGR,0,5,5,5), + PIXMAN_a4r4g4b4 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ARGB,4,4,4,4), + PIXMAN_x4r4g4b4 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ARGB,0,4,4,4), + PIXMAN_a4b4g4r4 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ABGR,4,4,4,4), + PIXMAN_x4b4g4r4 = PIXMAN_FORMAT(16,PIXMAN_TYPE_ABGR,0,4,4,4), + +/* 8bpp formats */ + PIXMAN_a8 = PIXMAN_FORMAT(8,PIXMAN_TYPE_A,8,0,0,0), + PIXMAN_r3g3b2 = PIXMAN_FORMAT(8,PIXMAN_TYPE_ARGB,0,3,3,2), + PIXMAN_b2g3r3 = PIXMAN_FORMAT(8,PIXMAN_TYPE_ABGR,0,3,3,2), + PIXMAN_a2r2g2b2 = PIXMAN_FORMAT(8,PIXMAN_TYPE_ARGB,2,2,2,2), + PIXMAN_a2b2g2r2 = PIXMAN_FORMAT(8,PIXMAN_TYPE_ABGR,2,2,2,2), + + PIXMAN_c8 = PIXMAN_FORMAT(8,PIXMAN_TYPE_COLOR,0,0,0,0), + PIXMAN_g8 = PIXMAN_FORMAT(8,PIXMAN_TYPE_GRAY,0,0,0,0), + + PIXMAN_x4a4 = PIXMAN_FORMAT(8,PIXMAN_TYPE_A,4,0,0,0), + + PIXMAN_x4c4 = PIXMAN_FORMAT(8,PIXMAN_TYPE_COLOR,0,0,0,0), + PIXMAN_x4g4 = PIXMAN_FORMAT(8,PIXMAN_TYPE_GRAY,0,0,0,0), + +/* 4bpp formats */ + PIXMAN_a4 = PIXMAN_FORMAT(4,PIXMAN_TYPE_A,4,0,0,0), + PIXMAN_r1g2b1 = PIXMAN_FORMAT(4,PIXMAN_TYPE_ARGB,0,1,2,1), + PIXMAN_b1g2r1 = PIXMAN_FORMAT(4,PIXMAN_TYPE_ABGR,0,1,2,1), + PIXMAN_a1r1g1b1 = PIXMAN_FORMAT(4,PIXMAN_TYPE_ARGB,1,1,1,1), + PIXMAN_a1b1g1r1 = PIXMAN_FORMAT(4,PIXMAN_TYPE_ABGR,1,1,1,1), + + PIXMAN_c4 = PIXMAN_FORMAT(4,PIXMAN_TYPE_COLOR,0,0,0,0), + PIXMAN_g4 = PIXMAN_FORMAT(4,PIXMAN_TYPE_GRAY,0,0,0,0), + +/* 1bpp formats */ + PIXMAN_a1 = PIXMAN_FORMAT(1,PIXMAN_TYPE_A,1,0,0,0), + + PIXMAN_g1 = PIXMAN_FORMAT(1,PIXMAN_TYPE_GRAY,0,0,0,0), + +/* YUV formats */ + PIXMAN_yuy2 = PIXMAN_FORMAT(16,PIXMAN_TYPE_YUY2,0,0,0,0), + PIXMAN_yv12 = PIXMAN_FORMAT(12,PIXMAN_TYPE_YV12,0,0,0,0) +} pixman_format_code_t; + +/* Querying supported format values. */ +pixman_bool_t pixman_format_supported_destination (pixman_format_code_t format); +pixman_bool_t pixman_format_supported_source (pixman_format_code_t format); + +/* Constructors */ +pixman_image_t *pixman_image_create_solid_fill (pixman_color_t *color); +pixman_image_t *pixman_image_create_linear_gradient (pixman_point_fixed_t *p1, + pixman_point_fixed_t *p2, + const pixman_gradient_stop_t *stops, + int n_stops); +pixman_image_t *pixman_image_create_radial_gradient (pixman_point_fixed_t *inner, + pixman_point_fixed_t *outer, + pixman_fixed_t inner_radius, + pixman_fixed_t outer_radius, + const pixman_gradient_stop_t *stops, + int n_stops); +pixman_image_t *pixman_image_create_conical_gradient (pixman_point_fixed_t *center, + pixman_fixed_t angle, + const pixman_gradient_stop_t *stops, + int n_stops); +pixman_image_t *pixman_image_create_bits (pixman_format_code_t format, + int width, + int height, + uint32_t *bits, + int rowstride_bytes); + +/* Destructor */ +pixman_image_t *pixman_image_ref (pixman_image_t *image); +pixman_bool_t pixman_image_unref (pixman_image_t *image); + +void pixman_image_set_destroy_function (pixman_image_t *image, + pixman_image_destroy_func_t function, + void *data); +void * pixman_image_get_destroy_data (pixman_image_t *image); + +/* Set properties */ +pixman_bool_t pixman_image_set_clip_region (pixman_image_t *image, + pixman_region16_t *region); +pixman_bool_t pixman_image_set_clip_region32 (pixman_image_t *image, + pixman_region32_t *region); +void pixman_image_set_has_client_clip (pixman_image_t *image, + pixman_bool_t clien_clip); +pixman_bool_t pixman_image_set_transform (pixman_image_t *image, + const pixman_transform_t *transform); +void pixman_image_set_repeat (pixman_image_t *image, + pixman_repeat_t repeat); +pixman_bool_t pixman_image_set_filter (pixman_image_t *image, + pixman_filter_t filter, + const pixman_fixed_t *filter_params, + int n_filter_params); +void pixman_image_set_source_clipping (pixman_image_t *image, + pixman_bool_t source_clipping); +void pixman_image_set_alpha_map (pixman_image_t *image, + pixman_image_t *alpha_map, + int16_t x, + int16_t y); +void pixman_image_set_component_alpha (pixman_image_t *image, + pixman_bool_t component_alpha); +pixman_bool_t pixman_image_get_component_alpha (pixman_image_t *image); +void pixman_image_set_accessors (pixman_image_t *image, + pixman_read_memory_func_t read_func, + pixman_write_memory_func_t write_func); +void pixman_image_set_indexed (pixman_image_t *image, + const pixman_indexed_t *indexed); +uint32_t *pixman_image_get_data (pixman_image_t *image); +int pixman_image_get_width (pixman_image_t *image); +int pixman_image_get_height (pixman_image_t *image); +int pixman_image_get_stride (pixman_image_t *image); /* in bytes */ +int pixman_image_get_depth (pixman_image_t *image); +pixman_format_code_t pixman_image_get_format (pixman_image_t *image); +pixman_bool_t pixman_image_fill_rectangles (pixman_op_t op, + pixman_image_t *image, + pixman_color_t *color, + int n_rects, + const pixman_rectangle16_t *rects); +pixman_bool_t pixman_image_fill_boxes (pixman_op_t op, + pixman_image_t *dest, + pixman_color_t *color, + int n_boxes, + const pixman_box32_t *boxes); + +/* Composite */ +pixman_bool_t pixman_compute_composite_region (pixman_region16_t *region, + pixman_image_t *src_image, + pixman_image_t *mask_image, + pixman_image_t *dst_image, + int16_t src_x, + int16_t src_y, + int16_t mask_x, + int16_t mask_y, + int16_t dest_x, + int16_t dest_y, + uint16_t width, + uint16_t height); +void pixman_image_composite (pixman_op_t op, + pixman_image_t *src, + pixman_image_t *mask, + pixman_image_t *dest, + int16_t src_x, + int16_t src_y, + int16_t mask_x, + int16_t mask_y, + int16_t dest_x, + int16_t dest_y, + uint16_t width, + uint16_t height); +void pixman_image_composite32 (pixman_op_t op, + pixman_image_t *src, + pixman_image_t *mask, + pixman_image_t *dest, + int32_t src_x, + int32_t src_y, + int32_t mask_x, + int32_t mask_y, + int32_t dest_x, + int32_t dest_y, + int32_t width, + int32_t height); + +/* Executive Summary: This function is a no-op that only exists + * for historical reasons. + * + * There used to be a bug in the X server where it would rely on + * out-of-bounds accesses when it was asked to composite with a + * window as the source. It would create a pixman image pointing + * to some bogus position in memory, but then set a clip region + * to the position where the actual bits were. + * + * Due to a bug in old versions of pixman, where it would not clip + * against the image bounds when a clip region was set, this would + * actually work. So when the pixman bug was fixed, a workaround was + * added to allow certain out-of-bound accesses. This function disabled + * those workarounds. + * + * Since 0.21.2, pixman doesn't do these workarounds anymore, so now this + * function is a no-op. + */ +void pixman_disable_out_of_bounds_workaround (void); + +/* + * Trapezoids + */ +typedef struct pixman_edge pixman_edge_t; +typedef struct pixman_trapezoid pixman_trapezoid_t; +typedef struct pixman_trap pixman_trap_t; +typedef struct pixman_span_fix pixman_span_fix_t; +typedef struct pixman_triangle pixman_triangle_t; + +/* + * An edge structure. This represents a single polygon edge + * and can be quickly stepped across small or large gaps in the + * sample grid + */ +struct pixman_edge +{ + pixman_fixed_t x; + pixman_fixed_t e; + pixman_fixed_t stepx; + pixman_fixed_t signdx; + pixman_fixed_t dy; + pixman_fixed_t dx; + + pixman_fixed_t stepx_small; + pixman_fixed_t stepx_big; + pixman_fixed_t dx_small; + pixman_fixed_t dx_big; +}; + +struct pixman_trapezoid +{ + pixman_fixed_t top, bottom; + pixman_line_fixed_t left, right; +}; + +struct pixman_triangle +{ + pixman_point_fixed_t p1, p2, p3; +}; + +/* whether 't' is a well defined not obviously empty trapezoid */ +#define pixman_trapezoid_valid(t) \ + ((t)->left.p1.y != (t)->left.p2.y && \ + (t)->right.p1.y != (t)->right.p2.y && \ + (int) ((t)->bottom - (t)->top) > 0) + +struct pixman_span_fix +{ + pixman_fixed_t l, r, y; +}; + +struct pixman_trap +{ + pixman_span_fix_t top, bot; +}; + +pixman_fixed_t pixman_sample_ceil_y (pixman_fixed_t y, + int bpp); +pixman_fixed_t pixman_sample_floor_y (pixman_fixed_t y, + int bpp); +void pixman_edge_step (pixman_edge_t *e, + int n); +void pixman_edge_init (pixman_edge_t *e, + int bpp, + pixman_fixed_t y_start, + pixman_fixed_t x_top, + pixman_fixed_t y_top, + pixman_fixed_t x_bot, + pixman_fixed_t y_bot); +void pixman_line_fixed_edge_init (pixman_edge_t *e, + int bpp, + pixman_fixed_t y, + const pixman_line_fixed_t *line, + int x_off, + int y_off); +void pixman_rasterize_edges (pixman_image_t *image, + pixman_edge_t *l, + pixman_edge_t *r, + pixman_fixed_t t, + pixman_fixed_t b); +void pixman_add_traps (pixman_image_t *image, + int16_t x_off, + int16_t y_off, + int ntrap, + pixman_trap_t *traps); +void pixman_add_trapezoids (pixman_image_t *image, + int16_t x_off, + int y_off, + int ntraps, + const pixman_trapezoid_t *traps); +void pixman_rasterize_trapezoid (pixman_image_t *image, + const pixman_trapezoid_t *trap, + int x_off, + int y_off); +void pixman_composite_trapezoids (pixman_op_t op, + pixman_image_t * src, + pixman_image_t * dst, + pixman_format_code_t mask_format, + int x_src, + int y_src, + int x_dst, + int y_dst, + int n_traps, + const pixman_trapezoid_t * traps); +void pixman_composite_triangles (pixman_op_t op, + pixman_image_t * src, + pixman_image_t * dst, + pixman_format_code_t mask_format, + int x_src, + int y_src, + int x_dst, + int y_dst, + int n_tris, + const pixman_triangle_t * tris); +void pixman_add_triangles (pixman_image_t *image, + int32_t x_off, + int32_t y_off, + int n_tris, + const pixman_triangle_t *tris); + +PIXMAN_END_DECLS + +#endif /* PIXMAN_H__ */ diff --git a/pixman/test/blitters-test.c b/pixman/test/blitters-test.c index 5a867f23a..3ecfb0994 100644 --- a/pixman/test/blitters-test.c +++ b/pixman/test/blitters-test.c @@ -1,417 +1,422 @@ -/* - * Test program, which stresses the use of different color formats and - * compositing operations. - * - * Script 'fuzzer-find-diff.pl' can be used to narrow down the problem in - * the case of test failure. - */ -#include -#include -#include -#include -#include "utils.h" - -static pixman_indexed_t rgb_palette[9]; -static pixman_indexed_t y_palette[9]; - -/* Create random image for testing purposes */ -static pixman_image_t * -create_random_image (pixman_format_code_t *allowed_formats, - int max_width, - int max_height, - int max_extra_stride, - pixman_format_code_t *used_fmt) -{ - int n = 0, i, width, height, stride; - pixman_format_code_t fmt; - uint32_t *buf; - pixman_image_t *img; - - while (allowed_formats[n] != PIXMAN_null) - n++; - fmt = allowed_formats[lcg_rand_n (n)]; - - width = lcg_rand_n (max_width) + 1; - height = lcg_rand_n (max_height) + 1; - stride = (width * PIXMAN_FORMAT_BPP (fmt) + 7) / 8 + - lcg_rand_n (max_extra_stride + 1); - stride = (stride + 3) & ~3; - - /* do the allocation */ - buf = aligned_malloc (64, stride * height); - - /* initialize image with random data */ - for (i = 0; i < stride * height; i++) - { - /* generation is biased to having more 0 or 255 bytes as - * they are more likely to be special-cased in code - */ - *((uint8_t *)buf + i) = lcg_rand_n (4) ? lcg_rand_n (256) : - (lcg_rand_n (2) ? 0 : 255); - } - - img = pixman_image_create_bits (fmt, width, height, buf, stride); - - if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_COLOR) - { - pixman_image_set_indexed (img, &(rgb_palette[PIXMAN_FORMAT_BPP (fmt)])); - } - else if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_GRAY) - { - pixman_image_set_indexed (img, &(y_palette[PIXMAN_FORMAT_BPP (fmt)])); - } - - image_endian_swap (img); - - if (used_fmt) *used_fmt = fmt; - return img; -} - -/* Free random image, and optionally update crc32 based on its data */ -static uint32_t -free_random_image (uint32_t initcrc, - pixman_image_t *img, - pixman_format_code_t fmt) -{ - uint32_t crc32 = 0; - int stride = pixman_image_get_stride (img); - uint32_t *data = pixman_image_get_data (img); - int height = pixman_image_get_height (img); - - if (fmt != PIXMAN_null) - { - /* mask unused 'x' part */ - if (PIXMAN_FORMAT_BPP (fmt) - PIXMAN_FORMAT_DEPTH (fmt) && - PIXMAN_FORMAT_DEPTH (fmt) != 0) - { - int i; - uint32_t *data = pixman_image_get_data (img); - uint32_t mask = (1 << PIXMAN_FORMAT_DEPTH (fmt)) - 1; - - if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_BGRA) - mask <<= (PIXMAN_FORMAT_BPP (fmt) - PIXMAN_FORMAT_DEPTH (fmt)); - - for (i = 0; i < 32; i++) - mask |= mask << (i * PIXMAN_FORMAT_BPP (fmt)); - - for (i = 0; i < stride * height / 4; i++) - data[i] &= mask; - } - - /* swap endiannes in order to provide identical results on both big - * and litte endian systems - */ - image_endian_swap (img); - crc32 = compute_crc32 (initcrc, data, stride * height); - } - - pixman_image_unref (img); - free (data); - - return crc32; -} - -static pixman_op_t op_list[] = { - PIXMAN_OP_SRC, - PIXMAN_OP_OVER, - PIXMAN_OP_ADD, - PIXMAN_OP_CLEAR, - PIXMAN_OP_SRC, - PIXMAN_OP_DST, - PIXMAN_OP_OVER, - PIXMAN_OP_OVER_REVERSE, - PIXMAN_OP_IN, - PIXMAN_OP_IN_REVERSE, - PIXMAN_OP_OUT, - PIXMAN_OP_OUT_REVERSE, - PIXMAN_OP_ATOP, - PIXMAN_OP_ATOP_REVERSE, - PIXMAN_OP_XOR, - PIXMAN_OP_ADD, - PIXMAN_OP_SATURATE, - PIXMAN_OP_DISJOINT_CLEAR, - PIXMAN_OP_DISJOINT_SRC, - PIXMAN_OP_DISJOINT_DST, - PIXMAN_OP_DISJOINT_OVER, - PIXMAN_OP_DISJOINT_OVER_REVERSE, - PIXMAN_OP_DISJOINT_IN, - PIXMAN_OP_DISJOINT_IN_REVERSE, - PIXMAN_OP_DISJOINT_OUT, - PIXMAN_OP_DISJOINT_OUT_REVERSE, - PIXMAN_OP_DISJOINT_ATOP, - PIXMAN_OP_DISJOINT_ATOP_REVERSE, - PIXMAN_OP_DISJOINT_XOR, - PIXMAN_OP_CONJOINT_CLEAR, - PIXMAN_OP_CONJOINT_SRC, - PIXMAN_OP_CONJOINT_DST, - PIXMAN_OP_CONJOINT_OVER, - PIXMAN_OP_CONJOINT_OVER_REVERSE, - PIXMAN_OP_CONJOINT_IN, - PIXMAN_OP_CONJOINT_IN_REVERSE, - PIXMAN_OP_CONJOINT_OUT, - PIXMAN_OP_CONJOINT_OUT_REVERSE, - PIXMAN_OP_CONJOINT_ATOP, - PIXMAN_OP_CONJOINT_ATOP_REVERSE, - PIXMAN_OP_CONJOINT_XOR, - PIXMAN_OP_MULTIPLY, - PIXMAN_OP_SCREEN, - PIXMAN_OP_OVERLAY, - PIXMAN_OP_DARKEN, - PIXMAN_OP_LIGHTEN, - PIXMAN_OP_COLOR_DODGE, - PIXMAN_OP_COLOR_BURN, - PIXMAN_OP_HARD_LIGHT, - PIXMAN_OP_DIFFERENCE, - PIXMAN_OP_EXCLUSION, -#if 0 /* these use floating point math and are not always bitexact on different platforms */ - PIXMAN_OP_SOFT_LIGHT, - PIXMAN_OP_HSL_HUE, - PIXMAN_OP_HSL_SATURATION, - PIXMAN_OP_HSL_COLOR, - PIXMAN_OP_HSL_LUMINOSITY, -#endif -}; - -static pixman_format_code_t img_fmt_list[] = { - PIXMAN_a8r8g8b8, - PIXMAN_x8r8g8b8, - PIXMAN_r5g6b5, - PIXMAN_r3g3b2, - PIXMAN_a8, - PIXMAN_a8b8g8r8, - PIXMAN_x8b8g8r8, - PIXMAN_b8g8r8a8, - PIXMAN_b8g8r8x8, - PIXMAN_x14r6g6b6, - PIXMAN_r8g8b8, - PIXMAN_b8g8r8, - PIXMAN_r5g6b5, - PIXMAN_b5g6r5, - PIXMAN_x2r10g10b10, - PIXMAN_a2r10g10b10, - PIXMAN_x2b10g10r10, - PIXMAN_a2b10g10r10, - PIXMAN_a1r5g5b5, - PIXMAN_x1r5g5b5, - PIXMAN_a1b5g5r5, - PIXMAN_x1b5g5r5, - PIXMAN_a4r4g4b4, - PIXMAN_x4r4g4b4, - PIXMAN_a4b4g4r4, - PIXMAN_x4b4g4r4, - PIXMAN_a8, - PIXMAN_r3g3b2, - PIXMAN_b2g3r3, - PIXMAN_a2r2g2b2, - PIXMAN_a2b2g2r2, - PIXMAN_c8, - PIXMAN_g8, - PIXMAN_x4c4, - PIXMAN_x4g4, - PIXMAN_c4, - PIXMAN_g4, - PIXMAN_g1, - PIXMAN_x4a4, - PIXMAN_a4, - PIXMAN_r1g2b1, - PIXMAN_b1g2r1, - PIXMAN_a1r1g1b1, - PIXMAN_a1b1g1r1, - PIXMAN_a1, - PIXMAN_null -}; - -static pixman_format_code_t mask_fmt_list[] = { - PIXMAN_a8r8g8b8, - PIXMAN_a8, - PIXMAN_a4, - PIXMAN_a1, - PIXMAN_null -}; - - -/* - * Composite operation with pseudorandom images - */ -uint32_t -test_composite (int testnum, int verbose) -{ - int i; - pixman_image_t *src_img = NULL; - pixman_image_t *dst_img = NULL; - pixman_image_t *mask_img = NULL; - int src_width, src_height; - int dst_width, dst_height; - int src_stride, dst_stride; - int src_x, src_y; - int dst_x, dst_y; - int mask_x, mask_y; - int w, h; - pixman_op_t op; - pixman_format_code_t src_fmt, dst_fmt, mask_fmt; - uint32_t *dstbuf, *srcbuf, *maskbuf; - uint32_t crc32; - int max_width, max_height, max_extra_stride; - FLOAT_REGS_CORRUPTION_DETECTOR_START (); - - max_width = max_height = 24 + testnum / 10000; - max_extra_stride = 4 + testnum / 1000000; - - if (max_width > 256) - max_width = 256; - - if (max_height > 16) - max_height = 16; - - if (max_extra_stride > 8) - max_extra_stride = 8; - - lcg_srand (testnum); - - op = op_list[lcg_rand_n (sizeof (op_list) / sizeof (op_list[0]))]; - - if (lcg_rand_n (8)) - { - /* normal image */ - src_img = create_random_image (img_fmt_list, max_width, max_height, - max_extra_stride, &src_fmt); - } - else - { - /* solid case */ - src_img = create_random_image (img_fmt_list, 1, 1, - max_extra_stride, &src_fmt); - - pixman_image_set_repeat (src_img, PIXMAN_REPEAT_NORMAL); - } - - dst_img = create_random_image (img_fmt_list, max_width, max_height, - max_extra_stride, &dst_fmt); - - src_width = pixman_image_get_width (src_img); - src_height = pixman_image_get_height (src_img); - src_stride = pixman_image_get_stride (src_img); - - dst_width = pixman_image_get_width (dst_img); - dst_height = pixman_image_get_height (dst_img); - dst_stride = pixman_image_get_stride (dst_img); - - dstbuf = pixman_image_get_data (dst_img); - srcbuf = pixman_image_get_data (src_img); - - src_x = lcg_rand_n (src_width); - src_y = lcg_rand_n (src_height); - dst_x = lcg_rand_n (dst_width); - dst_y = lcg_rand_n (dst_height); - - mask_img = NULL; - mask_fmt = PIXMAN_null; - mask_x = 0; - mask_y = 0; - maskbuf = NULL; - - if ((src_fmt == PIXMAN_x8r8g8b8 || src_fmt == PIXMAN_x8b8g8r8) && - (lcg_rand_n (4) == 0)) - { - /* PIXBUF */ - mask_fmt = lcg_rand_n (2) ? PIXMAN_a8r8g8b8 : PIXMAN_a8b8g8r8; - mask_img = pixman_image_create_bits (mask_fmt, - src_width, - src_height, - srcbuf, - src_stride); - mask_x = src_x; - mask_y = src_y; - maskbuf = srcbuf; - } - else if (lcg_rand_n (2)) - { - if (lcg_rand_n (2)) - { - mask_img = create_random_image (mask_fmt_list, max_width, max_height, - max_extra_stride, &mask_fmt); - } - else - { - /* solid case */ - mask_img = create_random_image (mask_fmt_list, 1, 1, - max_extra_stride, &mask_fmt); - pixman_image_set_repeat (mask_img, PIXMAN_REPEAT_NORMAL); - } - - if (lcg_rand_n (2)) - pixman_image_set_component_alpha (mask_img, 1); - - mask_x = lcg_rand_n (pixman_image_get_width (mask_img)); - mask_y = lcg_rand_n (pixman_image_get_height (mask_img)); - } - - - w = lcg_rand_n (dst_width - dst_x + 1); - h = lcg_rand_n (dst_height - dst_y + 1); - - if (verbose) - { - printf ("op=%d, src_fmt=%08X, dst_fmt=%08X, mask_fmt=%08X\n", - op, src_fmt, dst_fmt, mask_fmt); - printf ("src_width=%d, src_height=%d, dst_width=%d, dst_height=%d\n", - src_width, src_height, dst_width, dst_height); - printf ("src_x=%d, src_y=%d, dst_x=%d, dst_y=%d\n", - src_x, src_y, dst_x, dst_y); - printf ("src_stride=%d, dst_stride=%d\n", - src_stride, dst_stride); - printf ("w=%d, h=%d\n", w, h); - } - - pixman_image_composite (op, src_img, mask_img, dst_img, - src_x, src_y, mask_x, mask_y, dst_x, dst_y, w, h); - - if (verbose) - { - int j; - - printf ("---\n"); - for (i = 0; i < dst_height; i++) - { - for (j = 0; j < dst_stride; j++) - { - if (j == (dst_width * PIXMAN_FORMAT_BPP (dst_fmt) + 7) / 8) - printf ("| "); - - printf ("%02X ", *((uint8_t *)dstbuf + i * dst_stride + j)); - } - printf ("\n"); - } - printf ("---\n"); - } - - free_random_image (0, src_img, PIXMAN_null); - crc32 = free_random_image (0, dst_img, dst_fmt); - - if (mask_img) - { - if (srcbuf == maskbuf) - pixman_image_unref(mask_img); - else - free_random_image (0, mask_img, PIXMAN_null); - } - - FLOAT_REGS_CORRUPTION_DETECTOR_FINISH (); - return crc32; -} - -int -main (int argc, const char *argv[]) -{ - int i; - - for (i = 1; i <= 8; i++) - { - initialize_palette (&(rgb_palette[i]), i, TRUE); - initialize_palette (&(y_palette[i]), i, FALSE); - } - - return fuzzer_test_main("blitters", 2000000, - 0x1DB8BDF8, - test_composite, argc, argv); -} +/* + * Test program, which stresses the use of different color formats and + * compositing operations. + * + * Script 'fuzzer-find-diff.pl' can be used to narrow down the problem in + * the case of test failure. + */ +#include +#include +#include +#include +#include "utils.h" + +static pixman_indexed_t rgb_palette[9]; +static pixman_indexed_t y_palette[9]; + +/* Create random image for testing purposes */ +static pixman_image_t * +create_random_image (pixman_format_code_t *allowed_formats, + int max_width, + int max_height, + int max_extra_stride, + pixman_format_code_t *used_fmt) +{ + int n = 0, i, width, height, stride; + pixman_format_code_t fmt; + uint32_t *buf; + pixman_image_t *img; + + while (allowed_formats[n] != PIXMAN_null) + n++; + fmt = allowed_formats[lcg_rand_n (n)]; + + width = lcg_rand_n (max_width) + 1; + height = lcg_rand_n (max_height) + 1; + stride = (width * PIXMAN_FORMAT_BPP (fmt) + 7) / 8 + + lcg_rand_n (max_extra_stride + 1); + stride = (stride + 3) & ~3; + + /* do the allocation */ + buf = aligned_malloc (64, stride * height); + + /* initialize image with random data */ + for (i = 0; i < stride * height; i++) + { + /* generation is biased to having more 0 or 255 bytes as + * they are more likely to be special-cased in code + */ + *((uint8_t *)buf + i) = lcg_rand_n (4) ? lcg_rand_n (256) : + (lcg_rand_n (2) ? 0 : 255); + } + + img = pixman_image_create_bits (fmt, width, height, buf, stride); + + if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_COLOR) + { + pixman_image_set_indexed (img, &(rgb_palette[PIXMAN_FORMAT_BPP (fmt)])); + } + else if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_GRAY) + { + pixman_image_set_indexed (img, &(y_palette[PIXMAN_FORMAT_BPP (fmt)])); + } + + image_endian_swap (img); + + if (used_fmt) *used_fmt = fmt; + return img; +} + +/* Free random image, and optionally update crc32 based on its data */ +static uint32_t +free_random_image (uint32_t initcrc, + pixman_image_t *img, + pixman_format_code_t fmt) +{ + uint32_t crc32 = 0; + int stride = pixman_image_get_stride (img); + uint32_t *data = pixman_image_get_data (img); + int height = pixman_image_get_height (img); + + if (fmt != PIXMAN_null) + { + /* mask unused 'x' part */ + if (PIXMAN_FORMAT_BPP (fmt) - PIXMAN_FORMAT_DEPTH (fmt) && + PIXMAN_FORMAT_DEPTH (fmt) != 0) + { + int i; + uint32_t *data = pixman_image_get_data (img); + uint32_t mask = (1 << PIXMAN_FORMAT_DEPTH (fmt)) - 1; + + if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_BGRA || + PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_RGBA) + { + mask <<= (PIXMAN_FORMAT_BPP (fmt) - PIXMAN_FORMAT_DEPTH (fmt)); + } + + for (i = 0; i < 32; i++) + mask |= mask << (i * PIXMAN_FORMAT_BPP (fmt)); + + for (i = 0; i < stride * height / 4; i++) + data[i] &= mask; + } + + /* swap endiannes in order to provide identical results on both big + * and litte endian systems + */ + image_endian_swap (img); + crc32 = compute_crc32 (initcrc, data, stride * height); + } + + pixman_image_unref (img); + free (data); + + return crc32; +} + +static pixman_op_t op_list[] = { + PIXMAN_OP_SRC, + PIXMAN_OP_OVER, + PIXMAN_OP_ADD, + PIXMAN_OP_CLEAR, + PIXMAN_OP_SRC, + PIXMAN_OP_DST, + PIXMAN_OP_OVER, + PIXMAN_OP_OVER_REVERSE, + PIXMAN_OP_IN, + PIXMAN_OP_IN_REVERSE, + PIXMAN_OP_OUT, + PIXMAN_OP_OUT_REVERSE, + PIXMAN_OP_ATOP, + PIXMAN_OP_ATOP_REVERSE, + PIXMAN_OP_XOR, + PIXMAN_OP_ADD, + PIXMAN_OP_SATURATE, + PIXMAN_OP_DISJOINT_CLEAR, + PIXMAN_OP_DISJOINT_SRC, + PIXMAN_OP_DISJOINT_DST, + PIXMAN_OP_DISJOINT_OVER, + PIXMAN_OP_DISJOINT_OVER_REVERSE, + PIXMAN_OP_DISJOINT_IN, + PIXMAN_OP_DISJOINT_IN_REVERSE, + PIXMAN_OP_DISJOINT_OUT, + PIXMAN_OP_DISJOINT_OUT_REVERSE, + PIXMAN_OP_DISJOINT_ATOP, + PIXMAN_OP_DISJOINT_ATOP_REVERSE, + PIXMAN_OP_DISJOINT_XOR, + PIXMAN_OP_CONJOINT_CLEAR, + PIXMAN_OP_CONJOINT_SRC, + PIXMAN_OP_CONJOINT_DST, + PIXMAN_OP_CONJOINT_OVER, + PIXMAN_OP_CONJOINT_OVER_REVERSE, + PIXMAN_OP_CONJOINT_IN, + PIXMAN_OP_CONJOINT_IN_REVERSE, + PIXMAN_OP_CONJOINT_OUT, + PIXMAN_OP_CONJOINT_OUT_REVERSE, + PIXMAN_OP_CONJOINT_ATOP, + PIXMAN_OP_CONJOINT_ATOP_REVERSE, + PIXMAN_OP_CONJOINT_XOR, + PIXMAN_OP_MULTIPLY, + PIXMAN_OP_SCREEN, + PIXMAN_OP_OVERLAY, + PIXMAN_OP_DARKEN, + PIXMAN_OP_LIGHTEN, + PIXMAN_OP_COLOR_DODGE, + PIXMAN_OP_COLOR_BURN, + PIXMAN_OP_HARD_LIGHT, + PIXMAN_OP_DIFFERENCE, + PIXMAN_OP_EXCLUSION, +#if 0 /* these use floating point math and are not always bitexact on different platforms */ + PIXMAN_OP_SOFT_LIGHT, + PIXMAN_OP_HSL_HUE, + PIXMAN_OP_HSL_SATURATION, + PIXMAN_OP_HSL_COLOR, + PIXMAN_OP_HSL_LUMINOSITY, +#endif +}; + +static pixman_format_code_t img_fmt_list[] = { + PIXMAN_a8r8g8b8, + PIXMAN_x8r8g8b8, + PIXMAN_r5g6b5, + PIXMAN_r3g3b2, + PIXMAN_a8, + PIXMAN_a8b8g8r8, + PIXMAN_x8b8g8r8, + PIXMAN_b8g8r8a8, + PIXMAN_b8g8r8x8, + PIXMAN_r8g8b8a8, + PIXMAN_r8g8b8x8, + PIXMAN_x14r6g6b6, + PIXMAN_r8g8b8, + PIXMAN_b8g8r8, + PIXMAN_r5g6b5, + PIXMAN_b5g6r5, + PIXMAN_x2r10g10b10, + PIXMAN_a2r10g10b10, + PIXMAN_x2b10g10r10, + PIXMAN_a2b10g10r10, + PIXMAN_a1r5g5b5, + PIXMAN_x1r5g5b5, + PIXMAN_a1b5g5r5, + PIXMAN_x1b5g5r5, + PIXMAN_a4r4g4b4, + PIXMAN_x4r4g4b4, + PIXMAN_a4b4g4r4, + PIXMAN_x4b4g4r4, + PIXMAN_a8, + PIXMAN_r3g3b2, + PIXMAN_b2g3r3, + PIXMAN_a2r2g2b2, + PIXMAN_a2b2g2r2, + PIXMAN_c8, + PIXMAN_g8, + PIXMAN_x4c4, + PIXMAN_x4g4, + PIXMAN_c4, + PIXMAN_g4, + PIXMAN_g1, + PIXMAN_x4a4, + PIXMAN_a4, + PIXMAN_r1g2b1, + PIXMAN_b1g2r1, + PIXMAN_a1r1g1b1, + PIXMAN_a1b1g1r1, + PIXMAN_a1, + PIXMAN_null +}; + +static pixman_format_code_t mask_fmt_list[] = { + PIXMAN_a8r8g8b8, + PIXMAN_a8, + PIXMAN_a4, + PIXMAN_a1, + PIXMAN_null +}; + + +/* + * Composite operation with pseudorandom images + */ +uint32_t +test_composite (int testnum, int verbose) +{ + int i; + pixman_image_t *src_img = NULL; + pixman_image_t *dst_img = NULL; + pixman_image_t *mask_img = NULL; + int src_width, src_height; + int dst_width, dst_height; + int src_stride, dst_stride; + int src_x, src_y; + int dst_x, dst_y; + int mask_x, mask_y; + int w, h; + pixman_op_t op; + pixman_format_code_t src_fmt, dst_fmt, mask_fmt; + uint32_t *dstbuf, *srcbuf, *maskbuf; + uint32_t crc32; + int max_width, max_height, max_extra_stride; + FLOAT_REGS_CORRUPTION_DETECTOR_START (); + + max_width = max_height = 24 + testnum / 10000; + max_extra_stride = 4 + testnum / 1000000; + + if (max_width > 256) + max_width = 256; + + if (max_height > 16) + max_height = 16; + + if (max_extra_stride > 8) + max_extra_stride = 8; + + lcg_srand (testnum); + + op = op_list[lcg_rand_n (sizeof (op_list) / sizeof (op_list[0]))]; + + if (lcg_rand_n (8)) + { + /* normal image */ + src_img = create_random_image (img_fmt_list, max_width, max_height, + max_extra_stride, &src_fmt); + } + else + { + /* solid case */ + src_img = create_random_image (img_fmt_list, 1, 1, + max_extra_stride, &src_fmt); + + pixman_image_set_repeat (src_img, PIXMAN_REPEAT_NORMAL); + } + + dst_img = create_random_image (img_fmt_list, max_width, max_height, + max_extra_stride, &dst_fmt); + + src_width = pixman_image_get_width (src_img); + src_height = pixman_image_get_height (src_img); + src_stride = pixman_image_get_stride (src_img); + + dst_width = pixman_image_get_width (dst_img); + dst_height = pixman_image_get_height (dst_img); + dst_stride = pixman_image_get_stride (dst_img); + + dstbuf = pixman_image_get_data (dst_img); + srcbuf = pixman_image_get_data (src_img); + + src_x = lcg_rand_n (src_width); + src_y = lcg_rand_n (src_height); + dst_x = lcg_rand_n (dst_width); + dst_y = lcg_rand_n (dst_height); + + mask_img = NULL; + mask_fmt = PIXMAN_null; + mask_x = 0; + mask_y = 0; + maskbuf = NULL; + + if ((src_fmt == PIXMAN_x8r8g8b8 || src_fmt == PIXMAN_x8b8g8r8) && + (lcg_rand_n (4) == 0)) + { + /* PIXBUF */ + mask_fmt = lcg_rand_n (2) ? PIXMAN_a8r8g8b8 : PIXMAN_a8b8g8r8; + mask_img = pixman_image_create_bits (mask_fmt, + src_width, + src_height, + srcbuf, + src_stride); + mask_x = src_x; + mask_y = src_y; + maskbuf = srcbuf; + } + else if (lcg_rand_n (2)) + { + if (lcg_rand_n (2)) + { + mask_img = create_random_image (mask_fmt_list, max_width, max_height, + max_extra_stride, &mask_fmt); + } + else + { + /* solid case */ + mask_img = create_random_image (mask_fmt_list, 1, 1, + max_extra_stride, &mask_fmt); + pixman_image_set_repeat (mask_img, PIXMAN_REPEAT_NORMAL); + } + + if (lcg_rand_n (2)) + pixman_image_set_component_alpha (mask_img, 1); + + mask_x = lcg_rand_n (pixman_image_get_width (mask_img)); + mask_y = lcg_rand_n (pixman_image_get_height (mask_img)); + } + + + w = lcg_rand_n (dst_width - dst_x + 1); + h = lcg_rand_n (dst_height - dst_y + 1); + + if (verbose) + { + printf ("op=%d, src_fmt=%08X, dst_fmt=%08X, mask_fmt=%08X\n", + op, src_fmt, dst_fmt, mask_fmt); + printf ("src_width=%d, src_height=%d, dst_width=%d, dst_height=%d\n", + src_width, src_height, dst_width, dst_height); + printf ("src_x=%d, src_y=%d, dst_x=%d, dst_y=%d\n", + src_x, src_y, dst_x, dst_y); + printf ("src_stride=%d, dst_stride=%d\n", + src_stride, dst_stride); + printf ("w=%d, h=%d\n", w, h); + } + + pixman_image_composite (op, src_img, mask_img, dst_img, + src_x, src_y, mask_x, mask_y, dst_x, dst_y, w, h); + + if (verbose) + { + int j; + + printf ("---\n"); + for (i = 0; i < dst_height; i++) + { + for (j = 0; j < dst_stride; j++) + { + if (j == (dst_width * PIXMAN_FORMAT_BPP (dst_fmt) + 7) / 8) + printf ("| "); + + printf ("%02X ", *((uint8_t *)dstbuf + i * dst_stride + j)); + } + printf ("\n"); + } + printf ("---\n"); + } + + free_random_image (0, src_img, PIXMAN_null); + crc32 = free_random_image (0, dst_img, dst_fmt); + + if (mask_img) + { + if (srcbuf == maskbuf) + pixman_image_unref(mask_img); + else + free_random_image (0, mask_img, PIXMAN_null); + } + + FLOAT_REGS_CORRUPTION_DETECTOR_FINISH (); + return crc32; +} + +int +main (int argc, const char *argv[]) +{ + int i; + + for (i = 1; i <= 8; i++) + { + initialize_palette (&(rgb_palette[i]), i, TRUE); + initialize_palette (&(y_palette[i]), i, FALSE); + } + + return fuzzer_test_main("blitters", 2000000, + 0x265CDFEB, + test_composite, argc, argv); +} diff --git a/pixman/test/composite.c b/pixman/test/composite.c index e6d52b990..9a001e519 100644 --- a/pixman/test/composite.c +++ b/pixman/test/composite.c @@ -102,6 +102,8 @@ static const format_t formats[] = P(x8b8g8r8), P(b8g8r8a8), P(b8g8r8x8), + P(r8g8b8a8), + P(r8g8b8x8), P(x2r10g10b10), P(x2b10g10r10), P(a2r10g10b10), @@ -556,6 +558,13 @@ get_pixel (pixman_image_t *image, bs = g + gs; break; + case PIXMAN_TYPE_RGBA: + as = 0; + bs = PIXMAN_FORMAT_BPP (format) - (b + g + r); + gs = b + bs; + rs = g + gs; + break; + case PIXMAN_TYPE_A: as = 0; rs = 0; @@ -900,13 +909,13 @@ main (int argc, char **argv) #ifdef USE_OPENMP # pragma omp parallel for default(none) shared(result, argv, seed) #endif - for (i = seed; i <= N_TESTS; ++i) + for (i = 0; i <= N_TESTS; ++i) { - if (!result && !run_test (i)) + if (!result && !run_test (i + seed)) { - printf ("Test 0x%08X failed.\n", i); + printf ("Test 0x%08X failed.\n", seed + i); - result = i; + result = seed + i; } } diff --git a/pixman/test/fetch-test.c b/pixman/test/fetch-test.c index 60bc765f6..feb98d9b7 100644 --- a/pixman/test/fetch-test.c +++ b/pixman/test/fetch-test.c @@ -33,6 +33,16 @@ static testcase_t testcases[] = 0x8899aabb, 0xccddeeff }, NULL, }, + { + PIXMAN_r8g8b8a8, + 2, 2, + 8, + { 0x11223300, 0x55667744, + 0x99aabb88, 0xddeeffcc }, + { 0x00112233, 0x44556677, + 0x8899aabb, 0xccddeeff }, + NULL, + }, { PIXMAN_g1, 8, 2, diff --git a/pixman/test/stress-test.c b/pixman/test/stress-test.c index d496f93e2..571420ab0 100644 --- a/pixman/test/stress-test.c +++ b/pixman/test/stress-test.c @@ -19,6 +19,8 @@ static const pixman_format_code_t image_formats[] = PIXMAN_x8b8g8r8, PIXMAN_b8g8r8a8, PIXMAN_b8g8r8x8, + PIXMAN_r8g8b8a8, + PIXMAN_r8g8b8x8, PIXMAN_x14r6g6b6, PIXMAN_r8g8b8, PIXMAN_b8g8r8, -- cgit v1.2.3