diff options
Diffstat (limited to 'pixman/test/lowlevel-blt-bench.c')
-rw-r--r-- | pixman/test/lowlevel-blt-bench.c | 299 |
1 files changed, 276 insertions, 23 deletions
diff --git a/pixman/test/lowlevel-blt-bench.c b/pixman/test/lowlevel-blt-bench.c index 3da094a2b..aff460874 100644 --- a/pixman/test/lowlevel-blt-bench.c +++ b/pixman/test/lowlevel-blt-bench.c @@ -367,14 +367,14 @@ bench_RT (pixman_op_t op, } void -bench_composite (char * testname, - int src_fmt, - int src_flags, - int op, - int mask_fmt, - int mask_flags, - int dst_fmt, - double npix) +bench_composite (const 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; @@ -587,7 +587,7 @@ bench_composite (char * testname, #define PIXMAN_OP_OUT_REV (PIXMAN_OP_OUT_REVERSE) -struct +struct test_entry { char *testname; int src_fmt; @@ -596,8 +596,11 @@ struct int mask_fmt; int mask_flags; int dst_fmt; -} -tests_tbl[] = +}; + +typedef struct test_entry test_entry_t; + +static const test_entry_t tests_tbl[] = { { "add_8_8_8", PIXMAN_a8, 0, PIXMAN_OP_ADD, PIXMAN_a8, 0, PIXMAN_a8 }, { "add_n_8_8", PIXMAN_a8r8g8b8, 1, PIXMAN_OP_ADD, PIXMAN_a8, 0, PIXMAN_a8 }, @@ -719,6 +722,260 @@ tests_tbl[] = { "rpixbuf", PIXMAN_x8b8g8r8, 0, PIXMAN_OP_SRC, PIXMAN_a8b8g8r8, 0, PIXMAN_a8b8g8r8 }, }; +static const test_entry_t special_patterns[] = +{ + { "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 }, + { "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_0888_8888_rev", PIXMAN_b8g8r8, 0, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_x8r8g8b8 }, + { "src_0888_0565_rev", PIXMAN_b8g8r8, 0, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_r5g6b5 }, + { "src_n_8", PIXMAN_a8, 1, PIXMAN_OP_SRC, PIXMAN_null, 0, PIXMAN_a8 }, + { "pixbuf", PIXMAN_x8b8g8r8, 0, PIXMAN_OP_SRC, PIXMAN_a8b8g8r8, 0, PIXMAN_a8r8g8b8 }, + { "rpixbuf", PIXMAN_x8b8g8r8, 0, PIXMAN_OP_SRC, PIXMAN_a8b8g8r8, 0, PIXMAN_a8b8g8r8 }, +}; + +/* Returns the sub-string's end pointer in string. */ +static const char * +copy_sub_string (char *buf, + const char *string, + const char *scan_from, + const char *end) +{ + const char *delim; + size_t n; + + delim = strchr (scan_from, '_'); + if (!delim) + delim = end; + + n = delim - string; + strncpy(buf, string, n); + buf[n] = '\0'; + + return delim; +} + +static pixman_op_t +parse_longest_operator (char *buf, const char **strp, const char *end) +{ + const char *p = *strp; + const char *sub_end; + const char *best_end = p; + pixman_op_t best_op = PIXMAN_OP_NONE; + pixman_op_t op; + + while (p < end) + { + sub_end = copy_sub_string (buf, *strp, p, end); + op = operator_from_string (buf); + p = sub_end + 1; + + if (op != PIXMAN_OP_NONE) + { + best_end = p; + best_op = op; + } + } + + *strp = best_end; + return best_op; +} + +static pixman_format_code_t +parse_format (char *buf, const char **p, const char *end) +{ + pixman_format_code_t format; + const char *delim; + + if (*p >= end) + return PIXMAN_null; + + delim = copy_sub_string (buf, *p, *p, end); + format = format_from_string (buf); + + if (format != PIXMAN_null) + *p = delim + 1; + + return format; +} + +static int +parse_test_pattern (test_entry_t *test, const char *pattern) +{ + const char *p = pattern; + const char *end = pattern + strlen (pattern); + char buf[1024]; + pixman_format_code_t format[3]; + int i; + + if (strlen (pattern) > sizeof (buf) - 1) + return -1; + + /* Special cases that the parser cannot produce. */ + for (i = 0; i < ARRAY_LENGTH (special_patterns); i++) + { + if (strcmp (pattern, special_patterns[i].testname) == 0) + { + *test = special_patterns[i]; + return 0; + } + } + + /* Extract operator, may contain delimiters, + * so take the longest string that matches. + */ + test->op = parse_longest_operator (buf, &p, end); + if (test->op == PIXMAN_OP_NONE) + return -1; + + /* extract up to three pixel formats */ + format[0] = parse_format (buf, &p, end); + format[1] = parse_format (buf, &p, end); + format[2] = parse_format (buf, &p, end); + + if (format[0] == PIXMAN_null || format[1] == PIXMAN_null) + return -1; + + /* recognize CA flag */ + test->mask_flags = 0; + if (p < end) + { + if (strcmp (p, "ca") == 0) + test->mask_flags |= CA_FLAG; + else + return -1; /* trailing garbage */ + } + + test->src_fmt = format[0]; + if (format[2] == PIXMAN_null) + { + test->mask_fmt = PIXMAN_null; + test->dst_fmt = format[1]; + } + else + { + test->mask_fmt = format[1]; + test->dst_fmt = format[2]; + } + + test->src_flags = 0; + if (test->src_fmt == PIXMAN_solid) + { + test->src_fmt = PIXMAN_a8r8g8b8; + test->src_flags |= SOLID_FLAG; + } + + if (test->mask_fmt == PIXMAN_solid) + { + if (test->mask_flags & CA_FLAG) + test->mask_fmt = PIXMAN_a8r8g8b8; + else + test->mask_fmt = PIXMAN_a8; + + test->mask_flags |= SOLID_FLAG; + } + + return 0; +} + +static int +check_int (int got, int expected, const char *name, const char *field) +{ + if (got == expected) + return 0; + + printf ("%s: %s failure: expected %d, got %d.\n", + name, field, expected, got); + + return 1; +} + +static int +check_format (int got, int expected, const char *name, const char *field) +{ + if (got == expected) + return 0; + + printf ("%s: %s failure: expected %s (%#x), got %s (%#x).\n", + name, field, + format_name (expected), expected, + format_name (got), got); + + return 1; +} + +static void +parser_self_test (void) +{ + const test_entry_t *ent; + test_entry_t test; + int fails = 0; + int i; + + for (i = 0; i < ARRAY_LENGTH (tests_tbl); i++) + { + ent = &tests_tbl[i]; + + if (parse_test_pattern (&test, ent->testname) < 0) + { + printf ("parsing failed for '%s'\n", ent->testname); + fails++; + continue; + } + + fails += check_format (test.src_fmt, ent->src_fmt, + ent->testname, "src_fmt"); + fails += check_format (test.mask_fmt, ent->mask_fmt, + ent->testname, "mask_fmt"); + fails += check_format (test.dst_fmt, ent->dst_fmt, + ent->testname, "dst_fmt"); + fails += check_int (test.src_flags, ent->src_flags, + ent->testname, "src_flags"); + fails += check_int (test.mask_flags, ent->mask_flags, + ent->testname, "mask_flags"); + fails += check_int (test.op, ent->op, ent->testname, "op"); + } + + if (fails) + { + printf ("Parser self-test failed.\n"); + exit (EXIT_FAILURE); + } + + printf ("Parser self-test complete.\n"); +} + +static void +run_one_test (const char *pattern, double bandwidth_) +{ + test_entry_t test; + + if (parse_test_pattern (&test, pattern) < 0) + { + printf ("Error: Could not parse the test pattern '%s'.\n", pattern); + return; + } + + bench_composite (pattern, + test.src_fmt, + test.src_flags, + test.op, + test.mask_fmt, + test.mask_flags, + test.dst_fmt, + bandwidth_ / 8); +} + +static void +run_default_tests (double bandwidth_) +{ + int i; + + for (i = 0; i < ARRAY_LENGTH (tests_tbl); i++) + run_one_test (tests_tbl[i].testname, bandwidth_); +} + int main (int argc, char *argv[]) { @@ -754,6 +1011,8 @@ main (int argc, char *argv[]) return 1; } + parser_self_test (); + src = aligned_malloc (4096, BUFSIZE * 3); memset (src, 0xCC, BUFSIZE * 3); dst = src + (BUFSIZE / 4); @@ -801,19 +1060,13 @@ main (int argc, char *argv[]) } printf ("---\n"); - for (i = 0; i < ARRAY_LENGTH (tests_tbl); i++) + if (strcmp (pattern, "all") == 0) { - if (strcmp (pattern, "all") == 0 || strcmp (tests_tbl[i].testname, pattern) == 0) - { - 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); - } + run_default_tests (bandwidth); + } + else + { + run_one_test (pattern, bandwidth); } free (src); |