glsl-1.30: add more loop unroll tests
[piglit.git] / tests / spec / gl-1.4 / polygon-offset.c
bloba749071bc769a23dccd3f87e8f46bfe79d32f62d
1 /*
2 * BEGIN_COPYRIGHT -*- glean -*-
4 * Copyright (C) 2001 Allen Akin All Rights Reserved.
5 * Copyright (C) 2014 Intel Corporation All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person
8 * obtaining a copy of this software and associated documentation
9 * files (the "Software"), to deal in the Software without
10 * restriction, including without limitation the rights to use,
11 * copy, modify, merge, publish, distribute, sublicense, and/or
12 * sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following
14 * conditions:
16 * The above copyright notice and this permission notice shall be
17 * included in all copies or substantial portions of the
18 * Software.
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
26 * IN THE SOFTWARE.
28 * END_COPYRIGHT
31 /** @file polygon-offset.c
33 * Implementation of polygon offset tests.
35 * This test verifies glPolygonOffset. It is run on every OpenGL-capable
36 * drawing surface configuration that supports creation of a window, has a
37 * depth buffer, and is RGB.
39 * The first subtest verifies that the OpenGL implementation is using a
40 * plausible value for the "minimum resolvable difference" (MRD). This is the
41 * offset in window coordinates that is sufficient to provide separation in
42 * depth (Z) for any two parallel surfaces. The subtest searches for the MRD
43 * by drawing two surfaces at a distance from each other and checking the
44 * resulting image to see if they were cleanly separated. The distance is
45 * then modified (using a binary search) until a minimum value is found. This
46 * is the so-called "ideal" MRD. Then two surfaces are drawn using
47 * glPolygonOffset to produce a separation that should equal one MRD. The
48 * depth values at corresponding points on each surface are subtracted to form
49 * the "actual" MRD. The subtest performs these checks twice, once close to
50 * the viewpoint and once far away from it, and passes if the largest of the
51 * ideal MRDs and the largest of the actual MRDs are nearly the same.
53 * The second subtest verifies that the OpenGL implementation is producing
54 * plausible values for slope-dependent offsets. The OpenGL spec requires
55 * that the depth slope of a surface be computed by an approximation that is
56 * at least as large as max(abs(dz/dx),abs(dz/dy)) and no larger than
57 * sqrt((dz/dx)**2+(dz/dy)**2). The subtest draws a quad rotated by various
58 * angles along various axes, samples three points on the quad's surface, and
59 * computes dz/dx and dz/dy. Then it draws two additional quads offset by one
60 * and two times the depth slope, respectively. The base quad and the two new
61 * quads are sampled and their actual depths read from the depth buffer. The
62 * subtest passes if the quads are offset by amounts that are within one and
63 * two times the allowable range, respectively.
65 * Derived in part from tests written by Angus Dorbie <dorbie@sgi.com> in
66 * September 2000 and Rickard E. (Rik) Faith <faith@valinux.com> in October
67 * 2000.
69 * Ported to Piglit by Laura Ekstrand.
72 #include "piglit-util-gl.h"
73 #include <math.h>
75 PIGLIT_GL_TEST_CONFIG_BEGIN
77 config.supports_gl_compat_version = 11;
79 config.window_visual = PIGLIT_GL_VISUAL_RGBA |
80 PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_DEPTH;
82 PIGLIT_GL_TEST_CONFIG_END
85 struct angle_axis {
86 GLfloat angle;
87 GLfloat axis[3];
90 static void
91 multiply_matrix_with_vector(const double *matrix, double *vector)
93 double tmp[4];
94 unsigned i;
96 /* The matrix is stored in the natural OpenGL order: column-major. In
97 * GLSL, this would be:
99 * vp.x = m[0] * v.xxxx;
100 * vp.y = m[1] * v.yyyy;
101 * vp.z = m[2] * v.zzzz;
102 * vp.w = m[3] * v.wwww;
103 * v = vp;
105 for (i = 0; i < 4; i++)
106 tmp[i] = matrix[i] * vector[0];
108 for (i = 0; i < 4; i++)
109 tmp[i] += matrix[i + 4] * vector[1];
111 for (i = 0; i < 4; i++)
112 tmp[i] += matrix[i + 8] * vector[2];
114 for (i = 0; i < 4; i++)
115 tmp[i] += matrix[i + 12] * vector[3];
117 memcpy(vector, tmp, sizeof(tmp));
120 static void
121 project(double x, double y, double z, const double *modelview,
122 const double *projection, const int *viewport, double *result)
124 double vp[4] = { x, y, z, 1.0 };
126 /* Calculate v' as P * M * v. */
127 multiply_matrix_with_vector(modelview, vp);
128 multiply_matrix_with_vector(projection, vp);
130 if (vp[3] == 0.0) {
131 fprintf(stderr, "Cannot perspective divide by zero.\n");
132 piglit_report_result(PIGLIT_FAIL);
135 vp[0] /= vp[3];
136 vp[1] /= vp[3];
137 vp[2] /= vp[3];
139 /* Calculate the screen position using the same formula a gluProject. */
140 result[0] = viewport[0] + (viewport[2] * ((vp[0] + 1.0) / 2.0));
141 result[1] = viewport[1] + (viewport[3] * ((vp[1] + 1.0) / 2.0));
142 result[2] = (vp[2] + 1.0) / 2.0;
145 static void
146 draw_quad_at_distance(GLdouble dist)
148 glBegin(GL_QUADS);
149 glVertex3d(-dist, -dist, -dist);
150 glVertex3d( dist, -dist, -dist);
151 glVertex3d( dist, dist, -dist);
152 glVertex3d(-dist, dist, -dist);
153 glEnd();
156 static GLdouble
157 window_coord_depth(GLdouble dist)
159 /* Assumes we're using the "far at infinity" projection matrix and
160 * simple viewport transformation.
162 return 0.5 * (dist - 2.0) / dist + 0.5;
165 static bool
166 red_quad_was_drawn(void)
168 static const float expected[] = {1.0f, 0.0f, 0.0f};
169 return piglit_probe_rect_rgb_silent(0, 0, piglit_width, piglit_height,
170 expected);
173 void
174 piglit_init(int argc, char **argv)
176 glEnable(GL_DEPTH_TEST);
177 glDisable(GL_DITHER);
178 glEnable(GL_CULL_FACE);
179 glShadeModel(GL_FLAT);
182 static void
183 find_ideal_mrd(GLdouble *ideal_mrd_near, GLdouble *ideal_mrd_far,
184 GLdouble *next_to_near, GLdouble *next_to_far)
186 /* MRD stands for Minimum Resolvable Difference, the smallest distance
187 * in depth that suffices to separate any two polygons (or a polygon
188 * and the near or far clipping planes).
190 * This function tries to determine the "ideal" MRD for the current
191 * rendering context. It's expressed in window coordinates, because
192 * the value in model or clipping coordinates depends on the scale
193 * factors in the modelview and projection matrices and on the
194 * distances to the near and far clipping planes.
196 * For simple unsigned-integer depth buffers that aren't too deep (so
197 * that precision isn't an issue during coordinate transformations),
198 * it should be about one least-significant bit. For deep or
199 * floating-point or compressed depth buffers the situation may be
200 * more complicated, so we don't pass or fail an implementation solely
201 * on the basis of its ideal MRD.
203 * There are two subtle parts of this function. The first is the
204 * projection matrix we use for rendering. This matrix places the far
205 * clip plane at infinity (so that we don't run into arbitrary limits
206 * during our search process). The second is the method used for
207 * drawing the polygon. We scale the x and y coords of the polygon
208 * vertices by the polygon's depth, so that it always occupies the
209 * full view frustum. This makes it easier to verify that the polygon
210 * was resolved completely -- we just read back the entire window and
211 * see if any background pixels appear.
213 * To insure that we get reasonable results on machines with unusual
214 * depth buffers (floating-point, or compressed), we determine the MRD
215 * twice, once close to the near clipping plane and once as far away
216 * from the eye as possible. On a simple integer depth buffer these
217 * two values should be essentially the same. For other depth-buffer
218 * formats, the ideal MRD is simply the largest of the two.
221 GLdouble near_dist, far_dist, half_dist;
222 int i;
224 /* First, find a distance that is as far away as possible, yet a quad
225 * at that distance can be distinguished from the background. Start
226 * by pushing quads away from the eye until we find an interval where
227 * the closer quad can be resolved, but the farther quad cannot. Then
228 * binary-search to find the threshold.
231 glDepthFunc(GL_LESS);
232 glClearDepth(1.0);
233 glColor3f(1.0, 0.0, 0.0); /* red */
234 near_dist = 1.0;
235 far_dist = 2.0;
236 for (;;) {
237 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
238 draw_quad_at_distance(far_dist);
239 if (!red_quad_was_drawn())
240 break;
241 piglit_present_results();
242 near_dist = far_dist;
243 far_dist *= 2.0;
245 for (i = 0; i < 64; ++i) {
246 half_dist = 0.5 * (near_dist + far_dist);
247 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
248 draw_quad_at_distance(half_dist);
249 if (red_quad_was_drawn())
250 near_dist = half_dist;
251 else
252 far_dist = half_dist;
253 piglit_present_results();
255 *next_to_far = near_dist;
257 /* We can derive a resolvable difference from the value next_to_far,
258 * but it's not necessarily the one we want. Consider mapping the
259 * object coordinate range [0,1] onto the integer window coordinate
260 * range [0,2]. A natural way to do this is with a linear function,
261 * windowCoord = 2*objectCoord. With rounding, this maps [0,0.25) to
262 * 0, [0.25,0.75) to 1, and [0.75,1] to 2. Note that the intervals at
263 * either end are 0.25 wide, but the one in the middle is 0.5 wide.
264 * The difference we can derive from next_to_far is related to the
265 * width of the final interval. We want to back up just a bit so that
266 * we can get a (possibly much larger) difference that will work for
267 * the larger interval. To do this we need to find a difference that
268 * allows us to distinguish two quads when the more distant one is at
269 * distance next_to_far.
272 near_dist = 1.0;
273 far_dist = *next_to_far;
274 for (i = 0; i < 64; ++i) {
275 half_dist = 0.5 * (near_dist + far_dist);
276 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
278 glColor3f(0.0, 0.0, 0.0); /* black */
279 glDepthFunc(GL_ALWAYS);
280 draw_quad_at_distance(*next_to_far);
282 glColor3f(1.0, 0.0, 0.0); /* red */
283 glDepthFunc(GL_LESS);
284 draw_quad_at_distance(half_dist);
286 if (red_quad_was_drawn())
287 near_dist = half_dist;
288 else
289 far_dist = half_dist;
290 piglit_present_results();
293 *ideal_mrd_far = window_coord_depth(*next_to_far)
294 - window_coord_depth(near_dist);
296 /* Now we apply a similar strategy at the near end of the depth range,
297 * but swapping the senses of various comparisons so that we approach
298 * the near clipping plane rather than the far.
301 glClearDepth(0.0);
302 glDepthFunc(GL_GREATER);
303 glColor3f(1.0, 0.0, 0.0); /* red */
304 near_dist = 1.0;
305 far_dist = *next_to_far;
306 for (i = 0; i < 64; ++i) {
307 half_dist = 0.5 * (near_dist + far_dist);
308 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
309 draw_quad_at_distance(half_dist);
310 if (red_quad_was_drawn())
311 far_dist = half_dist;
312 else
313 near_dist = half_dist;
314 piglit_present_results();
316 *next_to_near = far_dist;
318 near_dist = *next_to_near;
319 far_dist = *next_to_far;
320 for (i = 0; i < 64; ++i) {
321 half_dist = 0.5 * (near_dist + far_dist);
322 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
324 glColor3f(0.0, 0.0, 0.0); /* black */
325 glDepthFunc(GL_ALWAYS);
326 draw_quad_at_distance(*next_to_near);
328 glColor3f(1.0, 0.0, 0.0); /* red */
329 glDepthFunc(GL_GREATER);
330 draw_quad_at_distance(half_dist);
332 if (red_quad_was_drawn())
333 far_dist = half_dist;
334 else
335 near_dist = half_dist;
336 piglit_present_results();
339 *ideal_mrd_near = window_coord_depth(far_dist)
340 - window_coord_depth(*next_to_near);
343 static double
344 read_depth(int x, int y)
346 GLuint depth;
347 glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, &depth);
349 /* This normalization of "depth" is correct even on 64-bit
350 * machines because GL types have machine-independent ranges.
352 return ((double) depth) / 4294967295.0;
355 static void
356 find_actual_mrd(GLdouble *next_to_near, GLdouble *next_to_far,
357 GLdouble *actual_mrd_near, GLdouble *actual_mrd_far)
359 /* Here we use polygon offset to determine the implementation's actual
360 * MRD.
363 double base_depth;
365 glDepthFunc(GL_ALWAYS);
367 /* Draw a quad far away from the eye and read the depth at its
368 * center:
370 glDisable(GL_POLYGON_OFFSET_FILL);
371 draw_quad_at_distance(*next_to_far);
372 base_depth = read_depth(piglit_width/2, piglit_height/2);
374 /* Now draw a quad that's one MRD closer to the eye: */
375 glEnable(GL_POLYGON_OFFSET_FILL);
376 glPolygonOffset(0.0, -1.0);
377 draw_quad_at_distance(*next_to_far);
379 /* The difference between the depths of the two quads is the value the
380 * implementation is actually using for one MRD:
382 *actual_mrd_far = base_depth
383 - read_depth(piglit_width/2, piglit_height/2);
385 /* Repeat the process for a quad close to the eye: */
386 glDisable(GL_POLYGON_OFFSET_FILL);
387 draw_quad_at_distance(*next_to_near);
388 base_depth = read_depth(piglit_width / 2, piglit_height / 2);
389 glEnable(GL_POLYGON_OFFSET_FILL);
390 glPolygonOffset(0.0, 1.0); /* 1 MRD further away */
391 draw_quad_at_distance(*next_to_near);
392 *actual_mrd_near = read_depth(piglit_width / 2, piglit_height / 2)
393 - base_depth;
396 static bool
397 check_slope_offset(const struct angle_axis *aa, GLdouble *ideal_mrd_near)
399 /* This function checks for correct slope-based offsets for a quad
400 * rotated to a given angle around a given axis.
402 * The basic strategy is to:
403 * Draw the quad. (Note: the quad's size and position
404 * are chosen so that it won't ever be clipped.)
405 * Sample three points in the quad's interior.
406 * Compute dz/dx and dz/dy based on those samples.
407 * Compute the range of allowable offsets; must be between
408 * max(abs(dz/dx), abs(dz/dy)) and
409 * sqrt((dz/dx)**2, (dz/dy)**2)
410 * Sample the depth of the quad at its center.
411 * Use PolygonOffset to produce an offset equal to one
412 * times the depth slope of the base quad.
413 * Draw another quad with the same orientation as the first.
414 * Sample the second quad at its center.
415 * Compute the difference in depths between the first quad
416 * and the second.
417 * Verify that the difference is within the allowable range.
418 * Repeat for a third quad at twice the offset from the first.
419 * (This verifies that the implementation is scaling
420 * the depth offset correctly.)
422 const GLfloat quad_dist = 2.5; /* must be > 1+sqrt(2) to avoid */
423 /* clipping by the near plane */
424 GLdouble modelview_mat[16];
425 GLdouble projection_mat[16];
426 GLint viewport[4];
427 GLdouble centerw[3];
428 GLdouble base_depth;
429 GLdouble p0[3];
430 GLdouble p1[3];
431 GLdouble p2[3];
432 double det, dzdx, dzdy, mmax, mmin;
433 GLdouble offset_depth, offset;
436 glClearDepth(1.0);
437 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
438 glEnable(GL_DEPTH_TEST);
439 glDepthFunc(GL_LESS);
441 glColor3f(1.0, 0.0, 0.0); /* red */
443 glMatrixMode(GL_MODELVIEW);
444 glLoadIdentity();
445 glTranslatef(0.0, 0.0, -quad_dist);
446 glRotatef(aa->angle, aa->axis[0], aa->axis[1], aa->axis[2]);
448 glGetDoublev(GL_MODELVIEW_MATRIX, modelview_mat);
449 glGetDoublev(GL_PROJECTION_MATRIX, projection_mat);
450 glGetIntegerv(GL_VIEWPORT, viewport);
452 glDisable(GL_POLYGON_OFFSET_FILL);
454 piglit_draw_rect(-1.0, -1.0, 2.0, 2.0);
456 project(0.0, 0.0, 0.0, modelview_mat, projection_mat, viewport,
457 centerw);
458 base_depth = read_depth(centerw[0], centerw[1]);
460 project(-0.9, -0.9, 0.0, modelview_mat, projection_mat, viewport, p0);
461 p0[2] = read_depth(p0[0], p0[1]);
463 project( 0.9, -0.9, 0.0, modelview_mat, projection_mat, viewport, p1);
464 p1[2] = read_depth(p1[0], p1[1]);
466 project( 0.9, 0.9, 0.0, modelview_mat, projection_mat, viewport, p2);
467 p2[2] = read_depth(p2[0], p2[1]);
469 det = (p0[0] - p1[0]) * (p0[1] - p2[1])
470 - (p0[0] - p2[0]) * (p0[1] - p1[1]);
471 if (fabs(det) < 0.001)
472 return false; /* too close to colinear to evaluate */
474 dzdx = ((p0[2] - p1[2]) * (p0[1] - p2[1])
475 - (p0[2] - p2[2]) * (p0[1] - p1[1])) / det;
476 dzdy = ((p0[0] - p1[0]) * (p0[2] - p2[2])
477 - (p0[0] - p2[0]) * (p0[2] - p1[2])) / det;
479 mmax = 1.1 * sqrt(dzdx * dzdx + dzdy * dzdy) + (*ideal_mrd_near);
480 /* (adding ideal_mrd_near is a fudge for roundoff error */
481 /* when the slope is extremely close to zero) */
482 mmin = 0.9 * fmax(fabs(dzdx), fabs(dzdy));
484 glEnable(GL_POLYGON_OFFSET_FILL);
485 glPolygonOffset(-1.0, 0.0);
486 piglit_present_results();
487 piglit_draw_rect(-1.0, -1.0, 2.0, 2.0);
488 offset_depth = read_depth(centerw[0], centerw[1]);
489 offset = fmax(base_depth - offset_depth, 0.0);
490 if (offset < mmin || offset > mmax) {
491 if (offset < mmin)
492 printf("Depth-slope related offset was too small");
493 else
494 printf("Depth-slope related offset was too large");
495 printf("; first failure at:\n");
496 printf("\tAngle = %f degrees, axis = (%f, %f, %f)\n",
497 aa->angle, aa->axis[0], aa->axis[1], aa->axis[2]);
498 printf("\tFailing offset was %.16f\n", offset);
499 printf("\tAllowable range is (%f, %f)\n", mmin, mmax);
500 printf("\tglPolygonOffset(-1.0, 0.0);\n");
501 printf("\tglReadPixels returned %f\n", offset_depth);
502 return false;
505 glPolygonOffset(-2.0, 0.0);
506 piglit_present_results();
507 piglit_draw_rect(-1.0, -1.0, 2.0, 2.0);
508 offset_depth = read_depth(centerw[0], centerw[1]);
509 offset = fmax(base_depth - offset_depth, 0.0);
510 if (offset < 2.0 * mmin || offset > 2.0 * mmax) {
511 if (offset < 2.0 * mmin)
512 printf("Depth-slope related offset was too small");
513 else
514 printf("Depth-slope related offset was too large");
515 printf("; first failure at:\n");
516 printf("\tAngle = %f degrees, axis = (%f, %f, %f)\n",
517 aa->angle, aa->axis[0], aa->axis[1], aa->axis[2]);
518 printf("\tFailing offset was %.16f\n", offset);
519 printf("\tAllowable range is (%f, %f)\n", 2.0 * mmin,
520 2.0 * mmax);
521 printf("\tglPolygonOffset(-2.0, 0.0);\n");
522 printf("\tglReadPixels returned %f\n", offset_depth);
523 return false;
526 return true;
529 static bool
530 check_slope_offsets(GLdouble* ideal_mrd_near)
532 /* This function checks that the implementation is offsetting
533 * primitives correctly according to their depth slopes. (Note that
534 * it uses some values computed by find_ideal_mrd, so that function
535 * must be run first.)
537 unsigned i;
539 /* Rotation angles (degrees) and axes for which offset will be checked
541 static const struct angle_axis aa[] = {
542 { 0, {1, 0, 0}},
543 {30, {1, 0, 0}},
544 {45, {1, 0, 0}},
545 {60, {1, 0, 0}},
546 {80, {1, 0, 0}},
547 { 0, {0, 1, 0}},
548 {30, {0, 1, 0}},
549 {45, {0, 1, 0}},
550 {60, {0, 1, 0}},
551 {80, {0, 1, 0}},
552 { 0, {1, 1, 0}},
553 {30, {1, 1, 0}},
554 {45, {1, 1, 0}},
555 {60, {1, 1, 0}},
556 {80, {1, 1, 0}},
557 { 0, {2, 1, 0}},
558 {30, {2, 1, 0}},
559 {45, {2, 1, 0}},
560 {60, {2, 1, 0}},
561 {80, {2, 1, 0}}
564 for (i = 0; i < ARRAY_SIZE(aa); ++i)
565 if (!check_slope_offset(aa + i, ideal_mrd_near))
566 return false;
568 return true;
569 } /* check_slope_offsets */
571 static void
572 log_mrd(const char *pre, double mrd, GLint dbits)
574 int bits;
575 bits = (int)(0.5 + (pow(2.0, dbits) - 1.0) * mrd);
576 printf("%s %e (nominally %i %s)\n", pre, mrd, bits,
577 (bits == 1) ? "bit": "bits");
578 } /* log_mrd */
580 enum piglit_result
581 piglit_display(void)
583 bool pass = true;
584 double ideal_mrd, actual_mrd;
585 GLdouble ideal_mrd_near, ideal_mrd_far, next_to_near, next_to_far;
586 GLdouble actual_mrd_near, actual_mrd_far;
587 bool big_enough_mrd, small_enough_mrd;
588 GLint dbits;
590 /* The following projection matrix places the near clipping plane at
591 * distance 1.0, and the far clipping plane at infinity. This allows
592 * us to stress depth-buffer resolution as far away from the eye as
593 * possible, without introducing code that depends on the size or
594 * format of the depth buffer.
596 * To derive this matrix, start with the matrix generated by glFrustum
597 * with near-plane distance equal to 1.0, and take the limit of the
598 * matrix elements as the far-plane distance goes to infinity.
600 static const GLfloat near_1_far_infinity[] = {
601 1.0, 0.0, 0.0, 0.0,
602 0.0, 1.0, 0.0, 0.0,
603 0.0, 0.0, -1.0, -1.0,
604 0.0, 0.0, -2.0, 0.0
607 glViewport(0, 0, piglit_width, piglit_height);
609 glMatrixMode(GL_PROJECTION);
610 glLoadMatrixf(near_1_far_infinity);
612 glMatrixMode(GL_MODELVIEW);
613 glLoadIdentity();
615 glDepthFunc(GL_LESS);
616 glDisable(GL_POLYGON_OFFSET_FILL);
617 glClearDepth(1.0);
619 find_ideal_mrd(&ideal_mrd_near, &ideal_mrd_far,
620 &next_to_near, &next_to_far);
621 find_actual_mrd(&next_to_near, &next_to_far,
622 &actual_mrd_near, &actual_mrd_far);
623 ideal_mrd = fmax(ideal_mrd_near, ideal_mrd_far);
624 actual_mrd = fmax(actual_mrd_near, actual_mrd_far);
625 big_enough_mrd = (actual_mrd >= 0.99 * ideal_mrd);
626 small_enough_mrd = (actual_mrd <= 2.0 * ideal_mrd);
628 pass = big_enough_mrd && small_enough_mrd && pass;
629 pass = check_slope_offsets(&ideal_mrd_near) && pass;
631 /* Print the results */
632 if (!big_enough_mrd) {
633 printf("Actual MRD is too small ");
634 printf("(may cause incorrect results)\n");
637 if (!small_enough_mrd) {
638 printf("Actual MRD is too large ");
639 printf("(may waste depth-buffer range)\n\n");
642 glGetIntegerv(GL_DEPTH_BITS, &dbits);
643 printf("GL_DEPTH_BITS = %d\n", dbits);
644 log_mrd("Ideal MRD at near plane is", ideal_mrd_near, dbits);
645 log_mrd("Actual MRD at near plane is", actual_mrd_near, dbits);
646 log_mrd("Ideal MRD at infinity is", ideal_mrd_far, dbits);
647 log_mrd("Actual MRD at infinity is", actual_mrd_far, dbits);
649 return pass ? PIGLIT_PASS : PIGLIT_FAIL;