예제 #1
0
/*
 * Composite operation with pseudorandom images
 */
uint32_t
test_composite (int      testnum,
		int      verbose)
{
    int                i;
    pixman_image_t *   src_img;
    pixman_image_t *   dst_img;
    pixman_transform_t transform;
    pixman_region16_t  clip;
    int                src_width, src_height;
    int                dst_width, dst_height;
    int                src_stride, dst_stride;
    int                src_x, src_y;
    int                dst_x, dst_y;
    int                src_bpp;
    int                dst_bpp;
    int                w, h;
    pixman_fixed_t     scale_x = 65536, scale_y = 65536;
    pixman_fixed_t     translate_x = 0, translate_y = 0;
    int                op;
    int                repeat = 0;
    int                src_fmt, dst_fmt;
    uint32_t *         srcbuf;
    uint32_t *         dstbuf;
    uint32_t           crc32;

    lcg_srand (testnum);

    src_bpp = (lcg_rand_n (2) == 0) ? 2 : 4;
    dst_bpp = (lcg_rand_n (2) == 0) ? 2 : 4;
    op = (lcg_rand_n (2) == 0) ? PIXMAN_OP_SRC : PIXMAN_OP_OVER;

    src_width = lcg_rand_n (MAX_SRC_WIDTH) + 1;
    src_height = lcg_rand_n (MAX_SRC_HEIGHT) + 1;
    dst_width = lcg_rand_n (MAX_DST_WIDTH) + 1;
    dst_height = lcg_rand_n (MAX_DST_HEIGHT) + 1;
    src_stride = src_width * src_bpp + lcg_rand_n (MAX_STRIDE) * src_bpp;
    dst_stride = dst_width * dst_bpp + lcg_rand_n (MAX_STRIDE) * dst_bpp;

    if (src_stride & 3)
	src_stride += 2;

    if (dst_stride & 3)
	dst_stride += 2;

    src_x = -(src_width / 4) + lcg_rand_n (src_width * 3 / 2);
    src_y = -(src_height / 4) + lcg_rand_n (src_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);

    srcbuf = (uint32_t *)malloc (src_stride * src_height);
    dstbuf = (uint32_t *)malloc (dst_stride * dst_height);

    for (i = 0; i < src_stride * src_height; i++)
	*((uint8_t *)srcbuf + i) = lcg_rand_n (256);

    for (i = 0; i < dst_stride * dst_height; i++)
	*((uint8_t *)dstbuf + i) = lcg_rand_n (256);

    src_fmt = src_bpp == 4 ? (lcg_rand_n (2) == 0 ?
                              PIXMAN_a8r8g8b8 : PIXMAN_x8r8g8b8) : PIXMAN_r5g6b5;

    dst_fmt = dst_bpp == 4 ? (lcg_rand_n (2) == 0 ?
                              PIXMAN_a8r8g8b8 : PIXMAN_x8r8g8b8) : PIXMAN_r5g6b5;

    src_img = pixman_image_create_bits (
        src_fmt, src_width, src_height, srcbuf, src_stride);

    dst_img = pixman_image_create_bits (
        dst_fmt, dst_width, dst_height, dstbuf, dst_stride);

    image_endian_swap (src_img, src_bpp * 8);
    image_endian_swap (dst_img, dst_bpp * 8);

    if (lcg_rand_n (8) > 0)
    {
	scale_x = -32768 * 3 + lcg_rand_N (65536 * 5);
	scale_y = -32768 * 3 + lcg_rand_N (65536 * 5);
	translate_x = lcg_rand_N (65536);
	translate_y = lcg_rand_N (65536);
	pixman_transform_init_scale (&transform, scale_x, scale_y);
	pixman_transform_translate (&transform, NULL, translate_x, translate_y);
	pixman_image_set_transform (src_img, &transform);
    }

    switch (lcg_rand_n (4))
    {
    case 0:
	repeat = PIXMAN_REPEAT_NONE;
	break;

    case 1:
	repeat = PIXMAN_REPEAT_NORMAL;
	break;

    case 2:
	repeat = PIXMAN_REPEAT_PAD;
	break;

    case 3:
	repeat = PIXMAN_REPEAT_REFLECT;
	break;

    default:
        break;
    }
    pixman_image_set_repeat (src_img, repeat);

    if (lcg_rand_n (2))
	pixman_image_set_filter (src_img, PIXMAN_FILTER_NEAREST, NULL, 0);
    else
	pixman_image_set_filter (src_img, PIXMAN_FILTER_BILINEAR, NULL, 0);

    if (verbose)
    {
	printf ("src_fmt=%08X, dst_fmt=%08X\n", src_fmt, dst_fmt);
	printf ("op=%d, scale_x=%d, scale_y=%d, repeat=%d\n",
	        op, scale_x, scale_y, repeat);
	printf ("translate_x=%d, translate_y=%d\n",
	        translate_x, translate_y);
	printf ("src_width=%d, src_height=%d, dst_width=%d, dst_height=%d\n",
	        src_width, src_height, dst_width, dst_height);
	printf ("src_x=%d, src_y=%d, dst_x=%d, dst_y=%d\n",
	        src_x, src_y, dst_x, dst_y);
	printf ("w=%d, h=%d\n", w, h);
    }

    if (lcg_rand_n (8) == 0)
    {
	pixman_box16_t clip_boxes[2];
	int            n = lcg_rand_n (2) + 1;

	for (i = 0; i < n; i++)
	{
	    clip_boxes[i].x1 = lcg_rand_n (src_width);
	    clip_boxes[i].y1 = lcg_rand_n (src_height);
	    clip_boxes[i].x2 =
		clip_boxes[i].x1 + lcg_rand_n (src_width - clip_boxes[i].x1);
	    clip_boxes[i].y2 =
		clip_boxes[i].y1 + lcg_rand_n (src_height - clip_boxes[i].y1);

	    if (verbose)
	    {
		printf ("source 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 (src_img, &clip);
	pixman_image_set_source_clipping (src_img, 1);
	pixman_region_fini (&clip);
    }

    if (lcg_rand_n (8) == 0)
    {
	pixman_box16_t clip_boxes[2];
	int            n = lcg_rand_n (2) + 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);
    }

    pixman_image_composite (op, src_img, NULL, dst_img,
                            src_x, src_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, dst_bpp * 8);

    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 (src_img);
    pixman_image_unref (dst_img);

    crc32 = compute_crc32 (0, dstbuf, dst_stride * dst_height);
    free (srcbuf);
    free (dstbuf);
    return crc32;
}
예제 #2
0
/*
 * Composite operation with pseudorandom images
 */
uint32_t
test_composite (int      testnum,
		int      verbose)
{
    int                i;
    pixman_image_t *   src_img;
    pixman_image_t *   dst_img;
    pixman_region16_t  clip;
    int                dst_width, dst_height;
    int                dst_stride;
    int                dst_x, dst_y;
    int                dst_bpp;
    pixman_op_t        op;
    uint32_t *         dst_bits;
    uint32_t           crc32;
    pixman_format_code_t mask_format, dst_format;
    pixman_trapezoid_t *traps;
    int src_x, src_y;
    int n_traps;

    static pixman_color_t colors[] =
    {
	{ 0xffff, 0xffff, 0xffff, 0xffff },
	{ 0x0000, 0x0000, 0x0000, 0x0000 },
	{ 0xabcd, 0xabcd, 0x0000, 0xabcd },
	{ 0x0000, 0x0000, 0x0000, 0xffff },
	{ 0x0101, 0x0101, 0x0101, 0x0101 },
	{ 0x7777, 0x6666, 0x5555, 0x9999 },
    };
    
    FLOAT_REGS_CORRUPTION_DETECTOR_START ();

    lcg_srand (testnum);

    op = RANDOM_ELT (operators);
    mask_format = RANDOM_ELT (mask_formats);

    /* Create source image */
    
    if (lcg_rand_n (4) == 0)
    {
	src_img = pixman_image_create_solid_fill (
	    &(colors[lcg_rand_n (ARRAY_LENGTH (colors))]));

	src_x = 10;
	src_y = 234;
    }
    else
    {
	pixman_format_code_t src_format = RANDOM_ELT(formats);
	int src_bpp = (PIXMAN_FORMAT_BPP (src_format) + 7) / 8;
	int src_width = lcg_rand_n (MAX_SRC_WIDTH) + 1;
	int src_height = lcg_rand_n (MAX_SRC_HEIGHT) + 1;
	int src_stride = src_width * src_bpp + lcg_rand_n (MAX_STRIDE) * src_bpp;
	uint32_t *bits;

	src_x = -(src_width / 4) + lcg_rand_n (src_width * 3 / 2);
	src_y = -(src_height / 4) + lcg_rand_n (src_height * 3 / 2);

	src_stride = (src_stride + 3) & ~3;
	
	bits = (uint32_t *)make_random_bytes (src_stride * src_height);

	src_img = pixman_image_create_bits (
	    src_format, src_width, src_height, bits, src_stride);

	pixman_image_set_destroy_function (src_img, destroy_bits, bits);

	if (lcg_rand_n (8) == 0)
	{
	    pixman_box16_t clip_boxes[2];
	    int            n = lcg_rand_n (2) + 1;
	    
	    for (i = 0; i < n; i++)
	    {
		clip_boxes[i].x1 = lcg_rand_n (src_width);
		clip_boxes[i].y1 = lcg_rand_n (src_height);
		clip_boxes[i].x2 =
		    clip_boxes[i].x1 + lcg_rand_n (src_width - clip_boxes[i].x1);
		clip_boxes[i].y2 =
		    clip_boxes[i].y1 + lcg_rand_n (src_height - clip_boxes[i].y1);
		
		if (verbose)
		{
		    printf ("source 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 (src_img, &clip);
	    pixman_image_set_source_clipping (src_img, 1);
	    pixman_region_fini (&clip);
	}

	image_endian_swap (src_img);
    }

    /* Create destination image */
    {
	dst_format = RANDOM_ELT(formats);
	dst_bpp = (PIXMAN_FORMAT_BPP (dst_format) + 7) / 8;
	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;
	
	dst_bits = (uint32_t *)make_random_bytes (dst_stride * dst_height);

	dst_x = -(dst_width / 4) + lcg_rand_n (dst_width * 3 / 2);
	dst_y = -(dst_height / 4) + lcg_rand_n (dst_height * 3 / 2);
	
	dst_img = pixman_image_create_bits (
	    dst_format, dst_width, dst_height, dst_bits, dst_stride);

	image_endian_swap (dst_img);
    }

    /* Create traps */
    {
	int i;

	n_traps = lcg_rand_n (25);
	traps = fence_malloc (n_traps * sizeof (pixman_trapezoid_t));

	for (i = 0; i < n_traps; ++i)
	{
	    pixman_trapezoid_t *t = &(traps[i]);
	    
	    t->top = random_fixed (MAX_DST_HEIGHT) - MAX_DST_HEIGHT / 2;
	    t->bottom = t->top + random_fixed (MAX_DST_HEIGHT);
	    t->left.p1.x = random_fixed (MAX_DST_WIDTH) - MAX_DST_WIDTH / 2;
	    t->left.p1.y = t->top - random_fixed (50);
	    t->left.p2.x = random_fixed (MAX_DST_WIDTH) - MAX_DST_WIDTH / 2;
	    t->left.p2.y = t->bottom + random_fixed (50);
	    t->right.p1.x = t->left.p1.x + random_fixed (MAX_DST_WIDTH);
	    t->right.p1.y = t->top - random_fixed (50);
	    t->right.p2.x = t->left.p2.x + random_fixed (MAX_DST_WIDTH);
	    t->right.p2.y = t->bottom - random_fixed (50);
	}
    }
    
    if (lcg_rand_n (8) == 0)
    {
	pixman_box16_t clip_boxes[2];
	int            n = lcg_rand_n (2) + 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);
    }

    pixman_composite_trapezoids (op, src_img, dst_img, mask_format,
				 src_x, src_y, dst_x, dst_y, n_traps, traps);

    if (dst_format == PIXMAN_x8r8g8b8)
    {
	/* ignore unused part */
	for (i = 0; i < dst_stride * dst_height / 4; i++)
	    dst_bits[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 *)dst_bits + i * dst_stride + j));

	    printf ("\n");
	}
    }

    crc32 = compute_crc32 (0, dst_bits, dst_stride * dst_height);

    fence_free (dst_bits);
    
    pixman_image_unref (src_img);
    pixman_image_unref (dst_img);
    fence_free (traps);

    FLOAT_REGS_CORRUPTION_DETECTOR_FINISH ();
    return crc32;
}
예제 #3
0
static bool
sna_tiling_blt_copy_boxes__with_alpha(struct sna *sna, uint8_t alu,
				      struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
				      struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
				      int bpp, int alpha_fixup,
				      const BoxRec *box, int nbox)
{
	RegionRec region, tile, this;
	struct kgem_bo *bo;
	int max_size, step;
	bool ret = false;

	if (wedged(sna) ||
	    !kgem_bo_can_blt(&sna->kgem, src_bo) ||
	    !kgem_bo_can_blt(&sna->kgem, dst_bo)) {
		/* XXX */
		DBG(("%s: tiling blt fail: src?=%d, dst?=%d\n",
		     __FUNCTION__,
		     kgem_bo_can_blt(&sna->kgem, src_bo),
		     kgem_bo_can_blt(&sna->kgem, dst_bo)));
		return false;
	}

	max_size = sna->kgem.aperture_high * PAGE_SIZE;
	max_size -= MAX(kgem_bo_size(src_bo), kgem_bo_size(dst_bo));
	if (max_size <= 0) {
		DBG(("%s: tiles cannot fit into aperture\n", __FUNCTION__));
		return false;
	}
	if (max_size > sna->kgem.max_copy_tile_size)
		max_size = sna->kgem.max_copy_tile_size;

	pixman_region_init_rects(&region, box, nbox);

	/* Use a small step to accommodate enlargement through tile alignment */
	step = sna->render.max_3d_size;
	if (region.extents.x1 & (8*512 / bpp - 1) || region.extents.y1 & 63)
		step /= 2;
	while (step * step * 4 > max_size)
		step /= 2;
	if (sna->kgem.gen < 033)
		step /= 2; /* accommodate severe fence restrictions */
	if (step == 0) {
		DBG(("%s: tiles cannot fit into aperture\n", __FUNCTION__));
		return false;
	}

	DBG(("%s (alu=%d), tile.size=%d, box=%dx[(%d, %d), (%d, %d)])\n",
	     __FUNCTION__, alu, step, nbox,
	     region.extents.x1, region.extents.y1,
	     region.extents.x2, region.extents.y2));

	for (tile.extents.y1 = tile.extents.y2 = region.extents.y1;
	     tile.extents.y2 < region.extents.y2;
	     tile.extents.y1 = tile.extents.y2) {
		int y2 = tile.extents.y1 + step;
		if (y2 > region.extents.y2)
			y2 = region.extents.y2;
		tile.extents.y2 = y2;

		for (tile.extents.x1 = tile.extents.x2 = region.extents.x1;
		     tile.extents.x2 < region.extents.x2;
		     tile.extents.x1 = tile.extents.x2) {
			int w, h;
			int x2 = tile.extents.x1 + step;
			if (x2 > region.extents.x2)
				x2 = region.extents.x2;
			tile.extents.x2 = x2;

			tile.data = NULL;

			RegionNull(&this);
			RegionIntersect(&this, &region, &tile);
			if (RegionNil(&this))
				continue;

			w = this.extents.x2 - this.extents.x1;
			h = this.extents.y2 - this.extents.y1;
			bo = kgem_create_2d(&sna->kgem, w, h, bpp,
					    kgem_choose_tiling(&sna->kgem,
							       I915_TILING_X,
							       w, h, bpp),
					    CREATE_TEMPORARY);
			if (bo) {
				int16_t dx = this.extents.x1;
				int16_t dy = this.extents.y1;

				assert(bo->pitch <= 8192);
				assert(bo->tiling != I915_TILING_Y);

				if (!sna_blt_copy_boxes(sna, GXcopy,
							src_bo, src_dx, src_dy,
							bo, -dx, -dy,
							bpp, REGION_RECTS(&this), REGION_NUM_RECTS(&this)))
					goto err;

				if (!sna_blt_copy_boxes__with_alpha(sna, alu,
								    bo, -dx, -dy,
								    dst_bo, dst_dx, dst_dy,
								    bpp, alpha_fixup,
								    REGION_RECTS(&this), REGION_NUM_RECTS(&this)))
					goto err;

				kgem_bo_destroy(&sna->kgem, bo);
			}
			RegionUninit(&this);
		}
	}

	ret = true;
	goto done;
err:
	kgem_bo_destroy(&sna->kgem, bo);
	RegionUninit(&this);
done:
	pixman_region_fini(&region);
	return ret;
}
예제 #4
0
bool
sna_tiling_fill_boxes(struct sna *sna,
		      CARD8 op,
		      PictFormat format,
		      const xRenderColor *color,
		      PixmapPtr dst, struct kgem_bo *dst_bo,
		      const BoxRec *box, int n)
{
	RegionRec region, tile, this;
	struct kgem_bo *bo;
	int step;
	bool ret = false;

	pixman_region_init_rects(&region, box, n);

	/* Use a small step to accommodate enlargement through tile alignment */
	step = sna->render.max_3d_size;
	if (region.extents.x1 & (8*512 / dst->drawable.bitsPerPixel - 1) ||
	    region.extents.y1 & 63)
		step /= 2;
	while (step * step * 4 > sna->kgem.max_copy_tile_size)
		step /= 2;

	DBG(("%s (op=%d, format=%x, color=(%04x,%04x,%04x, %04x), tile.size=%d, box=%dx[(%d, %d), (%d, %d)])\n",
	     __FUNCTION__, op, (int)format,
	     color->red, color->green, color->blue, color->alpha,
	     step, n,
	     region.extents.x1, region.extents.y1,
	     region.extents.x2, region.extents.y2));

	for (tile.extents.y1 = tile.extents.y2 = region.extents.y1;
	     tile.extents.y2 < region.extents.y2;
	     tile.extents.y1 = tile.extents.y2) {
		int y2 = tile.extents.y1 + step;
		if (y2 > region.extents.y2)
			y2 = region.extents.y2;
		tile.extents.y2 = y2;

		for (tile.extents.x1 = tile.extents.x2 = region.extents.x1;
		     tile.extents.x2 < region.extents.x2;
		     tile.extents.x1 = tile.extents.x2) {
			PixmapRec tmp;
			int x2 = tile.extents.x1 + step;
			if (x2 > region.extents.x2)
				x2 = region.extents.x2;
			tile.extents.x2 = x2;

			tile.data = NULL;

			RegionNull(&this);
			RegionIntersect(&this, &region, &tile);
			if (RegionNil(&this))
				continue;

			tmp.drawable.width  = this.extents.x2 - this.extents.x1;
			tmp.drawable.height = this.extents.y2 - this.extents.y1;
			tmp.drawable.depth  = dst->drawable.depth;
			tmp.drawable.bitsPerPixel = dst->drawable.bitsPerPixel;
			tmp.devPrivate.ptr = NULL;

			bo = kgem_create_2d(&sna->kgem,
					    tmp.drawable.width,
					    tmp.drawable.height,
					    dst->drawable.bitsPerPixel,
					    kgem_choose_tiling(&sna->kgem,
							       I915_TILING_X,
							       tmp.drawable.width,
							       tmp.drawable.height,
							       dst->drawable.bitsPerPixel),
					    CREATE_TEMPORARY);
			if (bo) {
				int16_t dx = this.extents.x1;
				int16_t dy = this.extents.y1;

				assert(kgem_bo_can_blt(&sna->kgem, bo));

				if (!sna->render.copy_boxes(sna, GXcopy,
							     dst, dst_bo, 0, 0,
							     &tmp, bo, -dx, -dy,
							     REGION_RECTS(&this), REGION_NUM_RECTS(&this), 0))
					goto err;

				RegionTranslate(&this, -dx, -dy);
				if (!sna->render.fill_boxes(sna, op, format, color,
							     &tmp, bo,
							     REGION_RECTS(&this), REGION_NUM_RECTS(&this)))
					goto err;

				if (!sna->render.copy_boxes(sna, GXcopy,
							     &tmp, bo, 0, 0,
							     dst, dst_bo, dx, dy,
							     REGION_RECTS(&this), REGION_NUM_RECTS(&this), 0))
					goto err;

				kgem_bo_destroy(&sna->kgem, bo);
			}
			RegionUninit(&this);
		}
	}

	ret = true;
	goto done;
err:
	kgem_bo_destroy(&sna->kgem, bo);
	RegionUninit(&this);
done:
	pixman_region_fini(&region);
	return ret;
}
예제 #5
0
/**
 * _cairo_traps_extract_region:
 * @traps: a #cairo_traps_t
 * @region: on return, %NULL is stored here if the trapezoids aren't
 *          exactly representable as a pixman region, otherwise a
 *          a pointer to such a region, newly allocated.
 *          (free with pixman region destroy)
 *
 * Determines if a set of trapezoids are exactly representable as a
 * pixman region, and if so creates such a region.
 *
 * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_INT_STATUS_UNSUPPORTED
 * or %CAIRO_STATUS_NO_MEMORY
 **/
cairo_int_status_t
_cairo_traps_extract_region (cairo_traps_t     *traps,
			     pixman_region16_t *region)
{
#define NUM_STATIC_BOXES 16
    pixman_box16_t static_boxes[NUM_STATIC_BOXES];
    pixman_box16_t *boxes;
    int i, box_count;
    pixman_region_status_t status;

    for (i = 0; i < traps->num_traps; i++)
	if (!(traps->traps[i].left.p1.x == traps->traps[i].left.p2.x
	      && traps->traps[i].right.p1.x == traps->traps[i].right.p2.x
	      && _cairo_fixed_is_integer(traps->traps[i].top)
	      && _cairo_fixed_is_integer(traps->traps[i].bottom)
	      && _cairo_fixed_is_integer(traps->traps[i].left.p1.x)
	      && _cairo_fixed_is_integer(traps->traps[i].right.p1.x))) {
	    return CAIRO_INT_STATUS_UNSUPPORTED;
	}

    if (traps->num_traps <= NUM_STATIC_BOXES) {
	boxes = static_boxes;
    } else {
	/*boxes = _cairo_malloc2 (traps->num_traps, sizeof(pixman_box16_t));*/
	boxes = malloc (traps->num_traps * sizeof(pixman_box16_t));

	if (boxes == NULL)
	    return CAIRO_STATUS_NO_MEMORY;
    }

    box_count = 0;

    for (i = 0; i < traps->num_traps; i++) {
	int x1 = _cairo_fixed_integer_part(traps->traps[i].left.p1.x);
	int y1 = _cairo_fixed_integer_part(traps->traps[i].top);
	int x2 = _cairo_fixed_integer_part(traps->traps[i].right.p1.x);
	int y2 = _cairo_fixed_integer_part(traps->traps[i].bottom);

	/* XXX: Sometimes we get degenerate trapezoids from the tesellator;
	 * skip these.
	 */
	if (x1 == x2 || y1 == y2)
	  continue;

	boxes[box_count].x1 = (short) x1;
	boxes[box_count].y1 = (short) y1;
	boxes[box_count].x2 = (short) x2;
	boxes[box_count].y2 = (short) y2;

	box_count++;
    }

    status = pixman_region_init_rects (region, boxes, box_count);

    if (boxes != static_boxes)
	free (boxes);

    if (status != PIXMAN_REGION_STATUS_SUCCESS) {
	    pixman_region_fini (region);
		return CAIRO_INT_STATUS_UNSUPPORTED;
    }

    return CAIRO_STATUS_SUCCESS;
}
예제 #6
0
static pixman_image_t *
create_image (int max_size, const pixman_format_code_t *formats, uint32_t flags)
{
    int width, height;
    pixman_image_t *image;
    pixman_format_code_t format;
    uint32_t *data;
    int bpp;
    int stride;
    int i;
    pixman_image_destroy_func_t destroy;

    if ((flags & ALLOW_SOLID) && lcg_rand_n (4) == 0)
    {
	pixman_color_t color;

	color.alpha = lcg_rand_u32();
	color.red = lcg_rand_u32();
	color.green = lcg_rand_u32();
	color.blue = lcg_rand_u32();

	return pixman_image_create_solid_fill (&color);
    }

    width = lcg_rand_n (max_size) + 1;
    height = lcg_rand_n (max_size) + 1;
    format = random_format (formats);

    bpp = PIXMAN_FORMAT_BPP (format);
    stride = (width * bpp + 7) / 8 + lcg_rand_n (17);
    stride = (stride + 3) & ~3;

    if (lcg_rand_n (64) == 0)
    {
	if (!(data = (uint32_t *)make_random_bytes (stride * height)))
	{
	    fprintf (stderr, "Out of memory\n");
	    abort ();
	}
	destroy = destroy_fenced;
    }
    else
    {
	uint8_t *d8;

	data = malloc (stride * height);

	d8 = (uint8_t *)data;
	for (i = 0; i < height * stride; ++i)
	    d8[i] = lcg_rand_n (256);

	destroy = destroy_malloced;
    }

    image = pixman_image_create_bits (format, width, height, data, stride);
    pixman_image_set_destroy_function (image, destroy, data);

    if ((flags & ALLOW_CLIPPED) && lcg_rand_n (8) == 0)
    {
	pixman_box16_t clip_boxes[8];
	pixman_region16_t clip;
	int n = lcg_rand_n (8) + 1;

	for (i = 0; i < n; i++)
	{
	    clip_boxes[i].x1 = lcg_rand_n (width);
	    clip_boxes[i].y1 = lcg_rand_n (height);
	    clip_boxes[i].x2 =
		clip_boxes[i].x1 + lcg_rand_n (width - clip_boxes[i].x1);
	    clip_boxes[i].y2 =
		clip_boxes[i].y1 + lcg_rand_n (height - clip_boxes[i].y1);
	}

	pixman_region_init_rects (&clip, clip_boxes, n);
	pixman_image_set_clip_region (image, &clip);
	pixman_region_fini (&clip);
    }

    if ((flags & ALLOW_SOURCE_CLIPPING) && lcg_rand_n (4) == 0)
    {
	pixman_image_set_source_clipping (image, TRUE);
	pixman_image_set_has_client_clip (image, TRUE);
    }

    if ((flags & ALLOW_ALPHA_MAP) && lcg_rand_n (16) == 0)
    {
	pixman_image_t *alpha_map;
	int alpha_x, alpha_y;

	alpha_x = lcg_rand_n (width);
	alpha_y = lcg_rand_n (height);
	alpha_map =
	    create_image (max_size, formats, (flags & ~(ALLOW_ALPHA_MAP | ALLOW_SOLID)));
	pixman_image_set_alpha_map (image, alpha_map, alpha_x, alpha_y);
	pixman_image_unref (alpha_map);
    }

    if ((flags & ALLOW_REPEAT) && lcg_rand_n (2) == 0)
	pixman_image_set_repeat (image, lcg_rand_n (4));

    image_endian_swap (image);

    return image;
}
예제 #7
0
bool sna_tiling_blt_copy_boxes(struct sna *sna, uint8_t alu,
			       struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
			       struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
			       int bpp, const BoxRec *box, int nbox)
{
	RegionRec region, tile, this;
	struct kgem_bo *bo;
	int step;
	bool ret = false;

	if (!kgem_bo_can_blt(&sna->kgem, src_bo) ||
	    !kgem_bo_can_blt(&sna->kgem, dst_bo)) {
		/* XXX */
		DBG(("%s: tiling blt fail: src?=%d, dst?=%d\n",
		     __FUNCTION__,
		     kgem_bo_can_blt(&sna->kgem, src_bo),
		     kgem_bo_can_blt(&sna->kgem, dst_bo)));
		return false;
	}

	pixman_region_init_rects(&region, box, nbox);

	/* Use a small step to accommodate enlargement through tile alignment */
	step = sna->render.max_3d_size;
	if (region.extents.x1 & (8*512 / bpp - 1) || region.extents.y1 & 63)
		step /= 2;
	while (step * step * 4 > sna->kgem.max_copy_tile_size)
		step /= 2;

	DBG(("%s (alu=%d), tile.size=%d, box=%dx[(%d, %d), (%d, %d)])\n",
	     __FUNCTION__, alu, step, nbox,
	     region.extents.x1, region.extents.y1,
	     region.extents.x2, region.extents.y2));

	for (tile.extents.y1 = tile.extents.y2 = region.extents.y1;
	     tile.extents.y2 < region.extents.y2;
	     tile.extents.y1 = tile.extents.y2) {
		tile.extents.y2 = tile.extents.y1 + step;
		if (tile.extents.y2 > region.extents.y2)
			tile.extents.y2 = region.extents.y2;

		for (tile.extents.x1 = tile.extents.x2 = region.extents.x1;
		     tile.extents.x2 < region.extents.x2;
		     tile.extents.x1 = tile.extents.x2) {
			int w, h;

			tile.extents.x2 = tile.extents.x1 + step;
			if (tile.extents.x2 > region.extents.x2)
				tile.extents.x2 = region.extents.x2;

			tile.data = NULL;

			RegionNull(&this);
			RegionIntersect(&this, &region, &tile);
			if (!RegionNotEmpty(&this))
				continue;

			w = this.extents.x2 - this.extents.x1;
			h = this.extents.y2 - this.extents.y1;
			bo = kgem_create_2d(&sna->kgem, w, h, bpp,
					    kgem_choose_tiling(&sna->kgem,
							       I915_TILING_X,
							       w, h, bpp),
					    CREATE_TEMPORARY);
			if (bo) {
				int16_t dx = this.extents.x1;
				int16_t dy = this.extents.y1;

				assert(bo->pitch <= 8192);
				assert(bo->tiling != I915_TILING_Y);

				if (!sna_blt_copy_boxes(sna, alu,
							src_bo, src_dx, src_dy,
							bo, -dx, -dy,
							bpp, REGION_RECTS(&this), REGION_NUM_RECTS(&this)))
					goto err;

				if (!sna_blt_copy_boxes(sna, alu,
							bo, -dx, -dy,
							dst_bo, dst_dx, dst_dy,
							bpp, REGION_RECTS(&this), REGION_NUM_RECTS(&this)))
					goto err;

				kgem_bo_destroy(&sna->kgem, bo);
			}
			RegionUninit(&this);
		}
	}

	ret = true;
	goto done;
err:
	kgem_bo_destroy(&sna->kgem, bo);
	RegionUninit(&this);
done:
	pixman_region_fini(&region);
	return ret;
}