scaling-test.c revision 1b18d63a
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 <assert.h> 11317c648bSmrg#include <stdlib.h> 12317c648bSmrg#include <stdio.h> 13952204abSmrg#include "utils.h" 14317c648bSmrg 151b18d63aSmrg#define MAX_SRC_WIDTH 16 161b18d63aSmrg#define MAX_SRC_HEIGHT 16 171b18d63aSmrg#define MAX_DST_WIDTH 16 181b18d63aSmrg#define MAX_DST_HEIGHT 16 19317c648bSmrg#define MAX_STRIDE 4 20317c648bSmrg 21317c648bSmrg/* 22317c648bSmrg * Composite operation with pseudorandom images 23317c648bSmrg */ 24d0321353Smrguint32_t 251b18d63aSmrgtest_composite (int testnum, 26d0321353Smrg int verbose) 27317c648bSmrg{ 28d0321353Smrg int i; 29d0321353Smrg pixman_image_t * src_img; 30d0321353Smrg pixman_image_t * dst_img; 31317c648bSmrg pixman_transform_t transform; 32d0321353Smrg pixman_region16_t clip; 33d0321353Smrg int src_width, src_height; 34d0321353Smrg int dst_width, dst_height; 35d0321353Smrg int src_stride, dst_stride; 36d0321353Smrg int src_x, src_y; 37d0321353Smrg int dst_x, dst_y; 38d0321353Smrg int src_bpp; 39d0321353Smrg int dst_bpp; 40d0321353Smrg int w, h; 411b18d63aSmrg pixman_fixed_t scale_x = 65536, scale_y = 65536; 421b18d63aSmrg pixman_fixed_t translate_x = 0, translate_y = 0; 43d0321353Smrg int op; 44d0321353Smrg int repeat = 0; 45d0321353Smrg int src_fmt, dst_fmt; 46d0321353Smrg uint32_t * srcbuf; 47d0321353Smrg uint32_t * dstbuf; 48d0321353Smrg uint32_t crc32; 491b18d63aSmrg FLOAT_REGS_CORRUPTION_DETECTOR_START (); 50d0321353Smrg 51d0321353Smrg lcg_srand (testnum); 52d0321353Smrg 53d0321353Smrg src_bpp = (lcg_rand_n (2) == 0) ? 2 : 4; 54d0321353Smrg dst_bpp = (lcg_rand_n (2) == 0) ? 2 : 4; 55d0321353Smrg op = (lcg_rand_n (2) == 0) ? PIXMAN_OP_SRC : PIXMAN_OP_OVER; 56d0321353Smrg 57d0321353Smrg src_width = lcg_rand_n (MAX_SRC_WIDTH) + 1; 58d0321353Smrg src_height = lcg_rand_n (MAX_SRC_HEIGHT) + 1; 59d0321353Smrg dst_width = lcg_rand_n (MAX_DST_WIDTH) + 1; 60d0321353Smrg dst_height = lcg_rand_n (MAX_DST_HEIGHT) + 1; 61d0321353Smrg src_stride = src_width * src_bpp + lcg_rand_n (MAX_STRIDE) * src_bpp; 62d0321353Smrg dst_stride = dst_width * dst_bpp + lcg_rand_n (MAX_STRIDE) * dst_bpp; 63d0321353Smrg 64d0321353Smrg if (src_stride & 3) 65d0321353Smrg src_stride += 2; 66952204abSmrg 67d0321353Smrg if (dst_stride & 3) 68d0321353Smrg dst_stride += 2; 69d0321353Smrg 70d0321353Smrg src_x = -(src_width / 4) + lcg_rand_n (src_width * 3 / 2); 71d0321353Smrg src_y = -(src_height / 4) + lcg_rand_n (src_height * 3 / 2); 72d0321353Smrg dst_x = -(dst_width / 4) + lcg_rand_n (dst_width * 3 / 2); 73d0321353Smrg dst_y = -(dst_height / 4) + lcg_rand_n (dst_height * 3 / 2); 74d0321353Smrg w = lcg_rand_n (dst_width * 3 / 2 - dst_x); 75d0321353Smrg h = lcg_rand_n (dst_height * 3 / 2 - dst_y); 76d0321353Smrg 77d0321353Smrg srcbuf = (uint32_t *)malloc (src_stride * src_height); 78d0321353Smrg dstbuf = (uint32_t *)malloc (dst_stride * dst_height); 79d0321353Smrg 80317c648bSmrg for (i = 0; i < src_stride * src_height; i++) 81d0321353Smrg *((uint8_t *)srcbuf + i) = lcg_rand_n (256); 82d0321353Smrg 83317c648bSmrg for (i = 0; i < dst_stride * dst_height; i++) 84d0321353Smrg *((uint8_t *)dstbuf + i) = lcg_rand_n (256); 85317c648bSmrg 86d0321353Smrg src_fmt = src_bpp == 4 ? (lcg_rand_n (2) == 0 ? 87d0321353Smrg PIXMAN_a8r8g8b8 : PIXMAN_x8r8g8b8) : PIXMAN_r5g6b5; 88317c648bSmrg 89d0321353Smrg dst_fmt = dst_bpp == 4 ? (lcg_rand_n (2) == 0 ? 90d0321353Smrg PIXMAN_a8r8g8b8 : PIXMAN_x8r8g8b8) : PIXMAN_r5g6b5; 91317c648bSmrg 92d0321353Smrg src_img = pixman_image_create_bits ( 93317c648bSmrg src_fmt, src_width, src_height, srcbuf, src_stride); 94317c648bSmrg 95d0321353Smrg dst_img = pixman_image_create_bits ( 96317c648bSmrg dst_fmt, dst_width, dst_height, dstbuf, dst_stride); 97317c648bSmrg 98d0321353Smrg image_endian_swap (src_img, src_bpp * 8); 99d0321353Smrg image_endian_swap (dst_img, dst_bpp * 8); 100d0321353Smrg 101d0321353Smrg if (lcg_rand_n (8) > 0) 102d0321353Smrg { 1031b18d63aSmrg scale_x = -32768 * 3 + lcg_rand_N (65536 * 5); 1041b18d63aSmrg scale_y = -32768 * 3 + lcg_rand_N (65536 * 5); 1051b18d63aSmrg translate_x = lcg_rand_N (65536); 1061b18d63aSmrg translate_y = lcg_rand_N (65536); 107d0321353Smrg pixman_transform_init_scale (&transform, scale_x, scale_y); 1081b18d63aSmrg pixman_transform_translate (&transform, NULL, translate_x, translate_y); 109d0321353Smrg pixman_image_set_transform (src_img, &transform); 110317c648bSmrg } 111317c648bSmrg 112d0321353Smrg switch (lcg_rand_n (4)) 113d0321353Smrg { 114d0321353Smrg case 0: 115d0321353Smrg repeat = PIXMAN_REPEAT_NONE; 116d0321353Smrg break; 117d0321353Smrg 118d0321353Smrg case 1: 119d0321353Smrg repeat = PIXMAN_REPEAT_NORMAL; 120d0321353Smrg break; 121d0321353Smrg 122d0321353Smrg case 2: 123d0321353Smrg repeat = PIXMAN_REPEAT_PAD; 124d0321353Smrg break; 125d0321353Smrg 126d0321353Smrg case 3: 127d0321353Smrg repeat = PIXMAN_REPEAT_REFLECT; 128d0321353Smrg break; 129952204abSmrg 130952204abSmrg default: 131952204abSmrg break; 132317c648bSmrg } 133d0321353Smrg pixman_image_set_repeat (src_img, repeat); 134d0321353Smrg 135952204abSmrg if (lcg_rand_n (2)) 136952204abSmrg pixman_image_set_filter (src_img, PIXMAN_FILTER_NEAREST, NULL, 0); 137952204abSmrg else 138952204abSmrg pixman_image_set_filter (src_img, PIXMAN_FILTER_BILINEAR, NULL, 0); 139952204abSmrg 140d0321353Smrg if (verbose) 141d0321353Smrg { 142d0321353Smrg printf ("src_fmt=%08X, dst_fmt=%08X\n", src_fmt, dst_fmt); 143d0321353Smrg printf ("op=%d, scale_x=%d, scale_y=%d, repeat=%d\n", 144d0321353Smrg op, scale_x, scale_y, repeat); 1451b18d63aSmrg printf ("translate_x=%d, translate_y=%d\n", 1461b18d63aSmrg translate_x, translate_y); 147d0321353Smrg printf ("src_width=%d, src_height=%d, dst_width=%d, dst_height=%d\n", 148d0321353Smrg src_width, src_height, dst_width, dst_height); 149d0321353Smrg printf ("src_x=%d, src_y=%d, dst_x=%d, dst_y=%d\n", 150d0321353Smrg src_x, src_y, dst_x, dst_y); 151d0321353Smrg printf ("w=%d, h=%d\n", w, h); 152317c648bSmrg } 153317c648bSmrg 154d0321353Smrg if (lcg_rand_n (8) == 0) 155d0321353Smrg { 156d0321353Smrg pixman_box16_t clip_boxes[2]; 157d0321353Smrg int n = lcg_rand_n (2) + 1; 158d0321353Smrg 159d0321353Smrg for (i = 0; i < n; i++) 160d0321353Smrg { 161d0321353Smrg clip_boxes[i].x1 = lcg_rand_n (src_width); 162d0321353Smrg clip_boxes[i].y1 = lcg_rand_n (src_height); 163d0321353Smrg clip_boxes[i].x2 = 164d0321353Smrg clip_boxes[i].x1 + lcg_rand_n (src_width - clip_boxes[i].x1); 165d0321353Smrg clip_boxes[i].y2 = 166d0321353Smrg clip_boxes[i].y1 + lcg_rand_n (src_height - clip_boxes[i].y1); 167d0321353Smrg 168d0321353Smrg if (verbose) 169d0321353Smrg { 170d0321353Smrg printf ("source clip box: [%d,%d-%d,%d]\n", 171d0321353Smrg clip_boxes[i].x1, clip_boxes[i].y1, 172d0321353Smrg clip_boxes[i].x2, clip_boxes[i].y2); 173d0321353Smrg } 174d0321353Smrg } 175952204abSmrg 176d0321353Smrg pixman_region_init_rects (&clip, clip_boxes, n); 177d0321353Smrg pixman_image_set_clip_region (src_img, &clip); 178d0321353Smrg pixman_image_set_source_clipping (src_img, 1); 179d0321353Smrg pixman_region_fini (&clip); 180317c648bSmrg } 181317c648bSmrg 182d0321353Smrg if (lcg_rand_n (8) == 0) 183d0321353Smrg { 184d0321353Smrg pixman_box16_t clip_boxes[2]; 185d0321353Smrg int n = lcg_rand_n (2) + 1; 186d0321353Smrg for (i = 0; i < n; i++) 187d0321353Smrg { 188d0321353Smrg clip_boxes[i].x1 = lcg_rand_n (dst_width); 189d0321353Smrg clip_boxes[i].y1 = lcg_rand_n (dst_height); 190d0321353Smrg clip_boxes[i].x2 = 191d0321353Smrg clip_boxes[i].x1 + lcg_rand_n (dst_width - clip_boxes[i].x1); 192d0321353Smrg clip_boxes[i].y2 = 193d0321353Smrg clip_boxes[i].y1 + lcg_rand_n (dst_height - clip_boxes[i].y1); 194d0321353Smrg 195d0321353Smrg if (verbose) 196d0321353Smrg { 197d0321353Smrg printf ("destination clip box: [%d,%d-%d,%d]\n", 198d0321353Smrg clip_boxes[i].x1, clip_boxes[i].y1, 199d0321353Smrg clip_boxes[i].x2, clip_boxes[i].y2); 200d0321353Smrg } 201d0321353Smrg } 202d0321353Smrg pixman_region_init_rects (&clip, clip_boxes, n); 203d0321353Smrg pixman_image_set_clip_region (dst_img, &clip); 204d0321353Smrg pixman_region_fini (&clip); 205317c648bSmrg } 206317c648bSmrg 207317c648bSmrg pixman_image_composite (op, src_img, NULL, dst_img, 208317c648bSmrg src_x, src_y, 0, 0, dst_x, dst_y, w, h); 209317c648bSmrg 210d0321353Smrg if (dst_fmt == PIXMAN_x8r8g8b8) 211d0321353Smrg { 212d0321353Smrg /* ignore unused part */ 213d0321353Smrg for (i = 0; i < dst_stride * dst_height / 4; i++) 214d0321353Smrg dstbuf[i] &= 0xFFFFFF; 215317c648bSmrg } 216317c648bSmrg 217d0321353Smrg image_endian_swap (dst_img, dst_bpp * 8); 218d0321353Smrg 219d0321353Smrg if (verbose) 220d0321353Smrg { 221d0321353Smrg int j; 222d0321353Smrg 223d0321353Smrg for (i = 0; i < dst_height; i++) 224d0321353Smrg { 225d0321353Smrg for (j = 0; j < dst_stride; j++) 226d0321353Smrg printf ("%02X ", *((uint8_t *)dstbuf + i * dst_stride + j)); 227d0321353Smrg 228d0321353Smrg printf ("\n"); 229d0321353Smrg } 230317c648bSmrg } 231317c648bSmrg 232317c648bSmrg pixman_image_unref (src_img); 233317c648bSmrg pixman_image_unref (dst_img); 234317c648bSmrg 2351b18d63aSmrg crc32 = compute_crc32 (0, dstbuf, dst_stride * dst_height); 236d0321353Smrg free (srcbuf); 237d0321353Smrg free (dstbuf); 2381b18d63aSmrg 2391b18d63aSmrg FLOAT_REGS_CORRUPTION_DETECTOR_FINISH (); 240317c648bSmrg return crc32; 241317c648bSmrg} 242317c648bSmrg 243d0321353Smrgint 2441b18d63aSmrgmain (int argc, const char *argv[]) 245317c648bSmrg{ 246d0321353Smrg pixman_disable_out_of_bounds_workaround (); 247d0321353Smrg 2481b18d63aSmrg return fuzzer_test_main("scaling", 8000000, 0x7F1AB59F, 2491b18d63aSmrg test_composite, argc, argv); 250317c648bSmrg} 251