Home | History | Annotate | Download | only in test
      1 /*
      2  * Copyright  2005 Eric Anholt
      3  * Copyright  2009 Chris Wilson
      4  * Copyright  2010 Soeren Sandmann
      5  * Copyright  2010 Red Hat, Inc.
      6  *
      7  * Permission to use, copy, modify, distribute, and sell this software and its
      8  * documentation for any purpose is hereby granted without fee, provided that
      9  * the above copyright notice appear in all copies and that both that
     10  * copyright notice and this permission notice appear in supporting
     11  * documentation, and that the name of Eric Anholt not be used in
     12  * advertising or publicity pertaining to distribution of the software without
     13  * specific, written prior permission.  Eric Anholt makes no
     14  * representations about the suitability of this software for any purpose.  It
     15  * is provided "as is" without express or implied warranty.
     16  *
     17  * ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     18  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
     19  * EVENT SHALL ERIC ANHOLT BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     20  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     21  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
     22  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
     23  * PERFORMANCE OF THIS SOFTWARE.
     24  */
     25 #include <stdio.h>
     26 #include <stdlib.h> /* abort() */
     27 #include <math.h>
     28 #include <time.h>
     29 #include "utils.h"
     30 
     31 typedef struct image_t image_t;
     32 
     33 static const color_t colors[] =
     34 {
     35     { 1.0, 1.0, 1.0, 1.0 },
     36     { 1.0, 1.0, 1.0, 0.0 },
     37     { 0.0, 0.0, 0.0, 1.0 },
     38     { 0.0, 0.0, 0.0, 0.0 },
     39     { 1.0, 0.0, 0.0, 1.0 },
     40     { 0.0, 1.0, 0.0, 1.0 },
     41     { 0.0, 0.0, 1.0, 1.0 },
     42     { 0.5, 0.0, 0.0, 0.5 },
     43 };
     44 
     45 static uint16_t
     46 _color_double_to_short (double d)
     47 {
     48     uint32_t i;
     49 
     50     i = (uint32_t) (d * 65536);
     51     i -= (i >> 16);
     52 
     53     return i;
     54 }
     55 
     56 static void
     57 compute_pixman_color (const color_t *color,
     58 		      pixman_color_t *out)
     59 {
     60     out->red   = _color_double_to_short (color->r);
     61     out->green = _color_double_to_short (color->g);
     62     out->blue  = _color_double_to_short (color->b);
     63     out->alpha = _color_double_to_short (color->a);
     64 }
     65 
     66 #define REPEAT 0x01000000
     67 #define FLAGS  0xff000000
     68 
     69 static const int sizes[] =
     70 {
     71     0,
     72     1,
     73     1 | REPEAT,
     74     10
     75 };
     76 
     77 static const pixman_format_code_t formats[] =
     78 {
     79     /* 32 bpp formats */
     80     PIXMAN_a8r8g8b8,
     81     PIXMAN_x8r8g8b8,
     82     PIXMAN_a8b8g8r8,
     83     PIXMAN_x8b8g8r8,
     84     PIXMAN_b8g8r8a8,
     85     PIXMAN_b8g8r8x8,
     86     PIXMAN_r8g8b8a8,
     87     PIXMAN_r8g8b8x8,
     88     PIXMAN_x2r10g10b10,
     89     PIXMAN_x2b10g10r10,
     90     PIXMAN_a2r10g10b10,
     91     PIXMAN_a2b10g10r10,
     92 
     93     /* sRGB formats */
     94     PIXMAN_a8r8g8b8_sRGB,
     95 
     96     /* 24 bpp formats */
     97     PIXMAN_r8g8b8,
     98     PIXMAN_b8g8r8,
     99     PIXMAN_r5g6b5,
    100     PIXMAN_b5g6r5,
    101 
    102     /* 16 bpp formats */
    103     PIXMAN_x1r5g5b5,
    104     PIXMAN_x1b5g5r5,
    105     PIXMAN_a1r5g5b5,
    106     PIXMAN_a1b5g5r5,
    107     PIXMAN_a4b4g4r4,
    108     PIXMAN_x4b4g4r4,
    109     PIXMAN_a4r4g4b4,
    110     PIXMAN_x4r4g4b4,
    111 
    112     /* 8 bpp formats */
    113     PIXMAN_a8,
    114     PIXMAN_r3g3b2,
    115     PIXMAN_b2g3r3,
    116     PIXMAN_a2r2g2b2,
    117     PIXMAN_a2b2g2r2,
    118     PIXMAN_x4a4,
    119 
    120     /* 4 bpp formats */
    121     PIXMAN_a4,
    122     PIXMAN_r1g2b1,
    123     PIXMAN_b1g2r1,
    124     PIXMAN_a1r1g1b1,
    125     PIXMAN_a1b1g1r1,
    126 
    127     /* 1 bpp formats */
    128     PIXMAN_a1,
    129 };
    130 
    131 struct image_t
    132 {
    133     pixman_image_t *image;
    134     pixman_format_code_t format;
    135     const color_t *color;
    136     pixman_repeat_t repeat;
    137     int size;
    138 };
    139 
    140 static const pixman_op_t operators[] =
    141 {
    142     PIXMAN_OP_CLEAR,
    143     PIXMAN_OP_SRC,
    144     PIXMAN_OP_DST,
    145     PIXMAN_OP_OVER,
    146     PIXMAN_OP_OVER_REVERSE,
    147     PIXMAN_OP_IN,
    148     PIXMAN_OP_IN_REVERSE,
    149     PIXMAN_OP_OUT,
    150     PIXMAN_OP_OUT_REVERSE,
    151     PIXMAN_OP_ATOP,
    152     PIXMAN_OP_ATOP_REVERSE,
    153     PIXMAN_OP_XOR,
    154     PIXMAN_OP_ADD,
    155     PIXMAN_OP_SATURATE,
    156 
    157     PIXMAN_OP_DISJOINT_CLEAR,
    158     PIXMAN_OP_DISJOINT_SRC,
    159     PIXMAN_OP_DISJOINT_DST,
    160     PIXMAN_OP_DISJOINT_OVER,
    161     PIXMAN_OP_DISJOINT_OVER_REVERSE,
    162     PIXMAN_OP_DISJOINT_IN,
    163     PIXMAN_OP_DISJOINT_IN_REVERSE,
    164     PIXMAN_OP_DISJOINT_OUT,
    165     PIXMAN_OP_DISJOINT_OUT_REVERSE,
    166     PIXMAN_OP_DISJOINT_ATOP,
    167     PIXMAN_OP_DISJOINT_ATOP_REVERSE,
    168     PIXMAN_OP_DISJOINT_XOR,
    169 
    170     PIXMAN_OP_CONJOINT_CLEAR,
    171     PIXMAN_OP_CONJOINT_SRC,
    172     PIXMAN_OP_CONJOINT_DST,
    173     PIXMAN_OP_CONJOINT_OVER,
    174     PIXMAN_OP_CONJOINT_OVER_REVERSE,
    175     PIXMAN_OP_CONJOINT_IN,
    176     PIXMAN_OP_CONJOINT_IN_REVERSE,
    177     PIXMAN_OP_CONJOINT_OUT,
    178     PIXMAN_OP_CONJOINT_OUT_REVERSE,
    179     PIXMAN_OP_CONJOINT_ATOP,
    180     PIXMAN_OP_CONJOINT_ATOP_REVERSE,
    181     PIXMAN_OP_CONJOINT_XOR,
    182 };
    183 
    184 static uint32_t
    185 get_value (pixman_image_t *image)
    186 {
    187     uint32_t value = *(uint32_t *)pixman_image_get_data (image);
    188 
    189 #ifdef WORDS_BIGENDIAN
    190     {
    191 	pixman_format_code_t format = pixman_image_get_format (image);
    192 	value >>= 8 * sizeof(value) - PIXMAN_FORMAT_BPP (format);
    193     }
    194 #endif
    195 
    196     return value;
    197 }
    198 
    199 static char *
    200 describe_image (image_t *info, char *buf)
    201 {
    202     if (info->size)
    203     {
    204 	sprintf (buf, "%s, %dx%d%s",
    205 		 format_name (info->format),
    206 		 info->size, info->size,
    207 		 info->repeat ? " R" :"");
    208     }
    209     else
    210     {
    211 	sprintf (buf, "solid");
    212     }
    213 
    214     return buf;
    215 }
    216 
    217 static char *
    218 describe_color (const color_t *color, char *buf)
    219 {
    220     sprintf (buf, "%.3f %.3f %.3f %.3f",
    221 	     color->r, color->g, color->b, color->a);
    222 
    223     return buf;
    224 }
    225 
    226 static pixman_bool_t
    227 composite_test (image_t *dst,
    228 		pixman_op_t op,
    229 		image_t *src,
    230 		image_t *mask,
    231 		pixman_bool_t component_alpha,
    232 		int testno)
    233 {
    234     color_t expected, tdst, tsrc, tmsk;
    235     pixel_checker_t checker;
    236 
    237     if (mask)
    238     {
    239 	pixman_image_set_component_alpha (mask->image, component_alpha);
    240 
    241 	pixman_image_composite (op, src->image, mask->image, dst->image,
    242 				0, 0, 0, 0, 0, 0, dst->size, dst->size);
    243     }
    244     else
    245     {
    246 	pixman_image_composite (op, src->image, NULL, dst->image,
    247 				0, 0,
    248 				0, 0,
    249 				0, 0,
    250 				dst->size, dst->size);
    251     }
    252 
    253     tdst = *dst->color;
    254     tsrc = *src->color;
    255 
    256     if (mask)
    257     {
    258 	tmsk = *mask->color;
    259     }
    260 
    261     /* It turns out that by construction all source, mask etc. colors are
    262      * linear because they are made from fills, and fills are always in linear
    263      * color space.  However, if they have been converted to bitmaps, we need
    264      * to simulate the sRGB approximation to pass the test cases.
    265      */
    266     if (src->size)
    267     {
    268 	if (PIXMAN_FORMAT_TYPE (src->format) == PIXMAN_TYPE_ARGB_SRGB)
    269         {
    270 	    tsrc.r = convert_linear_to_srgb (tsrc.r);
    271 	    tsrc.g = convert_linear_to_srgb (tsrc.g);
    272 	    tsrc.b = convert_linear_to_srgb (tsrc.b);
    273 	    round_color (src->format, &tsrc);
    274 	    tsrc.r = convert_srgb_to_linear (tsrc.r);
    275 	    tsrc.g = convert_srgb_to_linear (tsrc.g);
    276 	    tsrc.b = convert_srgb_to_linear (tsrc.b);
    277 	}
    278         else
    279         {
    280 	    round_color (src->format, &tsrc);
    281 	}
    282     }
    283 
    284     if (mask && mask->size)
    285     {
    286 	if (PIXMAN_FORMAT_TYPE (mask->format) == PIXMAN_TYPE_ARGB_SRGB)
    287 	{
    288 	    tmsk.r = convert_linear_to_srgb (tmsk.r);
    289 	    tmsk.g = convert_linear_to_srgb (tmsk.g);
    290 	    tmsk.b = convert_linear_to_srgb (tmsk.b);
    291 	    round_color (mask->format, &tmsk);
    292 	    tmsk.r = convert_srgb_to_linear (tmsk.r);
    293 	    tmsk.g = convert_srgb_to_linear (tmsk.g);
    294 	    tmsk.b = convert_srgb_to_linear (tmsk.b);
    295 	}
    296 	else
    297 	{
    298 	    round_color (mask->format, &tmsk);
    299 	}
    300     }
    301 
    302     if (mask)
    303     {
    304 	if (component_alpha && PIXMAN_FORMAT_R (mask->format) == 0)
    305 	{
    306 	    /* Ax component-alpha masks expand alpha into
    307 	     * all color channels.
    308 	     */
    309 	    tmsk.r = tmsk.g = tmsk.b = tmsk.a;
    310 	}
    311     }
    312 
    313     if (PIXMAN_FORMAT_TYPE (dst->format) == PIXMAN_TYPE_ARGB_SRGB)
    314     {
    315 	tdst.r = convert_linear_to_srgb (tdst.r);
    316 	tdst.g = convert_linear_to_srgb (tdst.g);
    317 	tdst.b = convert_linear_to_srgb (tdst.b);
    318     	round_color (dst->format, &tdst);
    319 	tdst.r = convert_srgb_to_linear (tdst.r);
    320 	tdst.g = convert_srgb_to_linear (tdst.g);
    321 	tdst.b = convert_srgb_to_linear (tdst.b);
    322     }
    323     else
    324     {
    325     	round_color (dst->format, &tdst);
    326     }
    327 
    328     do_composite (op,
    329 		  &tsrc,
    330 		  mask? &tmsk : NULL,
    331 		  &tdst,
    332 		  &expected,
    333 		  component_alpha);
    334 
    335     pixel_checker_init (&checker, dst->format);
    336 
    337     if (!pixel_checker_check (&checker, get_value (dst->image), &expected))
    338     {
    339 	char buf[40], buf2[40];
    340 	int a, r, g, b;
    341 	uint32_t pixel;
    342 
    343 	printf ("---- Test %d failed ----\n", testno);
    344 	printf ("Operator:      %s %s\n",
    345                 operator_name (op), component_alpha ? "CA" : "");
    346 
    347 	printf ("Source:        %s\n", describe_image (src, buf));
    348 	if (mask != NULL)
    349 	    printf ("Mask:          %s\n", describe_image (mask, buf));
    350 
    351 	printf ("Destination:   %s\n\n", describe_image (dst, buf));
    352 	printf ("               R     G     B     A         Rounded\n");
    353 	printf ("Source color:  %s     %s\n",
    354 		describe_color (src->color, buf),
    355 		describe_color (&tsrc, buf2));
    356 	if (mask)
    357 	{
    358 	    printf ("Mask color:    %s     %s\n",
    359 		    describe_color (mask->color, buf),
    360 		    describe_color (&tmsk, buf2));
    361 	}
    362 	printf ("Dest. color:   %s     %s\n",
    363 		describe_color (dst->color, buf),
    364 		describe_color (&tdst, buf2));
    365 
    366 	pixel = get_value (dst->image);
    367 
    368 	printf ("Expected:      %s\n", describe_color (&expected, buf));
    369 
    370 	pixel_checker_split_pixel (&checker, pixel, &a, &r, &g, &b);
    371 
    372 	printf ("Got:           %5d %5d %5d %5d  [pixel: 0x%08x]\n", r, g, b, a, pixel);
    373 	pixel_checker_get_min (&checker, &expected, &a, &r, &g, &b);
    374 	printf ("Min accepted:  %5d %5d %5d %5d\n", r, g, b, a);
    375 	pixel_checker_get_max (&checker, &expected, &a, &r, &g, &b);
    376 	printf ("Max accepted:  %5d %5d %5d %5d\n", r, g, b, a);
    377 
    378 	return FALSE;
    379     }
    380     return TRUE;
    381 }
    382 
    383 static void
    384 image_init (image_t *info,
    385 	    int color,
    386 	    int format,
    387 	    int size)
    388 {
    389     pixman_color_t fill;
    390 
    391     info->color = &colors[color];
    392     compute_pixman_color (info->color, &fill);
    393 
    394     info->format = formats[format];
    395     info->size = sizes[size] & ~FLAGS;
    396     info->repeat = PIXMAN_REPEAT_NONE;
    397 
    398     if (info->size)
    399     {
    400 	pixman_image_t *solid;
    401 
    402 	info->image = pixman_image_create_bits (info->format,
    403 						info->size, info->size,
    404 						NULL, 0);
    405 
    406 	solid = pixman_image_create_solid_fill (&fill);
    407 	pixman_image_composite32 (PIXMAN_OP_SRC, solid, NULL, info->image,
    408 				  0, 0, 0, 0, 0, 0, info->size, info->size);
    409 	pixman_image_unref (solid);
    410 
    411 	if (sizes[size] & REPEAT)
    412 	{
    413 	    pixman_image_set_repeat (info->image, PIXMAN_REPEAT_NORMAL);
    414 	    info->repeat = PIXMAN_REPEAT_NORMAL;
    415 	}
    416     }
    417     else
    418     {
    419 	info->image = pixman_image_create_solid_fill (&fill);
    420     }
    421 }
    422 
    423 static void
    424 image_fini (image_t *info)
    425 {
    426     pixman_image_unref (info->image);
    427 }
    428 
    429 static int
    430 random_size (void)
    431 {
    432     return prng_rand_n (ARRAY_LENGTH (sizes));
    433 }
    434 
    435 static int
    436 random_color (void)
    437 {
    438     return prng_rand_n (ARRAY_LENGTH (colors));
    439 }
    440 
    441 static int
    442 random_format (void)
    443 {
    444     return prng_rand_n (ARRAY_LENGTH (formats));
    445 }
    446 
    447 static pixman_bool_t
    448 run_test (uint32_t seed)
    449 {
    450     image_t src, mask, dst;
    451     pixman_op_t op;
    452     int ca;
    453     int ok;
    454 
    455     prng_srand (seed);
    456 
    457     image_init (&dst, random_color(), random_format(), 1);
    458     image_init (&src, random_color(), random_format(), random_size());
    459     image_init (&mask, random_color(), random_format(), random_size());
    460 
    461     op = operators [prng_rand_n (ARRAY_LENGTH (operators))];
    462 
    463     ca = prng_rand_n (3);
    464 
    465     switch (ca)
    466     {
    467     case 0:
    468 	ok = composite_test (&dst, op, &src, NULL, FALSE, seed);
    469 	break;
    470     case 1:
    471 	ok = composite_test (&dst, op, &src, &mask, FALSE, seed);
    472 	break;
    473     case 2:
    474 	ok = composite_test (&dst, op, &src, &mask,
    475 			     mask.size? TRUE : FALSE, seed);
    476 	break;
    477     default:
    478 	ok = FALSE;
    479 	break;
    480     }
    481 
    482     image_fini (&src);
    483     image_fini (&mask);
    484     image_fini (&dst);
    485 
    486     return ok;
    487 }
    488 
    489 int
    490 main (int argc, char **argv)
    491 {
    492 #define N_TESTS (8 * 1024 * 1024)
    493     int result = 0;
    494     uint32_t seed;
    495     int32_t i;
    496 
    497     if (argc > 1)
    498     {
    499 	char *end;
    500 
    501 	i = strtol (argv[1], &end, 0);
    502 
    503 	if (end != argv[1])
    504 	{
    505 	    if (!run_test (i))
    506 		return 1;
    507 	    else
    508 		return 0;
    509 	}
    510 	else
    511 	{
    512 	    printf ("Usage:\n\n   %s <number>\n\n", argv[0]);
    513 	    return -1;
    514 	}
    515     }
    516 
    517     if (getenv ("PIXMAN_RANDOMIZE_TESTS"))
    518 	seed = get_random_seed();
    519     else
    520 	seed = 1;
    521 
    522 #ifdef USE_OPENMP
    523 #   pragma omp parallel for default(none) shared(result, argv, seed)
    524 #endif
    525     for (i = 0; i <= N_TESTS; ++i)
    526     {
    527 	if (!result && !run_test (i + seed))
    528 	{
    529 	    printf ("Test 0x%08X failed.\n", seed + i);
    530 
    531 	    result = seed + i;
    532 	}
    533     }
    534 
    535     return result;
    536 }
    537