From a13b75f056f9f9efcf6ecb8610b40ddbbb2bbb69 Mon Sep 17 00:00:00 2001 From: marha Date: Wed, 19 Jan 2011 17:29:52 +0000 Subject: xserver pixman mesa git update 19 jan 2011 --- pixman/test/Makefile.am | 4 + pixman/test/alphamap.c | 515 +++++++++++++++++++++++----------------------- pixman/test/radial-test.c | 198 ++++++++++++++++++ 3 files changed, 458 insertions(+), 259 deletions(-) create mode 100644 pixman/test/radial-test.c (limited to 'pixman/test') diff --git a/pixman/test/Makefile.am b/pixman/test/Makefile.am index 71e535374..8d8471d1c 100644 --- a/pixman/test/Makefile.am +++ b/pixman/test/Makefile.am @@ -92,6 +92,7 @@ TESTPROGRAMS_GTK = \ clip-in \ composite-test \ gradient-test \ + radial-test \ alpha-test \ screen-test \ convolution-test \ @@ -102,6 +103,9 @@ INCLUDES += $(GTK_CFLAGS) gradient_test_LDADD = $(GTK_LDADD) gradient_test_SOURCES = gradient-test.c $(GTK_UTILS) +radial_test_LDADD = $(GTK_LDADD) +radial_test_SOURCES = radial-test.c utils.c utils.h $(GTK_UTILS) + alpha_test_LDADD = $(GTK_LDADD) alpha_test_SOURCES = alpha-test.c $(GTK_UTILS) diff --git a/pixman/test/alphamap.c b/pixman/test/alphamap.c index ba3130e5d..554b309fb 100644 --- a/pixman/test/alphamap.c +++ b/pixman/test/alphamap.c @@ -1,259 +1,256 @@ -#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 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 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); - pixman_image_unref (alpha); - } - - 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_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; -} +#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 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 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); + pixman_image_unref (alpha); + } + + 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, 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_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_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; +} diff --git a/pixman/test/radial-test.c b/pixman/test/radial-test.c new file mode 100644 index 000000000..5d716c339 --- /dev/null +++ b/pixman/test/radial-test.c @@ -0,0 +1,198 @@ +#include "utils.h" +#include "gtk-utils.h" + +#define NUM_GRADIENTS 7 +#define NUM_STOPS 3 +#define NUM_REPEAT 4 +#define SIZE 128 +#define WIDTH (SIZE * NUM_GRADIENTS) +#define HEIGHT (SIZE * NUM_REPEAT) + +/* + * We want to test all the possible relative positions of the start + * and end circle: + * + * - The start circle can be smaller/equal/bigger than the end + * circle. A radial gradient can be classified in one of these + * three cases depending on the sign of dr. + * + * - The smaller circle can be completely inside/internally + * tangent/outside (at least in part) of the bigger circle. This + * classification is the same as the one which can be computed by + * examining the sign of a = (dx^2 + dy^2 - dr^2). + * + * - If the two circles have the same size, neither can be inside or + * internally tangent + * + * This test draws radial gradients whose circles always have the same + * centers (0, 0) and (1, 0), but with different radiuses. From left + * to right: + * + * - Small start circle completely inside the end circle + * 0.25 -> 1.75; dr = 1.5 > 0; a = 1 - 1.50^2 < 0 + * + * - Small start circle internally tangent to the end circle + * 0.50 -> 1.50; dr = 1.0 > 0; a = 1 - 1.00^2 = 0 + * + * - Small start circle outside of the end circle + * 0.50 -> 1.00; dr = 0.5 > 0; a = 1 - 0.50^2 > 0 + * + * - Start circle with the same size as the end circle + * 1.00 -> 1.00; dr = 0.0 = 0; a = 1 - 0.00^2 > 0 + * + * - Small end circle outside of the start circle + * 1.00 -> 0.50; dr = -0.5 > 0; a = 1 - 0.50^2 > 0 + * + * - Small end circle internally tangent to the start circle + * 1.50 -> 0.50; dr = -1.0 > 0; a = 1 - 1.00^2 = 0 + * + * - Small end circle completely inside the start circle + * 1.75 -> 0.25; dr = -1.5 > 0; a = 1 - 1.50^2 < 0 + * + */ + +const static double radiuses[NUM_GRADIENTS] = { + 0.25, + 0.50, + 0.50, + 1.00, + 1.00, + 1.50, + 1.75 +}; + +#define double_to_color(x) \ + (((uint32_t) ((x)*65536)) - (((uint32_t) ((x)*65536)) >> 16)) + +#define PIXMAN_STOP(offset,r,g,b,a) \ + { pixman_double_to_fixed (offset), \ + { \ + double_to_color (r), \ + double_to_color (g), \ + double_to_color (b), \ + double_to_color (a) \ + } \ + } + +static const pixman_gradient_stop_t stops[NUM_STOPS] = { + PIXMAN_STOP (0.0, 1, 0, 0, 0.75), + PIXMAN_STOP (0.70710678, 0, 1, 0, 0), + PIXMAN_STOP (1.0, 0, 0, 1, 1) +}; + +static pixman_image_t * +create_radial (int index) +{ + pixman_point_fixed_t p0, p1; + pixman_fixed_t r0, r1; + double x0, x1, radius0, radius1, left, right, center; + + x0 = 0; + x1 = 1; + radius0 = radiuses[index]; + radius1 = radiuses[NUM_GRADIENTS - index - 1]; + + /* center the gradient */ + left = MIN (x0 - radius0, x1 - radius1); + right = MAX (x0 + radius0, x1 + radius1); + center = (left + right) * 0.5; + x0 -= center; + x1 -= center; + + /* scale to make it fit within a 1x1 rect centered in (0,0) */ + x0 *= 0.25; + x1 *= 0.25; + radius0 *= 0.25; + radius1 *= 0.25; + + p0.x = pixman_double_to_fixed (x0); + p0.y = pixman_double_to_fixed (0); + + p1.x = pixman_double_to_fixed (x1); + p1.y = pixman_double_to_fixed (0); + + r0 = pixman_double_to_fixed (radius0); + r1 = pixman_double_to_fixed (radius1); + + return pixman_image_create_radial_gradient (&p0, &p1, + r0, r1, + stops, NUM_STOPS); +} + +static const pixman_repeat_t repeat[NUM_REPEAT] = { + PIXMAN_REPEAT_NONE, + PIXMAN_REPEAT_NORMAL, + PIXMAN_REPEAT_REFLECT, + PIXMAN_REPEAT_PAD +}; + +int +main (int argc, char **argv) +{ + pixman_transform_t transform; + pixman_image_t *src_img, *dest_img; + int i, j; + + enable_fp_exceptions (); + + dest_img = pixman_image_create_bits (PIXMAN_a8r8g8b8, + WIDTH, HEIGHT, + NULL, 0); + + pixman_transform_init_identity (&transform); + + /* + * The create_radial() function returns gradients centered in the + * origin and whose interesting part fits a 1x1 square. We want to + * paint these gradients on a SIZExSIZE square and to make things + * easier we want the origin in the top-left corner of the square + * we want to see. + */ + pixman_transform_translate (NULL, &transform, + pixman_double_to_fixed (0.5), + pixman_double_to_fixed (0.5)); + + pixman_transform_scale (NULL, &transform, + pixman_double_to_fixed (SIZE), + pixman_double_to_fixed (SIZE)); + + /* + * Gradients are evaluated at the center of each pixel, so we need + * to translate by half a pixel to trigger some interesting + * cornercases. In particular, the original implementation of PDF + * radial gradients tried to divide by 0 when using this transform + * on the "tangent circles" cases. + */ + pixman_transform_translate (NULL, &transform, + pixman_double_to_fixed (0.5), + pixman_double_to_fixed (0.5)); + + for (i = 0; i < NUM_GRADIENTS; i++) + { + src_img = create_radial (i); + pixman_image_set_transform (src_img, &transform); + + for (j = 0; j < NUM_REPEAT; j++) + { + pixman_image_set_repeat (src_img, repeat[j]); + + pixman_image_composite32 (PIXMAN_OP_OVER, + src_img, + NULL, + dest_img, + 0, 0, + 0, 0, + i * SIZE, j * SIZE, + SIZE, SIZE); + + } + + pixman_image_unref (src_img); + } + + show_image (dest_img); + + pixman_image_unref (dest_img); + + return 0; +} -- cgit v1.2.3