pixman/test/alphamap.c
Søren Sandmann Pedersen ab584ab500 test/alphamap.c: Make dst and orig_dst more independent of each other
When making the copy of the destination, do so separately for the
image and the alpha map. This ensures that the alpha channel of the
alpha map will be different from the alpha channel of the actual
image.

Previously, orig_dst would be copied onto dst along with its alpha
map, which mean that the alpha map of orig_dst would become the new
alpha channel of *both* dst and dst's alpha map. This meant that test
didn't actually test that the alpha maps alpha channel was actually
fetched.
2012-01-10 09:04:36 -05:00

333 lines
7.6 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include "utils.h"
#define WIDTH 48
#define HEIGHT 48
static const pixman_format_code_t formats[] =
{
PIXMAN_a8r8g8b8,
PIXMAN_a2r10g10b10,
PIXMAN_a4r4g4b4,
PIXMAN_a8
};
static const pixman_format_code_t alpha_formats[] =
{
PIXMAN_null,
PIXMAN_a8,
PIXMAN_a2r10g10b10,
PIXMAN_a4r4g4b4
};
static const int origins[] =
{
0, 10, -100
};
static const char *
format_name (pixman_format_code_t format)
{
if (format == PIXMAN_a8)
return "a8";
else if (format == PIXMAN_a2r10g10b10)
return "a2r10g10b10";
else if (format == PIXMAN_a8r8g8b8)
return "a8r8g8b8";
else if (format == PIXMAN_a4r4g4b4)
return "a4r4g4b4";
else if (format == PIXMAN_null)
return "none";
else
assert (0);
return "<unknown - bug in alphamap.c>";
}
static void
on_destroy (pixman_image_t *image, void *data)
{
uint32_t *bits = pixman_image_get_data (image);
fence_free (bits);
}
static pixman_image_t *
make_image (pixman_format_code_t format)
{
uint32_t *bits;
uint8_t bpp = PIXMAN_FORMAT_BPP (format) / 8;
pixman_image_t *image;
bits = (uint32_t *)make_random_bytes (WIDTH * HEIGHT * bpp);
image = pixman_image_create_bits (format, WIDTH, HEIGHT, bits, WIDTH * bpp);
if (image && bits)
pixman_image_set_destroy_function (image, on_destroy, NULL);
return image;
}
static uint8_t
get_alpha (pixman_image_t *image, int x, int y, int orig_x, int orig_y)
{
uint8_t *bits;
uint8_t r;
if (image->common.alpha_map)
{
if (x - orig_x >= 0 && x - orig_x < WIDTH &&
y - orig_y >= 0 && y - orig_y < HEIGHT)
{
image = (pixman_image_t *)image->common.alpha_map;
x -= orig_x;
y -= orig_y;
}
else
{
return 0;
}
}
bits = (uint8_t *)image->bits.bits;
if (image->bits.format == PIXMAN_a8)
{
r = bits[y * WIDTH + x];
}
else if (image->bits.format == PIXMAN_a2r10g10b10)
{
r = ((uint32_t *)bits)[y * WIDTH + x] >> 30;
r |= r << 2;
r |= r << 4;
}
else if (image->bits.format == PIXMAN_a8r8g8b8)
{
r = ((uint32_t *)bits)[y * WIDTH + x] >> 24;
}
else if (image->bits.format == PIXMAN_a4r4g4b4)
{
r = ((uint16_t *)bits)[y * WIDTH + x] >> 12;
r |= r << 4;
}
else
{
assert (0);
}
return r;
}
static uint16_t
get_red (pixman_image_t *image, int x, int y, int orig_x, int orig_y)
{
uint8_t *bits;
uint16_t r;
bits = (uint8_t *)image->bits.bits;
if (image->bits.format == PIXMAN_a8)
{
r = 0x00;
}
else if (image->bits.format == PIXMAN_a2r10g10b10)
{
r = ((uint32_t *)bits)[y * WIDTH + x] >> 14;
r &= 0xffc0;
r |= (r >> 10);
}
else if (image->bits.format == PIXMAN_a8r8g8b8)
{
r = ((uint32_t *)bits)[y * WIDTH + x] >> 16;
r &= 0xff;
r |= r << 8;
}
else if (image->bits.format == PIXMAN_a4r4g4b4)
{
r = ((uint16_t *)bits)[y * WIDTH + x] >> 8;
r &= 0xf;
r |= r << 4;
r |= r << 8;
}
else
{
assert (0);
}
return r;
}
static int
run_test (int s, int d, int sa, int da, int soff, int doff)
{
pixman_format_code_t sf = formats[s];
pixman_format_code_t df = formats[d];
pixman_format_code_t saf = alpha_formats[sa];
pixman_format_code_t daf = alpha_formats[da];
pixman_image_t *src, *dst, *orig_dst, *alpha, *orig_alpha;
pixman_transform_t t1;
int j, k;
int n_alpha_bits, n_red_bits;
soff = origins[soff];
doff = origins[doff];
n_alpha_bits = PIXMAN_FORMAT_A (df);
if (daf != PIXMAN_null)
n_alpha_bits = PIXMAN_FORMAT_A (daf);
n_red_bits = PIXMAN_FORMAT_R (df);
/* Source */
src = make_image (sf);
if (saf != PIXMAN_null)
{
alpha = make_image (saf);
pixman_image_set_alpha_map (src, alpha, soff, soff);
pixman_image_unref (alpha);
}
/* Destination */
orig_dst = make_image (df);
dst = make_image (df);
pixman_image_composite (PIXMAN_OP_SRC, orig_dst, NULL, dst,
0, 0, 0, 0, 0, 0, WIDTH, HEIGHT);
if (daf != PIXMAN_null)
{
orig_alpha = make_image (daf);
alpha = make_image (daf);
pixman_image_composite (PIXMAN_OP_SRC, orig_alpha, NULL, alpha,
0, 0, 0, 0, 0, 0, WIDTH, HEIGHT);
pixman_image_set_alpha_map (orig_dst, orig_alpha, doff, doff);
pixman_image_set_alpha_map (dst, alpha, doff, doff);
pixman_image_unref (orig_alpha);
pixman_image_unref (alpha);
}
/* Transformations, repeats and filters on destinations should be ignored,
* so just set some random ones.
*/
pixman_transform_init_identity (&t1);
pixman_transform_scale (&t1, NULL, pixman_int_to_fixed (100), pixman_int_to_fixed (11));
pixman_transform_rotate (&t1, NULL, pixman_double_to_fixed (0.5), pixman_double_to_fixed (0.11));
pixman_transform_translate (&t1, NULL, pixman_int_to_fixed (11), pixman_int_to_fixed (17));
pixman_image_set_transform (dst, &t1);
pixman_image_set_filter (dst, PIXMAN_FILTER_BILINEAR, NULL, 0);
pixman_image_set_repeat (dst, PIXMAN_REPEAT_REFLECT);
pixman_image_composite (PIXMAN_OP_ADD, src, NULL, dst,
0, 0, 0, 0, 0, 0, WIDTH, HEIGHT);
for (j = MAX (doff, 0); j < MIN (HEIGHT, HEIGHT + doff); ++j)
{
for (k = MAX (doff, 0); k < MIN (WIDTH, WIDTH + doff); ++k)
{
uint8_t sa, da, oda, refa;
uint16_t sr, dr, odr, refr;
sa = get_alpha (src, k, j, soff, soff);
da = get_alpha (dst, k, j, doff, doff);
oda = get_alpha (orig_dst, k, j, doff, doff);
if (sa + oda > 255)
refa = 255;
else
refa = sa + oda;
if (da >> (8 - n_alpha_bits) != refa >> (8 - n_alpha_bits))
{
printf ("\nWrong alpha value at (%d, %d). Should be 0x%x; got 0x%x. Source was 0x%x, original dest was 0x%x\n",
k, j, refa, da, sa, oda);
printf ("src: %s, alpha: %s, origin %d %d\ndst: %s, alpha: %s, origin: %d %d\n\n",
format_name (sf),
format_name (saf),
soff, soff,
format_name (df),
format_name (daf),
doff, doff);
return 1;
}
/* There are cases where we go through the 8 bit compositing
* path even with 10bpc formats. This results in incorrect
* results here, so only do the red check for narrow formats
*/
if (n_red_bits <= 8)
{
sr = get_red (src, k, j, soff, soff);
dr = get_red (dst, k, j, doff, doff);
odr = get_red (orig_dst, k, j, doff, doff);
if (sr + odr > 0xffff)
refr = 0xffff;
else
refr = sr + odr;
if (abs ((dr >> (16 - n_red_bits)) - (refr >> (16 - n_red_bits))) > 1)
{
printf ("%d red bits\n", n_red_bits);
printf ("\nWrong red value at (%d, %d). Should be 0x%x; got 0x%x. Source was 0x%x, original dest was 0x%x\n",
k, j, refr, dr, sr, odr);
printf ("src: %s, alpha: %s, origin %d %d\ndst: %s, alpha: %s, origin: %d %d\n\n",
format_name (sf),
format_name (saf),
soff, soff,
format_name (df),
format_name (daf),
doff, doff);
return 1;
}
}
}
}
pixman_image_set_alpha_map (src, NULL, 0, 0);
pixman_image_set_alpha_map (dst, NULL, 0, 0);
pixman_image_set_alpha_map (orig_dst, NULL, 0, 0);
pixman_image_unref (src);
pixman_image_unref (dst);
pixman_image_unref (orig_dst);
return 0;
}
int
main (int argc, char **argv)
{
int i, j, a, b, x, y;
for (i = 0; i < ARRAY_LENGTH (formats); ++i)
{
for (j = 0; j < ARRAY_LENGTH (formats); ++j)
{
for (a = 0; a < ARRAY_LENGTH (alpha_formats); ++a)
{
for (b = 0; b < ARRAY_LENGTH (alpha_formats); ++b)
{
for (x = 0; x < ARRAY_LENGTH (origins); ++x)
{
for (y = 0; y < ARRAY_LENGTH (origins); ++y)
{
if (run_test (i, j, a, b, x, y) != 0)
return 1;
}
}
}
}
}
}
return 0;
}