Some implementations (i965 in particular) treat primitive restart
differently depending what type of primitive is being drawn. This
test verifies that primitive restart works correctly for all primitive
types.
---
tests/all.tests | 5 +
tests/general/CMakeLists.gl.txt | 1 +
tests/general/primitive-restart-draw-mode.c | 275 ++++++++++++++++++++++++++++
3 files changed, 281 insertions(+)
create mode 100644 tests/general/primitive-restart-draw-mode.c
diff --git a/tests/all.tests b/tests/all.tests
index 7e5bd03..9791e9a 100644
--- a/tests/all.tests
+++ b/tests/all.tests
@@ -2244,6 +2244,11 @@ add_single_param_test_set(
"DISABLE_VBO",
"VBO_VERTEX_ONLY", "VBO_INDEX_ONLY",
"VBO_SEPARATE_VERTEX_AND_INDEX", "VBO_COMBINED_VERTEX_AND_INDEX")
+add_single_param_test_set(
+ nv_primitive_restart,
+ 'primitive-restart-draw-mode',
+ 'points', 'lines', 'line_loop', 'line_strip', 'triangles',
+ 'triangle_strip', 'triangle_fan', 'quads', 'quad_strip', 'polygon')
ext_provoking_vertex = Group()
spec['EXT_provoking_vertex'] = ext_provoking_vertex
diff --git a/tests/general/CMakeLists.gl.txt b/tests/general/CMakeLists.gl.txt
index 0e87baa..98e3271 100644
--- a/tests/general/CMakeLists.gl.txt
+++ b/tests/general/CMakeLists.gl.txt
@@ -94,6 +94,7 @@ piglit_add_executable (point-line-no-cull
point-line-no-cull.c)
piglit_add_executable (polygon-mode-offset polygon-mode-offset.c)
piglit_add_executable (polygon-mode polygon-mode.c)
piglit_add_executable (primitive-restart primitive-restart.c)
+piglit_add_executable (primitive-restart-draw-mode
primitive-restart-draw-mode.c)
piglit_add_executable (provoking-vertex provoking-vertex.c)
piglit_add_executable (push-pop-texture-state push-pop-texture-state.c)
piglit_add_executable (oes-read-format oes-read-format.c)
diff --git a/tests/general/primitive-restart-draw-mode.c
b/tests/general/primitive-restart-draw-mode.c
new file mode 100644
index 0000000..311fd81
--- /dev/null
+++ b/tests/general/primitive-restart-draw-mode.c
@@ -0,0 +1,275 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file primitive-restart-draw-mode.c
+ *
+ * Test proper functioning of primitive restart in all draw modes. In
+ * particular, verify that dangling vertices are properly discarded.
+ *
+ * The test operates as follows:
+ *
+ * - Choose a pattern of 8 vertices which will allow easy visual
+ * inspection of the rendered image. For some primitive types, we
+ * arrange the 8 vertices in an octagon. For others, we arrange
+ * them in two rows, with vertices alternating between the two rows.
+ *
+ * - Construct an index buffer consisting of the values 0 through 7,
+ * interrupted at some location by the primitive restart index, and
+ * draw using the resulting index buffer using glDrawElements().
+ * Seven images are drawn in a vertical array, one for each possible
+ * place where the primitive restart index might interrupt the
+ * indices.
+ *
+ * - To the right of each of the above images, use a pair of calls to
+ * glDrawArrays() to simulate the expected behaviour of primitive
+ * restart.
+ *
+ * - Compare the left and right halves of the resulting window to make
+ * sure they match.
+ *
+ * Note: for easier visual inspection of the result, the image under
+ * test is drawn in blue, and the vertices are drawn in white using
+ * GL_POINTS.
+ */
+
+#include "piglit-util-gl-common.h"
+
+
+#define NUM_VERTICES 8
+#define NUM_ROWS (NUM_VERTICES - 1)
+#define NUM_COLS 2
+#define PATTERN_SIZE 75
+#define VERTEX_ATTR 0
+
+PIGLIT_GL_TEST_CONFIG_BEGIN
+ config.supports_gl_compat_version = 10;
+ config.window_width = PATTERN_SIZE * NUM_COLS;
+ config.window_height = PATTERN_SIZE * NUM_ROWS;
+ config.window_visual = PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_RGBA;
+PIGLIT_GL_TEST_CONFIG_END
+
+
+enum vertex_pattern
+{
+ VERTEX_PATTERN_OCTAGON,
+ VERTEX_PATTERN_2_ROWS,
+ VERTEX_PATTERN_COUNT,
+};
+
+
+static const struct xy_coords
+{
+ GLfloat x;
+ GLfloat y;
+} vertex_patterns[VERTEX_PATTERN_COUNT][NUM_VERTICES] = {
+ /* VERTEX_PATTERN_OCTAGON */
+ {
+ { 27, 69 },
+ { 48, 69 },
+ { 69, 48 },
+ { 69, 27 },
+ { 48, 6 },
+ { 27, 6 },
+ { 6, 27 },
+ { 6, 48 },
+ },
+ /* VERTEX_PATTERN_2_ROWS */
+ {
+ { 20, 63 },
+ { 55, 63 },
+ { 20, 46 },
+ { 55, 46 },
+ { 20, 29 },
+ { 55, 29 },
+ { 20, 12 },
+ { 55, 12 },
+ },
+};
+
+
+static const struct test_desc
+{
+ const char *name;
+ GLenum prim_type;
+ enum vertex_pattern pattern;
+} tests[] = {
+ { "points", GL_POINTS, VERTEX_PATTERN_OCTAGON },
+ { "lines", GL_LINES, VERTEX_PATTERN_OCTAGON },
+ { "line_loop", GL_LINE_LOOP, VERTEX_PATTERN_OCTAGON },
+ { "line_strip", GL_LINE_STRIP, VERTEX_PATTERN_OCTAGON },
+ { "triangles", GL_TRIANGLES, VERTEX_PATTERN_2_ROWS },
+ { "triangle_strip", GL_TRIANGLE_STRIP, VERTEX_PATTERN_2_ROWS },
+ { "triangle_fan", GL_TRIANGLE_FAN, VERTEX_PATTERN_OCTAGON },
+ { "quads", GL_QUADS, VERTEX_PATTERN_OCTAGON },
+ { "quad_strip", GL_QUAD_STRIP, VERTEX_PATTERN_2_ROWS },
+ { "polygon", GL_POLYGON, VERTEX_PATTERN_OCTAGON },
+};
+
+static const struct test_desc *test = NULL;
+
+
+static const char vs_text[] =
+ "#version 110\n"
+ "attribute vec2 vertex;\n"
+ "uniform vec2 offset;\n"
+ "uniform vec2 window_size;\n"
+ "uniform vec4 color;\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = vec4((vertex + offset) / window_size * 2.0 - 1.0,\n"
+ " 0.0, 1.0);\n"
+ " gl_FrontColor = color;\n"
+ "}\n";
+
+
+static GLuint prog;
+static GLint window_size_loc;
+static GLint offset_loc;
+static GLint color_loc;
+
+
+static void
+print_usage_and_exit(const char *prog_name)
+{
+ int i;
+ printf("Usage: %s<subtest>\n"
+ " where<subtest> is one of the following:\n", prog_name);
+ for (i = 0; i< ARRAY_SIZE(tests); i++)
+ printf(" %s\n", tests[i].name);
+ piglit_report_result(PIGLIT_FAIL);
+}
+
+
+void
+piglit_init(int argc, char **argv)
+{
+ int i;
+ GLuint vs;
+
+ /* Parse params */
+ if (argc != 2)
+ print_usage_and_exit(argv[0]);
+ for (i = 0; i< ARRAY_SIZE(tests); i++) {
+ if (strcmp(argv[1], tests[i].name) == 0) {
+ test =&tests[i];
+ break;
+ }
+ }
+ if (test == NULL)
+ print_usage_and_exit(argv[0]);
+
+ piglit_require_GLSL_version(110);
+ if (!piglit_is_extension_supported("GL_NV_primitive_restart")&&
+ piglit_get_gl_version()< 31) {
+ printf("GL_NV_primitive_restart or GL 3.1 required\n");
+ piglit_report_result(PIGLIT_SKIP);
+ }
+
+ prog = glCreateProgram();
+ vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vs_text);
+ glAttachShader(prog, vs);
+ glDeleteShader(vs);
+ glBindAttribLocation(prog, VERTEX_ATTR, "vertex");
+ glLinkProgram(prog);
+ if (!piglit_link_check_status(prog) ||
+ !piglit_check_gl_error(GL_NO_ERROR)) {
+ piglit_report_result(PIGLIT_FAIL);
+ }
+ window_size_loc = glGetUniformLocation(prog, "window_size");
+ offset_loc = glGetUniformLocation(prog, "offset");
+ color_loc = glGetUniformLocation(prog, "color");
+}
+
+
+static void
+draw_pattern(int restart_pos, bool use_primitive_restart)
+{
+ /* Draw test pattern in blue */
+ glUniform4f(color_loc, 0.25, 0.25, 1.0, 1.0);
+ if (use_primitive_restart) {
+ GLubyte index_buffer[NUM_VERTICES + 1];
+ int i;
+
+ for (i = 0; i< restart_pos; i++) {
+ index_buffer[i] = i;
+ }
+ index_buffer[restart_pos] = 0xff;
+ for (i = restart_pos + 1; i< ARRAY_SIZE(index_buffer); i++) {
+ index_buffer[i] = i - 1;
+ }
+ if (piglit_get_gl_version()>= 31) {
+ glEnable(GL_PRIMITIVE_RESTART);
+ glPrimitiveRestartIndex(0xff);
+ } else {
+ glEnableClientState(GL_PRIMITIVE_RESTART_NV);
+ glPrimitiveRestartIndexNV(0xff);
+ }
+ glDrawElements(test->prim_type, ARRAY_SIZE(index_buffer),
+ GL_UNSIGNED_BYTE, index_buffer);
+ if (piglit_get_gl_version()>= 31)
+ glDisable(GL_PRIMITIVE_RESTART);
+ else
+ glDisableClientState(GL_PRIMITIVE_RESTART_NV);
+ } else {
+ glDrawArrays(test->prim_type, 0, restart_pos);
+ glDrawArrays(test->prim_type, restart_pos,
+ NUM_VERTICES - restart_pos);
+ }
+
+ if (test->prim_type != GL_POINTS) {
+ /* Draw vertices in white */
+ glUniform4f(color_loc, 1.0, 1.0, 1.0, 1.0);
+ glDrawArrays(GL_POINTS, 0, NUM_VERTICES);
+ }
+}
+
+
+enum piglit_result
+piglit_display(void)
+{
+ int row, col;
+ bool pass = true;
+
+ glClear(GL_COLOR_BUFFER_BIT);
+ glUseProgram(prog);
+ glUniform2f(window_size_loc, piglit_width, piglit_height);
+ glVertexAttribPointer(VERTEX_ATTR, 2, GL_FLOAT, GL_FALSE,
+ sizeof(vertex_patterns[test->pattern][0]),
+ vertex_patterns[test->pattern]);
+ glEnableVertexAttribArray(VERTEX_ATTR);
+
+ for (col = 0; col< NUM_COLS; col++) {
+ for (row = 0; row< NUM_ROWS; row++) {
+ glUniform2f(offset_loc, col * PATTERN_SIZE,
+ (NUM_ROWS - 1 - row) * PATTERN_SIZE);
+ draw_pattern(row + 1, col == 0);
+ }
+ }
+
+ pass = piglit_probe_rect_halves_equal_rgba(0, 0, piglit_width,
+ piglit_height)&& pass;
+ pass = piglit_check_gl_error(GL_NO_ERROR)&& pass;
+ piglit_present_results();
+ return pass ? PIGLIT_PASS : PIGLIT_FAIL;
+}