[Piglit] [PATCH 2/6] Add vbo support to shader_runner.

Paul Berry stereotype441 at gmail.com
Thu Oct 27 10:42:05 PDT 2011


On 27 October 2011 10:32, Ian Romanick <idr at freedesktop.org> wrote:

> On 10/20/2011 02:12 PM, Paul Berry wrote:
>
>> This patch adds the ability for shader_runner tests to include a
>> "[vertex data]" section containing data in columnar format, for example:
>>
>> [vertex data]
>> vertex/float/3 foo/uint/1 bar/int/2
>> 0.0 0.0 0.0    0xe0000000 0 0
>> 0.0 1.0 0.0    0x70000000 1 1
>> 1.0 1.0 0.0    0x00000000 0 1
>>
>> Each column header is of the form ATTRNAME/TYPE/COUNT, where ATTRNAME
>> is the name of the vertex attribute to be bound to this column, TYPE
>> is the type of data that follows ("float", "int", or "uint"), and
>> COUNT is the vector length of the data (e.g. "3" for vec3 data).
>>
>> To send vertex data to the shader, use the new shader_runner command
>> "draw arrays".  The parameters are the same as for the glDrawArrays()
>> command, so for example to draw triangle primitives using 3 elements
>> from the vertex data array starting at element 0, use the command:
>>
>> draw arrays GL_TRIANGLES 0 3
>>
>> More detailed examples can be found in the tests/shaders/vbo
>> directory.
>>
>> The implementation is largely in a new file, piglit-vbo.cpp, so that
>> it can be re-used by other piglit tests if necessary.
>> ---
>>  tests/shaders/shader_runner.c                   |   80 ++++
>>  tests/shaders/vbo/vbo-generic-**float.shader_test |   37 ++
>>  tests/shaders/vbo/vbo-generic-**int.shader_test   |   39 ++
>>  tests/shaders/vbo/vbo-generic-**uint.shader_test  |   39 ++
>>  tests/util/CMakeLists.gl.txt                    |    1 +
>>  tests/util/piglit-vbo.cpp                       |  514
>> +++++++++++++++++++++++
>>  tests/util/piglit-vbo.h                         |   35 ++
>>  7 files changed, 745 insertions(+), 0 deletions(-)
>>  create mode 100644 tests/shaders/vbo/vbo-generic-**float.shader_test
>>  create mode 100644 tests/shaders/vbo/vbo-generic-**int.shader_test
>>  create mode 100644 tests/shaders/vbo/vbo-generic-**uint.shader_test
>>  create mode 100644 tests/util/piglit-vbo.cpp
>>  create mode 100644 tests/util/piglit-vbo.h
>>
>> diff --git a/tests/shaders/shader_runner.**c
>> b/tests/shaders/shader_runner.**c
>> index b07ff55..77a753c 100644
>> --- a/tests/shaders/shader_runner.**c
>> +++ b/tests/shaders/shader_runner.**c
>> @@ -37,6 +37,7 @@
>>  #include<libgen.h>
>>  #endif
>>  #include "piglit-util.h"
>> +#include "piglit-vbo.h"
>>
>>  int piglit_width = 250, piglit_height = 250;
>>  int piglit_window_mode = GLUT_RGB | GLUT_ALPHA | GLUT_DOUBLE;
>> @@ -65,7 +66,10 @@ unsigned num_fragment_shaders = 0;
>>  char *shader_strings[256];
>>  GLsizei shader_string_sizes[256];
>>  unsigned num_shader_strings = 0;
>> +const char *vertex_data_start = NULL;
>> +const char *vertex_data_end = NULL;
>>  GLuint prog;
>> +size_t num_vbo_rows = 0;
>>
>>  enum states {
>>        none = 0,
>> @@ -79,6 +83,7 @@ enum states {
>>        fragment_shader,
>>        fragment_shader_file,
>>        fragment_program,
>> +       vertex_data,
>>        test,
>>  };
>>
>> @@ -473,6 +478,10 @@ leave_state(enum states state, const char *line)
>>        case fragment_program:
>>                break;
>>
>> +       case vertex_data:
>> +               vertex_data_end = line;
>> +               break;
>> +
>>        case test:
>>                break;
>>
>> @@ -592,6 +601,9 @@ process_test_script(const char *script_name)
>>                                state = fragment_shader_file;
>>                                shader_strings[0] = NULL;
>>                                num_shader_strings = 0;
>> +                       } else if (strncmp(line, "[vertex data]", 13) ==
>> 0) {
>> +                               state = vertex_data;
>> +                               vertex_data_start = NULL;
>>                        } else if (strncmp(line, "[test]", 6) == 0) {
>>                                test_start = strchrnul(line, '\n');
>>                                if (test_start[0] != '\0')
>> @@ -625,6 +637,11 @@ process_test_script(const char *script_name)
>>                                    load_shader_file(line);
>>                                break;
>>
>> +                       case vertex_data:
>> +                               if (vertex_data_start == NULL)
>> +                                       vertex_data_start = line;
>> +                               break;
>> +
>>                        case test:
>>                                break;
>>                        }
>> @@ -884,6 +901,43 @@ draw_instanced_rect(int primcount, float x, float y,
>> float w, float h)
>>        glDisableClientState(GL_**VERTEX_ARRAY);
>>  }
>>
>> +
>> +struct mode_table {
>> +       const char *name;
>> +       GLenum value;
>> +} mode_table[] = {
>> +       { "GL_POINTS",         GL_POINTS         },
>> +       { "GL_LINE_STRIP",     GL_LINE_STRIP     },
>> +       { "GL_LINE_LOOP",      GL_LINE_LOOP      },
>> +       { "GL_LINES",          GL_LINES          },
>> +       { "GL_POLYGON",        GL_POLYGON        },
>> +       { "GL_TRIANGLE_STRIP", GL_TRIANGLE_STRIP },
>> +       { "GL_TRIANGLE_FAN",   GL_TRIANGLE_FAN   },
>> +       { "GL_TRIANGLES",      GL_TRIANGLES      },
>> +       { "GL_QUAD_STRIP",     GL_QUAD_STRIP     },
>> +       { "GL_QUADS",          GL_QUADS          },
>> +       { NULL, 0 }
>> +};
>> +
>> +
>> +GLenum
>> +decode_mode(const char *mode_str)
>> +{
>> +       int i;
>> +
>> +       for (i = 0; mode_table[i].name; ++i) {
>> +               if (0 == strcmp(mode_str, mode_table[i].name))
>> +                       return mode_table[i].value;
>> +       }
>> +
>> +       printf("unknown drawing mode \"%s\"", mode_str);
>> +       piglit_report_result(PIGLIT_**FAIL);
>> +
>> +       /* Should not be reached, but return 0 to avoid compiler warning
>> */
>> +       return 0;
>> +}
>> +
>> +
>>  enum piglit_result
>>  piglit_display(void)
>>  {
>> @@ -900,6 +954,7 @@ piglit_display(void)
>>                float c[32];
>>                double d[4];
>>                int x, y, w, h, l, tex, level;
>> +               char s[32];
>>
>>                line = eat_whitespace(line);
>>
>> @@ -927,6 +982,28 @@ piglit_display(void)
>>                        &primcount,
>>                               c + 0, c + 1, c + 2, c + 3);
>>                        draw_instanced_rect(primcount, c[0], c[1], c[2],
>> c[3]);
>> +               } else if (sscanf(line, "draw arrays %31s %d %d",
>> s,&x,&y)) {
>> +                       GLenum mode = decode_mode(s);
>> +                       int first = x;
>> +                       size_t count = (size_t) y;
>> +                       if (first<  0) {
>> +                               printf("draw arrays 'first' must be>=
>> 0\n");
>> +                               piglit_report_result(PIGLIT_**FAIL);
>> +                       } else if ((size_t) first>= num_vbo_rows) {
>> +                               printf("draw arrays 'first' must be<
>>  %lu\n",
>> +                                      num_vbo_rows);
>> +                               piglit_report_result(PIGLIT_**FAIL);
>> +                       }
>> +                       if (count<= 0) {
>> +                               printf("draw arrays 'count' must be>
>>  0\n");
>> +                               piglit_report_result(PIGLIT_**FAIL);
>> +                       } else if (count>  num_vbo_rows - (size_t) first)
>> {
>> +                               printf("draw arrays cannot draw beyond
>> %lu\n",
>> +                                      num_vbo_rows);
>> +                               piglit_report_result(PIGLIT_**FAIL);
>> +                       }
>> +                       /* TODO: wrapper? */
>> +                       glDrawArrays(mode, first, count);
>>                } else if (string_match("disable", line)) {
>>                        do_enable_disable(line + 7, false);
>>                } else if (string_match("enable", line)) {
>> @@ -1523,4 +1600,7 @@ piglit_init(int argc, char **argv)
>>
>>        process_test_script(argv[1]);
>>        link_and_use_shaders();
>> +       if (vertex_data_start != NULL)
>> +               num_vbo_rows = setup_vbo_from_text(prog,
>> vertex_data_start,
>> +                                                  vertex_data_end);
>>  }
>> diff --git a/tests/shaders/vbo/vbo-**generic-float.shader_test
>> b/tests/shaders/vbo/vbo-**generic-float.shader_test
>> new file mode 100644
>> index 0000000..8982211
>> --- /dev/null
>> +++ b/tests/shaders/vbo/vbo-**generic-float.shader_test
>> @@ -0,0 +1,37 @@
>> +[require]
>> +GLSL>= 1.10
>> +GL>= 2.1
>> +
>> +[vertex shader]
>> +attribute vec4 vertex;
>> +attribute float foo;
>> +attribute vec2 bar;
>> +
>> +void main()
>> +{
>> +       gl_Position = gl_ModelViewProjectionMatrix * vertex;
>> +       gl_FrontColor = vec4(foo, bar, 1.0);
>> +}
>> +
>> +[fragment shader]
>> +void main()
>> +{
>> +       gl_FragColor = gl_Color;
>> +}
>> +
>> +[vertex data]
>> +vertex/float/3 foo/float/1 bar/float/2
>> +0.0 0.0 0.0    1.0         0.0 0.0
>> +0.0 1.0 0.0    0.5         1.0 1.0
>> +1.0 1.0 0.0    0.0         0.0 1.0
>> +
>> +[test]
>> +ortho 0.0 1.0 0.0 1.0
>> +clear color 0.0 0.0 0.0 0.0
>> +clear
>> +draw arrays GL_TRIANGLES 0 3
>> +relative probe rgba (0.3, 0.7) (0.5, 0.4, 0.7, 1.0)
>> +relative probe rgba (0.1, 0.5) (0.7, 0.4, 0.5, 1.0)
>> +relative probe rgba (0.1, 0.9) (0.5, 0.8, 0.9, 1.0)
>> +relative probe rgba (0.5, 0.9) (0.3, 0.4, 0.9, 1.0)
>> +relative probe rgba (0.7, 0.3) (0.0, 0.0, 0.0, 0.0)
>> diff --git a/tests/shaders/vbo/vbo-**generic-int.shader_test
>> b/tests/shaders/vbo/vbo-**generic-int.shader_test
>> new file mode 100644
>> index 0000000..669b85d
>> --- /dev/null
>> +++ b/tests/shaders/vbo/vbo-**generic-int.shader_test
>> @@ -0,0 +1,39 @@
>> +[require]
>> +GLSL>= 1.30
>> +GL>= 3.0
>> +
>> +[vertex shader]
>> +#version 130
>> +attribute vec4 vertex;
>> +attribute int foo;
>> +attribute ivec2 bar;
>> +
>> +void main()
>> +{
>> +       gl_Position = gl_ModelViewProjectionMatrix * vertex;
>> +       gl_FrontColor = vec4(foo/10.0, bar, 1.0);
>> +}
>> +
>> +[fragment shader]
>> +#version 130
>> +void main()
>> +{
>> +       gl_FragColor = gl_Color;
>> +}
>> +
>> +[vertex data]
>> +vertex/float/3 foo/int/1 bar/int/2
>> +0.0 0.0 0.0    10        0 0
>> +0.0 1.0 0.0     5        1 1
>> +1.0 1.0 0.0     0        0 1
>> +
>> +[test]
>> +ortho 0.0 1.0 0.0 1.0
>> +clear color 0.0 0.0 0.0 0.0
>> +clear
>> +draw arrays GL_TRIANGLES 0 3
>> +relative probe rgba (0.3, 0.7) (0.5, 0.4, 0.7, 1.0)
>> +relative probe rgba (0.1, 0.5) (0.7, 0.4, 0.5, 1.0)
>> +relative probe rgba (0.1, 0.9) (0.5, 0.8, 0.9, 1.0)
>> +relative probe rgba (0.5, 0.9) (0.3, 0.4, 0.9, 1.0)
>> +relative probe rgba (0.7, 0.3) (0.0, 0.0, 0.0, 0.0)
>> diff --git a/tests/shaders/vbo/vbo-**generic-uint.shader_test
>> b/tests/shaders/vbo/vbo-**generic-uint.shader_test
>> new file mode 100644
>> index 0000000..6f56dd1
>> --- /dev/null
>> +++ b/tests/shaders/vbo/vbo-**generic-uint.shader_test
>> @@ -0,0 +1,39 @@
>> +[require]
>> +GLSL>= 1.30
>> +GL>= 3.0
>> +
>> +[vertex shader]
>> +#version 130
>> +attribute vec4 vertex;
>> +attribute uint foo;
>> +attribute ivec2 bar;
>> +
>> +void main()
>> +{
>> +       gl_Position = gl_ModelViewProjectionMatrix * vertex;
>> +       gl_FrontColor = vec4(float(foo)/float(**0xe0000000u), bar, 1.0);
>> +}
>> +
>> +[fragment shader]
>> +#version 130
>> +void main()
>> +{
>> +       gl_FragColor = gl_Color;
>> +}
>> +
>> +[vertex data]
>> +vertex/float/3 foo/uint/1 bar/int/2
>> +0.0 0.0 0.0    0xe0000000 0 0
>> +0.0 1.0 0.0    0x70000000 1 1
>> +1.0 1.0 0.0    0x00000000 0 1
>> +
>> +[test]
>> +ortho 0.0 1.0 0.0 1.0
>> +clear color 0.0 0.0 0.0 0.0
>> +clear
>> +draw arrays GL_TRIANGLES 0 3
>> +relative probe rgba (0.3, 0.7) (0.5, 0.4, 0.7, 1.0)
>> +relative probe rgba (0.1, 0.5) (0.7, 0.4, 0.5, 1.0)
>> +relative probe rgba (0.1, 0.9) (0.5, 0.8, 0.9, 1.0)
>> +relative probe rgba (0.5, 0.9) (0.3, 0.4, 0.9, 1.0)
>> +relative probe rgba (0.7, 0.3) (0.0, 0.0, 0.0, 0.0)
>> diff --git a/tests/util/CMakeLists.gl.txt b/tests/util/CMakeLists.gl.txt
>> index a03b50b..df1bfb9 100644
>> --- a/tests/util/CMakeLists.gl.txt
>> +++ b/tests/util/CMakeLists.gl.txt
>> @@ -10,6 +10,7 @@ set(UTIL_SOURCES
>>        piglit-shader.c
>>        piglit-shader-gl.c
>>        piglit-util-gl.c
>> +       piglit-vbo.cpp
>>        )
>>
>>  IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
>> diff --git a/tests/util/piglit-vbo.cpp b/tests/util/piglit-vbo.cpp
>> new file mode 100644
>> index 0000000..fdba6b1
>> --- /dev/null
>> +++ b/tests/util/piglit-vbo.cpp
>> @@ -0,0 +1,514 @@
>> +/*
>> + * Copyright © 2011 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 piglit-vbo.cpp
>> + *
>> + * This file adds the facility for specifying vertex data to piglit
>> + * tests using a columnar text format, for example:
>> + *
>> + *   \verbatim
>> + *   vertex/float/3 foo/uint/1 bar/int/2
>> + *   0.0 0.0 0.0    10         0 0 # comment
>> + *   0.0 1.0 0.0     5         1 1
>> + *   1.0 1.0 0.0     0         0 1
>> + *   \endverbatim
>> + *
>> + * The format consists of a row of column headers followed by any
>> + * number of rows of data.  Each column header has the form
>> + * "ATTRNAME/TYPE/COUNT", where ATTRNAME is the name of the vertex
>> + * attribute to be bound to this column, TYPE is the type of data that
>> + * follows ("float", "int", or "uint"), and COUNT is the vector length
>> + * of the data (e.g. "3" for vec3 data).
>> + *
>> + * The data follows the column headers in space-separated form.  "#"
>> + * can be used for comments, as in shell scripts.
>> + *
>> + * To process textual vertex data, call the function
>> + * setup_vbo_from_text(), passing the int identifying the linked
>> + * program, and the string containing the vertex data.  The return
>> + * value is the number of rows of vertex data found.
>> + *
>> + * If an error occurs, setup_vbo_from_text() will print out a
>> + * description of the error and exit with PIGLIT_FAIL.
>> + *
>> + * For the example above, the call to setup_vbo_from_text() is roughly
>> + * equivalent to the following GL operations:
>> + *
>> + * \code
>> + * struct vertex_attributes {
>> + *         GLfloat vertex[3];
>> + *         GLuint foo;
>> + *         GLint bar[2];
>> + * } vertex_data[] = {
>> + *         { { 0.0, 0.0, 0.0 }, 10, { 0, 0 } },
>> + *         { { 0.0, 1.0, 0.0 },  5, { 1, 1 } },
>> + *         { { 1.0, 1.0, 0.0 },  0, { 0, 1 } }
>> + * };
>> + * size_t stride = sizeof(vertex_data[0]);
>> + * GLint vertex_index = glGetAttribLocation(prog, "vertex");
>> + * GLint foo_index = glGetAttribLocation(prog, "foo");
>> + * GLint bar_index = glGetAttribLocation(prog, "bar");
>> + * GLuint buffer_handle;
>> + * glGenBuffers(1,&buffer_handle)**;
>> + * glBindBuffer(GL_ARRAY_BUFFER, buffer_handle);
>> + * glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data),&vertex_**data,
>> + *              GL_STATIC_DRAW);
>> + * glVertexAttribPointer(vertex_**index, 3, GL_FLOAT, GL_FALSE, stride,
>> + *                       (void *) offsetof(vertex_attributes, vertex));
>> + * glVertexAttribIPointer(foo_**index, 3, GL_UNSIGNED_INT, stride,
>> + *                        (void *) offsetof(vertex_attributes, foo));
>> + * glVertexAttribIPointer(bar_**index, 3, GL_INT, stride,
>> + *                        (void *) offsetof(vertex_attributes, bar));
>> + * glEnableVertexAttribArray(**vertex_index);
>> + * glEnableVertexAttribArray(foo_**index);
>> + * glEnableVertexAttribArray(bar_**index);
>> + * \endcode
>> + */
>> +
>> +#ifndef _GNU_SOURCE
>> +#define _GNU_SOURCE
>> +#endif
>> +
>> +#if defined(_MSC_VER)
>> +#define bool BOOL
>> +#define true 1
>> +#define false 0
>> +#else
>> +#include<stdbool.h>
>> +#endif
>>
>
> Is any of the above necessary (or even correct) in C++?
>

Whoops, good catch.  I blindly copied this stuff out of shader_runner.c
without engaging my brain.  You're right, of course.  It's not necessary in
C++ and it probably would make things mighty confusing for people trying to
build Piglit on Windows.  I'll pull it out.


>
>  +#include<string.h>
>> +#include<ctype.h>
>> +#if defined(_WIN32)
>> +#include<stdlib.h>
>> +#else
>> +#include<libgen.h>
>> +#endif
>> +#include "piglit-util.h"
>> +#include "piglit-vbo.h"
>> +#include<vector>
>> +#include<string>
>> +#include<errno.h>
>> +
>> +
>> +/**
>> + * Currently all the attribute types we support (int, uint, and float)
>> + * are 4 bytes in width.
>> + */
>> +const int ATTRIBUTE_SIZE = 4;
>> +
>> +
>> +/**
>> + * Convert a type name string to a GLenum.
>> + */
>> +GLenum
>> +decode_type(const char *type)
>> +{
>> +       static struct type_table_entry {
>> +               const char *type; /* NULL means end of table */
>> +               GLenum enum_value;
>> +       } const type_table[] = {
>> +               { "int",     GL_INT            },
>> +               { "uint",    GL_UNSIGNED_INT   },
>> +               { "float",   GL_FLOAT          },
>> +               { NULL,      0                 }
>> +       };
>> +
>> +
>> +       for (int i = 0; type_table[i].type; ++i) {
>> +               if (0 == strcmp(type, type_table[i].type))
>> +                       return type_table[i].enum_value;
>> +       }
>> +
>> +       printf("Unrecognized type: %s\n", type);
>> +       piglit_report_result(PIGLIT_**FAIL);
>> +       return 0;
>> +}
>> +
>> +
>> +/**
>> + * Description of a vertex attribute, built from its column header
>> + */
>> +class vertex_attrib_description
>> +{
>> +public:
>> +       vertex_attrib_description(**GLuint prog, const char *text);
>> +       bool parse_datum(const char **text, void *data) const;
>> +       void setup(size_t *offset, size_t stride) const;
>> +
>> +       /**
>> +        * Data type of this attribute.
>> +        */
>> +       GLenum data_type;
>> +
>> +       /**
>> +        * Vector length of this attribute.
>> +        */
>> +       size_t count;
>> +
>> +       /**
>> +        * Index of this vertex attribute in the linked program.
>> +        */
>> +       GLuint index;
>> +};
>> +
>> +
>> +/**
>> + * Build a vertex_attrib_description from a column header, by looking
>> + * up the vertex attribute in the linked program and interpreting the
>> + * type and count parts of the header.
>> + *
>> + * If there is a parse failure, print a description of the problem and
>> + * then exit with PIGLIT_FAIL.
>> + */
>> +vertex_attrib_description::**vertex_attrib_description(**GLuint prog,
>> +                                                    const char *text)
>> +{
>> +       /* Split the column header into name/type/count fields */
>> +       const char *first_slash = strchr(text, '/');
>> +       if (first_slash == NULL) {
>> +               printf("Column headers must be in the form
>> name/type/count.  "
>> +                      "Got: %s\n",
>> +                      text);
>> +               piglit_report_result(PIGLIT_**FAIL);
>> +       }
>> +       std::string name(text, first_slash);
>> +       const char *second_slash = strchr(first_slash + 1, '/');
>> +       if (second_slash == NULL) {
>> +               printf("Column headers must be in the form
>> name/type/count.  "
>> +                      "Got: %s\n",
>> +                      text);
>> +               piglit_report_result(PIGLIT_**FAIL);
>> +       }
>> +       std::string type_str(first_slash + 1, second_slash);
>> +       this->data_type = decode_type(type_str.c_str());
>> +       char *endptr;
>> +       this->count = strtoul(second_slash + 1,&endptr, 10);
>>
>> +       if (*endptr != '\0') {
>> +               printf("Column headers must be in the form
>> name/type/count.  "
>> +                      "Got: %s\n",
>> +                      text);
>> +               piglit_report_result(PIGLIT_**FAIL);
>> +       }
>> +
>> +       GLint attrib_location = glGetAttribLocation(prog, name.c_str());
>> +       if (attrib_location == -1) {
>> +               printf("Unexpected vbo column name.  Got: %s\n",
>> name.c_str());
>> +               piglit_report_result(PIGLIT_**FAIL);
>> +       }
>> +       this->index = attrib_location;
>> +       /* If the type is integral, verify that integer vertex
>> +        * attribute support is present.  Note: we treat it as a FAIL
>> +        * if support is not present, because it's up to the test to
>> +        * either (a) not require integer vertex attribute support, or
>> +        * (b) skip itself if integer vertex attribute support is not
>> +        * present.
>> +        */
>> +       if (this->data_type != GL_FLOAT&&
>> +           (piglit_is_gles() || piglit_get_gl_version()<  30)) {
>> +               printf("Test uses glVertexAttribIPointer(),"
>> +                      " which is unsupported.\n");
>> +               piglit_report_result(PIGLIT_**FAIL);
>> +       }
>> +
>> +       if (this->count<  1 || this->count>  4) {
>> +               printf("Count must be between 1 and 4.  Got: %lu\n",
>> count);
>> +               piglit_report_result(PIGLIT_**FAIL);
>> +       }
>> +}
>> +
>> +
>> +/**
>> + * Parse a single number (floating point or integral) from one of the
>> + * data rows, and store it in the location pointed to by \c data.
>> + * Update \c text to point to the next character of input.
>> + *
>> + * If there is a parse failure, print a description of the problem and
>> + * then return false.  Otherwise return true.
>> + */
>> +bool
>> +vertex_attrib_description::**parse_datum(const char **text, void *data)
>> const
>> +{
>> +       char *endptr;
>> +       errno = 0;
>> +       switch (this->data_type) {
>> +       case GL_FLOAT: {
>> +               double value = strtod(*text,&endptr);
>> +               if (errno == ERANGE) {
>> +                       printf("Could not parse as double\n");
>> +                       return false;
>> +               }
>> +               *((GLfloat *) data) = (float) value;
>> +               break;
>> +       }
>> +       case GL_INT: {
>> +               long value = strtol(*text,&endptr, 0);
>>
>> +               if (errno == ERANGE) {
>> +                       printf("Could not parse as signed integer\n");
>> +                       return false;
>> +               }
>> +               *((GLint *) data) = (GLint) value;
>> +               break;
>> +       }
>> +       case GL_UNSIGNED_INT: {
>> +               unsigned long value = strtoul(*text,&endptr, 0);
>>
>> +               if (errno == ERANGE) {
>> +                       printf("Could not parse as unsigned integer\n");
>> +                       return false;
>> +               }
>> +               *((GLuint *) data) = (GLuint) value;
>> +               break;
>> +       }
>> +       }
>> +       *text = endptr;
>> +       return true;
>> +}
>> +
>> +
>> +/**
>> + * Execute the necessary GL calls to bind this attribute to its data.
>> + */
>> +void
>> +vertex_attrib_description::**setup(size_t *offset, size_t stride) const
>> +{
>> +       if (this->data_type == GL_FLOAT) {
>> +               glVertexAttribPointer(this->**index, this->count,
>> +                                     this->data_type, GL_FALSE, stride,
>> +                                     (void *) *offset);
>> +       } else {
>> +               glVertexAttribIPointer(this->**index, this->count,
>> +                                      this->data_type, stride,
>> +                                      (void *) *offset);
>> +       }
>> +       glEnableVertexAttribArray(**index);
>> +       *offset += ATTRIBUTE_SIZE * this->count;
>> +}
>> +
>> +
>> +/**
>> + * Data structure containing all of the data parsed from the text
>> + * input, as well as the methods that parse it and convert it to GL
>> + * calls.
>> + */
>> +class vbo_data
>> +{
>> +public:
>> +       vbo_data(std::string const&text, GLuint prog);
>>
>> +       size_t setup() const;
>> +
>> +private:
>> +       void parse_header_line(const std::string&line, GLuint prog);
>> +       void parse_data_line(const std::string&line, unsigned int
>> line_num);
>>
>> +       void parse_line(std::string line, unsigned int line_num, GLuint
>> prog);
>> +
>> +       /**
>> +        * True if the header line has already been parsed.
>> +        */
>> +       bool header_seen;
>> +
>> +       /**
>> +        * Description of each attribute.
>> +        */
>> +       std::vector<vertex_attrib_**description>  attribs;
>> +
>> +       /**
>> +        * Raw data buffer containing parsed numbers.
>> +        */
>> +       std::vector<char>  raw_data;
>> +
>> +       /**
>> +        * Number of bytes in each row of raw_data.
>> +        */
>> +       size_t stride;
>> +
>> +       /**
>> +        * Number of rows in raw_data.
>> +        */
>> +       size_t num_rows;
>> +};
>> +
>> +
>> +
>> +static bool
>> +is_blank_line(const std::string&line)
>> +{
>> +       for (size_t i = 0; i<  line.size(); ++i) {
>> +               if (!isspace(line[i]))
>> +                       return false;
>> +       }
>> +       return true;
>> +}
>> +
>> +
>> +/**
>> + * Populate this->attribs and compute this->stride based on column
>> + * headers.
>> + *
>> + * If there is a parse failure, print a description of the problem and
>> + * then exit with PIGLIT_FAIL.
>> + */
>> +void
>> +vbo_data::parse_header_line(**const std::string&line, GLuint prog)
>>
>> +{
>> +       size_t pos = 0;
>> +       this->stride = 0;
>> +       while (pos<  line.size()) {
>> +               if (isspace(line[pos])) {
>> +                       ++pos;
>> +               } else {
>> +                       size_t column_header_end = pos;
>> +                       while (column_header_end<  line.size()&&
>> +                              !isspace(line[column_header_**end]))
>> +                               ++column_header_end;
>> +                       std::string column_header = line.substr(
>> +                               pos, column_header_end - pos);
>> +                       vertex_attrib_description desc(
>> +                               prog, column_header.c_str());
>> +                       attribs.push_back(desc);
>> +                       this->stride += ATTRIBUTE_SIZE * desc.count;
>> +                       pos = column_header_end + 1;
>> +               }
>> +       }
>> +}
>> +
>> +
>> +/**
>> + * Convert a data row into binary form and append it to this->raw_data.
>> + *
>> + * If there is a parse failure, print a description of the problem and
>> + * then exit with PIGLIT_FAIL.
>> + */
>> +void
>> +vbo_data::parse_data_line(**const std::string&line, unsigned int
>> line_num)
>>
>> +{
>> +       /* Allocate space in raw_data for this line */
>> +       size_t old_size = this->raw_data.size();
>> +       this->raw_data.resize(old_size + this->stride);
>> +       char *data_ptr =&this->raw_data[old_size];
>>
>> +
>> +       const char *line_ptr = line.c_str();
>> +       for (size_t i = 0; i<  this->attribs.size(); ++i) {
>> +               for (size_t j = 0; j<  this->attribs[i].count; ++j) {
>> +                       if (!this->attribs[i].parse_**datum(&line_ptr,
>> +                                                         data_ptr)) {
>> +                               printf("At line %u of [vertex data]
>> section\n",
>> +                                      line_num);
>> +                               printf("Offending text: %s\n", line_ptr);
>> +                               piglit_report_result(PIGLIT_**FAIL);
>> +                       }
>> +                       data_ptr += ATTRIBUTE_SIZE;
>> +               }
>> +       }
>> +
>> +       ++this->num_rows;
>> +}
>> +
>> +
>> +/**
>> + * Parse a line of input text.
>> + *
>> + * If there is a parse failure, print a description of the problem and
>> + * then exit with PIGLIT_FAIL.
>> + */
>> +void
>> +vbo_data::parse_line(std::**string line, unsigned int line_num, GLuint
>> prog)
>> +{
>> +       /* Ignore end-of-line comments */
>> +       line = line.substr(0, line.find('#'));
>> +
>> +       /* Ignore blank or comment-only lines */
>> +       if (is_blank_line(line))
>> +               return;
>> +
>> +       if (!this->header_seen) {
>> +               this->header_seen = true;
>> +               parse_header_line(line, prog);
>> +       } else {
>> +               parse_data_line(line, line_num);
>> +       }
>> +}
>> +
>> +
>> +/**
>> + * Parse the input but don't execute any GL commands.
>> + *
>> + * If there is a parse failure, print a description of the problem and
>> + * then exit with PIGLIT_FAIL.
>> + */
>> +vbo_data::vbo_data(const std::string&text, GLuint prog)
>>
>> +       : header_seen(false), num_rows(0)
>> +{
>> +       unsigned int line_num = 1;
>> +
>> +       size_t pos = 0;
>> +       while (pos<  text.size()) {
>> +               size_t end_of_line = text.find('\n', pos);
>> +               if (end_of_line == std::string::npos)
>> +                       end_of_line = text.size();
>> +               parse_line(text.substr(pos, end_of_line), line_num++,
>> prog);
>> +               pos = end_of_line + 1;
>> +       }
>> +}
>> +
>> +
>> +/**
>> + * Execute the necessary GL commands to set up the vertex data passed
>> + * to the constructor.
>> + */
>> +size_t
>> +vbo_data::setup() const
>> +{
>> +       GLuint buffer_handle;
>> +       glGenBuffers(1,&buffer_handle)**;
>> +       glBindBuffer(GL_ARRAY_BUFFER, buffer_handle);
>> +       glBufferData(GL_ARRAY_BUFFER, this->stride * this->num_rows,
>> +               &this->raw_data[0], GL_STATIC_DRAW);
>> +
>> +       size_t offset = 0;
>> +       for (size_t i = 0; i<  attribs.size(); ++i)
>> +               attribs[i].setup(&offset, this->stride);
>> +
>> +       /* Leave buffer bound for later draw calls */
>> +
>> +       return this->num_rows;
>> +}
>> +
>> +
>> +/**
>> + * Set up a vertex buffer object for the program prog based on the
>> + * data encoded in text_start.  text_end indicates the end of the text
>> + * string; if it is NULL, the string is assumed to be null-terminated.
>> + *
>> + * Return value is the number of rows of vertex data found.
>> + *
>> + * For details about the format of the text string, see the comment at
>> + * the top of this file.
>> + */
>> +size_t
>> +setup_vbo_from_text(GLuint prog, const char *text_start, const char
>> *text_end)
>> +{
>> +       if (text_end == NULL)
>> +               text_end = text_start + strlen(text_start);
>> +       std::string text(text_start, text_end);
>> +       return vbo_data(text, prog).setup();
>> +}
>> diff --git a/tests/util/piglit-vbo.h b/tests/util/piglit-vbo.h
>> new file mode 100644
>> index 0000000..22935e3
>> --- /dev/null
>> +++ b/tests/util/piglit-vbo.h
>> @@ -0,0 +1,35 @@
>> +/*
>> + * Copyright © 2011 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.
>> + */
>> +
>> +#pragma once
>> +
>> +#ifdef __cplusplus
>> +extern "C" {
>> +#endif
>> +
>> +size_t
>> +setup_vbo_from_text(GLuint prog, const char *text_start, const char
>> *text_end);
>> +
>> +#ifdef __cplusplus
>> +} /* end extern "C" */
>> +#endif
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/piglit/attachments/20111027/3336cc74/attachment-0001.htm>


More information about the Piglit mailing list