/* * Test program, which rasterizes lots of polygons and computes a CRC32 * value for all the results. Based on scaling-test. */ #include #include #include #include "utils.h" /* FIXME: we should really test bigger polygons here, but currently * the rasterization algorithm is really slow with long edges */ #define MAX_POLY_WIDTH (1 << 22) #define MAX_POLY_HEIGHT (1 << 22) #define MAX_DST_WIDTH 45 #define MAX_DST_HEIGHT 45 #define MAX_STRIDE 4 static pixman_image_t * generate_random_polygon (int width, int height, int verbose) { pixman_image_t *poly; int n_edges = lcg_rand_n (20); polygon_builder_t builder; double last_x, last_y; int i; int r; polygon_builder_init (&builder); r = lcg_rand_N (width) - width / 2; last_x = (r * 0.88); last_y = ((int)lcg_rand_N (height) - height / 2) * 0.43; polygon_builder_move_to (&builder, last_x, last_y); for (i = 0; i < n_edges; ++i) { double dx, dy; switch (lcg_rand_n (8)) { case 0: /* Vertical */ dx = 0; dy = ((int)lcg_rand_N (height) - height / 2) * 0.92; break; case 1: /* Almost vertical */ dx = 0.005; dy = ((int)lcg_rand_N (height) - height / 2) * 0.77; break; case 2: /* Horizontal */ dx = ((int)lcg_rand_N (width) - width / 2) * 0.97; dy = 0; break; case 3: /* Almost horizontal */ dy = 0.005; dx = ((int)lcg_rand_N (width) - width / 2) * 0.94; break; default: /* Random */ dx = ((int)lcg_rand_N (width) - width / 2) * 0.93; dy = ((int)lcg_rand_N (height) - height / 2) * 0.99; break; } if (last_x + dx > (1 << 22)) dx = (1 << 22) - last_x; if (last_x + dx < -(1 << 22)) dx = -(1 << 22) - last_x; if (last_y + dy > (1 << 22)) dy = (1 << 22) - last_y; if (last_y + dy < -(1 << 22)) dy = -(1 << 22) - last_y; polygon_builder_line_to (&builder, last_x + dx, last_y + dy); last_x += dx; last_y += dy; } poly = polygon_builder_get_polygon (&builder, lcg_rand_n (2), verbose); pixman_image_set_resample (poly, lcg_rand_n (3)); return poly; } /* * Composite operation with pseudorandom images */ static uint32_t test_polygon (int testnum, int verbose) { int i; pixman_image_t * poly_img; pixman_image_t * dst_img; pixman_region16_t clip; int poly_width, poly_height; int dst_width, dst_height; int dst_stride; int poly_x, poly_y; int dst_x, dst_y; int dst_bpp; int w, h; int op; int dst_fmt; uint32_t * dstbuf; uint32_t crc32; static const pixman_op_t ops[] = { PIXMAN_OP_SRC, PIXMAN_OP_OVER, PIXMAN_OP_ATOP, PIXMAN_OP_OUT, PIXMAN_OP_OUT_REVERSE, PIXMAN_OP_IN, PIXMAN_OP_OVER_REVERSE, PIXMAN_OP_IN_REVERSE }; FLOAT_REGS_CORRUPTION_DETECTOR_START (); lcg_srand (testnum); dst_bpp = (1 << (lcg_rand_n (3))); /* 1, 2, or 4 */ op = ops[lcg_rand_n (ARRAY_LENGTH (ops))]; poly_width = lcg_rand_N (MAX_POLY_WIDTH) + 1; poly_height = lcg_rand_N (MAX_POLY_HEIGHT) + 1; dst_width = lcg_rand_n (MAX_DST_WIDTH) + 1; dst_height = lcg_rand_n (MAX_DST_HEIGHT) + 1; dst_stride = dst_width * dst_bpp + lcg_rand_n (MAX_STRIDE) * dst_bpp; dst_stride = (dst_stride + 3) & ~3; poly_x = -(poly_width / 4) + lcg_rand_N (poly_width * 3 / 2); poly_y = -(poly_height / 4) + lcg_rand_N (poly_height * 3 / 2); dst_x = -(dst_width / 4) + lcg_rand_n (dst_width * 3 / 2); dst_y = -(dst_height / 4) + lcg_rand_n (dst_height * 3 / 2); w = lcg_rand_n (dst_width * 3 / 2 - dst_x); h = lcg_rand_n (dst_height * 3 / 2 - dst_y); dstbuf = (uint32_t *)malloc (dst_stride * dst_height); for (i = 0; i < dst_stride * dst_height; i++) *((uint8_t *)dstbuf + i) = lcg_rand_n (256); switch (dst_bpp) { default: case 1: dst_fmt = PIXMAN_a8; break; case 2: dst_fmt = PIXMAN_r5g6b5; break; case 4: dst_fmt = (lcg_rand_n (2) == 0 ? PIXMAN_a8r8g8b8 : PIXMAN_x8r8g8b8); break; } dst_img = pixman_image_create_bits ( dst_fmt, dst_width, dst_height, dstbuf, dst_stride); assert (dst_img); image_endian_swap (dst_img); if (verbose) { printf ("dst_fmt=%08X\n", dst_fmt); printf ("op=%d\n", op); printf ("poly_width=%d, poly_height=%d, dst_width=%d, dst_height=%d\n", poly_width, poly_height, dst_width, dst_height); printf ("poly_x=%d, poly_y=%d, dst_x=%d, dst_y=%d\n", poly_x, poly_y, dst_x, dst_y); printf ("w=%d, h=%d\n", w, h); } if (lcg_rand_n (8) == 0) { pixman_box16_t clip_boxes[8]; int n = lcg_rand_n (8) + 1; for (i = 0; i < n; i++) { clip_boxes[i].x1 = lcg_rand_n (dst_width); clip_boxes[i].y1 = lcg_rand_n (dst_height); clip_boxes[i].x2 = clip_boxes[i].x1 + lcg_rand_n (dst_width - clip_boxes[i].x1); clip_boxes[i].y2 = clip_boxes[i].y1 + lcg_rand_n (dst_height - clip_boxes[i].y1); if (verbose) { printf ("destination clip box: [%d,%d-%d,%d]\n", clip_boxes[i].x1, clip_boxes[i].y1, clip_boxes[i].x2, clip_boxes[i].y2); } } pixman_region_init_rects (&clip, clip_boxes, n); pixman_image_set_clip_region (dst_img, &clip); pixman_region_fini (&clip); } poly_img = generate_random_polygon (poly_width, poly_height, verbose); pixman_image_composite (op, poly_img, NULL, dst_img, poly_x, poly_y, 0, 0, dst_x, dst_y, w, h); if (dst_fmt == PIXMAN_x8r8g8b8) { /* ignore unused part */ for (i = 0; i < dst_stride * dst_height / 4; i++) dstbuf[i] &= 0xFFFFFF; } image_endian_swap (dst_img); if (verbose) { int j; for (i = 0; i < dst_height; i++) { for (j = 0; j < dst_stride; j++) printf ("%02X ", *((uint8_t *)dstbuf + i * dst_stride + j)); printf ("\n"); } } pixman_image_unref (poly_img); pixman_image_unref (dst_img); crc32 = compute_crc32 (0, dstbuf, dst_stride * dst_height); free (dstbuf); FLOAT_REGS_CORRUPTION_DETECTOR_FINISH (); return crc32; } int main (int argc, const char *argv[]) { pixman_disable_out_of_bounds_workaround (); return fuzzer_test_main("polygon rasterization", 300000, 0xBE6AEE4B, test_polygon, argc, argv); }