103b705cfSriastradh#include <stdint.h>
203b705cfSriastradh#include <stdio.h>
303b705cfSriastradh#include <stdlib.h>
403b705cfSriastradh
503b705cfSriastradh#include <X11/Xutil.h> /* for XDestroyImage */
603b705cfSriastradh#include <pixman.h> /* for pixman blt functions */
703b705cfSriastradh
803b705cfSriastradh#include "test.h"
903b705cfSriastradh
1003b705cfSriastradhenum trapezoid {
1103b705cfSriastradh	RECT_ALIGN,
1203b705cfSriastradh	RECT_UNALIGN,
1303b705cfSriastradh	GENERAL
1403b705cfSriastradh};
1503b705cfSriastradh
1603b705cfSriastradhstatic const uint8_t ops[] = {
1703b705cfSriastradh	PictOpClear,
1803b705cfSriastradh	PictOpSrc,
1903b705cfSriastradh	PictOpDst,
2003b705cfSriastradh};
2103b705cfSriastradh
2203b705cfSriastradhstatic XRenderPictFormat *mask_format(Display *dpy, enum mask mask)
2303b705cfSriastradh{
2403b705cfSriastradh	switch (mask) {
2503b705cfSriastradh	default:
2603b705cfSriastradh	case MASK_NONE: return NULL;
2703b705cfSriastradh	case MASK_A1: return  XRenderFindStandardFormat(dpy, PictStandardA1);
2803b705cfSriastradh	case MASK_A8: return  XRenderFindStandardFormat(dpy, PictStandardA8);
2903b705cfSriastradh	}
3003b705cfSriastradh}
3103b705cfSriastradh
3203b705cfSriastradhstatic const char *mask_name(enum mask mask)
3303b705cfSriastradh{
3403b705cfSriastradh	switch (mask) {
3503b705cfSriastradh	default:
3603b705cfSriastradh	case MASK_NONE: return "none";
3703b705cfSriastradh	case MASK_A1: return "a1";
3803b705cfSriastradh	case MASK_A8: return "a8";
3903b705cfSriastradh	}
4003b705cfSriastradh}
4103b705cfSriastradh
4203b705cfSriastradhstatic const char *trapezoid_name(enum trapezoid trapezoid)
4303b705cfSriastradh{
4403b705cfSriastradh	switch (trapezoid) {
4503b705cfSriastradh	default:
4603b705cfSriastradh	case RECT_ALIGN: return "pixel-aligned";
4703b705cfSriastradh	case RECT_UNALIGN: return "rectilinear";
4803b705cfSriastradh	case GENERAL: return "general";
4903b705cfSriastradh	}
5003b705cfSriastradh}
5103b705cfSriastradh
5203b705cfSriastradhstatic void fill_rect(struct test_display *dpy, Picture p, uint8_t op,
5303b705cfSriastradh		      int x, int y, int w, int h,
5403b705cfSriastradh		      int dx, int dy, enum mask mask,
5503b705cfSriastradh		      uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha)
5603b705cfSriastradh{
5703b705cfSriastradh	XRenderColor render_color;
5803b705cfSriastradh	XTrapezoid trap;
5903b705cfSriastradh	Picture src;
6003b705cfSriastradh
6103b705cfSriastradh	render_color.red   = red * alpha;
6203b705cfSriastradh	render_color.green = green * alpha;
6303b705cfSriastradh	render_color.blue  = blue * alpha;
6403b705cfSriastradh	render_color.alpha = alpha << 8;
6503b705cfSriastradh
6603b705cfSriastradh	trap.left.p1.x = trap.left.p2.x = (x << 16) + dx;
6703b705cfSriastradh	trap.top = trap.left.p1.y = trap.right.p1.y = (y << 16) + dy;
6803b705cfSriastradh	trap.right.p1.x = trap.right.p2.x = ((x + w) << 16) + dx;
6903b705cfSriastradh	trap.bottom = trap.left.p2.y = trap.right.p2.y = ((y + h) << 16) + dy;
7003b705cfSriastradh
7103b705cfSriastradh	src = XRenderCreateSolidFill(dpy->dpy, &render_color);
7203b705cfSriastradh	XRenderCompositeTrapezoids(dpy->dpy,
7303b705cfSriastradh				   op, src, p, mask_format(dpy->dpy, mask),
7403b705cfSriastradh				   0, 0, &trap, 1);
7503b705cfSriastradh	XRenderFreePicture(dpy->dpy, src);
7603b705cfSriastradh}
7703b705cfSriastradh
7803b705cfSriastradhstatic void pixel_tests(struct test *t, int reps, int sets, enum target target)
7903b705cfSriastradh{
8003b705cfSriastradh	struct test_target tt;
8103b705cfSriastradh	XImage image;
8242542f5fSchristos	uint32_t *cells = malloc(t->out.width*t->out.height*4);
8303b705cfSriastradh	struct {
8403b705cfSriastradh		uint16_t x, y;
8503b705cfSriastradh	} *pixels = malloc(reps*sizeof(*pixels));
8603b705cfSriastradh	int r, s;
8703b705cfSriastradh
8803b705cfSriastradh	printf("Testing setting of single pixels (%s): ", test_target_name(target));
8903b705cfSriastradh	fflush(stdout);
9003b705cfSriastradh
9142542f5fSchristos	test_target_create_render(&t->out, target, &tt);
9203b705cfSriastradh
9303b705cfSriastradh	for (s = 0; s < sets; s++) {
9403b705cfSriastradh		for (r = 0; r < reps; r++) {
9503b705cfSriastradh			int x = rand() % (tt.width - 1);
9603b705cfSriastradh			int y = rand() % (tt.height - 1);
9703b705cfSriastradh			int red = rand() % 0xff;
9803b705cfSriastradh			int green = rand() % 0xff;
9903b705cfSriastradh			int blue = rand() % 0xff;
10003b705cfSriastradh			int alpha = rand() % 0xff;
10103b705cfSriastradh
10242542f5fSchristos			fill_rect(&t->out, tt.picture, PictOpSrc,
10303b705cfSriastradh				  x, y, 1, 1,
10403b705cfSriastradh				  0, 0, MASK_NONE,
10503b705cfSriastradh				  red, green, blue, alpha);
10603b705cfSriastradh
10703b705cfSriastradh			pixels[r].x = x;
10803b705cfSriastradh			pixels[r].y = y;
10942542f5fSchristos			cells[y*t->out.width+x] = color(red, green, blue, alpha);
11003b705cfSriastradh		}
11103b705cfSriastradh
11242542f5fSchristos		test_init_image(&image, &t->out.shm, tt.format, 1, 1);
11303b705cfSriastradh
11403b705cfSriastradh		for (r = 0; r < reps; r++) {
11503b705cfSriastradh			uint32_t result;
11603b705cfSriastradh			uint32_t x = pixels[r].x;
11703b705cfSriastradh			uint32_t y = pixels[r].y;
11803b705cfSriastradh
11942542f5fSchristos			XShmGetImage(t->out.dpy, tt.draw, &image,
12003b705cfSriastradh				     x, y, AllPlanes);
12103b705cfSriastradh
12203b705cfSriastradh			result = *(uint32_t *)image.data;
12303b705cfSriastradh			if (!pixel_equal(image.depth, result,
12403b705cfSriastradh					 cells[y*tt.width+x])) {
12503b705cfSriastradh				uint32_t mask = depth_mask(image.depth);
12603b705cfSriastradh				die("failed to set pixel (%d,%d) to %08x [%08x], found %08x [%08x] instead\n",
12703b705cfSriastradh				    x, y,
12803b705cfSriastradh				    cells[y*tt.width+x] & mask,
12903b705cfSriastradh				    cells[y*tt.width+x],
13003b705cfSriastradh				    result & mask,
13103b705cfSriastradh				    result);
13203b705cfSriastradh			}
13303b705cfSriastradh		}
13403b705cfSriastradh	}
13503b705cfSriastradh	printf("passed [%d iterations x %d]\n", reps, sets);
13603b705cfSriastradh
13742542f5fSchristos	test_target_destroy_render(&t->out, &tt);
13803b705cfSriastradh
13903b705cfSriastradh	free(pixels);
14003b705cfSriastradh	free(cells);
14103b705cfSriastradh}
14203b705cfSriastradh
14303b705cfSriastradhstatic void clear(struct test_display *dpy, struct test_target *tt)
14403b705cfSriastradh{
14503b705cfSriastradh	XRenderColor render_color = {0};
14603b705cfSriastradh	XRenderFillRectangle(dpy->dpy, PictOpClear, tt->picture, &render_color,
14703b705cfSriastradh			     0, 0, tt->width, tt->height);
14803b705cfSriastradh}
14903b705cfSriastradh
15003b705cfSriastradhstatic void area_tests(struct test *t, int reps, int sets, enum target target)
15103b705cfSriastradh{
15203b705cfSriastradh	struct test_target tt;
15303b705cfSriastradh	XImage image;
15442542f5fSchristos	uint32_t *cells = calloc(sizeof(uint32_t), t->out.width*t->out.height);
15503b705cfSriastradh	int r, s, x, y;
15603b705cfSriastradh
15703b705cfSriastradh	printf("Testing area sets (%s): ", test_target_name(target));
15803b705cfSriastradh	fflush(stdout);
15903b705cfSriastradh
16042542f5fSchristos	test_target_create_render(&t->out, target, &tt);
16142542f5fSchristos	clear(&t->out, &tt);
16203b705cfSriastradh
16342542f5fSchristos	test_init_image(&image, &t->out.shm, tt.format, tt.width, tt.height);
16403b705cfSriastradh
16503b705cfSriastradh	for (s = 0; s < sets; s++) {
16603b705cfSriastradh		for (r = 0; r < reps; r++) {
16703b705cfSriastradh			int w = rand() % tt.width;
16803b705cfSriastradh			int h = rand() % tt.height;
16903b705cfSriastradh			int red = rand() % 0xff;
17003b705cfSriastradh			int green = rand() % 0xff;
17103b705cfSriastradh			int blue = rand() % 0xff;
17203b705cfSriastradh			int alpha = rand() % 0xff;
17303b705cfSriastradh
17403b705cfSriastradh			x = rand() % (2*tt.width) - tt.width;
17503b705cfSriastradh			y = rand() % (2*tt.height) - tt.height;
17603b705cfSriastradh
17742542f5fSchristos			fill_rect(&t->out, tt.picture, PictOpSrc,
17803b705cfSriastradh				  x, y, w, h,
17903b705cfSriastradh				  0, 0, MASK_NONE,
18003b705cfSriastradh				  red, green, blue, alpha);
18103b705cfSriastradh
18203b705cfSriastradh			if (x < 0)
18303b705cfSriastradh				w += x, x = 0;
18403b705cfSriastradh			if (y < 0)
18503b705cfSriastradh				h += y, y = 0;
18603b705cfSriastradh			if (x >= tt.width || y >= tt.height)
18703b705cfSriastradh				continue;
18803b705cfSriastradh
18903b705cfSriastradh			if (x + w > tt.width)
19003b705cfSriastradh				w = tt.width - x;
19103b705cfSriastradh			if (y + h > tt.height)
19203b705cfSriastradh				h = tt.height - y;
19303b705cfSriastradh			if (w <= 0 || h <= 0)
19403b705cfSriastradh				continue;
19503b705cfSriastradh
19603b705cfSriastradh			pixman_fill(cells, tt.width, 32, x, y, w, h,
19703b705cfSriastradh				    color(red, green, blue, alpha));
19803b705cfSriastradh		}
19903b705cfSriastradh
20042542f5fSchristos		XShmGetImage(t->out.dpy, tt.draw, &image, 0, 0, AllPlanes);
20103b705cfSriastradh
20203b705cfSriastradh		for (y = 0; y < tt.height; y++) {
20303b705cfSriastradh			for (x = 0; x < tt.width; x++) {
20403b705cfSriastradh				uint32_t result =
20503b705cfSriastradh					*(uint32_t *)(image.data +
20603b705cfSriastradh						      y*image.bytes_per_line +
20703b705cfSriastradh						      image.bits_per_pixel*x/8);
20803b705cfSriastradh				if (!pixel_equal(image.depth, result, cells[y*tt.width+x])) {
20903b705cfSriastradh					uint32_t mask = depth_mask(image.depth);
21003b705cfSriastradh
21103b705cfSriastradh					die("failed to set pixel (%d,%d) to %08x [%08x], found %08x [%08x] instead\n",
21203b705cfSriastradh					    x, y,
21303b705cfSriastradh					    cells[y*tt.width+x] & mask,
21403b705cfSriastradh					    cells[y*tt.width+x],
21503b705cfSriastradh					    result & mask,
21603b705cfSriastradh					    result);
21703b705cfSriastradh				}
21803b705cfSriastradh			}
21903b705cfSriastradh		}
22003b705cfSriastradh	}
22103b705cfSriastradh
22203b705cfSriastradh	printf("passed [%d iterations x %d]\n", reps, sets);
22303b705cfSriastradh
22442542f5fSchristos	test_target_destroy_render(&t->out, &tt);
22503b705cfSriastradh	free(cells);
22603b705cfSriastradh}
22703b705cfSriastradh
22803b705cfSriastradhstatic void rect_tests(struct test *t,
22903b705cfSriastradh		       int dx, int dy,
23003b705cfSriastradh		       enum mask mask,
23103b705cfSriastradh		       int reps, int sets,
23203b705cfSriastradh		       enum target target)
23303b705cfSriastradh{
23442542f5fSchristos	struct test_target out, ref;
23503b705cfSriastradh	int r, s;
23603b705cfSriastradh
23703b705cfSriastradh	printf("Testing area fills (offset %dx%d, mask %s) (%s): ",
23803b705cfSriastradh	       dx, dy, mask_name(mask), test_target_name(target));
23903b705cfSriastradh	fflush(stdout);
24003b705cfSriastradh
24142542f5fSchristos	test_target_create_render(&t->out, target, &out);
24242542f5fSchristos	clear(&t->out, &out);
24303b705cfSriastradh
24403b705cfSriastradh	test_target_create_render(&t->ref, target, &ref);
24503b705cfSriastradh	clear(&t->ref, &ref);
24603b705cfSriastradh
24703b705cfSriastradh	for (s = 0; s < sets; s++) {
24803b705cfSriastradh		for (r = 0; r < reps; r++) {
24942542f5fSchristos			int x = rand() % (2*out.width) - out.width;
25042542f5fSchristos			int y = rand() % (2*out.height) - out.height;
25142542f5fSchristos			int w = rand() % out.width;
25242542f5fSchristos			int h = rand() % out.height;
25303b705cfSriastradh			int op = ops[rand() % sizeof(ops)];
25403b705cfSriastradh			int red = rand() % 0xff;
25503b705cfSriastradh			int green = rand() % 0xff;
25603b705cfSriastradh			int blue = rand() % 0xff;
25703b705cfSriastradh			int alpha = rand() % 0xff;
25803b705cfSriastradh
25942542f5fSchristos			fill_rect(&t->out, out.picture, op,
26003b705cfSriastradh				  x, y, w, h, dx, dy, mask,
26103b705cfSriastradh				  red, green, blue, alpha);
26203b705cfSriastradh			fill_rect(&t->ref, ref.picture, op,
26303b705cfSriastradh				  x, y, w, h, dx, dy, mask,
26403b705cfSriastradh				  red, green, blue, alpha);
26503b705cfSriastradh		}
26603b705cfSriastradh
26703b705cfSriastradh		test_compare(t,
26842542f5fSchristos			     out.draw, out.format,
26903b705cfSriastradh			     ref.draw, ref.format,
27042542f5fSchristos			     0, 0, out.width, out.height,
27103b705cfSriastradh			     "");
27203b705cfSriastradh	}
27303b705cfSriastradh
27403b705cfSriastradh	printf("passed [%d iterations x %d]\n", reps, sets);
27503b705cfSriastradh
27642542f5fSchristos	test_target_destroy_render(&t->out, &out);
27703b705cfSriastradh	test_target_destroy_render(&t->ref, &ref);
27803b705cfSriastradh}
27903b705cfSriastradh
28003b705cfSriastradhstatic void random_trapezoid(XTrapezoid *trap, enum trapezoid trapezoid,
28103b705cfSriastradh			     int x1, int y1, int x2, int y2)
28203b705cfSriastradh{
28303b705cfSriastradh	switch (trapezoid) {
28403b705cfSriastradh	case RECT_ALIGN:
28503b705cfSriastradh		x1 = x1 + rand() % (x2 - x1);
28603b705cfSriastradh		x2 = x1 + rand() % (x2 - x1);
28703b705cfSriastradh		y1 = y1 + rand() % (y2 - y1);
28803b705cfSriastradh		y2 = y1 + rand() % (y2 - y1);
28903b705cfSriastradh
29003b705cfSriastradh		trap->left.p1.x = trap->left.p2.x = x1 << 16;
29103b705cfSriastradh		trap->top = trap->left.p1.y = trap->right.p1.y = y1 << 16;
29203b705cfSriastradh		trap->right.p1.x = trap->right.p2.x = x2 << 16;
29303b705cfSriastradh		trap->bottom = trap->left.p2.y = trap->right.p2.y = y2 << 16;
29403b705cfSriastradh		break;
29503b705cfSriastradh
29603b705cfSriastradh	case RECT_UNALIGN:
29703b705cfSriastradh		x1 <<= 16; x2 <<= 16;
29803b705cfSriastradh		y1 <<= 16; y2 <<= 16;
29903b705cfSriastradh
30003b705cfSriastradh		x1 = x1 + rand() % (x2 - x1);
30103b705cfSriastradh		x2 = x1 + rand() % (x2 - x1);
30203b705cfSriastradh		y1 = y1 + rand() % (y2 - y1);
30303b705cfSriastradh		y2 = y1 + rand() % (y2 - y1);
30403b705cfSriastradh
30503b705cfSriastradh		trap->left.p1.x = trap->left.p2.x = x1;
30603b705cfSriastradh		trap->top = trap->left.p1.y = trap->right.p1.y = y1;
30703b705cfSriastradh		trap->right.p1.x = trap->right.p2.x = x2;
30803b705cfSriastradh		trap->bottom = trap->left.p2.y = trap->right.p2.y = y2;
30903b705cfSriastradh		break;
31003b705cfSriastradh
31103b705cfSriastradh	case GENERAL:
31203b705cfSriastradh		x1 <<= 16; x2 <<= 16;
31303b705cfSriastradh		y1 <<= 16; y2 <<= 16;
31403b705cfSriastradh
31503b705cfSriastradh		trap->top = y1 + rand() % (y2 - y1);
31603b705cfSriastradh		trap->bottom = y1 + rand() % (y2 - y1);
31703b705cfSriastradh
31803b705cfSriastradh		trap->left.p1.x = x1 + rand() % (x2 - x1);
31903b705cfSriastradh		trap->left.p2.x = x1 + rand() % (x2 - x1);
32003b705cfSriastradh
32103b705cfSriastradh		trap->right.p1.x = x1 + rand() % (x2 - x1);
32203b705cfSriastradh		trap->right.p2.x = x1 + rand() % (x2 - x1);
32303b705cfSriastradh		break;
32403b705cfSriastradh
32503b705cfSriastradh	}
32603b705cfSriastradh}
32703b705cfSriastradh
32803b705cfSriastradhstatic void trap_tests(struct test *t,
32903b705cfSriastradh		       enum mask mask,
33003b705cfSriastradh		       enum trapezoid trapezoid,
33103b705cfSriastradh		       int reps, int sets,
33203b705cfSriastradh		       enum target target)
33303b705cfSriastradh{
33442542f5fSchristos	struct test_target out, ref;
33503b705cfSriastradh	XTrapezoid *traps;
33603b705cfSriastradh	int max_traps = 65536;
33703b705cfSriastradh	int r, s, n;
33803b705cfSriastradh
33903b705cfSriastradh	traps = malloc(sizeof(*traps) * max_traps);
34003b705cfSriastradh	if (traps == NULL)
34103b705cfSriastradh		return;
34203b705cfSriastradh
34303b705cfSriastradh	printf("Testing trapezoids (%s with mask %s) (%s): ",
34403b705cfSriastradh	       trapezoid_name(trapezoid),
34503b705cfSriastradh	       mask_name(mask),
34603b705cfSriastradh	       test_target_name(target));
34703b705cfSriastradh	fflush(stdout);
34803b705cfSriastradh
34942542f5fSchristos	test_target_create_render(&t->out, target, &out);
35042542f5fSchristos	clear(&t->out, &out);
35103b705cfSriastradh
35203b705cfSriastradh	test_target_create_render(&t->ref, target, &ref);
35303b705cfSriastradh	clear(&t->ref, &ref);
35403b705cfSriastradh
35503b705cfSriastradh	for (s = 0; s < sets; s++) {
35603b705cfSriastradh		for (r = 0; r < reps; r++) {
35703b705cfSriastradh			XRenderColor render_color;
35803b705cfSriastradh			int op = ops[rand() % sizeof(ops)];
35903b705cfSriastradh			int red = rand() % 0xff;
36003b705cfSriastradh			int green = rand() % 0xff;
36103b705cfSriastradh			int blue = rand() % 0xff;
36203b705cfSriastradh			int alpha = rand() % 0xff;
36303b705cfSriastradh			int num_traps = rand() % max_traps;
36403b705cfSriastradh			Picture src;
36503b705cfSriastradh
36603b705cfSriastradh			for (n = 0; n < num_traps; n++)
36703b705cfSriastradh				random_trapezoid(&traps[n], 0,
36842542f5fSchristos						 0, 0, out.width, out.height);
36903b705cfSriastradh
37003b705cfSriastradh			render_color.red   = red * alpha;
37103b705cfSriastradh			render_color.green = green * alpha;
37203b705cfSriastradh			render_color.blue  = blue * alpha;
37303b705cfSriastradh			render_color.alpha = alpha << 8;
37403b705cfSriastradh
37542542f5fSchristos			src = XRenderCreateSolidFill(t->out.dpy,
37603b705cfSriastradh						     &render_color);
37742542f5fSchristos			XRenderCompositeTrapezoids(t->out.dpy,
37842542f5fSchristos						   op, src, out.picture,
37942542f5fSchristos						   mask_format(t->out.dpy, mask),
38003b705cfSriastradh						   0, 0, traps, num_traps);
38142542f5fSchristos			XRenderFreePicture(t->out.dpy, src);
38203b705cfSriastradh
38303b705cfSriastradh			src = XRenderCreateSolidFill(t->ref.dpy,
38403b705cfSriastradh						     &render_color);
38503b705cfSriastradh			XRenderCompositeTrapezoids(t->ref.dpy,
38603b705cfSriastradh						   op, src, ref.picture,
38703b705cfSriastradh						   mask_format(t->ref.dpy, mask),
38803b705cfSriastradh						   0, 0, traps, num_traps);
38903b705cfSriastradh			XRenderFreePicture(t->ref.dpy, src);
39003b705cfSriastradh		}
39103b705cfSriastradh
39203b705cfSriastradh		test_compare(t,
39342542f5fSchristos			     out.draw, out.format,
39403b705cfSriastradh			     ref.draw, ref.format,
39542542f5fSchristos			     0, 0, out.width, out.height,
39603b705cfSriastradh			     "");
39703b705cfSriastradh	}
39803b705cfSriastradh
39903b705cfSriastradh	printf("passed [%d iterations x %d]\n", reps, sets);
40003b705cfSriastradh
40142542f5fSchristos	test_target_destroy_render(&t->out, &out);
40203b705cfSriastradh	test_target_destroy_render(&t->ref, &ref);
40303b705cfSriastradh	free(traps);
40403b705cfSriastradh}
40503b705cfSriastradh
406fe8aea9eSmrgenum edge {
407fe8aea9eSmrg	EDGE_SHARP = PolyEdgeSharp,
408fe8aea9eSmrg	EDGE_SMOOTH,
409fe8aea9eSmrg};
410fe8aea9eSmrg
411fe8aea9eSmrgstatic const char *edge_name(enum edge edge)
412fe8aea9eSmrg{
413fe8aea9eSmrg	switch (edge) {
414fe8aea9eSmrg	default:
415fe8aea9eSmrg	case EDGE_SHARP: return "sharp";
416fe8aea9eSmrg	case EDGE_SMOOTH: return "smooth";
417fe8aea9eSmrg	}
418fe8aea9eSmrg}
419fe8aea9eSmrg
420fe8aea9eSmrgstatic void set_edge(Display *dpy, Picture p, enum edge edge)
421fe8aea9eSmrg{
422fe8aea9eSmrg	XRenderPictureAttributes a;
423fe8aea9eSmrg
424fe8aea9eSmrg	a.poly_edge = edge;
425fe8aea9eSmrg	XRenderChangePicture(dpy, p, CPPolyEdge, &a);
426fe8aea9eSmrg}
427fe8aea9eSmrg
428fe8aea9eSmrgstatic void edge_test(struct test *t,
429fe8aea9eSmrg		      enum mask mask,
430fe8aea9eSmrg		      enum edge edge,
431fe8aea9eSmrg		      enum target target)
432fe8aea9eSmrg{
433fe8aea9eSmrg	struct test_target out, ref;
434fe8aea9eSmrg	XRenderColor white = { 0xffff, 0xffff, 0xffff, 0xffff };
435fe8aea9eSmrg	Picture src_ref, src_out;
436fe8aea9eSmrg	XTrapezoid trap;
437fe8aea9eSmrg	int left_or_right, p;
438fe8aea9eSmrg
439fe8aea9eSmrg	test_target_create_render(&t->out, target, &out);
440fe8aea9eSmrg	set_edge(t->out.dpy, out.picture, edge);
441fe8aea9eSmrg	src_out = XRenderCreateSolidFill(t->out.dpy, &white);
442fe8aea9eSmrg
443fe8aea9eSmrg	test_target_create_render(&t->ref, target, &ref);
444fe8aea9eSmrg	set_edge(t->ref.dpy, ref.picture, edge);
445fe8aea9eSmrg	src_ref = XRenderCreateSolidFill(t->ref.dpy, &white);
446fe8aea9eSmrg
447fe8aea9eSmrg	printf("Testing edges (with mask %s and %s edges) (%s): ",
448fe8aea9eSmrg	       mask_name(mask),
449fe8aea9eSmrg	       edge_name(edge),
450fe8aea9eSmrg	       test_target_name(target));
451fe8aea9eSmrg	fflush(stdout);
452fe8aea9eSmrg
453fe8aea9eSmrg	for (left_or_right = 0; left_or_right <= 1; left_or_right++) {
454fe8aea9eSmrg		for (p = -64; p <= out.width + 64; p++) {
455fe8aea9eSmrg			char buf[80];
456fe8aea9eSmrg
457fe8aea9eSmrg			if (left_or_right) {
458fe8aea9eSmrg				trap.left.p1.x = 0;
459fe8aea9eSmrg				trap.left.p1.y = 0;
460fe8aea9eSmrg				trap.left.p2.x = 0;
461fe8aea9eSmrg				trap.left.p2.y = out.height << 16;
462fe8aea9eSmrg
463fe8aea9eSmrg				trap.right.p1.x = p << 16;
464fe8aea9eSmrg				trap.right.p1.y = 0;
465fe8aea9eSmrg				trap.right.p2.x = out.width << 16;
466fe8aea9eSmrg				trap.right.p2.y = out.height << 16;
467fe8aea9eSmrg			} else {
468fe8aea9eSmrg				trap.right.p1.x = out.width << 16;
469fe8aea9eSmrg				trap.right.p1.y = 0;
470fe8aea9eSmrg				trap.right.p2.x = out.width << 16;
471fe8aea9eSmrg				trap.right.p2.y = out.height << 16;
472fe8aea9eSmrg
473fe8aea9eSmrg				trap.left.p1.x = 0;
474fe8aea9eSmrg				trap.left.p1.y = 0;
475fe8aea9eSmrg				trap.left.p2.x = p << 16;
476fe8aea9eSmrg				trap.left.p2.y = out.height << 16;
477fe8aea9eSmrg			}
478fe8aea9eSmrg
479fe8aea9eSmrg			trap.top = 0;
480fe8aea9eSmrg			trap.bottom = out.height << 16;
481fe8aea9eSmrg
482fe8aea9eSmrg			sprintf(buf,
483fe8aea9eSmrg				"trap=((%d, %d), (%d, %d)), ((%d, %d), (%d, %d))\n",
484fe8aea9eSmrg				trap.left.p1.x >> 16, trap.left.p1.y >> 16,
485fe8aea9eSmrg				trap.left.p2.x >> 16, trap.left.p2.y >> 16,
486fe8aea9eSmrg				trap.right.p1.x >> 16, trap.right.p1.y >> 16,
487fe8aea9eSmrg				trap.right.p2.x >> 16, trap.right.p2.y >> 16);
488fe8aea9eSmrg
489fe8aea9eSmrg			clear(&t->out, &out);
490fe8aea9eSmrg			XRenderCompositeTrapezoids(t->out.dpy,
491fe8aea9eSmrg						   PictOpSrc,
492fe8aea9eSmrg						   src_out,
493fe8aea9eSmrg						   out.picture,
494fe8aea9eSmrg						   mask_format(t->out.dpy, mask),
495fe8aea9eSmrg						   0, 0,
496fe8aea9eSmrg						   &trap, 1);
497fe8aea9eSmrg
498fe8aea9eSmrg			clear(&t->ref, &ref);
499fe8aea9eSmrg			XRenderCompositeTrapezoids(t->ref.dpy,
500fe8aea9eSmrg						   PictOpSrc,
501fe8aea9eSmrg						   src_ref,
502fe8aea9eSmrg						   ref.picture,
503fe8aea9eSmrg						   mask_format(t->ref.dpy, mask),
504fe8aea9eSmrg						   0, 0,
505fe8aea9eSmrg						   &trap, 1);
506fe8aea9eSmrg
507fe8aea9eSmrg			test_compare(t,
508fe8aea9eSmrg				     out.draw, out.format,
509fe8aea9eSmrg				     ref.draw, ref.format,
510fe8aea9eSmrg				     0, 0, out.width, out.height,
511fe8aea9eSmrg				     buf);
512fe8aea9eSmrg		}
513fe8aea9eSmrg	}
514fe8aea9eSmrg
515fe8aea9eSmrg	XRenderFreePicture(t->out.dpy, src_out);
516fe8aea9eSmrg	test_target_destroy_render(&t->out, &out);
517fe8aea9eSmrg
518fe8aea9eSmrg	XRenderFreePicture(t->ref.dpy, src_ref);
519fe8aea9eSmrg	test_target_destroy_render(&t->ref, &ref);
520fe8aea9eSmrg
521fe8aea9eSmrg	printf("pass\n");
522fe8aea9eSmrg}
523fe8aea9eSmrg
52403b705cfSriastradhint main(int argc, char **argv)
52503b705cfSriastradh{
52603b705cfSriastradh	struct test test;
52703b705cfSriastradh	int i, dx, dy;
52803b705cfSriastradh	enum target target;
52903b705cfSriastradh	enum mask mask;
530fe8aea9eSmrg	enum edge edge;
53103b705cfSriastradh	enum trapezoid trapezoid;
53203b705cfSriastradh
53303b705cfSriastradh	test_init(&test, argc, argv);
53403b705cfSriastradh
535fe8aea9eSmrg	for (target = TARGET_FIRST; target <= TARGET_LAST; target++) {
536fe8aea9eSmrg		for (mask = MASK_NONE; mask <= MASK_A8; mask++)
537fe8aea9eSmrg			for (edge = EDGE_SHARP; edge <= EDGE_SMOOTH; edge++)
538fe8aea9eSmrg				edge_test(&test, mask, edge, target);
539fe8aea9eSmrg	}
540fe8aea9eSmrg
54103b705cfSriastradh	for (i = 0; i <= DEFAULT_ITERATIONS; i++) {
54242542f5fSchristos		int reps = REPS(i), sets = SETS(i);
54303b705cfSriastradh
54403b705cfSriastradh		for (target = TARGET_FIRST; target <= TARGET_LAST; target++) {
54503b705cfSriastradh			pixel_tests(&test, reps, sets, target);
54603b705cfSriastradh			area_tests(&test, reps, sets, target);
54703b705cfSriastradh			for (dy = 0; dy < 1 << 16; dy += 1 << 14)
54803b705cfSriastradh				for (dx = 0; dx < 1 << 16; dx += 1 << 14)
54903b705cfSriastradh					for (mask = MASK_NONE; mask <= MASK_A8; mask++)
55003b705cfSriastradh						rect_tests(&test, dx, dy, mask, reps, sets, target);
55103b705cfSriastradh			for (trapezoid = RECT_ALIGN; trapezoid <= GENERAL; trapezoid++)
55203b705cfSriastradh				trap_tests(&test, mask, trapezoid, reps, sets, target);
55303b705cfSriastradh		}
55403b705cfSriastradh	}
55503b705cfSriastradh
55603b705cfSriastradh	return 0;
55703b705cfSriastradh}
558