1fe8aea9eSmrg#include <stdint.h>
2fe8aea9eSmrg#include <stdio.h>
3fe8aea9eSmrg#include <stdlib.h>
4fe8aea9eSmrg
5fe8aea9eSmrg#include "test.h"
6fe8aea9eSmrg
7fe8aea9eSmrgenum edge {
8fe8aea9eSmrg	EDGE_SHARP = PolyEdgeSharp,
9fe8aea9eSmrg	EDGE_SMOOTH,
10fe8aea9eSmrg};
11fe8aea9eSmrg
12fe8aea9eSmrgstatic void set_edge(Display *dpy, Picture p, enum edge edge)
13fe8aea9eSmrg{
14fe8aea9eSmrg	XRenderPictureAttributes a;
15fe8aea9eSmrg
16fe8aea9eSmrg	a.poly_edge = edge;
17fe8aea9eSmrg	XRenderChangePicture(dpy, p, CPPolyEdge, &a);
18fe8aea9eSmrg}
19fe8aea9eSmrg
20fe8aea9eSmrgstatic XRenderPictFormat *mask_format(Display *dpy, enum mask mask)
21fe8aea9eSmrg{
22fe8aea9eSmrg	switch (mask) {
23fe8aea9eSmrg	default:
24fe8aea9eSmrg	case MASK_NONE: return NULL;
25fe8aea9eSmrg	case MASK_A1: return XRenderFindStandardFormat(dpy, PictStandardA1);
26fe8aea9eSmrg	case MASK_A8: return XRenderFindStandardFormat(dpy, PictStandardA8);
27fe8aea9eSmrg	}
28fe8aea9eSmrg}
29fe8aea9eSmrg
30fe8aea9eSmrgstatic const char *mask_name(enum mask mask)
31fe8aea9eSmrg{
32fe8aea9eSmrg	switch (mask) {
33fe8aea9eSmrg	default:
34fe8aea9eSmrg	case MASK_NONE: return "none";
35fe8aea9eSmrg	case MASK_A1: return "a1";
36fe8aea9eSmrg	case MASK_A8: return "a8";
37fe8aea9eSmrg	}
38fe8aea9eSmrg}
39fe8aea9eSmrg
40fe8aea9eSmrgstatic const char *edge_name(enum edge edge)
41fe8aea9eSmrg{
42fe8aea9eSmrg	switch (edge) {
43fe8aea9eSmrg	default:
44fe8aea9eSmrg	case EDGE_SHARP: return "sharp";
45fe8aea9eSmrg	case EDGE_SMOOTH: return "smooth";
46fe8aea9eSmrg	}
47fe8aea9eSmrg}
48fe8aea9eSmrg
49fe8aea9eSmrgstatic void clear(struct test_display *dpy, struct test_target *tt)
50fe8aea9eSmrg{
51fe8aea9eSmrg	XRenderColor render_color = {0};
52fe8aea9eSmrg	XRenderFillRectangle(dpy->dpy, PictOpClear, tt->picture, &render_color,
53fe8aea9eSmrg			     0, 0, tt->width, tt->height);
54fe8aea9eSmrg}
55fe8aea9eSmrg
56fe8aea9eSmrgstatic void step_to_point(int step, int width, int height, XPointFixed *p)
57fe8aea9eSmrg{
58fe8aea9eSmrg	do {
59fe8aea9eSmrg		p->x = (step - 64) << 16;
60fe8aea9eSmrg		p->y = -64 << 16;
61fe8aea9eSmrg
62fe8aea9eSmrg		step -= width - 128;
63fe8aea9eSmrg		if (step <= 0)
64fe8aea9eSmrg			return;
65fe8aea9eSmrg
66fe8aea9eSmrg		p->x = (width + 64) << 16;
67fe8aea9eSmrg		p->y = (step - 64) << 16;
68fe8aea9eSmrg		step -= height - 128;
69fe8aea9eSmrg
70fe8aea9eSmrg		if (step <= 0)
71fe8aea9eSmrg			return;
72fe8aea9eSmrg
73fe8aea9eSmrg		p->x = (width + 64 - step) << 16;
74fe8aea9eSmrg		p->y = (height + 64) << 16;
75fe8aea9eSmrg		step -= width - 128;
76fe8aea9eSmrg
77fe8aea9eSmrg		if (step <= 0)
78fe8aea9eSmrg			return;
79fe8aea9eSmrg
80fe8aea9eSmrg		p->x = -64 << 16;
81fe8aea9eSmrg		p->y = (height + 64 - step) << 16;
82fe8aea9eSmrg		step -= height - 128;
83fe8aea9eSmrg	} while (step > 0);
84fe8aea9eSmrg}
85fe8aea9eSmrg
86fe8aea9eSmrgstatic void edge_test(struct test *t,
87fe8aea9eSmrg		      enum mask mask,
88fe8aea9eSmrg		      enum edge edge,
89fe8aea9eSmrg		      enum target target)
90fe8aea9eSmrg{
91fe8aea9eSmrg	struct test_target out, ref;
92fe8aea9eSmrg	XRenderColor white = { 0xffff, 0xffff, 0xffff, 0xffff };
93fe8aea9eSmrg	Picture src_ref, src_out;
94fe8aea9eSmrg	XTriangle tri;
95fe8aea9eSmrg	unsigned step, max;
96fe8aea9eSmrg
97fe8aea9eSmrg	test_target_create_render(&t->out, target, &out);
98fe8aea9eSmrg	set_edge(t->out.dpy, out.picture, edge);
99fe8aea9eSmrg	src_out = XRenderCreateSolidFill(t->out.dpy, &white);
100fe8aea9eSmrg
101fe8aea9eSmrg	test_target_create_render(&t->ref, target, &ref);
102fe8aea9eSmrg	set_edge(t->ref.dpy, ref.picture, edge);
103fe8aea9eSmrg	src_ref = XRenderCreateSolidFill(t->ref.dpy, &white);
104fe8aea9eSmrg
105fe8aea9eSmrg	printf("Testing edges (with mask %s and %s edges) (%s): ",
106fe8aea9eSmrg	       mask_name(mask),
107fe8aea9eSmrg	       edge_name(edge),
108fe8aea9eSmrg	       test_target_name(target));
109fe8aea9eSmrg	fflush(stdout);
110fe8aea9eSmrg
111fe8aea9eSmrg	max = 2*(out.width + 128 + out.height+128);
112fe8aea9eSmrg	step = 0;
113fe8aea9eSmrg	for (step = 0; step <= max; step++) {
114fe8aea9eSmrg		char buf[80];
115fe8aea9eSmrg
116fe8aea9eSmrg		step_to_point(step, out.width, out.height, &tri.p1);
117fe8aea9eSmrg		step_to_point(step + out.width + 128,
118fe8aea9eSmrg			      out.width, out.height,
119fe8aea9eSmrg			      &tri.p2);
120fe8aea9eSmrg		step_to_point(step + out.height + 128 + 2*(out.width + 128),
121fe8aea9eSmrg			      out.width, out.height,
122fe8aea9eSmrg			      &tri.p3);
123fe8aea9eSmrg
124fe8aea9eSmrg		sprintf(buf,
125fe8aea9eSmrg			"tri=((%d, %d), (%d, %d), (%d, %d))\n",
126fe8aea9eSmrg			tri.p1.x >> 16, tri.p1.y >> 16,
127fe8aea9eSmrg			tri.p2.x >> 16, tri.p2.y >> 16,
128fe8aea9eSmrg			tri.p3.x >> 16, tri.p3.y >> 16);
129fe8aea9eSmrg
130fe8aea9eSmrg		clear(&t->out, &out);
131fe8aea9eSmrg		XRenderCompositeTriangles(t->out.dpy,
132fe8aea9eSmrg					  PictOpSrc,
133fe8aea9eSmrg					  src_out,
134fe8aea9eSmrg					  out.picture,
135fe8aea9eSmrg					  mask_format(t->out.dpy, mask),
136fe8aea9eSmrg					  0, 0,
137fe8aea9eSmrg					  &tri, 1);
138fe8aea9eSmrg
139fe8aea9eSmrg		clear(&t->ref, &ref);
140fe8aea9eSmrg		XRenderCompositeTriangles(t->ref.dpy,
141fe8aea9eSmrg					  PictOpSrc,
142fe8aea9eSmrg					  src_ref,
143fe8aea9eSmrg					  ref.picture,
144fe8aea9eSmrg					  mask_format(t->ref.dpy, mask),
145fe8aea9eSmrg					  0, 0,
146fe8aea9eSmrg					  &tri, 1);
147fe8aea9eSmrg
148fe8aea9eSmrg		test_compare(t,
149fe8aea9eSmrg			     out.draw, out.format,
150fe8aea9eSmrg			     ref.draw, ref.format,
151fe8aea9eSmrg			     0, 0, out.width, out.height,
152fe8aea9eSmrg			     buf);
153fe8aea9eSmrg	}
154fe8aea9eSmrg
155fe8aea9eSmrg	XRenderFreePicture(t->out.dpy, src_out);
156fe8aea9eSmrg	test_target_destroy_render(&t->out, &out);
157fe8aea9eSmrg
158fe8aea9eSmrg	XRenderFreePicture(t->ref.dpy, src_ref);
159fe8aea9eSmrg	test_target_destroy_render(&t->ref, &ref);
160fe8aea9eSmrg
161fe8aea9eSmrg	printf("pass\n");
162fe8aea9eSmrg}
163fe8aea9eSmrg
164fe8aea9eSmrgint main(int argc, char **argv)
165fe8aea9eSmrg{
166fe8aea9eSmrg	struct test test;
167fe8aea9eSmrg	enum target target;
168fe8aea9eSmrg	enum mask mask;
169fe8aea9eSmrg	enum edge edge;
170fe8aea9eSmrg
171fe8aea9eSmrg	test_init(&test, argc, argv);
172fe8aea9eSmrg
173fe8aea9eSmrg	for (target = TARGET_FIRST; target <= TARGET_LAST; target++) {
174fe8aea9eSmrg		for (mask = MASK_NONE; mask <= MASK_A8; mask++)
175fe8aea9eSmrg			for (edge = EDGE_SHARP; edge <= EDGE_SMOOTH; edge++)
176fe8aea9eSmrg				edge_test(&test, mask, edge, target);
177fe8aea9eSmrg	}
178fe8aea9eSmrg
179fe8aea9eSmrg	return 0;
180fe8aea9eSmrg}
181