1 // BEGIN_COPYRIGHT -*- glean -*-
3 // Copyright (C) 2001 Allen Akin All Rights Reserved.
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
14 // The above copyright notice and this permission notice shall be
15 // included in all copies or substantial portions of the
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.
29 // treadpix.cpp: implementation of ReadPixels tests
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);
55 for (int i
= 0; i
< 100 && r
.passRGBA
; ++i
) {
56 // Generate a random color and use it to clear the color buffer:
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:
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
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]);
84 max(ErrorBits(dr
, config
.r
),
85 max(ErrorBits(dg
, config
.g
),
86 max(ErrorBits(db
, config
.b
),
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
) {
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
)
112 } // ReadPixSanityTest::checkRGBA
115 ReadPixSanityTest::checkDepth(ReadPixSanityResult
& r
, Window
& w
) {
116 DrawingSurfaceConfig
& config
= *r
.config
;
117 RandomDouble
dRand(35798);
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
145 double err
= ErrorBits(dd
, config
.z
);
146 if (err
> r
.errDepth
) {
150 r
.expectedDepth
= expected
;
151 r
.actualDepth
= buf
[y
][x
]/4294967295.0;
155 if (r
.errDepth
> thresh
)
159 } // ReadPixSanityTest::checkDepth
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
;
179 for (int x
= 0; x
< READPIX_SANITY_WIN_SIZE
; ++x
)
180 if (buf
[y
][x
] != expected
) {
181 r
.passStencil
= false;
184 r
.expectedStencil
= expected
;
185 r
.actualStencil
= buf
[y
][x
];
191 } // ReadPixSanityTest::checkStencil
194 ReadPixSanityTest::checkIndex(ReadPixSanityResult
& r
, Window
& w
) {
195 DrawingSurfaceConfig
& config
= *r
.config
;
196 RandomBits
iRand(config
.bufSize
, 2);
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
) {
215 r
.expectedIndex
= expected
;
216 r
.actualIndex
= buf
[y
][x
];
222 } // ReadPixSanityTest::checkIndex
224 ///////////////////////////////////////////////////////////////////////////////
225 // runOne: Run a single test case
226 ///////////////////////////////////////////////////////////////////////////////
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
);
266 glColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
267 glDepthMask(GL_TRUE
);
270 if (r
.config
->canRGBA
)
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 ///////////////////////////////////////////////////////////////////////////////
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
301 << env
->options
.db2Name
308 if (oldR
.errRGBA
!= newR
.errRGBA
)
309 env
->log
<< "\tRGBA: "
310 << env
->options
.db1Name
313 << " bits in error; "
314 << env
->options
.db2Name
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
330 << env
->options
.db2Name
337 if (oldR
.errDepth
!= newR
.errDepth
)
338 env
->log
<< "\tDepth: "
339 << env
->options
.db1Name
342 << " bits in error; "
343 << env
->options
.db2Name
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
359 << env
->options
.db2Name
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
377 << env
->options
.db2Name
386 } // ReadPixSanityTest::compareOne
389 ReadPixSanityTest::summarize(const char* label
, bool oldPass
, bool newPass
) {
390 if (oldPass
== newPass
) {
391 if (env
->options
.verbosity
)
395 << (oldPass
? "passed": "failed")
400 << env
->options
.db1Name
402 << (oldPass
? "passed": "failed")
404 << env
->options
.db2Name
406 << (newPass
? "passed": "failed")
410 } // ReadPixSanityTest::summarize
413 ReadPixSanityTest::logOne(ReadPixSanityResult
& r
) {
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"
433 env
->log
<< "\tDepth worst-case error was "
434 << r
.errDepth
<< " bits at ("
435 << r
.xDepth
<< ", " << r
.yDepth
<< ")\n";
436 env
->log
<< "\t\texpected "
443 if (!r
.passStencil
) {
444 env
->log
<< "\tStencil expected "
452 env
->log
<< "\tIndex expected "
459 if (env
->options
.verbosity
) {
460 if (r
.config
->canRGBA
)
461 env
->log
<< "\tRGBA largest readback error was "
465 env
->log
<< "\tDepth largest readback error was "
469 } // ReadPixSanityTest::logOne
471 ///////////////////////////////////////////////////////////////////////////////
472 // The test object itself:
473 ///////////////////////////////////////////////////////////////////////////////
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"
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 ////////////////////////////////////////////////////////////////////////////////
498 // Verifies that unsigned RGBA values written to a framebuffer with
499 // sufficient depth are not altered by the OpenGL implementation.
500 ////////////////////////////////////////////////////////////////////////////////
504 // Mac OS header file AssertMacros.h defines check as a macro.
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);
524 // Draw random colors into the window, recording the raw
525 // color data in the array "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
534 case GL_UNSIGNED_BYTE
:
535 glColor4ubv(reinterpret_cast<GLubyte
*>
538 case GL_UNSIGNED_SHORT
:
539 glColor4usv(reinterpret_cast<GLushort
*>
542 case GL_UNSIGNED_INT
:
543 glColor4uiv(reinterpret_cast<GLuint
*>
548 glVertex2i(x
+ 1, y
+ 1);
549 glVertex2i(x
+ 2, y
+ 1);
550 glVertex2i(x
+ 2, y
+ 2);
551 glVertex2i(x
+ 1, y
+ 2);
556 // Read the relevant contents of the window into the array
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
565 case GL_UNSIGNED_BYTE
:
568 case GL_UNSIGNED_SHORT
:
571 case GL_UNSIGNED_INT
:
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))
586 // Compare masked actual and expected values, and record the
587 // worst-case error location and magnitude.
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
];
602 max(e
[i
], a
[i
]) - min(e
[i
], a
[i
]);
603 if (roundingMode
== 1) {
605 if (err
< ~Mask
[i
] / 2)
612 for (unsigned j
= 0; j
< 4; ++j
) {
613 r
.expected
[j
] = e
[j
];
622 // We only pass if the maximum error was zero.
623 r
.pass
= (r
.err
== 0);
635 ///////////////////////////////////////////////////////////////////////////////
636 // runOne: Run a single test case
637 ///////////////////////////////////////////////////////////////////////////////
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();
670 if ((*rpsRes
)->config
== r
.config
)
672 if (rpsRes
== readPixSanityTest
.results
.end() || !(*rpsRes
)->pass
) {
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");
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
);
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
);
718 glDisable(GL_SCISSOR_TEST
);
719 glDisable(GL_ALPHA_TEST
);
720 glDisable(GL_STENCIL_TEST
);
721 glDisable(GL_DEPTH_TEST
);
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
);
759 check
<GLushort
>(r
.us
, *(r
.config
), GL_UNSIGNED_SHORT
, roundingMode
);
761 check
<GLuint
>(r
.ui
, *(r
.config
), GL_UNSIGNED_INT
, roundingMode
);
763 r
.pass
= r
.ub
.pass
&& r
.us
.pass
&& r
.ui
.pass
;
765 } // ExactRGBATest::runOne
767 ///////////////////////////////////////////////////////////////////////////////
768 // compareOne: Compare results for a single test case
769 ///////////////////////////////////////////////////////////////////////////////
771 ExactRGBATest::compareOne(ExactRGBAResult
& oldR
, ExactRGBAResult
& newR
) {
772 if (oldR
.skipped
|| newR
.skipped
) {
774 << ((oldR
.skipped
&& newR
.skipped
)? ": SAME "
776 << newR
.config
->conciseDescription()
780 << env
->options
.db1Name
784 << env
->options
.db2Name
786 env
->log
<< "\tNo comparison is possible.\n";
790 if (oldR
.ub
== newR
.ub
&& oldR
.us
== newR
.us
&& oldR
.ui
== newR
.ui
) {
791 if (env
->options
.verbosity
)
794 << newR
.config
->conciseDescription()
802 << newR
.config
->conciseDescription()
806 << env
->options
.db1Name
807 << (oldR
.pass
? " PASS, ": " FAIL, ")
808 << env
->options
.db2Name
809 << (newR
.pass
? " PASS\n": " FAIL\n");
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
820 ExactRGBATest::summarize(const char* label
, const ExactRGBAResult::Flavor
& o
,
821 const ExactRGBAResult::Flavor
& n
) {
823 if (env
->options
.verbosity
)
827 << (o
.pass
? "passed": "failed")
830 if (o
.pass
!= n
.pass
)
833 << env
->options
.db1Name
835 << (o
.pass
? "passed": "failed")
837 << env
->options
.db2Name
839 << (n
.pass
? "passed": "failed")
842 if (o
.x
!= n
.x
|| o
.y
!= n
.y
)
844 << env
->options
.db1Name
850 << env
->options
.db2Name
859 << env
->options
.db1Name
863 << env
->options
.db2Name
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
882 ExactRGBATest::logFlavor(const char* label
, const ExactRGBAResult::Flavor
& r
) {
886 << " worst-case error was 0x"
890 << r
.x
<< ", " << r
.y
<< ")\n";
891 env
->log
<< "\t\texpected (0x"
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"
904 } // ExactRGBATest::logFlavor
907 ExactRGBATest::logOne(ExactRGBAResult
& r
) {
909 env
->log
<< name
<< ": NOTE ";
911 env
->log
<< "\tTest skipped; prerequisite test "
912 << readPixSanityTest
.name
913 << " failed or was not run\n";
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};
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"
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"