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 <stdlib.h> 9 #include <stdio.h> 10 #include "utils.h" 11 12 static pixman_indexed_t rgb_palette[9]; 13 static pixman_indexed_t y_palette[9]; 14 15 /* The first eight format in the list are by far the most widely 16 * used formats, so we test those more than the others 17 */ 18 #define N_MOST_LIKELY_FORMATS 8 19 20 /* Create random image for testing purposes */ 21 static pixman_image_t * 22 create_random_image (pixman_format_code_t *allowed_formats, 23 int max_width, 24 int max_height, 25 int max_extra_stride, 26 pixman_format_code_t *used_fmt) 27 { 28 int n = 0, width, height, stride; 29 pixman_format_code_t fmt; 30 uint32_t *buf; 31 pixman_image_t *img; 32 33 while (allowed_formats[n] != PIXMAN_null) 34 n++; 35 36 if (n > N_MOST_LIKELY_FORMATS && prng_rand_n (4) != 0) 37 n = N_MOST_LIKELY_FORMATS; 38 fmt = allowed_formats[prng_rand_n (n)]; 39 40 width = prng_rand_n (max_width) + 1; 41 height = prng_rand_n (max_height) + 1; 42 stride = (width * PIXMAN_FORMAT_BPP (fmt) + 7) / 8 + 43 prng_rand_n (max_extra_stride + 1); 44 stride = (stride + 3) & ~3; 45 46 /* do the allocation */ 47 buf = aligned_malloc (64, stride * height); 48 49 if (prng_rand_n (4) == 0) 50 { 51 /* uniform distribution */ 52 prng_randmemset (buf, stride * height, 0); 53 } 54 else 55 { 56 /* significantly increased probability for 0x00 and 0xFF */ 57 prng_randmemset (buf, stride * height, RANDMEMSET_MORE_00_AND_FF); 58 } 59 60 img = pixman_image_create_bits (fmt, width, height, buf, stride); 61 62 if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_COLOR) 63 { 64 pixman_image_set_indexed (img, &(rgb_palette[PIXMAN_FORMAT_BPP (fmt)])); 65 } 66 else if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_GRAY) 67 { 68 pixman_image_set_indexed (img, &(y_palette[PIXMAN_FORMAT_BPP (fmt)])); 69 } 70 71 if (prng_rand_n (16) == 0) 72 pixman_image_set_filter (img, PIXMAN_FILTER_BILINEAR, NULL, 0); 73 74 image_endian_swap (img); 75 76 if (used_fmt) *used_fmt = fmt; 77 return img; 78 } 79 80 /* Free random image, and optionally update crc32 based on its data */ 81 static uint32_t 82 free_random_image (uint32_t initcrc, 83 pixman_image_t *img, 84 pixman_format_code_t fmt) 85 { 86 uint32_t crc32 = 0; 87 uint32_t *data = pixman_image_get_data (img); 88 89 if (fmt != PIXMAN_null) 90 crc32 = compute_crc32_for_image (initcrc, img); 91 92 pixman_image_unref (img); 93 free (data); 94 95 return crc32; 96 } 97 98 static pixman_op_t op_list[] = { 99 PIXMAN_OP_SRC, 100 PIXMAN_OP_OVER, 101 PIXMAN_OP_ADD, 102 PIXMAN_OP_CLEAR, 103 PIXMAN_OP_SRC, 104 PIXMAN_OP_DST, 105 PIXMAN_OP_OVER, 106 PIXMAN_OP_OVER_REVERSE, 107 PIXMAN_OP_IN, 108 PIXMAN_OP_IN_REVERSE, 109 PIXMAN_OP_OUT, 110 PIXMAN_OP_OUT_REVERSE, 111 PIXMAN_OP_ATOP, 112 PIXMAN_OP_ATOP_REVERSE, 113 PIXMAN_OP_XOR, 114 PIXMAN_OP_ADD, 115 PIXMAN_OP_SATURATE, 116 PIXMAN_OP_DISJOINT_CLEAR, 117 PIXMAN_OP_DISJOINT_SRC, 118 PIXMAN_OP_DISJOINT_DST, 119 PIXMAN_OP_DISJOINT_OVER, 120 PIXMAN_OP_DISJOINT_OVER_REVERSE, 121 PIXMAN_OP_DISJOINT_IN, 122 PIXMAN_OP_DISJOINT_IN_REVERSE, 123 PIXMAN_OP_DISJOINT_OUT, 124 PIXMAN_OP_DISJOINT_OUT_REVERSE, 125 PIXMAN_OP_DISJOINT_ATOP, 126 PIXMAN_OP_DISJOINT_ATOP_REVERSE, 127 PIXMAN_OP_DISJOINT_XOR, 128 PIXMAN_OP_CONJOINT_CLEAR, 129 PIXMAN_OP_CONJOINT_SRC, 130 PIXMAN_OP_CONJOINT_DST, 131 PIXMAN_OP_CONJOINT_OVER, 132 PIXMAN_OP_CONJOINT_OVER_REVERSE, 133 PIXMAN_OP_CONJOINT_IN, 134 PIXMAN_OP_CONJOINT_IN_REVERSE, 135 PIXMAN_OP_CONJOINT_OUT, 136 PIXMAN_OP_CONJOINT_OUT_REVERSE, 137 PIXMAN_OP_CONJOINT_ATOP, 138 PIXMAN_OP_CONJOINT_ATOP_REVERSE, 139 PIXMAN_OP_CONJOINT_XOR, 140 PIXMAN_OP_MULTIPLY, 141 PIXMAN_OP_SCREEN, 142 PIXMAN_OP_OVERLAY, 143 PIXMAN_OP_DARKEN, 144 PIXMAN_OP_LIGHTEN, 145 PIXMAN_OP_COLOR_DODGE, 146 PIXMAN_OP_COLOR_BURN, 147 PIXMAN_OP_HARD_LIGHT, 148 PIXMAN_OP_DIFFERENCE, 149 PIXMAN_OP_EXCLUSION, 150 #if 0 /* these use floating point math and are not always bitexact on different platforms */ 151 PIXMAN_OP_SOFT_LIGHT, 152 PIXMAN_OP_HSL_HUE, 153 PIXMAN_OP_HSL_SATURATION, 154 PIXMAN_OP_HSL_COLOR, 155 PIXMAN_OP_HSL_LUMINOSITY, 156 #endif 157 }; 158 159 static pixman_format_code_t img_fmt_list[] = { 160 PIXMAN_a8r8g8b8, 161 PIXMAN_a8b8g8r8, 162 PIXMAN_x8r8g8b8, 163 PIXMAN_x8b8g8r8, 164 PIXMAN_r5g6b5, 165 PIXMAN_b5g6r5, 166 PIXMAN_a8, 167 PIXMAN_a1, 168 PIXMAN_r3g3b2, 169 PIXMAN_b8g8r8a8, 170 PIXMAN_b8g8r8x8, 171 PIXMAN_r8g8b8a8, 172 PIXMAN_r8g8b8x8, 173 PIXMAN_x14r6g6b6, 174 PIXMAN_r8g8b8, 175 PIXMAN_b8g8r8, 176 #if 0 /* These are going to use floating point in the near future */ 177 PIXMAN_x2r10g10b10, 178 PIXMAN_a2r10g10b10, 179 PIXMAN_x2b10g10r10, 180 PIXMAN_a2b10g10r10, 181 #endif 182 PIXMAN_a1r5g5b5, 183 PIXMAN_x1r5g5b5, 184 PIXMAN_a1b5g5r5, 185 PIXMAN_x1b5g5r5, 186 PIXMAN_a4r4g4b4, 187 PIXMAN_x4r4g4b4, 188 PIXMAN_a4b4g4r4, 189 PIXMAN_x4b4g4r4, 190 PIXMAN_r3g3b2, 191 PIXMAN_b2g3r3, 192 PIXMAN_a2r2g2b2, 193 PIXMAN_a2b2g2r2, 194 PIXMAN_c8, 195 PIXMAN_g8, 196 PIXMAN_x4c4, 197 PIXMAN_x4g4, 198 PIXMAN_c4, 199 PIXMAN_g4, 200 PIXMAN_g1, 201 PIXMAN_x4a4, 202 PIXMAN_a4, 203 PIXMAN_r1g2b1, 204 PIXMAN_b1g2r1, 205 PIXMAN_a1r1g1b1, 206 PIXMAN_a1b1g1r1, 207 PIXMAN_null 208 }; 209 210 static pixman_format_code_t mask_fmt_list[] = { 211 PIXMAN_a8r8g8b8, 212 PIXMAN_a8, 213 PIXMAN_a4, 214 PIXMAN_a1, 215 PIXMAN_null 216 }; 217 218 219 /* 220 * Composite operation with pseudorandom images 221 */ 222 uint32_t 223 test_composite (int testnum, int verbose) 224 { 225 int i; 226 pixman_image_t *src_img = NULL; 227 pixman_image_t *dst_img = NULL; 228 pixman_image_t *mask_img = NULL; 229 int src_width, src_height; 230 int dst_width, dst_height; 231 int src_stride, dst_stride; 232 int src_x, src_y; 233 int dst_x, dst_y; 234 int mask_x, mask_y; 235 int w, h; 236 pixman_op_t op; 237 pixman_format_code_t src_fmt, dst_fmt, mask_fmt; 238 uint32_t *dstbuf, *srcbuf, *maskbuf; 239 uint32_t crc32; 240 int max_width, max_height, max_extra_stride; 241 FLOAT_REGS_CORRUPTION_DETECTOR_START (); 242 243 max_width = max_height = 24 + testnum / 10000; 244 max_extra_stride = 4 + testnum / 1000000; 245 246 if (max_width > 256) 247 max_width = 256; 248 249 if (max_height > 16) 250 max_height = 16; 251 252 if (max_extra_stride > 8) 253 max_extra_stride = 8; 254 255 prng_srand (testnum); 256 257 op = op_list[prng_rand_n (ARRAY_LENGTH (op_list))]; 258 259 if (prng_rand_n (8)) 260 { 261 /* normal image */ 262 src_img = create_random_image (img_fmt_list, max_width, max_height, 263 max_extra_stride, &src_fmt); 264 } 265 else 266 { 267 /* solid case */ 268 src_img = create_random_image (img_fmt_list, 1, 1, 269 max_extra_stride, &src_fmt); 270 271 pixman_image_set_repeat (src_img, PIXMAN_REPEAT_NORMAL); 272 } 273 274 dst_img = create_random_image (img_fmt_list, max_width, max_height, 275 max_extra_stride, &dst_fmt); 276 277 src_width = pixman_image_get_width (src_img); 278 src_height = pixman_image_get_height (src_img); 279 src_stride = pixman_image_get_stride (src_img); 280 281 dst_width = pixman_image_get_width (dst_img); 282 dst_height = pixman_image_get_height (dst_img); 283 dst_stride = pixman_image_get_stride (dst_img); 284 285 dstbuf = pixman_image_get_data (dst_img); 286 srcbuf = pixman_image_get_data (src_img); 287 288 src_x = prng_rand_n (src_width); 289 src_y = prng_rand_n (src_height); 290 dst_x = prng_rand_n (dst_width); 291 dst_y = prng_rand_n (dst_height); 292 293 mask_img = NULL; 294 mask_fmt = PIXMAN_null; 295 mask_x = 0; 296 mask_y = 0; 297 maskbuf = NULL; 298 299 if ((src_fmt == PIXMAN_x8r8g8b8 || src_fmt == PIXMAN_x8b8g8r8) && 300 (prng_rand_n (4) == 0)) 301 { 302 /* PIXBUF */ 303 mask_fmt = prng_rand_n (2) ? PIXMAN_a8r8g8b8 : PIXMAN_a8b8g8r8; 304 mask_img = pixman_image_create_bits (mask_fmt, 305 src_width, 306 src_height, 307 srcbuf, 308 src_stride); 309 mask_x = src_x; 310 mask_y = src_y; 311 maskbuf = srcbuf; 312 } 313 else if (prng_rand_n (2)) 314 { 315 if (prng_rand_n (2)) 316 { 317 mask_img = create_random_image (mask_fmt_list, max_width, max_height, 318 max_extra_stride, &mask_fmt); 319 } 320 else 321 { 322 /* solid case */ 323 mask_img = create_random_image (mask_fmt_list, 1, 1, 324 max_extra_stride, &mask_fmt); 325 pixman_image_set_repeat (mask_img, PIXMAN_REPEAT_NORMAL); 326 } 327 328 if (prng_rand_n (2)) 329 pixman_image_set_component_alpha (mask_img, 1); 330 331 mask_x = prng_rand_n (pixman_image_get_width (mask_img)); 332 mask_y = prng_rand_n (pixman_image_get_height (mask_img)); 333 } 334 335 336 w = prng_rand_n (dst_width - dst_x + 1); 337 h = prng_rand_n (dst_height - dst_y + 1); 338 339 if (verbose) 340 { 341 printf ("op=%s\n", operator_name (op)); 342 printf ("src_fmt=%s, dst_fmt=%s, mask_fmt=%s\n", 343 format_name (src_fmt), format_name (dst_fmt), 344 format_name (mask_fmt)); 345 printf ("src_width=%d, src_height=%d, dst_width=%d, dst_height=%d\n", 346 src_width, src_height, dst_width, dst_height); 347 printf ("src_x=%d, src_y=%d, dst_x=%d, dst_y=%d\n", 348 src_x, src_y, dst_x, dst_y); 349 printf ("src_stride=%d, dst_stride=%d\n", 350 src_stride, dst_stride); 351 printf ("w=%d, h=%d\n", w, h); 352 } 353 354 pixman_image_composite (op, src_img, mask_img, dst_img, 355 src_x, src_y, mask_x, mask_y, dst_x, dst_y, w, h); 356 357 if (verbose) 358 { 359 int j; 360 361 printf ("---\n"); 362 for (i = 0; i < dst_height; i++) 363 { 364 for (j = 0; j < dst_stride; j++) 365 { 366 if (j == (dst_width * PIXMAN_FORMAT_BPP (dst_fmt) + 7) / 8) 367 printf ("| "); 368 369 printf ("%02X ", *((uint8_t *)dstbuf + i * dst_stride + j)); 370 } 371 printf ("\n"); 372 } 373 printf ("---\n"); 374 } 375 376 free_random_image (0, src_img, PIXMAN_null); 377 crc32 = free_random_image (0, dst_img, dst_fmt); 378 379 if (mask_img) 380 { 381 if (srcbuf == maskbuf) 382 pixman_image_unref(mask_img); 383 else 384 free_random_image (0, mask_img, PIXMAN_null); 385 } 386 387 FLOAT_REGS_CORRUPTION_DETECTOR_FINISH (); 388 return crc32; 389 } 390 391 int 392 main (int argc, const char *argv[]) 393 { 394 int i; 395 396 prng_srand (0); 397 398 for (i = 1; i <= 8; i++) 399 { 400 initialize_palette (&(rgb_palette[i]), i, TRUE); 401 initialize_palette (&(y_palette[i]), i, FALSE); 402 } 403 404 return fuzzer_test_main("blitters", 2000000, 405 0x0CF3283B, 406 test_composite, argc, argv); 407 } 408