reftest_compare_surfaces: Report how much the images differ
authorSimon McVittie <smcv@debian.org>
Sat, 13 Feb 2021 18:26:24 +0000 (18:26 +0000)
committerSimon McVittie <smcv@debian.org>
Fri, 5 Nov 2021 12:54:16 +0000 (12:54 +0000)
In unattended/non-interactive/autobuilder environments where the images
are not trivially accessible, this provides a way to distinguish between
totally different rendering and more subtle issues.

Signed-off-by: Simon McVittie <smcv@debian.org>
Forwarded: https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/3195
Applied-upstream: no, upstream want reftests to be a strict pass/fail with identical results required

Gbp-Pq: Name reftest_compare_surfaces-Report-how-much-the-images-diffe.patch

testsuite/gsk/compare-render.c
testsuite/reftests/gtk-reftest.c
testsuite/reftests/reftest-compare.c
testsuite/reftests/reftest-compare.h

index a62252ab357d595e928493b7eb7ea1f4065326e1..9742358b5b0fcb73527eb2ebc6ec5add7bcfedc7 100644 (file)
@@ -236,11 +236,19 @@ main (int argc, char **argv)
     }
   else
     {
+      guint max_diff = 0;
+      guint pixels_changed = 0;
+      guint pixels = 0;
+
       /* Now compare the two */
-      diff_surface = reftest_compare_surfaces (rendered_surface, reference_surface);
+      diff_surface = reftest_compare_surfaces (rendered_surface, reference_surface,
+                                               &max_diff, &pixels_changed, &pixels);
 
       if (diff_surface)
         {
+          g_print ("%u (out of %u) pixels differ from reference by up to %u levels\n",
+                   pixels_changed, pixels, max_diff);
+
           save_image (diff_surface, node_file, ".diff.png");
           cairo_surface_destroy (diff_surface);
           success = FALSE;
index cd153969a8405f4c1531885eb05ddd8ad782ca6e..3ae54133bbe4218f3c365e9e35ad07264d3cf763 100644 (file)
@@ -298,6 +298,9 @@ test_ui_file (GFile *file)
   char *ui_file, *reference_file;
   cairo_surface_t *ui_image, *reference_image, *diff_image;
   GtkStyleProvider *provider;
+  guint max_diff = 0;
+  guint pixels_changed = 0;
+  guint pixels = 0;
 
   ui_file = g_file_get_path (file);
 
@@ -317,12 +320,16 @@ test_ui_file (GFile *file)
     }
   g_free (reference_file);
 
-  diff_image = reftest_compare_surfaces (ui_image, reference_image);
+  diff_image = reftest_compare_surfaces (ui_image, reference_image,
+                                         &max_diff, &pixels_changed, &pixels);
 
   save_image (ui_image, ui_file, ".out.png");
   save_image (reference_image, ui_file, ".ref.png");
+
   if (diff_image)
     {
+      g_test_message ("%u (out of %u) pixels differ from reference by up to %u levels",
+                      pixels_changed, pixels, max_diff);
       save_image (diff_image, ui_file, ".diff.png");
       cairo_surface_destroy (diff_image);
       g_test_fail ();
index 5bccb697b8aaefd7efdc04555d69f55fb4dc1a25..ac72c61c042e82d809c679b3e0fc4bcc97e2317f 100644 (file)
@@ -83,12 +83,16 @@ buffer_diff_core (const guchar *buf_a,
                  const guchar *buf_b,
                   int           stride_b,
                  int           width,
-                 int           height)
+                 int           height,
+                  guint        *max_diff_out,
+                  guint        *pixels_changed_out)
 {
   int x, y;
   guchar *buf_diff = NULL;
   int stride_diff = 0;
   cairo_surface_t *diff = NULL;
+  guint max_diff = 0;
+  guint pixels_changed = 0;
 
   for (y = 0; y < height; y++)
     {
@@ -129,6 +133,10 @@ buffer_diff_core (const guchar *buf_a,
               guint channel_diff;
 
               channel_diff = ABS (value_a - value_b);
+
+              if (channel_diff > max_diff)
+                max_diff = channel_diff;
+
               channel_diff *= 4;  /* emphasize */
               if (channel_diff)
                 channel_diff += 128; /* make sure it's visible */
@@ -137,6 +145,8 @@ buffer_diff_core (const guchar *buf_a,
               diff_pixel |= channel_diff << (channel * 8);
             }
 
+          pixels_changed++;
+
           if ((diff_pixel & 0x00ffffff) == 0)
             {
               /* alpha only difference, convert to luminance */
@@ -148,12 +158,21 @@ buffer_diff_core (const guchar *buf_a,
       }
   }
 
+  if (max_diff_out != NULL)
+    *max_diff_out = max_diff;
+
+  if (pixels_changed_out != NULL)
+    *pixels_changed_out = pixels_changed;
+
   return diff;
 }
 
 cairo_surface_t *
 reftest_compare_surfaces (cairo_surface_t *surface1,
-                          cairo_surface_t *surface2)
+                          cairo_surface_t *surface2,
+                          guint           *max_diff_out,
+                          guint           *pixels_changed_out,
+                          guint           *pixels_out)
 {
   int w1, h1, w2, h2, w, h;
   cairo_surface_t *coerced1, *coerced2, *diff;
@@ -169,11 +188,14 @@ reftest_compare_surfaces (cairo_surface_t *surface1,
                            cairo_image_surface_get_stride (coerced1),
                            cairo_image_surface_get_data (coerced2),
                            cairo_image_surface_get_stride (coerced2),
-                           w, h);
+                           w, h, max_diff_out, pixels_changed_out);
 
   cairo_surface_destroy (coerced1);
   cairo_surface_destroy (coerced2);
 
+  if (pixels_out != NULL)
+    *pixels_out = w * h;
+
   return diff;
 }
 
index 551b1c5a9291002a396b2049bede8aef44df9b0e..c6e001c505ba6f126c76f4c3f8621189cd2cbf2c 100644 (file)
@@ -24,7 +24,10 @@ G_BEGIN_DECLS
 
 G_MODULE_EXPORT
 cairo_surface_t *       reftest_compare_surfaces        (cairo_surface_t        *surface1,
-                                                         cairo_surface_t        *surface2);
+                                                         cairo_surface_t        *surface2,
+                                                         guint                  *max_diff_out,
+                                                         guint                  *pixels_changed_out,
+                                                         guint                  *pixels_out);
 
 G_END_DECLS