ext_gpu_shader4: add compiler tests for everything
[piglit.git] / tests / spec / gl-3.2 / adj-prims.c
blob6faff74d2b1f45808f92d3560a597307dd8e65b9
1 /*
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
13 * Software.
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
21 * IN THE SOFTWARE.
24 /**
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.
31 * Brian Paul
32 * May 2016
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] = {
55 {1.0, 0.2, 0.2, 1.0},
56 {0.2, 1.0, 0.2, 1.0},
57 {0.2, 0.2, 1.0, 1.0},
58 {1.0, 1.0, 1.0, 1.0},
59 {0.2, 1.0, 1.0, 1.0},
60 {1.0, 0.2, 1.0, 1.0},
61 {1.0, 1.0, 0.2, 1.0},
62 {0.5, 1.0, 1.0, 1.0},
63 {1.0, 0.5, 1.0, 1.0},
64 {1.0, 1.0, 0.5, 1.0},
65 {0.7, 1.0, 1.0, 1.0},
66 {1.0, 0.7, 1.0, 1.0},
67 {1.0, 1.0, 0.7, 1.0},
68 {1.0, 0.2, 0.2, 1.0},
69 {0.2, 1.0, 0.2, 1.0},
70 {0.2, 0.2, 1.0, 1.0},
71 {1.0, 1.0, 1.0, 1.0},
72 {0.5, 0.5, 0.5, 1.0}
75 static const float lines_adj_verts[8][2] = {
76 // first line
77 {-1, -.75},
78 {-0.5, -0.25},
79 { 0.5, -0.25},
80 { 1.0, -.75},
81 // second line
82 {-1, 0.0},
83 {-0.5, 0.5},
84 { 0.5, 0.5},
85 { 1.0, 0.0}
88 static const float line_strip_adj_verts[7][2] = {
89 {-1.5, .3},
90 {-1, -.3},
91 {-0.5, .3},
92 { 0.0, -.3},
93 { 0.5, .3},
94 { 1.0, -.3},
95 { 1.5, .3},
98 static const float triangles_adj_verts[6][2] = {
99 {0, -.5},
100 {-1.2, 0},
101 {-.75, 1},
102 {0, 1.5},
103 {0.75, 1},
104 {1.2, 0},
107 static const float triangle_strip_adj_verts[][2] = {
108 {-1.5, -0.5}, // 0
109 {-1.9, 0.0}, // 1
110 {-1.5, 0.5}, // 2
111 {-1, -1}, // 3 *
112 {-1, -.5}, // 4
113 {-1.5, 1}, // 5 *
114 {-1, 0.5}, // 6
115 {-.5, -1}, // 7 *
116 {-.5, -.5}, // 8
117 {-1, 1}, // 9 *
118 {-.5, .5}, // 10
119 {0, -1}, // 11 *
120 {0, -.5}, // 12
121 {-.5, 1}, // 13 *
122 {0, 0.5}, // 14
123 {0.5, -1}, // 15 *
124 {0.5, -.5}, // 16
125 {1, 0}, // 17
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.
160 static unsigned
161 provoking_vertex_index(GLenum prim_mode, GLenum pv_mode, unsigned prim_index)
163 switch (prim_mode) {
164 case GL_LINES_ADJACENCY:
165 if (pv_mode == GL_FIRST_VERTEX_CONVENTION)
166 return prim_index * 4 + 1;
167 else
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;
172 else
173 return prim_index + 2;
174 case GL_TRIANGLES_ADJACENCY:
175 if (pv_mode == GL_FIRST_VERTEX_CONVENTION)
176 return prim_index * 6 + 0;
177 else
178 return prim_index * 6 + 4;
179 case GL_TRIANGLE_STRIP_ADJACENCY:
180 if (pv_mode == GL_FIRST_VERTEX_CONVENTION) {
181 if (prim_index & 1)
182 return prim_index * 2 + 2;
183 else
184 return prim_index * 2;
185 } else
186 return prim_index * 2 + 4;
187 default:
188 assert(!"Unexpected prim_mode");
189 return 0;
195 * Given a primitive type and a primitive (line/triangle) index, return
196 * the (x,y) screen coordinate for probing.
198 static void
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)
203 int i0, i1, i2 = -1;
204 float coord[4], ndc[4], win[3];
206 switch (prim_mode) {
207 case GL_LINES_ADJACENCY:
208 i0 = prim_index * 4 + 1;
209 i1 = prim_index * 4 + 2;
210 break;
211 case GL_LINE_STRIP_ADJACENCY:
212 i0 = prim_index + 1;
213 i1 = prim_index + 2;
214 break;
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;
220 break;
221 case GL_TRIANGLE_STRIP_ADJACENCY:
222 if (prim_index & 1) {
223 i0 = prim_index * 2;
224 i1 = prim_index * 2 + 2;
225 } else {
226 i0 = prim_index * 2 + 2;
227 i1 = prim_index * 2;
229 if (polygon_mode != GL_LINE)
230 i2 = prim_index * 2 + 4;
231 break;
232 default:
233 assert(!"Unexpected prim_mode");
234 *x = *y = 0;
235 return;
238 /* average of 2 or 3 points */
239 if (i2 == -1) {
240 coord[0] = (verts[i0][0] + verts[i1][0]) / 2.0;
241 coord[1] = (verts[i0][1] + verts[i1][1]) / 2.0;
242 } else {
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;
246 coord[2] = 0.0;
247 coord[3] = 1.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);
253 *x = (int) win[0];
254 *y = (int) win[1];
259 * Do the colors match, within an epsilon?
261 static bool
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)
270 return false;
271 else
272 return true;
277 * Given a primitive type and a number of vertices, return the number of
278 * primitives (lines/tris) that'll be drawn.
280 static unsigned
281 num_gs_prims(GLenum prim_mode, unsigned num_verts)
283 switch (prim_mode) {
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;
296 default:
297 assert(!"Unexpected prim_mode");
298 return 0;
304 * Check if a primitive strip was rendered correctly by doing color probing.
305 * vp_pos is the viewport position (0..3).
307 static bool
308 probe_prims(GLenum prim_mode, const float verts[][2], unsigned num_verts,
309 unsigned vp_pos)
311 const int vp_w = piglit_width / 4;
312 const unsigned num_prims = num_gs_prims(prim_mode, num_verts);
313 unsigned prim;
315 for (prim = 0; prim < num_prims; prim++) {
316 bool pass = false;
317 float expected_color[4];
318 float bad_color[4] = { -1 };
319 bool bad_color_found = false;
320 int x, y, i;
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)) {
332 pass = true;
334 } else {
335 GLfloat buf[9][4];
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]))
354 pass = true;
355 else {
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];
366 if (!pass) {
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",
372 expected_color[0],
373 expected_color[1],
374 expected_color[2],
375 expected_color[3]);
376 printf("Found %g, %g, %g, %g\n",
377 bad_color[0],
378 bad_color[1],
379 bad_color[2],
380 bad_color[3]);
383 return false;
387 return true;
390 static bool
391 probe_xfb(GLenum prim_mode, unsigned num_verts)
393 bool pass = true;
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",
413 expected_color[0],
414 expected_color[1],
415 expected_color[2],
416 expected_color[3]);
417 printf("Found %g, %g, %g, %g\n",
418 found_color[0],
419 found_color[1],
420 found_color[2],
421 found_color[3]);
423 pass = false;
427 glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
429 return pass;
433 static GLuint
434 make_gs_program(GLenum input_prim)
436 static const char *vs_text =
437 "#version 150 \n"
438 "in vec4 vertex; \n"
439 "in vec4 color; \n"
440 "uniform mat4 modelViewProj; \n"
441 "out vec4 pos;\n"
442 "out vec4 vs_gs_color; \n"
443 "out int vs_gs_vertex_id; \n"
444 "void main() \n"
445 "{ \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"
450 "} \n";
451 static const char *gs_text_lines =
452 "#version 150 \n"
453 "layout(lines_adjacency) in;\n"
454 "layout(line_strip, max_vertices = 2) out;\n"
455 "in vec4 pos[]; \n"
456 "in vec4 vs_gs_color[4]; \n"
457 "flat out vec4 gs_fs_color; \n"
458 "void main() \n"
459 "{ \n"
460 " gs_fs_color = vs_gs_color[1]; \n"
461 " gl_Position = pos[1]; \n"
462 " EmitVertex(); \n"
463 " gs_fs_color = vs_gs_color[2]; \n"
464 " gl_Position = pos[2]; \n"
465 " EmitVertex(); \n"
466 " EndPrimitive(); \n"
467 "} \n";
468 static const char *gs_text_triangles =
469 "#version 150 \n"
470 "layout(triangles_adjacency) in;\n"
471 "layout(triangle_strip, max_vertices = 3) out;\n"
472 "in vec4 pos[]; \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"
476 "void main() \n"
477 "{ \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"
482 " EmitVertex(); \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"
487 " EmitVertex(); \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"
492 " EmitVertex(); \n"
493 " //EndPrimitive(); \n"
494 "} \n";
495 static const char *fs_text =
496 "#version 150 \n"
497 "flat in vec4 gs_fs_color; \n"
498 "void main() \n"
499 "{ \n"
500 " gl_FragColor = gs_fs_color; \n"
501 "} \n";
502 static const char *gs_xfb_varyings[] = { "gs_fs_color" };
503 const char *gs_text;
504 GLuint program;
506 switch (input_prim) {
507 case GL_LINES_ADJACENCY:
508 case GL_LINE_STRIP_ADJACENCY:
509 gs_text = gs_text_lines;
510 break;
511 case GL_TRIANGLES_ADJACENCY:
512 case GL_TRIANGLE_STRIP_ADJACENCY:
513 gs_text = gs_text_triangles;
514 break;
515 default:
516 assert(!"Unexpected input_prim");
517 return 0;
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,
526 assert(program);
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);
536 return program;
540 static GLuint
541 make_ref_program(void)
543 static const char *vs_text =
544 "#version 150 \n"
545 "in vec4 vertex; \n"
546 "uniform vec4 color; \n"
547 "uniform mat4 modelViewProj; \n"
548 "out vec4 vs_fs_color; \n"
549 "void main() \n"
550 "{ \n"
551 " gl_Position = vertex * modelViewProj; \n"
552 " vs_fs_color = color; \n"
553 "} \n";
555 static const char *fs_text =
556 "#version 150 \n"
557 "in vec4 vs_fs_color; \n"
558 "void main() \n"
559 "{ \n"
560 " gl_FragColor = vs_fs_color; \n"
561 "} \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);
573 return program;
577 static void
578 draw_elements3(GLenum mode, unsigned v0, unsigned v1, unsigned v2)
580 GLushort elements[3];
581 elements[0] = v0;
582 elements[1] = v1;
583 elements[2] = v2;
584 glDrawElements(mode, 3, GL_UNSIGNED_SHORT, elements);
588 static void
589 set_color(const GLfloat c[4])
591 glUniform4fv(colorUniform, 1, c);
595 static void
596 draw_lines_adj(GLuint vao, unsigned n)
598 assert(n % 4 == 0);
600 glBindVertexArray(vao);
602 unsigned i;
603 for (i = 0; i < n; i += 4) {
604 unsigned pvi =
605 provoking_vertex_index(GL_LINES_ADJACENCY,
606 provoking_vertex, i/4);
607 set_color(gray);
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]);
615 // draw "real" line
616 glDrawArrays(GL_LINES, i+1, 2);
622 static void
623 draw_line_strip_adj(GLuint vao, unsigned n)
625 unsigned i;
627 assert(n >= 4);
629 glBindVertexArray(vao);
631 set_color(gray);
632 glDrawArrays(GL_LINES, 0, 2);
633 glDrawArrays(GL_LINES, n-2, 2);
635 for (i = 1; i < n-2; i++) {
636 unsigned pvi =
637 provoking_vertex_index(GL_LINE_STRIP_ADJACENCY,
638 provoking_vertex, i-1);
639 set_color(colors[pvi]);
640 glDrawArrays(GL_LINES, i, 2);
645 static void
646 draw_triangles_adj(GLuint vao, unsigned n)
648 unsigned i;
650 assert(n % 6 == 0);
652 glBindVertexArray(vao);
654 for (i = 0; i < n; i += 6) {
655 unsigned pvi =
656 provoking_vertex_index(GL_TRIANGLES_ADJACENCY,
657 provoking_vertex, i/6);
659 // draw gray outlines of "wing" triangles
660 set_color(gray);
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);
672 static void
673 draw_triangle_strip_adj(GLuint vao, unsigned n)
675 unsigned i;
677 assert(n >= 6);
679 glBindVertexArray(vao);
681 // draw first "wing" triangle
682 set_color(gray);
683 glDrawArrays(GL_LINE_LOOP, 0, 3);
685 for (i = 0; i < n-4; i += 2) {
686 unsigned pvi =
687 provoking_vertex_index(GL_TRIANGLE_STRIP_ADJACENCY,
688 provoking_vertex, i/2);
690 if (i % 4 == 2) {
691 // even tri
692 set_color(gray);
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);
697 else {
698 // odd tri
699 set_color(gray);
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
707 set_color(gray);
708 draw_elements3(GL_LINE_LOOP, i, i+2, i+3);
712 static void
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);
724 static void
725 set_viewport(unsigned pos)
727 int vp_w = piglit_width / 4;
728 assert(pos < 4);
729 glViewport(pos * vp_w, 0, vp_w, piglit_height);
733 static void
734 draw_gs_triangles(GLenum prim_mode, GLuint vao, unsigned num_verts,
735 unsigned vp_pos)
737 size_t buffer_size;
738 void *zeros;
740 use_program(gs_triangles_program);
741 set_viewport(vp_pos);
742 glBindVertexArray(vao);
744 buffer_size =
745 12 * sizeof(float) *
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);
753 free(zeros);
755 glBeginTransformFeedback(GL_TRIANGLES);
757 if (draw_elements) {
758 GLushort* elements;
760 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, element_buf);
761 glBufferData(GL_ELEMENT_ARRAY_BUFFER,
762 sizeof(GLushort) * num_verts, NULL,
763 GL_STATIC_DRAW);
764 elements = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
765 for (unsigned i = 0; i < num_verts; i++) {
766 elements[i] = i;
768 glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
770 glDrawElements(prim_mode, num_verts, GL_UNSIGNED_SHORT, NULL);
771 } else {
772 glDrawArrays(prim_mode, 0, num_verts);
775 glEndTransformFeedback();
778 enum piglit_result
779 piglit_display(void)
781 bool pass = true;
783 glClear(GL_COLOR_BUFFER_BIT);
785 if (draw_with_gs) {
786 use_program(gs_lines_program);
787 set_viewport(0);
788 glBindVertexArray(lines_adj_vao);
789 glDrawArrays(GL_LINES_ADJACENCY, 0,
790 NUM_VERTS(lines_adj_verts));
792 use_program(gs_line_strip_program);
793 set_viewport(1);
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;
810 else {
811 /* This path is basically for debugging and visualizing the
812 * "extra" lines and tris in adjacency primitives.
814 use_program(ref_program);
816 set_viewport(0);
817 draw_lines_adj(lines_adj_vao, 8);
819 set_viewport(1);
820 draw_line_strip_adj(line_strip_adj_vao, 7);
822 set_viewport(2);
823 draw_triangles_adj(triangles_adj_vao, 6);
825 set_viewport(3);
826 draw_triangle_strip_adj(triangle_strip_adj_vao, 17);
829 /* check the rendering */
830 pass = probe_prims(GL_LINES_ADJACENCY,
831 lines_adj_verts,
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,
839 triangles_adj_verts,
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;
852 static GLuint
853 create_vao(const GLfloat (*verts)[2], GLuint numVerts)
855 GLuint vao, vbo;
857 glGenVertexArrays(1, &vao);
858 glBindVertexArray(vao);
860 // positions
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);
868 // colors
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);
875 return vao;
879 void
880 piglit_init(int argc, char **argv)
882 int i;
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)
888 cull_mode = GL_BACK;
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;
899 else
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);
907 glFrontFace(GL_CW);
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();