From: Basile Clement <basile-pix...@clement.pm> This adds support for testing dithered destinations in tolerance-test. When dithering is enabled, the pixel checker allows for an additional quantization error. --- test/tolerance-test.c | 22 +++++++- test/utils.c | 121 ++++++++++++++++++++++++++++++++++++++---- test/utils.h | 12 +++++ 3 files changed, 142 insertions(+), 13 deletions(-)
diff --git a/test/tolerance-test.c b/test/tolerance-test.c index 320bb7f..011cdb4 100644 --- a/test/tolerance-test.c +++ b/test/tolerance-test.c @@ -76,6 +76,11 @@ static const pixman_op_t operators[] = PIXMAN_OP_EXCLUSION, }; +static const pixman_dither_t dithers[] = +{ + PIXMAN_DITHER_ORDERED_BAYER_8, +}; + #define RANDOM_ELT(array) \ (array[prng_rand_n (ARRAY_LENGTH (array))]) @@ -176,7 +181,8 @@ verify (int test_no, pixman_image_t *orig_dest, int x, int y, int width, int height, - pixman_bool_t component_alpha) + pixman_bool_t component_alpha, + pixman_dither_t dither) { pixel_checker_t dest_checker, src_checker, mask_checker; int i, j; @@ -185,6 +191,9 @@ verify (int test_no, pixel_checker_init (&dest_checker, dest->bits.format); pixel_checker_init (&mask_checker, mask->bits.format); + if (dest->bits.dither != PIXMAN_DITHER_NONE) + pixel_checker_allow_dither (&dest_checker); + assert (dest->bits.format == orig_dest->bits.format); for (j = y; j < y + height; ++j) @@ -220,6 +229,7 @@ verify (int test_no, printf (" operator: %s (%s alpha)\n", operator_name (op), component_alpha? "component" : "unified"); + printf (" dither: %s\n", dither_name (dither)); printf (" dest_x, dest_y: %d %d\n", x, y); printf (" width, height: %d %d\n", width, height); printf (" source: format: %-14s size: %2d x %2d\n", @@ -275,6 +285,7 @@ do_check (int i) pixman_image_t *dest_copy; pixman_bool_t result = TRUE; pixman_bool_t component_alpha; + pixman_dither_t dither = PIXMAN_DITHER_NONE; prng_srand (i); op = RANDOM_ELT (operators); @@ -296,6 +307,12 @@ do_check (int i) if (y + height > dest->bits.height) height = dest->bits.height - y; + if (prng_rand_n (2)) + { + dither = RANDOM_ELT (dithers); + pixman_image_set_dither (dest, dither); + } + component_alpha = prng_rand_n (2); pixman_image_set_component_alpha (mask, component_alpha); @@ -305,7 +322,8 @@ do_check (int i) x, y, width, height); if (!verify (i, op, source, mask, dest, dest_copy, - x, y, width, height, component_alpha)) + x, y, width, height, component_alpha, + dither)) { result = FALSE; } diff --git a/test/utils.c b/test/utils.c index 4eeb068..9ce7a6c 100644 --- a/test/utils.c +++ b/test/utils.c @@ -1174,6 +1174,31 @@ static const operator_entry_t op_list[] = #undef ALIAS }; +typedef struct { + pixman_dither_t dither; + const char *name; + pixman_bool_t is_alias; +} dither_entry_t; + +static const dither_entry_t dither_list[] = +{ +#define ENTRY(dither) \ + { PIXMAN_DITHER_##dither, "PIXMAN_DITHER_" #dither, FALSE } +#define ALIAS(dither, nam) \ + { PIXMAN_DITHER_##dither, nam, TRUE } + + /* dither_name () will return the first hit in this table, + * so keep the list properly ordered between entries and aliases. + * Aliases are not listed by list_dithers (). + */ + + ENTRY (ORDERED_BAYER_8), + ENTRY (NONE), + +#undef ENTRY +#undef ALIAS +}; + struct format_entry { pixman_format_code_t format; @@ -1382,6 +1407,28 @@ list_operators (void) printf ("\n\n"); } +void +list_dithers (void) +{ + int n_chars; + int i; + + printf ("Dithers:\n "); + + n_chars = 0; + for (i = 0; i < ARRAY_LENGTH (dither_list); ++i) + { + const dither_entry_t *ent = &dither_list[i]; + + if (ent->is_alias) + continue; + + emit (ent->name, &n_chars); + } + + printf ("\n\n"); +} + pixman_op_t operator_from_string (const char *s) { @@ -1406,6 +1453,22 @@ operator_from_string (const char *s) return PIXMAN_OP_NONE; } +pixman_dither_t +dither_from_string (const char *s) +{ + int i; + + for (i = 0; i < ARRAY_LENGTH (dither_list); ++i) + { + const dither_entry_t *ent = &dither_list[i]; + + if (strcasecmp (ent->name, s) == 0) + return ent->dither; + } + + return PIXMAN_DITHER_NONE; +} + const char * operator_name (pixman_op_t op) { @@ -1438,6 +1501,22 @@ format_name (pixman_format_code_t format) return "<unknown format>"; }; +const char * +dither_name (pixman_dither_t dither) +{ + int i; + + for (i = 0; i < ARRAY_LENGTH (dither_list); ++i) + { + const dither_entry_t *ent = &dither_list[i]; + + if (ent->dither == dither) + return ent->name; + } + + return "<unknown dither>"; +} + #define IS_ZERO(f) (-DBL_MIN < (f) && (f) < DBL_MIN) typedef double (* blend_func_t) (double as, double s, double ad, double d); @@ -1924,6 +2003,10 @@ round_color (pixman_format_code_t format, color_t *color) color->a = round_channel (color->a, PIXMAN_FORMAT_A (format)); } +/* The acceptable deviation in units of [0.0, 1.0] + */ +#define DEVIATION (0.0128) + /* Check whether @pixel is a valid quantization of the a, r, g, b * parameters. Some slack is permitted. */ @@ -1992,6 +2075,22 @@ pixel_checker_init (pixel_checker_t *checker, pixman_format_code_t format) checker->rw = PIXMAN_FORMAT_R (format); checker->gw = PIXMAN_FORMAT_G (format); checker->bw = PIXMAN_FORMAT_B (format); + + checker->ad = DEVIATION; + checker->rd = DEVIATION; + checker->gd = DEVIATION; + checker->bd = DEVIATION; +} + +/* When dithering is enabled, we allow one extra pixel of tolerance + */ +void +pixel_checker_allow_dither (pixel_checker_t *checker) +{ + checker->ad += 1 / (double)((1 << checker->aw) - 1); + checker->rd += 1 / (double)((1 << checker->rw) - 1); + checker->gd += 1 / (double)((1 << checker->gw) - 1); + checker->bd += 1 / (double)((1 << checker->bw) - 1); } static void @@ -2085,7 +2184,7 @@ convert (double v, uint32_t width, uint32_t mask, uint32_t shift, double def) } static void -get_limits (const pixel_checker_t *checker, double limit, +get_limits (const pixel_checker_t *checker, double sign, color_t *color, int *ao, int *ro, int *go, int *bo) { @@ -2101,23 +2200,23 @@ get_limits (const pixel_checker_t *checker, double limit, color = &tmp; } - *ao = convert (color->a + limit, checker->aw, checker->am, checker->as, 1.0); - *ro = convert (color->r + limit, checker->rw, checker->rm, checker->rs, 0.0); - *go = convert (color->g + limit, checker->gw, checker->gm, checker->gs, 0.0); - *bo = convert (color->b + limit, checker->bw, checker->bm, checker->bs, 0.0); + *ao = convert (color->a + sign * checker->ad, + checker->aw, checker->am, checker->as, 1.0); + *ro = convert (color->r + sign * checker->rd, + checker->rw, checker->rm, checker->rs, 0.0); + *go = convert (color->g + sign * checker->gd, + checker->gw, checker->gm, checker->gs, 0.0); + *bo = convert (color->b + sign * checker->bd, + checker->bw, checker->bm, checker->bs, 0.0); } -/* The acceptable deviation in units of [0.0, 1.0] - */ -#define DEVIATION (0.0128) - void pixel_checker_get_max (const pixel_checker_t *checker, color_t *color, int *am, int *rm, int *gm, int *bm) { pixel_checker_require_uint32_format(checker); - get_limits (checker, DEVIATION, color, am, rm, gm, bm); + get_limits (checker, 1, color, am, rm, gm, bm); } void @@ -2126,7 +2225,7 @@ pixel_checker_get_min (const pixel_checker_t *checker, color_t *color, { pixel_checker_require_uint32_format(checker); - get_limits (checker, - DEVIATION, color, am, rm, gm, bm); + get_limits (checker, - 1, color, am, rm, gm, bm); } pixman_bool_t diff --git a/test/utils.h b/test/utils.h index e5ac945..701417f 100644 --- a/test/utils.h +++ b/test/utils.h @@ -219,15 +219,23 @@ list_formats (void); void list_operators (void); +void list_dithers (void); + pixman_op_t operator_from_string (const char *s); +pixman_dither_t +dither_from_string (const char *s); + const char * operator_name (pixman_op_t op); const char * format_name (pixman_format_code_t format); +const char * +dither_name (pixman_dither_t dither); + typedef struct { double r, g, b, a; @@ -250,11 +258,15 @@ typedef struct uint32_t am, rm, gm, bm; uint32_t as, rs, gs, bs; uint32_t aw, rw, gw, bw; + float ad, rd, gd, bd; } pixel_checker_t; void pixel_checker_init (pixel_checker_t *checker, pixman_format_code_t format); +void +pixel_checker_allow_dither (pixel_checker_t *checker); + void pixel_checker_split_pixel (const pixel_checker_t *checker, uint32_t pixel, int *a, int *r, int *g, int *b); -- 2.21.0 _______________________________________________ Pixman mailing list Pixman@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/pixman