[Piglit] [PATCH 1/2] Ported polygon offset test from Glean to Piglit.
Brian Paul
brianp at vmware.com
Mon Oct 20 16:40:44 PDT 2014
On 10/20/2014 05:30 PM, Laura Ekstrand wrote:
> ---
> tests/all.py | 1 +
> tests/spec/gl-1.4/CMakeLists.gl.txt | 1 +
> tests/spec/gl-1.4/polygon-offset.c | 672 ++++++++++++++++++++++++++++++++++++
> 3 files changed, 674 insertions(+)
> create mode 100644 tests/spec/gl-1.4/polygon-offset.c
>
> diff --git a/tests/all.py b/tests/all.py
> index eb317de..617700d 100644
> --- a/tests/all.py
> +++ b/tests/all.py
> @@ -826,6 +826,7 @@ add_plain_test(gl14, 'tex1d-2dborder')
> add_plain_test(gl14, 'blendminmax')
> add_plain_test(gl14, 'blendsquare')
> add_concurrent_test(gl14, "gl-1.4-dlist-multidrawarrays")
> +add_concurrent_test(gl14, "gl-1.4-polygon-offset")
> add_msaa_visual_plain_tests(gl14, 'copy-pixels')
> add_plain_test(gl14, 'draw-batch')
> add_plain_test(gl14, 'stencil-wrap')
> diff --git a/tests/spec/gl-1.4/CMakeLists.gl.txt b/tests/spec/gl-1.4/CMakeLists.gl.txt
> index 1b1a16f..601c1e1 100644
> --- a/tests/spec/gl-1.4/CMakeLists.gl.txt
> +++ b/tests/spec/gl-1.4/CMakeLists.gl.txt
> @@ -10,5 +10,6 @@ link_libraries (
> )
>
> piglit_add_executable (gl-1.4-dlist-multidrawarrays dlist-multidrawarrays.c)
> +piglit_add_executable (gl-1.4-polygon-offset polygon-offset.c)
>
> # vim: ft=cmake:
> diff --git a/tests/spec/gl-1.4/polygon-offset.c b/tests/spec/gl-1.4/polygon-offset.c
> new file mode 100644
> index 0000000..1eecd4f
> --- /dev/null
> +++ b/tests/spec/gl-1.4/polygon-offset.c
> @@ -0,0 +1,672 @@
> +/*
> + * BEGIN_COPYRIGHT -*- glean -*-
> + *
> + * Copyright (C) 2001 Allen Akin All Rights Reserved.
> + * Copyright (C) 2014 Intel Corporation All Rights Reserved.
> + *
> + * 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 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.
> + *
> + * END_COPYRIGHT
> + */
> +
> +/** @file polygon-offset.c
> + *
> + * Implementation of polygon offset tests.
> + *
> + * This test verifies glPolygonOffset. It is run on every
> + * OpenGL-capable drawing surface configuration that supports
> + * creation of a window, has a depth buffer, and is RGB.
> + *
> + * The first subtest verifies that the OpenGL implementation is
> + * using a plausible value for the \"minimum resolvable
> + * difference\" (MRD). This is the offset in window coordinates
> + * that is sufficient to provide separation in depth (Z) for any
> + * two parallel surfaces. The subtest searches for the MRD by
> + * drawing two surfaces at a distance from each other and
> + * checking the resulting image to see if they were cleanly
> + * separated. The distance is then modified (using a binary
> + * search) until a minimum value is found. This is the so-called
> + * \"ideal\" MRD. Then two surfaces are drawn using
> + * glPolygonOffset to produce a separation that should equal one
> + * MRD. The depth values at corresponding points on each surface
> + * are subtracted to form the \"actual\" MRD. The subtest performs
> + * these checks twice, once close to the viewpoint and once far
> + * away from it, and passes if the largest of the ideal MRDs and
> + * the largest of the actual MRDs are nearly the same.
> + *
> + * The second subtest verifies that the OpenGL implementation is
> + * producing plausible values for slope-dependent offsets. The
> + * OpenGL spec requires that the depth slope of a surface be
> + * computed by an approximation that is at least as large as
> + * max(abs(dz/dx),abs(dz/dy)) and no larger than
> + * sqrt((dz/dx)**2+(dz/dy)**2). The subtest draws a quad rotated
> + * by various angles along various axes, samples three points on
> + * the quad's surface, and computes dz/dx and dz/dy. Then it
> + * draws two additional quads offset by one and two times the
> + * depth slope, respectively. The base quad and the two new
> + * quads are sampled and their actual depths read from the depth
> + * buffer. The subtest passes if the quads are offset by amounts
> + * that are within one and two times the allowable range,
> + * respectively.
> + *
> + * Derived in part from tests written by Angus Dorbie <dorbie at sgi.com>
> + * in September 2000 and Rickard E. (Rik) Faith <faith at valinux.com> in
> + * October 2000.
> + *
> + * Ported to Piglit by Laura Ekstrand.
> + */
> +
> +#include "piglit-util-gl.h"
> +#include <GL/glu.h>
> +
> +#include <math.h>
> +
> +#define PGOS_WIN_SIZE 128
> +
> +PIGLIT_GL_TEST_CONFIG_BEGIN
> +
> + config.supports_gl_compat_version = 11;
> +
> + config.window_visual = PIGLIT_GL_VISUAL_RGBA |
> + PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_DEPTH;
> +
> + config.window_width = PGOS_WIN_SIZE;
> + config.window_height = PGOS_WIN_SIZE;
A window width of < 160 pixels will cause trouble on Windows 8. See the
comments in tests/util/piglit-framework-gl.h
You can use the default window size and then just set the
projection/viewport to the smaller size.
> +
> +PIGLIT_GL_TEST_CONFIG_END
> +
> +
> +struct angle_axis {
> + GLfloat angle;
> + GLfloat axis[3];
> +};
> +
> +void
> +red(void)
We usually declare functions like this as static so the compiler doesn't
generate warnings about missing prototypes. Looks like we don't have
the GCC flag for that now, but I think we used to.
> +{
> + glColor3f(1.0, 0.0, 0.0);
> +}
> +
> +void
> +black(void)
> +{
> + glColor3f(0.0, 0.0, 0.0);
> +}
> +
> +void
> +draw_quad_at_distance(GLdouble dist)
> +{
> + glBegin(GL_QUADS);
> + glVertex3d(-dist, -dist, -dist);
> + glVertex3d( dist, -dist, -dist);
> + glVertex3d( dist, dist, -dist);
> + glVertex3d(-dist, dist, -dist);
> + glEnd();
> +}
> +
> +GLdouble
> +window_coord_depth(GLdouble dist)
> +{
> + /*
> + * Assumes we're using the "far at infinity" projection matrix
> + * and simple viewport transformation.
> + */
> + return 0.5 * (dist - 2.0) / dist + 0.5;
> +}
> +
> +bool
> +red_quad_was_drawn(void)
> +{
> + float expected[] = {1.0f, 0.0f, 0.0f};
> + return piglit_probe_rect_rgb_silent(0, 0, PGOS_WIN_SIZE, PGOS_WIN_SIZE, expected);
> +}
> +
> +void
> +piglit_init(int argc, char **argv)
> +{
> +
> +} /* piglit_init */
I think you can drop that comment.
> +
> +void
> +find_ideal_mrd(GLdouble* ideal_mrd_near, GLdouble* ideal_mrd_far, GLdouble* next_to_near,
> + GLdouble* next_to_far)
Please wrap line to 78 or so columns.
> +{
> + /*
> + * MRD stands for Minimum Resolvable Difference, the smallest
> + * distance in depth that suffices to separate any two
> + * polygons (or a polygon and the near or far clipping
> + * planes).
> + *
> + * This function tries to determine the "ideal" MRD for the
> + * current rendering context. It's expressed in window
> + * coordinates, because the value in model or clipping
> + * coordinates depends on the scale factors in the modelview
> + * and projection matrices and on the distances to the near
> + * and far clipping planes.
> + *
> + * For simple unsigned-integer depth buffers that aren't too
> + * deep (so that precision isn't an issue during coordinate
> + * transformations), it should be about one least-significant
> + * bit. For deep or floating-point or compressed depth
> + * buffers the situation may be more complicated, so we don't
> + * pass or fail an implementation solely on the basis of its
> + * ideal MRD.
> + *
> + * There are two subtle parts of this function. The first is
> + * the projection matrix we use for rendering. This matrix
> + * places the far clip plane at infinity (so that we don't run
> + * into arbitrary limits during our search process). The
> + * second is the method used for drawing the polygon. We
> + * scale the x and y coords of the polygon vertices by the
> + * polygon's depth, so that it always occupies the full view
> + * frustum. This makes it easier to verify that the polygon
> + * was resolved completely -- we just read back the entire
> + * window and see if any background pixels appear.
> + *
> + * To insure that we get reasonable results on machines with
> + * unusual depth buffers (floating-point, or compressed), we
> + * determine the MRD twice, once close to the near clipping
> + * plane and once as far away from the eye as possible. On a
> + * simple integer depth buffer these two values should be
> + * essentially the same. For other depth-buffer formats, the
> + * ideal MRD is simply the largest of the two.
> + */
> +
> + GLdouble near_dist, far_dist, half_dist;
> + int i;
> +
> + /*
> + * First, find a distance that is as far away as possible, yet
> + * a quad at that distance can be distinguished from the
> + * background. Start by pushing quads away from the eye until
> + * we find an interval where the closer quad can be resolved,
> + * but the farther quad cannot. Then binary-search to find
> + * the threshold.
> + */
> +
> + glDepthFunc(GL_LESS);
> + glClearDepth(1.0);
> + red();
> + near_dist = 1.0;
> + far_dist = 2.0;
> + for (;;) {
> + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
> + draw_quad_at_distance(far_dist);
> + if (!red_quad_was_drawn())
> + break;
> + piglit_present_results();
> + near_dist = far_dist;
> + far_dist *= 2.0;
> + }
> + for (i = 0; i < 64; ++i) {
> + half_dist = 0.5 * (near_dist + far_dist);
> + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
> + draw_quad_at_distance(half_dist);
> + if (red_quad_was_drawn())
> + near_dist = half_dist;
> + else
> + far_dist = half_dist;
> + piglit_present_results();
> + }
> + *next_to_far = near_dist;
> +
> + /*
> + * We can derive a resolvable difference from the value
> + * next_to_far, but it's not necessarily the one we want.
> + * Consider mapping the object coordinate range [0,1] onto the
> + * integer window coordinate range [0,2]. A natural way to do
> + * this is with a linear function, windowCoord =
> + * 2*objectCoord. With rounding, this maps [0,0.25) to 0,
> + * [0.25,0.75) to 1, and [0.75,1] to 2. Note that the
> + * intervals at either end are 0.25 wide, but the one in the
> + * middle is 0.5 wide. The difference we can derive from
> + * next_to_far is related to the width of the final interval.
> + * We want to back up just a bit so that we can get a
> + * (possibly much larger) difference that will work for the
> + * larger interval. To do this we need to find a difference
> + * that allows us to distinguish two quads when the more
> + * distant one is at distance next_to_far.
> + */
> +
> + near_dist = 1.0;
> + far_dist = *next_to_far;
> + for (i = 0; i < 64; ++i) {
> + half_dist = 0.5 * (near_dist + far_dist);
> + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
> +
> + black();
> + glDepthFunc(GL_ALWAYS);
> + draw_quad_at_distance(*next_to_far);
> +
> + red();
> + glDepthFunc(GL_LESS);
> + draw_quad_at_distance(half_dist);
> +
> + if (red_quad_was_drawn())
> + near_dist = half_dist;
> + else
> + far_dist = half_dist;
> + piglit_present_results();
> + }
> +
> + *ideal_mrd_far = window_coord_depth(*next_to_far)
> + - window_coord_depth(near_dist);
> +
> + /*
> + * Now we apply a similar strategy at the near end of the
> + * depth range, but swapping the senses of various comparisons
> + * so that we approach the near clipping plane rather than the
> + * far.
> + */
> +
> + glClearDepth(0.0);
> + glDepthFunc(GL_GREATER);
> + red();
> + near_dist = 1.0;
> + far_dist = *next_to_far;
> + for (i = 0; i < 64; ++i) {
> + half_dist = 0.5 * (near_dist + far_dist);
> + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
> + draw_quad_at_distance(half_dist);
> + if (red_quad_was_drawn())
> + far_dist = half_dist;
> + else
> + near_dist = half_dist;
> + piglit_present_results();
> + }
> + *next_to_near = far_dist;
> +
> + near_dist = *next_to_near;
> + far_dist = *next_to_far;
> + for (i = 0; i < 64; ++i) {
> + half_dist = 0.5 * (near_dist + far_dist);
> + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
> +
> + black();
> + glDepthFunc(GL_ALWAYS);
> + draw_quad_at_distance(*next_to_near);
> +
> + red();
> + glDepthFunc(GL_GREATER);
> + draw_quad_at_distance(half_dist);
> +
> + if (red_quad_was_drawn())
> + far_dist = half_dist;
> + else
> + near_dist = half_dist;
> + piglit_present_results();
> + }
> +
> + *ideal_mrd_near = window_coord_depth(far_dist)
> + - window_coord_depth(*next_to_near);
> +} /* find_ideal_mrd */
> +
> +double
> +read_depth(int x, int y)
> +{
> + GLuint depth;
> + glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, &depth);
> +
> + /*
> + * This normalization of "depth" is correct even on 64-bit
> + * machines because GL types have machine-independent ranges.
> + */
> + return ((double) depth) / 4294967295.0;
> +}
> +
> +void
> +find_actual_mrd(GLdouble* next_to_near, GLdouble* next_to_far,
> + GLdouble* actual_mrd_near, GLdouble* actual_mrd_far)
> +{
> + /*
> + * Here we use polygon offset to determine the
> + * implementation's actual MRD.
> + */
> +
> + double base_depth;
> +
> + glDepthFunc(GL_ALWAYS);
> +
> + /* Draw a quad far away from the eye and read the depth at its
> + * center: */
> + glDisable(GL_POLYGON_OFFSET_FILL);
> + draw_quad_at_distance(*next_to_far);
> + base_depth = read_depth(PGOS_WIN_SIZE/2, PGOS_WIN_SIZE/2);
> +
> + /* Now draw a quad that's one MRD closer to the eye: */
> + glEnable(GL_POLYGON_OFFSET_FILL);
> + glPolygonOffset(0.0, -1.0);
> + draw_quad_at_distance(*next_to_far);
> +
> + /*
> + * The difference between the depths of the two quads is the
> + * value the implementation is actually using for one MRD:
> + */
> + *actual_mrd_far = base_depth
> + - read_depth(PGOS_WIN_SIZE/2, PGOS_WIN_SIZE/2);
> +
> + /* Repeat the process for a quad close to the eye: */
> + glDisable(GL_POLYGON_OFFSET_FILL);
> + draw_quad_at_distance(*next_to_near);
> + base_depth = read_depth(PGOS_WIN_SIZE/2, PGOS_WIN_SIZE/2);
> + glEnable(GL_POLYGON_OFFSET_FILL);
> + glPolygonOffset(0.0, 1.0); /* 1 MRD further away */
> + draw_quad_at_distance(*next_to_near);
> + *actual_mrd_near = read_depth(PGOS_WIN_SIZE/2, PGOS_WIN_SIZE/2)
> + - base_depth;
> +} /* find_actual_mrd */
> +
> +void
> +draw_2x2_quad(void)
> +{
> + glBegin(GL_QUADS);
> + glVertex2f(-1.0, -1.0);
> + glVertex2f( 1.0, -1.0);
> + glVertex2f( 1.0, 1.0);
> + glVertex2f(-1.0, 1.0);
> + glEnd();
> +}
> +
> +bool
> +check_slope_offset(struct angle_axis* aa, GLdouble* ideal_mrd_near)
> +{
> + /*
> + * This function checks for correct slope-based offsets for
> + * a quad rotated to a given angle around a given axis.
> + *
> + * The basic strategy is to:
> + * Draw the quad. (Note: the quad's size and position
> + * are chosen so that it won't ever be clipped.)
> + * Sample three points in the quad's interior.
> + * Compute dz/dx and dz/dy based on those samples.
> + * Compute the range of allowable offsets; must be between
> + * max(abs(dz/dx), abs(dz/dy)) and
> + * sqrt((dz/dx)**2, (dz/dy)**2)
> + * Sample the depth of the quad at its center.
> + * Use PolygonOffset to produce an offset equal to one
> + * times the depth slope of the base quad.
> + * Draw another quad with the same orientation as the first.
> + * Sample the second quad at its center.
> + * Compute the difference in depths between the first quad
> + * and the second.
> + * Verify that the difference is within the allowable range.
> + * Repeat for a third quad at twice the offset from the first.
> + * (This verifies that the implementation is scaling
> + * the depth offset correctly.)
> + */
> +
> + const GLfloat quad_dist = 2.5; /* must be > 1+sqrt(2) to avoid */
> + /* clipping by the near plane */
> + GLdouble modelview_mat[16];
> + GLdouble projection_mat[16];
> + GLint viewport[4];
> + GLdouble centerw[3];
> + GLdouble base_depth;
> + GLdouble p0[3];
> + GLdouble p1[3];
> + GLdouble p2[3];
> + double det, dzdx, dzdy, mmax, mmin;
> + GLdouble offset_depth, offset;
> +
> +
> + glClearDepth(1.0);
> + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
> + glEnable(GL_DEPTH_TEST);
> + glDepthFunc(GL_LESS);
> +
> + red();
> +
> + glMatrixMode(GL_MODELVIEW);
> + glLoadIdentity();
> + glTranslatef(0.0, 0.0, -quad_dist);
> + glRotatef(aa->angle, aa->axis[0], aa->axis[1], aa->axis[2]);
> +
> + glGetDoublev(GL_MODELVIEW_MATRIX, modelview_mat);
> + glGetDoublev(GL_PROJECTION_MATRIX, projection_mat);
> + glGetIntegerv(GL_VIEWPORT, viewport);
> +
> + glDisable(GL_POLYGON_OFFSET_FILL);
> +
> + draw_2x2_quad();
> +
> + gluProject(0.0, 0.0, 0.0, modelview_mat, projection_mat, viewport,
> + centerw + 0, centerw + 1, centerw + 2);
> + base_depth = read_depth(centerw[0], centerw[1]);
> +
> + gluProject(-0.9, -0.9, 0.0, modelview_mat, projection_mat, viewport,
> + p0 + 0, p0 + 1, p0 + 2);
> + p0[2] = read_depth(p0[0], p0[1]);
> + gluProject( 0.9, -0.9, 0.0, modelview_mat, projection_mat, viewport,
> + p1 + 0, p1 + 1, p1 + 2);
> + p1[2] = read_depth(p1[0], p1[1]);
> + gluProject( 0.9, 0.9, 0.0, modelview_mat, projection_mat, viewport,
> + p2 + 0, p2 + 1, p2 + 2);
> + p2[2] = read_depth(p2[0], p2[1]);
> +
> + det = (p0[0] - p1[0]) * (p0[1] - p2[1])
> + - (p0[0] - p2[0]) * (p0[1] - p1[1]);
> + if (fabs(det) < 0.001)
> + return false; /* too close to colinear to evaluate */
> +
> + dzdx = ((p0[2] - p1[2]) * (p0[1] - p2[1])
> + - (p0[2] - p2[2]) * (p0[1] - p1[1])) / det;
> + dzdy = ((p0[0] - p1[0]) * (p0[2] - p2[2])
> + - (p0[0] - p2[0]) * (p0[2] - p1[2])) / det;
> +
> + mmax = 1.1 * sqrt(dzdx * dzdx + dzdy * dzdy) + (*ideal_mrd_near);
> + /* (adding ideal_mrd_near is a fudge for roundoff error when */
> + /* the slope is extremely close to zero) */
> + mmin = 0.9 * fmax(fabs(dzdx), fabs(dzdy));
> +
> + glEnable(GL_POLYGON_OFFSET_FILL);
> + glPolygonOffset(-1.0, 0.0);
> + piglit_present_results();
> + draw_2x2_quad();
> + offset_depth = read_depth(centerw[0], centerw[1]);
> + offset = fmax(base_depth - offset_depth, 0.0);
> + if (offset < mmin || offset > mmax) {
> + if (offset < mmin)
> + printf("\tDepth-slope related offset was too small");
> + else
> + printf("\tDepth-slope related offset was too large");
> + printf("; first failure at:\n");
> + printf("\t\tAngle = %f degrees, axis = (%f, %f, %f)\n",
> + aa->angle, aa->axis[0], aa->axis[1], aa->axis[2]);
> + printf("\t\tFailing offset was %.16f\n", offset);
> + printf("\t\tAllowable range is (%f, %f)\n", mmin, mmax);
> + return false;
> + }
> +
> + glPolygonOffset(-2.0, 0.0);
> + piglit_present_results();
> + draw_2x2_quad();
> + offset_depth = read_depth(centerw[0], centerw[1]);
> + offset = fmax(base_depth - offset_depth, 0.0);
> + if (offset < 2.0 * mmin || offset > 2.0 * mmax) {
> + if (offset < 2.0 * mmin)
> + printf("\tDepth-slope related offset was too small");
> + else
> + printf("\tDepth-slope related offset was too large");
> + printf("; first failure at:\n");
> + printf("\t\tAngle = %f degrees, axis = (%f, %f, %f)\n",
> + aa->angle, aa->axis[0], aa->axis[1], aa->axis[2]);
> + printf("\t\tFailing offset was %.16f\n", offset);
> + printf("\t\tAllowable range is (%f, %f)\n", 2.0 * mmin, 2.0 * mmax);
> + return false;
> + }
> +
> + return true;
> +}
> +
> +bool
> +check_slope_offsets(GLdouble* ideal_mrd_near)
> +{
> + /*
> + * This function checks that the implementation is offsetting
> + * primitives correctly according to their depth slopes.
> + * (Note that it uses some values computed by find_ideal_mrd, so
> + * that function must be run first.)
> + */
> + bool pass = true;
> + int i;
> +
> + /* Rotation angles (degrees) and axes for which offset will be checked: */
> + struct angle_axis aa[] = {
> + { 0, {1, 0, 0}},
> + {30, {1, 0, 0}},
> + {45, {1, 0, 0}},
> + {60, {1, 0, 0}},
> + {80, {1, 0, 0}},
> + { 0, {0, 1, 0}},
> + {30, {0, 1, 0}},
> + {45, {0, 1, 0}},
> + {60, {0, 1, 0}},
> + {80, {0, 1, 0}},
> + { 0, {1, 1, 0}},
> + {30, {1, 1, 0}},
> + {45, {1, 1, 0}},
> + {60, {1, 1, 0}},
> + {80, {1, 1, 0}},
> + { 0, {2, 1, 0}},
> + {30, {2, 1, 0}},
> + {45, {2, 1, 0}},
> + {60, {2, 1, 0}},
> + {80, {2, 1, 0}}
> + };
> +
> + for (i = 0; pass && i < ARRAY_SIZE(aa); ++i)
> + pass &= check_slope_offset(aa + i, ideal_mrd_near);
> +
> + return pass;
> +} /* check_slope_offsets */
> +
> +void
> +log_mrd(double mrd, GLint dbits)
> +{
> + int bits;
> + bits = (int)(0.5 + (pow(2.0, dbits) - 1.0) * mrd);
> + printf("%e (nominally %i %s)\n", mrd, bits, (bits == 1)? "bit": "bits");
> +} /* log_mrd */
> +
> +enum piglit_result
> +piglit_display(void)
> +{
> + bool pass = true;
> + double ideal_mrd, actual_mrd;
> + GLdouble ideal_mrd_near, ideal_mrd_far, next_to_near, next_to_far;
> + GLdouble actual_mrd_near, actual_mrd_far;
> + bool big_enough_mrd, small_enough_mrd;
> + GLint dbits;
> +
> + /*
> + * The following projection matrix places the near clipping
> + * plane at distance 1.0, and the far clipping plane at
> + * infinity. This allows us to stress depth-buffer resolution
> + * as far away from the eye as possible, without introducing
> + * code that depends on the size or format of the depth
> + * buffer.
> + *
> + * (To derive this matrix, start with the matrix generated by
> + * glFrustum with near-plane distance equal to 1.0, and take
> + * the limit of the matrix elements as the far-plane distance
> + * goes to infinity.)
> + */
> +
> + static GLfloat near_1_far_infinity[] = {
> + 1.0, 0.0, 0.0, 0.0,
> + 0.0, 1.0, 0.0, 0.0,
> + 0.0, 0.0, -1.0, -1.0,
> + 0.0, 0.0, -2.0, 0.0
> + };
> +
> + glViewport(0, 0, PGOS_WIN_SIZE, PGOS_WIN_SIZE);
> + glDepthRange(0.0, 1.0);
> +
> + glMatrixMode(GL_PROJECTION);
> + glLoadMatrixf(near_1_far_infinity);
> +
> + glDisable(GL_LIGHTING);
> +
> + glFrontFace(GL_CCW);
> + glDisable(GL_NORMALIZE);
> + glDisable(GL_COLOR_MATERIAL);
> +
> + glMatrixMode(GL_MODELVIEW);
> + glLoadIdentity();
> +
> + glDisable(GL_TEXTURE_2D);
> +
> + glDisable(GL_FOG);
> +
> + glDisable(GL_SCISSOR_TEST);
> + glDisable(GL_ALPHA_TEST);
> + glDisable(GL_STENCIL_TEST);
> + glDepthFunc(GL_LESS);
> + glEnable(GL_DEPTH_TEST);
> + glDisable(GL_BLEND);
> + glDisable(GL_DITHER);
> + glDisable(GL_COLOR_LOGIC_OP);
> +
> + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
> + glDepthMask(GL_TRUE);
> +
> + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
> + glCullFace(GL_BACK);
> + glEnable(GL_CULL_FACE);
> + glDisable(GL_POLYGON_STIPPLE);
> + glDisable(GL_POLYGON_OFFSET_FILL);
> +
> + glShadeModel(GL_FLAT);
> +
> + glClearColor(0.0, 0.0, 0.0, 0.0);
> + glClearDepth(1.0);
> +
> + find_ideal_mrd(&ideal_mrd_near, &ideal_mrd_far, &next_to_near, &next_to_far);
> + find_actual_mrd(&next_to_near, &next_to_far, &actual_mrd_near, &actual_mrd_far);
> + ideal_mrd = fmax(ideal_mrd_near, ideal_mrd_far);
> + actual_mrd = fmax(actual_mrd_near, actual_mrd_far);
> + big_enough_mrd = (actual_mrd >= 0.99 * ideal_mrd);
> + small_enough_mrd = (actual_mrd <= 2.0 * ideal_mrd);
> +
> + pass &= big_enough_mrd;
> + pass &= small_enough_mrd;
> + pass &= check_slope_offsets(&ideal_mrd_near);
> +
> + /* Print the results */
> + if (!big_enough_mrd)
> + printf("\tActual MRD is too small (may cause incorrect results)\n");
> + if (!small_enough_mrd)
> + printf("\tActual MRD is too large (may waste depth-buffer range)\n\n");
> +
> + glGetIntegerv(GL_DEPTH_BITS, &dbits);
> + printf("\tIdeal MRD at near plane is ");
> + log_mrd(ideal_mrd_near, dbits);
> + printf("\tActual MRD at near plane is ");
> + log_mrd(actual_mrd_near, dbits);
> + printf("\tIdeal MRD at infinity is ");
> + log_mrd(ideal_mrd_far, dbits);
> + printf("\tActual MRD at infinity is ");
> + log_mrd(actual_mrd_far, dbits);
> + printf("\n");
> +
> + return pass ? PIGLIT_PASS : PIGLIT_FAIL;
> +} /* piglit_display */
>
I just skimmed the rest and it looks alright.
-Brian
More information about the Piglit
mailing list