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