Add more structure constructor tests.
[piglit/hramrach.git] / tests / glean / treadpix.cpp
blob5044d4c6cc3b8209895983eb50a5a91b260a3ef6
1 // BEGIN_COPYRIGHT -*- glean -*-
2 //
3 // Copyright (C) 2001 Allen Akin All Rights Reserved.
4 //
5 // Permission is hereby granted, free of charge, to any person
6 // obtaining a copy of this software and associated documentation
7 // files (the "Software"), to deal in the Software without
8 // restriction, including without limitation the rights to use,
9 // copy, modify, merge, publish, distribute, sublicense, and/or
10 // sell copies of the Software, and to permit persons to whom the
11 // Software is furnished to do so, subject to the following
12 // conditions:
14 // The above copyright notice and this permission notice shall be
15 // included in all copies or substantial portions of the
16 // Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
19 // KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
20 // WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
21 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ALLEN AKIN BE
22 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 // AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
24 // OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 // DEALINGS IN THE SOFTWARE.
27 // END_COPYRIGHT
29 // treadpix.cpp: implementation of ReadPixels tests
31 #include <cmath>
32 #ifdef __CYGWIN__
33 #undef log2
34 #endif
35 #include <iomanip>
36 #include <cstdlib>
37 #include "misc.h"
38 #include "rand.h"
39 #include "treadpix.h"
42 namespace GLEAN {
44 void
45 ReadPixSanityTest::checkRGBA(ReadPixSanityResult& r, Window& w) {
46 DrawingSurfaceConfig& config = *r.config;
47 RandomBitsDouble rRand(config.r, 1066);
48 RandomBitsDouble gRand(config.g, 1492);
49 RandomBitsDouble bRand(config.b, 1776);
50 RandomBitsDouble aRand((config.a? config.a: 1), 1789);
51 int thresh = 1;
53 r.passRGBA = true;
54 r.errRGBA = 0.0;
55 for (int i = 0; i < 100 && r.passRGBA; ++i) {
56 // Generate a random color and use it to clear the color buffer:
57 float expected[4];
58 expected[0] = rRand.next();
59 expected[1] = gRand.next();
60 expected[2] = bRand.next();
61 expected[3] = aRand.next();
62 glClearColor(expected[0],expected[1],expected[2],expected[3]);
63 glClear(GL_COLOR_BUFFER_BIT);
65 // If the color buffer doesn't have an alpha channel, then
66 // the spec requires the readback value to be 1.0:
67 if (!config.a)
68 expected[3] = 1.0;
70 // Read the buffer:
71 GLfloat buf[READPIX_SANITY_WIN_SIZE][READPIX_SANITY_WIN_SIZE][4];
72 glReadPixels(0, 0, READPIX_SANITY_WIN_SIZE,
73 READPIX_SANITY_WIN_SIZE, GL_RGBA, GL_FLOAT, buf);
75 // Now compute the error for each pixel, and record the
76 // worst one we find:
77 for (int y = 0; y < READPIX_SANITY_WIN_SIZE; ++y)
78 for (int x = 0; x < READPIX_SANITY_WIN_SIZE; ++x) {
79 GLfloat dr = abs(buf[y][x][0] - expected[0]);
80 GLfloat dg = abs(buf[y][x][1] - expected[1]);
81 GLfloat db = abs(buf[y][x][2] - expected[2]);
82 GLfloat da = abs(buf[y][x][3] - expected[3]);
83 double err =
84 max(ErrorBits(dr, config.r),
85 max(ErrorBits(dg, config.g),
86 max(ErrorBits(db, config.b),
87 ErrorBits(da,
88 config.a? config.a: thresh+1))));
89 // The "thresh+1" fudge above is
90 // needed to force the error to
91 // be greater than the threshold
92 // in the case where there is no
93 // alpha channel. Without it the
94 // error would be just equal to
95 // the threshold, and the test
96 // would spuriously pass.
97 if (err > r.errRGBA) {
98 r.xRGBA = x;
99 r.yRGBA = y;
100 r.errRGBA = err;
101 for (int j = 0; j < 4; ++j) {
102 r.expectedRGBA[j] = expected[j];
103 r.actualRGBA[j] = buf[y][x][j];
108 if (r.errRGBA > thresh)
109 r.passRGBA = false;
110 w.swap();
112 } // ReadPixSanityTest::checkRGBA
114 void
115 ReadPixSanityTest::checkDepth(ReadPixSanityResult& r, Window& w) {
116 DrawingSurfaceConfig& config = *r.config;
117 RandomDouble dRand(35798);
118 int thresh = 1;
120 r.passDepth = true;
121 r.errDepth = 0.0;
122 for (int i = 0; i < 100 && r.passDepth; ++i) {
123 // Generate a random depth and use it to clear the depth buffer:
124 GLdouble expected = dRand.next();
125 glClearDepth(expected);
126 glClear(GL_DEPTH_BUFFER_BIT);
128 // Because glReadPixels won't return data of type GLdouble,
129 // there's no straightforward portable way to deal with
130 // integer depth buffers that are deeper than 32 bits or
131 // floating-point depth buffers that have higher precision
132 // than a GLfloat. Since this is just a sanity check, we'll
133 // use integer readback and settle for 32 bits at best.
134 GLuint buf[READPIX_SANITY_WIN_SIZE][READPIX_SANITY_WIN_SIZE];
135 glReadPixels(0, 0, READPIX_SANITY_WIN_SIZE,
136 READPIX_SANITY_WIN_SIZE, GL_DEPTH_COMPONENT,
137 GL_UNSIGNED_INT, buf);
139 // Now compute the error for each pixel, and record the
140 // worst one we find:
141 for (int y = 0; y < READPIX_SANITY_WIN_SIZE; ++y)
142 for (int x = 0; x < READPIX_SANITY_WIN_SIZE; ++x) {
143 GLfloat dd = abs(buf[y][x]/4294967295.0
144 - expected);
145 double err = ErrorBits(dd, config.z);
146 if (err > r.errDepth) {
147 r.xDepth = x;
148 r.yDepth = y;
149 r.errDepth = err;
150 r.expectedDepth = expected;
151 r.actualDepth = buf[y][x]/4294967295.0;
155 if (r.errDepth > thresh)
156 r.passDepth = false;
157 w.swap();
159 } // ReadPixSanityTest::checkDepth
161 void
162 ReadPixSanityTest::checkStencil(ReadPixSanityResult& r, Window& w) {
163 DrawingSurfaceConfig& config = *r.config;
164 RandomBits sRand(config.s, 10101);
166 r.passStencil = true;
167 for (int i = 0; i < 100 && r.passStencil; ++i) {
168 GLuint expected = sRand.next();
169 glClearStencil(expected);
170 glClear(GL_STENCIL_BUFFER_BIT);
172 GLuint buf[READPIX_SANITY_WIN_SIZE][READPIX_SANITY_WIN_SIZE];
173 glReadPixels(0, 0, READPIX_SANITY_WIN_SIZE,
174 READPIX_SANITY_WIN_SIZE, GL_STENCIL_INDEX,
175 GL_UNSIGNED_INT, buf);
177 for (int y = 0; y < READPIX_SANITY_WIN_SIZE && r.passStencil;
178 ++y)
179 for (int x = 0; x < READPIX_SANITY_WIN_SIZE; ++x)
180 if (buf[y][x] != expected) {
181 r.passStencil = false;
182 r.xStencil = x;
183 r.yStencil = y;
184 r.expectedStencil = expected;
185 r.actualStencil = buf[y][x];
186 break;
189 w.swap();
191 } // ReadPixSanityTest::checkStencil
193 void
194 ReadPixSanityTest::checkIndex(ReadPixSanityResult& r, Window& w) {
195 DrawingSurfaceConfig& config = *r.config;
196 RandomBits iRand(config.bufSize, 2);
198 r.passIndex = true;
199 for (int i = 0; i < 100 && r.passIndex; ++i) {
200 GLuint expected = iRand.next();
201 glClearIndex(expected);
202 glClear(GL_COLOR_BUFFER_BIT);
204 GLuint buf[READPIX_SANITY_WIN_SIZE][READPIX_SANITY_WIN_SIZE];
205 glReadPixels(0, 0, READPIX_SANITY_WIN_SIZE,
206 READPIX_SANITY_WIN_SIZE, GL_COLOR_INDEX,
207 GL_UNSIGNED_INT, buf);
209 for (int y = 0; y < READPIX_SANITY_WIN_SIZE && r.passIndex; ++y)
210 for (int x = 0; x < READPIX_SANITY_WIN_SIZE; ++x)
211 if (buf[y][x] != expected) {
212 r.passIndex = false;
213 r.xIndex = x;
214 r.yIndex = y;
215 r.expectedIndex = expected;
216 r.actualIndex = buf[y][x];
217 break;
220 w.swap();
222 } // ReadPixSanityTest::checkIndex
224 ///////////////////////////////////////////////////////////////////////////////
225 // runOne: Run a single test case
226 ///////////////////////////////////////////////////////////////////////////////
227 void
228 ReadPixSanityTest::runOne(ReadPixSanityResult& r, GLEAN::Window& w) {
230 // Many (if not most) other tests need to read the contents of
231 // the framebuffer to determine if the correct image has been
232 // drawn. Obviously this is a waste of time if the basic
233 // functionality of glReadPixels isn't working.
235 // This test does a "sanity" check of glReadPixels. Using as
236 // little of the GL as practicable, it writes a random value
237 // in the framebuffer, reads it, and compares the value read
238 // with the value written.
240 glPixelStorei(GL_PACK_SWAP_BYTES, GL_FALSE);
241 glPixelStorei(GL_PACK_LSB_FIRST, GL_FALSE);
242 glPixelStorei(GL_PACK_ROW_LENGTH, 0);
243 glPixelStorei(GL_PACK_SKIP_ROWS, 0);
244 glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
245 glPixelStorei(GL_PACK_ALIGNMENT, 1);
247 glPixelTransferi(GL_MAP_COLOR, GL_FALSE);
248 glPixelTransferi(GL_MAP_STENCIL, GL_FALSE);
249 glPixelTransferi(GL_INDEX_SHIFT, 0);
250 glPixelTransferi(GL_INDEX_OFFSET, 0);
251 glPixelTransferf(GL_RED_SCALE, 1.0);
252 glPixelTransferf(GL_GREEN_SCALE, 1.0);
253 glPixelTransferf(GL_BLUE_SCALE, 1.0);
254 glPixelTransferf(GL_ALPHA_SCALE, 1.0);
255 glPixelTransferf(GL_DEPTH_SCALE, 1.0);
256 glPixelTransferf(GL_RED_BIAS, 0.0);
257 glPixelTransferf(GL_GREEN_BIAS, 0.0);
258 glPixelTransferf(GL_BLUE_BIAS, 0.0);
259 glPixelTransferf(GL_ALPHA_BIAS, 0.0);
260 glPixelTransferf(GL_DEPTH_BIAS, 0.0);
262 glDisable(GL_SCISSOR_TEST);
263 glDisable(GL_DITHER);
265 glIndexMask(~0);
266 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
267 glDepthMask(GL_TRUE);
268 glStencilMask(~0);
270 if (r.config->canRGBA)
271 checkRGBA(r, w);
272 if (r.config->z)
273 checkDepth(r, w);
274 if (r.config->s)
275 checkStencil(r, w);
277 r.pass = r.passRGBA & r.passDepth & r.passStencil & r.passIndex;
278 } // ReadPixSanityTest::runOne
280 ///////////////////////////////////////////////////////////////////////////////
281 // compareOne: Compare results for a single test case
282 ///////////////////////////////////////////////////////////////////////////////
283 void
284 ReadPixSanityTest::compareOne(ReadPixSanityResult& oldR, ReadPixSanityResult& newR) {
285 comparePassFail(oldR, newR);
286 summarize("RGBA: ", oldR.passRGBA, newR.passRGBA);
287 summarize("Depth: ", oldR.passDepth, newR.passDepth);
288 summarize("Stencil: ", oldR.passStencil, newR.passStencil);
289 summarize("Index: ", oldR.passIndex, newR.passIndex);
290 if (env->options.verbosity) {
291 if (!oldR.passRGBA && !newR.passRGBA) {
292 if (oldR.xRGBA != newR.xRGBA
293 || oldR.yRGBA != newR.yRGBA)
294 env->log << "\tRGBA: "
295 << env->options.db1Name
296 << " failed at ("
297 << oldR.xRGBA
298 << ", "
299 << oldR.yRGBA
300 << "); "
301 << env->options.db2Name
302 << " failed at ("
303 << newR.xRGBA
304 << ", "
305 << newR.yRGBA
306 << ").\n"
308 if (oldR.errRGBA != newR.errRGBA)
309 env->log << "\tRGBA: "
310 << env->options.db1Name
311 << " had "
312 << oldR.errRGBA
313 << " bits in error; "
314 << env->options.db2Name
315 << " had "
316 << newR.errRGBA
317 << " bits in error.\n"
320 if (!oldR.passDepth && !newR.passDepth) {
321 if (oldR.xDepth != newR.xDepth
322 || oldR.yDepth != newR.yDepth)
323 env->log << "\tDepth: "
324 << env->options.db1Name
325 << " failed at ("
326 << oldR.xDepth
327 << ", "
328 << oldR.yDepth
329 << "); "
330 << env->options.db2Name
331 << " failed at ("
332 << newR.xDepth
333 << ", "
334 << newR.yDepth
335 << ").\n"
337 if (oldR.errDepth != newR.errDepth)
338 env->log << "\tDepth: "
339 << env->options.db1Name
340 << " had "
341 << oldR.errDepth
342 << " bits in error; "
343 << env->options.db2Name
344 << " had "
345 << newR.errDepth
346 << " bits in error.\n"
349 if (!oldR.passStencil && !newR.passStencil) {
350 if (oldR.xStencil != newR.xStencil
351 || oldR.yStencil != newR.yStencil)
352 env->log << "\tStencil: "
353 << env->options.db1Name
354 << " failed at ("
355 << oldR.xStencil
356 << ", "
357 << oldR.yStencil
358 << "); "
359 << env->options.db2Name
360 << " failed at ("
361 << newR.xStencil
362 << ", "
363 << newR.yStencil
364 << ").\n"
367 if (!oldR.passIndex && !newR.passIndex) {
368 if (oldR.xIndex != newR.xIndex
369 || oldR.yIndex != newR.yIndex)
370 env->log << "\tIndex: "
371 << env->options.db1Name
372 << " failed at ("
373 << oldR.xIndex
374 << ", "
375 << oldR.yIndex
376 << "); "
377 << env->options.db2Name
378 << " failed at ("
379 << newR.xIndex
380 << ", "
381 << newR.yIndex
382 << ").\n"
386 } // ReadPixSanityTest::compareOne
388 void
389 ReadPixSanityTest::summarize(const char* label, bool oldPass, bool newPass) {
390 if (oldPass == newPass) {
391 if (env->options.verbosity)
392 env->log << "\t"
393 << label
394 << "both "
395 << (oldPass? "passed": "failed")
396 << ".\n";
397 } else {
398 env->log << "\t"
399 << label
400 << env->options.db1Name
401 << " "
402 << (oldPass? "passed": "failed")
403 << "; "
404 << env->options.db2Name
405 << " "
406 << (newPass? "passed": "failed")
407 << ".\n"
410 } // ReadPixSanityTest::summarize
412 void
413 ReadPixSanityTest::logOne(ReadPixSanityResult& r) {
414 logPassFail(r);
415 logConcise(r);
417 if (!r.passRGBA) {
418 env->log << "\tRGB(A) worst-case error was "
419 << r.errRGBA << " bits at ("
420 << r.xRGBA << ", " << r.yRGBA << ")\n";
421 env->log << "\t\texpected ("
422 << r.expectedRGBA[0] << ", "
423 << r.expectedRGBA[1] << ", "
424 << r.expectedRGBA[2] << ", "
425 << r.expectedRGBA[3] << ")\n\t\tgot ("
426 << r.actualRGBA[0] << ", "
427 << r.actualRGBA[1] << ", "
428 << r.actualRGBA[2] << ", "
429 << r.actualRGBA[3] << ")\n"
432 if (!r.passDepth) {
433 env->log << "\tDepth worst-case error was "
434 << r.errDepth << " bits at ("
435 << r.xDepth << ", " << r.yDepth << ")\n";
436 env->log << "\t\texpected "
437 << r.expectedDepth
438 << "; got "
439 << r.actualDepth
440 << ".\n"
443 if (!r.passStencil) {
444 env->log << "\tStencil expected "
445 << r.expectedStencil
446 << "; got "
447 << r.actualStencil
448 << ".\n"
451 if (!r.passIndex) {
452 env->log << "\tIndex expected "
453 << r.expectedIndex
454 << "; got "
455 << r.actualIndex
456 << ".\n"
459 if (env->options.verbosity) {
460 if (r.config->canRGBA)
461 env->log << "\tRGBA largest readback error was "
462 << r.errRGBA
463 << " bits\n";
464 if (r.config->z)
465 env->log << "\tDepth largest readback error was "
466 << r.errDepth
467 << " bits\n";
469 } // ReadPixSanityTest::logOne
471 ///////////////////////////////////////////////////////////////////////////////
472 // The test object itself:
473 ///////////////////////////////////////////////////////////////////////////////
474 ReadPixSanityTest
475 readPixSanityTest("readPixSanity", "1",
477 "This test performs a sanity check of glReadPixels, using as\n"
478 "few other portions of the GL as possible. If this test fails,\n"
479 "it may be pointless to run other tests, since so many of them\n"
480 "depend on reading the contents of the framebuffer to determine\n"
481 "if they pass.\n"
482 "\n"
483 "The test works by using glClear to fill the framebuffer with a\n"
484 "randomly-chosen value, reading the contents of the\n"
485 "framebuffer, and comparing the actual contents with the\n"
486 "expected contents. RGB, RGBA, color index, stencil, and depth\n"
487 "buffers (whichever are applicable to the current rendering\n"
488 "context) are checked. The test passes if the actual contents\n"
489 "are within 1 LSB of the expected contents.\n"
492 }; // namespace GLEAN
496 ////////////////////////////////////////////////////////////////////////////////
497 // ExactRGBATest
498 // Verifies that unsigned RGBA values written to a framebuffer with
499 // sufficient depth are not altered by the OpenGL implementation.
500 ////////////////////////////////////////////////////////////////////////////////
502 namespace {
504 // Mac OS header file AssertMacros.h defines check as a macro.
505 #ifdef check
506 #undef check
507 #endif
509 template<class T>
510 void
511 check(GLEAN::ExactRGBAResult::Flavor& r, GLEAN::DrawingSurfaceConfig& config,
512 GLenum type, int roundingMode) {
513 unsigned size = EXACT_RGBA_WIN_SIZE - 2;
514 unsigned nPixels = size * size;
515 unsigned nComponents = 4 * nPixels;
516 T* expected = new T[nComponents];
517 T* actual = new T[nComponents];
518 GLEAN::RandomBits rand(32, 1929);
519 unsigned x;
520 unsigned y;
521 T* p;
522 T* q;
524 // Draw random colors into the window, recording the raw
525 // color data in the array "expected":
526 p = expected;
527 for (y = 0; y < size; ++y)
528 for (x = 0; x < size; ++x) {
529 p[0] = rand.next(); // r
530 p[1] = rand.next(); // g
531 p[2] = rand.next(); // b
532 p[3] = rand.next(); // a
533 switch (type) {
534 case GL_UNSIGNED_BYTE:
535 glColor4ubv(reinterpret_cast<GLubyte*>
536 (p));
537 break;
538 case GL_UNSIGNED_SHORT:
539 glColor4usv(reinterpret_cast<GLushort*>
540 (p));
541 break;
542 case GL_UNSIGNED_INT:
543 glColor4uiv(reinterpret_cast<GLuint*>
544 (p));
545 break;
547 glBegin(GL_QUADS);
548 glVertex2i(x + 1, y + 1);
549 glVertex2i(x + 2, y + 1);
550 glVertex2i(x + 2, y + 2);
551 glVertex2i(x + 1, y + 2);
552 glEnd();
553 p += 4;
556 // Read the relevant contents of the window into the array
557 // "actual":
558 glReadPixels(1, 1, size, size, GL_RGBA, type, actual);
560 // Find masks that select only the high-order bits that should
561 // be common to both the host representation and the framebuffer
562 // representation:
563 int hostBits;
564 switch (type) {
565 case GL_UNSIGNED_BYTE:
566 hostBits = 8;
567 break;
568 case GL_UNSIGNED_SHORT:
569 hostBits = 16;
570 break;
571 case GL_UNSIGNED_INT:
572 hostBits = 32;
573 break;
575 T Mask[4];
576 Mask[0] = static_cast<T>(-1) << (hostBits - min(hostBits, config.r));
577 Mask[1] = static_cast<T>(-1) << (hostBits - min(hostBits, config.g));
578 Mask[2] = static_cast<T>(-1) << (hostBits - min(hostBits, config.b));
579 Mask[3] = static_cast<T>(-1) << (hostBits - min(hostBits, config.a));
580 // Patch up arithmetic for RGB drawing surfaces. All other nasty cases
581 // are eliminated by the drawing surface filter, which requires
582 // nonzero R, G, and B.
583 if (Mask[0] == static_cast<T>(-1))
584 Mask[0] = 0;
586 // Compare masked actual and expected values, and record the
587 // worst-case error location and magnitude.
588 r.err = 0;
589 p = expected;
590 q = actual;
591 for (y = 0; y < size; ++y)
592 for (x = 0; x < size; ++x) {
593 T e[4] = { p[0], p[1], p[2], p[3] };
594 T a[4] = { q[0], q[1], q[2], q[3] };
595 for (unsigned i = 0; i < 4; ++i) {
596 if (roundingMode == 0) {
597 // Follow the OpenGL spec to the letter
598 e[i] = e[i] & Mask[i];
599 a[i] = a[i] & Mask[i];
601 GLuint err =
602 max(e[i], a[i]) - min(e[i], a[i]);
603 if (roundingMode == 1) {
604 // Do the sane thing
605 if (err < ~Mask[i] / 2)
606 err = 0;
608 if (err > r.err) {
609 r.x = x;
610 r.y = y;
611 r.err = err;
612 for (unsigned j = 0; j < 4; ++j) {
613 r.expected[j] = e[j];
614 r.actual[j] = a[j];
618 p += 4;
619 q += 4;
622 // We only pass if the maximum error was zero.
623 r.pass = (r.err == 0);
625 delete[] expected;
626 delete[] actual;
632 namespace GLEAN {
635 ///////////////////////////////////////////////////////////////////////////////
636 // runOne: Run a single test case
637 ///////////////////////////////////////////////////////////////////////////////
638 void
639 ExactRGBATest::runOne(ExactRGBAResult& r, GLEAN::Window& w) {
641 // Many other tests depend on the ability of the OpenGL
642 // implementation to store fixed-point RGBA values in the
643 // framebuffer, and to read back exactly the value that
644 // was stored. The OpenGL spec guarantees that this will work
645 // under certain conditions, which are spelled out in section
646 // 2.13.9 in the 1.2.1 version of the spec:
648 // Suppose that lighting is disabled, the color associated
649 // with a vertex has not been clipped, and one of
650 // [gl]Colorub, [gl]Colorus, or [gl]Colorui was used to
651 // specify that color. When these conditions are
652 // satisfied, an RGBA component must convert to a value
653 // that matches the component as specified in the Color
654 // command: if m [the number of bits in the framebuffer
655 // color channel] is less than the number of bits b with
656 // which the component was specified, then the converted
657 // value must equal the most significant m bits of the
658 // specified value; otherwise, the most significant b bits
659 // of the converted value must equal the specified value.
661 // This test attempts to verify that behavior.
664 // Don't bother running if the ReadPixels sanity test for this
665 // display surface configuration failed:
666 vector<ReadPixSanityResult*>::const_iterator rpsRes;
667 for (rpsRes = readPixSanityTest.results.begin();
668 rpsRes != readPixSanityTest.results.end();
669 ++rpsRes)
670 if ((*rpsRes)->config == r.config)
671 break;
672 if (rpsRes == readPixSanityTest.results.end() || !(*rpsRes)->pass) {
673 r.skipped = true;
674 r.pass = false;
675 return;
678 // Hack: Make hardware driver tests feasible
679 // (One can debate the sanity of the spec requirement cited above,
680 // anyway. On the one hand, we don't want to remember which API call
681 // was used to set the color. This means that glColoru[b|s|i] must
682 // perform some conversion. The default language of the spec mandates
683 // that the maximum integer value always correspond to 1.0, which
684 // mandates rounding up of discarded bits. However, the language
685 // above mandates simply discarding those bits.)
686 int roundingMode = 0;
687 const char* s = getenv("GLEAN_EXACTRGBA_ROUNDING");
688 if (s) {
689 roundingMode = atoi(s);
690 env->log << "Note: Rounding mode changed to " << roundingMode << "\n";
693 // Much of this state should already be set, if the defaults are
694 // implemented correctly. We repeat the setting here in order
695 // to insure reasonable results when there are bugs.
697 GLUtils::useScreenCoords(EXACT_RGBA_WIN_SIZE, EXACT_RGBA_WIN_SIZE);
699 glDisable(GL_LIGHTING);
701 glFrontFace(GL_CCW);
703 glDisable(GL_COLOR_MATERIAL);
705 glDisable(GL_TEXTURE_1D);
706 glDisable(GL_TEXTURE_2D);
707 glDisable(GL_TEXTURE_3D);
709 glDisable(GL_CLIP_PLANE0);
710 glDisable(GL_CLIP_PLANE1);
711 glDisable(GL_CLIP_PLANE2);
712 glDisable(GL_CLIP_PLANE3);
713 glDisable(GL_CLIP_PLANE4);
714 glDisable(GL_CLIP_PLANE5);
716 glDisable(GL_FOG);
718 glDisable(GL_SCISSOR_TEST);
719 glDisable(GL_ALPHA_TEST);
720 glDisable(GL_STENCIL_TEST);
721 glDisable(GL_DEPTH_TEST);
722 glDisable(GL_BLEND);
723 glDisable(GL_DITHER);
724 glDisable(GL_COLOR_LOGIC_OP);
726 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
728 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
729 glDisable(GL_CULL_FACE);
730 glDisable(GL_POLYGON_STIPPLE);
731 glDisable(GL_POLYGON_OFFSET_FILL);
733 glShadeModel(GL_FLAT);
735 glPixelStorei(GL_PACK_SWAP_BYTES, GL_FALSE);
736 glPixelStorei(GL_PACK_LSB_FIRST, GL_FALSE);
737 glPixelStorei(GL_PACK_ROW_LENGTH, 0);
738 glPixelStorei(GL_PACK_SKIP_ROWS, 0);
739 glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
740 glPixelStorei(GL_PACK_ALIGNMENT, 1);
742 glPixelTransferi(GL_MAP_COLOR, GL_FALSE);
743 glPixelTransferi(GL_MAP_STENCIL, GL_FALSE);
744 glPixelTransferi(GL_INDEX_SHIFT, 0);
745 glPixelTransferi(GL_INDEX_OFFSET, 0);
746 glPixelTransferf(GL_RED_SCALE, 1.0);
747 glPixelTransferf(GL_GREEN_SCALE, 1.0);
748 glPixelTransferf(GL_BLUE_SCALE, 1.0);
749 glPixelTransferf(GL_ALPHA_SCALE, 1.0);
750 glPixelTransferf(GL_DEPTH_SCALE, 1.0);
751 glPixelTransferf(GL_RED_BIAS, 0.0);
752 glPixelTransferf(GL_GREEN_BIAS, 0.0);
753 glPixelTransferf(GL_BLUE_BIAS, 0.0);
754 glPixelTransferf(GL_ALPHA_BIAS, 0.0);
755 glPixelTransferf(GL_DEPTH_BIAS, 0.0);
757 check<GLubyte>(r.ub, *(r.config), GL_UNSIGNED_BYTE, roundingMode);
758 w.swap();
759 check<GLushort>(r.us, *(r.config), GL_UNSIGNED_SHORT, roundingMode);
760 w.swap();
761 check<GLuint>(r.ui, *(r.config), GL_UNSIGNED_INT, roundingMode);
762 w.swap();
763 r.pass = r.ub.pass && r.us.pass && r.ui.pass;
764 r.skipped = false;
765 } // ExactRGBATest::runOne
767 ///////////////////////////////////////////////////////////////////////////////
768 // compareOne: Compare results for a single test case
769 ///////////////////////////////////////////////////////////////////////////////
770 void
771 ExactRGBATest::compareOne(ExactRGBAResult& oldR, ExactRGBAResult& newR) {
772 if (oldR.skipped || newR.skipped) {
773 env->log << name
774 << ((oldR.skipped && newR.skipped)? ": SAME "
775 : ": DIFF ")
776 << newR.config->conciseDescription()
777 << '\n';
778 if (oldR.skipped)
779 env->log << "\t"
780 << env->options.db1Name
781 << " skipped\n";
782 if (newR.skipped)
783 env->log << "\t"
784 << env->options.db2Name
785 << " skipped\n";
786 env->log << "\tNo comparison is possible.\n";
787 return;
790 if (oldR.ub == newR.ub && oldR.us == newR.us && oldR.ui == newR.ui) {
791 if (env->options.verbosity)
792 env->log << name
793 << ": SAME "
794 << newR.config->conciseDescription()
795 << '\n'
796 << (oldR.pass
797 ? "\tBoth PASS\n"
798 : "\tBoth FAIL\n");
799 } else {
800 env->log << name
801 << ": DIFF "
802 << newR.config->conciseDescription()
803 << '\n'
804 #if 1
805 << '\t'
806 << env->options.db1Name
807 << (oldR.pass? " PASS, ": " FAIL, ")
808 << env->options.db2Name
809 << (newR.pass? " PASS\n": " FAIL\n");
810 #endif
814 summarize("Unsigned byte: ", oldR.ub, newR.ub);
815 summarize("Unsigned short: ", oldR.us, newR.us);
816 summarize("Unsigned int: ", oldR.ui, newR.ui);
817 } // ExactRGBATest::compareOne
819 void
820 ExactRGBATest::summarize(const char* label, const ExactRGBAResult::Flavor& o,
821 const ExactRGBAResult::Flavor& n) {
822 if (o == n) {
823 if (env->options.verbosity)
824 env->log << "\t"
825 << label
826 << "both "
827 << (o.pass? "passed": "failed")
828 << ".\n";
829 } else {
830 if (o.pass != n.pass)
831 env->log << "\t"
832 << label
833 << env->options.db1Name
834 << " "
835 << (o.pass? "passed": "failed")
836 << "; "
837 << env->options.db2Name
838 << " "
839 << (n.pass? "passed": "failed")
840 << ".\n"
842 if (o.x != n.x || o.y != n.y)
843 env->log << "\t"
844 << env->options.db1Name
845 << " failed at ("
846 << o.x
847 << ", "
848 << o.y
849 << "); "
850 << env->options.db2Name
851 << " failed at ("
852 << n.x
853 << ", "
854 << n.y
855 << ")\n"
857 if (o.err != n.err)
858 env->log << "\t"
859 << env->options.db1Name
860 << " had max error "
861 << o.err
862 << "; "
863 << env->options.db2Name
864 << " had max error "
865 << n.err
866 << "\n"
868 if (o.expected[0] != n.expected[0]
869 || o.expected[1] != n.expected[1]
870 || o.expected[2] != n.expected[2]
871 || o.expected[3] != n.expected[3])
872 env->log << "\tExpected values differ.\n";
873 if (o.actual[0] != n.actual[0]
874 || o.actual[1] != n.actual[1]
875 || o.actual[2] != n.actual[2]
876 || o.actual[3] != n.actual[3])
877 env->log << "\tActual values differ.\n";
879 } // ExactRGBATest::summarize
881 void
882 ExactRGBATest::logFlavor(const char* label, const ExactRGBAResult::Flavor& r) {
883 if (!r.pass) {
884 env->log << "\t"
885 << label
886 << " worst-case error was 0x"
887 << hex
888 << r.err << " at ("
889 << dec
890 << r.x << ", " << r.y << ")\n";
891 env->log << "\t\texpected (0x"
892 << hex
893 << r.expected[0] << ", 0x"
894 << r.expected[1] << ", 0x"
895 << r.expected[2] << ", 0x"
896 << r.expected[3] << ")\n\t\tgot (0x"
897 << r.actual[0] << ", 0x"
898 << r.actual[1] << ", 0x"
899 << r.actual[2] << ", 0x"
900 << r.actual[3] << ")\n"
901 << dec
904 } // ExactRGBATest::logFlavor
906 void
907 ExactRGBATest::logOne(ExactRGBAResult& r) {
908 if (r.skipped) {
909 env->log << name << ": NOTE ";
910 logConcise(r);
911 env->log << "\tTest skipped; prerequisite test "
912 << readPixSanityTest.name
913 << " failed or was not run\n";
914 return;
917 logPassFail(r);
918 logConcise(r);
920 logFlavor("Unsigned byte ", r.ub);
921 logFlavor("Unsigned short", r.us);
922 logFlavor("Unsigned int ", r.ui);
923 } // ExactRGBATest::logOne
925 ///////////////////////////////////////////////////////////////////////////////
926 // The test object itself:
927 ///////////////////////////////////////////////////////////////////////////////
928 Test* exactRGBATestPrereqs[] = {&readPixSanityTest, 0};
929 ExactRGBATest
930 exactRGBATest("exactRGBA", "rgb", exactRGBATestPrereqs,
932 "The OpenGL specification requires that under certain conditions\n"
933 "(e.g. lighting disabled, no clipping, no dithering, etc.) colors\n"
934 "specified as unsigned integers are represented *exactly* in the\n"
935 "framebuffer (up to the number of bits common to both the\n"
936 "original color and the framebuffer color channel). Several glean\n"
937 "tests depend on this behavior, so this test is a prerequisite for\n"
938 "them.\n"
939 "\n"
940 "This test works by drawing many small quadrilaterals whose\n"
941 "colors are specified by glColorub, glColorus, and glColorui;\n"
942 "reading back the resulting image; and comparing the colors read\n"
943 "back to the colors written. The high-order bits shared by the\n"
944 "source representation of the colors and the framebuffer\n"
945 "representation of the colors must agree exactly for the test to\n"
946 "pass.\n"
951 } // namespace GLEAN