2 * Copyright 2016 VMware, Inc.
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
25 * Test rendering of GS adjacency primitives, with:
26 * - First and last provoking vertex
27 * - Front and back-face culling
28 * - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
29 * See code for command line arguments.
36 #include "piglit-util-gl.h"
37 #include "piglit-matrix.h"
40 PIGLIT_GL_TEST_CONFIG_BEGIN
41 config
.window_width
= 800;
42 config
.window_height
= 200;
43 config
.supports_gl_core_version
= 32;
44 config
.window_visual
= PIGLIT_GL_VISUAL_RGBA
| PIGLIT_GL_VISUAL_DOUBLE
;
45 config
.khr_no_error_support
= PIGLIT_NO_ERRORS
;
46 PIGLIT_GL_TEST_CONFIG_END
49 #define VERTEX_SIZE (2 * sizeof(GLfloat))
51 static const float gray
[4] = { 0.5, 0.5, 0.5, 1.0 };
52 static const float black
[4] = { 0.0, 0.0, 0.0, 0.0 };
54 static const float colors
[18][4] = {
75 static const float lines_adj_verts
[8][2] = {
88 static const float line_strip_adj_verts
[7][2] = {
98 static const float triangles_adj_verts
[6][2] = {
107 static const float triangle_strip_adj_verts
[][2] = {
128 #define NUM_VERTS(ARRAY) (sizeof(ARRAY) / VERTEX_SIZE)
130 static GLfloat ortho_matrix
[16];
132 static GLuint lines_adj_vao
;
133 static GLuint line_strip_adj_vao
;
134 static GLuint triangles_adj_vao
;
135 static GLuint triangle_strip_adj_vao
;
137 static GLenum polygon_mode
= GL_FILL
;
138 static GLenum cull_mode
= GL_NONE
;
139 static GLenum provoking_vertex
= GL_LAST_VERTEX_CONVENTION
;
141 static GLuint gs_lines_program
;
142 static GLuint gs_line_strip_program
;
143 static GLuint gs_triangles_program
;
144 static GLuint gs_triangle_strip_program
;
145 static GLuint xfb_buf
;
146 static GLuint element_buf
;
147 static GLuint ref_program
;
148 static GLint colorUniform
, modelViewProjUniform
;
150 // if false, draw without GS, also draw the 'extra' lines/tris. For debugging.
151 static bool draw_with_gs
= true;
152 static bool draw_elements
= false;
156 * Given a primitive type (adjacency type only), and the first/last provoking
157 * vertex mode, and a primitive (line, triangle) index, return the index of
158 * the vertex which will specify the primitive's flat-shaded color.
161 provoking_vertex_index(GLenum prim_mode
, GLenum pv_mode
, unsigned prim_index
)
164 case GL_LINES_ADJACENCY
:
165 if (pv_mode
== GL_FIRST_VERTEX_CONVENTION
)
166 return prim_index
* 4 + 1;
168 return prim_index
* 4 + 2;
169 case GL_LINE_STRIP_ADJACENCY
:
170 if (pv_mode
== GL_FIRST_VERTEX_CONVENTION
)
171 return prim_index
+ 1;
173 return prim_index
+ 2;
174 case GL_TRIANGLES_ADJACENCY
:
175 if (pv_mode
== GL_FIRST_VERTEX_CONVENTION
)
176 return prim_index
* 6 + 0;
178 return prim_index
* 6 + 4;
179 case GL_TRIANGLE_STRIP_ADJACENCY
:
180 if (pv_mode
== GL_FIRST_VERTEX_CONVENTION
) {
182 return prim_index
* 2 + 2;
184 return prim_index
* 2;
186 return prim_index
* 2 + 4;
188 assert(!"Unexpected prim_mode");
195 * Given a primitive type and a primitive (line/triangle) index, return
196 * the (x,y) screen coordinate for probing.
199 compute_probe_location(GLenum prim_mode
, unsigned prim_index
,
200 const float verts
[][2],
201 int vp_x
, int vp_y
, int *x
, int *y
)
204 float coord
[4], ndc
[4], win
[3];
207 case GL_LINES_ADJACENCY
:
208 i0
= prim_index
* 4 + 1;
209 i1
= prim_index
* 4 + 2;
211 case GL_LINE_STRIP_ADJACENCY
:
215 case GL_TRIANGLES_ADJACENCY
:
216 i0
= prim_index
* 6 + 0;
217 i1
= prim_index
* 6 + 2;
218 if (polygon_mode
!= GL_LINE
)
219 i2
= prim_index
* 6 + 4;
221 case GL_TRIANGLE_STRIP_ADJACENCY
:
222 if (prim_index
& 1) {
224 i1
= prim_index
* 2 + 2;
226 i0
= prim_index
* 2 + 2;
229 if (polygon_mode
!= GL_LINE
)
230 i2
= prim_index
* 2 + 4;
233 assert(!"Unexpected prim_mode");
238 /* average of 2 or 3 points */
240 coord
[0] = (verts
[i0
][0] + verts
[i1
][0]) / 2.0;
241 coord
[1] = (verts
[i0
][1] + verts
[i1
][1]) / 2.0;
243 coord
[0] = (verts
[i0
][0] + verts
[i1
][0] + verts
[i2
][0]) / 3.0;
244 coord
[1] = (verts
[i0
][1] + verts
[i1
][1] + verts
[i2
][1]) / 3.0;
249 piglit_matrix_mul_vector(ndc
, ortho_matrix
, coord
);
250 piglit_ndc_to_window(win
, ndc
, vp_x
, vp_y
,
251 piglit_width
/4, piglit_height
);
259 * Do the colors match, within an epsilon?
262 colors_match(const float c1
[4], const float c2
[4])
264 const float epsilon
= 1.0 / 256.0;
266 if (fabs(c1
[0] - c2
[0]) > epsilon
||
267 fabs(c1
[1] - c2
[1]) > epsilon
||
268 fabs(c1
[2] - c2
[2]) > epsilon
||
269 fabs(c1
[3] - c2
[3]) > epsilon
)
277 * Given a primitive type and a number of vertices, return the number of
278 * primitives (lines/tris) that'll be drawn.
281 num_gs_prims(GLenum prim_mode
, unsigned num_verts
)
284 case GL_LINES_ADJACENCY
:
285 assert(num_verts
% 4 == 0);
286 return num_verts
/ 4;
287 case GL_LINE_STRIP_ADJACENCY
:
288 assert(num_verts
>= 4);
289 return num_verts
- 3;
290 case GL_TRIANGLES_ADJACENCY
:
291 assert(num_verts
% 6 == 0);
292 return num_verts
/ 6;
293 case GL_TRIANGLE_STRIP_ADJACENCY
:
294 assert(num_verts
>= 6);
295 return (num_verts
- 4) / 2;
297 assert(!"Unexpected prim_mode");
304 * Check if a primitive strip was rendered correctly by doing color probing.
305 * vp_pos is the viewport position (0..3).
308 probe_prims(GLenum prim_mode
, const float verts
[][2], unsigned num_verts
,
311 const int vp_w
= piglit_width
/ 4;
312 const unsigned num_prims
= num_gs_prims(prim_mode
, num_verts
);
315 for (prim
= 0; prim
< num_prims
; prim
++) {
317 float expected_color
[4];
318 float bad_color
[4] = { -1 };
319 bool bad_color_found
= false;
322 compute_probe_location(prim_mode
, prim
, verts
,
323 vp_pos
* vp_w
, 0, &x
, &y
);
325 if (cull_mode
== GL_FRONT
&&
326 (prim_mode
== GL_TRIANGLES_ADJACENCY
||
327 prim_mode
== GL_TRIANGLE_STRIP_ADJACENCY
)) {
328 // All triangles should be front facing.
329 // With front culling, all should be discarded.
330 // Region should be black.
331 if (piglit_probe_rect_rgba(x
-1, y
-1, 3, 3, black
)) {
336 unsigned pvi
= provoking_vertex_index(prim_mode
,
337 provoking_vertex
, prim
);
338 memcpy(&expected_color
, colors
[pvi
], sizeof(expected_color
));
339 if (prim_mode
== GL_TRIANGLES_ADJACENCY
||
340 prim_mode
== GL_TRIANGLE_STRIP_ADJACENCY
) {
341 expected_color
[2] = pvi
* (1.0 / 255);
342 expected_color
[3] = provoking_vertex
== GL_FIRST_VERTEX_CONVENTION
? 0.0 : 1.0;
345 // Read a 3x3 region for line probing
346 glReadPixels(x
-1, y
-1, 3, 3, GL_RGBA
, GL_FLOAT
, buf
);
348 // look for non-black pixel
349 for (i
= 0; i
< 9; i
++) {
350 if (buf
[i
][0] != 0 || buf
[i
][1] != 0 ||
351 buf
[i
][2] != 0 || buf
[i
][3] != 0) {
352 // check for expected color
353 if (colors_match(expected_color
, buf
[i
]))
356 bad_color_found
= true;
357 bad_color
[0] = buf
[i
][0];
358 bad_color
[1] = buf
[i
][1];
359 bad_color
[2] = buf
[i
][2];
360 bad_color
[3] = buf
[i
][3];
367 printf("Failure for %s, "
368 "prim %u wrong color at (%d,%d)\n",
369 piglit_get_prim_name(prim_mode
), prim
, x
, y
);
370 if (bad_color_found
) {
371 printf("Expected %g, %g, %g, %g\n",
376 printf("Found %g, %g, %g, %g\n",
391 probe_xfb(GLenum prim_mode
, unsigned num_verts
)
394 const unsigned num_prims
= num_gs_prims(prim_mode
, num_verts
);
395 const float *xfb_data
= glMapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER
, GL_READ_ONLY
);
397 for (unsigned prim
= 0; prim
< num_prims
; prim
++) {
398 const float *found_color
;
399 float expected_color
[4];
400 unsigned pvi
= provoking_vertex_index(prim_mode
,
401 provoking_vertex
, prim
);
403 memcpy(&expected_color
, colors
[pvi
], sizeof(expected_color
));
404 expected_color
[2] = pvi
* (1.0 / 255);
405 expected_color
[3] = provoking_vertex
== GL_FIRST_VERTEX_CONVENTION
? 0.0 : 1.0;
407 found_color
= xfb_data
+ 4 * (3 * prim
+ (provoking_vertex
== GL_FIRST_VERTEX_CONVENTION
? 0 : 2));
409 if (!colors_match(expected_color
, found_color
)) {
410 printf("Transform Feedback Failure for %s, prim %u wrong color\n",
411 piglit_get_prim_name(prim_mode
), prim
);
412 printf("Expected %g, %g, %g, %g\n",
417 printf("Found %g, %g, %g, %g\n",
427 glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER
);
434 make_gs_program(GLenum input_prim
)
436 static const char *vs_text
=
440 "uniform mat4 modelViewProj; \n"
442 "out vec4 vs_gs_color; \n"
443 "out int vs_gs_vertex_id; \n"
446 " gl_Position = vertex * modelViewProj; \n"
447 " pos = vertex * modelViewProj; \n"
448 " vs_gs_color = color; \n"
449 " vs_gs_vertex_id = gl_VertexID; \n"
451 static const char *gs_text_lines
=
453 "layout(lines_adjacency) in;\n"
454 "layout(line_strip, max_vertices = 2) out;\n"
456 "in vec4 vs_gs_color[4]; \n"
457 "flat out vec4 gs_fs_color; \n"
460 " gs_fs_color = vs_gs_color[1]; \n"
461 " gl_Position = pos[1]; \n"
463 " gs_fs_color = vs_gs_color[2]; \n"
464 " gl_Position = pos[2]; \n"
466 " EndPrimitive(); \n"
468 static const char *gs_text_triangles
=
470 "layout(triangles_adjacency) in;\n"
471 "layout(triangle_strip, max_vertices = 3) out;\n"
473 "in vec4 vs_gs_color[6]; \n"
474 "in int vs_gs_vertex_id[6]; \n"
475 "flat out vec4 gs_fs_color; \n"
478 " gs_fs_color = vs_gs_color[0]; \n"
479 " gs_fs_color.b = vs_gs_vertex_id[0] * (1. / 255.); \n"
480 " gs_fs_color.a = 0.0; \n"
481 " gl_Position = pos[0]; \n"
483 " gs_fs_color = vs_gs_color[2]; \n"
484 " gs_fs_color.b = vs_gs_vertex_id[2] * (1. / 255.); \n"
485 " gs_fs_color.a = 0.5; \n"
486 " gl_Position = pos[2]; \n"
488 " gs_fs_color = vs_gs_color[4]; \n"
489 " gs_fs_color.b = vs_gs_vertex_id[4] * (1. / 255.); \n"
490 " gs_fs_color.a = 1.0; \n"
491 " gl_Position = pos[4]; \n"
493 " //EndPrimitive(); \n"
495 static const char *fs_text
=
497 "flat in vec4 gs_fs_color; \n"
500 " gl_FragColor = gs_fs_color; \n"
502 static const char *gs_xfb_varyings
[] = { "gs_fs_color" };
506 switch (input_prim
) {
507 case GL_LINES_ADJACENCY
:
508 case GL_LINE_STRIP_ADJACENCY
:
509 gs_text
= gs_text_lines
;
511 case GL_TRIANGLES_ADJACENCY
:
512 case GL_TRIANGLE_STRIP_ADJACENCY
:
513 gs_text
= gs_text_triangles
;
516 assert(!"Unexpected input_prim");
520 program
= piglit_build_simple_program_unlinked_multiple_shaders(
521 GL_VERTEX_SHADER
, vs_text
,
522 GL_GEOMETRY_SHADER
, gs_text
,
523 GL_FRAGMENT_SHADER
, fs_text
,
528 glBindAttribLocation(program
, 0, "vertex");
529 glBindAttribLocation(program
, 1, "color");
531 glTransformFeedbackVaryings(program
, 1, &gs_xfb_varyings
[0],
532 GL_INTERLEAVED_ATTRIBS
);
534 glLinkProgram(program
);
541 make_ref_program(void)
543 static const char *vs_text
=
546 "uniform vec4 color; \n"
547 "uniform mat4 modelViewProj; \n"
548 "out vec4 vs_fs_color; \n"
551 " gl_Position = vertex * modelViewProj; \n"
552 " vs_fs_color = color; \n"
555 static const char *fs_text
=
557 "in vec4 vs_fs_color; \n"
560 " gl_FragColor = vs_fs_color; \n"
563 GLuint program
= piglit_build_simple_program_unlinked_multiple_shaders(
564 GL_VERTEX_SHADER
, vs_text
,
565 GL_FRAGMENT_SHADER
, fs_text
,
568 glBindAttribLocation(program
, 0, "vertex");
569 glBindAttribLocation(program
, 1, "color");
571 glLinkProgram(program
);
578 draw_elements3(GLenum mode
, unsigned v0
, unsigned v1
, unsigned v2
)
580 GLushort elements
[3];
584 glDrawElements(mode
, 3, GL_UNSIGNED_SHORT
, elements
);
589 set_color(const GLfloat c
[4])
591 glUniform4fv(colorUniform
, 1, c
);
596 draw_lines_adj(GLuint vao
, unsigned n
)
600 glBindVertexArray(vao
);
603 for (i
= 0; i
< n
; i
+= 4) {
605 provoking_vertex_index(GL_LINES_ADJACENCY
,
606 provoking_vertex
, i
/4);
609 // draw preceeding "wing" line
610 glDrawArrays(GL_LINES
, i
, 2);
611 // draw trailing "wing" line
612 glDrawArrays(GL_LINES
, i
+2, 2);
614 set_color(colors
[pvi
]);
616 glDrawArrays(GL_LINES
, i
+1, 2);
623 draw_line_strip_adj(GLuint vao
, unsigned n
)
629 glBindVertexArray(vao
);
632 glDrawArrays(GL_LINES
, 0, 2);
633 glDrawArrays(GL_LINES
, n
-2, 2);
635 for (i
= 1; i
< n
-2; i
++) {
637 provoking_vertex_index(GL_LINE_STRIP_ADJACENCY
,
638 provoking_vertex
, i
-1);
639 set_color(colors
[pvi
]);
640 glDrawArrays(GL_LINES
, i
, 2);
646 draw_triangles_adj(GLuint vao
, unsigned n
)
652 glBindVertexArray(vao
);
654 for (i
= 0; i
< n
; i
+= 6) {
656 provoking_vertex_index(GL_TRIANGLES_ADJACENCY
,
657 provoking_vertex
, i
/6);
659 // draw gray outlines of "wing" triangles
661 draw_elements3(GL_LINE_LOOP
, i
, i
+1, i
+2);
662 draw_elements3(GL_LINE_LOOP
, i
+2, i
+3, i
+4);
663 draw_elements3(GL_LINE_LOOP
, i
, i
+4, i
+5);
665 // draw "real" triangle
666 set_color(colors
[pvi
]);
667 draw_elements3(GL_TRIANGLES
, i
, i
+2, i
+4);
673 draw_triangle_strip_adj(GLuint vao
, unsigned n
)
679 glBindVertexArray(vao
);
681 // draw first "wing" triangle
683 glDrawArrays(GL_LINE_LOOP
, 0, 3);
685 for (i
= 0; i
< n
-4; i
+= 2) {
687 provoking_vertex_index(GL_TRIANGLE_STRIP_ADJACENCY
,
688 provoking_vertex
, i
/2);
693 draw_elements3(GL_LINE_LOOP
, i
, i
+3, i
+4);
694 set_color(colors
[pvi
]);
695 draw_elements3(GL_TRIANGLES
, i
, i
+4, i
+2);
700 draw_elements3(GL_LINE_LOOP
, i
, i
+4, i
+3);
701 set_color(colors
[pvi
]);
702 draw_elements3(GL_TRIANGLES
, i
, i
+2, i
+4);
706 // draw last "wing" triangle
708 draw_elements3(GL_LINE_LOOP
, i
, i
+2, i
+3);
713 use_program(GLuint program
)
715 glUseProgram(program
);
716 modelViewProjUniform
= glGetUniformLocation(program
, "modelViewProj");
717 colorUniform
= glGetUniformLocation(program
, "color");
719 piglit_ortho_matrix(ortho_matrix
, -2, 2, -2, 2, -1, 1);
720 glUniformMatrix4fv(modelViewProjUniform
, 1, GL_FALSE
, ortho_matrix
);
725 set_viewport(unsigned pos
)
727 int vp_w
= piglit_width
/ 4;
729 glViewport(pos
* vp_w
, 0, vp_w
, piglit_height
);
734 draw_gs_triangles(GLenum prim_mode
, GLuint vao
, unsigned num_verts
,
740 use_program(gs_triangles_program
);
741 set_viewport(vp_pos
);
742 glBindVertexArray(vao
);
746 num_gs_prims(prim_mode
, num_verts
);
747 zeros
= calloc(1, buffer_size
);
749 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER
, 0, xfb_buf
);
750 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER
, buffer_size
,
751 zeros
, GL_STREAM_READ
);
755 glBeginTransformFeedback(GL_TRIANGLES
);
760 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, element_buf
);
761 glBufferData(GL_ELEMENT_ARRAY_BUFFER
,
762 sizeof(GLushort
) * num_verts
, NULL
,
764 elements
= glMapBuffer(GL_ELEMENT_ARRAY_BUFFER
, GL_WRITE_ONLY
);
765 for (unsigned i
= 0; i
< num_verts
; i
++) {
768 glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER
);
770 glDrawElements(prim_mode
, num_verts
, GL_UNSIGNED_SHORT
, NULL
);
772 glDrawArrays(prim_mode
, 0, num_verts
);
775 glEndTransformFeedback();
783 glClear(GL_COLOR_BUFFER_BIT
);
786 use_program(gs_lines_program
);
788 glBindVertexArray(lines_adj_vao
);
789 glDrawArrays(GL_LINES_ADJACENCY
, 0,
790 NUM_VERTS(lines_adj_verts
));
792 use_program(gs_line_strip_program
);
794 glBindVertexArray(line_strip_adj_vao
);
795 glDrawArrays(GL_LINE_STRIP_ADJACENCY
, 0,
796 NUM_VERTS(line_strip_adj_verts
));
798 draw_gs_triangles(GL_TRIANGLES_ADJACENCY
, triangles_adj_vao
,
799 NUM_VERTS(triangles_adj_verts
), 2);
801 pass
= probe_xfb(GL_TRIANGLES_ADJACENCY
,
802 NUM_VERTS(triangles_adj_verts
)) && pass
;
804 draw_gs_triangles(GL_TRIANGLE_STRIP_ADJACENCY
, triangle_strip_adj_vao
,
805 NUM_VERTS(triangle_strip_adj_verts
), 3);
807 pass
= probe_xfb(GL_TRIANGLE_STRIP_ADJACENCY
,
808 NUM_VERTS(triangle_strip_adj_verts
)) && pass
;
811 /* This path is basically for debugging and visualizing the
812 * "extra" lines and tris in adjacency primitives.
814 use_program(ref_program
);
817 draw_lines_adj(lines_adj_vao
, 8);
820 draw_line_strip_adj(line_strip_adj_vao
, 7);
823 draw_triangles_adj(triangles_adj_vao
, 6);
826 draw_triangle_strip_adj(triangle_strip_adj_vao
, 17);
829 /* check the rendering */
830 pass
= probe_prims(GL_LINES_ADJACENCY
,
832 NUM_VERTS(lines_adj_verts
), 0) && pass
;
834 pass
= probe_prims(GL_LINE_STRIP_ADJACENCY
,
835 line_strip_adj_verts
,
836 NUM_VERTS(line_strip_adj_verts
), 1) && pass
;
838 pass
= probe_prims(GL_TRIANGLES_ADJACENCY
,
840 NUM_VERTS(triangles_adj_verts
), 2) && pass
;
842 pass
= probe_prims(GL_TRIANGLE_STRIP_ADJACENCY
,
843 triangle_strip_adj_verts
,
844 NUM_VERTS(triangle_strip_adj_verts
), 3) && pass
;
846 piglit_present_results();
848 return pass
? PIGLIT_PASS
: PIGLIT_FAIL
;
853 create_vao(const GLfloat (*verts
)[2], GLuint numVerts
)
857 glGenVertexArrays(1, &vao
);
858 glBindVertexArray(vao
);
861 glGenBuffers(1, &vbo
);
862 glBindBuffer(GL_ARRAY_BUFFER
, vbo
);
863 glBufferData(GL_ARRAY_BUFFER
, numVerts
* VERTEX_SIZE
,
864 verts
, GL_STATIC_DRAW
);
865 glVertexAttribPointer(0, 2, GL_FLOAT
, GL_FALSE
, VERTEX_SIZE
, NULL
);
866 glEnableVertexAttribArray(0);
869 glGenBuffers(1, &vbo
);
870 glBindBuffer(GL_ARRAY_BUFFER
, vbo
);
871 glBufferData(GL_ARRAY_BUFFER
, sizeof(colors
), colors
, GL_STATIC_DRAW
);
872 glVertexAttribPointer(1, 4, GL_FLOAT
, GL_FALSE
, 4*sizeof(GLfloat
), NULL
);
873 glEnableVertexAttribArray(1);
880 piglit_init(int argc
, char **argv
)
884 for (i
= 1; i
< argc
; i
++) {
885 if (strcmp(argv
[i
], "line") == 0)
886 polygon_mode
= GL_LINE
;
887 else if (strcmp(argv
[i
], "cull-back") == 0)
889 else if (strcmp(argv
[i
], "cull-front") == 0)
890 cull_mode
= GL_FRONT
;
891 else if (strcmp(argv
[i
], "ref") == 0)
892 draw_with_gs
= GL_FALSE
;
893 else if (strcmp(argv
[i
], "pv-last") == 0)
894 provoking_vertex
= GL_LAST_VERTEX_CONVENTION
;
895 else if (strcmp(argv
[i
], "pv-first") == 0)
896 provoking_vertex
= GL_FIRST_VERTEX_CONVENTION
;
897 else if (strcmp(argv
[i
], "elements") == 0)
898 draw_elements
= true;
900 printf("Unexpected %s argument\n", argv
[i
]);
903 glPolygonMode(GL_FRONT_AND_BACK
, polygon_mode
);
904 if (cull_mode
!= GL_NONE
) {
905 glCullFace(cull_mode
);
906 glEnable(GL_CULL_FACE
);
909 glProvokingVertex(provoking_vertex
);
911 glGenBuffers(1, &xfb_buf
);
912 glGenBuffers(1, &element_buf
);
914 lines_adj_vao
= create_vao(lines_adj_verts
,
915 NUM_VERTS(lines_adj_verts
));
917 line_strip_adj_vao
= create_vao(line_strip_adj_verts
,
918 NUM_VERTS(line_strip_adj_verts
));
920 triangles_adj_vao
= create_vao(triangles_adj_verts
,
921 NUM_VERTS(triangles_adj_verts
));
923 triangle_strip_adj_vao
= create_vao(triangle_strip_adj_verts
,
924 NUM_VERTS(triangle_strip_adj_verts
));
926 gs_lines_program
= make_gs_program(GL_LINES_ADJACENCY
);
927 gs_line_strip_program
= make_gs_program(GL_LINE_STRIP_ADJACENCY
);
928 gs_triangles_program
= make_gs_program(GL_TRIANGLES_ADJACENCY
);
929 gs_triangle_strip_program
= make_gs_program(GL_TRIANGLE_STRIP_ADJACENCY
);
930 ref_program
= make_ref_program();