From eeab52467b06a339cb5baee3071ef83bf3a48edb Mon Sep 17 00:00:00 2001 From: marha Date: Tue, 21 Sep 2010 18:40:53 +0000 Subject: pixman git update 21/9/2010 --- pixman/test/Makefile.am | 17 +- pixman/test/affine-test.c | 261 ++++++++++++++ pixman/test/alphamap.c | 289 +++++++++++++--- pixman/test/blitters-test.c | 15 - pixman/test/composite-test.c | 383 +++++++++++---------- pixman/test/lowlevel-blt-bench.c | 712 +++++++++++++++++++++++++++++++++++++++ pixman/test/utils.c | 148 +++++++- pixman/test/utils.h | 19 +- 8 files changed, 1583 insertions(+), 261 deletions(-) create mode 100644 pixman/test/affine-test.c create mode 100644 pixman/test/lowlevel-blt-bench.c (limited to 'pixman/test') diff --git a/pixman/test/Makefile.am b/pixman/test/Makefile.am index 108ae96ee..e3ab89038 100644 --- a/pixman/test/Makefile.am +++ b/pixman/test/Makefile.am @@ -13,11 +13,12 @@ TESTPROGRAMS = \ window-test \ gradient-crash-test \ trap-crasher \ - alphamap \ alpha-loop \ scaling-crash-test \ + alphamap \ blitters-test \ scaling-test \ + affine-test \ composite a1_trap_test_LDADD = $(TEST_LDADD) @@ -39,6 +40,9 @@ blitters_test_SOURCES = blitters-test.c utils.c utils.h scaling_test_LDADD = $(TEST_LDADD) scaling_test_SOURCES = scaling-test.c utils.c utils.h +affine_test_LDADD = $(TEST_LDADD) +affine_test_SOURCES = affine-test.c utils.c utils.h + alphamap_LDADD = $(TEST_LDADD) alphamap_SOURCES = alphamap.c utils.c utils.h @@ -90,7 +94,14 @@ convolution_test_SOURCES = convolution-test.c $(GTK_UTILS) endif -noinst_PROGRAMS = $(TESTPROGRAMS) $(TESTPROGRAMS_GTK) +# Benchmarks -TESTS = $(TESTPROGRAMS) +BENCHMARKS = \ + lowlevel-blt-bench +lowlevel_blt_bench_SOURCES = lowlevel-blt-bench.c utils.c utils.h +lowlevel_blt_bench_LDADD = $(TEST_LDADD) + +noinst_PROGRAMS = $(TESTPROGRAMS) $(TESTPROGRAMS_GTK) $(BENCHMARKS) + +TESTS = $(TESTPROGRAMS) diff --git a/pixman/test/affine-test.c b/pixman/test/affine-test.c new file mode 100644 index 000000000..3e32b5a23 --- /dev/null +++ b/pixman/test/affine-test.c @@ -0,0 +1,261 @@ +/* + * Test program, which can detect some problems with affine transformations + * in pixman. Testing is done by running lots of random SRC and OVER + * compositing operations a8r8g8b8, x8a8r8g8b8, r5g6b5 and a8 color formats + * with random scaled, rotated and translated transforms. + * + * Script 'fuzzer-find-diff.pl' can be used to narrow down the problem in + * the case of test failure. + */ +#include +#include +#include +#include "utils.h" + +#define MAX_SRC_WIDTH 16 +#define MAX_SRC_HEIGHT 16 +#define MAX_DST_WIDTH 16 +#define MAX_DST_HEIGHT 16 +#define MAX_STRIDE 4 + +/* + * Composite operation with pseudorandom images + */ +uint32_t +test_composite (int testnum, + int verbose) +{ + int i; + pixman_image_t * src_img; + pixman_image_t * dst_img; + pixman_transform_t transform; + pixman_region16_t clip; + 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 src_bpp; + int dst_bpp; + int w, h; + pixman_fixed_t scale_x = 65536, scale_y = 65536; + pixman_fixed_t translate_x = 0, translate_y = 0; + int op; + int repeat = 0; + int src_fmt, dst_fmt; + uint32_t * srcbuf; + uint32_t * dstbuf; + uint32_t crc32; + FLOAT_REGS_CORRUPTION_DETECTOR_START (); + + lcg_srand (testnum); + + src_bpp = (lcg_rand_n (2) == 0) ? 2 : 4; + dst_bpp = (lcg_rand_n (2) == 0) ? 2 : 4; + op = (lcg_rand_n (2) == 0) ? PIXMAN_OP_SRC : PIXMAN_OP_OVER; + + src_width = lcg_rand_n (MAX_SRC_WIDTH) + 1; + src_height = lcg_rand_n (MAX_SRC_HEIGHT) + 1; + dst_width = lcg_rand_n (MAX_DST_WIDTH) + 1; + dst_height = lcg_rand_n (MAX_DST_HEIGHT) + 1; + src_stride = src_width * src_bpp + lcg_rand_n (MAX_STRIDE) * src_bpp; + dst_stride = dst_width * dst_bpp + lcg_rand_n (MAX_STRIDE) * dst_bpp; + + if (src_stride & 3) + src_stride += 2; + + if (dst_stride & 3) + dst_stride += 2; + + src_x = -(src_width / 4) + lcg_rand_n (src_width * 3 / 2); + src_y = -(src_height / 4) + lcg_rand_n (src_height * 3 / 2); + dst_x = -(dst_width / 4) + lcg_rand_n (dst_width * 3 / 2); + dst_y = -(dst_height / 4) + lcg_rand_n (dst_height * 3 / 2); + w = lcg_rand_n (dst_width * 3 / 2 - dst_x); + h = lcg_rand_n (dst_height * 3 / 2 - dst_y); + + srcbuf = (uint32_t *)malloc (src_stride * src_height); + dstbuf = (uint32_t *)malloc (dst_stride * dst_height); + + for (i = 0; i < src_stride * src_height; i++) + *((uint8_t *)srcbuf + i) = lcg_rand_n (256); + + for (i = 0; i < dst_stride * dst_height; i++) + *((uint8_t *)dstbuf + i) = lcg_rand_n (256); + + src_fmt = src_bpp == 4 ? (lcg_rand_n (2) == 0 ? + PIXMAN_a8r8g8b8 : PIXMAN_x8r8g8b8) : PIXMAN_r5g6b5; + + dst_fmt = dst_bpp == 4 ? (lcg_rand_n (2) == 0 ? + PIXMAN_a8r8g8b8 : PIXMAN_x8r8g8b8) : PIXMAN_r5g6b5; + + src_img = pixman_image_create_bits ( + src_fmt, src_width, src_height, srcbuf, src_stride); + + dst_img = pixman_image_create_bits ( + dst_fmt, dst_width, dst_height, dstbuf, dst_stride); + + image_endian_swap (src_img, src_bpp * 8); + image_endian_swap (dst_img, dst_bpp * 8); + + pixman_transform_init_identity (&transform); + + if (lcg_rand_n (8) > 0) + { + scale_x = -32768 * 3 + lcg_rand_N (65536 * 5); + scale_y = -32768 * 3 + lcg_rand_N (65536 * 5); + translate_x = lcg_rand_N (65536); + translate_y = lcg_rand_N (65536); + pixman_transform_init_scale (&transform, scale_x, scale_y); + pixman_transform_translate (&transform, NULL, translate_x, translate_y); + } + + if (lcg_rand_n (4) > 0) + { + int c = lcg_rand_N (2 * 65536) - 65536; + int s = lcg_rand_N (2 * 65536) - 65536; + + pixman_transform_rotate (&transform, NULL, c, s); + } + + pixman_image_set_transform (src_img, &transform); + + switch (lcg_rand_n (4)) + { + case 0: + repeat = PIXMAN_REPEAT_NONE; + break; + + case 1: + repeat = PIXMAN_REPEAT_NORMAL; + break; + + case 2: + repeat = PIXMAN_REPEAT_PAD; + break; + + case 3: + repeat = PIXMAN_REPEAT_REFLECT; + break; + + default: + break; + } + pixman_image_set_repeat (src_img, repeat); + + if (lcg_rand_n (2)) + pixman_image_set_filter (src_img, PIXMAN_FILTER_NEAREST, NULL, 0); + else + pixman_image_set_filter (src_img, PIXMAN_FILTER_BILINEAR, NULL, 0); + + if (verbose) + { + printf ("src_fmt=%08X, dst_fmt=%08X\n", src_fmt, dst_fmt); + printf ("op=%d, scale_x=%d, scale_y=%d, repeat=%d\n", + op, scale_x, scale_y, repeat); + printf ("translate_x=%d, translate_y=%d\n", + translate_x, translate_y); + 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 ("w=%d, h=%d\n", w, h); + } + + if (lcg_rand_n (8) == 0) + { + pixman_box16_t clip_boxes[2]; + int n = lcg_rand_n (2) + 1; + + for (i = 0; i < n; i++) + { + clip_boxes[i].x1 = lcg_rand_n (src_width); + clip_boxes[i].y1 = lcg_rand_n (src_height); + clip_boxes[i].x2 = + clip_boxes[i].x1 + lcg_rand_n (src_width - clip_boxes[i].x1); + clip_boxes[i].y2 = + clip_boxes[i].y1 + lcg_rand_n (src_height - clip_boxes[i].y1); + + if (verbose) + { + printf ("source clip box: [%d,%d-%d,%d]\n", + clip_boxes[i].x1, clip_boxes[i].y1, + clip_boxes[i].x2, clip_boxes[i].y2); + } + } + + pixman_region_init_rects (&clip, clip_boxes, n); + pixman_image_set_clip_region (src_img, &clip); + pixman_image_set_source_clipping (src_img, 1); + pixman_region_fini (&clip); + } + + if (lcg_rand_n (8) == 0) + { + pixman_box16_t clip_boxes[2]; + int n = lcg_rand_n (2) + 1; + for (i = 0; i < n; i++) + { + clip_boxes[i].x1 = lcg_rand_n (dst_width); + clip_boxes[i].y1 = lcg_rand_n (dst_height); + clip_boxes[i].x2 = + clip_boxes[i].x1 + lcg_rand_n (dst_width - clip_boxes[i].x1); + clip_boxes[i].y2 = + clip_boxes[i].y1 + lcg_rand_n (dst_height - clip_boxes[i].y1); + + if (verbose) + { + printf ("destination clip box: [%d,%d-%d,%d]\n", + clip_boxes[i].x1, clip_boxes[i].y1, + clip_boxes[i].x2, clip_boxes[i].y2); + } + } + pixman_region_init_rects (&clip, clip_boxes, n); + pixman_image_set_clip_region (dst_img, &clip); + pixman_region_fini (&clip); + } + + pixman_image_composite (op, src_img, NULL, dst_img, + src_x, src_y, 0, 0, dst_x, dst_y, w, h); + + if (dst_fmt == PIXMAN_x8r8g8b8) + { + /* ignore unused part */ + for (i = 0; i < dst_stride * dst_height / 4; i++) + dstbuf[i] &= 0xFFFFFF; + } + + image_endian_swap (dst_img, dst_bpp * 8); + + if (verbose) + { + int j; + + for (i = 0; i < dst_height; i++) + { + for (j = 0; j < dst_stride; j++) + printf ("%02X ", *((uint8_t *)dstbuf + i * dst_stride + j)); + + printf ("\n"); + } + } + + pixman_image_unref (src_img); + pixman_image_unref (dst_img); + + crc32 = compute_crc32 (0, dstbuf, dst_stride * dst_height); + free (srcbuf); + free (dstbuf); + + FLOAT_REGS_CORRUPTION_DETECTOR_FINISH (); + return crc32; +} + +int +main (int argc, const char *argv[]) +{ + pixman_disable_out_of_bounds_workaround (); + + return fuzzer_test_main ("affine", 8000000, 0x46EC3C6A, + test_composite, argc, argv); +} diff --git a/pixman/test/alphamap.c b/pixman/test/alphamap.c index e6a25efcb..eb7a330f9 100644 --- a/pixman/test/alphamap.c +++ b/pixman/test/alphamap.c @@ -1,49 +1,240 @@ -#include -#include -#include "utils.h" - -#define WIDTH 400 -#define HEIGHT 200 - -int -main (int argc, char **argv) -{ - uint8_t *alpha = make_random_bytes (WIDTH * HEIGHT); - uint32_t *src = (uint32_t *)make_random_bytes (WIDTH * HEIGHT * 4); - uint32_t *dest = (uint32_t *)make_random_bytes (WIDTH * HEIGHT * 4); - int i; - - pixman_image_t *a = pixman_image_create_bits (PIXMAN_a8, WIDTH, HEIGHT, (uint32_t *)alpha, WIDTH); - pixman_image_t *d = pixman_image_create_bits (PIXMAN_a8r8g8b8, WIDTH, HEIGHT, dest, WIDTH * 4); - - for (i = 0; i < 2; ++i) - { - pixman_format_code_t sformat = (i == 0)? PIXMAN_a8r8g8b8 : PIXMAN_a2r10g10b10; - pixman_image_t *s = pixman_image_create_bits (sformat, WIDTH, HEIGHT, src, WIDTH * 4); - int j, k; - - pixman_image_set_alpha_map (s, a, 0, 0); - - pixman_image_composite (PIXMAN_OP_SRC, s, NULL, d, 0, 0, 0, 0, 0, 0, WIDTH, HEIGHT); - - for (j = 0; j < HEIGHT; ++j) - { - for (k = 0; k < WIDTH; ++k) - { - uint8_t ap = ((uint8_t *)alpha)[j * WIDTH + k]; - uint32_t dap = (dest[j * WIDTH + k] >> 24); - uint32_t sap = (src[j * WIDTH + k] >> 24); - - if (ap != dap) - { - printf ("Wrong alpha value at (%d, %d). Should be %d; got %d (src was %d)\n", k, j, ap, dap, sap); - return 1; - } - } - } - - pixman_image_unref (s); - } - - 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 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; +} diff --git a/pixman/test/blitters-test.c b/pixman/test/blitters-test.c index a61817d96..a9e8cc2ce 100644 --- a/pixman/test/blitters-test.c +++ b/pixman/test/blitters-test.c @@ -14,21 +14,6 @@ static pixman_indexed_t rgb_palette[9]; static pixman_indexed_t y_palette[9]; -static void * -aligned_malloc (size_t align, size_t size) -{ - void *result; - -#ifdef HAVE_POSIX_MEMALIGN - if (posix_memalign (&result, align, size) != 0) - result = NULL; -#else - result = malloc (size); -#endif - - return result; -} - /* Create random image for testing purposes */ static pixman_image_t * create_random_image (pixman_format_code_t *allowed_formats, diff --git a/pixman/test/composite-test.c b/pixman/test/composite-test.c index 5401abfdf..79d5d5eac 100644 --- a/pixman/test/composite-test.c +++ b/pixman/test/composite-test.c @@ -1,192 +1,191 @@ -#include -#include -#include -#include "pixman.h" -#include "gtk-utils.h" - -#define WIDTH 60 -#define HEIGHT 60 - -typedef struct { - const char *name; - pixman_op_t op; -} operator_t; - -static const operator_t operators[] = { - { "CLEAR", PIXMAN_OP_CLEAR }, - { "SRC", PIXMAN_OP_SRC }, - { "DST", PIXMAN_OP_DST }, - { "OVER", PIXMAN_OP_OVER }, - { "OVER_REVERSE", PIXMAN_OP_OVER_REVERSE }, - { "IN", PIXMAN_OP_IN }, - { "IN_REVERSE", PIXMAN_OP_IN_REVERSE }, - { "OUT", PIXMAN_OP_OUT }, - { "OUT_REVERSE", PIXMAN_OP_OUT_REVERSE }, - { "ATOP", PIXMAN_OP_ATOP }, - { "ATOP_REVERSE", PIXMAN_OP_ATOP_REVERSE }, - { "XOR", PIXMAN_OP_XOR }, - { "ADD", PIXMAN_OP_ADD }, - { "SATURATE", PIXMAN_OP_SATURATE }, - - { "MULTIPLY", PIXMAN_OP_MULTIPLY }, - { "SCREEN", PIXMAN_OP_SCREEN }, - { "OVERLAY", PIXMAN_OP_OVERLAY }, - { "DARKEN", PIXMAN_OP_DARKEN }, - { "LIGHTEN", PIXMAN_OP_LIGHTEN }, - { "COLOR_DODGE", PIXMAN_OP_COLOR_DODGE }, - { "COLOR_BURN", PIXMAN_OP_COLOR_BURN }, - { "HARD_LIGHT", PIXMAN_OP_HARD_LIGHT }, - { "SOFT_LIGHT", PIXMAN_OP_SOFT_LIGHT }, - { "DIFFERENCE", PIXMAN_OP_DIFFERENCE }, - { "EXCLUSION", PIXMAN_OP_EXCLUSION }, - { "HSL_HUE", PIXMAN_OP_HSL_HUE }, - { "HSL_SATURATION", PIXMAN_OP_HSL_SATURATION }, - { "HSL_COLOR", PIXMAN_OP_HSL_COLOR }, - { "HSL_LUMINOSITY", PIXMAN_OP_HSL_LUMINOSITY }, -}; - -static uint32_t -reader (const void *src, int size) -{ - switch (size) - { - case 1: - return *(uint8_t *)src; - case 2: - return *(uint16_t *)src; - case 4: - return *(uint32_t *)src; - default: - g_assert_not_reached(); - } -} - -static void -writer (void *src, uint32_t value, int size) -{ - switch (size) - { - case 1: - *(uint8_t *)src = value; - break; - - case 2: - *(uint16_t *)src = value; - break; - - case 4: - *(uint32_t *)src = value; - break; - - default: - break; - } -} - -int -main (int argc, char **argv) -{ -#define d2f pixman_double_to_fixed - - GtkWidget *window, *swindow; - GtkWidget *table; - uint32_t *dest = malloc (WIDTH * HEIGHT * 4); - uint32_t *src = malloc (WIDTH * HEIGHT * 4); - pixman_image_t *src_img; - pixman_image_t *dest_img; - pixman_point_fixed_t p1 = { -10 << 0, 0 }; - pixman_point_fixed_t p2 = { WIDTH << 16, (HEIGHT - 10) << 16 }; - uint16_t full = 0xcfff; - uint16_t low = 0x5000; - uint16_t alpha = 0xffff; - pixman_gradient_stop_t stops[6] = - { - { d2f (0.0), { full, low, low, alpha } }, - { d2f (0.25), { full, full, low, alpha } }, - { d2f (0.4), { low, full, low, alpha } }, - { d2f (0.5), { low, full, full, alpha } }, - { d2f (0.8), { low, low, full, alpha } }, - { d2f (1.0), { full, low, full, alpha } }, - }; - - - int i; - - gtk_init (&argc, &argv); - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - - gtk_window_set_default_size (GTK_WINDOW (window), 800, 600); - - g_signal_connect (window, "delete-event", - G_CALLBACK (gtk_main_quit), - NULL); - table = gtk_table_new (G_N_ELEMENTS (operators) / 6, 6, TRUE); - - src_img = pixman_image_create_linear_gradient (&p1, &p2, stops, - sizeof (stops) / sizeof (stops[0])); - - pixman_image_set_repeat (src_img, PIXMAN_REPEAT_PAD); - - dest_img = pixman_image_create_bits (PIXMAN_a8r8g8b8, - WIDTH, HEIGHT, - dest, - WIDTH * 4); - pixman_image_set_accessors (dest_img, reader, writer); - - for (i = 0; i < G_N_ELEMENTS (operators); ++i) - { - GtkWidget *image; - GdkPixbuf *pixbuf; - GtkWidget *vbox; - GtkWidget *label; - int j, k; - - vbox = gtk_vbox_new (FALSE, 0); - - label = gtk_label_new (operators[i].name); - gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 6); - gtk_widget_show (label); - - for (j = 0; j < HEIGHT; ++j) - { - for (k = 0; k < WIDTH; ++k) - dest[j * WIDTH + k] = 0x7f6f6f00; - } - pixman_image_composite (operators[i].op, src_img, NULL, dest_img, - 0, 0, 0, 0, 0, 0, WIDTH, HEIGHT); - pixbuf = pixbuf_from_argb32 (pixman_image_get_data (dest_img), TRUE, - WIDTH, HEIGHT, WIDTH * 4); - image = gtk_image_new_from_pixbuf (pixbuf); - gtk_box_pack_start (GTK_BOX (vbox), image, FALSE, FALSE, 0); - gtk_widget_show (image); - - gtk_table_attach_defaults (GTK_TABLE (table), vbox, - i % 6, (i % 6) + 1, i / 6, (i / 6) + 1); - gtk_widget_show (vbox); - - g_object_unref (pixbuf); - } - - pixman_image_unref (src_img); - free (src); - pixman_image_unref (dest_img); - free (dest); - - swindow = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); - - gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (swindow), table); - gtk_widget_show (table); - - gtk_container_add (GTK_CONTAINER (window), swindow); - gtk_widget_show (swindow); - - gtk_widget_show (window); - - gtk_main (); - - return 0; -} +#include +#include +#include +#include "pixman.h" +#include "gtk-utils.h" + +#define WIDTH 60 +#define HEIGHT 60 + +typedef struct { + const char *name; + pixman_op_t op; +} operator_t; + +static const operator_t operators[] = { + { "CLEAR", PIXMAN_OP_CLEAR }, + { "SRC", PIXMAN_OP_SRC }, + { "DST", PIXMAN_OP_DST }, + { "OVER", PIXMAN_OP_OVER }, + { "OVER_REVERSE", PIXMAN_OP_OVER_REVERSE }, + { "IN", PIXMAN_OP_IN }, + { "IN_REVERSE", PIXMAN_OP_IN_REVERSE }, + { "OUT", PIXMAN_OP_OUT }, + { "OUT_REVERSE", PIXMAN_OP_OUT_REVERSE }, + { "ATOP", PIXMAN_OP_ATOP }, + { "ATOP_REVERSE", PIXMAN_OP_ATOP_REVERSE }, + { "XOR", PIXMAN_OP_XOR }, + { "ADD", PIXMAN_OP_ADD }, + { "SATURATE", PIXMAN_OP_SATURATE }, + + { "MULTIPLY", PIXMAN_OP_MULTIPLY }, + { "SCREEN", PIXMAN_OP_SCREEN }, + { "OVERLAY", PIXMAN_OP_OVERLAY }, + { "DARKEN", PIXMAN_OP_DARKEN }, + { "LIGHTEN", PIXMAN_OP_LIGHTEN }, + { "COLOR_DODGE", PIXMAN_OP_COLOR_DODGE }, + { "COLOR_BURN", PIXMAN_OP_COLOR_BURN }, + { "HARD_LIGHT", PIXMAN_OP_HARD_LIGHT }, + { "SOFT_LIGHT", PIXMAN_OP_SOFT_LIGHT }, + { "DIFFERENCE", PIXMAN_OP_DIFFERENCE }, + { "EXCLUSION", PIXMAN_OP_EXCLUSION }, + { "HSL_HUE", PIXMAN_OP_HSL_HUE }, + { "HSL_SATURATION", PIXMAN_OP_HSL_SATURATION }, + { "HSL_COLOR", PIXMAN_OP_HSL_COLOR }, + { "HSL_LUMINOSITY", PIXMAN_OP_HSL_LUMINOSITY }, +}; + +static uint32_t +reader (const void *src, int size) +{ + switch (size) + { + case 1: + return *(uint8_t *)src; + case 2: + return *(uint16_t *)src; + case 4: + return *(uint32_t *)src; + default: + g_assert_not_reached(); + } +} + +static void +writer (void *src, uint32_t value, int size) +{ + switch (size) + { + case 1: + *(uint8_t *)src = value; + break; + + case 2: + *(uint16_t *)src = value; + break; + + case 4: + *(uint32_t *)src = value; + break; + + default: + break; + } +} + +int +main (int argc, char **argv) +{ +#define d2f pixman_double_to_fixed + + GtkWidget *window, *swindow; + GtkWidget *table; + uint32_t *dest = malloc (WIDTH * HEIGHT * 4); + uint32_t *src = malloc (WIDTH * HEIGHT * 4); + pixman_image_t *src_img; + pixman_image_t *dest_img; + pixman_point_fixed_t p1 = { -10 << 0, 0 }; + pixman_point_fixed_t p2 = { WIDTH << 16, (HEIGHT - 10) << 16 }; + uint16_t full = 0xcfff; + uint16_t low = 0x5000; + uint16_t alpha = 0xffff; + pixman_gradient_stop_t stops[6] = + { + { d2f (0.0), { full, low, low, alpha } }, + { d2f (0.25), { full, full, low, alpha } }, + { d2f (0.4), { low, full, low, alpha } }, + { d2f (0.6), { low, full, full, alpha } }, + { d2f (0.8), { low, low, full, alpha } }, + { d2f (1.0), { full, low, full, alpha } }, + }; + + int i; + + gtk_init (&argc, &argv); + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + + gtk_window_set_default_size (GTK_WINDOW (window), 800, 600); + + g_signal_connect (window, "delete-event", + G_CALLBACK (gtk_main_quit), + NULL); + table = gtk_table_new (G_N_ELEMENTS (operators) / 6, 6, TRUE); + + src_img = pixman_image_create_linear_gradient (&p1, &p2, stops, + sizeof (stops) / sizeof (stops[0])); + + pixman_image_set_repeat (src_img, PIXMAN_REPEAT_PAD); + + dest_img = pixman_image_create_bits (PIXMAN_a8r8g8b8, + WIDTH, HEIGHT, + dest, + WIDTH * 4); + pixman_image_set_accessors (dest_img, reader, writer); + + for (i = 0; i < G_N_ELEMENTS (operators); ++i) + { + GtkWidget *image; + GdkPixbuf *pixbuf; + GtkWidget *vbox; + GtkWidget *label; + int j, k; + + vbox = gtk_vbox_new (FALSE, 0); + + label = gtk_label_new (operators[i].name); + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 6); + gtk_widget_show (label); + + for (j = 0; j < HEIGHT; ++j) + { + for (k = 0; k < WIDTH; ++k) + dest[j * WIDTH + k] = 0x7f6f6f00; + } + pixman_image_composite (operators[i].op, src_img, NULL, dest_img, + 0, 0, 0, 0, 0, 0, WIDTH, HEIGHT); + pixbuf = pixbuf_from_argb32 (pixman_image_get_data (dest_img), TRUE, + WIDTH, HEIGHT, WIDTH * 4); + image = gtk_image_new_from_pixbuf (pixbuf); + gtk_box_pack_start (GTK_BOX (vbox), image, FALSE, FALSE, 0); + gtk_widget_show (image); + + gtk_table_attach_defaults (GTK_TABLE (table), vbox, + i % 6, (i % 6) + 1, i / 6, (i / 6) + 1); + gtk_widget_show (vbox); + + g_object_unref (pixbuf); + } + + pixman_image_unref (src_img); + free (src); + pixman_image_unref (dest_img); + free (dest); + + swindow = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + + gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (swindow), table); + gtk_widget_show (table); + + gtk_container_add (GTK_CONTAINER (window), swindow); + gtk_widget_show (swindow); + + gtk_widget_show (window); + + gtk_main (); + + return 0; +} diff --git a/pixman/test/lowlevel-blt-bench.c b/pixman/test/lowlevel-blt-bench.c new file mode 100644 index 000000000..d4df81507 --- /dev/null +++ b/pixman/test/lowlevel-blt-bench.c @@ -0,0 +1,712 @@ +/* + * Copyright © 2009 Nokia Corporation + * Copyright © 2010 Movial Creative Technologies Oy + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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. + */ + +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "pixman-private.h" +#include "utils.h" + +#define SOLID_FLAG 1 +#define CA_FLAG 2 + +#define L1CACHE_SIZE (8 * 1024) +#define L2CACHE_SIZE (128 * 1024) + +#define WIDTH 1920 +#define HEIGHT 1080 +#define BUFSIZE (WIDTH * HEIGHT * 4) +#define XWIDTH 256 +#define XHEIGHT 256 +#define TILEWIDTH 32 +#define TINYWIDTH 8 + +#define EXCLUDE_OVERHEAD 1 + +uint32_t *dst; +uint32_t *src; +uint32_t *mask; + +double bandwidth = 0; + +double +bench_memcpy () +{ + int64_t n = 0, total; + double t1, t2; + int x = 0; + + t1 = gettime (); + while (1) + { + memcpy (dst, src, BUFSIZE - 64); + memcpy (src, dst, BUFSIZE - 64); + n += 4 * (BUFSIZE - 64); + t2 = gettime (); + if (t2 - t1 > 0.5) + break; + } + n = total = n * 5; + t1 = gettime (); + while (n > 0) + { + if (++x >= 64) + x = 0; + memcpy ((char *)dst + 1, (char *)src + x, BUFSIZE - 64); + memcpy ((char *)src + 1, (char *)dst + x, BUFSIZE - 64); + n -= 4 * (BUFSIZE - 64); + } + t2 = gettime (); + return (double)total / (t2 - t1); +} + +static void +pixman_image_composite_wrapper (pixman_implementation_t *impl, + pixman_op_t op, + 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) +{ + pixman_image_composite (op, src_image, mask_image, dst_image, src_x, + src_y, mask_x, mask_y, dest_x, dest_y, width, height); +} + +static void +pixman_image_composite_empty (pixman_implementation_t *impl, + pixman_op_t op, + 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) +{ + pixman_image_composite (op, src_image, mask_image, dst_image, 0, + 0, 0, 0, 0, 0, 1, 1); +} + +void +noinline +bench_L (pixman_op_t op, + pixman_image_t * src_img, + pixman_image_t * mask_img, + pixman_image_t * dst_img, + int64_t n, + pixman_composite_func_t func, + int width, + int lines_count) +{ + int64_t i, j; + int x = 0; + int q = 0; + volatile int qx; + + for (i = 0; i < n; i++) + { + /* touch destination buffer to fetch it into L1 cache */ + for (j = 0; j < width + 64; j += 16) { + q += dst[j]; + q += src[j]; + } + if (++x >= 64) + x = 0; + func (0, op, src_img, mask_img, dst_img, x, 0, x, 0, 63 - x, 0, width, lines_count); + } + qx = q; +} + +void +noinline +bench_M (pixman_op_t op, + pixman_image_t * src_img, + pixman_image_t * mask_img, + pixman_image_t * dst_img, + int64_t n, + pixman_composite_func_t func) +{ + int64_t i; + int x = 0; + + for (i = 0; i < n; i++) + { + if (++x >= 64) + x = 0; + func (0, op, src_img, mask_img, dst_img, x, 0, x, 0, 1, 0, WIDTH - 64, HEIGHT); + } +} + +double +noinline +bench_HT (pixman_op_t op, + pixman_image_t * src_img, + pixman_image_t * mask_img, + pixman_image_t * dst_img, + int64_t n, + pixman_composite_func_t func) +{ + double pix_cnt = 0; + int x = 0; + int y = 0; + int64_t i; + + srand (0); + for (i = 0; i < n; i++) + { + int w = (rand () % (TILEWIDTH * 2)) + 1; + int h = (rand () % (TILEWIDTH * 2)) + 1; + if (x + w > WIDTH) + { + x = 0; + y += TILEWIDTH * 2; + } + if (y + h > HEIGHT) + { + y = 0; + } + func (0, op, src_img, mask_img, dst_img, x, y, x, y, x, y, w, h); + x += w; + pix_cnt += w * h; + } + return pix_cnt; +} + +double +noinline +bench_VT (pixman_op_t op, + pixman_image_t * src_img, + pixman_image_t * mask_img, + pixman_image_t * dst_img, + int64_t n, + pixman_composite_func_t func) +{ + double pix_cnt = 0; + int x = 0; + int y = 0; + int64_t i; + + srand (0); + for (i = 0; i < n; i++) + { + int w = (rand () % (TILEWIDTH * 2)) + 1; + int h = (rand () % (TILEWIDTH * 2)) + 1; + if (y + h > HEIGHT) + { + y = 0; + x += TILEWIDTH * 2; + } + if (x + w > WIDTH) + { + x = 0; + } + func (0, op, src_img, mask_img, dst_img, x, y, x, y, x, y, w, h); + y += h; + pix_cnt += w * h; + } + return pix_cnt; +} + +double +noinline +bench_R (pixman_op_t op, + pixman_image_t * src_img, + pixman_image_t * mask_img, + pixman_image_t * dst_img, + int64_t n, + pixman_composite_func_t func, + int maxw, + int maxh) +{ + double pix_cnt = 0; + int64_t i; + + if (maxw <= TILEWIDTH * 2 || maxh <= TILEWIDTH * 2) + { + printf("error: maxw <= TILEWIDTH * 2 || maxh <= TILEWIDTH * 2\n"); + return 0; + } + + srand (0); + for (i = 0; i < n; i++) + { + int w = (rand () % (TILEWIDTH * 2)) + 1; + int h = (rand () % (TILEWIDTH * 2)) + 1; + int sx = rand () % (maxw - TILEWIDTH * 2); + int sy = rand () % (maxh - TILEWIDTH * 2); + int dx = rand () % (maxw - TILEWIDTH * 2); + int dy = rand () % (maxh - TILEWIDTH * 2); + func (0, op, src_img, mask_img, dst_img, sx, sy, sx, sy, dx, dy, w, h); + pix_cnt += w * h; + } + return pix_cnt; +} + +double +noinline +bench_RT (pixman_op_t op, + pixman_image_t * src_img, + pixman_image_t * mask_img, + pixman_image_t * dst_img, + int64_t n, + pixman_composite_func_t func, + int maxw, + int maxh) +{ + double pix_cnt = 0; + int64_t i; + + if (maxw <= TINYWIDTH * 2 || maxh <= TINYWIDTH * 2) + { + printf("error: maxw <= TINYWIDTH * 2 || maxh <= TINYWIDTH * 2\n"); + return 0; + } + + srand (0); + for (i = 0; i < n; i++) + { + int w = (rand () % (TINYWIDTH * 2)) + 1; + int h = (rand () % (TINYWIDTH * 2)) + 1; + int sx = rand () % (maxw - TINYWIDTH * 2); + int sy = rand () % (maxh - TINYWIDTH * 2); + int dx = rand () % (maxw - TINYWIDTH * 2); + int dy = rand () % (maxh - TINYWIDTH * 2); + func (0, op, src_img, mask_img, dst_img, sx, sy, sx, sy, dx, dy, w, h); + pix_cnt += w * h; + } + return pix_cnt; +} + +void +bench_composite (char * testname, + int src_fmt, + int src_flags, + int op, + int mask_fmt, + int mask_flags, + int dst_fmt, + double npix) +{ + pixman_image_t * src_img; + pixman_image_t * dst_img; + pixman_image_t * mask_img; + pixman_image_t * xsrc_img; + pixman_image_t * xdst_img; + pixman_image_t * xmask_img; + double t1, t2, t3, pix_cnt; + int64_t n, l1test_width, nlines; + double bytes_per_pix = 0; + + pixman_composite_func_t func = pixman_image_composite_wrapper; + + if (!(src_flags & SOLID_FLAG)) + { + bytes_per_pix += (src_fmt >> 24) / 8.0; + src_img = pixman_image_create_bits (src_fmt, + WIDTH, HEIGHT, + src, + WIDTH * 4); + xsrc_img = pixman_image_create_bits (src_fmt, + XWIDTH, XHEIGHT, + src, + XWIDTH * 4); + } + else + { + src_img = pixman_image_create_bits (src_fmt, + 1, 1, + src, + 4); + xsrc_img = pixman_image_create_bits (src_fmt, + 1, 1, + src, + 4); + pixman_image_set_repeat (src_img, PIXMAN_REPEAT_NORMAL); + pixman_image_set_repeat (xsrc_img, PIXMAN_REPEAT_NORMAL); + } + + bytes_per_pix += (dst_fmt >> 24) / 8.0; + dst_img = pixman_image_create_bits (dst_fmt, + WIDTH, HEIGHT, + dst, + WIDTH * 4); + + mask_img = NULL; + xmask_img = NULL; + if (!(mask_flags & SOLID_FLAG) && mask_fmt != PIXMAN_null) + { + bytes_per_pix += (mask_fmt >> 24) / ((op == PIXMAN_OP_SRC) ? 8.0 : 4.0); + mask_img = pixman_image_create_bits (mask_fmt, + WIDTH, HEIGHT, + mask, + WIDTH * 4); + xmask_img = pixman_image_create_bits (mask_fmt, + XWIDTH, XHEIGHT, + mask, + XWIDTH * 4); + } + else if (mask_fmt != PIXMAN_null) + { + mask_img = pixman_image_create_bits (mask_fmt, + 1, 1, + mask, + 4); + xmask_img = pixman_image_create_bits (mask_fmt, + 1, 1, + mask, + 4 * 4); + pixman_image_set_repeat (mask_img, PIXMAN_REPEAT_NORMAL); + pixman_image_set_repeat (xmask_img, PIXMAN_REPEAT_NORMAL); + } + if ((mask_flags & CA_FLAG) && mask_fmt != PIXMAN_null) + { + pixman_image_set_component_alpha (mask_img, 1); + } + xdst_img = pixman_image_create_bits (dst_fmt, + XWIDTH, XHEIGHT, + dst, + XWIDTH * 4); + + + printf ("%24s %c", testname, func != pixman_image_composite_wrapper ? + '-' : '='); + + memcpy (src, dst, BUFSIZE); + memcpy (dst, src, BUFSIZE); + + l1test_width = L1CACHE_SIZE / 8 - 64; + if (l1test_width < 1) + l1test_width = 1; + if (l1test_width > WIDTH - 64) + l1test_width = WIDTH - 64; + n = 1 + npix / (l1test_width * 8); + t1 = gettime (); +#if EXCLUDE_OVERHEAD + bench_L (op, src_img, mask_img, dst_img, n, pixman_image_composite_empty, l1test_width, 1); +#endif + t2 = gettime (); + bench_L (op, src_img, mask_img, dst_img, n, func, l1test_width, 1); + t3 = gettime (); + printf (" L1:%7.2f", (double)n * l1test_width * 1 / + ((t3 - t2) - (t2 - t1)) / 1000000.); + fflush (stdout); + + memcpy (src, dst, BUFSIZE); + memcpy (dst, src, BUFSIZE); + + nlines = (L2CACHE_SIZE / l1test_width) / + ((PIXMAN_FORMAT_BPP(src_fmt) + PIXMAN_FORMAT_BPP(dst_fmt)) / 8); + if (nlines < 1) + nlines = 1; + n = 1 + npix / (l1test_width * nlines); + t1 = gettime (); +#if EXCLUDE_OVERHEAD + bench_L (op, src_img, mask_img, dst_img, n, pixman_image_composite_empty, l1test_width, nlines); +#endif + t2 = gettime (); + bench_L (op, src_img, mask_img, dst_img, n, func, l1test_width, nlines); + t3 = gettime (); + printf (" L2:%7.2f", (double)n * l1test_width * nlines / + ((t3 - t2) - (t2 - t1)) / 1000000.); + fflush (stdout); + + memcpy (src, dst, BUFSIZE); + memcpy (dst, src, BUFSIZE); + + n = 1 + npix / (WIDTH * HEIGHT); + t1 = gettime (); +#if EXCLUDE_OVERHEAD + bench_M (op, src_img, mask_img, dst_img, n, pixman_image_composite_empty); +#endif + t2 = gettime (); + bench_M (op, src_img, mask_img, dst_img, n, func); + t3 = gettime (); + printf (" M:%6.2f (%6.2f%%)", + ((double)n * (WIDTH - 64) * HEIGHT / ((t3 - t2) - (t2 - t1))) / 1000000., + ((double)n * (WIDTH - 64) * HEIGHT / ((t3 - t2) - (t2 - t1)) * bytes_per_pix) * (100.0 / bandwidth) ); + fflush (stdout); + + memcpy (src, dst, BUFSIZE); + memcpy (dst, src, BUFSIZE); + + n = 1 + npix / (8 * TILEWIDTH * TILEWIDTH); + t1 = gettime (); +#if EXCLUDE_OVERHEAD + pix_cnt = bench_HT (op, src_img, mask_img, dst_img, n, pixman_image_composite_empty); +#endif + t2 = gettime (); + pix_cnt = bench_HT (op, src_img, mask_img, dst_img, n, func); + t3 = gettime (); + printf (" HT:%6.2f", (double)pix_cnt / ((t3 - t2) - (t2 - t1)) / 1000000.); + fflush (stdout); + + memcpy (src, dst, BUFSIZE); + memcpy (dst, src, BUFSIZE); + + n = 1 + npix / (8 * TILEWIDTH * TILEWIDTH); + t1 = gettime (); +#if EXCLUDE_OVERHEAD + pix_cnt = bench_VT (op, src_img, mask_img, dst_img, n, pixman_image_composite_empty); +#endif + t2 = gettime (); + pix_cnt = bench_VT (op, src_img, mask_img, dst_img, n, func); + t3 = gettime (); + printf (" VT:%6.2f", (double)pix_cnt / ((t3 - t2) - (t2 - t1)) / 1000000.); + fflush (stdout); + + memcpy (src, dst, BUFSIZE); + memcpy (dst, src, BUFSIZE); + + n = 1 + npix / (8 * TILEWIDTH * TILEWIDTH); + t1 = gettime (); +#if EXCLUDE_OVERHEAD + pix_cnt = bench_R (op, src_img, mask_img, dst_img, n, pixman_image_composite_empty, WIDTH, HEIGHT); +#endif + t2 = gettime (); + pix_cnt = bench_R (op, src_img, mask_img, dst_img, n, func, WIDTH, HEIGHT); + t3 = gettime (); + printf (" R:%6.2f", (double)pix_cnt / ((t3 - t2) - (t2 - t1)) / 1000000.); + fflush (stdout); + + memcpy (src, dst, BUFSIZE); + memcpy (dst, src, BUFSIZE); + + n = 1 + npix / (16 * TINYWIDTH * TINYWIDTH); + t1 = gettime (); +#if EXCLUDE_OVERHEAD + pix_cnt = bench_RT (op, src_img, mask_img, dst_img, n, pixman_image_composite_empty, WIDTH, HEIGHT); +#endif + t2 = gettime (); + pix_cnt = bench_RT (op, src_img, mask_img, dst_img, n, func, WIDTH, HEIGHT); + t3 = gettime (); + printf (" RT:%6.2f (%4.0fKops/s)\n", (double)pix_cnt / ((t3 - t2) - (t2 - t1)) / 1000000., (double) n / ((t3 - t2) * 1000)); + + if (mask_img) { + pixman_image_unref (mask_img); + pixman_image_unref (xmask_img); + } + pixman_image_unref (src_img); + pixman_image_unref (dst_img); + pixman_image_unref (xsrc_img); + pixman_image_unref (xdst_img); +} + +#define PIXMAN_OP_OUT_REV (PIXMAN_OP_OUT_REVERSE) + +struct +{ + char *testname; + int src_fmt; + int src_flags; + int op; + int mask_fmt; + int mask_flags; + int dst_fmt; +} +tests_tbl[] = +{ + { "add_8_8_8", PIXMAN_a8, 0, PIXMAN_OP_ADD, PIXMAN_a8, 0, PIXMAN_a8 }, + { "add_n_8_8000", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_ADD, PIXMAN_a8, 0, PIXMAN_a8 }, + { "add_n_8_8888", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_ADD, PIXMAN_a8, 0, PIXMAN_a8r8g8b8 }, + { "add_n_8_x888", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_ADD, PIXMAN_a8, 0, PIXMAN_x8r8g8b8 }, + { "add_n_8_0565", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_ADD, PIXMAN_a8, 0, PIXMAN_r5g6b5 }, + { "add_n_8_1555", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_ADD, PIXMAN_a8, 0, PIXMAN_a1r5g5b5 }, + { "add_n_8_4444", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_ADD, PIXMAN_a8, 0, PIXMAN_a4r4g4b4 }, + { "add_n_8_2222", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_ADD, PIXMAN_a8, 0, PIXMAN_a2r2g2b2 }, + { "add_n_8_2x10", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_ADD, PIXMAN_a8, 0, PIXMAN_x2r10g10b10 }, + { "add_n_8_2a10", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_ADD, PIXMAN_a8, 0, PIXMAN_a2r10g10b10 }, + { "add_n_8000", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_a8 }, + { "add_n_8888", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_a8r8g8b8 }, + { "add_n_x888", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_x8r8g8b8 }, + { "add_n_0565", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_r5g6b5 }, + { "add_n_1555", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_a1r5g5b5 }, + { "add_n_4444", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_a4r4g4b4 }, + { "add_n_2222", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_a2r2g2b2 }, + { "add_n_2x10", PIXMAN_a2r10g10b10, 1, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_x2r10g10b10 }, + { "add_n_2a10", PIXMAN_a2r10g10b10, 1, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_a2r10g10b10 }, + { "add_8000_8000", PIXMAN_a8, 0, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_a8 }, + { "add_x888_x888", PIXMAN_x8r8g8b8, 0, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_x8r8g8b8 }, + { "add_8888_8888", PIXMAN_a8r8g8b8, 0, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_a8r8g8b8 }, + { "add_8888_0565", PIXMAN_a8r8g8b8, 0, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_r5g6b5 }, + { "add_8888_1555", PIXMAN_a8r8g8b8, 0, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_a1r5g5b5 }, + { "add_8888_4444", PIXMAN_a8r8g8b8, 0, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_a4r4g4b4 }, + { "add_8888_2222", PIXMAN_a8r8g8b8, 0, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_a2r2g2b2 }, + { "add_0565_0565", PIXMAN_r5g6b5, 0, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_r5g6b5 }, + { "add_1555_1555", PIXMAN_a1r5g5b5, 0, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_a1r5g5b5 }, + { "add_0565_2x10", PIXMAN_r5g6b5, 0, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_x2r10g10b10 }, + { "add_2a10_2a10", PIXMAN_a2r10g10b10, 0, PIXMAN_OP_ADD, PIXMAN_null, 0, PIXMAN_a2r10g10b10 }, + { "src_n_2222", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_a2r2g2b2 }, + { "src_n_0565", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_r5g6b5 }, + { "src_n_1555", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_a1r5g5b5 }, + { "src_n_4444", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_a4r4g4b4 }, + { "src_n_x888", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_x8r8g8b8 }, + { "src_n_8888", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_a8r8g8b8 }, + { "src_n_2x10", PIXMAN_a2r10g10b10, 1, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_x2r10g10b10 }, + { "src_n_2a10", PIXMAN_a2r10g10b10, 1, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_a2r10g10b10 }, + { "src_8888_0565", PIXMAN_a8r8g8b8, 0, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_r5g6b5 }, + { "src_8888_4444", PIXMAN_a8r8g8b8, 0, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_a4r4g4b4 }, + { "src_8888_2222", PIXMAN_a8r8g8b8, 0, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_a2r2g2b2 }, + { "src_8888_2x10", PIXMAN_a8r8g8b8, 0, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_x2r10g10b10 }, + { "src_8888_2a10", PIXMAN_a8r8g8b8, 0, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_a2r10g10b10 }, + { "src_0888_0565", PIXMAN_r8g8b8, 0, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_r5g6b5 }, + { "src_0888_8888", PIXMAN_r8g8b8, 0, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_a8r8g8b8 }, + { "src_0888_x888", PIXMAN_r8g8b8, 0, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_x8r8g8b8 }, + { "src_x888_x888", PIXMAN_x8r8g8b8, 0, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_x8r8g8b8 }, + { "src_x888_8888", PIXMAN_x8r8g8b8, 0, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_a8r8g8b8 }, + { "src_8888_8888", PIXMAN_a8r8g8b8, 0, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_a8r8g8b8 }, + { "src_0565_0565", PIXMAN_r5g6b5, 0, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_r5g6b5 }, + { "src_1555_0565", PIXMAN_a1r5g5b5, 0, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_r5g6b5 }, + { "src_0565_1555", PIXMAN_r5g6b5, 0, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_a1r5g5b5 }, + { "src_n_8_0565", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_SRC, PIXMAN_a8, 0, PIXMAN_r5g6b5 }, + { "src_n_8_1555", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_SRC, PIXMAN_a8, 0, PIXMAN_a1r5g5b5 }, + { "src_n_8_4444", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_SRC, PIXMAN_a8, 0, PIXMAN_a4r4g4b4 }, + { "src_n_8_2222", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_SRC, PIXMAN_a8, 0, PIXMAN_a2r2g2b2 }, + { "src_n_8_x888", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_SRC, PIXMAN_a8, 0, PIXMAN_x8r8g8b8 }, + { "src_n_8_8888", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_SRC, PIXMAN_a8, 0, PIXMAN_a8r8g8b8 }, + { "src_n_8_2x10", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_SRC, PIXMAN_a8, 0, PIXMAN_x2r10g10b10 }, + { "src_n_8_2a10", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_SRC, PIXMAN_a8, 0, PIXMAN_a2r10g10b10 }, + { "src_8888_8_0565", PIXMAN_a8r8g8b8, 0, PIXMAN_OP_SRC, PIXMAN_a8, 0, PIXMAN_r5g6b5 }, + { "src_0888_8_0565", PIXMAN_r8g8b8, 0, PIXMAN_OP_SRC, PIXMAN_a8, 0, PIXMAN_r5g6b5 }, + { "src_0888_8_8888", PIXMAN_r8g8b8, 0, PIXMAN_OP_SRC, PIXMAN_a8, 0, PIXMAN_a8r8g8b8 }, + { "src_0888_8_x888", PIXMAN_r8g8b8, 0, PIXMAN_OP_SRC, PIXMAN_a8, 0, PIXMAN_x8r8g8b8 }, + { "src_x888_8_x888", PIXMAN_x8r8g8b8, 0, PIXMAN_OP_SRC, PIXMAN_a8, 0, PIXMAN_x8r8g8b8 }, + { "src_x888_8_8888", PIXMAN_x8r8g8b8, 0, PIXMAN_OP_SRC, PIXMAN_a8, 0, PIXMAN_a8r8g8b8 }, + { "src_0565_8_0565", PIXMAN_r5g6b5, 0, PIXMAN_OP_SRC, PIXMAN_a8, 0, PIXMAN_r5g6b5 }, + { "src_1555_8_0565", PIXMAN_a1r5g5b5, 0, PIXMAN_OP_SRC, PIXMAN_a8, 0, PIXMAN_r5g6b5 }, + { "src_0565_8_1555", PIXMAN_r5g6b5, 0, PIXMAN_OP_SRC, PIXMAN_a8, 0, PIXMAN_a1r5g5b5 }, + { "over_n_x888", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_null, 0, PIXMAN_x8r8g8b8 }, + { "over_n_8888", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_null, 0, PIXMAN_a8r8g8b8 }, + { "over_n_0565", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_null, 0, PIXMAN_r5g6b5 }, + { "over_n_1555", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_null, 0, PIXMAN_a1r5g5b5 }, + { "over_8888_0565", PIXMAN_a8r8g8b8, 0, PIXMAN_OP_OVER, PIXMAN_null, 0, PIXMAN_r5g6b5 }, + { "over_8888_x888", PIXMAN_a8r8g8b8, 0, PIXMAN_OP_OVER, PIXMAN_null, 0, PIXMAN_x8r8g8b8 }, + { "over_n_8_0565", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_a8, 0, PIXMAN_r5g6b5 }, + { "over_n_8_1555", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_a8, 0, PIXMAN_a1r5g5b5 }, + { "over_n_8_4444", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_a8, 0, PIXMAN_a4r4g4b4 }, + { "over_n_8_2222", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_a8, 0, PIXMAN_a2r2g2b2 }, + { "over_n_8_x888", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_a8, 0, PIXMAN_x8r8g8b8 }, + { "over_n_8_8888", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_a8, 0, PIXMAN_a8r8g8b8 }, + { "over_n_8_2x10", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_a8, 0, PIXMAN_x2r10g10b10 }, + { "over_n_8_2a10", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_a8, 0, PIXMAN_a2r10g10b10 }, + { "over_n_8888_8888_ca", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, 2, PIXMAN_a8r8g8b8 }, + { "over_n_8888_x888_ca", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, 2, PIXMAN_x8r8g8b8 }, + { "over_n_8888_0565_ca", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, 2, PIXMAN_r5g6b5 }, + { "over_n_8888_1555_ca", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, 2, PIXMAN_a1r5g5b5 }, + { "over_n_8888_4444_ca", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, 2, PIXMAN_a4r4g4b4 }, + { "over_n_8888_2222_ca", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, 2, PIXMAN_a2r2g2b2 }, + { "over_n_8888_2x10_ca", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, 2, PIXMAN_x2r10g10b10 }, + { "over_n_8888_2a10_ca", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, 2, PIXMAN_a2r10g10b10 }, + { "over_8888_n_8888", PIXMAN_a8r8g8b8, 0, PIXMAN_OP_OVER, PIXMAN_a8, 1, PIXMAN_a8r8g8b8 }, + { "over_8888_n_x888", PIXMAN_a8r8g8b8, 0, PIXMAN_OP_OVER, PIXMAN_a8, 1, PIXMAN_x8r8g8b8 }, + { "over_8888_n_0565", PIXMAN_a8r8g8b8, 0, PIXMAN_OP_OVER, PIXMAN_a8, 1, PIXMAN_r5g6b5 }, + { "over_8888_n_1555", PIXMAN_a8r8g8b8, 0, PIXMAN_OP_OVER, PIXMAN_a8, 1, PIXMAN_a1r5g5b5 }, + { "outrev_n_8_0565", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OUT_REV, PIXMAN_a8, 0, PIXMAN_r5g6b5 }, + { "outrev_n_8_1555", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OUT_REV, PIXMAN_a8, 0, PIXMAN_a1r5g5b5 }, + { "outrev_n_8_x888", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OUT_REV, PIXMAN_a8, 0, PIXMAN_x8r8g8b8 }, + { "outrev_n_8_8888", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OUT_REV, PIXMAN_a8, 0, PIXMAN_a8r8g8b8 }, + { "outrev_n_8888_0565_ca", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OUT_REV, PIXMAN_a8r8g8b8, 2, PIXMAN_r5g6b5 }, + { "outrev_n_8888_1555_ca", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OUT_REV, PIXMAN_a8r8g8b8, 2, PIXMAN_a1r5g5b5 }, + { "outrev_n_8888_x888_ca", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OUT_REV, PIXMAN_a8r8g8b8, 2, PIXMAN_x8r8g8b8 }, + { "outrev_n_8888_8888_ca", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_OUT_REV, PIXMAN_a8r8g8b8, 2, PIXMAN_a8r8g8b8 }, +}; + +int +main (int argc, char *argv[]) +{ + double x; + int i; + char *pattern = argc > 1 ? argv[1] : "all"; + + src = aligned_malloc (4096, BUFSIZE * 3); + memset (src, 0xCC, BUFSIZE * 3); + dst = src + (BUFSIZE / 4); + mask = dst + (BUFSIZE / 4); + + printf ("Benchmark for a set of most commonly used functions\n"); + printf ("---\n"); + printf ("All results are presented in millions of pixels per second\n"); + printf ("L1 - small Xx1 rectangle (fitting L1 cache), always blitted at the same\n"); + printf (" memory location with small drift in horizontal direction\n"); + printf ("L2 - small XxY rectangle (fitting L2 cache), always blitted at the same\n"); + printf (" memory location with small drift in horizontal direction\n"); + printf ("M - large %dx%d rectangle, always blitted at the same\n", + WIDTH - 64, HEIGHT); + printf (" memory location with small drift in horizontal direction\n"); + printf ("HT - random rectangles with %dx%d average size are copied from\n", + TILEWIDTH, TILEWIDTH); + printf (" one %dx%d buffer to another, traversing from left to right\n", + WIDTH, HEIGHT); + printf (" and from top to bottom\n"); + printf ("VT - random rectangles with %dx%d average size are copied from\n", + TILEWIDTH, TILEWIDTH); + printf (" one %dx%d buffer to another, traversing from top to bottom\n", + WIDTH, HEIGHT); + printf (" and from left to right\n"); + printf ("R - random rectangles with %dx%d average size are copied from\n", + TILEWIDTH, TILEWIDTH); + printf (" random locations of one %dx%d buffer to another\n", + WIDTH, HEIGHT); + printf ("RT - as R, but %dx%d average sized rectangles are copied\n", + TINYWIDTH, TINYWIDTH); + printf ("---\n"); + bandwidth = x = bench_memcpy (); + printf ("reference memcpy speed = %.1fMB/s (%.1fMP/s for 32bpp fills)\n", + x / 1000000., x / 4000000); + printf ("---\n"); + + for (i = 0; i < sizeof(tests_tbl) / sizeof(tests_tbl[0]); i++) + { + if (strcmp (pattern, "all") == 0 || strstr (tests_tbl[i].testname, pattern)) + { + bench_composite (tests_tbl[i].testname, + tests_tbl[i].src_fmt, + tests_tbl[i].src_flags, + tests_tbl[i].op, + tests_tbl[i].mask_fmt, + tests_tbl[i].mask_flags, + tests_tbl[i].dst_fmt, + bandwidth/8); + } + } + + free (src); + return 0; +} diff --git a/pixman/test/utils.c b/pixman/test/utils.c index f5199268b..22ab02fae 100644 --- a/pixman/test/utils.c +++ b/pixman/test/utils.c @@ -1,10 +1,20 @@ #include "utils.h" #include +#ifdef HAVE_GETTIMEOFDAY +#include +#else +#include +#endif + #ifdef HAVE_UNISTD_H #include #endif +#ifdef HAVE_SYS_MMAN_H +#include +#endif + /* Random number seed */ @@ -197,10 +207,117 @@ image_endian_swap (pixman_image_t *img, int bpp) } } +#define N_LEADING_PROTECTED 10 +#define N_TRAILING_PROTECTED 10 + +typedef struct +{ + void *addr; + uint32_t len; + uint8_t *trailing; + int n_bytes; +} info_t; + +#if defined(HAVE_MPROTECT) && defined(HAVE_GETPAGESIZE) + +/* This is apparently necessary on at least OS X */ +#ifndef MAP_ANONYMOUS +#define MAP_ANONYMOUS MAP_ANON +#endif + +void * +fence_malloc (uint32_t len) +{ + unsigned long page_size = getpagesize(); + unsigned long page_mask = page_size - 1; + uint32_t n_payload_bytes = (len + page_mask) & ~page_mask; + uint32_t n_bytes = + (page_size * (N_LEADING_PROTECTED + N_TRAILING_PROTECTED + 2) + + n_payload_bytes) & ~page_mask; + uint8_t *initial_page; + uint8_t *leading_protected; + uint8_t *trailing_protected; + uint8_t *payload; + uint8_t *addr; + + addr = mmap (NULL, n_bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, + -1, 0); + + if (addr == (void *)MAP_FAILED) + { + printf ("mmap failed on %u %u\n", len, n_bytes); + return NULL; + } + + initial_page = (uint8_t *)(((unsigned long)addr + page_mask) & ~page_mask); + leading_protected = initial_page + page_size; + payload = leading_protected + N_LEADING_PROTECTED * page_size; + trailing_protected = payload + n_payload_bytes; + + ((info_t *)initial_page)->addr = addr; + ((info_t *)initial_page)->len = len; + ((info_t *)initial_page)->trailing = trailing_protected; + ((info_t *)initial_page)->n_bytes = n_bytes; + + if (mprotect (leading_protected, N_LEADING_PROTECTED * page_size, + PROT_NONE) == -1) + { + free (addr); + return NULL; + } + + if (mprotect (trailing_protected, N_TRAILING_PROTECTED * page_size, + PROT_NONE) == -1) + { + mprotect (leading_protected, N_LEADING_PROTECTED * page_size, + PROT_READ | PROT_WRITE); + + free (addr); + return NULL; + } + + return payload; +} + +void +fence_free (void *data) +{ + uint32_t page_size = getpagesize(); + uint8_t *payload = data; + uint8_t *leading_protected = payload - N_LEADING_PROTECTED * page_size; + uint8_t *initial_page = leading_protected - page_size; + info_t *info = (info_t *)initial_page; + uint8_t *trailing_protected = info->trailing; + + mprotect (leading_protected, N_LEADING_PROTECTED * page_size, + PROT_READ | PROT_WRITE); + + mprotect (trailing_protected, N_LEADING_PROTECTED * page_size, + PROT_READ | PROT_WRITE); + + munmap (info->addr, info->n_bytes); +} + +#else + +void * +fence_malloc (uint32_t len) +{ + return malloc (len); +} + +void +fence_free (void *data) +{ + free (data); +} + +#endif + uint8_t * make_random_bytes (int n_bytes) { - uint8_t *bytes = malloc (n_bytes); + uint8_t *bytes = fence_malloc (n_bytes); int i; if (!bytes) @@ -325,6 +442,20 @@ fuzzer_test_main (const char *test_name, return 0; } +/* Try to obtain current time in seconds */ +double +gettime (void) +{ +#ifdef HAVE_GETTIMEOFDAY + struct timeval tv; + + gettimeofday (&tv, NULL); + return (double)((int64_t)tv.tv_sec * 1000000 + tv.tv_usec) / 1000000.; +#else + return (double)clock() / (double)CLOCKS_PER_SEC; +#endif +} + static const char *global_msg; static void @@ -352,3 +483,18 @@ fail_after (int seconds, const char *msg) #endif #endif } + +void * +aligned_malloc (size_t align, size_t size) +{ + void *result; + +#ifdef HAVE_POSIX_MEMALIGN + if (posix_memalign (&result, align, size) != 0) + result = NULL; +#else + result = malloc (size); +#endif + + return result; +} diff --git a/pixman/test/utils.h b/pixman/test/utils.h index ab71452a4..e6122119a 100644 --- a/pixman/test/utils.h +++ b/pixman/test/utils.h @@ -51,10 +51,23 @@ compute_crc32 (uint32_t in_crc32, void image_endian_swap (pixman_image_t *img, int bpp); -/* Generate n_bytes random bytes in malloced memory */ +/* Allocate memory that is bounded by protected pages, + * so that out-of-bounds access will cause segfaults + */ +void * +fence_malloc (uint32_t len); + +void +fence_free (void *data); + +/* Generate n_bytes random bytes in fence_malloced memory */ uint8_t * make_random_bytes (int n_bytes); +/* Return current time in seconds */ +double +gettime (void); + /* main body of the fuzzer test */ int fuzzer_test_main (const char *test_name, @@ -101,3 +114,7 @@ fail_after (int seconds, const char *msg); assert (frcd_canary_variable6 == frcd_volatile_constant6); \ assert (frcd_canary_variable7 == frcd_volatile_constant7); \ assert (frcd_canary_variable8 == frcd_volatile_constant8); + +/* Try to get an aligned memory chunk */ +void * +aligned_malloc (size_t align, size_t size); -- cgit v1.2.3