[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