[Pixman] [PATCH 2/4] test: Check the dithering path in tolerance-test
basile-pixman at clement.pm
basile-pixman at clement.pm
Tue Apr 9 21:29:25 UTC 2019
From: Basile Clement <basile-pixman at 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
More information about the Pixman
mailing list