/* 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.h" #include "math.h" namespace piglit_util_test_pattern { /** * 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 ~ManifestProgram() {}; 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 ~TestPattern() {}; 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]); }; }