2 * Copyright © 2014 Intel Corporation
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:
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
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 DEALINGS
24 #include "piglit-util-gl.h"
27 * @file point-vertex-id.c
29 * Tests glPolygonMode(GL_POINT) used in combination with gl_VertexID
30 * or gl_InstanceID or both.
32 * Specify gl_VertexID or gl_InstanceID as an argument to specify
33 * which to test. Alternatively you can specify both in order to test
34 * a combination of both. Additionally ‘divisor’ can be specified to
35 * make it use an instanced array.
37 * See bug #84677 and #91292
40 PIGLIT_GL_TEST_CONFIG_BEGIN
42 config
.supports_gl_compat_version
= 20;
44 config
.window_visual
= PIGLIT_GL_VISUAL_RGBA
| PIGLIT_GL_VISUAL_DOUBLE
;
46 PIGLIT_GL_TEST_CONFIG_END
50 "uniform vec2 viewport_size;\n"
52 "#ifdef USE_VERTEX_ID\n"
53 "uniform vec2 pos_array[12];\n"
58 "#ifdef USE_DIVISOR\n"
59 "in vec2 triangle_offset;\n"
65 "#ifdef USE_VERTEX_ID\n"
66 " vec2 pos = pos_array[gl_VertexID];\n"
68 " gl_Position = vec4(pos, 0.0, 1.0);\n"
69 "#ifdef USE_INSTANCE_ID\n"
70 " float instance_offset = 20.0;\n"
71 "#ifdef USE_DIVISOR\n"
72 " instance_offset = 10.0;\n"
74 " gl_Position.t += float(gl_InstanceID) * instance_offset;\n"
76 "#ifdef USE_DIVISOR\n"
77 " gl_Position.st += triangle_offset;\n"
79 " gl_Position.st = ((gl_Position.st + 0.5) * 2.0 /\n"
80 " viewport_size - 1.0);\n"
81 " gl_FrontColor = vec4(1.0);\n"
89 enum test_mode_flags
{
90 TEST_MODE_VERTEX_ID
= (1 << 0),
91 TEST_MODE_INSTANCE_ID
= (1 << 1),
92 TEST_MODE_DIVISOR
= (1 << 2),
95 static enum test_mode_flags test_modes
;
97 static const struct vertex
102 /* This triangle won't be drawn because none of the vertices
104 { 30, 10, GL_FALSE
},
105 { 40, 10, GL_FALSE
},
106 { 30, 20, GL_FALSE
},
107 /* Copy of the above two triangles but shifted up by 20. If
108 * instanced rendering is used these will be generated based
109 * on the gl_InstanceID or an instanced array instead.
114 { 30, 30, GL_FALSE
},
115 { 40, 30, GL_FALSE
},
116 { 30, 40, GL_FALSE
},
119 /* If a divisor is set then each pair of triangles will be drawn as an
120 * instance and these offsets will be added to each instance.
122 static const struct vertex
123 triangle_offsets
[] = {
128 /* If both the divisor and the instance id is used then these offsets
129 * will be used instead. The remainder of the offset will be added by
132 static const struct vertex
133 triangle_offsets_with_instance_id
[] = {
142 char shader_buf
[sizeof vertex_shader
+ 512];
143 GLint pos_location
= 0, viewport_size_location
;
145 float *ref_image
, *p
;
148 strcpy(shader_buf
, "#version 130\n");
149 if (test_modes
& TEST_MODE_INSTANCE_ID
) {
151 "#extension GL_ARB_draw_instanced : require\n"
152 "#define USE_INSTANCE_ID\n");
154 if (test_modes
& TEST_MODE_DIVISOR
)
155 strcat(shader_buf
, "#define USE_DIVISOR\n");
156 if (test_modes
& TEST_MODE_VERTEX_ID
)
157 strcat(shader_buf
, "#define USE_VERTEX_ID\n");
158 strcat(shader_buf
, vertex_shader
);
160 program
= piglit_build_simple_program(shader_buf
, NULL
);
162 glUseProgram(program
);
164 glClear(GL_COLOR_BUFFER_BIT
);
166 viewport_size_location
= glGetUniformLocation(program
, "viewport_size");
167 glUniform2f(viewport_size_location
,
171 if (test_modes
& TEST_MODE_VERTEX_ID
) {
172 pos_location
= glGetUniformLocation(program
, "pos_array");
174 for (i
= 0; i
< ARRAY_SIZE(vertices
); i
++) {
175 glUniform2f(pos_location
+ i
,
181 glEnableClientState(GL_EDGE_FLAG_ARRAY
);
182 glEdgeFlagPointer(sizeof (struct vertex
),
183 &vertices
[0].edge_flag
);
185 if (!(test_modes
& TEST_MODE_VERTEX_ID
)) {
186 pos_location
= glGetAttribLocation(program
, "pos");
187 if (pos_location
== -1)
188 piglit_report_result(PIGLIT_FAIL
);
189 glEnableVertexAttribArray(pos_location
);
190 glVertexAttribPointer(pos_location
,
193 GL_FALSE
, /* normalized */
194 sizeof (struct vertex
),
198 if (test_modes
& TEST_MODE_DIVISOR
) {
199 pos_location
= glGetAttribLocation(program
, "triangle_offset");
200 if (pos_location
== -1)
201 piglit_report_result(PIGLIT_FAIL
);
202 glEnableVertexAttribArray(pos_location
);
203 glVertexAttribDivisor(pos_location
, 1);
204 glVertexAttribPointer(pos_location
,
207 GL_FALSE
, /* normalized */
208 sizeof (struct vertex
),
209 (test_modes
& TEST_MODE_INSTANCE_ID
) ?
210 &triangle_offsets_with_instance_id
[0].x
:
211 &triangle_offsets
[0].x
);
214 glPolygonMode(GL_FRONT_AND_BACK
, GL_POINT
);
216 if (test_modes
& (TEST_MODE_INSTANCE_ID
| TEST_MODE_DIVISOR
)) {
217 glDrawArraysInstanced(GL_TRIANGLES
,
219 ARRAY_SIZE(vertices
) / 2,
222 glDrawArrays(GL_TRIANGLES
,
224 ARRAY_SIZE(vertices
));
227 ref_image
= malloc(piglit_width
* piglit_height
* 3 *
229 memset(ref_image
, 0, piglit_width
* piglit_height
* 3 * sizeof (float));
230 for (i
= 0; i
< ARRAY_SIZE(vertices
); i
++) {
231 if (!vertices
[i
].edge_flag
)
235 (vertices
[i
].x
+ vertices
[i
].y
* piglit_width
) * 3);
236 p
[0] = p
[1] = p
[2] = 1.0f
;
238 pass
= piglit_probe_image_color(0, 0,
239 piglit_width
, piglit_height
,
244 glDeleteProgram(program
);
246 piglit_present_results();
250 return pass
? PIGLIT_PASS
: PIGLIT_FAIL
;
254 piglit_init(int argc
, char **argv
)
258 for (i
= 1; i
< argc
; i
++) {
259 if (!strcmp(argv
[i
], "gl_VertexID")) {
260 test_modes
|= TEST_MODE_VERTEX_ID
;
261 } else if (!strcmp(argv
[i
], "gl_InstanceID")) {
262 test_modes
|= TEST_MODE_INSTANCE_ID
;
263 } else if (!strcmp(argv
[i
], "divisor")) {
264 test_modes
|= TEST_MODE_DIVISOR
;
266 fprintf(stderr
, "Unknown argument: %s\n", argv
[i
]);
267 piglit_report_result(PIGLIT_FAIL
);
271 if (test_modes
== 0) {
273 "usage: point-vertex-id [gl_VertexID] [gl_InstanceID] "
275 "At least one of the arguments must be specified\n");
276 piglit_report_result(PIGLIT_FAIL
);
279 if (test_modes
& (TEST_MODE_INSTANCE_ID
| TEST_MODE_DIVISOR
))
280 piglit_require_extension("GL_ARB_draw_instanced");
281 if (test_modes
& TEST_MODE_DIVISOR
)
282 piglit_require_extension("GL_ARB_instanced_arrays");
284 piglit_require_GLSL_version(130);