Commit 968d5572 authored by Eric Anholt's avatar Eric Anholt

gl-1.1: Add a new test for large vertex counts.

There's a limitation on VC4 where it can only handle 65536 verts at a
time in a glDrawArrays(), so the driver needs to split up the calls.
This tests that path for all the primitive types.

v2: handle error from glMapBuffer().
Reviewed-by: default avatarIan Romanick <ian.d.romanick@intel.com>
parent dce99851
......@@ -712,6 +712,13 @@ with profile.test_list.group_manager(
g(['getteximage-targets', '2D'])
g(['teximage-scale-bias'])
g(['tex-upside-down-miptree'])
for prim in ['GL_POINTS', 'GL_LINE_LOOP', 'GL_LINE_STRIP', 'GL_LINES',
'GL_TRIANGLES', 'GL_TRIANGLE_STRIP', 'GL_TRIANGLE_FAN',
'GL_QUADS', 'GL_QUAD_STRIP', 'GL_POLYGON']:
for mode in ['varray', 'vbo']:
g(['gl-1.1-drawarrays-vertex-count', '100000', mode, prim])
add_msaa_visual_plain_tests(g, ['draw-pixels'])
add_msaa_visual_plain_tests(g, ['read-front'], run_concurrent=False)
add_msaa_visual_plain_tests(g, ['read-front', 'clear-front-first'],
......
......@@ -10,6 +10,7 @@ link_libraries (
piglit_add_executable (gl-1.1-color-material-array color-material-array.c)
piglit_add_executable (gl-1.1-draw-arrays-start draw-arrays-start.c)
piglit_add_executable (gl-1.1-drawarrays-vertex-count drawarrays-vertex-count.c)
piglit_add_executable (gl-1.1-read-pixels-after-display-list read-pixels-after-display-list.c)
piglit_add_executable (gl-1.1-set-vertex-color-after-draw set-vertex-color-after-draw.c)
piglit_add_executable (gl-1.1-xor xor.c)
......
/*
* Copyright © 2016 Broadcom Limited
*
* 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 drawarrays-vertex-count.c
*
* Tests glDrawArrays with large vertex counts and a start vertex
* offset. Catches a limitation of the vc4 hardware where
* glDrawArrays() with a large count ends up truncating the high 16
* bits of vertex indices.
*/
#include "piglit-util-gl.h"
PIGLIT_GL_TEST_CONFIG_BEGIN
config.supports_gl_compat_version = 10;
config.window_visual = PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_RGBA;
PIGLIT_GL_TEST_CONFIG_END
static GLenum primtype;
static unsigned int count;
static bool use_vbo;
static const float green[4] = {0.0, 1.0, 0.0, 0.0};
static const float black[4] = {0.0, 0.0, 0.0, 0.0};
static const float red[4] = {1.0, 0.0, 0.0, 0.0};
static int v_from_end(int count, int prims, int primsize)
{
int v = count - prims * primsize;
return v - v % primsize;
}
/* Probes for a green filled rectangle in the screen, surrounded by black. */
static bool
probe_rect(int x, int y, int w, int h)
{
return (piglit_probe_rect_rgba(x, y, w, h, green) &&
piglit_probe_rect_rgba(0, 0, piglit_width, y, black) &&
piglit_probe_rect_rgba(0, y, x, h, black) &&
piglit_probe_rect_rgba(x + w, y,
piglit_width - (x + w), h, black) &&
piglit_probe_rect_rgba(0, y + h,
piglit_width, piglit_height - (y + h),
black));
}
/* Probes for a green outlined rectangle in the screen, surrounded by black. */
static bool
probe_line_rect(int x1, int y1, int x2, int y2)
{
int probe_w = x2 - x1 - 2;
int probe_h = y2 - y1 - 2;
/* Note that GL line rasterization may not include the endpoints. */
return (/* rect */
piglit_probe_rect_rgba(x1 + 1, y1, probe_w, 1, green) &&
piglit_probe_rect_rgba(x1 + 1, y2, probe_w, 1, green) &&
piglit_probe_rect_rgba(x1, y1 + 1, 1, probe_h, green) &&
piglit_probe_rect_rgba(x2, y1 + 1, 1, probe_h, green) &&
/* inside the rect */
piglit_probe_rect_rgba(x1 + 1, y1 + 1,
probe_w, probe_h, black) &&
/* outside the rect */
piglit_probe_rect_rgba(0, 0, piglit_width, y1, black) &&
piglit_probe_rect_rgba(0, y1,
x1, y2 - y1, black) &&
piglit_probe_rect_rgba(x2 + 1, y1,
piglit_width - x2, y2 - y1, black) &&
piglit_probe_rect_rgba(0, y2 + 1,
piglit_width, piglit_height - (y2 + 1),
black));
}
/* Sets a range of the color array to a spefific color. */
static void
set_colors(float *colors, unsigned int start, unsigned int count,
const float *color)
{
unsigned int i;
for (i = start; i < start + count; i++)
memcpy(&colors[i * 4], color, 4 * sizeof(float));
}
void set_point(float *verts, int p, float x, float y)
{
verts[p * 2 + 0] = x;
verts[p * 2 + 1] = y;
}
enum piglit_result
piglit_display(void)
{
/* Start vertex offset for DrawArrays. */
unsigned int sv = count / 3;
/* Vertex index for the primitive we care about */
unsigned int v;
bool pass = true;
char *data;
float *vert;
float *color;
unsigned int i;
GLsizei vert_size = 2 * sizeof(float);
GLsizei color_size = 4 * sizeof(float);
GLsizei vert_buffer_size = vert_size * (sv + count);
GLsizei color_buffer_size = color_size * (sv + count);
GLsizei buffer_size = vert_buffer_size + color_buffer_size;
int quad_x1 = piglit_width / 2 - 5;
int quad_y1 = piglit_height / 2 - 5;
int quad_x2 = quad_x1 + 10;
int quad_y2 = quad_y1 + 10;
int smallquad_x1 = piglit_width / 2;
int smallquad_y1 = piglit_height / 2;
int smallquad_x2 = smallquad_x1 + 1;
int smallquad_y2 = smallquad_y1 + 1;
piglit_ortho_projection(piglit_width, piglit_height, false);
if (use_vbo) {
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, buffer_size, NULL, GL_STREAM_DRAW);
glVertexPointer(2, GL_FLOAT, 0, 0);
data = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
} else {
data = malloc(buffer_size);
}
if (!data)
return PIGLIT_FAIL;
vert = (float *)data;
color = (float *)(data + vert_buffer_size);
if (use_vbo) {
glVertexPointer(2, GL_FLOAT, 0, 0);
glColorPointer(4, GL_FLOAT, 0,
(void *)(uintptr_t)vert_buffer_size);
} else {
glVertexPointer(2, GL_FLOAT, 0, vert);
glColorPointer(4, GL_FLOAT, 0, color);
}
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glClear(GL_COLOR_BUFFER_BIT);
/* Initialize all colors to red. */
set_colors(color, 0, sv + count, red);
/* Initialize all the vertices to offscreen. */
for (i = 0; i < sv + count; i++)
set_point(vert, i, -1, -1);
switch (primtype) {
case GL_POINTS:
/* Four points in the middle of the screen. */
v = sv + v_from_end(count, 4, 1);
set_colors(color, v, 4, green);
/* Adjust point and line coordinates to pixel centers,
* to prevent rounding-based test failures.
*/
set_point(vert, v++, smallquad_x1 + 0.5, smallquad_y1 + 0.5);
set_point(vert, v++, smallquad_x2 + 0.5, smallquad_y1 + 0.5);
set_point(vert, v++, smallquad_x1 + 0.5, smallquad_y2 + 0.5);
set_point(vert, v++, smallquad_x2 + 0.5, smallquad_y2 + 0.5);
break;
case GL_LINES:
/* Draw the outline of a quad. */
v = sv + v_from_end(count, 4, 2);
set_colors(color, v, 4 * 2, green);
set_point(vert, v++, quad_x1, quad_y1 + 0.5);
set_point(vert, v++, quad_x2, quad_y1 + 0.5);
set_point(vert, v++, quad_x1, quad_y2 + 0.5);
set_point(vert, v++, quad_x2, quad_y2 + 0.5);
set_point(vert, v++, quad_x1 + 0.5, quad_y1);
set_point(vert, v++, quad_x1 + 0.5, quad_y2);
set_point(vert, v++, quad_x2 + 0.5, quad_y1);
set_point(vert, v++, quad_x2 + 0.5, quad_y2);
break;
case GL_LINE_STRIP:
v = sv + v_from_end(count, 4, 1);
/* Strip start point plus a bunch of degenerate lines. */
for (i = sv; i < v; i++)
set_point(vert, i, quad_x1 + 0.5, quad_y1 + 0.5);
/* Last 4 points producing the real lines. */
set_colors(color, v - 1, 5, green);
set_point(vert, v++, quad_x2 + 0.5, quad_y1 + 0.5);
set_point(vert, v++, quad_x2 + 0.5, quad_y2 + 0.5);
set_point(vert, v++, quad_x1 + 0.5, quad_y2 + 0.5);
set_point(vert, v++, quad_x1 + 0.5, quad_y1 + 0.5);
break;
case GL_LINE_LOOP:
v = sv + v_from_end(count, 3, 1);
/* Loop start point plus a bunch of degenerate lines. */
set_colors(color, sv, 1, green);
for (i = sv; i < v; i++)
set_point(vert, i, quad_x1 + 0.5, quad_y1 + 0.5);
/* Last 3 points producing the real lines. */
set_colors(color, v - 1, 4, green);
set_point(vert, v++, quad_x2 + 0.5, quad_y1 + 0.5);
set_point(vert, v++, quad_x2 + 0.5, quad_y2 + 0.5);
set_point(vert, v++, quad_x1 + 0.5, quad_y2 + 0.5);
break;
case GL_TRIANGLES:
/* Set up a pair of triangles to make a quad. */
v = sv + v_from_end(count, 2, 3);
set_colors(color, v, 2 * 3, green);
set_point(vert, v++, quad_x1, quad_y1);
set_point(vert, v++, quad_x2, quad_y1);
set_point(vert, v++, quad_x1, quad_y2);
set_point(vert, v++, quad_x2, quad_y1);
set_point(vert, v++, quad_x2, quad_y2);
set_point(vert, v++, quad_x1, quad_y2);
break;
case GL_TRIANGLE_STRIP:
v = sv + v_from_end(count, 3, 1);
/* A bunch of degenerate tri strip triangles. */
for (i = sv; i < v; i++)
set_point(vert, i, quad_x1, quad_y1);
/* Last 3 strip points producing one more degenerate
* plus two real tris.
*/
set_colors(color, v - 1, 4, green);
set_point(vert, v++, quad_x2, quad_y1);
set_point(vert, v++, quad_x1, quad_y2);
set_point(vert, v++, quad_x2, quad_y2);
break;
case GL_TRIANGLE_FAN:
case GL_POLYGON:
v = sv + v_from_end(count, 3, 1);
/* Fan start point plus a bunch of degenerate tris. */
set_colors(color, sv, 1, green);
for (i = sv; i < v; i++)
set_point(vert, i, quad_x1, quad_y1);
/* Last 3 fan points producing the real tris. */
set_colors(color, v, 3, green);
set_point(vert, v++, quad_x2, quad_y1);
set_point(vert, v++, quad_x2, quad_y2);
set_point(vert, v++, quad_x1, quad_y2);
break;
case GL_QUADS:
v = sv + v_from_end(count, 1, 4);
set_colors(color, v, 4, green);
set_point(vert, v++, quad_x1, quad_y1);
set_point(vert, v++, quad_x2, quad_y1);
set_point(vert, v++, quad_x2, quad_y2);
set_point(vert, v++, quad_x1, quad_y2);
break;
case GL_QUAD_STRIP:
v = sv + v_from_end(count, 1, 2);
for (i = sv; i < v; i++) {
if ((i - sv) % 2 == 0)
set_point(vert, i, quad_x1, quad_y1);
else
set_point(vert, i, quad_x2, quad_y1);
}
set_colors(color, v - 2, 4, green);
set_point(vert, v++, quad_x1, quad_y2);
set_point(vert, v++, quad_x2, quad_y2);
break;
default:
fprintf(stderr, "bad primitive\n");
piglit_report_result(PIGLIT_FAIL);
break;
}
/* Initialize the 0 - sv primitives to something that would
* draw some red garbage if we were to accidentally draw using
* them.
*/
v = 0;
switch (primtype) {
case GL_POINTS:
for (i = 0; i < sv; i++) {
set_point(vert, v++,
i % piglit_width,
(i / piglit_width) % piglit_height);
}
break;
case GL_LINES:
case GL_LINE_STRIP:
case GL_LINE_LOOP:
for (i = 0; i < sv / 2; i++) {
int y = i % piglit_height;
set_point(vert, v++, 0, y);
set_point(vert, v++, piglit_width, y);
}
break;
case GL_TRIANGLES:
case GL_TRIANGLE_FAN:
case GL_TRIANGLE_STRIP:
for (i = 0; i < sv / 3; i++) {
set_point(vert, v++, 0, 0);
set_point(vert, v++, piglit_width, 0);
set_point(vert, v++, 0, piglit_height);
}
break;
case GL_QUADS:
case GL_QUAD_STRIP:
case GL_POLYGON:
for (i = 0; i < sv / 4; i++) {
set_point(vert, v++, 0, 0);
set_point(vert, v++, piglit_width, 0);
set_point(vert, v++, piglit_width, piglit_height);
set_point(vert, v++, 0, piglit_height);
}
break;
default:
fprintf(stderr, "bad primitive\n");
piglit_report_result(PIGLIT_FAIL);
break;
}
if (use_vbo)
glUnmapBuffer(GL_ARRAY_BUFFER);
glDrawArrays(primtype, sv, count);
switch (primtype) {
case GL_POINTS:
pass = probe_rect(smallquad_x1, smallquad_y1,
smallquad_x2 - smallquad_x1 + 1,
smallquad_y2 - smallquad_y1 + 1);
break;
case GL_LINES:
case GL_LINE_LOOP:
case GL_LINE_STRIP:
pass = probe_line_rect(quad_x1, quad_y1,
quad_x2, quad_y2);
break;
case GL_TRIANGLES:
case GL_TRIANGLE_FAN:
case GL_TRIANGLE_STRIP:
case GL_QUADS:
case GL_QUAD_STRIP:
case GL_POLYGON:
pass = probe_rect(quad_x1, quad_y1,
quad_x2 - quad_x1,
quad_y2 - quad_y1);
break;
default:
fprintf(stderr, "bad primitive\n");
piglit_report_result(PIGLIT_FAIL);
break;
}
piglit_present_results();
if (!use_vbo)
free(data);
return pass ? PIGLIT_PASS : PIGLIT_FAIL;
}
static const struct {
const char *name;
GLenum e;
} prims[] = {
{ "GL_POINTS", GL_POINTS },
{ "GL_LINES", GL_LINES },
{ "GL_LINE_STRIP", GL_LINE_STRIP },
{ "GL_LINE_LOOP", GL_LINE_LOOP },
{ "GL_TRIANGLES", GL_TRIANGLES },
{ "GL_TRIANGLE_STRIP", GL_TRIANGLE_STRIP },
{ "GL_TRIANGLE_FAN", GL_TRIANGLE_FAN },
{ "GL_QUADS", GL_QUADS },
{ "GL_QUAD_STRIP", GL_QUAD_STRIP },
{ "GL_POLYGON", GL_POLYGON },
};
static void usage(const char *progname)
{
int i;
fprintf(stderr, "Usage: %s <vertcount> <vbo|varray> <primtype>\n",
progname);
fprintf(stderr, "\n");
fprintf(stderr, "primtype may be:\n");
for (i = 0; i < ARRAY_SIZE(prims); i++)
fprintf(stderr, " %s\n", prims[i].name);
exit(1);
}
void
piglit_init(int argc, char **argv)
{
int i;
if (argc != 4)
usage(argv[0]);
count = atoi(argv[1]);
if (strcmp(argv[2], "vbo") == 0) {
piglit_require_extension("GL_ARB_vertex_buffer_object");
use_vbo = true;
} else if (strcmp(argv[2], "varray") != 0) {
usage(argv[0]);
}
for (i = 0; i < ARRAY_SIZE(prims); i++) {
if (strcmp(prims[i].name, argv[3]) == 0) {
primtype = prims[i].e;
break;
}
}
if (i == ARRAY_SIZE(prims))
usage(argv[0]);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment