Add tests to validate new sRGB behavior
authorAntti S. Lankila <alankila@bel.fi>
Sun, 29 Jul 2012 19:14:34 +0000 (22:14 +0300)
committerSøren Sandmann Pedersen <ssp@redhat.com>
Mon, 30 Jul 2012 19:44:38 +0000 (15:44 -0400)
Composite checks random combinations of operations that now also have
sRGB sources, masks and destinations, and stress-test validates the
read/write primitives.

test/composite.c
test/stress-test.c
test/utils.c
test/utils.h

index 81c416e..2930fb7 100644 (file)
@@ -99,6 +99,9 @@ static const format_t formats[] =
     P(x2b10g10r10),
     P(a2r10g10b10),
     P(a2b10g10r10),
+    
+    /* sRGB formats */
+    P(a8r8g8b8_sRGB),
 
     /* 24 bpp formats */
     P(r8g8b8),
@@ -544,17 +547,56 @@ composite_test (image_t *dst,
     }
 
     tdst = *dst->color;
-    round_color (dst->format->format, &tdst);
-
     tsrc = *src->color;
-    if (src->size)
-       round_color (src->format->format, &tsrc);
 
     if (mask)
     {
        tmsk = *mask->color;
-       if (mask->size)
+    }
+
+    /* It turns out that by construction all source, mask etc. colors are
+     * linear because they are made from fills, and fills are always in linear
+     * color space.  However, if they have been converted to bitmaps, we need
+     * to simulate the sRGB approximation to pass the test cases.
+     */
+    if (src->size)
+    {
+       if (PIXMAN_FORMAT_TYPE (src->format->format) == PIXMAN_TYPE_ARGB_SRGB)
+        {
+           tsrc.r = convert_linear_to_srgb (tsrc.r);
+           tsrc.g = convert_linear_to_srgb (tsrc.g);
+           tsrc.b = convert_linear_to_srgb (tsrc.b);
+           round_color (src->format->format, &tsrc);
+           tsrc.r = convert_srgb_to_linear (tsrc.r);
+           tsrc.g = convert_srgb_to_linear (tsrc.g);
+           tsrc.b = convert_srgb_to_linear (tsrc.b);
+       }
+        else
+        {
+           round_color (src->format->format, &tsrc);
+       }
+    }
+
+    if (mask && mask->size)
+    {
+       if (PIXMAN_FORMAT_TYPE (mask->format->format) == PIXMAN_TYPE_ARGB_SRGB)
+       {
+           tmsk.r = convert_linear_to_srgb (tmsk.r);
+           tmsk.g = convert_linear_to_srgb (tmsk.g);
+           tmsk.b = convert_linear_to_srgb (tmsk.b);
            round_color (mask->format->format, &tmsk);
+           tmsk.r = convert_srgb_to_linear (tmsk.r);
+           tmsk.g = convert_srgb_to_linear (tmsk.g);
+           tmsk.b = convert_srgb_to_linear (tmsk.b);
+       }
+       else
+       {
+           round_color (mask->format->format, &tmsk);
+       }
+    }
+
+    if (mask)
+    {
        if (component_alpha && PIXMAN_FORMAT_R (mask->format->format) == 0)
        {
            /* Ax component-alpha masks expand alpha into
@@ -564,6 +606,21 @@ composite_test (image_t *dst,
        }
     }
 
+    if (PIXMAN_FORMAT_TYPE (dst->format->format) == PIXMAN_TYPE_ARGB_SRGB)
+    {
+       tdst.r = convert_linear_to_srgb (tdst.r);
+       tdst.g = convert_linear_to_srgb (tdst.g);
+       tdst.b = convert_linear_to_srgb (tdst.b);
+       round_color (dst->format->format, &tdst);
+       tdst.r = convert_srgb_to_linear (tdst.r);
+       tdst.g = convert_srgb_to_linear (tdst.g);
+       tdst.b = convert_srgb_to_linear (tdst.b);
+    }
+    else
+    {
+       round_color (dst->format->format, &tdst);
+    }
+
     do_composite (op->op,
                  &tsrc,
                  mask? &tmsk : NULL,
index 9280802..54ab1c5 100644 (file)
@@ -25,6 +25,7 @@ static const pixman_format_code_t image_formats[] =
     PIXMAN_x14r6g6b6,
     PIXMAN_r8g8b8,
     PIXMAN_b8g8r8,
+    PIXMAN_a8r8g8b8_sRGB,
     PIXMAN_r5g6b5,
     PIXMAN_b5g6r5,
     PIXMAN_x2r10g10b10,
index 563b33d..85b58d0 100644 (file)
@@ -1,6 +1,7 @@
 #define _GNU_SOURCE
 
 #include "utils.h"
+#include <math.h>
 #include <signal.h>
 #include <stdlib.h>
 
@@ -765,6 +766,24 @@ aligned_malloc (size_t align, size_t size)
        (((c) >>  8) & 0xff) * 301 +                                    \
        (((c)      ) & 0xff) * 58) >> 2))
 
+double
+convert_srgb_to_linear (double c)
+{
+    if (c <= 0.04045)
+        return c / 12.92;
+    else
+        return powf ((c + 0.055) / 1.055, 2.4);
+}
+
+double
+convert_linear_to_srgb (double c)
+{
+    if (c <= 0.0031308)
+        return c * 12.92;
+    else
+        return 1.055 * powf (c, 1.0/2.4) - 0.055;
+}
+
 void
 initialize_palette (pixman_indexed_t *palette, uint32_t depth, int is_rgb)
 {
@@ -868,6 +887,7 @@ pixel_checker_init (pixel_checker_t *checker, pixman_format_code_t format)
        break;
 
     case PIXMAN_TYPE_ARGB:
+    case PIXMAN_TYPE_ARGB_SRGB:
        checker->bs = 0;
        checker->gs = checker->bs + PIXMAN_FORMAT_B (format);
        checker->rs = checker->gs + PIXMAN_FORMAT_G (format);
@@ -968,11 +988,25 @@ pixel_checker_get_min (const pixel_checker_t *checker, color_t *color,
 
 pixman_bool_t
 pixel_checker_check (const pixel_checker_t *checker, uint32_t pixel,
-                    color_t *color)
+                    color_t *color_in)
 {
     int32_t a_lo, a_hi, r_lo, r_hi, g_lo, g_hi, b_lo, b_hi;
     int32_t ai, ri, gi, bi;
     pixman_bool_t result;
+    color_t tmp, *color;
+
+    if (PIXMAN_FORMAT_TYPE (checker->format) == PIXMAN_TYPE_ARGB_SRGB)
+    {
+       tmp.a = color_in->a;
+       tmp.r = convert_linear_to_srgb (color_in->r);
+       tmp.g = convert_linear_to_srgb (color_in->g);
+       tmp.b = convert_linear_to_srgb (color_in->b);
+       color = &tmp;
+    }
+    else
+    {
+       color = color_in;
+    }
 
     pixel_checker_get_min (checker, color, &a_lo, &r_lo, &g_lo, &b_lo);
     pixel_checker_get_max (checker, color, &a_hi, &r_hi, &g_hi, &b_hi);
index ac2decd..faf427f 100644 (file)
@@ -163,6 +163,12 @@ write_png (pixman_image_t *image, const char *filename);
 void *
 aligned_malloc (size_t align, size_t size);
 
+double
+convert_srgb_to_linear (double component);
+
+double
+convert_linear_to_srgb (double component);
+
 void
 initialize_palette (pixman_indexed_t *palette, uint32_t depth, int is_rgb);