1 /*
2  * Copyright © 2013 VMware, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  *
23  */
24 
25 
26 /**
27  * Test glPolygonMode + glPolygonOffset.
28  *
29  * Brian Paul
30  * Feb 2013
31  */
32 
33 
34 #include "piglit-util-gl.h"
35 
36 
37 PIGLIT_GL_TEST_CONFIG_BEGIN
38 	config.supports_gl_compat_version = 10;
39 	config.window_visual = (PIGLIT_GL_VISUAL_RGB |
40 				PIGLIT_GL_VISUAL_DOUBLE |
41 				PIGLIT_GL_VISUAL_DEPTH);
42 PIGLIT_GL_TEST_CONFIG_END
43 
44 
45 
46 /**
47  * Check that we drew a white outline around the blue polygon
48  */
49 static bool
check_lines_visible(int number)50 check_lines_visible(int number)
51 {
52 	static const float white[3] = {1, 1, 1};
53 	static const float blue[3] = {0, 0, 1};
54 	const int w = piglit_width, h = piglit_height;
55 	const int mx = w / 2, my = h / 2;
56 	float p[4];
57 	bool pass = true;
58 
59 	/* probe bottom */
60 	if (!piglit_probe_pixel_rgb_silent(mx, 1, white, p)) {
61 		piglit_report_subtest_result(PIGLIT_FAIL,
62 			"config %d: Expected white pixel on bottom edge",
63 			number);
64 		pass = false;
65 	}
66 
67 	/* probe top */
68 	if (!piglit_probe_pixel_rgb_silent(mx, h-2, white, p)) {
69 		piglit_report_subtest_result(PIGLIT_FAIL,
70 			"config %d: Expected white pixel on top edge",
71 			number);
72 		pass = false;
73 	}
74 
75 	/* probe left */
76 	if (!piglit_probe_pixel_rgb_silent(1, my, white, p)) {
77 		piglit_report_subtest_result(PIGLIT_FAIL,
78 			"config %d: Expected white pixel on left edge",
79 			number);
80 		pass = false;
81 	}
82 
83 	/* probe right */
84 	if (!piglit_probe_pixel_rgb_silent(w-2, my, white, p)) {
85 		piglit_report_subtest_result(PIGLIT_FAIL,
86 			"config %d: Expected white pixel on right edge",
87 			number);
88 		pass = false;
89 	}
90 
91 	/* probe center */
92 	if (!piglit_probe_pixel_rgb_silent(mx, my, blue, p)) {
93 		piglit_report_subtest_result(PIGLIT_FAIL,
94 			"config %d: Expected blue pixel in center",
95 			number);
96 		pass = false;
97 	}
98 
99 	return pass;
100 }
101 
102 
103 /** Draw rect with clockwise vertices */
104 static void
rect_cw(float coords[2][2])105 rect_cw(float coords[2][2])
106 {
107 	glBegin(GL_POLYGON);
108 	glVertex2f(coords[0][0], coords[0][0]);
109 	glVertex2f(coords[0][0], coords[1][0]);
110 	glVertex2f(coords[1][0], coords[1][0]);
111 	glVertex2f(coords[1][0], coords[0][0]);
112 	glEnd();
113 }
114 
115 
116 /** Draw rect with counter clockwise vertices */
117 static void
rect_ccw(float coords[2][2])118 rect_ccw(float coords[2][2])
119 {
120 	glBegin(GL_POLYGON);
121 	glVertex2f(coords[0][0], coords[0][0]);
122 	glVertex2f(coords[1][0], coords[0][0]);
123 	glVertex2f(coords[1][0], coords[1][0]);
124 	glVertex2f(coords[0][0], coords[1][0]);
125 	glEnd();
126 }
127 
128 
129 enum color { WHITE, BLUE };
130 
131 struct test_config {
132 	GLenum offsetEnable;
133 	float offsetFactor, offsetUnits;
134 	/* first prim: */
135 	GLenum frontMode1, backMode1;
136 	enum color color1;
137 	GLenum winding1;
138 	/* second prim: */
139 	GLenum frontMode2, backMode2;
140 	enum color color2;
141 	GLenum winding2;
142 };
143 
144 
145 /**
146  * For all these test configurations, we should wind up drawing a
147  * blue filled quad with a white outline.
148  */
149 static const struct test_config configs[] = {
150 	{
151 		GL_POLYGON_OFFSET_FILL, 1.0, 1.0,
152 		/* first prim */
153 		GL_LINE, GL_LINE, WHITE, GL_CCW,
154 		/* second prim */
155 		GL_FILL, GL_FILL, BLUE, GL_CCW
156 	},
157 	{
158 		GL_POLYGON_OFFSET_FILL, 1.0, 1.0,
159 		/* first prim */
160 		GL_FILL, GL_FILL, BLUE, GL_CCW,
161 		/* second prim */
162 		GL_LINE, GL_LINE, WHITE, GL_CCW
163 	},
164 	{
165 		GL_POLYGON_OFFSET_FILL, 1.0, 1.0,
166 		/* first prim */
167 		GL_FILL, GL_LINE, BLUE, GL_CCW,
168 		/* second prim */
169 		GL_FILL, GL_LINE, WHITE, GL_CW
170 	},
171 	{
172 		GL_POLYGON_OFFSET_FILL, 1.0, 1.0,
173 		/* first prim */
174 		GL_LINE, GL_FILL, WHITE, GL_CCW,
175 		/* second prim */
176 		GL_LINE, GL_FILL, BLUE, GL_CW
177 	},
178 	{
179 		GL_POLYGON_OFFSET_LINE, 1.0, -1.0,
180 		/* first prim */
181 		GL_LINE, GL_FILL, WHITE, GL_CCW,
182 		/* second prim */
183 		GL_LINE, GL_FILL, BLUE, GL_CW
184 	},
185 	{
186 		GL_POLYGON_OFFSET_LINE, 1.0, -1.0,
187 		/* first prim */
188 		GL_LINE, GL_FILL, BLUE, GL_CW,
189 		/* second prim */
190 		GL_LINE, GL_FILL, WHITE, GL_CCW
191 	},
192 	{
193 		GL_POLYGON_OFFSET_LINE, 1.0, -1.0,
194 		/* first prim */
195 		GL_FILL, GL_LINE, BLUE, GL_CCW,
196 		/* second prim */
197 		GL_FILL, GL_LINE, WHITE, GL_CW
198 	}
199 };
200 
201 
202 /** Test one configuration */
203 static bool
test(int config_number)204 test(int config_number)
205 {
206 	const struct test_config *config = &configs[config_number];
207 	bool pass;
208 	float white_coords[2][2], blue_coords[2][2], (*coords)[2];
209 
210 	/* for drawing the filled quad (cover the whole window) */
211 	blue_coords[0][0] = 0;
212 	blue_coords[0][1] = 0;
213 	blue_coords[1][0] = piglit_width;
214 	blue_coords[1][1] = piglit_height;
215 
216 	/* for drawing the outline (2 pixels smaller than the window size) */
217 	white_coords[0][0] = 1;
218 	white_coords[0][1] = 1;
219 	white_coords[1][0] = piglit_width - 2;
220 	white_coords[1][1] = piglit_height - 2;
221 
222 	assert(config->offsetEnable == GL_POLYGON_OFFSET_FILL ||
223 	       config->offsetEnable == GL_POLYGON_OFFSET_LINE ||
224 	       config->offsetEnable == GL_POLYGON_OFFSET_POINT);
225 
226 	assert(config->frontMode1 == GL_LINE ||
227 	       config->frontMode1 == GL_FILL ||
228 	       config->frontMode1 == GL_POINT);
229 
230 	assert(config->backMode1 == GL_LINE ||
231 	       config->backMode1 == GL_FILL ||
232 	       config->backMode1 == GL_POINT);
233 
234 	assert(config->winding1 == GL_CW ||
235 	       config->winding1 == GL_CCW);
236 
237 	assert(config->winding2 == GL_CW ||
238 	       config->winding2 == GL_CCW);
239 
240 	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
241 
242 	glEnable(config->offsetEnable);
243 	glPolygonOffset(config->offsetFactor, config->offsetUnits);
244 
245 	/* draw first prim */
246 	glPolygonMode(GL_FRONT, config->frontMode1);
247 	glPolygonMode(GL_BACK, config->backMode1);
248 	if (config->color1 == WHITE) {
249 		glColor3f(1, 1, 1);
250 		coords = white_coords;
251 	}
252 	else {
253 		glColor3f(0, 0, 1);
254 		coords = blue_coords;
255 	}
256 
257 	if (config->winding1 == GL_CW)
258 		rect_cw(coords);
259 	else
260 		rect_ccw(coords);
261 
262 	/* draw second prim */
263 	glPolygonMode(GL_FRONT, config->frontMode2);
264 	glPolygonMode(GL_BACK, config->backMode2);
265 	if (config->color2 == WHITE) {
266 		glColor3f(1, 1, 1);
267 		coords = white_coords;
268 	}
269 	else {
270 		glColor3f(0, 0, 1);
271 		coords = blue_coords;
272 	}
273 
274 	if (config->winding2 == GL_CW)
275 		rect_cw(coords);
276 	else
277 		rect_ccw(coords);
278 
279 	/* check results */
280 	pass = check_lines_visible(config_number);
281 
282 	piglit_present_results();
283 
284 	glDisable(config->offsetEnable);
285 
286 	return pass;
287 }
288 
289 
290 enum piglit_result
piglit_display(void)291 piglit_display(void)
292 {
293 	int i;
294 	bool pass = true;
295 
296 	piglit_ortho_projection(piglit_width, piglit_height, GL_FALSE);
297 
298 	/* Sub-pixel translation so that lines hit specific pixels */
299 	glMatrixMode(GL_MODELVIEW);
300 	glLoadIdentity();
301 	glTranslatef(0.375, 0.375, 0.0);
302 
303 	for (i = 0; i < ARRAY_SIZE(configs); i++) {
304 		pass = test(i) && pass;
305 	}
306 
307 	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
308 }
309 
310 
311 void
piglit_init(int argc,char ** argv)312 piglit_init(int argc, char **argv)
313 {
314 	glClearColor(1, 0, 0, 0);
315 	glEnable(GL_DEPTH_TEST);
316 	glDepthFunc(GL_LEQUAL);
317 }
318