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