scaling-test.c revision 6ba797d6
1/* 2 * Test program, which can detect some problems with nearest neighbour 3 * and bilinear scaling in pixman. Testing is done by running lots 4 * of random SRC and OVER compositing operations a8r8g8b8, x8a8r8g8b8 5 * and r5g6b5 color formats. 6 * 7 * Script 'fuzzer-find-diff.pl' can be used to narrow down the problem in 8 * the case of test failure. 9 */ 10#include <assert.h> 11#include <stdlib.h> 12#include <stdio.h> 13#include "utils.h" 14 15#define MAX_SRC_WIDTH 48 16#define MAX_SRC_HEIGHT 8 17#define MAX_DST_WIDTH 48 18#define MAX_DST_HEIGHT 8 19#define MAX_STRIDE 4 20 21/* 22 * Composite operation with pseudorandom images 23 */ 24uint32_t 25test_composite (int testnum, 26 int verbose) 27{ 28 int i; 29 pixman_image_t * src_img; 30 pixman_image_t * mask_img; 31 pixman_image_t * dst_img; 32 pixman_transform_t transform; 33 pixman_region16_t clip; 34 int src_width, src_height; 35 int mask_width, mask_height; 36 int dst_width, dst_height; 37 int src_stride, mask_stride, dst_stride; 38 int src_x, src_y; 39 int mask_x, mask_y; 40 int dst_x, dst_y; 41 int src_bpp; 42 int mask_bpp = 1; 43 int dst_bpp; 44 int w, h; 45 pixman_fixed_t scale_x = 65536, scale_y = 65536; 46 pixman_fixed_t translate_x = 0, translate_y = 0; 47 pixman_fixed_t mask_scale_x = 65536, mask_scale_y = 65536; 48 pixman_fixed_t mask_translate_x = 0, mask_translate_y = 0; 49 pixman_op_t op; 50 pixman_repeat_t repeat = PIXMAN_REPEAT_NONE; 51 pixman_repeat_t mask_repeat = PIXMAN_REPEAT_NONE; 52 pixman_format_code_t src_fmt, dst_fmt; 53 uint32_t * srcbuf; 54 uint32_t * dstbuf; 55 uint32_t * maskbuf; 56 uint32_t crc32; 57 FLOAT_REGS_CORRUPTION_DETECTOR_START (); 58 59 lcg_srand (testnum); 60 61 src_bpp = (lcg_rand_n (2) == 0) ? 2 : 4; 62 dst_bpp = (lcg_rand_n (2) == 0) ? 2 : 4; 63 switch (lcg_rand_n (3)) 64 { 65 case 0: 66 op = PIXMAN_OP_SRC; 67 break; 68 case 1: 69 op = PIXMAN_OP_OVER; 70 break; 71 default: 72 op = PIXMAN_OP_ADD; 73 break; 74 } 75 76 src_width = lcg_rand_n (MAX_SRC_WIDTH) + 1; 77 src_height = lcg_rand_n (MAX_SRC_HEIGHT) + 1; 78 79 if (lcg_rand_n (2)) 80 { 81 mask_width = lcg_rand_n (MAX_SRC_WIDTH) + 1; 82 mask_height = lcg_rand_n (MAX_SRC_HEIGHT) + 1; 83 } 84 else 85 { 86 mask_width = mask_height = 1; 87 } 88 89 dst_width = lcg_rand_n (MAX_DST_WIDTH) + 1; 90 dst_height = lcg_rand_n (MAX_DST_HEIGHT) + 1; 91 src_stride = src_width * src_bpp + lcg_rand_n (MAX_STRIDE) * src_bpp; 92 mask_stride = mask_width * mask_bpp + lcg_rand_n (MAX_STRIDE) * mask_bpp; 93 dst_stride = dst_width * dst_bpp + lcg_rand_n (MAX_STRIDE) * dst_bpp; 94 95 if (src_stride & 3) 96 src_stride += 2; 97 98 if (mask_stride & 1) 99 mask_stride += 1; 100 if (mask_stride & 2) 101 mask_stride += 2; 102 103 if (dst_stride & 3) 104 dst_stride += 2; 105 106 src_x = -(src_width / 4) + lcg_rand_n (src_width * 3 / 2); 107 src_y = -(src_height / 4) + lcg_rand_n (src_height * 3 / 2); 108 mask_x = -(mask_width / 4) + lcg_rand_n (mask_width * 3 / 2); 109 mask_y = -(mask_height / 4) + lcg_rand_n (mask_height * 3 / 2); 110 dst_x = -(dst_width / 4) + lcg_rand_n (dst_width * 3 / 2); 111 dst_y = -(dst_height / 4) + lcg_rand_n (dst_height * 3 / 2); 112 w = lcg_rand_n (dst_width * 3 / 2 - dst_x); 113 h = lcg_rand_n (dst_height * 3 / 2 - dst_y); 114 115 srcbuf = (uint32_t *)malloc (src_stride * src_height); 116 maskbuf = (uint32_t *)malloc (mask_stride * mask_height); 117 dstbuf = (uint32_t *)malloc (dst_stride * dst_height); 118 119 for (i = 0; i < src_stride * src_height; i++) 120 *((uint8_t *)srcbuf + i) = lcg_rand_n (256); 121 122 for (i = 0; i < mask_stride * mask_height; i++) 123 *((uint8_t *)maskbuf + i) = lcg_rand_n (256); 124 125 for (i = 0; i < dst_stride * dst_height; i++) 126 *((uint8_t *)dstbuf + i) = lcg_rand_n (256); 127 128 src_fmt = src_bpp == 4 ? (lcg_rand_n (2) == 0 ? 129 PIXMAN_a8r8g8b8 : PIXMAN_x8r8g8b8) : PIXMAN_r5g6b5; 130 131 dst_fmt = dst_bpp == 4 ? (lcg_rand_n (2) == 0 ? 132 PIXMAN_a8r8g8b8 : PIXMAN_x8r8g8b8) : PIXMAN_r5g6b5; 133 134 src_img = pixman_image_create_bits ( 135 src_fmt, src_width, src_height, srcbuf, src_stride); 136 137 mask_img = pixman_image_create_bits ( 138 PIXMAN_a8, mask_width, mask_height, maskbuf, mask_stride); 139 140 dst_img = pixman_image_create_bits ( 141 dst_fmt, dst_width, dst_height, dstbuf, dst_stride); 142 143 image_endian_swap (src_img); 144 image_endian_swap (dst_img); 145 146 if (lcg_rand_n (4) > 0) 147 { 148 scale_x = -32768 * 3 + lcg_rand_N (65536 * 5); 149 scale_y = -32768 * 3 + lcg_rand_N (65536 * 5); 150 translate_x = lcg_rand_N (65536); 151 translate_y = lcg_rand_N (65536); 152 pixman_transform_init_scale (&transform, scale_x, scale_y); 153 pixman_transform_translate (&transform, NULL, translate_x, translate_y); 154 pixman_image_set_transform (src_img, &transform); 155 } 156 157 if (lcg_rand_n (2) > 0) 158 { 159 mask_scale_x = -32768 * 3 + lcg_rand_N (65536 * 5); 160 mask_scale_y = -32768 * 3 + lcg_rand_N (65536 * 5); 161 mask_translate_x = lcg_rand_N (65536); 162 mask_translate_y = lcg_rand_N (65536); 163 pixman_transform_init_scale (&transform, mask_scale_x, mask_scale_y); 164 pixman_transform_translate (&transform, NULL, mask_translate_x, mask_translate_y); 165 pixman_image_set_transform (mask_img, &transform); 166 } 167 168 switch (lcg_rand_n (4)) 169 { 170 case 0: 171 mask_repeat = PIXMAN_REPEAT_NONE; 172 break; 173 174 case 1: 175 mask_repeat = PIXMAN_REPEAT_NORMAL; 176 break; 177 178 case 2: 179 mask_repeat = PIXMAN_REPEAT_PAD; 180 break; 181 182 case 3: 183 mask_repeat = PIXMAN_REPEAT_REFLECT; 184 break; 185 186 default: 187 break; 188 } 189 pixman_image_set_repeat (mask_img, mask_repeat); 190 191 switch (lcg_rand_n (4)) 192 { 193 case 0: 194 repeat = PIXMAN_REPEAT_NONE; 195 break; 196 197 case 1: 198 repeat = PIXMAN_REPEAT_NORMAL; 199 break; 200 201 case 2: 202 repeat = PIXMAN_REPEAT_PAD; 203 break; 204 205 case 3: 206 repeat = PIXMAN_REPEAT_REFLECT; 207 break; 208 209 default: 210 break; 211 } 212 pixman_image_set_repeat (src_img, repeat); 213 214 if (lcg_rand_n (2)) 215 pixman_image_set_filter (src_img, PIXMAN_FILTER_NEAREST, NULL, 0); 216 else 217 pixman_image_set_filter (src_img, PIXMAN_FILTER_BILINEAR, NULL, 0); 218 219 if (lcg_rand_n (2)) 220 pixman_image_set_filter (mask_img, PIXMAN_FILTER_NEAREST, NULL, 0); 221 else 222 pixman_image_set_filter (mask_img, PIXMAN_FILTER_BILINEAR, NULL, 0); 223 224 if (verbose) 225 { 226 printf ("src_fmt=%08X, dst_fmt=%08X\n", src_fmt, dst_fmt); 227 printf ("op=%d, scale_x=%d, scale_y=%d, repeat=%d\n", 228 op, scale_x, scale_y, repeat); 229 printf ("translate_x=%d, translate_y=%d\n", 230 translate_x, translate_y); 231 printf ("src_width=%d, src_height=%d, dst_width=%d, dst_height=%d\n", 232 src_width, src_height, dst_width, dst_height); 233 printf ("src_x=%d, src_y=%d, dst_x=%d, dst_y=%d\n", 234 src_x, src_y, dst_x, dst_y); 235 printf ("w=%d, h=%d\n", w, h); 236 } 237 238 if (lcg_rand_n (8) == 0) 239 { 240 pixman_box16_t clip_boxes[2]; 241 int n = lcg_rand_n (2) + 1; 242 243 for (i = 0; i < n; i++) 244 { 245 clip_boxes[i].x1 = lcg_rand_n (src_width); 246 clip_boxes[i].y1 = lcg_rand_n (src_height); 247 clip_boxes[i].x2 = 248 clip_boxes[i].x1 + lcg_rand_n (src_width - clip_boxes[i].x1); 249 clip_boxes[i].y2 = 250 clip_boxes[i].y1 + lcg_rand_n (src_height - clip_boxes[i].y1); 251 252 if (verbose) 253 { 254 printf ("source clip box: [%d,%d-%d,%d]\n", 255 clip_boxes[i].x1, clip_boxes[i].y1, 256 clip_boxes[i].x2, clip_boxes[i].y2); 257 } 258 } 259 260 pixman_region_init_rects (&clip, clip_boxes, n); 261 pixman_image_set_clip_region (src_img, &clip); 262 pixman_image_set_source_clipping (src_img, 1); 263 pixman_region_fini (&clip); 264 } 265 266 if (lcg_rand_n (8) == 0) 267 { 268 pixman_box16_t clip_boxes[2]; 269 int n = lcg_rand_n (2) + 1; 270 271 for (i = 0; i < n; i++) 272 { 273 clip_boxes[i].x1 = lcg_rand_n (mask_width); 274 clip_boxes[i].y1 = lcg_rand_n (mask_height); 275 clip_boxes[i].x2 = 276 clip_boxes[i].x1 + lcg_rand_n (mask_width - clip_boxes[i].x1); 277 clip_boxes[i].y2 = 278 clip_boxes[i].y1 + lcg_rand_n (mask_height - clip_boxes[i].y1); 279 280 if (verbose) 281 { 282 printf ("mask clip box: [%d,%d-%d,%d]\n", 283 clip_boxes[i].x1, clip_boxes[i].y1, 284 clip_boxes[i].x2, clip_boxes[i].y2); 285 } 286 } 287 288 pixman_region_init_rects (&clip, clip_boxes, n); 289 pixman_image_set_clip_region (mask_img, &clip); 290 pixman_image_set_source_clipping (mask_img, 1); 291 pixman_region_fini (&clip); 292 } 293 294 if (lcg_rand_n (8) == 0) 295 { 296 pixman_box16_t clip_boxes[2]; 297 int n = lcg_rand_n (2) + 1; 298 for (i = 0; i < n; i++) 299 { 300 clip_boxes[i].x1 = lcg_rand_n (dst_width); 301 clip_boxes[i].y1 = lcg_rand_n (dst_height); 302 clip_boxes[i].x2 = 303 clip_boxes[i].x1 + lcg_rand_n (dst_width - clip_boxes[i].x1); 304 clip_boxes[i].y2 = 305 clip_boxes[i].y1 + lcg_rand_n (dst_height - clip_boxes[i].y1); 306 307 if (verbose) 308 { 309 printf ("destination clip box: [%d,%d-%d,%d]\n", 310 clip_boxes[i].x1, clip_boxes[i].y1, 311 clip_boxes[i].x2, clip_boxes[i].y2); 312 } 313 } 314 pixman_region_init_rects (&clip, clip_boxes, n); 315 pixman_image_set_clip_region (dst_img, &clip); 316 pixman_region_fini (&clip); 317 } 318 319 if (lcg_rand_n (2) == 0) 320 pixman_image_composite (op, src_img, NULL, dst_img, 321 src_x, src_y, 0, 0, dst_x, dst_y, w, h); 322 else 323 pixman_image_composite (op, src_img, mask_img, dst_img, 324 src_x, src_y, mask_x, mask_y, dst_x, dst_y, w, h); 325 326 if (dst_fmt == PIXMAN_x8r8g8b8) 327 { 328 /* ignore unused part */ 329 for (i = 0; i < dst_stride * dst_height / 4; i++) 330 dstbuf[i] &= 0xFFFFFF; 331 } 332 333 image_endian_swap (dst_img); 334 335 if (verbose) 336 { 337 int j; 338 339 for (i = 0; i < dst_height; i++) 340 { 341 for (j = 0; j < dst_stride; j++) 342 printf ("%02X ", *((uint8_t *)dstbuf + i * dst_stride + j)); 343 344 printf ("\n"); 345 } 346 } 347 348 pixman_image_unref (src_img); 349 pixman_image_unref (mask_img); 350 pixman_image_unref (dst_img); 351 352 crc32 = compute_crc32 (0, dstbuf, dst_stride * dst_height); 353 free (srcbuf); 354 free (maskbuf); 355 free (dstbuf); 356 357 FLOAT_REGS_CORRUPTION_DETECTOR_FINISH (); 358 return crc32; 359} 360 361int 362main (int argc, const char *argv[]) 363{ 364 pixman_disable_out_of_bounds_workaround (); 365 366 return fuzzer_test_main("scaling", 8000000, 0x80DF1CB2, 367 test_composite, argc, argv); 368} 369