scaling-test.c revision f4f78bb6
1317c648bSmrg/* 21b18d63aSmrg * Test program, which can detect some problems with nearest neighbour 31b18d63aSmrg * and bilinear scaling in pixman. Testing is done by running lots 41b18d63aSmrg * of random SRC and OVER compositing operations a8r8g8b8, x8a8r8g8b8 51b18d63aSmrg * and r5g6b5 color formats. 6317c648bSmrg * 71b18d63aSmrg * Script 'fuzzer-find-diff.pl' can be used to narrow down the problem in 81b18d63aSmrg * the case of test failure. 9317c648bSmrg */ 10317c648bSmrg#include <stdlib.h> 11317c648bSmrg#include <stdio.h> 12952204abSmrg#include "utils.h" 13317c648bSmrg 146ba797d6Smrg#define MAX_SRC_WIDTH 48 156ba797d6Smrg#define MAX_SRC_HEIGHT 8 166ba797d6Smrg#define MAX_DST_WIDTH 48 176ba797d6Smrg#define MAX_DST_HEIGHT 8 18317c648bSmrg#define MAX_STRIDE 4 19317c648bSmrg 20317c648bSmrg/* 21317c648bSmrg * Composite operation with pseudorandom images 22317c648bSmrg */ 239ad247e8Sjmcneill 249ad247e8Sjmcneillstatic pixman_format_code_t 259ad247e8Sjmcneillget_format (int bpp) 269ad247e8Sjmcneill{ 279ad247e8Sjmcneill if (bpp == 4) 289ad247e8Sjmcneill { 29f4f78bb6Smrg switch (prng_rand_n (4)) 309ad247e8Sjmcneill { 319ad247e8Sjmcneill default: 329ad247e8Sjmcneill case 0: 339ad247e8Sjmcneill return PIXMAN_a8r8g8b8; 349ad247e8Sjmcneill case 1: 359ad247e8Sjmcneill return PIXMAN_x8r8g8b8; 369ad247e8Sjmcneill case 2: 379ad247e8Sjmcneill return PIXMAN_a8b8g8r8; 389ad247e8Sjmcneill case 3: 399ad247e8Sjmcneill return PIXMAN_x8b8g8r8; 409ad247e8Sjmcneill } 419ad247e8Sjmcneill } 429ad247e8Sjmcneill else 439ad247e8Sjmcneill { 449ad247e8Sjmcneill return PIXMAN_r5g6b5; 459ad247e8Sjmcneill } 469ad247e8Sjmcneill} 479ad247e8Sjmcneill 48d0321353Smrguint32_t 491b18d63aSmrgtest_composite (int testnum, 50d0321353Smrg int verbose) 51317c648bSmrg{ 52d0321353Smrg int i; 53d0321353Smrg pixman_image_t * src_img; 546ba797d6Smrg pixman_image_t * mask_img; 55d0321353Smrg pixman_image_t * dst_img; 56317c648bSmrg pixman_transform_t transform; 57d0321353Smrg pixman_region16_t clip; 58d0321353Smrg int src_width, src_height; 596ba797d6Smrg int mask_width, mask_height; 60d0321353Smrg int dst_width, dst_height; 616ba797d6Smrg int src_stride, mask_stride, dst_stride; 62d0321353Smrg int src_x, src_y; 636ba797d6Smrg int mask_x, mask_y; 64d0321353Smrg int dst_x, dst_y; 65d0321353Smrg int src_bpp; 666ba797d6Smrg int mask_bpp = 1; 67d0321353Smrg int dst_bpp; 68d0321353Smrg int w, h; 691b18d63aSmrg pixman_fixed_t scale_x = 65536, scale_y = 65536; 701b18d63aSmrg pixman_fixed_t translate_x = 0, translate_y = 0; 716ba797d6Smrg pixman_fixed_t mask_scale_x = 65536, mask_scale_y = 65536; 726ba797d6Smrg pixman_fixed_t mask_translate_x = 0, mask_translate_y = 0; 736ba797d6Smrg pixman_op_t op; 746ba797d6Smrg pixman_repeat_t repeat = PIXMAN_REPEAT_NONE; 756ba797d6Smrg pixman_repeat_t mask_repeat = PIXMAN_REPEAT_NONE; 766ba797d6Smrg pixman_format_code_t src_fmt, dst_fmt; 77d0321353Smrg uint32_t * srcbuf; 78d0321353Smrg uint32_t * dstbuf; 796ba797d6Smrg uint32_t * maskbuf; 80d0321353Smrg uint32_t crc32; 811b18d63aSmrg FLOAT_REGS_CORRUPTION_DETECTOR_START (); 82d0321353Smrg 83f4f78bb6Smrg prng_srand (testnum); 84d0321353Smrg 85f4f78bb6Smrg src_bpp = (prng_rand_n (2) == 0) ? 2 : 4; 86f4f78bb6Smrg dst_bpp = (prng_rand_n (2) == 0) ? 2 : 4; 87f4f78bb6Smrg switch (prng_rand_n (3)) 886ba797d6Smrg { 896ba797d6Smrg case 0: 906ba797d6Smrg op = PIXMAN_OP_SRC; 916ba797d6Smrg break; 926ba797d6Smrg case 1: 936ba797d6Smrg op = PIXMAN_OP_OVER; 946ba797d6Smrg break; 956ba797d6Smrg default: 966ba797d6Smrg op = PIXMAN_OP_ADD; 976ba797d6Smrg break; 986ba797d6Smrg } 99d0321353Smrg 100f4f78bb6Smrg src_width = prng_rand_n (MAX_SRC_WIDTH) + 1; 101f4f78bb6Smrg src_height = prng_rand_n (MAX_SRC_HEIGHT) + 1; 1026ba797d6Smrg 103f4f78bb6Smrg if (prng_rand_n (2)) 1046ba797d6Smrg { 105f4f78bb6Smrg mask_width = prng_rand_n (MAX_SRC_WIDTH) + 1; 106f4f78bb6Smrg mask_height = prng_rand_n (MAX_SRC_HEIGHT) + 1; 1076ba797d6Smrg } 1086ba797d6Smrg else 1096ba797d6Smrg { 1106ba797d6Smrg mask_width = mask_height = 1; 1116ba797d6Smrg } 1126ba797d6Smrg 113f4f78bb6Smrg dst_width = prng_rand_n (MAX_DST_WIDTH) + 1; 114f4f78bb6Smrg dst_height = prng_rand_n (MAX_DST_HEIGHT) + 1; 115f4f78bb6Smrg src_stride = src_width * src_bpp + prng_rand_n (MAX_STRIDE) * src_bpp; 116f4f78bb6Smrg mask_stride = mask_width * mask_bpp + prng_rand_n (MAX_STRIDE) * mask_bpp; 117f4f78bb6Smrg dst_stride = dst_width * dst_bpp + prng_rand_n (MAX_STRIDE) * dst_bpp; 118d0321353Smrg 119d0321353Smrg if (src_stride & 3) 120d0321353Smrg src_stride += 2; 121952204abSmrg 1226ba797d6Smrg if (mask_stride & 1) 1236ba797d6Smrg mask_stride += 1; 1246ba797d6Smrg if (mask_stride & 2) 1256ba797d6Smrg mask_stride += 2; 1266ba797d6Smrg 127d0321353Smrg if (dst_stride & 3) 128d0321353Smrg dst_stride += 2; 129d0321353Smrg 130f4f78bb6Smrg src_x = -(src_width / 4) + prng_rand_n (src_width * 3 / 2); 131f4f78bb6Smrg src_y = -(src_height / 4) + prng_rand_n (src_height * 3 / 2); 132f4f78bb6Smrg mask_x = -(mask_width / 4) + prng_rand_n (mask_width * 3 / 2); 133f4f78bb6Smrg mask_y = -(mask_height / 4) + prng_rand_n (mask_height * 3 / 2); 134f4f78bb6Smrg dst_x = -(dst_width / 4) + prng_rand_n (dst_width * 3 / 2); 135f4f78bb6Smrg dst_y = -(dst_height / 4) + prng_rand_n (dst_height * 3 / 2); 136f4f78bb6Smrg w = prng_rand_n (dst_width * 3 / 2 - dst_x); 137f4f78bb6Smrg h = prng_rand_n (dst_height * 3 / 2 - dst_y); 138d0321353Smrg 139d0321353Smrg srcbuf = (uint32_t *)malloc (src_stride * src_height); 1406ba797d6Smrg maskbuf = (uint32_t *)malloc (mask_stride * mask_height); 141d0321353Smrg dstbuf = (uint32_t *)malloc (dst_stride * dst_height); 142d0321353Smrg 143f4f78bb6Smrg prng_randmemset (srcbuf, src_stride * src_height, 0); 144f4f78bb6Smrg prng_randmemset (maskbuf, mask_stride * mask_height, 0); 145f4f78bb6Smrg prng_randmemset (dstbuf, dst_stride * dst_height, 0); 146317c648bSmrg 1479ad247e8Sjmcneill src_fmt = get_format (src_bpp); 1489ad247e8Sjmcneill dst_fmt = get_format (dst_bpp); 149317c648bSmrg 150d0321353Smrg src_img = pixman_image_create_bits ( 151317c648bSmrg src_fmt, src_width, src_height, srcbuf, src_stride); 152317c648bSmrg 1536ba797d6Smrg mask_img = pixman_image_create_bits ( 1546ba797d6Smrg PIXMAN_a8, mask_width, mask_height, maskbuf, mask_stride); 1556ba797d6Smrg 156d0321353Smrg dst_img = pixman_image_create_bits ( 157317c648bSmrg dst_fmt, dst_width, dst_height, dstbuf, dst_stride); 158317c648bSmrg 1596ba797d6Smrg image_endian_swap (src_img); 1606ba797d6Smrg image_endian_swap (dst_img); 161d0321353Smrg 162f4f78bb6Smrg if (prng_rand_n (4) > 0) 163d0321353Smrg { 164f4f78bb6Smrg scale_x = -32768 * 3 + prng_rand_n (65536 * 5); 165f4f78bb6Smrg scale_y = -32768 * 3 + prng_rand_n (65536 * 5); 166f4f78bb6Smrg translate_x = prng_rand_n (65536); 167f4f78bb6Smrg translate_y = prng_rand_n (65536); 168d0321353Smrg pixman_transform_init_scale (&transform, scale_x, scale_y); 1691b18d63aSmrg pixman_transform_translate (&transform, NULL, translate_x, translate_y); 170d0321353Smrg pixman_image_set_transform (src_img, &transform); 171317c648bSmrg } 172317c648bSmrg 173f4f78bb6Smrg if (prng_rand_n (2) > 0) 1746ba797d6Smrg { 175f4f78bb6Smrg mask_scale_x = -32768 * 3 + prng_rand_n (65536 * 5); 176f4f78bb6Smrg mask_scale_y = -32768 * 3 + prng_rand_n (65536 * 5); 177f4f78bb6Smrg mask_translate_x = prng_rand_n (65536); 178f4f78bb6Smrg mask_translate_y = prng_rand_n (65536); 1796ba797d6Smrg pixman_transform_init_scale (&transform, mask_scale_x, mask_scale_y); 1806ba797d6Smrg pixman_transform_translate (&transform, NULL, mask_translate_x, mask_translate_y); 1816ba797d6Smrg pixman_image_set_transform (mask_img, &transform); 1826ba797d6Smrg } 1836ba797d6Smrg 184f4f78bb6Smrg switch (prng_rand_n (4)) 1856ba797d6Smrg { 1866ba797d6Smrg case 0: 1876ba797d6Smrg mask_repeat = PIXMAN_REPEAT_NONE; 1886ba797d6Smrg break; 1896ba797d6Smrg 1906ba797d6Smrg case 1: 1916ba797d6Smrg mask_repeat = PIXMAN_REPEAT_NORMAL; 1926ba797d6Smrg break; 1936ba797d6Smrg 1946ba797d6Smrg case 2: 1956ba797d6Smrg mask_repeat = PIXMAN_REPEAT_PAD; 1966ba797d6Smrg break; 1976ba797d6Smrg 1986ba797d6Smrg case 3: 1996ba797d6Smrg mask_repeat = PIXMAN_REPEAT_REFLECT; 2006ba797d6Smrg break; 2016ba797d6Smrg 2026ba797d6Smrg default: 2036ba797d6Smrg break; 2046ba797d6Smrg } 2056ba797d6Smrg pixman_image_set_repeat (mask_img, mask_repeat); 2066ba797d6Smrg 207f4f78bb6Smrg switch (prng_rand_n (4)) 208d0321353Smrg { 209d0321353Smrg case 0: 210d0321353Smrg repeat = PIXMAN_REPEAT_NONE; 211d0321353Smrg break; 212d0321353Smrg 213d0321353Smrg case 1: 214d0321353Smrg repeat = PIXMAN_REPEAT_NORMAL; 215d0321353Smrg break; 216d0321353Smrg 217d0321353Smrg case 2: 218d0321353Smrg repeat = PIXMAN_REPEAT_PAD; 219d0321353Smrg break; 220d0321353Smrg 221d0321353Smrg case 3: 222d0321353Smrg repeat = PIXMAN_REPEAT_REFLECT; 223d0321353Smrg break; 224952204abSmrg 225952204abSmrg default: 226952204abSmrg break; 227317c648bSmrg } 228d0321353Smrg pixman_image_set_repeat (src_img, repeat); 229d0321353Smrg 230f4f78bb6Smrg if (prng_rand_n (2)) 231952204abSmrg pixman_image_set_filter (src_img, PIXMAN_FILTER_NEAREST, NULL, 0); 232952204abSmrg else 233952204abSmrg pixman_image_set_filter (src_img, PIXMAN_FILTER_BILINEAR, NULL, 0); 234952204abSmrg 235f4f78bb6Smrg if (prng_rand_n (2)) 2366ba797d6Smrg pixman_image_set_filter (mask_img, PIXMAN_FILTER_NEAREST, NULL, 0); 2376ba797d6Smrg else 2386ba797d6Smrg pixman_image_set_filter (mask_img, PIXMAN_FILTER_BILINEAR, NULL, 0); 2396ba797d6Smrg 240d0321353Smrg if (verbose) 241d0321353Smrg { 242f4f78bb6Smrg printf ("src_fmt=%s, dst_fmt=%s\n", 243f4f78bb6Smrg format_name (src_fmt), format_name (dst_fmt)); 244f4f78bb6Smrg printf ("op=%s, scale_x=%d, scale_y=%d, repeat=%d\n", 245f4f78bb6Smrg operator_name (op), scale_x, scale_y, repeat); 2461b18d63aSmrg printf ("translate_x=%d, translate_y=%d\n", 2471b18d63aSmrg translate_x, translate_y); 248d0321353Smrg printf ("src_width=%d, src_height=%d, dst_width=%d, dst_height=%d\n", 249d0321353Smrg src_width, src_height, dst_width, dst_height); 250d0321353Smrg printf ("src_x=%d, src_y=%d, dst_x=%d, dst_y=%d\n", 251d0321353Smrg src_x, src_y, dst_x, dst_y); 252d0321353Smrg printf ("w=%d, h=%d\n", w, h); 253317c648bSmrg } 254317c648bSmrg 255f4f78bb6Smrg if (prng_rand_n (8) == 0) 256d0321353Smrg { 257d0321353Smrg pixman_box16_t clip_boxes[2]; 258f4f78bb6Smrg int n = prng_rand_n (2) + 1; 259d0321353Smrg 260d0321353Smrg for (i = 0; i < n; i++) 261d0321353Smrg { 262f4f78bb6Smrg clip_boxes[i].x1 = prng_rand_n (src_width); 263f4f78bb6Smrg clip_boxes[i].y1 = prng_rand_n (src_height); 264d0321353Smrg clip_boxes[i].x2 = 265f4f78bb6Smrg clip_boxes[i].x1 + prng_rand_n (src_width - clip_boxes[i].x1); 266d0321353Smrg clip_boxes[i].y2 = 267f4f78bb6Smrg clip_boxes[i].y1 + prng_rand_n (src_height - clip_boxes[i].y1); 268d0321353Smrg 269d0321353Smrg if (verbose) 270d0321353Smrg { 271d0321353Smrg printf ("source clip box: [%d,%d-%d,%d]\n", 272d0321353Smrg clip_boxes[i].x1, clip_boxes[i].y1, 273d0321353Smrg clip_boxes[i].x2, clip_boxes[i].y2); 274d0321353Smrg } 275d0321353Smrg } 276952204abSmrg 277d0321353Smrg pixman_region_init_rects (&clip, clip_boxes, n); 278d0321353Smrg pixman_image_set_clip_region (src_img, &clip); 279d0321353Smrg pixman_image_set_source_clipping (src_img, 1); 280d0321353Smrg pixman_region_fini (&clip); 281317c648bSmrg } 282317c648bSmrg 283f4f78bb6Smrg if (prng_rand_n (8) == 0) 2846ba797d6Smrg { 2856ba797d6Smrg pixman_box16_t clip_boxes[2]; 286f4f78bb6Smrg int n = prng_rand_n (2) + 1; 2876ba797d6Smrg 2886ba797d6Smrg for (i = 0; i < n; i++) 2896ba797d6Smrg { 290f4f78bb6Smrg clip_boxes[i].x1 = prng_rand_n (mask_width); 291f4f78bb6Smrg clip_boxes[i].y1 = prng_rand_n (mask_height); 2926ba797d6Smrg clip_boxes[i].x2 = 293f4f78bb6Smrg clip_boxes[i].x1 + prng_rand_n (mask_width - clip_boxes[i].x1); 2946ba797d6Smrg clip_boxes[i].y2 = 295f4f78bb6Smrg clip_boxes[i].y1 + prng_rand_n (mask_height - clip_boxes[i].y1); 2966ba797d6Smrg 2976ba797d6Smrg if (verbose) 2986ba797d6Smrg { 2996ba797d6Smrg printf ("mask clip box: [%d,%d-%d,%d]\n", 3006ba797d6Smrg clip_boxes[i].x1, clip_boxes[i].y1, 3016ba797d6Smrg clip_boxes[i].x2, clip_boxes[i].y2); 3026ba797d6Smrg } 3036ba797d6Smrg } 3046ba797d6Smrg 3056ba797d6Smrg pixman_region_init_rects (&clip, clip_boxes, n); 3066ba797d6Smrg pixman_image_set_clip_region (mask_img, &clip); 3076ba797d6Smrg pixman_image_set_source_clipping (mask_img, 1); 3086ba797d6Smrg pixman_region_fini (&clip); 3096ba797d6Smrg } 3106ba797d6Smrg 311f4f78bb6Smrg if (prng_rand_n (8) == 0) 312d0321353Smrg { 313d0321353Smrg pixman_box16_t clip_boxes[2]; 314f4f78bb6Smrg int n = prng_rand_n (2) + 1; 315d0321353Smrg for (i = 0; i < n; i++) 316d0321353Smrg { 317f4f78bb6Smrg clip_boxes[i].x1 = prng_rand_n (dst_width); 318f4f78bb6Smrg clip_boxes[i].y1 = prng_rand_n (dst_height); 319d0321353Smrg clip_boxes[i].x2 = 320f4f78bb6Smrg clip_boxes[i].x1 + prng_rand_n (dst_width - clip_boxes[i].x1); 321d0321353Smrg clip_boxes[i].y2 = 322f4f78bb6Smrg clip_boxes[i].y1 + prng_rand_n (dst_height - clip_boxes[i].y1); 323d0321353Smrg 324d0321353Smrg if (verbose) 325d0321353Smrg { 326d0321353Smrg printf ("destination clip box: [%d,%d-%d,%d]\n", 327d0321353Smrg clip_boxes[i].x1, clip_boxes[i].y1, 328d0321353Smrg clip_boxes[i].x2, clip_boxes[i].y2); 329d0321353Smrg } 330d0321353Smrg } 331d0321353Smrg pixman_region_init_rects (&clip, clip_boxes, n); 332d0321353Smrg pixman_image_set_clip_region (dst_img, &clip); 333d0321353Smrg pixman_region_fini (&clip); 334317c648bSmrg } 335317c648bSmrg 336f4f78bb6Smrg if (prng_rand_n (2) == 0) 3376ba797d6Smrg pixman_image_composite (op, src_img, NULL, dst_img, 338317c648bSmrg src_x, src_y, 0, 0, dst_x, dst_y, w, h); 3396ba797d6Smrg else 3406ba797d6Smrg pixman_image_composite (op, src_img, mask_img, dst_img, 3416ba797d6Smrg src_x, src_y, mask_x, mask_y, dst_x, dst_y, w, h); 342317c648bSmrg 3439ad247e8Sjmcneill if (dst_fmt == PIXMAN_x8r8g8b8 || dst_fmt == PIXMAN_x8b8g8r8) 344d0321353Smrg { 345d0321353Smrg /* ignore unused part */ 346d0321353Smrg for (i = 0; i < dst_stride * dst_height / 4; i++) 347d0321353Smrg dstbuf[i] &= 0xFFFFFF; 348317c648bSmrg } 349317c648bSmrg 3506ba797d6Smrg image_endian_swap (dst_img); 351d0321353Smrg 352d0321353Smrg if (verbose) 353d0321353Smrg { 354d0321353Smrg int j; 355d0321353Smrg 356d0321353Smrg for (i = 0; i < dst_height; i++) 357d0321353Smrg { 358d0321353Smrg for (j = 0; j < dst_stride; j++) 359d0321353Smrg printf ("%02X ", *((uint8_t *)dstbuf + i * dst_stride + j)); 360d0321353Smrg 361d0321353Smrg printf ("\n"); 362d0321353Smrg } 363317c648bSmrg } 364317c648bSmrg 365317c648bSmrg pixman_image_unref (src_img); 3666ba797d6Smrg pixman_image_unref (mask_img); 367317c648bSmrg pixman_image_unref (dst_img); 368317c648bSmrg 3691b18d63aSmrg crc32 = compute_crc32 (0, dstbuf, dst_stride * dst_height); 370d0321353Smrg free (srcbuf); 3716ba797d6Smrg free (maskbuf); 372d0321353Smrg free (dstbuf); 3731b18d63aSmrg 3741b18d63aSmrg FLOAT_REGS_CORRUPTION_DETECTOR_FINISH (); 375317c648bSmrg return crc32; 376317c648bSmrg} 377317c648bSmrg 3789ad247e8Sjmcneill#if BILINEAR_INTERPOLATION_BITS == 8 379f4f78bb6Smrg#define CHECKSUM 0x9096E6B6 3809ad247e8Sjmcneill#elif BILINEAR_INTERPOLATION_BITS == 7 381f4f78bb6Smrg#define CHECKSUM 0xCE8EC6BA 3829ad247e8Sjmcneill#elif BILINEAR_INTERPOLATION_BITS == 4 383f4f78bb6Smrg#define CHECKSUM 0xAB1D39BE 3849ad247e8Sjmcneill#else 3859ad247e8Sjmcneill#define CHECKSUM 0x00000000 3869ad247e8Sjmcneill#endif 3879ad247e8Sjmcneill 388d0321353Smrgint 3891b18d63aSmrgmain (int argc, const char *argv[]) 390317c648bSmrg{ 391d0321353Smrg pixman_disable_out_of_bounds_workaround (); 392d0321353Smrg 3939ad247e8Sjmcneill return fuzzer_test_main("scaling", 8000000, CHECKSUM, 3941b18d63aSmrg test_composite, argc, argv); 395317c648bSmrg} 396