[Piglit] [PATCH 1/3] Make the functions in ext_framebuffer_multisample/common.cpp available globally
Anuj Phogat
anuj.phogat at gmail.com
Fri Aug 9 14:56:51 PDT 2013
A lot of classes and functions in ext_framebuffer_multisample/common.cpp
can be utilized to develop new piglit test cases. This patch moves the
Fbo and test_pattern classes to a global location tests/util.
Functions from these classes will be utilized in my later patches for
tests in spec/arb_framebuffer_object.
Signed-off-by: Anuj Phogat <anuj.phogat at gmail.com>
---
tests/spec/ext_framebuffer_multisample/common.cpp | 1112 ---------------------
tests/spec/ext_framebuffer_multisample/common.h | 403 +-------
tests/util/CMakeLists.gl.txt | 2 +
tests/util/piglit-fbo.cpp | 204 ++++
tests/util/piglit-fbo.h | 139 +++
tests/util/piglit-test-pattern.cpp | 967 ++++++++++++++++++
tests/util/piglit-test-pattern.h | 322 ++++++
7 files changed, 1636 insertions(+), 1513 deletions(-)
create mode 100644 tests/util/piglit-fbo.cpp
create mode 100644 tests/util/piglit-fbo.h
create mode 100644 tests/util/piglit-test-pattern.cpp
create mode 100644 tests/util/piglit-test-pattern.h
diff --git a/tests/spec/ext_framebuffer_multisample/common.cpp b/tests/spec/ext_framebuffer_multisample/common.cpp
index 65f98f7..1217f54 100644
--- a/tests/spec/ext_framebuffer_multisample/common.cpp
+++ b/tests/spec/ext_framebuffer_multisample/common.cpp
@@ -110,182 +110,6 @@
#include "common.h"
-FboConfig::FboConfig(int num_samples, int width, int height)
- : num_samples(num_samples),
- width(width),
- height(height),
- combine_depth_stencil(true),
- attach_texture(false),
- color_internalformat(GL_RGBA),
- depth_internalformat(GL_DEPTH_COMPONENT24),
- stencil_internalformat(GL_STENCIL_INDEX8)
-{
-}
-
-Fbo::Fbo()
- : config(0, 0, 0), /* will be overwritten on first call to setup() */
- handle(0),
- color_tex(0),
- color_rb(0),
- depth_rb(0),
- stencil_rb(0),
- gl_objects_generated(false)
-{
-}
-
-void
-Fbo::generate_gl_objects(void)
-{
- glGenFramebuffers(1, &handle);
- glGenTextures(1, &color_tex);
- glGenRenderbuffers(1, &color_rb);
- glGenRenderbuffers(1, &depth_rb);
- glGenRenderbuffers(1, &stencil_rb);
- gl_objects_generated = true;
-}
-
-void
-Fbo::set_samples(int num_samples)
-{
- FboConfig new_config = this->config;
- new_config.num_samples = num_samples;
- setup(new_config);
-}
-
-/**
- * Modify the state of the framebuffer object to reflect the state in
- * new_config. if the resulting framebuffer is incomplete, terminate
- * the test.
- */
-void
-Fbo::setup(const FboConfig &new_config)
-{
- if (!try_setup(new_config)) {
- printf("Framebuffer not complete\n");
- piglit_report_result(PIGLIT_SKIP);
- }
-}
-
-
-/**
- * Modify the state of the framebuffer object to reflect the state in
- * config. Return true if the resulting framebuffer is complete,
- * false otherwise.
- */
-bool
-Fbo::try_setup(const FboConfig &new_config)
-{
- this->config = new_config;
-
- if (!gl_objects_generated)
- generate_gl_objects();
-
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, handle);
-
- /* Color buffer */
- if (config.color_internalformat != GL_NONE) {
- if (!config.attach_texture) {
- glBindRenderbuffer(GL_RENDERBUFFER, color_rb);
- glRenderbufferStorageMultisample(GL_RENDERBUFFER,
- config.num_samples,
- config.color_internalformat,
- config.width,
- config.height);
- glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER,
- GL_COLOR_ATTACHMENT0,
- GL_RENDERBUFFER, color_rb);
- } else if (config.num_samples == 0) {
- piglit_require_extension("GL_ARB_texture_rectangle");
- glBindTexture(GL_TEXTURE_RECTANGLE, color_tex);
- glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER,
- GL_NEAREST);
- glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER,
- GL_NEAREST);
- glTexImage2D(GL_TEXTURE_RECTANGLE,
- 0 /* level */,
- config.color_internalformat,
- config.width,
- config.height,
- 0 /* border */,
- GL_RGBA /* format */,
- GL_BYTE /* type */,
- NULL /* data */);
- glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,
- GL_COLOR_ATTACHMENT0,
- GL_TEXTURE_RECTANGLE,
- color_tex,
- 0 /* level */);
- } else {
- piglit_require_extension("GL_ARB_texture_multisample");
- glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, color_tex);
- glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE,
- config.num_samples,
- config.color_internalformat,
- config.width,
- config.height,
- GL_TRUE /* fixed sample locations */);
-
- glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,
- GL_COLOR_ATTACHMENT0,
- GL_TEXTURE_2D_MULTISAMPLE,
- color_tex,
- 0 /* level */);
- }
- }
-
- /* Depth/stencil buffer(s) */
- if (config.combine_depth_stencil) {
- glBindRenderbuffer(GL_RENDERBUFFER, depth_rb);
- glRenderbufferStorageMultisample(GL_RENDERBUFFER,
- config.num_samples,
- GL_DEPTH_STENCIL,
- config.width,
- config.height);
- glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER,
- GL_DEPTH_STENCIL_ATTACHMENT,
- GL_RENDERBUFFER, depth_rb);
- } else {
- if (config.stencil_internalformat != GL_NONE) {
- glBindRenderbuffer(GL_RENDERBUFFER, stencil_rb);
- glRenderbufferStorageMultisample(GL_RENDERBUFFER,
- config.num_samples,
- config.stencil_internalformat,
- config.width,
- config.height);
- glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER,
- GL_STENCIL_ATTACHMENT,
- GL_RENDERBUFFER, stencil_rb);
- }
-
- if (config.depth_internalformat != GL_NONE) {
- glBindRenderbuffer(GL_RENDERBUFFER, depth_rb);
- glRenderbufferStorageMultisample(GL_RENDERBUFFER,
- config.num_samples,
- config.depth_internalformat,
- config.width,
- config.height);
- glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER,
- GL_DEPTH_ATTACHMENT,
- GL_RENDERBUFFER, depth_rb);
- }
- }
-
- bool success = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER)
- == GL_FRAMEBUFFER_COMPLETE;
-
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
-
- return success;
-}
-
-
-
-void
-Fbo::set_viewport()
-{
- glViewport(0, 0, config.width, config.height);
-}
-
void
DownsampleProg::compile(int supersample_factor)
{
@@ -396,942 +220,6 @@ DownsampleProg::run(const Fbo *src_fbo, int dest_width, int dest_height,
glDisable(GL_FRAMEBUFFER_SRGB);
}
-void
-ManifestStencil::compile()
-{
- static const char *vert =
- "#version 120\n"
- "attribute vec2 pos;\n"
- "void main()\n"
- "{\n"
- " gl_Position = vec4(pos, 0.0, 1.0);\n"
- "}\n";
-
- static const char *frag =
- "#version 120\n"
- "uniform vec4 color;\n"
- "void main()\n"
- "{\n"
- " gl_FragColor = color;\n"
- "}\n";
-
- /* Compile program */
- prog = glCreateProgram();
- GLint vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vert);
- glAttachShader(prog, vs);
- GLint fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, frag);
- glAttachShader(prog, fs);
- glBindAttribLocation(prog, 0, "pos");
- glLinkProgram(prog);
- if (!piglit_link_check_status(prog)) {
- piglit_report_result(PIGLIT_FAIL);
- }
-
- /* Set up uniforms */
- glUseProgram(prog);
- color_loc = glGetUniformLocation(prog, "color");
-
- /* Set up vertex array object */
- glGenVertexArrays(1, &vao);
- glBindVertexArray(vao);
-
- /* Set up vertex input buffer */
- float vertex_data[4][2] = {
- { -1, -1 },
- { -1, 1 },
- { 1, 1 },
- { 1, -1 }
- };
- glGenVertexArrays(1, &vertex_buf);
- glBindBuffer(GL_ARRAY_BUFFER, vertex_buf);
- glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data,
- GL_STATIC_DRAW);
- glEnableVertexAttribArray(0);
- glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_data[0]),
- (void *) 0);
-
- /* Set up element input buffer to tesselate a quad into
- * triangles
- */
- unsigned int indices[6] = { 0, 1, 2, 0, 2, 3 };
- GLuint element_buf;
- glGenBuffers(1, &element_buf);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, element_buf);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices,
- GL_STATIC_DRAW);
-}
-
-void
-ManifestStencil::run()
-{
- static float colors[8][4] = {
- { 0.0, 0.0, 0.0, 1.0 },
- { 0.0, 0.0, 1.0, 1.0 },
- { 0.0, 1.0, 0.0, 1.0 },
- { 0.0, 1.0, 1.0, 1.0 },
- { 1.0, 0.0, 0.0, 1.0 },
- { 1.0, 0.0, 1.0, 1.0 },
- { 1.0, 1.0, 0.0, 1.0 },
- { 1.0, 1.0, 1.0, 1.0 }
- };
-
- glUseProgram(prog);
- glBindVertexArray(vao);
-
- glEnable(GL_STENCIL_TEST);
- glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
-
- /* Clear the color buffer to 0, in case the stencil buffer
- * contains any values outside the range 0..7
- */
- glClear(GL_COLOR_BUFFER_BIT);
-
- for (int i = 0; i < 8; ++i) {
- glStencilFunc(GL_EQUAL, i, 0xff);
- glUniform4fv(color_loc, 1, colors[i]);
- glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void *) 0);
- }
-
- glDisable(GL_STENCIL_TEST);
-}
-
-void
-ManifestDepth::compile()
-{
- static const char *vert =
- "#version 120\n"
- "attribute vec2 pos;\n"
- "uniform float depth;\n"
- "void main()\n"
- "{\n"
- " gl_Position = vec4(pos, depth, 1.0);\n"
- "}\n";
-
- static const char *frag =
- "#version 120\n"
- "uniform vec4 color;\n"
- "void main()\n"
- "{\n"
- " gl_FragColor = color;\n"
- "}\n";
-
- /* Compile program */
- prog = glCreateProgram();
- GLint vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vert);
- glAttachShader(prog, vs);
- GLint fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, frag);
- glAttachShader(prog, fs);
- glBindAttribLocation(prog, 0, "pos");
- glLinkProgram(prog);
- if (!piglit_link_check_status(prog)) {
- piglit_report_result(PIGLIT_FAIL);
- }
-
- /* Set up uniforms */
- glUseProgram(prog);
- color_loc = glGetUniformLocation(prog, "color");
- depth_loc = glGetUniformLocation(prog, "depth");
-
- /* Set up vertex array object */
- glGenVertexArrays(1, &vao);
- glBindVertexArray(vao);
-
- /* Set up vertex input buffer */
- float vertex_data[4][2] = {
- { -1, -1 },
- { -1, 1 },
- { 1, 1 },
- { 1, -1 }
- };
- glGenVertexArrays(1, &vertex_buf);
- glBindBuffer(GL_ARRAY_BUFFER, vertex_buf);
- glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data,
- GL_STATIC_DRAW);
- glEnableVertexAttribArray(0);
- glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_data[0]),
- (void *) 0);
-
- /* Set up element input buffer to tesselate a quad into
- * triangles
- */
- unsigned int indices[6] = { 0, 1, 2, 0, 2, 3 };
- GLuint element_buf;
- glGenBuffers(1, &element_buf);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, element_buf);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices,
- GL_STATIC_DRAW);
-}
-
-void
-ManifestDepth::run()
-{
- static float colors[8][4] = {
- { 0.0, 0.0, 0.0, 1.0 },
- { 0.0, 0.0, 1.0, 1.0 },
- { 0.0, 1.0, 0.0, 1.0 },
- { 0.0, 1.0, 1.0, 1.0 },
- { 1.0, 0.0, 0.0, 1.0 },
- { 1.0, 0.0, 1.0, 1.0 },
- { 1.0, 1.0, 0.0, 1.0 },
- { 1.0, 1.0, 1.0, 1.0 }
- };
-
- glUseProgram(prog);
- glBindVertexArray(vao);
-
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_LESS);
- glEnable(GL_STENCIL_TEST);
- glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
- glStencilFunc(GL_EQUAL, 0, 0xff);
-
- /* Clear the stencil buffer to 0, leaving depth and color
- * buffers unchanged.
- */
- glClear(GL_STENCIL_BUFFER_BIT);
-
- for (int i = 0; i < 8; ++i) {
- glUniform4fv(color_loc, 1, colors[i]);
- glUniform1f(depth_loc, float(7 - 2*i)/8);
- glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void *) 0);
- }
-
- glDisable(GL_STENCIL_TEST);
- glDisable(GL_DEPTH_TEST);
-}
-
-
-const float TestPattern::no_projection[4][4] = {
- { 1, 0, 0, 0 },
- { 0, 1, 0, 0 },
- { 0, 0, 1, 0 },
- { 0, 0, 0, 1 }
-};
-
-
-void Triangles::compile()
-{
- /* Triangle coords within (-1,-1) to (1,1) rect */
- static const float pos_within_tri[][2] = {
- { -0.5, -1.0 },
- { 0.0, 1.0 },
- { 0.5, -1.0 }
- };
-
- /* Number of triangle instances across (and down) */
- int tris_across = 8;
-
- /* Total number of triangles drawn */
- num_tris = tris_across * tris_across;
-
- /* Scaling factor uniformly applied to triangle coords */
- float tri_scale = 0.8 / tris_across;
-
- /* Amount each triangle should be rotated compared to prev */
- float rotation_delta = M_PI * 2.0 / num_tris;
-
- /* Final scaling factor */
- float final_scale = 0.95;
-
- static const char *vert =
- "#version 120\n"
- "attribute vec2 pos_within_tri;\n"
- "uniform float tri_scale;\n"
- "uniform float rotation_delta;\n"
- "uniform int tris_across;\n"
- "uniform float final_scale;\n"
- "uniform mat4 proj;\n"
- "uniform int tri_num; /* [0, num_tris) */\n"
- "\n"
- "void main()\n"
- "{\n"
- " vec2 pos = tri_scale * pos_within_tri;\n"
- " float rotation = rotation_delta * tri_num;\n"
- " pos = mat2(cos(rotation), sin(rotation),\n"
- " -sin(rotation), cos(rotation)) * pos;\n"
- " int i = int(mod(float(tri_num), float(tris_across)));\n"
- " int j = tris_across - 1 - tri_num / tris_across;\n"
- " pos += (vec2(i, j) * 2.0 + 1.0) / tris_across - 1.0;\n"
- " pos *= final_scale;\n"
- " gl_Position = proj * vec4(pos, 0.0, 1.0);\n"
- "}\n";
-
- static const char *frag =
- "#version 120\n"
- "void main()\n"
- "{\n"
- " gl_FragColor = vec4(1.0);\n"
- "}\n";
-
- /* Compile program */
- prog = glCreateProgram();
- GLint vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vert);
- glAttachShader(prog, vs);
- GLint fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, frag);
- glAttachShader(prog, fs);
- glBindAttribLocation(prog, 0, "pos_within_tri");
- glLinkProgram(prog);
- if (!piglit_link_check_status(prog)) {
- piglit_report_result(PIGLIT_FAIL);
- }
-
- /* Set up uniforms */
- glUseProgram(prog);
- glUniform1f(glGetUniformLocation(prog, "tri_scale"), tri_scale);
- glUniform1f(glGetUniformLocation(prog, "rotation_delta"),
- rotation_delta);
- glUniform1i(glGetUniformLocation(prog, "tris_across"), tris_across);
- glUniform1f(glGetUniformLocation(prog, "final_scale"), final_scale);
- proj_loc = glGetUniformLocation(prog, "proj");
- tri_num_loc = glGetUniformLocation(prog, "tri_num");
-
- /* Set up vertex array object */
- glGenVertexArrays(1, &vao);
- glBindVertexArray(vao);
-
- /* Set up vertex input buffer */
- glGenBuffers(1, &vertex_buf);
- glBindBuffer(GL_ARRAY_BUFFER, vertex_buf);
- glBufferData(GL_ARRAY_BUFFER, sizeof(pos_within_tri), pos_within_tri,
- GL_STATIC_DRAW);
- glEnableVertexAttribArray(0);
- glVertexAttribPointer(0, ARRAY_SIZE(pos_within_tri[0]), GL_FLOAT,
- GL_FALSE, sizeof(pos_within_tri[0]), (void *) 0);
-}
-
-void Triangles::draw(const float (*proj)[4])
-{
- glClear(GL_COLOR_BUFFER_BIT);
-
- glUseProgram(prog);
- glUniformMatrix4fv(proj_loc, 1, GL_TRUE, &proj[0][0]);
- glBindVertexArray(vao);
- for (int tri_num = 0; tri_num < num_tris; ++tri_num) {
- glUniform1i(tri_num_loc, tri_num);
- glDrawArrays(GL_TRIANGLES, 0, 3);
- }
-}
-
-
-InterpolationTestPattern::InterpolationTestPattern(const char *frag)
- : frag(frag), viewport_size_loc(0)
-{
-}
-
-
-void
-InterpolationTestPattern::compile()
-{
- static struct vertex_attributes {
- float pos_within_tri[2];
- float barycentric_coords[3];
- } vertex_data[] = {
- { { -0.5, -1.0 }, { 1, 0, 0 } },
- { { 0.0, 1.0 }, { 0, 1, 0 } },
- { { 0.5, -1.0 }, { 0, 0, 1 } }
- };
-
- /* Number of triangle instances across (and down) */
- int tris_across = 8;
-
- /* Total number of triangles drawn */
- num_tris = tris_across * tris_across;
-
- /* Scaling factor uniformly applied to triangle coords */
- float tri_scale = 0.8 / tris_across;
-
- /* Amount each triangle should be rotated compared to prev */
- float rotation_delta = M_PI * 2.0 / num_tris;
-
- /* Final scaling factor */
- float final_scale = 0.95;
-
- static const char *vert =
- "#version 120\n"
- "attribute vec2 pos_within_tri;\n"
- "attribute vec3 in_barycentric_coords;\n"
- "varying vec3 barycentric_coords;\n"
- "centroid varying vec3 barycentric_coords_centroid;\n"
- "varying vec2 pixel_pos;\n"
- "centroid varying vec2 pixel_pos_centroid;\n"
- "uniform float tri_scale;\n"
- "uniform float rotation_delta;\n"
- "uniform int tris_across;\n"
- "uniform float final_scale;\n"
- "uniform mat4 proj;\n"
- "uniform int tri_num; /* [0, num_tris) */\n"
- "uniform ivec2 viewport_size;\n"
- "\n"
- "void main()\n"
- "{\n"
- " vec2 pos = tri_scale * pos_within_tri;\n"
- " float rotation = rotation_delta * tri_num;\n"
- " pos = mat2(cos(rotation), sin(rotation),\n"
- " -sin(rotation), cos(rotation)) * pos;\n"
- " int i = int(mod(float(tri_num), float(tris_across)));\n"
- " int j = tris_across - 1 - tri_num / tris_across;\n"
- " pos += (vec2(i, j) * 2.0 + 1.0) / tris_across - 1.0;\n"
- " pos *= final_scale;\n"
- " gl_Position = proj * vec4(pos, 0.0, 1.0);\n"
- " barycentric_coords = barycentric_coords_centroid =\n"
- " in_barycentric_coords;\n"
- " pixel_pos = pixel_pos_centroid =\n"
- " vec2(viewport_size) * (pos + 1.0) / 2.0;\n"
- "}\n";
-
- /* Compile program */
- prog = glCreateProgram();
- GLint vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vert);
- glAttachShader(prog, vs);
- GLint fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, frag);
- glAttachShader(prog, fs);
- glBindAttribLocation(prog, 0, "pos_within_tri");
- glBindAttribLocation(prog, 1, "in_barycentric_coords");
- glLinkProgram(prog);
- if (!piglit_link_check_status(prog)) {
- piglit_report_result(PIGLIT_FAIL);
- }
-
- /* Set up uniforms */
- glUseProgram(prog);
- glUniform1f(glGetUniformLocation(prog, "tri_scale"), tri_scale);
- glUniform1f(glGetUniformLocation(prog, "rotation_delta"),
- rotation_delta);
- glUniform1i(glGetUniformLocation(prog, "tris_across"), tris_across);
- glUniform1f(glGetUniformLocation(prog, "final_scale"), final_scale);
- proj_loc = glGetUniformLocation(prog, "proj");
- tri_num_loc = glGetUniformLocation(prog, "tri_num");
- viewport_size_loc = glGetUniformLocation(prog, "viewport_size");
-
- /* Set up vertex array object */
- glGenVertexArrays(1, &vao);
- glBindVertexArray(vao);
-
- /* Set up vertex input buffer */
- glGenBuffers(1, &vertex_buf);
- glBindBuffer(GL_ARRAY_BUFFER, vertex_buf);
- glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data,
- GL_STATIC_DRAW);
- glEnableVertexAttribArray(0);
- glVertexAttribPointer(0, ARRAY_SIZE(vertex_data[0].pos_within_tri),
- GL_FLOAT, GL_FALSE, sizeof(vertex_data[0]),
- (void *) offsetof(vertex_attributes,
- pos_within_tri));
- glEnableVertexAttribArray(1);
- glVertexAttribPointer(1, ARRAY_SIZE(vertex_data[0].barycentric_coords),
- GL_FLOAT, GL_FALSE, sizeof(vertex_data[0]),
- (void *) offsetof(vertex_attributes,
- barycentric_coords));
-}
-
-
-void
-InterpolationTestPattern::draw(const float (*proj)[4])
-{
- glUseProgram(prog);
-
- /* Depending what the fragment shader does, it's possible that
- * viewport_size might get optimized away. Only set it if it
- * didn't.
- */
- if (viewport_size_loc != -1) {
- GLint viewport_dims[4];
- glGetIntegerv(GL_VIEWPORT, viewport_dims);
- glUniform2i(viewport_size_loc, viewport_dims[2], viewport_dims[3]);
- }
-
- Triangles::draw(proj);
-}
-
-
-void Lines::compile()
-{
- /* Line coords within (-1,-1) to (1,1) rect */
- static const float pos_line[][2] = {
- { -0.8, -0.5 },
- { 0.8, -0.5 }
- };
-
- /* Number of line instances across (and down) */
- int lines_across = 4;
-
- /* Total number of lines drawn */
- num_lines = lines_across * lines_across;
-
- /* Amount each line should be rotated compared to prev */
- float rotation_delta = M_PI * 2.0 / num_lines;
-
- /* Scaling factor uniformly applied to line coords */
- float line_scale = 0.8 / lines_across;
-
- /* Final scaling factor */
- float final_scale = 0.95;
-
- static const char *vert =
- "#version 120\n"
- "attribute vec2 pos_line;\n"
- "uniform float line_scale;\n"
- "uniform float rotation_delta;\n"
- "uniform int lines_across;\n"
- "uniform float final_scale;\n"
- "uniform mat4 proj;\n"
- "uniform int line_num;\n"
- "\n"
- "void main()\n"
- "{\n"
- " vec2 pos = line_scale * pos_line;\n"
- " float rotation = rotation_delta * line_num;\n"
- " pos = mat2(cos(rotation), sin(rotation),\n"
- " -sin(rotation), cos(rotation)) * pos;\n"
- " int i = int(mod(float(line_num), float(lines_across)));\n"
- " int j = lines_across - 1 - line_num / lines_across;\n"
- " pos += (vec2(i, j) * 2.0 + 1.0) / lines_across - 1.0;\n"
- " pos *= final_scale;\n"
- " gl_Position = proj * vec4(pos, 0.0, 1.0);\n"
- "}\n";
-
- static const char *frag =
- "#version 120\n"
- "void main()\n"
- "{\n"
- " gl_FragColor = vec4(1.0);\n"
- "}\n";
-
- /* Compile program */
- prog = glCreateProgram();
- GLint vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vert);
- glAttachShader(prog, vs);
- GLint fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, frag);
- glAttachShader(prog, fs);
- glBindAttribLocation(prog, 0, "pos_line");
- glLinkProgram(prog);
- if (!piglit_link_check_status(prog)) {
- piglit_report_result(PIGLIT_FAIL);
- }
-
- /* Set up uniforms */
- glUseProgram(prog);
- glUniform1f(glGetUniformLocation(prog, "line_scale"), line_scale);
- glUniform1f(glGetUniformLocation(prog, "rotation_delta"),
- rotation_delta);
- glUniform1i(glGetUniformLocation(prog, "lines_across"), lines_across);
- glUniform1f(glGetUniformLocation(prog, "final_scale"), final_scale);
- proj_loc = glGetUniformLocation(prog, "proj");
- line_num_loc = glGetUniformLocation(prog, "line_num");
-
- /* Set up vertex array object */
- glGenVertexArrays(1, &vao);
- glBindVertexArray(vao);
-
- /* Set up vertex input buffer */
- glGenBuffers(1, &vertex_buf);
- glBindBuffer(GL_ARRAY_BUFFER, vertex_buf);
- glBufferData(GL_ARRAY_BUFFER, sizeof(pos_line), pos_line,
- GL_STATIC_DRAW);
- glEnableVertexAttribArray(0);
- glVertexAttribPointer(0, ARRAY_SIZE(pos_line[0]), GL_FLOAT,
- GL_FALSE, sizeof(pos_line[0]), (void *) 0);
-}
-
-void Lines::draw(const float (*proj)[4])
-{
- glClear(GL_COLOR_BUFFER_BIT);
- glUseProgram(prog);
- glUniformMatrix4fv(proj_loc, 1, GL_TRUE, &proj[0][0]);
- glBindVertexArray(vao);
- for (int line_num = 0; line_num < num_lines; ++line_num) {
- /* Draws with line width = 0.25, 0.75, 1.25,
- * 1.75, 2.25, 2.75, 3.25, 3.75
- */
- glLineWidth((1 + 2 * line_num) / 4.0);
- glUniform1i(line_num_loc, line_num);
- glDrawArrays(GL_LINES, 0, 2);
- }
-}
-
-void Points::compile()
-{
- /* Point coords within (-1,-1) to (1,1) rect */
- static const float pos_point[2] = { -0.5, -0.5 };
-
- /* Number of point instances across (and down) */
- int points_across = 4;
-
- /* Total number of points drawn */
- num_points = points_across * points_across;
-
- /* Scaling factor uniformly applied to point coords */
- float point_scale = 0.8 / points_across;
-
- /* Final scaling factor */
- float final_scale = 0.95;
-
- static const char *vert =
- "#version 120\n"
- "attribute vec2 pos_point;\n"
- "uniform float point_scale;\n"
- "uniform int points_across;\n"
- "uniform float final_scale;\n"
- "uniform mat4 proj;\n"
- "uniform int point_num;\n"
- "uniform float depth;\n"
- "\n"
- "void main()\n"
- "{\n"
- " vec2 pos = point_scale * pos_point;\n"
- " int i = int(mod(float(point_num), float(points_across)));\n"
- " int j = points_across - 1 - point_num / points_across;\n"
- " pos += (vec2(i, j) * 2.0 + 1.0) / points_across - 1.0;\n"
- " pos *= final_scale;\n"
- " gl_Position = proj * vec4(pos, depth, 1.0);\n"
- "}\n";
-
- static const char *frag =
- "#version 120\n"
- "void main()\n"
- "{\n"
- " gl_FragColor = vec4(1.0);\n"
- "}\n";
-
- /* Compile program */
- prog = glCreateProgram();
- GLint vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vert);
- glAttachShader(prog, vs);
- GLint fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, frag);
- glAttachShader(prog, fs);
- glBindAttribLocation(prog, 0, "pos_point");
- glLinkProgram(prog);
- if (!piglit_link_check_status(prog)) {
- piglit_report_result(PIGLIT_FAIL);
- }
-
- /* Set up uniforms */
- glUseProgram(prog);
- glUniform1f(glGetUniformLocation(prog, "point_scale"), point_scale);
- glUniform1i(glGetUniformLocation(prog, "points_across"), points_across);
- glUniform1f(glGetUniformLocation(prog, "final_scale"), final_scale);
- proj_loc = glGetUniformLocation(prog, "proj");
- point_num_loc = glGetUniformLocation(prog, "point_num");
- depth_loc = glGetUniformLocation(prog, "depth");
-
- /* Set up vertex array object */
- glGenVertexArrays(1, &vao);
- glBindVertexArray(vao);
-
- /* Set up vertex input buffer */
- glGenBuffers(1, &vertex_buf);
- glBindBuffer(GL_ARRAY_BUFFER, vertex_buf);
- glBufferData(GL_ARRAY_BUFFER, sizeof(pos_point), pos_point,
- GL_STATIC_DRAW);
- glEnableVertexAttribArray(0);
- glVertexAttribPointer(0, ARRAY_SIZE(pos_point), GL_FLOAT,
- GL_FALSE, 0, (void *) 0);
-}
-
-void Points::draw(const float (*proj)[4])
-{
- glClear(GL_COLOR_BUFFER_BIT);
- glUseProgram(prog);
- glUniformMatrix4fv(proj_loc, 1, GL_TRUE, &proj[0][0]);
- glBindVertexArray(vao);
- glUniform1f(depth_loc, 0.0);
- for (int point_num = 0; point_num < num_points; ++point_num) {
- glPointSize((1.0 + 4 * point_num) / 4.0);
- glUniform1i(point_num_loc, point_num);
- glDrawArrays(GL_POINTS, 0, 1);
- }
-}
-
-Sunburst::Sunburst()
- : out_type(GL_UNSIGNED_NORMALIZED),
- compute_depth(false),
- prog(0),
- rotation_loc(0),
- vert_depth_loc(0),
- frag_depth_loc(0),
- proj_loc(0),
- draw_colors_loc(0),
- vao(0),
- num_tris(0),
- vertex_buf(0)
-{
-}
-
-
-/**
- * Determine the GLSL type that should be used for rendering, based on
- * out_type.
- */
-const char *
-Sunburst::get_out_type_glsl() const
-{
- switch(out_type) {
- case GL_INT:
- return "ivec4";
- case GL_UNSIGNED_INT:
- return "uvec4";
- case GL_UNSIGNED_NORMALIZED:
- case GL_FLOAT:
- return "vec4";
- default:
- printf("Unrecognized out_type: %s\n",
- piglit_get_gl_enum_name(out_type));
- piglit_report_result(PIGLIT_FAIL);
- return "UNKNOWN";
- }
-}
-
-
-void Sunburst::compile()
-{
- static struct vertex_attributes {
- float pos_within_tri[2];
- float barycentric_coords[3];
- } vertex_data[] = {
- { { -0.3, -0.8 }, { 1, 0, 0 } },
- { { 0.0, 1.0 }, { 0, 1, 0 } },
- { { 0.3, -0.8 }, { 0, 0, 1 } }
- };
- bool need_glsl130 = out_type == GL_INT || out_type == GL_UNSIGNED_INT;
-
- if (need_glsl130) {
- piglit_require_gl_version(30);
- }
-
- /* Total number of triangles drawn */
- num_tris = 7;
-
- static const char *vert_template =
- "#version %s\n"
- "attribute vec2 pos_within_tri;\n"
- "attribute vec3 in_barycentric_coords;\n"
- "varying vec3 barycentric_coords;\n"
- "uniform float rotation;\n"
- "uniform float vert_depth;\n"
- "uniform mat4 proj;\n"
- "\n"
- "void main()\n"
- "{\n"
- " vec2 pos = pos_within_tri;\n"
- " pos = mat2(cos(rotation), sin(rotation),\n"
- " -sin(rotation), cos(rotation)) * pos;\n"
- " gl_Position = proj * vec4(pos, vert_depth, 1.0);\n"
- " barycentric_coords = in_barycentric_coords;\n"
- "}\n";
-
- static const char *frag_template =
- "#version %s\n"
- "#define OUT_TYPE %s\n"
- "#define COMPUTE_DEPTH %s\n"
- "uniform float frag_depth;\n"
- "varying vec3 barycentric_coords;\n"
- "uniform mat3x4 draw_colors;\n"
- "#if __VERSION__ == 130\n"
- " out OUT_TYPE frag_out;\n"
- "#endif\n"
- "\n"
- "void main()\n"
- "{\n"
- "#if __VERSION__ == 130\n"
- " frag_out = OUT_TYPE(draw_colors * barycentric_coords);\n"
- "#else\n"
- " gl_FragColor = draw_colors * barycentric_coords;\n"
- "#endif\n"
- "#if COMPUTE_DEPTH\n"
- " gl_FragDepth = (frag_depth + 1.0) / 2.0;\n"
- "#endif\n"
- "}\n";
-
- /* Compile program */
- prog = glCreateProgram();
- unsigned vert_alloc_len =
- strlen(vert_template) + 4;
- char *vert = (char *) malloc(vert_alloc_len);
- sprintf(vert, vert_template, need_glsl130 ? "130" : "120");
- GLint vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vert);
- free(vert);
- glAttachShader(prog, vs);
-
- const char *out_type_glsl = get_out_type_glsl();
- unsigned frag_alloc_len =
- strlen(frag_template) + strlen(out_type_glsl) + 4;
- char *frag = (char *) malloc(frag_alloc_len);
- sprintf(frag, frag_template, need_glsl130 ? "130" : "120",
- out_type_glsl,
- compute_depth ? "1" : "0");
- GLint fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, frag);
- free(frag);
- glAttachShader(prog, fs);
-
- glBindAttribLocation(prog, 0, "pos_within_tri");
- glBindAttribLocation(prog, 1, "in_barycentric_coords");
- if (need_glsl130) {
- glBindFragDataLocation(prog, 0, "frag_out");
- }
- glLinkProgram(prog);
- if (!piglit_link_check_status(prog)) {
- piglit_report_result(PIGLIT_FAIL);
- }
-
- /* Set up uniforms */
- glUseProgram(prog);
- rotation_loc = glGetUniformLocation(prog, "rotation");
- vert_depth_loc = glGetUniformLocation(prog, "vert_depth");
- frag_depth_loc = glGetUniformLocation(prog, "frag_depth");
- glUniform1f(vert_depth_loc, 0.0);
- glUniform1f(frag_depth_loc, 0.0);
- proj_loc = glGetUniformLocation(prog, "proj");
- draw_colors_loc = glGetUniformLocation(prog, "draw_colors");
-
- /* Set up vertex array object */
- glGenVertexArrays(1, &vao);
- glBindVertexArray(vao);
-
- /* Set up vertex input buffer */
- glGenBuffers(1, &vertex_buf);
- glBindBuffer(GL_ARRAY_BUFFER, vertex_buf);
- glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data,
- GL_STATIC_DRAW);
- glEnableVertexAttribArray(0);
- glVertexAttribPointer(0, ARRAY_SIZE(vertex_data[0].pos_within_tri),
- GL_FLOAT, GL_FALSE, sizeof(vertex_data[0]),
- (void *) 0);
- glEnableVertexAttribArray(1);
- glVertexAttribPointer(1, ARRAY_SIZE(vertex_data[0].barycentric_coords),
- GL_FLOAT, GL_FALSE, sizeof(vertex_data[0]),
- (void *) offsetof(vertex_attributes,
- barycentric_coords));
-}
-
-
-ColorGradientSunburst::ColorGradientSunburst(GLenum out_type)
-{
- this->out_type = out_type;
-}
-
-
-/**
- * Draw the color gradient sunburst, but instead of using color
- * components that range from 0.0 to 1.0, apply the given scaling
- * factor and offset to each color component.
- *
- * The offset is also applied when clearing the color buffer.
- */
-void
-ColorGradientSunburst::draw_with_scale_and_offset(const float (*proj)[4],
- float scale, float offset)
-{
- switch (out_type) {
- case GL_INT: {
- int clear_color[4] = { offset, offset, offset, offset };
- glClearBufferiv(GL_COLOR, 0, clear_color);
- break;
- }
- case GL_UNSIGNED_INT: {
- unsigned clear_color[4] = { offset, offset, offset, offset };
- glClearBufferuiv(GL_COLOR, 0, clear_color);
- break;
- }
- case GL_UNSIGNED_NORMALIZED:
- case GL_FLOAT: {
- glClearColor(offset, offset, offset, offset);
- glClear(GL_COLOR_BUFFER_BIT);
- break;
- }
- default:
- printf("Unrecognized out_type: %s\n",
- piglit_get_gl_enum_name(out_type));
- piglit_report_result(PIGLIT_FAIL);
- break;
- }
-
- glUseProgram(prog);
- glUniformMatrix4fv(proj_loc, 1, GL_TRUE, &proj[0][0]);
- float draw_colors[3][4] =
- { { 1, 0, 0, 1.0 }, { 0, 1, 0, 0.5 }, { 0, 0, 1, 1.0 } };
- for (int i = 0; i < 3; ++i) {
- for (int j = 0; j < 4; ++j) {
- draw_colors[i][j] = scale * draw_colors[i][j] + offset;
- }
- }
- glUniformMatrix3x4fv(draw_colors_loc, 1, GL_FALSE,
- &draw_colors[0][0]);
- glBindVertexArray(vao);
- for (int i = 0; i < num_tris; ++i) {
- glUniform1f(rotation_loc, M_PI * 2.0 * i / num_tris);
- glDrawArrays(GL_TRIANGLES, 0, 3);
- }
-}
-
-
-void
-ColorGradientSunburst::draw(const float (*proj)[4])
-{
- draw_with_scale_and_offset(proj, 1.0, 0.0);
-}
-
-
-void
-StencilSunburst::draw(const float (*proj)[4])
-{
- glEnable(GL_STENCIL_TEST);
- glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
-
- glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-
- glUseProgram(prog);
- glUniformMatrix4fv(proj_loc, 1, GL_TRUE, &proj[0][0]);
- glBindVertexArray(vao);
- for (int i = 0; i < num_tris; ++i) {
- glStencilFunc(GL_ALWAYS, i+1, 0xff);
- glUniform1f(rotation_loc, M_PI * 2.0 * i / num_tris);
- glDrawArrays(GL_TRIANGLES, 0, 3);
- }
-
- glDisable(GL_STENCIL_TEST);
-}
-
-
-DepthSunburst::DepthSunburst(bool compute_depth)
-{
- this->compute_depth = compute_depth;
-}
-
-
-void
-DepthSunburst::draw(const float (*proj)[4])
-{
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_LESS);
-
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- glUseProgram(prog);
- glUniformMatrix4fv(proj_loc, 1, GL_TRUE, &proj[0][0]);
- glBindVertexArray(vao);
- for (int i = 0; i < num_tris; ++i) {
- /* Draw triangles in a haphazard order so we can
- * verify that depth comparisons sort them out
- * properly.
- */
- int triangle_to_draw = (i * 3) % num_tris;
-
- /* Note: with num_tris == 7, this causes us to draw
- * triangles at depths of 3/4, 1/2, -1/4, 0, 1/4, 1/2,
- * and 3/4.
- */
- glUniform1f(compute_depth ? frag_depth_loc : vert_depth_loc,
- float(num_tris - triangle_to_draw * 2 - 1)
- / (num_tris + 1));
-
- glUniform1f(rotation_loc,
- M_PI * 2.0 * triangle_to_draw / num_tris);
- glDrawArrays(GL_TRIANGLES, 0, 3);
- }
-
- glDisable(GL_DEPTH_TEST);
-}
-
Stats::Stats()
: count(0), sum_squared_error(0.0)
{
diff --git a/tests/spec/ext_framebuffer_multisample/common.h b/tests/spec/ext_framebuffer_multisample/common.h
index 710d77e..eee31f0 100644
--- a/tests/spec/ext_framebuffer_multisample/common.h
+++ b/tests/spec/ext_framebuffer_multisample/common.h
@@ -27,6 +27,8 @@
*/
#include "piglit-util-gl-common.h"
+#include "piglit-test-pattern.h"
+#include "piglit-fbo.h"
#include "math.h"
enum test_type_enum {
@@ -39,115 +41,6 @@ enum test_type_enum {
};
/**
- * Information needed to configure a framebuffer object for MSAA
- * testing.
- */
-class FboConfig
-{
-public:
- FboConfig(int num_samples, int width, int height);
-
- int num_samples;
- int width;
- int height;
-
- /**
- * True if a single renderbuffer should be used as the backing
- * store for both the depth and stencil attachment points.
- * Defaults to true.
- */
- bool combine_depth_stencil;
-
- /**
- * True if a texture should be used as the backing store for
- * the color attachment point, false if a renderbuffer should
- * be used. Defaults to false.
- */
- bool attach_texture;
-
- /**
- * Internalformat that should be used for the color buffer, or
- * GL_NONE if no color buffer should be used. Defaults to
- * GL_RGBA.
- */
- GLenum color_internalformat;
-
- /**
- * Internalformat that should be used for the depth buffer, or
- * GL_NONE if no depth buffer should be used. Ignored if
- * combine_depth_stencil is true. Defaults to
- * GL_DEPTH_COMPONENT24.
- */
- GLenum depth_internalformat;
-
- /**
- * Internalformat that should be used for the stencil buffer,
- * or GL_NONE if no stencil buffer should be used. Ignored if
- * combine_depth_stencil is true. Defaults to
- * GL_STENCIL_INDEX8.
- */
- GLenum stencil_internalformat;
-};
-
-/**
- * Data structure representing one of the framebuffer objects used in
- * the test.
- *
- * For the supersampled framebuffer object we use a texture as the
- * backing store for the color buffer so that we can use a fragment
- * shader to blend down to the reference image.
- */
-class Fbo
-{
-public:
- Fbo();
-
- void set_samples(int num_samples);
- void setup(const FboConfig &new_config);
- bool try_setup(const FboConfig &new_config);
-
- void set_viewport();
-
- FboConfig config;
- GLuint handle;
-
- /**
- * If config.attach_texture is true, the backing store for the
- * color buffer.
- */
- GLuint color_tex;
-
- /**
- * If config.attach_texture is false, the backing store for
- * the color buffer.
- */
- GLuint color_rb;
-
- /**
- * If config.combine_depth_stencil is true, the backing store
- * for the depth/stencil buffer. If
- * config.combine_depth_stencil is false, the backing store
- * for the depth buffer.
- */
- GLuint depth_rb;
-
- /**
- * If config.combine_depth_stencil is false, the backing store
- * for the stencil buffer.
- */
- GLuint stencil_rb;
-
-private:
- void generate_gl_objects();
-
- /**
- * True if generate_gl_objects has been called and color_tex,
- * color_rb, depth_rb, and stencil_rb have been initialized.
- */
- bool gl_objects_generated;
-};
-
-/**
* Fragment shader program we apply to the supersampled color buffer
* to produce the reference image. This program manually blends each
* 16x16 block of samples in the supersampled color buffer down to a
@@ -167,298 +60,6 @@ private:
};
/**
- * There are two programs used to "manifest" an auxiliary buffer,
- * turning it into visible colors: one for manifesting the stencil
- * buffer, and one for manifesting the depth buffer. This is the base
- * class that they both derive from.
- */
-class ManifestProgram
-{
-public:
- virtual void compile() = 0;
- virtual void run() = 0;
-};
-
-/**
- * Program we use to manifest the stencil buffer.
- *
- * This program operates by repeatedly drawing over the entire buffer
- * using the stencil function "EQUAL", and a different color each
- * time. This causes stencil values from 0 to 7 to manifest as colors
- * (black, blue, green, cyan, red, magenta, yellow, white).
- */
-class ManifestStencil : public ManifestProgram
-{
-public:
- virtual void compile();
- virtual void run();
-
-private:
- GLint prog;
- GLint color_loc;
- GLuint vertex_buf;
- GLuint vao;
-};
-
-/**
- * Program we use to manifest the depth buffer.
- *
- * This program operates by repeatedly drawing over the entire buffer
- * at decreasing depth values with depth test enabled; the stencil
- * function is configured to "EQUAL" with a stencil op of "INCR", so
- * that after a sample passes the depth test, its stencil value will
- * be incremented and it will fail the stencil test on later draws.
- * As a result, depth values from back to front will manifest as
- * colors (black, blue, green, cyan, red, magenta, yellow, white).
- */
-class ManifestDepth : public ManifestProgram
-{
-public:
- virtual void compile();
- virtual void run();
-
-private:
- GLint prog;
- GLint color_loc;
- GLint depth_loc;
- GLuint vertex_buf;
- GLuint vao;
-};
-
-/**
- * There are three programs used to draw a test pattern, depending on
- * whether we are testing the color buffer, the depth buffer, or the
- * stencil buffer. This is the base class that they all derive from.
- */
-class TestPattern
-{
-public:
- virtual void compile() = 0;
-
- /**
- * Draw the test pattern, applying the given projection matrix
- * to vertex coordinates. The projection matrix is in
- * row-major order.
- *
- * If no projection transformation is needed, pass
- * TestPattern::no_projection for \c proj.
- */
- virtual void draw(const float (*proj)[4]) = 0;
-
- static const float no_projection[4][4];
-};
-
-/**
- * Program we use to draw a test pattern into the color buffer.
- *
- * This program draws a grid of small disjoint triangles, each rotated
- * at a different angle. This ensures that the image will have a
- * large number of edges at different angles, so that we'll thoroughly
- * exercise antialiasing.
- */
-class Triangles : public TestPattern
-{
-public:
- virtual void compile();
- virtual void draw(const float (*proj)[4]);
-
-protected:
- GLint prog;
- GLuint vertex_buf;
- GLuint vao;
- GLint proj_loc;
- GLint tri_num_loc;
- int num_tris;
-};
-
-
-/**
- * Program we use to test that interpolation works properly.
- *
- * This program draws the same sequence of small triangles as the
- * Triangles program, but it's capable of coloring the triangles in
- * various ways based on the fragment program provided to the
- * constructor.
- *
- * The fragment program has access to the following variables:
- *
- * - in vec3 barycentric_coords: barycentric coordinates of the
- * triangle being drawn, normally interpolated.
- *
- * - centroid in vec3 barycentric_coords_centroid: same as
- * barycentric_coords, but centroid interpolated.
- *
- * - in vec2 pixel_pos: pixel coordinate ((0,0) to (viewport_width,
- * viewport_height)), normally interpolated.
- *
- * - centroid in vec2 pixel_pos_centroid: same as pixel_pos, but
- * centroid interpolated.
- */
-class InterpolationTestPattern : public Triangles
-{
-public:
- explicit InterpolationTestPattern(const char *frag);
- virtual void compile();
- virtual void draw(const float (*proj)[4]);
-
-private:
- const char *frag;
- GLint viewport_size_loc;
-};
-
-
-/**
- * Program we use to draw a test pattern into the color buffer.
- *
- * This program draws a sequence of points with varied sizes. This ensures
- * antialiasing works well with all point sizes.
- */
-class Points : public TestPattern
-{
-public:
- virtual void compile();
- virtual void draw(const float (*proj)[4]);
-
-private:
- GLint prog;
- GLuint vao;
- GLint proj_loc;
- GLint depth_loc;
- GLint point_num_loc;
- GLuint vertex_buf;
- int num_points;
-};
-
-/**
- * Program we use to draw a test pattern into the color buffer.
- *
- * This program draws a sequence of lines with varied width. This ensures
- * antialiasing works well with all line widths.
- */
-class Lines : public TestPattern
-{
-public:
- virtual void compile();
- virtual void draw(const float (*proj)[4]);
-
-private:
- GLint prog;
- GLuint vao;
- GLint proj_loc;
- GLint line_num_loc;
- GLuint vertex_buf;
- int num_lines;
-};
-
-/**
- * Program we use to draw a test pattern into the depth and stencil
- * buffers.
- *
- * This program draws a "sunburst" pattern consisting of 7 overlapping
- * triangles, each at a different angle. This ensures that the
- * triangles overlap in a complex way, with the edges between them
- * covering a a large number of different angles, so that we'll
- * thoroughly exercise antialiasing.
- *
- * This program is further specialized into depth and stencil variants.
- */
-class Sunburst : public TestPattern
-{
-public:
- Sunburst();
-
- virtual void compile();
-
- /**
- * Type of color buffer being rendered into. Should be one of
- * the following enum values: GL_FLOAT,
- * GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_INT, or GL_INT.
- *
- * Defaults to GL_UNSIGNED_NORMALIZED.
- */
- GLenum out_type;
-
- /**
- * Whether or not the fragment shader should output a depth
- * value.
- *
- * Defaults to false.
- */
- bool compute_depth;
-
-protected:
- GLint prog;
- GLint rotation_loc;
- GLint vert_depth_loc;
- GLint frag_depth_loc;
- GLint proj_loc;
- GLint draw_colors_loc;
- GLuint vao;
- int num_tris;
-
-private:
- const char *get_out_type_glsl() const;
-
- GLuint vertex_buf;
-};
-
-/**
- * Program that draws a test pattern into the color buffer.
- *
- * This program draws triangles using a variety of colors and
- * gradients.
- *
- * This program is capable of drawing to floating point, integer, and
- * unsigned integer framebuffers, controlled by the out_type
- * constructor parameter, which should be GL_FLOAT,
- * GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_INT, or GL_INT.
- */
-class ColorGradientSunburst : public Sunburst
-{
-public:
- explicit ColorGradientSunburst(GLenum out_type);
-
- virtual void draw(const float (*proj)[4]);
-
- void draw_with_scale_and_offset(const float (*proj)[4],
- float scale, float offset);
-};
-
-/**
- * Program we use to draw a test pattern into the stencil buffer.
- *
- * The triangles in this sunburst are drawn back-to-front, using no
- * depth testing. Each triangle is drawn using a different stencil
- * value.
- */
-class StencilSunburst : public Sunburst
-{
-public:
- virtual void draw(const float (*proj)[4]);
-};
-
-/**
- * Program we use to draw a test pattern into the depth buffer.
- *
- * The triangles in this sunburst are drawn at a series of different
- * depth values, with depth testing enabled. They are drawn in an
- * arbitrary non-consecutive order, to verify that depth testing
- * properly sorts the surfaces into front-to-back order.
- *
- * If the constructor parameter compute_depth is true, the depth value
- * is determined using a fragment shader output. If it is false, it
- * is determined by the z value of the vertex shader gl_Position
- * output.
- */
-class DepthSunburst : public Sunburst
-{
-public:
- explicit DepthSunburst(bool compute_depth = false);
-
- virtual void draw(const float (*proj)[4]);
-};
-
-/**
* Data structure for keeping track of statistics on pixel accuracy.
*
* We keep track of the number of pixels tested, and the sum of the
diff --git a/tests/util/CMakeLists.gl.txt b/tests/util/CMakeLists.gl.txt
index 10be17a..d8fb32c 100644
--- a/tests/util/CMakeLists.gl.txt
+++ b/tests/util/CMakeLists.gl.txt
@@ -6,6 +6,8 @@ set(UTIL_GL_SOURCES
piglit-shader-gl.c
piglit-util-gl-enum.c
piglit-util-gl.c
+ piglit-test-pattern.cpp
+ piglit-fbo.cpp
piglit-vbo.cpp
sized-internalformats.c
minmax-test.c
diff --git a/tests/util/piglit-fbo.cpp b/tests/util/piglit-fbo.cpp
new file mode 100644
index 0000000..f466f42
--- /dev/null
+++ b/tests/util/piglit-fbo.cpp
@@ -0,0 +1,204 @@
+/*
+ * 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 piglit-fbo.cpp
+ *
+ * This file defines the functions which can be utilized to develop
+ * new piglit test cases. These functions initialize a framebuffer
+ * object based on paramaters passed.
+ */
+#include "piglit-fbo.h"
+
+FboConfig::FboConfig(int num_samples, int width, int height)
+ : num_samples(num_samples),
+ width(width),
+ height(height),
+ combine_depth_stencil(true),
+ attach_texture(false),
+ color_internalformat(GL_RGBA),
+ depth_internalformat(GL_DEPTH_COMPONENT24),
+ stencil_internalformat(GL_STENCIL_INDEX8)
+{
+}
+
+Fbo::Fbo()
+ : config(0, 0, 0), /* will be overwritten on first call to setup() */
+ handle(0),
+ color_tex(0),
+ color_rb(0),
+ depth_rb(0),
+ stencil_rb(0),
+ gl_objects_generated(false)
+{
+}
+
+void
+Fbo::generate_gl_objects(void)
+{
+ glGenFramebuffers(1, &handle);
+ glGenTextures(1, &color_tex);
+ glGenRenderbuffers(1, &color_rb);
+ glGenRenderbuffers(1, &depth_rb);
+ glGenRenderbuffers(1, &stencil_rb);
+ gl_objects_generated = true;
+}
+
+void
+Fbo::set_samples(int num_samples)
+{
+ FboConfig new_config = this->config;
+ new_config.num_samples = num_samples;
+ setup(new_config);
+}
+
+/**
+ * Modify the state of the framebuffer object to reflect the state in
+ * new_config. if the resulting framebuffer is incomplete, terminate
+ * the test.
+ */
+void
+Fbo::setup(const FboConfig &new_config)
+{
+ if (!try_setup(new_config)) {
+ printf("Framebuffer not complete\n");
+ piglit_report_result(PIGLIT_SKIP);
+ }
+}
+
+/**
+ * Modify the state of the framebuffer object to reflect the state in
+ * config. Return true if the resulting framebuffer is complete,
+ * false otherwise.
+ */
+bool
+Fbo::try_setup(const FboConfig &new_config)
+{
+ this->config = new_config;
+
+ if (!gl_objects_generated)
+ generate_gl_objects();
+
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, handle);
+
+ /* Color buffer */
+ if (config.color_internalformat != GL_NONE) {
+ if (!config.attach_texture) {
+ glBindRenderbuffer(GL_RENDERBUFFER, color_rb);
+ glRenderbufferStorageMultisample(GL_RENDERBUFFER,
+ config.num_samples,
+ config.color_internalformat,
+ config.width,
+ config.height);
+ glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER,
+ GL_COLOR_ATTACHMENT0,
+ GL_RENDERBUFFER, color_rb);
+ } else if (config.num_samples == 0) {
+ piglit_require_extension("GL_ARB_texture_rectangle");
+ glBindTexture(GL_TEXTURE_RECTANGLE, color_tex);
+ glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER,
+ GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER,
+ GL_NEAREST);
+ glTexImage2D(GL_TEXTURE_RECTANGLE,
+ 0 /* level */,
+ config.color_internalformat,
+ config.width,
+ config.height,
+ 0 /* border */,
+ GL_RGBA /* format */,
+ GL_BYTE /* type */,
+ NULL /* data */);
+ glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,
+ GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_RECTANGLE,
+ color_tex,
+ 0 /* level */);
+ } else {
+ piglit_require_extension("GL_ARB_texture_multisample");
+ glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, color_tex);
+ glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE,
+ config.num_samples,
+ config.color_internalformat,
+ config.width,
+ config.height,
+ GL_TRUE /* fixed sample locations */);
+
+ glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,
+ GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D_MULTISAMPLE,
+ color_tex,
+ 0 /* level */);
+ }
+ }
+
+ /* Depth/stencil buffer(s) */
+ if (config.combine_depth_stencil) {
+ glBindRenderbuffer(GL_RENDERBUFFER, depth_rb);
+ glRenderbufferStorageMultisample(GL_RENDERBUFFER,
+ config.num_samples,
+ GL_DEPTH_STENCIL,
+ config.width,
+ config.height);
+ glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER,
+ GL_DEPTH_STENCIL_ATTACHMENT,
+ GL_RENDERBUFFER, depth_rb);
+ } else {
+ if (config.stencil_internalformat != GL_NONE) {
+ glBindRenderbuffer(GL_RENDERBUFFER, stencil_rb);
+ glRenderbufferStorageMultisample(GL_RENDERBUFFER,
+ config.num_samples,
+ config.stencil_internalformat,
+ config.width,
+ config.height);
+ glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER,
+ GL_STENCIL_ATTACHMENT,
+ GL_RENDERBUFFER, stencil_rb);
+ }
+
+ if (config.depth_internalformat != GL_NONE) {
+ glBindRenderbuffer(GL_RENDERBUFFER, depth_rb);
+ glRenderbufferStorageMultisample(GL_RENDERBUFFER,
+ config.num_samples,
+ config.depth_internalformat,
+ config.width,
+ config.height);
+ glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER,
+ GL_DEPTH_ATTACHMENT,
+ GL_RENDERBUFFER, depth_rb);
+ }
+ }
+
+ bool success = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER)
+ == GL_FRAMEBUFFER_COMPLETE;
+
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
+
+ return success;
+}
+
+void
+Fbo::set_viewport()
+{
+ glViewport(0, 0, config.width, config.height);
+}
diff --git a/tests/util/piglit-fbo.h b/tests/util/piglit-fbo.h
new file mode 100644
index 0000000..87aebcf
--- /dev/null
+++ b/tests/util/piglit-fbo.h
@@ -0,0 +1,139 @@
+/* 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 piglit-fbo.h
+ * This file declares classes to initialize a framebuffer object as per piglit
+ * test's requirements.
+ */
+
+#include "piglit-util-gl-common.h"
+#include "math.h"
+
+/**
+ * Information needed to configure a framebuffer object for MSAA
+ * testing.
+ */
+class FboConfig
+{
+public:
+ FboConfig(int num_samples, int width, int height);
+
+ int num_samples;
+ int width;
+ int height;
+
+ /**
+ * True if a single renderbuffer should be used as the backing
+ * store for both the depth and stencil attachment points.
+ * Defaults to true.
+ */
+ bool combine_depth_stencil;
+
+ /**
+ * True if a texture should be used as the backing store for
+ * the color attachment point, false if a renderbuffer should
+ * be used. Defaults to false.
+ */
+ bool attach_texture;
+
+ /**
+ * Internalformat that should be used for the color buffer, or
+ * GL_NONE if no color buffer should be used. Defaults to
+ * GL_RGBA.
+ */
+ GLenum color_internalformat;
+
+ /**
+ * Internalformat that should be used for the depth buffer, or
+ * GL_NONE if no depth buffer should be used. Ignored if
+ * combine_depth_stencil is true. Defaults to
+ * GL_DEPTH_COMPONENT24.
+ */
+ GLenum depth_internalformat;
+
+ /**
+ * Internalformat that should be used for the stencil buffer,
+ * or GL_NONE if no stencil buffer should be used. Ignored if
+ * combine_depth_stencil is true. Defaults to
+ * GL_STENCIL_INDEX8.
+ */
+ GLenum stencil_internalformat;
+};
+
+/**
+ * Data structure representing one of the framebuffer objects used in
+ * the test.
+ *
+ * For the supersampled framebuffer object we use a texture as the
+ * backing store for the color buffer so that we can use a fragment
+ * shader to blend down to the reference image.
+ */
+class Fbo
+{
+public:
+ Fbo();
+
+ void set_samples(int num_samples);
+ void setup(const FboConfig &new_config);
+ bool try_setup(const FboConfig &new_config);
+
+ void set_viewport();
+
+ FboConfig config;
+ GLuint handle;
+
+ /**
+ * If config.attach_texture is true, the backing store for the
+ * color buffer.
+ */
+ GLuint color_tex;
+
+ /**
+ * If config.attach_texture is false, the backing store for
+ * the color buffer.
+ */
+ GLuint color_rb;
+
+ /**
+ * If config.combine_depth_stencil is true, the backing store
+ * for the depth/stencil buffer. If
+ * config.combine_depth_stencil is false, the backing store
+ * for the depth buffer.
+ */
+ GLuint depth_rb;
+
+ /**
+ * If config.combine_depth_stencil is false, the backing store
+ * for the stencil buffer.
+ */
+ GLuint stencil_rb;
+
+private:
+ void generate_gl_objects();
+
+ /**
+ * True if generate_gl_objects has been called and color_tex,
+ * color_rb, depth_rb, and stencil_rb have been initialized.
+ */
+ bool gl_objects_generated;
+};
diff --git a/tests/util/piglit-test-pattern.cpp b/tests/util/piglit-test-pattern.cpp
new file mode 100644
index 0000000..b7c8b61
--- /dev/null
+++ b/tests/util/piglit-test-pattern.cpp
@@ -0,0 +1,967 @@
+/*
+ * 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 piglit-test-pattern.cpp
+ *
+ * This file defines the functions which can be utilized to draw test patterns
+ * in to color, depth or stencil buffers.
+ *
+ */
+#include "piglit-test-pattern.h"
+
+const float TestPattern::no_projection[4][4] = {
+ { 1, 0, 0, 0 },
+ { 0, 1, 0, 0 },
+ { 0, 0, 1, 0 },
+ { 0, 0, 0, 1 }
+};
+
+
+void Triangles::compile()
+{
+ /* Triangle coords within (-1,-1) to (1,1) rect */
+ static const float pos_within_tri[][2] = {
+ { -0.5, -1.0 },
+ { 0.0, 1.0 },
+ { 0.5, -1.0 }
+ };
+
+ /* Number of triangle instances across (and down) */
+ int tris_across = 8;
+
+ /* Total number of triangles drawn */
+ num_tris = tris_across * tris_across;
+
+ /* Scaling factor uniformly applied to triangle coords */
+ float tri_scale = 0.8 / tris_across;
+
+ /* Amount each triangle should be rotated compared to prev */
+ float rotation_delta = M_PI * 2.0 / num_tris;
+
+ /* Final scaling factor */
+ float final_scale = 0.95;
+
+ static const char *vert =
+ "#version 120\n"
+ "attribute vec2 pos_within_tri;\n"
+ "uniform float tri_scale;\n"
+ "uniform float rotation_delta;\n"
+ "uniform int tris_across;\n"
+ "uniform float final_scale;\n"
+ "uniform mat4 proj;\n"
+ "uniform int tri_num; /* [0, num_tris) */\n"
+ "\n"
+ "void main()\n"
+ "{\n"
+ " vec2 pos = tri_scale * pos_within_tri;\n"
+ " float rotation = rotation_delta * tri_num;\n"
+ " pos = mat2(cos(rotation), sin(rotation),\n"
+ " -sin(rotation), cos(rotation)) * pos;\n"
+ " int i = int(mod(float(tri_num), float(tris_across)));\n"
+ " int j = tris_across - 1 - tri_num / tris_across;\n"
+ " pos += (vec2(i, j) * 2.0 + 1.0) / tris_across - 1.0;\n"
+ " pos *= final_scale;\n"
+ " gl_Position = proj * vec4(pos, 0.0, 1.0);\n"
+ "}\n";
+
+ static const char *frag =
+ "#version 120\n"
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = vec4(1.0);\n"
+ "}\n";
+
+ /* Compile program */
+ prog = glCreateProgram();
+ GLint vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vert);
+ glAttachShader(prog, vs);
+ GLint fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, frag);
+ glAttachShader(prog, fs);
+ glBindAttribLocation(prog, 0, "pos_within_tri");
+ glLinkProgram(prog);
+ if (!piglit_link_check_status(prog)) {
+ piglit_report_result(PIGLIT_FAIL);
+ }
+
+ /* Set up uniforms */
+ glUseProgram(prog);
+ glUniform1f(glGetUniformLocation(prog, "tri_scale"), tri_scale);
+ glUniform1f(glGetUniformLocation(prog, "rotation_delta"),
+ rotation_delta);
+ glUniform1i(glGetUniformLocation(prog, "tris_across"), tris_across);
+ glUniform1f(glGetUniformLocation(prog, "final_scale"), final_scale);
+ proj_loc = glGetUniformLocation(prog, "proj");
+ tri_num_loc = glGetUniformLocation(prog, "tri_num");
+
+ /* Set up vertex array object */
+ glGenVertexArrays(1, &vao);
+ glBindVertexArray(vao);
+
+ /* Set up vertex input buffer */
+ glGenBuffers(1, &vertex_buf);
+ glBindBuffer(GL_ARRAY_BUFFER, vertex_buf);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(pos_within_tri), pos_within_tri,
+ GL_STATIC_DRAW);
+ glEnableVertexAttribArray(0);
+ glVertexAttribPointer(0, ARRAY_SIZE(pos_within_tri[0]), GL_FLOAT,
+ GL_FALSE, sizeof(pos_within_tri[0]), (void *) 0);
+}
+
+void Triangles::draw(const float (*proj)[4])
+{
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glUseProgram(prog);
+ glUniformMatrix4fv(proj_loc, 1, GL_TRUE, &proj[0][0]);
+ glBindVertexArray(vao);
+ for (int tri_num = 0; tri_num < num_tris; ++tri_num) {
+ glUniform1i(tri_num_loc, tri_num);
+ glDrawArrays(GL_TRIANGLES, 0, 3);
+ }
+}
+
+
+InterpolationTestPattern::InterpolationTestPattern(const char *frag)
+ : frag(frag), viewport_size_loc(0)
+{
+}
+
+
+void
+InterpolationTestPattern::compile()
+{
+ static struct vertex_attributes {
+ float pos_within_tri[2];
+ float barycentric_coords[3];
+ } vertex_data[] = {
+ { { -0.5, -1.0 }, { 1, 0, 0 } },
+ { { 0.0, 1.0 }, { 0, 1, 0 } },
+ { { 0.5, -1.0 }, { 0, 0, 1 } }
+ };
+
+ /* Number of triangle instances across (and down) */
+ int tris_across = 8;
+
+ /* Total number of triangles drawn */
+ num_tris = tris_across * tris_across;
+
+ /* Scaling factor uniformly applied to triangle coords */
+ float tri_scale = 0.8 / tris_across;
+
+ /* Amount each triangle should be rotated compared to prev */
+ float rotation_delta = M_PI * 2.0 / num_tris;
+
+ /* Final scaling factor */
+ float final_scale = 0.95;
+
+ static const char *vert =
+ "#version 120\n"
+ "attribute vec2 pos_within_tri;\n"
+ "attribute vec3 in_barycentric_coords;\n"
+ "varying vec3 barycentric_coords;\n"
+ "centroid varying vec3 barycentric_coords_centroid;\n"
+ "varying vec2 pixel_pos;\n"
+ "centroid varying vec2 pixel_pos_centroid;\n"
+ "uniform float tri_scale;\n"
+ "uniform float rotation_delta;\n"
+ "uniform int tris_across;\n"
+ "uniform float final_scale;\n"
+ "uniform mat4 proj;\n"
+ "uniform int tri_num; /* [0, num_tris) */\n"
+ "uniform ivec2 viewport_size;\n"
+ "\n"
+ "void main()\n"
+ "{\n"
+ " vec2 pos = tri_scale * pos_within_tri;\n"
+ " float rotation = rotation_delta * tri_num;\n"
+ " pos = mat2(cos(rotation), sin(rotation),\n"
+ " -sin(rotation), cos(rotation)) * pos;\n"
+ " int i = int(mod(float(tri_num), float(tris_across)));\n"
+ " int j = tris_across - 1 - tri_num / tris_across;\n"
+ " pos += (vec2(i, j) * 2.0 + 1.0) / tris_across - 1.0;\n"
+ " pos *= final_scale;\n"
+ " gl_Position = proj * vec4(pos, 0.0, 1.0);\n"
+ " barycentric_coords = barycentric_coords_centroid =\n"
+ " in_barycentric_coords;\n"
+ " pixel_pos = pixel_pos_centroid =\n"
+ " vec2(viewport_size) * (pos + 1.0) / 2.0;\n"
+ "}\n";
+
+ /* Compile program */
+ prog = glCreateProgram();
+ GLint vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vert);
+ glAttachShader(prog, vs);
+ GLint fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, frag);
+ glAttachShader(prog, fs);
+ glBindAttribLocation(prog, 0, "pos_within_tri");
+ glBindAttribLocation(prog, 1, "in_barycentric_coords");
+ glLinkProgram(prog);
+ if (!piglit_link_check_status(prog)) {
+ piglit_report_result(PIGLIT_FAIL);
+ }
+
+ /* Set up uniforms */
+ glUseProgram(prog);
+ glUniform1f(glGetUniformLocation(prog, "tri_scale"), tri_scale);
+ glUniform1f(glGetUniformLocation(prog, "rotation_delta"),
+ rotation_delta);
+ glUniform1i(glGetUniformLocation(prog, "tris_across"), tris_across);
+ glUniform1f(glGetUniformLocation(prog, "final_scale"), final_scale);
+ proj_loc = glGetUniformLocation(prog, "proj");
+ tri_num_loc = glGetUniformLocation(prog, "tri_num");
+ viewport_size_loc = glGetUniformLocation(prog, "viewport_size");
+
+ /* Set up vertex array object */
+ glGenVertexArrays(1, &vao);
+ glBindVertexArray(vao);
+
+ /* Set up vertex input buffer */
+ glGenBuffers(1, &vertex_buf);
+ glBindBuffer(GL_ARRAY_BUFFER, vertex_buf);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data,
+ GL_STATIC_DRAW);
+ glEnableVertexAttribArray(0);
+ glVertexAttribPointer(0, ARRAY_SIZE(vertex_data[0].pos_within_tri),
+ GL_FLOAT, GL_FALSE, sizeof(vertex_data[0]),
+ (void *) offsetof(vertex_attributes,
+ pos_within_tri));
+ glEnableVertexAttribArray(1);
+ glVertexAttribPointer(1, ARRAY_SIZE(vertex_data[0].barycentric_coords),
+ GL_FLOAT, GL_FALSE, sizeof(vertex_data[0]),
+ (void *) offsetof(vertex_attributes,
+ barycentric_coords));
+}
+
+
+void
+InterpolationTestPattern::draw(const float (*proj)[4])
+{
+ glUseProgram(prog);
+
+ /* Depending what the fragment shader does, it's possible that
+ * viewport_size might get optimized away. Only set it if it
+ * didn't.
+ */
+ if (viewport_size_loc != -1) {
+ GLint viewport_dims[4];
+ glGetIntegerv(GL_VIEWPORT, viewport_dims);
+ glUniform2i(viewport_size_loc, viewport_dims[2], viewport_dims[3]);
+ }
+
+ Triangles::draw(proj);
+}
+
+
+void Lines::compile()
+{
+ /* Line coords within (-1,-1) to (1,1) rect */
+ static const float pos_line[][2] = {
+ { -0.8, -0.5 },
+ { 0.8, -0.5 }
+ };
+
+ /* Number of line instances across (and down) */
+ int lines_across = 4;
+
+ /* Total number of lines drawn */
+ num_lines = lines_across * lines_across;
+
+ /* Amount each line should be rotated compared to prev */
+ float rotation_delta = M_PI * 2.0 / num_lines;
+
+ /* Scaling factor uniformly applied to line coords */
+ float line_scale = 0.8 / lines_across;
+
+ /* Final scaling factor */
+ float final_scale = 0.95;
+
+ static const char *vert =
+ "#version 120\n"
+ "attribute vec2 pos_line;\n"
+ "uniform float line_scale;\n"
+ "uniform float rotation_delta;\n"
+ "uniform int lines_across;\n"
+ "uniform float final_scale;\n"
+ "uniform mat4 proj;\n"
+ "uniform int line_num;\n"
+ "\n"
+ "void main()\n"
+ "{\n"
+ " vec2 pos = line_scale * pos_line;\n"
+ " float rotation = rotation_delta * line_num;\n"
+ " pos = mat2(cos(rotation), sin(rotation),\n"
+ " -sin(rotation), cos(rotation)) * pos;\n"
+ " int i = int(mod(float(line_num), float(lines_across)));\n"
+ " int j = lines_across - 1 - line_num / lines_across;\n"
+ " pos += (vec2(i, j) * 2.0 + 1.0) / lines_across - 1.0;\n"
+ " pos *= final_scale;\n"
+ " gl_Position = proj * vec4(pos, 0.0, 1.0);\n"
+ "}\n";
+
+ static const char *frag =
+ "#version 120\n"
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = vec4(1.0);\n"
+ "}\n";
+
+ /* Compile program */
+ prog = glCreateProgram();
+ GLint vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vert);
+ glAttachShader(prog, vs);
+ GLint fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, frag);
+ glAttachShader(prog, fs);
+ glBindAttribLocation(prog, 0, "pos_line");
+ glLinkProgram(prog);
+ if (!piglit_link_check_status(prog)) {
+ piglit_report_result(PIGLIT_FAIL);
+ }
+
+ /* Set up uniforms */
+ glUseProgram(prog);
+ glUniform1f(glGetUniformLocation(prog, "line_scale"), line_scale);
+ glUniform1f(glGetUniformLocation(prog, "rotation_delta"),
+ rotation_delta);
+ glUniform1i(glGetUniformLocation(prog, "lines_across"), lines_across);
+ glUniform1f(glGetUniformLocation(prog, "final_scale"), final_scale);
+ proj_loc = glGetUniformLocation(prog, "proj");
+ line_num_loc = glGetUniformLocation(prog, "line_num");
+
+ /* Set up vertex array object */
+ glGenVertexArrays(1, &vao);
+ glBindVertexArray(vao);
+
+ /* Set up vertex input buffer */
+ glGenBuffers(1, &vertex_buf);
+ glBindBuffer(GL_ARRAY_BUFFER, vertex_buf);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(pos_line), pos_line,
+ GL_STATIC_DRAW);
+ glEnableVertexAttribArray(0);
+ glVertexAttribPointer(0, ARRAY_SIZE(pos_line[0]), GL_FLOAT,
+ GL_FALSE, sizeof(pos_line[0]), (void *) 0);
+}
+
+void Lines::draw(const float (*proj)[4])
+{
+ glClear(GL_COLOR_BUFFER_BIT);
+ glUseProgram(prog);
+ glUniformMatrix4fv(proj_loc, 1, GL_TRUE, &proj[0][0]);
+ glBindVertexArray(vao);
+ for (int line_num = 0; line_num < num_lines; ++line_num) {
+ /* Draws with line width = 0.25, 0.75, 1.25,
+ * 1.75, 2.25, 2.75, 3.25, 3.75
+ */
+ glLineWidth((1 + 2 * line_num) / 4.0);
+ glUniform1i(line_num_loc, line_num);
+ glDrawArrays(GL_LINES, 0, 2);
+ }
+}
+
+void Points::compile()
+{
+ /* Point coords within (-1,-1) to (1,1) rect */
+ static const float pos_point[2] = { -0.5, -0.5 };
+
+ /* Number of point instances across (and down) */
+ int points_across = 4;
+
+ /* Total number of points drawn */
+ num_points = points_across * points_across;
+
+ /* Scaling factor uniformly applied to point coords */
+ float point_scale = 0.8 / points_across;
+
+ /* Final scaling factor */
+ float final_scale = 0.95;
+
+ static const char *vert =
+ "#version 120\n"
+ "attribute vec2 pos_point;\n"
+ "uniform float point_scale;\n"
+ "uniform int points_across;\n"
+ "uniform float final_scale;\n"
+ "uniform mat4 proj;\n"
+ "uniform int point_num;\n"
+ "uniform float depth;\n"
+ "\n"
+ "void main()\n"
+ "{\n"
+ " vec2 pos = point_scale * pos_point;\n"
+ " int i = int(mod(float(point_num), float(points_across)));\n"
+ " int j = points_across - 1 - point_num / points_across;\n"
+ " pos += (vec2(i, j) * 2.0 + 1.0) / points_across - 1.0;\n"
+ " pos *= final_scale;\n"
+ " gl_Position = proj * vec4(pos, depth, 1.0);\n"
+ "}\n";
+
+ static const char *frag =
+ "#version 120\n"
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = vec4(1.0);\n"
+ "}\n";
+
+ /* Compile program */
+ prog = glCreateProgram();
+ GLint vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vert);
+ glAttachShader(prog, vs);
+ GLint fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, frag);
+ glAttachShader(prog, fs);
+ glBindAttribLocation(prog, 0, "pos_point");
+ glLinkProgram(prog);
+ if (!piglit_link_check_status(prog)) {
+ piglit_report_result(PIGLIT_FAIL);
+ }
+
+ /* Set up uniforms */
+ glUseProgram(prog);
+ glUniform1f(glGetUniformLocation(prog, "point_scale"), point_scale);
+ glUniform1i(glGetUniformLocation(prog, "points_across"), points_across);
+ glUniform1f(glGetUniformLocation(prog, "final_scale"), final_scale);
+ proj_loc = glGetUniformLocation(prog, "proj");
+ point_num_loc = glGetUniformLocation(prog, "point_num");
+ depth_loc = glGetUniformLocation(prog, "depth");
+
+ /* Set up vertex array object */
+ glGenVertexArrays(1, &vao);
+ glBindVertexArray(vao);
+
+ /* Set up vertex input buffer */
+ glGenBuffers(1, &vertex_buf);
+ glBindBuffer(GL_ARRAY_BUFFER, vertex_buf);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(pos_point), pos_point,
+ GL_STATIC_DRAW);
+ glEnableVertexAttribArray(0);
+ glVertexAttribPointer(0, ARRAY_SIZE(pos_point), GL_FLOAT,
+ GL_FALSE, 0, (void *) 0);
+}
+
+void Points::draw(const float (*proj)[4])
+{
+ glClear(GL_COLOR_BUFFER_BIT);
+ glUseProgram(prog);
+ glUniformMatrix4fv(proj_loc, 1, GL_TRUE, &proj[0][0]);
+ glBindVertexArray(vao);
+ glUniform1f(depth_loc, 0.0);
+ for (int point_num = 0; point_num < num_points; ++point_num) {
+ glPointSize((1.0 + 4 * point_num) / 4.0);
+ glUniform1i(point_num_loc, point_num);
+ glDrawArrays(GL_POINTS, 0, 1);
+ }
+}
+
+Sunburst::Sunburst()
+ : out_type(GL_UNSIGNED_NORMALIZED),
+ compute_depth(false),
+ prog(0),
+ rotation_loc(0),
+ vert_depth_loc(0),
+ frag_depth_loc(0),
+ proj_loc(0),
+ draw_colors_loc(0),
+ vao(0),
+ num_tris(0),
+ vertex_buf(0)
+{
+}
+
+
+/**
+ * Determine the GLSL type that should be used for rendering, based on
+ * out_type.
+ */
+const char *
+Sunburst::get_out_type_glsl() const
+{
+ switch(out_type) {
+ case GL_INT:
+ return "ivec4";
+ case GL_UNSIGNED_INT:
+ return "uvec4";
+ case GL_UNSIGNED_NORMALIZED:
+ case GL_FLOAT:
+ return "vec4";
+ default:
+ printf("Unrecognized out_type: %s\n",
+ piglit_get_gl_enum_name(out_type));
+ piglit_report_result(PIGLIT_FAIL);
+ return "UNKNOWN";
+ }
+}
+
+
+void Sunburst::compile()
+{
+ static struct vertex_attributes {
+ float pos_within_tri[2];
+ float barycentric_coords[3];
+ } vertex_data[] = {
+ { { -0.3, -0.8 }, { 1, 0, 0 } },
+ { { 0.0, 1.0 }, { 0, 1, 0 } },
+ { { 0.3, -0.8 }, { 0, 0, 1 } }
+ };
+ bool need_glsl130 = out_type == GL_INT || out_type == GL_UNSIGNED_INT;
+
+ if (need_glsl130) {
+ piglit_require_gl_version(30);
+ }
+
+ /* Total number of triangles drawn */
+ num_tris = 7;
+
+ static const char *vert_template =
+ "#version %s\n"
+ "attribute vec2 pos_within_tri;\n"
+ "attribute vec3 in_barycentric_coords;\n"
+ "varying vec3 barycentric_coords;\n"
+ "uniform float rotation;\n"
+ "uniform float vert_depth;\n"
+ "uniform mat4 proj;\n"
+ "\n"
+ "void main()\n"
+ "{\n"
+ " vec2 pos = pos_within_tri;\n"
+ " pos = mat2(cos(rotation), sin(rotation),\n"
+ " -sin(rotation), cos(rotation)) * pos;\n"
+ " gl_Position = proj * vec4(pos, vert_depth, 1.0);\n"
+ " barycentric_coords = in_barycentric_coords;\n"
+ "}\n";
+
+ static const char *frag_template =
+ "#version %s\n"
+ "#define OUT_TYPE %s\n"
+ "#define COMPUTE_DEPTH %s\n"
+ "uniform float frag_depth;\n"
+ "varying vec3 barycentric_coords;\n"
+ "uniform mat3x4 draw_colors;\n"
+ "#if __VERSION__ == 130\n"
+ " out OUT_TYPE frag_out;\n"
+ "#endif\n"
+ "\n"
+ "void main()\n"
+ "{\n"
+ "#if __VERSION__ == 130\n"
+ " frag_out = OUT_TYPE(draw_colors * barycentric_coords);\n"
+ "#else\n"
+ " gl_FragColor = draw_colors * barycentric_coords;\n"
+ "#endif\n"
+ "#if COMPUTE_DEPTH\n"
+ " gl_FragDepth = (frag_depth + 1.0) / 2.0;\n"
+ "#endif\n"
+ "}\n";
+
+ /* Compile program */
+ prog = glCreateProgram();
+ unsigned vert_alloc_len =
+ strlen(vert_template) + 4;
+ char *vert = (char *) malloc(vert_alloc_len);
+ sprintf(vert, vert_template, need_glsl130 ? "130" : "120");
+ GLint vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vert);
+ free(vert);
+ glAttachShader(prog, vs);
+
+ const char *out_type_glsl = get_out_type_glsl();
+ unsigned frag_alloc_len =
+ strlen(frag_template) + strlen(out_type_glsl) + 4;
+ char *frag = (char *) malloc(frag_alloc_len);
+ sprintf(frag, frag_template, need_glsl130 ? "130" : "120",
+ out_type_glsl,
+ compute_depth ? "1" : "0");
+ GLint fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, frag);
+ free(frag);
+ glAttachShader(prog, fs);
+
+ glBindAttribLocation(prog, 0, "pos_within_tri");
+ glBindAttribLocation(prog, 1, "in_barycentric_coords");
+ if (need_glsl130) {
+ glBindFragDataLocation(prog, 0, "frag_out");
+ }
+ glLinkProgram(prog);
+ if (!piglit_link_check_status(prog)) {
+ piglit_report_result(PIGLIT_FAIL);
+ }
+
+ /* Set up uniforms */
+ glUseProgram(prog);
+ rotation_loc = glGetUniformLocation(prog, "rotation");
+ vert_depth_loc = glGetUniformLocation(prog, "vert_depth");
+ frag_depth_loc = glGetUniformLocation(prog, "frag_depth");
+ glUniform1f(vert_depth_loc, 0.0);
+ glUniform1f(frag_depth_loc, 0.0);
+ proj_loc = glGetUniformLocation(prog, "proj");
+ draw_colors_loc = glGetUniformLocation(prog, "draw_colors");
+
+ /* Set up vertex array object */
+ glGenVertexArrays(1, &vao);
+ glBindVertexArray(vao);
+
+ /* Set up vertex input buffer */
+ glGenBuffers(1, &vertex_buf);
+ glBindBuffer(GL_ARRAY_BUFFER, vertex_buf);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data,
+ GL_STATIC_DRAW);
+ glEnableVertexAttribArray(0);
+ glVertexAttribPointer(0, ARRAY_SIZE(vertex_data[0].pos_within_tri),
+ GL_FLOAT, GL_FALSE, sizeof(vertex_data[0]),
+ (void *) 0);
+ glEnableVertexAttribArray(1);
+ glVertexAttribPointer(1, ARRAY_SIZE(vertex_data[0].barycentric_coords),
+ GL_FLOAT, GL_FALSE, sizeof(vertex_data[0]),
+ (void *) offsetof(vertex_attributes,
+ barycentric_coords));
+}
+
+
+ColorGradientSunburst::ColorGradientSunburst(GLenum out_type)
+{
+ this->out_type = out_type;
+}
+
+
+/**
+ * Draw the color gradient sunburst, but instead of using color
+ * components that range from 0.0 to 1.0, apply the given scaling
+ * factor and offset to each color component.
+ *
+ * The offset is also applied when clearing the color buffer.
+ */
+void
+ColorGradientSunburst::draw_with_scale_and_offset(const float (*proj)[4],
+ float scale, float offset)
+{
+ switch (out_type) {
+ case GL_INT: {
+ int clear_color[4] = { offset, offset, offset, offset };
+ glClearBufferiv(GL_COLOR, 0, clear_color);
+ break;
+ }
+ case GL_UNSIGNED_INT: {
+ unsigned clear_color[4] = { offset, offset, offset, offset };
+ glClearBufferuiv(GL_COLOR, 0, clear_color);
+ break;
+ }
+ case GL_UNSIGNED_NORMALIZED:
+ case GL_FLOAT: {
+ glClearColor(offset, offset, offset, offset);
+ glClear(GL_COLOR_BUFFER_BIT);
+ break;
+ }
+ default:
+ printf("Unrecognized out_type: %s\n",
+ piglit_get_gl_enum_name(out_type));
+ piglit_report_result(PIGLIT_FAIL);
+ break;
+ }
+
+ glUseProgram(prog);
+ glUniformMatrix4fv(proj_loc, 1, GL_TRUE, &proj[0][0]);
+ float draw_colors[3][4] =
+ { { 1, 0, 0, 1.0 }, { 0, 1, 0, 0.5 }, { 0, 0, 1, 1.0 } };
+ for (int i = 0; i < 3; ++i) {
+ for (int j = 0; j < 4; ++j) {
+ draw_colors[i][j] = scale * draw_colors[i][j] + offset;
+ }
+ }
+ glUniformMatrix3x4fv(draw_colors_loc, 1, GL_FALSE,
+ &draw_colors[0][0]);
+ glBindVertexArray(vao);
+ for (int i = 0; i < num_tris; ++i) {
+ glUniform1f(rotation_loc, M_PI * 2.0 * i / num_tris);
+ glDrawArrays(GL_TRIANGLES, 0, 3);
+ }
+}
+
+
+void
+ColorGradientSunburst::draw(const float (*proj)[4])
+{
+ draw_with_scale_and_offset(proj, 1.0, 0.0);
+}
+
+
+void
+StencilSunburst::draw(const float (*proj)[4])
+{
+ glEnable(GL_STENCIL_TEST);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+ glUseProgram(prog);
+ glUniformMatrix4fv(proj_loc, 1, GL_TRUE, &proj[0][0]);
+ glBindVertexArray(vao);
+ for (int i = 0; i < num_tris; ++i) {
+ glStencilFunc(GL_ALWAYS, i+1, 0xff);
+ glUniform1f(rotation_loc, M_PI * 2.0 * i / num_tris);
+ glDrawArrays(GL_TRIANGLES, 0, 3);
+ }
+
+ glDisable(GL_STENCIL_TEST);
+}
+
+
+DepthSunburst::DepthSunburst(bool compute_depth)
+{
+ this->compute_depth = compute_depth;
+}
+
+
+void
+DepthSunburst::draw(const float (*proj)[4])
+{
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LESS);
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glUseProgram(prog);
+ glUniformMatrix4fv(proj_loc, 1, GL_TRUE, &proj[0][0]);
+ glBindVertexArray(vao);
+ for (int i = 0; i < num_tris; ++i) {
+ /* Draw triangles in a haphazard order so we can
+ * verify that depth comparisons sort them out
+ * properly.
+ */
+ int triangle_to_draw = (i * 3) % num_tris;
+
+ /* Note: with num_tris == 7, this causes us to draw
+ * triangles at depths of 3/4, 1/2, -1/4, 0, 1/4, 1/2,
+ * and 3/4.
+ */
+ glUniform1f(compute_depth ? frag_depth_loc : vert_depth_loc,
+ float(num_tris - triangle_to_draw * 2 - 1)
+ / (num_tris + 1));
+
+ glUniform1f(rotation_loc,
+ M_PI * 2.0 * triangle_to_draw / num_tris);
+ glDrawArrays(GL_TRIANGLES, 0, 3);
+ }
+
+ glDisable(GL_DEPTH_TEST);
+}
+
+
+void
+ManifestStencil::compile()
+{
+ static const char *vert =
+ "#version 120\n"
+ "attribute vec2 pos;\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = vec4(pos, 0.0, 1.0);\n"
+ "}\n";
+
+ static const char *frag =
+ "#version 120\n"
+ "uniform vec4 color;\n"
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = color;\n"
+ "}\n";
+
+ /* Compile program */
+ prog = glCreateProgram();
+ GLint vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vert);
+ glAttachShader(prog, vs);
+ GLint fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, frag);
+ glAttachShader(prog, fs);
+ glBindAttribLocation(prog, 0, "pos");
+ glLinkProgram(prog);
+ if (!piglit_link_check_status(prog)) {
+ piglit_report_result(PIGLIT_FAIL);
+ }
+
+ /* Set up uniforms */
+ glUseProgram(prog);
+ color_loc = glGetUniformLocation(prog, "color");
+
+ /* Set up vertex array object */
+ glGenVertexArrays(1, &vao);
+ glBindVertexArray(vao);
+
+ /* Set up vertex input buffer */
+ float vertex_data[4][2] = {
+ { -1, -1 },
+ { -1, 1 },
+ { 1, 1 },
+ { 1, -1 }
+ };
+ glGenVertexArrays(1, &vertex_buf);
+ glBindBuffer(GL_ARRAY_BUFFER, vertex_buf);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data,
+ GL_STATIC_DRAW);
+ glEnableVertexAttribArray(0);
+ glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_data[0]),
+ (void *) 0);
+
+ /* Set up element input buffer to tesselate a quad into
+ * triangles
+ */
+ unsigned int indices[6] = { 0, 1, 2, 0, 2, 3 };
+ GLuint element_buf;
+ glGenBuffers(1, &element_buf);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, element_buf);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices,
+ GL_STATIC_DRAW);
+}
+
+void
+ManifestStencil::run()
+{
+ static float colors[8][4] = {
+ { 0.0, 0.0, 0.0, 1.0 },
+ { 0.0, 0.0, 1.0, 1.0 },
+ { 0.0, 1.0, 0.0, 1.0 },
+ { 0.0, 1.0, 1.0, 1.0 },
+ { 1.0, 0.0, 0.0, 1.0 },
+ { 1.0, 0.0, 1.0, 1.0 },
+ { 1.0, 1.0, 0.0, 1.0 },
+ { 1.0, 1.0, 1.0, 1.0 }
+ };
+
+ glUseProgram(prog);
+ glBindVertexArray(vao);
+
+ glEnable(GL_STENCIL_TEST);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+
+ /* Clear the color buffer to 0, in case the stencil buffer
+ * contains any values outside the range 0..7
+ */
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ for (int i = 0; i < 8; ++i) {
+ glStencilFunc(GL_EQUAL, i, 0xff);
+ glUniform4fv(color_loc, 1, colors[i]);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void *) 0);
+ }
+
+ glDisable(GL_STENCIL_TEST);
+}
+
+void
+ManifestDepth::compile()
+{
+ static const char *vert =
+ "#version 120\n"
+ "attribute vec2 pos;\n"
+ "uniform float depth;\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = vec4(pos, depth, 1.0);\n"
+ "}\n";
+
+ static const char *frag =
+ "#version 120\n"
+ "uniform vec4 color;\n"
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = color;\n"
+ "}\n";
+
+ /* Compile program */
+ prog = glCreateProgram();
+ GLint vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vert);
+ glAttachShader(prog, vs);
+ GLint fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, frag);
+ glAttachShader(prog, fs);
+ glBindAttribLocation(prog, 0, "pos");
+ glLinkProgram(prog);
+ if (!piglit_link_check_status(prog)) {
+ piglit_report_result(PIGLIT_FAIL);
+ }
+
+ /* Set up uniforms */
+ glUseProgram(prog);
+ color_loc = glGetUniformLocation(prog, "color");
+ depth_loc = glGetUniformLocation(prog, "depth");
+
+ /* Set up vertex array object */
+ glGenVertexArrays(1, &vao);
+ glBindVertexArray(vao);
+
+ /* Set up vertex input buffer */
+ float vertex_data[4][2] = {
+ { -1, -1 },
+ { -1, 1 },
+ { 1, 1 },
+ { 1, -1 }
+ };
+ glGenVertexArrays(1, &vertex_buf);
+ glBindBuffer(GL_ARRAY_BUFFER, vertex_buf);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data,
+ GL_STATIC_DRAW);
+ glEnableVertexAttribArray(0);
+ glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_data[0]),
+ (void *) 0);
+
+ /* Set up element input buffer to tesselate a quad into
+ * triangles
+ */
+ unsigned int indices[6] = { 0, 1, 2, 0, 2, 3 };
+ GLuint element_buf;
+ glGenBuffers(1, &element_buf);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, element_buf);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices,
+ GL_STATIC_DRAW);
+}
+
+void
+ManifestDepth::run()
+{
+ static float colors[8][4] = {
+ { 0.0, 0.0, 0.0, 1.0 },
+ { 0.0, 0.0, 1.0, 1.0 },
+ { 0.0, 1.0, 0.0, 1.0 },
+ { 0.0, 1.0, 1.0, 1.0 },
+ { 1.0, 0.0, 0.0, 1.0 },
+ { 1.0, 0.0, 1.0, 1.0 },
+ { 1.0, 1.0, 0.0, 1.0 },
+ { 1.0, 1.0, 1.0, 1.0 }
+ };
+
+ glUseProgram(prog);
+ glBindVertexArray(vao);
+
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LESS);
+ glEnable(GL_STENCIL_TEST);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
+ glStencilFunc(GL_EQUAL, 0, 0xff);
+
+ /* Clear the stencil buffer to 0, leaving depth and color
+ * buffers unchanged.
+ */
+ glClear(GL_STENCIL_BUFFER_BIT);
+
+ for (int i = 0; i < 8; ++i) {
+ glUniform4fv(color_loc, 1, colors[i]);
+ glUniform1f(depth_loc, float(7 - 2*i)/8);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void *) 0);
+ }
+
+ glDisable(GL_STENCIL_TEST);
+ glDisable(GL_DEPTH_TEST);
+}
diff --git a/tests/util/piglit-test-pattern.h b/tests/util/piglit-test-pattern.h
new file mode 100644
index 0000000..026c5a1
--- /dev/null
+++ b/tests/util/piglit-test-pattern.h
@@ -0,0 +1,322 @@
+/* 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 piglit-util-test-pattern.h
+ * This file declares classes and functions which can be utilized to draw
+ * test patterns in to color, depth or stencil buffers.
+ */
+
+#include "piglit-util-gl-common.h"
+#include "math.h"
+
+/**
+ * There are two programs used to "manifest" an auxiliary buffer,
+ * turning it into visible colors: one for manifesting the stencil
+ * buffer, and one for manifesting the depth buffer. This is the base
+ * class that they both derive from.
+ */
+class ManifestProgram
+{
+public:
+ virtual void compile() = 0;
+ virtual void run() = 0;
+};
+
+/**
+ * Program we use to manifest the stencil buffer.
+ *
+ * This program operates by repeatedly drawing over the entire buffer
+ * using the stencil function "EQUAL", and a different color each
+ * time. This causes stencil values from 0 to 7 to manifest as colors
+ * (black, blue, green, cyan, red, magenta, yellow, white).
+ */
+class ManifestStencil : public ManifestProgram
+{
+public:
+ virtual void compile();
+ virtual void run();
+
+private:
+ GLint prog;
+ GLint color_loc;
+ GLuint vertex_buf;
+ GLuint vao;
+};
+
+/**
+ * Program we use to manifest the depth buffer.
+ *
+ * This program operates by repeatedly drawing over the entire buffer
+ * at decreasing depth values with depth test enabled; the stencil
+ * function is configured to "EQUAL" with a stencil op of "INCR", so
+ * that after a sample passes the depth test, its stencil value will
+ * be incremented and it will fail the stencil test on later draws.
+ * As a result, depth values from back to front will manifest as
+ * colors (black, blue, green, cyan, red, magenta, yellow, white).
+ */
+class ManifestDepth : public ManifestProgram
+{
+public:
+ virtual void compile();
+ virtual void run();
+
+private:
+ GLint prog;
+ GLint color_loc;
+ GLint depth_loc;
+ GLuint vertex_buf;
+ GLuint vao;
+};
+
+/**
+ * There are three programs used to draw a test pattern, depending on
+ * whether we are testing the color buffer, the depth buffer, or the
+ * stencil buffer. This is the base class that they all derive from.
+ */
+class TestPattern
+{
+public:
+ virtual void compile() = 0;
+
+ /**
+ * Draw the test pattern, applying the given projection matrix
+ * to vertex coordinates. The projection matrix is in
+ * row-major order.
+ *
+ * If no projection transformation is needed, pass
+ * TestPattern::no_projection for \c proj.
+ */
+ virtual void draw(const float (*proj)[4]) = 0;
+
+ static const float no_projection[4][4];
+};
+
+/**
+ * Program we use to draw a test pattern into the color buffer.
+ *
+ * This program draws a grid of small disjoint triangles, each rotated
+ * at a different angle. This ensures that the image will have a
+ * large number of edges at different angles, so that we'll thoroughly
+ * exercise antialiasing.
+ */
+class Triangles : public TestPattern
+{
+public:
+ virtual void compile();
+ virtual void draw(const float (*proj)[4]);
+
+protected:
+ GLint prog;
+ GLuint vertex_buf;
+ GLuint vao;
+ GLint proj_loc;
+ GLint tri_num_loc;
+ int num_tris;
+};
+
+
+/**
+ * Program we use to test that interpolation works properly.
+ *
+ * This program draws the same sequence of small triangles as the
+ * Triangles program, but it's capable of coloring the triangles in
+ * various ways based on the fragment program provided to the
+ * constructor.
+ *
+ * The fragment program has access to the following variables:
+ *
+ * - in vec3 barycentric_coords: barycentric coordinates of the
+ * triangle being drawn, normally interpolated.
+ *
+ * - centroid in vec3 barycentric_coords_centroid: same as
+ * barycentric_coords, but centroid interpolated.
+ *
+ * - in vec2 pixel_pos: pixel coordinate ((0,0) to (viewport_width,
+ * viewport_height)), normally interpolated.
+ *
+ * - centroid in vec2 pixel_pos_centroid: same as pixel_pos, but
+ * centroid interpolated.
+ */
+class InterpolationTestPattern : public Triangles
+{
+public:
+ explicit InterpolationTestPattern(const char *frag);
+ virtual void compile();
+ virtual void draw(const float (*proj)[4]);
+
+private:
+ const char *frag;
+ GLint viewport_size_loc;
+};
+
+
+/**
+ * Program we use to draw a test pattern into the color buffer.
+ *
+ * This program draws a sequence of points with varied sizes. This ensures
+ * antialiasing works well with all point sizes.
+ */
+class Points : public TestPattern
+{
+public:
+ virtual void compile();
+ virtual void draw(const float (*proj)[4]);
+
+private:
+ GLint prog;
+ GLuint vao;
+ GLint proj_loc;
+ GLint depth_loc;
+ GLint point_num_loc;
+ GLuint vertex_buf;
+ int num_points;
+};
+
+/**
+ * Program we use to draw a test pattern into the color buffer.
+ *
+ * This program draws a sequence of lines with varied width. This ensures
+ * antialiasing works well with all line widths.
+ */
+class Lines : public TestPattern
+{
+public:
+ virtual void compile();
+ virtual void draw(const float (*proj)[4]);
+
+private:
+ GLint prog;
+ GLuint vao;
+ GLint proj_loc;
+ GLint line_num_loc;
+ GLuint vertex_buf;
+ int num_lines;
+};
+
+/**
+ * Program we use to draw a test pattern into the depth and stencil
+ * buffers.
+ *
+ * This program draws a "sunburst" pattern consisting of 7 overlapping
+ * triangles, each at a different angle. This ensures that the
+ * triangles overlap in a complex way, with the edges between them
+ * covering a a large number of different angles, so that we'll
+ * thoroughly exercise antialiasing.
+ *
+ * This program is further specialized into depth and stencil variants.
+ */
+class Sunburst : public TestPattern
+{
+public:
+ Sunburst();
+
+ virtual void compile();
+
+ /**
+ * Type of color buffer being rendered into. Should be one of
+ * the following enum values: GL_FLOAT,
+ * GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_INT, or GL_INT.
+ *
+ * Defaults to GL_UNSIGNED_NORMALIZED.
+ */
+ GLenum out_type;
+
+ /**
+ * Whether or not the fragment shader should output a depth
+ * value.
+ *
+ * Defaults to false.
+ */
+ bool compute_depth;
+
+protected:
+ GLint prog;
+ GLint rotation_loc;
+ GLint vert_depth_loc;
+ GLint frag_depth_loc;
+ GLint proj_loc;
+ GLint draw_colors_loc;
+ GLuint vao;
+ int num_tris;
+
+private:
+ const char *get_out_type_glsl() const;
+
+ GLuint vertex_buf;
+};
+
+/**
+ * Program that draws a test pattern into the color buffer.
+ *
+ * This program draws triangles using a variety of colors and
+ * gradients.
+ *
+ * This program is capable of drawing to floating point, integer, and
+ * unsigned integer framebuffers, controlled by the out_type
+ * constructor parameter, which should be GL_FLOAT,
+ * GL_UNSIGNED_NORMALIZED, GL_UNSIGNED_INT, or GL_INT.
+ */
+class ColorGradientSunburst : public Sunburst
+{
+public:
+ explicit ColorGradientSunburst(GLenum out_type);
+
+ virtual void draw(const float (*proj)[4]);
+
+ void draw_with_scale_and_offset(const float (*proj)[4],
+ float scale, float offset);
+};
+
+/**
+ * Program we use to draw a test pattern into the stencil buffer.
+ *
+ * The triangles in this sunburst are drawn back-to-front, using no
+ * depth testing. Each triangle is drawn using a different stencil
+ * value.
+ */
+class StencilSunburst : public Sunburst
+{
+public:
+ virtual void draw(const float (*proj)[4]);
+};
+
+/**
+ * Program we use to draw a test pattern into the depth buffer.
+ *
+ * The triangles in this sunburst are drawn at a series of different
+ * depth values, with depth testing enabled. They are drawn in an
+ * arbitrary non-consecutive order, to verify that depth testing
+ * properly sorts the surfaces into front-to-back order.
+ *
+ * If the constructor parameter compute_depth is true, the depth value
+ * is determined using a fragment shader output. If it is false, it
+ * is determined by the z value of the vertex shader gl_Position
+ * output.
+ */
+class DepthSunburst : public Sunburst
+{
+public:
+ explicit DepthSunburst(bool compute_depth = false);
+
+ virtual void draw(const float (*proj)[4]);
+};
--
1.8.1.4
More information about the Piglit
mailing list