#include #include #include "utils.h" #define WIDTH 100 #define HEIGHT 100 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 ""; } static pixman_image_t * make_image (pixman_format_code_t format) { uint32_t *bits; uint8_t bpp = PIXMAN_FORMAT_BPP (format) / 8; bits = (uint32_t *)make_random_bytes (WIDTH * HEIGHT * bpp); return pixman_image_create_bits (format, WIDTH, HEIGHT, bits, WIDTH * bpp); } static pixman_image_t * create_image (pixman_format_code_t format, pixman_format_code_t alpha_format, int alpha_origin_x, int alpha_origin_y) { pixman_image_t *image = make_image (format); if (alpha_format != PIXMAN_null) { pixman_image_t *alpha = make_image (alpha_format); pixman_image_set_alpha_map (image, alpha, alpha_origin_x, alpha_origin_y); } 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; } #define ARRAY_LENGTH(A) ((int) (sizeof (A) / sizeof ((A) [0]))) 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; pixman_transform_t t1; int j, k; int n_alpha_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); src = create_image (sf, saf, soff, soff); orig_dst = create_image (df, daf, doff, doff); dst = create_image (df, daf, doff, doff); /* Transformations on destinations should be ignored, so just set some * random one. */ 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)); #if 0 /* Unfortunately, this is actually broken at the moment, so we can't * actually turn it on */ pixman_image_set_transform (dst, &t1); #endif pixman_image_composite (PIXMAN_OP_SRC, orig_dst, NULL, dst, 0, 0, 0, 0, 0, 0, WIDTH, HEIGHT); 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, ref; 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) ref = 255; else ref = sa + oda; if (da >> (8 - n_alpha_bits) != ref >> (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, ref, 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; } } } 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; }