scaling-test.c revision 9ad247e8
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 { 299ad247e8Sjmcneill switch (lcg_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 83d0321353Smrg lcg_srand (testnum); 84d0321353Smrg 85d0321353Smrg src_bpp = (lcg_rand_n (2) == 0) ? 2 : 4; 86d0321353Smrg dst_bpp = (lcg_rand_n (2) == 0) ? 2 : 4; 876ba797d6Smrg switch (lcg_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 100d0321353Smrg src_width = lcg_rand_n (MAX_SRC_WIDTH) + 1; 101d0321353Smrg src_height = lcg_rand_n (MAX_SRC_HEIGHT) + 1; 1026ba797d6Smrg 1036ba797d6Smrg if (lcg_rand_n (2)) 1046ba797d6Smrg { 1056ba797d6Smrg mask_width = lcg_rand_n (MAX_SRC_WIDTH) + 1; 1066ba797d6Smrg mask_height = lcg_rand_n (MAX_SRC_HEIGHT) + 1; 1076ba797d6Smrg } 1086ba797d6Smrg else 1096ba797d6Smrg { 1106ba797d6Smrg mask_width = mask_height = 1; 1116ba797d6Smrg } 1126ba797d6Smrg 113d0321353Smrg dst_width = lcg_rand_n (MAX_DST_WIDTH) + 1; 114d0321353Smrg dst_height = lcg_rand_n (MAX_DST_HEIGHT) + 1; 115d0321353Smrg src_stride = src_width * src_bpp + lcg_rand_n (MAX_STRIDE) * src_bpp; 1166ba797d6Smrg mask_stride = mask_width * mask_bpp + lcg_rand_n (MAX_STRIDE) * mask_bpp; 117d0321353Smrg dst_stride = dst_width * dst_bpp + lcg_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 130d0321353Smrg src_x = -(src_width / 4) + lcg_rand_n (src_width * 3 / 2); 131d0321353Smrg src_y = -(src_height / 4) + lcg_rand_n (src_height * 3 / 2); 1326ba797d6Smrg mask_x = -(mask_width / 4) + lcg_rand_n (mask_width * 3 / 2); 1336ba797d6Smrg mask_y = -(mask_height / 4) + lcg_rand_n (mask_height * 3 / 2); 134d0321353Smrg dst_x = -(dst_width / 4) + lcg_rand_n (dst_width * 3 / 2); 135d0321353Smrg dst_y = -(dst_height / 4) + lcg_rand_n (dst_height * 3 / 2); 136d0321353Smrg w = lcg_rand_n (dst_width * 3 / 2 - dst_x); 137d0321353Smrg h = lcg_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 143317c648bSmrg for (i = 0; i < src_stride * src_height; i++) 144d0321353Smrg *((uint8_t *)srcbuf + i) = lcg_rand_n (256); 145d0321353Smrg 1466ba797d6Smrg for (i = 0; i < mask_stride * mask_height; i++) 1476ba797d6Smrg *((uint8_t *)maskbuf + i) = lcg_rand_n (256); 1486ba797d6Smrg 149317c648bSmrg for (i = 0; i < dst_stride * dst_height; i++) 150d0321353Smrg *((uint8_t *)dstbuf + i) = lcg_rand_n (256); 151317c648bSmrg 1529ad247e8Sjmcneill src_fmt = get_format (src_bpp); 1539ad247e8Sjmcneill dst_fmt = get_format (dst_bpp); 154317c648bSmrg 155d0321353Smrg src_img = pixman_image_create_bits ( 156317c648bSmrg src_fmt, src_width, src_height, srcbuf, src_stride); 157317c648bSmrg 1586ba797d6Smrg mask_img = pixman_image_create_bits ( 1596ba797d6Smrg PIXMAN_a8, mask_width, mask_height, maskbuf, mask_stride); 1606ba797d6Smrg 161d0321353Smrg dst_img = pixman_image_create_bits ( 162317c648bSmrg dst_fmt, dst_width, dst_height, dstbuf, dst_stride); 163317c648bSmrg 1646ba797d6Smrg image_endian_swap (src_img); 1656ba797d6Smrg image_endian_swap (dst_img); 166d0321353Smrg 1676ba797d6Smrg if (lcg_rand_n (4) > 0) 168d0321353Smrg { 1691b18d63aSmrg scale_x = -32768 * 3 + lcg_rand_N (65536 * 5); 1701b18d63aSmrg scale_y = -32768 * 3 + lcg_rand_N (65536 * 5); 1711b18d63aSmrg translate_x = lcg_rand_N (65536); 1721b18d63aSmrg translate_y = lcg_rand_N (65536); 173d0321353Smrg pixman_transform_init_scale (&transform, scale_x, scale_y); 1741b18d63aSmrg pixman_transform_translate (&transform, NULL, translate_x, translate_y); 175d0321353Smrg pixman_image_set_transform (src_img, &transform); 176317c648bSmrg } 177317c648bSmrg 1786ba797d6Smrg if (lcg_rand_n (2) > 0) 1796ba797d6Smrg { 1806ba797d6Smrg mask_scale_x = -32768 * 3 + lcg_rand_N (65536 * 5); 1816ba797d6Smrg mask_scale_y = -32768 * 3 + lcg_rand_N (65536 * 5); 1826ba797d6Smrg mask_translate_x = lcg_rand_N (65536); 1836ba797d6Smrg mask_translate_y = lcg_rand_N (65536); 1846ba797d6Smrg pixman_transform_init_scale (&transform, mask_scale_x, mask_scale_y); 1856ba797d6Smrg pixman_transform_translate (&transform, NULL, mask_translate_x, mask_translate_y); 1866ba797d6Smrg pixman_image_set_transform (mask_img, &transform); 1876ba797d6Smrg } 1886ba797d6Smrg 1896ba797d6Smrg switch (lcg_rand_n (4)) 1906ba797d6Smrg { 1916ba797d6Smrg case 0: 1926ba797d6Smrg mask_repeat = PIXMAN_REPEAT_NONE; 1936ba797d6Smrg break; 1946ba797d6Smrg 1956ba797d6Smrg case 1: 1966ba797d6Smrg mask_repeat = PIXMAN_REPEAT_NORMAL; 1976ba797d6Smrg break; 1986ba797d6Smrg 1996ba797d6Smrg case 2: 2006ba797d6Smrg mask_repeat = PIXMAN_REPEAT_PAD; 2016ba797d6Smrg break; 2026ba797d6Smrg 2036ba797d6Smrg case 3: 2046ba797d6Smrg mask_repeat = PIXMAN_REPEAT_REFLECT; 2056ba797d6Smrg break; 2066ba797d6Smrg 2076ba797d6Smrg default: 2086ba797d6Smrg break; 2096ba797d6Smrg } 2106ba797d6Smrg pixman_image_set_repeat (mask_img, mask_repeat); 2116ba797d6Smrg 212d0321353Smrg switch (lcg_rand_n (4)) 213d0321353Smrg { 214d0321353Smrg case 0: 215d0321353Smrg repeat = PIXMAN_REPEAT_NONE; 216d0321353Smrg break; 217d0321353Smrg 218d0321353Smrg case 1: 219d0321353Smrg repeat = PIXMAN_REPEAT_NORMAL; 220d0321353Smrg break; 221d0321353Smrg 222d0321353Smrg case 2: 223d0321353Smrg repeat = PIXMAN_REPEAT_PAD; 224d0321353Smrg break; 225d0321353Smrg 226d0321353Smrg case 3: 227d0321353Smrg repeat = PIXMAN_REPEAT_REFLECT; 228d0321353Smrg break; 229952204abSmrg 230952204abSmrg default: 231952204abSmrg break; 232317c648bSmrg } 233d0321353Smrg pixman_image_set_repeat (src_img, repeat); 234d0321353Smrg 235952204abSmrg if (lcg_rand_n (2)) 236952204abSmrg pixman_image_set_filter (src_img, PIXMAN_FILTER_NEAREST, NULL, 0); 237952204abSmrg else 238952204abSmrg pixman_image_set_filter (src_img, PIXMAN_FILTER_BILINEAR, NULL, 0); 239952204abSmrg 2406ba797d6Smrg if (lcg_rand_n (2)) 2416ba797d6Smrg pixman_image_set_filter (mask_img, PIXMAN_FILTER_NEAREST, NULL, 0); 2426ba797d6Smrg else 2436ba797d6Smrg pixman_image_set_filter (mask_img, PIXMAN_FILTER_BILINEAR, NULL, 0); 2446ba797d6Smrg 245d0321353Smrg if (verbose) 246d0321353Smrg { 247d0321353Smrg printf ("src_fmt=%08X, dst_fmt=%08X\n", src_fmt, dst_fmt); 248d0321353Smrg printf ("op=%d, scale_x=%d, scale_y=%d, repeat=%d\n", 249d0321353Smrg op, scale_x, scale_y, repeat); 2501b18d63aSmrg printf ("translate_x=%d, translate_y=%d\n", 2511b18d63aSmrg translate_x, translate_y); 252d0321353Smrg printf ("src_width=%d, src_height=%d, dst_width=%d, dst_height=%d\n", 253d0321353Smrg src_width, src_height, dst_width, dst_height); 254d0321353Smrg printf ("src_x=%d, src_y=%d, dst_x=%d, dst_y=%d\n", 255d0321353Smrg src_x, src_y, dst_x, dst_y); 256d0321353Smrg printf ("w=%d, h=%d\n", w, h); 257317c648bSmrg } 258317c648bSmrg 259d0321353Smrg if (lcg_rand_n (8) == 0) 260d0321353Smrg { 261d0321353Smrg pixman_box16_t clip_boxes[2]; 262d0321353Smrg int n = lcg_rand_n (2) + 1; 263d0321353Smrg 264d0321353Smrg for (i = 0; i < n; i++) 265d0321353Smrg { 266d0321353Smrg clip_boxes[i].x1 = lcg_rand_n (src_width); 267d0321353Smrg clip_boxes[i].y1 = lcg_rand_n (src_height); 268d0321353Smrg clip_boxes[i].x2 = 269d0321353Smrg clip_boxes[i].x1 + lcg_rand_n (src_width - clip_boxes[i].x1); 270d0321353Smrg clip_boxes[i].y2 = 271d0321353Smrg clip_boxes[i].y1 + lcg_rand_n (src_height - clip_boxes[i].y1); 272d0321353Smrg 273d0321353Smrg if (verbose) 274d0321353Smrg { 275d0321353Smrg printf ("source clip box: [%d,%d-%d,%d]\n", 276d0321353Smrg clip_boxes[i].x1, clip_boxes[i].y1, 277d0321353Smrg clip_boxes[i].x2, clip_boxes[i].y2); 278d0321353Smrg } 279d0321353Smrg } 280952204abSmrg 281d0321353Smrg pixman_region_init_rects (&clip, clip_boxes, n); 282d0321353Smrg pixman_image_set_clip_region (src_img, &clip); 283d0321353Smrg pixman_image_set_source_clipping (src_img, 1); 284d0321353Smrg pixman_region_fini (&clip); 285317c648bSmrg } 286317c648bSmrg 2876ba797d6Smrg if (lcg_rand_n (8) == 0) 2886ba797d6Smrg { 2896ba797d6Smrg pixman_box16_t clip_boxes[2]; 2906ba797d6Smrg int n = lcg_rand_n (2) + 1; 2916ba797d6Smrg 2926ba797d6Smrg for (i = 0; i < n; i++) 2936ba797d6Smrg { 2946ba797d6Smrg clip_boxes[i].x1 = lcg_rand_n (mask_width); 2956ba797d6Smrg clip_boxes[i].y1 = lcg_rand_n (mask_height); 2966ba797d6Smrg clip_boxes[i].x2 = 2976ba797d6Smrg clip_boxes[i].x1 + lcg_rand_n (mask_width - clip_boxes[i].x1); 2986ba797d6Smrg clip_boxes[i].y2 = 2996ba797d6Smrg clip_boxes[i].y1 + lcg_rand_n (mask_height - clip_boxes[i].y1); 3006ba797d6Smrg 3016ba797d6Smrg if (verbose) 3026ba797d6Smrg { 3036ba797d6Smrg printf ("mask clip box: [%d,%d-%d,%d]\n", 3046ba797d6Smrg clip_boxes[i].x1, clip_boxes[i].y1, 3056ba797d6Smrg clip_boxes[i].x2, clip_boxes[i].y2); 3066ba797d6Smrg } 3076ba797d6Smrg } 3086ba797d6Smrg 3096ba797d6Smrg pixman_region_init_rects (&clip, clip_boxes, n); 3106ba797d6Smrg pixman_image_set_clip_region (mask_img, &clip); 3116ba797d6Smrg pixman_image_set_source_clipping (mask_img, 1); 3126ba797d6Smrg pixman_region_fini (&clip); 3136ba797d6Smrg } 3146ba797d6Smrg 315d0321353Smrg if (lcg_rand_n (8) == 0) 316d0321353Smrg { 317d0321353Smrg pixman_box16_t clip_boxes[2]; 318d0321353Smrg int n = lcg_rand_n (2) + 1; 319d0321353Smrg for (i = 0; i < n; i++) 320d0321353Smrg { 321d0321353Smrg clip_boxes[i].x1 = lcg_rand_n (dst_width); 322d0321353Smrg clip_boxes[i].y1 = lcg_rand_n (dst_height); 323d0321353Smrg clip_boxes[i].x2 = 324d0321353Smrg clip_boxes[i].x1 + lcg_rand_n (dst_width - clip_boxes[i].x1); 325d0321353Smrg clip_boxes[i].y2 = 326d0321353Smrg clip_boxes[i].y1 + lcg_rand_n (dst_height - clip_boxes[i].y1); 327d0321353Smrg 328d0321353Smrg if (verbose) 329d0321353Smrg { 330d0321353Smrg printf ("destination clip box: [%d,%d-%d,%d]\n", 331d0321353Smrg clip_boxes[i].x1, clip_boxes[i].y1, 332d0321353Smrg clip_boxes[i].x2, clip_boxes[i].y2); 333d0321353Smrg } 334d0321353Smrg } 335d0321353Smrg pixman_region_init_rects (&clip, clip_boxes, n); 336d0321353Smrg pixman_image_set_clip_region (dst_img, &clip); 337d0321353Smrg pixman_region_fini (&clip); 338317c648bSmrg } 339317c648bSmrg 3406ba797d6Smrg if (lcg_rand_n (2) == 0) 3416ba797d6Smrg pixman_image_composite (op, src_img, NULL, dst_img, 342317c648bSmrg src_x, src_y, 0, 0, dst_x, dst_y, w, h); 3436ba797d6Smrg else 3446ba797d6Smrg pixman_image_composite (op, src_img, mask_img, dst_img, 3456ba797d6Smrg src_x, src_y, mask_x, mask_y, dst_x, dst_y, w, h); 346317c648bSmrg 3479ad247e8Sjmcneill if (dst_fmt == PIXMAN_x8r8g8b8 || dst_fmt == PIXMAN_x8b8g8r8) 348d0321353Smrg { 349d0321353Smrg /* ignore unused part */ 350d0321353Smrg for (i = 0; i < dst_stride * dst_height / 4; i++) 351d0321353Smrg dstbuf[i] &= 0xFFFFFF; 352317c648bSmrg } 353317c648bSmrg 3546ba797d6Smrg image_endian_swap (dst_img); 355d0321353Smrg 356d0321353Smrg if (verbose) 357d0321353Smrg { 358d0321353Smrg int j; 359d0321353Smrg 360d0321353Smrg for (i = 0; i < dst_height; i++) 361d0321353Smrg { 362d0321353Smrg for (j = 0; j < dst_stride; j++) 363d0321353Smrg printf ("%02X ", *((uint8_t *)dstbuf + i * dst_stride + j)); 364d0321353Smrg 365d0321353Smrg printf ("\n"); 366d0321353Smrg } 367317c648bSmrg } 368317c648bSmrg 369317c648bSmrg pixman_image_unref (src_img); 3706ba797d6Smrg pixman_image_unref (mask_img); 371317c648bSmrg pixman_image_unref (dst_img); 372317c648bSmrg 3731b18d63aSmrg crc32 = compute_crc32 (0, dstbuf, dst_stride * dst_height); 374d0321353Smrg free (srcbuf); 3756ba797d6Smrg free (maskbuf); 376d0321353Smrg free (dstbuf); 3771b18d63aSmrg 3781b18d63aSmrg FLOAT_REGS_CORRUPTION_DETECTOR_FINISH (); 379317c648bSmrg return crc32; 380317c648bSmrg} 381317c648bSmrg 3829ad247e8Sjmcneill#if BILINEAR_INTERPOLATION_BITS == 8 3839ad247e8Sjmcneill#define CHECKSUM 0x8D3A7539 3849ad247e8Sjmcneill#elif BILINEAR_INTERPOLATION_BITS == 7 3859ad247e8Sjmcneill#define CHECKSUM 0x03A23E0C 3869ad247e8Sjmcneill#elif BILINEAR_INTERPOLATION_BITS == 4 3879ad247e8Sjmcneill#define CHECKSUM 0xE96D1A5E 3889ad247e8Sjmcneill#else 3899ad247e8Sjmcneill#define CHECKSUM 0x00000000 3909ad247e8Sjmcneill#endif 3919ad247e8Sjmcneill 392d0321353Smrgint 3931b18d63aSmrgmain (int argc, const char *argv[]) 394317c648bSmrg{ 395d0321353Smrg pixman_disable_out_of_bounds_workaround (); 396d0321353Smrg 3979ad247e8Sjmcneill return fuzzer_test_main("scaling", 8000000, CHECKSUM, 3981b18d63aSmrg test_composite, argc, argv); 399317c648bSmrg} 400