diff options
Diffstat (limited to 'pixman')
-rw-r--r-- | pixman/pixman/pixman-access.c | 6075 | ||||
-rw-r--r-- | pixman/pixman/pixman.c | 2428 | ||||
-rw-r--r-- | pixman/pixman/pixman.h | 1976 | ||||
-rw-r--r-- | pixman/test/blitters-test.c | 839 | ||||
-rw-r--r-- | pixman/test/composite.c | 17 | ||||
-rw-r--r-- | pixman/test/fetch-test.c | 10 | ||||
-rw-r--r-- | pixman/test/stress-test.c | 2 |
7 files changed, 5740 insertions, 5607 deletions
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 <config.h>
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-#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 <config.h> +#endif + +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#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 <config.h>
-#endif
-#include "pixman-private.h"
-
-#include <stdlib.h>
-
-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:
- *
- * <informalexample><programlisting>
- * if (pixman_version() >= PIXMAN_VERSION_ENCODE(X,Y,Z)) {...}
- * </programlisting></informalexample>
- *
- * 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 <config.h> +#endif +#include "pixman-private.h" + +#include <stdlib.h> + +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: + * + * <informalexample><programlisting> + * if (pixman_version() >= PIXMAN_VERSION_ENCODE(X,Y,Z)) {...} + * </programlisting></informalexample> + * + * 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 <pixman-version.h>
-
-#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 <inttypes.h>
-/* 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 <sys/inttypes.h>
-#else
-# include <stdint.h>
-#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 <pixman-version.h> + +#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 <inttypes.h> +/* 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 <sys/inttypes.h> +#else +# include <stdint.h> +#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 <assert.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <config.h>
-#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 <assert.h> +#include <stdlib.h> +#include <stdio.h> +#include <config.h> +#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 @@ -34,6 +34,16 @@ static testcase_t testcases[] = NULL, }, { + PIXMAN_r8g8b8a8, + 2, 2, + 8, + { 0x11223300, 0x55667744, + 0x99aabb88, 0xddeeffcc }, + { 0x00112233, 0x44556677, + 0x8899aabb, 0xccddeeff }, + NULL, + }, + { PIXMAN_g1, 8, 2, 4, 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, |