1 /*
2  * Copyright © 2013 The Piglit project
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  * \file ignore-adjacent-vertices.c
26  *
27  * Test that adjacent vertices are ignored when no geometry shader is active.
28  * Draw the adjacency primitive in red and blend the non adjacency version in
29  * green on top of it. Then test that the entire framebuffer is either yellow
30  * or black.
31  *
32  * From the ARB_geometry_shader4 spec section 2.6.1:
33  * "If a geometry shader is not active, the "adjacent" vertices are ignored."
34  */
35 
36 #include "piglit-util-gl.h"
37 
38 struct primitive {
39 	GLenum type;
40 	int count;
41 	unsigned short indices[12];
42 };
43 
44 static const struct primitives {
45 	struct primitive  adjacency, base;
46 } tests[] = {
47 	{
48 		{GL_LINES_ADJACENCY, 8,
49 		{4, 5, 6, 7, 8, 9, 10, 11} },
50 		{GL_LINES, 4,
51 		{5, 6, 9, 10} }
52 	},
53 	{
54 		{GL_LINE_STRIP_ADJACENCY, 6,
55 		{4, 5, 6, 10, 9, 8} },
56 		{GL_LINE_STRIP, 4,
57 		{5, 6, 10, 9} }
58 	},
59 	{
60 		{GL_TRIANGLES_ADJACENCY, 12,
61 		{9, 4, 5, 6, 10, 14, 6, 11, 10, 9, 5, 1} },
62 		{GL_TRIANGLES, 6,
63 		{9, 5, 10, 6, 10, 5} }
64 	},
65 	{
66 		{GL_TRIANGLE_STRIP_ADJACENCY, 8,
67 		{9, 4, 5, 14, 10, 1, 6, 11} },
68 		{GL_TRIANGLE_STRIP, 4,
69 		{9, 5, 10, 6} }
70 	}
71 };
72 
73 static const float vertex_data[] = {
74 	-1, 1, -1/3., 1, 1/3., 1, 1, 1,
75 	0, 1/3., -1/3., 1/3., 1/3., 1/3., 1, 1/3.,
76 	0, -1/3., -1/3., -1/3., 1/3., -1/3., 1, -1/3.,
77 	0, 0, -1/3., 0, 1/3., 0, 1, 0,
78 };
79 
80 static const char vs_text[] =
81 	"attribute vec4 vertex;\n"
82 	"void main()\n"
83 	"{\n"
84 	"	gl_Position = vertex;\n"
85 	"}\n";
86 
87 static const char fs_text[] =
88 	"uniform vec4 color;\n"
89 	"void main()\n"
90 	"{\n"
91 	"	gl_FragColor = color;\n"
92 	"}\n";
93 
94 static const struct primitives *test;
95 static bool indexed = false;
96 static bool use_core = false;
97 
98 static void
99 parse_cmd_line(int argc, char **argv);
100 
101 PIGLIT_GL_TEST_CONFIG_BEGIN
102 	parse_cmd_line(argc, argv);
103 	if (!use_core) {
104 		config.supports_gl_compat_version = 20;
105 		config.supports_gl_core_version = 31;
106 	} else {
107 		config.supports_gl_compat_version = 32;
108 		config.supports_gl_core_version = 32;
109 	}
110 	config.window_visual = PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_RGBA;
111 PIGLIT_GL_TEST_CONFIG_END
112 
113 GLuint color_uniform;
114 
115 /* Parse command line arguments.
116  *
117  * Recognized command line arguments are:
118  *     * The primitive type with adjacency to test (one of GL_LINES_ADJACENCY,
119  *       GL_LINE_STRIP_ADJACENCY, GL_TRIANGLES_ADJACENCY or
120  *       GL_TRIANGLE_STRIP_ADJACENCY).
121  *     * The optional argument "indexed" to use indexed drawing.
122  *     * The optional argument "core" to use GLSL 1.50
123  */
124 static void
parse_cmd_line(int argc,char ** argv)125 parse_cmd_line(int argc, char **argv)
126 {
127 	int i, j;
128 
129 	for (i = 1; i < argc; i++) {
130 		for (j = 0; j < ARRAY_SIZE(tests); j++) {
131 			if (strcmp(argv[i],
132 			    piglit_get_prim_name(tests[j].adjacency.type)) == 0)
133 				test = &tests[j];
134 		}
135 		if (strcmp(argv[i], "indexed") == 0)
136 			indexed = true;
137 		else if (strcmp(argv[i], "core") == 0)
138 			use_core = true;
139 	}
140 
141 	if (test == NULL) {
142 		fprintf(stderr, "Please specify the adjacent primitive type "
143 			"to test on the command line\n");
144 		piglit_report_result(PIGLIT_FAIL);
145 	}
146 }
147 
148 void
piglit_init(int argc,char ** argv)149 piglit_init(int argc, char **argv)
150 {
151 		GLuint array_bufs[2];
152 	GLuint array;
153 	GLuint prog;
154 
155 	if (!use_core)
156 		piglit_require_extension("GL_ARB_geometry_shader4");
157 
158 	/* Bind Vertex Data */
159 	glGenVertexArrays(1, &array);
160 	glBindVertexArray(array);
161 	glGenBuffers(2, array_bufs);
162 	glBindBuffer(GL_ARRAY_BUFFER, array_bufs[0]);
163 	if (indexed)
164 		glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data),
165 			     vertex_data, GL_STREAM_DRAW);
166 	glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
167 	glEnableVertexAttribArray(0);
168 
169 	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, array_bufs[1]);
170 
171 	/* Create shader. */
172 	prog = piglit_build_simple_program(vs_text, fs_text);
173 	glBindAttribLocation(prog, 0, "vertex");
174 	glLinkProgram(prog);
175 	color_uniform = glGetUniformLocation(prog, "color");
176 	glUseProgram(prog);
177 
178 	/* Enable blending. */
179 	glEnable(GL_BLEND);
180 	glBlendEquation(GL_FUNC_ADD);
181 	glBlendFunc(GL_ONE, GL_ONE);
182 }
183 
184 static void
draw(const struct primitive prim)185 draw(const struct primitive prim)
186 {
187 	if (indexed) {
188 		/* Upload index data and draw. */
189 		glBufferData(GL_ELEMENT_ARRAY_BUFFER, prim.count * 2,
190 			     prim.indices, GL_STREAM_DRAW);
191 		glDrawElements(prim.type, prim.count, GL_UNSIGNED_SHORT, NULL);
192 	} else {
193 		int i;
194 		float data[24];
195 
196 		/* Build vertex data, upload it and draw. */
197 		for (i = 0; i < prim.count; ++i) {
198 			data[2 * i + 0] = vertex_data[2 * prim.indices[i] + 0];
199 			data[2 * i + 1] = vertex_data[2 * prim.indices[i] + 1];
200 		}
201 		glBufferData(GL_ARRAY_BUFFER, prim.count * 2 * 4, data,
202 			     GL_STREAM_DRAW);
203 		glDrawArrays(prim.type, 0, prim.count);
204 	}
205 }
206 
207 enum piglit_result
piglit_display(void)208 piglit_display(void)
209 {
210 	bool pass = true;
211 	const float black[] = {0, 0, 0, 1};
212 	const float red[] = {1, 0, 0, 1};
213 	const float green[] = {0, 1, 0, 1};
214 	const float yellow[] = {1, 1, 0, 1};
215 
216 	glClear(GL_COLOR_BUFFER_BIT);
217 
218 	/* Draw adjacency primitive red. */
219 	glUniform4fv(color_uniform, 1, red);
220 	draw(test->adjacency);
221 
222 	/* Draw normal primitive green. */
223 	glUniform4fv(color_uniform, 1, green);
224 	draw(test->base);
225 
226 	pass = piglit_probe_rect_two_rgb(0, 0, piglit_width, piglit_height,
227 					 black, yellow) && pass;
228 	pass = piglit_check_gl_error(GL_NO_ERROR) && pass;
229 
230 	if (!piglit_automatic)
231 		piglit_present_results();
232 
233 	return (pass ? PIGLIT_PASS : PIGLIT_FAIL);
234 }
235