[Piglit] [PATCH 1/2] Ported polygon offset test from Glean to Piglit.
Laura Ekstrand
laura at jlekstrand.net
Mon Oct 20 16:30:48 PDT 2014
---
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;
+
+PIGLIT_GL_TEST_CONFIG_END
+
+
+struct angle_axis {
+ GLfloat angle;
+ GLfloat axis[3];
+};
+
+void
+red(void)
+{
+ 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 */
+
+void
+find_ideal_mrd(GLdouble* ideal_mrd_near, GLdouble* ideal_mrd_far, GLdouble* next_to_near,
+ GLdouble* next_to_far)
+{
+ /*
+ * 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 */
--
2.1.0
More information about the Piglit
mailing list