blitters-test.c revision 1b18d63a
1/* 2 * Test program, which stresses the use of different color formats and 3 * compositing operations. 4 * 5 * Script 'fuzzer-find-diff.pl' can be used to narrow down the problem in 6 * the case of test failure. 7 */ 8#include <assert.h> 9#include <stdlib.h> 10#include <stdio.h> 11#include <config.h> 12#include "utils.h" 13 14static pixman_indexed_t rgb_palette[9]; 15static pixman_indexed_t y_palette[9]; 16 17/* Create random image for testing purposes */ 18static pixman_image_t * 19create_random_image (pixman_format_code_t *allowed_formats, 20 int max_width, 21 int max_height, 22 int max_extra_stride, 23 pixman_format_code_t *used_fmt) 24{ 25 int n = 0, i, width, height, stride; 26 pixman_format_code_t fmt; 27 uint32_t *buf; 28 pixman_image_t *img; 29 30 while (allowed_formats[n] != -1) 31 n++; 32 fmt = allowed_formats[lcg_rand_n (n)]; 33 34 width = lcg_rand_n (max_width) + 1; 35 height = lcg_rand_n (max_height) + 1; 36 stride = (width * PIXMAN_FORMAT_BPP (fmt) + 7) / 8 + 37 lcg_rand_n (max_extra_stride + 1); 38 stride = (stride + 3) & ~3; 39 40 /* do the allocation */ 41 buf = aligned_malloc (64, stride * height); 42 43 /* initialize image with random data */ 44 for (i = 0; i < stride * height; i++) 45 { 46 /* generation is biased to having more 0 or 255 bytes as 47 * they are more likely to be special-cased in code 48 */ 49 *((uint8_t *)buf + i) = lcg_rand_n (4) ? lcg_rand_n (256) : 50 (lcg_rand_n (2) ? 0 : 255); 51 } 52 53 img = pixman_image_create_bits (fmt, width, height, buf, stride); 54 55 if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_COLOR) 56 { 57 pixman_image_set_indexed (img, &(rgb_palette[PIXMAN_FORMAT_BPP (fmt)])); 58 } 59 else if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_GRAY) 60 { 61 pixman_image_set_indexed (img, &(y_palette[PIXMAN_FORMAT_BPP (fmt)])); 62 } 63 64 image_endian_swap (img, PIXMAN_FORMAT_BPP (fmt)); 65 66 if (used_fmt) *used_fmt = fmt; 67 return img; 68} 69 70/* Free random image, and optionally update crc32 based on its data */ 71static uint32_t 72free_random_image (uint32_t initcrc, 73 pixman_image_t *img, 74 pixman_format_code_t fmt) 75{ 76 uint32_t crc32 = 0; 77 int stride = pixman_image_get_stride (img); 78 uint32_t *data = pixman_image_get_data (img); 79 int height = pixman_image_get_height (img); 80 81 if (fmt != -1) 82 { 83 /* mask unused 'x' part */ 84 if (PIXMAN_FORMAT_BPP (fmt) - PIXMAN_FORMAT_DEPTH (fmt) && 85 PIXMAN_FORMAT_DEPTH (fmt) != 0) 86 { 87 int i; 88 uint32_t *data = pixman_image_get_data (img); 89 uint32_t mask = (1 << PIXMAN_FORMAT_DEPTH (fmt)) - 1; 90 91 if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_BGRA) 92 mask <<= (PIXMAN_FORMAT_BPP (fmt) - PIXMAN_FORMAT_DEPTH (fmt)); 93 94 for (i = 0; i < 32; i++) 95 mask |= mask << (i * PIXMAN_FORMAT_BPP (fmt)); 96 97 for (i = 0; i < stride * height / 4; i++) 98 data[i] &= mask; 99 } 100 101 /* swap endiannes in order to provide identical results on both big 102 * and litte endian systems 103 */ 104 image_endian_swap (img, PIXMAN_FORMAT_BPP (fmt)); 105 crc32 = compute_crc32 (initcrc, data, stride * height); 106 } 107 108 pixman_image_unref (img); 109 free (data); 110 111 return crc32; 112} 113 114static pixman_op_t op_list[] = { 115 PIXMAN_OP_SRC, 116 PIXMAN_OP_OVER, 117 PIXMAN_OP_ADD, 118 PIXMAN_OP_CLEAR, 119 PIXMAN_OP_SRC, 120 PIXMAN_OP_DST, 121 PIXMAN_OP_OVER, 122 PIXMAN_OP_OVER_REVERSE, 123 PIXMAN_OP_IN, 124 PIXMAN_OP_IN_REVERSE, 125 PIXMAN_OP_OUT, 126 PIXMAN_OP_OUT_REVERSE, 127 PIXMAN_OP_ATOP, 128 PIXMAN_OP_ATOP_REVERSE, 129 PIXMAN_OP_XOR, 130 PIXMAN_OP_ADD, 131 PIXMAN_OP_SATURATE, 132 PIXMAN_OP_DISJOINT_CLEAR, 133 PIXMAN_OP_DISJOINT_SRC, 134 PIXMAN_OP_DISJOINT_DST, 135 PIXMAN_OP_DISJOINT_OVER, 136 PIXMAN_OP_DISJOINT_OVER_REVERSE, 137 PIXMAN_OP_DISJOINT_IN, 138 PIXMAN_OP_DISJOINT_IN_REVERSE, 139 PIXMAN_OP_DISJOINT_OUT, 140 PIXMAN_OP_DISJOINT_OUT_REVERSE, 141 PIXMAN_OP_DISJOINT_ATOP, 142 PIXMAN_OP_DISJOINT_ATOP_REVERSE, 143 PIXMAN_OP_DISJOINT_XOR, 144 PIXMAN_OP_CONJOINT_CLEAR, 145 PIXMAN_OP_CONJOINT_SRC, 146 PIXMAN_OP_CONJOINT_DST, 147 PIXMAN_OP_CONJOINT_OVER, 148 PIXMAN_OP_CONJOINT_OVER_REVERSE, 149 PIXMAN_OP_CONJOINT_IN, 150 PIXMAN_OP_CONJOINT_IN_REVERSE, 151 PIXMAN_OP_CONJOINT_OUT, 152 PIXMAN_OP_CONJOINT_OUT_REVERSE, 153 PIXMAN_OP_CONJOINT_ATOP, 154 PIXMAN_OP_CONJOINT_ATOP_REVERSE, 155 PIXMAN_OP_CONJOINT_XOR, 156 PIXMAN_OP_MULTIPLY, 157 PIXMAN_OP_SCREEN, 158 PIXMAN_OP_OVERLAY, 159 PIXMAN_OP_DARKEN, 160 PIXMAN_OP_LIGHTEN, 161 PIXMAN_OP_COLOR_DODGE, 162 PIXMAN_OP_COLOR_BURN, 163 PIXMAN_OP_HARD_LIGHT, 164 PIXMAN_OP_DIFFERENCE, 165 PIXMAN_OP_EXCLUSION, 166#if 0 /* these use floating point math and are not always bitexact on different platforms */ 167 PIXMAN_OP_SOFT_LIGHT, 168 PIXMAN_OP_HSL_HUE, 169 PIXMAN_OP_HSL_SATURATION, 170 PIXMAN_OP_HSL_COLOR, 171 PIXMAN_OP_HSL_LUMINOSITY, 172#endif 173}; 174 175static pixman_format_code_t img_fmt_list[] = { 176 PIXMAN_a8r8g8b8, 177 PIXMAN_x8r8g8b8, 178 PIXMAN_r5g6b5, 179 PIXMAN_r3g3b2, 180 PIXMAN_a8, 181 PIXMAN_a8b8g8r8, 182 PIXMAN_x8b8g8r8, 183 PIXMAN_b8g8r8a8, 184 PIXMAN_b8g8r8x8, 185 PIXMAN_x14r6g6b6, 186 PIXMAN_r8g8b8, 187 PIXMAN_b8g8r8, 188 PIXMAN_r5g6b5, 189 PIXMAN_b5g6r5, 190 PIXMAN_x2r10g10b10, 191 PIXMAN_a2r10g10b10, 192 PIXMAN_x2b10g10r10, 193 PIXMAN_a2b10g10r10, 194 PIXMAN_a1r5g5b5, 195 PIXMAN_x1r5g5b5, 196 PIXMAN_a1b5g5r5, 197 PIXMAN_x1b5g5r5, 198 PIXMAN_a4r4g4b4, 199 PIXMAN_x4r4g4b4, 200 PIXMAN_a4b4g4r4, 201 PIXMAN_x4b4g4r4, 202 PIXMAN_a8, 203 PIXMAN_r3g3b2, 204 PIXMAN_b2g3r3, 205 PIXMAN_a2r2g2b2, 206 PIXMAN_a2b2g2r2, 207 PIXMAN_c8, 208 PIXMAN_g8, 209 PIXMAN_x4c4, 210 PIXMAN_x4g4, 211 PIXMAN_c4, 212 PIXMAN_g4, 213 PIXMAN_g1, 214 PIXMAN_x4a4, 215 PIXMAN_a4, 216 PIXMAN_r1g2b1, 217 PIXMAN_b1g2r1, 218 PIXMAN_a1r1g1b1, 219 PIXMAN_a1b1g1r1, 220 PIXMAN_a1, 221 -1 222}; 223 224static pixman_format_code_t mask_fmt_list[] = { 225 PIXMAN_a8r8g8b8, 226 PIXMAN_a8, 227 PIXMAN_a4, 228 PIXMAN_a1, 229 -1 230}; 231 232 233/* 234 * Composite operation with pseudorandom images 235 */ 236uint32_t 237test_composite (int testnum, int verbose) 238{ 239 int i; 240 pixman_image_t *src_img = NULL; 241 pixman_image_t *dst_img = NULL; 242 pixman_image_t *mask_img = NULL; 243 int src_width, src_height; 244 int dst_width, dst_height; 245 int src_stride, dst_stride; 246 int src_x, src_y; 247 int dst_x, dst_y; 248 int mask_x, mask_y; 249 int w, h; 250 int op; 251 pixman_format_code_t src_fmt, dst_fmt, mask_fmt; 252 uint32_t *dstbuf, *srcbuf, *maskbuf; 253 uint32_t crc32; 254 int max_width, max_height, max_extra_stride; 255 FLOAT_REGS_CORRUPTION_DETECTOR_START (); 256 257 max_width = max_height = 24 + testnum / 10000; 258 max_extra_stride = 4 + testnum / 1000000; 259 260 if (max_width > 256) 261 max_width = 256; 262 263 if (max_height > 16) 264 max_height = 16; 265 266 if (max_extra_stride > 8) 267 max_extra_stride = 8; 268 269 lcg_srand (testnum); 270 271 op = op_list[lcg_rand_n (sizeof (op_list) / sizeof (op_list[0]))]; 272 273 if (lcg_rand_n (8)) 274 { 275 /* normal image */ 276 src_img = create_random_image (img_fmt_list, max_width, max_height, 277 max_extra_stride, &src_fmt); 278 } 279 else 280 { 281 /* solid case */ 282 src_img = create_random_image (img_fmt_list, 1, 1, 283 max_extra_stride, &src_fmt); 284 285 pixman_image_set_repeat (src_img, PIXMAN_REPEAT_NORMAL); 286 } 287 288 dst_img = create_random_image (img_fmt_list, max_width, max_height, 289 max_extra_stride, &dst_fmt); 290 291 src_width = pixman_image_get_width (src_img); 292 src_height = pixman_image_get_height (src_img); 293 src_stride = pixman_image_get_stride (src_img); 294 295 dst_width = pixman_image_get_width (dst_img); 296 dst_height = pixman_image_get_height (dst_img); 297 dst_stride = pixman_image_get_stride (dst_img); 298 299 dstbuf = pixman_image_get_data (dst_img); 300 srcbuf = pixman_image_get_data (src_img); 301 302 src_x = lcg_rand_n (src_width); 303 src_y = lcg_rand_n (src_height); 304 dst_x = lcg_rand_n (dst_width); 305 dst_y = lcg_rand_n (dst_height); 306 307 mask_img = NULL; 308 mask_fmt = -1; 309 mask_x = 0; 310 mask_y = 0; 311 maskbuf = NULL; 312 313 if ((src_fmt == PIXMAN_x8r8g8b8 || src_fmt == PIXMAN_x8b8g8r8) && 314 (lcg_rand_n (4) == 0)) 315 { 316 /* PIXBUF */ 317 mask_fmt = lcg_rand_n (2) ? PIXMAN_a8r8g8b8 : PIXMAN_a8b8g8r8; 318 mask_img = pixman_image_create_bits (mask_fmt, 319 src_width, 320 src_height, 321 srcbuf, 322 src_stride); 323 mask_x = src_x; 324 mask_y = src_y; 325 maskbuf = srcbuf; 326 } 327 else if (lcg_rand_n (2)) 328 { 329 if (lcg_rand_n (2)) 330 { 331 mask_img = create_random_image (mask_fmt_list, max_width, max_height, 332 max_extra_stride, &mask_fmt); 333 } 334 else 335 { 336 /* solid case */ 337 mask_img = create_random_image (mask_fmt_list, 1, 1, 338 max_extra_stride, &mask_fmt); 339 pixman_image_set_repeat (mask_img, PIXMAN_REPEAT_NORMAL); 340 } 341 342 if (lcg_rand_n (2)) 343 pixman_image_set_component_alpha (mask_img, 1); 344 345 mask_x = lcg_rand_n (pixman_image_get_width (mask_img)); 346 mask_y = lcg_rand_n (pixman_image_get_height (mask_img)); 347 } 348 349 350 w = lcg_rand_n (dst_width - dst_x + 1); 351 h = lcg_rand_n (dst_height - dst_y + 1); 352 353 if (verbose) 354 { 355 printf ("op=%d, src_fmt=%08X, dst_fmt=%08X, mask_fmt=%08X\n", 356 op, src_fmt, dst_fmt, mask_fmt); 357 printf ("src_width=%d, src_height=%d, dst_width=%d, dst_height=%d\n", 358 src_width, src_height, dst_width, dst_height); 359 printf ("src_x=%d, src_y=%d, dst_x=%d, dst_y=%d\n", 360 src_x, src_y, dst_x, dst_y); 361 printf ("src_stride=%d, dst_stride=%d\n", 362 src_stride, dst_stride); 363 printf ("w=%d, h=%d\n", w, h); 364 } 365 366 pixman_image_composite (op, src_img, mask_img, dst_img, 367 src_x, src_y, mask_x, mask_y, dst_x, dst_y, w, h); 368 369 if (verbose) 370 { 371 int j; 372 373 printf ("---\n"); 374 for (i = 0; i < dst_height; i++) 375 { 376 for (j = 0; j < dst_stride; j++) 377 { 378 if (j == (dst_width * PIXMAN_FORMAT_BPP (dst_fmt) + 7) / 8) 379 printf ("| "); 380 381 printf ("%02X ", *((uint8_t *)dstbuf + i * dst_stride + j)); 382 } 383 printf ("\n"); 384 } 385 printf ("---\n"); 386 } 387 388 free_random_image (0, src_img, -1); 389 crc32 = free_random_image (0, dst_img, dst_fmt); 390 391 if (mask_img) 392 { 393 if (srcbuf == maskbuf) 394 pixman_image_unref(mask_img); 395 else 396 free_random_image (0, mask_img, -1); 397 } 398 399 FLOAT_REGS_CORRUPTION_DETECTOR_FINISH (); 400 return crc32; 401} 402 403#define CONVERT_15(c, is_rgb) \ 404 (is_rgb? \ 405 ((((c) >> 3) & 0x001f) | \ 406 (((c) >> 6) & 0x03e0) | \ 407 (((c) >> 9) & 0x7c00)) : \ 408 (((((c) >> 16) & 0xff) * 153 + \ 409 (((c) >> 8) & 0xff) * 301 + \ 410 (((c) ) & 0xff) * 58) >> 2)) 411 412static void 413initialize_palette (pixman_indexed_t *palette, uint32_t mask, int is_rgb) 414{ 415 int i; 416 417 for (i = 0; i < 32768; ++i) 418 palette->ent[i] = lcg_rand() & mask; 419 420 for (i = 0; i < mask + 1; ++i) 421 { 422 uint32_t rgba24; 423 pixman_bool_t retry; 424 uint32_t i15; 425 426 /* We filled the rgb->index map with random numbers, but we 427 * do need the ability to round trip, that is if some indexed 428 * color expands to an argb24, then the 15 bit version of that 429 * color must map back to the index. Anything else, we don't 430 * care about too much. 431 */ 432 do 433 { 434 uint32_t old_idx; 435 436 rgba24 = lcg_rand(); 437 i15 = CONVERT_15 (rgba24, is_rgb); 438 439 old_idx = palette->ent[i15]; 440 if (CONVERT_15 (palette->rgba[old_idx], is_rgb) == i15) 441 retry = 1; 442 else 443 retry = 0; 444 } while (retry); 445 446 palette->rgba[i] = rgba24; 447 palette->ent[i15] = i; 448 } 449 450 for (i = 0; i < mask + 1; ++i) 451 { 452 assert (palette->ent[CONVERT_15 (palette->rgba[i], is_rgb)] == i); 453 } 454} 455 456int 457main (int argc, const char *argv[]) 458{ 459 int i; 460 461 for (i = 1; i <= 8; i++) 462 { 463 initialize_palette (&(rgb_palette[i]), (1 << i) - 1, TRUE); 464 initialize_palette (&(y_palette[i]), (1 << i) - 1, FALSE); 465 } 466 467 return fuzzer_test_main("blitters", 2000000, 468 0x1DB8BDF8, 469 test_composite, argc, argv); 470} 471