Commit 007ab1e5 authored by Pekka Paalanen's avatar Pekka Paalanen Committed by Pekka Paalanen

tests: add range argument for fuzzy image matching

The fuzzy range will be used with GL-renderer testing, as it may produce
slightly different images than Pixman-renderer yet still correct results.

Such allowed differences are due to different rounding.
Signed-off-by: default avatarPekka Paalanen <pekka.paalanen@collabora.com>
parent 8fc4b59b
......@@ -141,7 +141,7 @@ TEST(internal_screenshot)
/* Test check_images_match() without a clip.
* We expect this to fail since we use a bad reference image
*/
match = check_images_match(screenshot->image, reference_bad, NULL);
match = check_images_match(screenshot->image, reference_bad, NULL, NULL);
testlog("Screenshot %s reference image\n", match? "equal to" : "different from");
assert(!match);
pixman_image_unref(reference_bad);
......@@ -155,10 +155,10 @@ TEST(internal_screenshot)
clip.width = 100;
clip.height = 100;
testlog("Clip: %d,%d %d x %d\n", clip.x, clip.y, clip.width, clip.height);
match = check_images_match(screenshot->image, reference_good, &clip);
match = check_images_match(screenshot->image, reference_good, &clip, NULL);
testlog("Screenshot %s reference image in clipped area\n", match? "matches" : "doesn't match");
if (!match) {
diffimg = visualize_image_difference(screenshot->image, reference_good, &clip);
diffimg = visualize_image_difference(screenshot->image, reference_good, &clip, NULL);
fname = screenshot_output_filename("internal-screenshot-error", 0);
write_image_as_png(diffimg, fname);
pixman_image_unref(diffimg);
......
......@@ -135,7 +135,7 @@ write_visual_diff(pixman_image_t *ref_image,
assert(ret >= 0);
fname = screenshot_output_filename(ext_test_name, seq_no);
diff = visualize_image_difference(shot->image, ref_image, clip);
diff = visualize_image_difference(shot->image, ref_image, clip, NULL);
write_image_as_png(diff, fname);
pixman_image_unref(diff);
......@@ -166,7 +166,7 @@ check_screen(struct client *client,
shot = capture_screenshot_of_output(client);
assert(shot);
match = check_images_match(shot->image, ref, clip);
match = check_images_match(shot->image, ref, clip, NULL);
testlog("ref %s vs. shot %s: %s\n", ref_fname, shot_fname,
match ? "PASS" : "FAIL");
......
......@@ -1077,6 +1077,24 @@ format_pixman2cairo(pixman_format_code_t fmt)
assert(0 && "unknown Pixman pixel format");
}
/**
* Validate range
*
* \param r Range to validate or NULL.
* \return The given range, or {0, 0} for NULL.
*
* Will abort if range is invalid, that is a > b.
*/
static struct range
range_get(const struct range *r)
{
if (!r)
return (struct range){ 0, 0 };
assert(r->a <= r->b);
return *r;
}
/**
* Compute the ROI for image comparisons
*
......@@ -1157,8 +1175,25 @@ image_iter_get_row(struct image_iterator *it, int y)
return (uint32_t *)(it->data + y * it->stride);
}
static bool
fuzzy_match_pixels(uint32_t pix_a, uint32_t pix_b, const struct range *fuzz)
{
int shift;
for (shift = 0; shift < 32; shift += 8) {
int val_a = (pix_a >> shift) & 0xffu;
int val_b = (pix_b >> shift) & 0xffu;
int d = val_b - val_a;
if (d < fuzz->a || d > fuzz->b)
return false;
}
return true;
}
/**
* Test if a given region within two images are pixel-identical.
* Test if a given region within two images are pixel-identical
*
* Returns true if the two images pixel-wise identical, and false otherwise.
*
......@@ -1166,15 +1201,23 @@ image_iter_get_row(struct image_iterator *it, int y)
* \param img_b Second image.
* \param clip_rect The region of interest, or NULL for comparing the whole
* images.
* \param prec Per-channel allowed difference, or NULL for identical match
* required.
*
* This function hard-fails if clip_rect is not inside both images. If clip_rect
* is given, the images do not have to match in size, otherwise size mismatch
* will be a hard failure.
*
* The per-pixel, per-channel difference is computed as img_b - img_a which is
* required to be in the range [prec->a, prec->b] inclusive. The difference is
* signed. All four channels are compared the same way, without any special
* meaning on alpha channel.
*/
bool
check_images_match(pixman_image_t *img_a, pixman_image_t *img_b,
const struct rectangle *clip_rect)
const struct rectangle *clip_rect, const struct range *prec)
{
struct range fuzz = range_get(prec);
struct image_iterator it_a;
struct image_iterator it_b;
pixman_box32_t box;
......@@ -1192,7 +1235,7 @@ check_images_match(pixman_image_t *img_a, pixman_image_t *img_b,
pix_b = image_iter_get_row(&it_b, y) + box.x1;
for (x = box.x1; x < box.x2; x++) {
if (*pix_a != *pix_b)
if (!fuzzy_match_pixels(*pix_a, *pix_b, &fuzz))
return false;
pix_a++;
......@@ -1232,6 +1275,8 @@ tint(uint32_t src, uint32_t add)
* \param img_b Second image.
* \param clip_rect The region of interest, or NULL for comparing the whole
* images.
* \param prec Per-channel allowed difference, or NULL for identical match
* required.
* \return A new image with the differences highlighted.
*
* Regions outside of the region of interest are shaded with black, matching
......@@ -1241,11 +1286,18 @@ tint(uint32_t src, uint32_t add)
* This function hard-fails if clip_rect is not inside both images. If clip_rect
* is given, the images do not have to match in size, otherwise size mismatch
* will be a hard failure.
*
* The per-pixel, per-channel difference is computed as img_b - img_a which is
* required to be in the range [prec->a, prec->b] inclusive. The difference is
* signed. All four channels are compared the same way, without any special
* meaning on alpha channel.
*/
pixman_image_t *
visualize_image_difference(pixman_image_t *img_a, pixman_image_t *img_b,
const struct rectangle *clip_rect)
const struct rectangle *clip_rect,
const struct range *prec)
{
struct range fuzz = range_get(prec);
pixman_image_t *diffimg;
pixman_image_t *shade;
struct image_iterator it_a;
......@@ -1288,7 +1340,7 @@ visualize_image_difference(pixman_image_t *img_a, pixman_image_t *img_b,
pix_d = image_iter_get_row(&it_d, y) + box.x1;
for (x = box.x1; x < box.x2; x++) {
if (*pix_a == *pix_b)
if (fuzzy_match_pixels(*pix_a, *pix_b, &fuzz))
*pix_d = tint(*pix_d, 0x00008000); /* green */
else
*pix_d = tint(*pix_d, 0x00c00000); /* red */
......
......@@ -176,6 +176,11 @@ struct rectangle {
int height;
};
struct range {
int a;
int b;
};
struct client *
create_client(void);
......@@ -224,11 +229,13 @@ screenshot_reference_filename(const char *basename, uint32_t seq);
bool
check_images_match(pixman_image_t *img_a, pixman_image_t *img_b,
const struct rectangle *clip);
const struct rectangle *clip,
const struct range *prec);
pixman_image_t *
visualize_image_difference(pixman_image_t *img_a, pixman_image_t *img_b,
const struct rectangle *clip_rect);
const struct rectangle *clip_rect,
const struct range *prec);
bool
write_image_as_png(pixman_image_t *image, const char *fname);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment