Add more structure constructor tests.
[piglit/hramrach.git] / tests / glean / ttexgen.cpp
blobe81c2a5b2b510393d492f77fccf332b30315c642
1 // BEGIN_COPYRIGHT -*- glean -*-
2 //
3 // Copyright (C) 1999 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:
13 //
14 // The above copyright notice and this permission notice shall be
15 // included in all copies or substantial portions of the
16 // Software.
17 //
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.
26 //
27 // END_COPYRIGHT
30 // ttexgen.cpp: Basic test of GL texture coordinate generation.
31 // This test does a basic test of the glTexGen functions, including
32 // object_linear, eye_linear, and sphere_map. We use the Sphere3D with
33 // a GeomRenderer to draw a sphere, and map a check texture onto it. We
34 // use an ortho projection to keep it simple. The result should be a 1:1
35 // mapping of the check texture for all three modes (sphere map maps 1:1
36 // because mapping it onto a sphere inverts the spheremap math).
38 // Note that accuracy issues might cause this test to fail if the
39 // texcoords near the center are a little warped; I've specifically tried
40 // to keep the matrices as "pure" as possible (no rotations) to
41 // keep the numerical precision high. So far it seems to work fine.
42 // Introducing a rotation by 90 degrees about the x axis resulted,
43 // on one driver, in a warping at the center of the sphere which caused
44 // the test to fail.
46 // For the second test of the three, we offset the texture by 0.5,
47 // so that each test's rendering is visually distinct from the
48 // previous.
50 // To test for pass/fail we examine the color buffer for red and blue,
51 // (the check colors) in the appropriate places.
53 // Author: Brian Sharp (brian@maniacal.org) December 2000
55 #include "ttexgen.h"
56 #include <stdio.h>
57 #include "geomutil.h"
60 const GLuint viewSize=50;
63 namespace GLEAN {
65 void
66 TexgenTest::FailMessage(BasicResult &r, const std::string& texgenMode,
67 GeomRenderer::DrawMethod method, bool arraysCompiled,
68 int retainedMode,
69 const std::string& colorMismatch) const {
70 env->log << name << ": FAIL "
71 << r.config->conciseDescription() << '\n';
72 env->log << "\t" << "during mode " << texgenMode << ", ";
73 switch(method)
75 case GeomRenderer::GLVERTEX_MODE: env->log << "glVertex-style rendering, "; break;
76 case GeomRenderer::GLARRAYELEMENT_MODE: env->log << "glArrayElement-style rendering, "; break;
77 case GeomRenderer::GLDRAWELEMENTS_MODE: env->log << "glDrawElements-style rendering, "; break;
78 case GeomRenderer::GLDRAWARRAYS_MODE: env->log << "glDrawArrays-style rendering, "; break;
80 if (arraysCompiled) env->log << "arrays locked, ";
81 else env->log << "arrays not locked, ";
83 if (retainedMode) env->log << "built into a display list, ";
84 else env->log << "called immediately (not display listed), ";
86 env->log << colorMismatch << std::endl;
89 bool
90 TexgenTest::compareColors(GLfloat* color0, GLfloat* color1, std::string& failureInfo) const {
92 // Compare the colors; fail and report why if they don't match.
93 if (color0[0] != color1[0] || color0[1] != color1[1] || color0[2] != color1[2])
95 // Assemble the error message into a C-string, then hand it back in the string.
96 char failureOut[1024];
97 sprintf(failureOut, "expected [%f,%f,%f], read back [%f,%f,%f]",
98 color0[0], color0[1], color0[2],
99 color1[0], color1[1], color1[2]);
101 failureInfo = std::string(failureOut);
102 return false;
105 return true;
108 bool
109 TexgenTest::verifyCheckers(GLfloat* pixels, GLfloat* upperLeftColor, GLfloat* upperRightColor, std::string& failureInfo) const {
111 // My loop control variable, since gcc and MSVC do things differently.
112 GLint samp;
114 // It's a viewSize x viewSize pixel block; since we drew a sphere that doesn't quite touch the
115 // edges, we need to be careful not to sample from what should be background.
116 // These pairs are hand-picked coordinates on the image that fall on the bottom-left quadrant
117 // of the sphere.
118 // XXX FIX ME: these sample coordinates assume that viewSize == 50.
119 GLuint samples[6][2] = {{13,13}, {4,22}, {22,4}, {20,20}, {20,10}, {10,20}};
121 // Run through those sample points in the bottom-left corner and make sure they're all the right color.
122 for (samp=0; samp<6; samp++)
124 GLuint sampleOffset = (samples[samp][0] + (viewSize*samples[samp][1]))*3;
125 if (!compareColors(upperRightColor, pixels + sampleOffset, failureInfo))
127 return false;
131 // Run through those sample points in the bottom-right corner and make sure they're all the right color.
132 // Note the "viewSize - samples[samp][0]" to flip it to the bottom-right quadrant.
133 for (samp=0; samp<6; samp++)
135 GLuint sampleOffset = ((viewSize - samples[samp][0]) + (viewSize*samples[samp][1]))*3;
136 if (!compareColors(upperLeftColor, pixels + sampleOffset, failureInfo))
138 return false;
142 // Run through those sample points in the upper-right corner and make sure they're all the right color.
143 for (samp=0; samp<6; samp++)
145 GLuint sampleOffset = ((viewSize - samples[samp][0]) + (viewSize*(viewSize - samples[samp][1])))*3;
146 if (!compareColors(upperRightColor, pixels + sampleOffset, failureInfo))
148 return false;
152 // Run through those sample points in the upper-left corner and make sure they're all the right color.
153 for (samp=0; samp<6; samp++)
155 GLuint sampleOffset = (samples[samp][0] + (viewSize*(viewSize - samples[samp][1])))*3;
156 if (!compareColors(upperLeftColor, pixels + sampleOffset, failureInfo))
158 return false;
162 return true;
166 ///////////////////////////////////////////////////////////////////////////////
167 // runOne: Run a single test case
168 ///////////////////////////////////////////////////////////////////////////////
169 void
170 TexgenTest::runOne(BasicResult& r, Window&) {
172 // Temporary buffer to store pixels we've read back for verification.
173 GLfloat pixels[50*50*3];
175 // Colors for matching against when we readback pixels.
176 GLfloat matchBlue[3] = {0,0,1};
177 GLfloat matchRed[3] = {1,0,0};
179 // A sphere to draw.
180 Sphere3D theSphere(9.9, 32, 16);
182 // A GeomRenderer to draw it with.
183 GeomRenderer sphereRenderer;
184 sphereRenderer.setDrawMethod(GeomRenderer::GLVERTEX_MODE);
185 sphereRenderer.setParameterBits(GeomRenderer::NORMAL_BIT);
186 sphereRenderer.setVArrayIndices(theSphere.getNumIndices(),GL_UNSIGNED_INT,theSphere.getIndices());
187 sphereRenderer.setVertexPointer(theSphere.getNumVertices(), 3, GL_FLOAT, 0, theSphere.getVertices());
188 sphereRenderer.setNormalPointer(GL_FLOAT, 0, theSphere.getNormals());
190 // draw the sphere in a 50x50 pixel window for some precision.
191 glViewport(0, 0, 50, 50);
193 // Basic GL setup.
194 glDisable(GL_DITHER);
195 glEnable(GL_CULL_FACE);
196 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
197 glColor3f(1,1,1);
199 // Setup the projection.
200 glMatrixMode(GL_PROJECTION);
201 glLoadIdentity();
202 glOrtho(-10,10,-10,10,-10,10);
203 glMatrixMode(GL_MODELVIEW);
204 glLoadIdentity();
206 // Set up our texture.
207 glEnable(GL_TEXTURE_2D);
208 GLuint checkerTextureHandle;
209 glGenTextures(1, &checkerTextureHandle);
210 glBindTexture(GL_TEXTURE_2D, checkerTextureHandle);
212 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
213 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
214 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
215 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
216 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
217 glEnable(GL_TEXTURE_GEN_S);
218 glEnable(GL_TEXTURE_GEN_T);
220 // Make a little checker texture.
221 unsigned char redBlueCheck[256*256*3];
222 for (int x=0; x<256; x++)
224 for (int y=0; y<256; y++)
226 bool xPastHalf = x >= 128;
227 bool yPastHalf = y >= 128;
229 redBlueCheck[(x+(256*y))*3 + 0] = ((xPastHalf && yPastHalf) || (!xPastHalf && !yPastHalf)) ? 255 : 0;
230 redBlueCheck[(x+(256*y))*3 + 1] = 0;
231 redBlueCheck[(x+(256*y))*3 + 2] = ((xPastHalf && !yPastHalf) || (!xPastHalf && yPastHalf)) ? 255 : 0;
234 gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, 256, 256, GL_RGB, GL_UNSIGNED_BYTE, redBlueCheck);
236 // Setup our arrays of configuration info; we loop over the rendering pass a number of times,
237 // using a different GL primitive path each time.
238 GeomRenderer::DrawMethod drawMethods[] = {GeomRenderer::GLVERTEX_MODE, GeomRenderer::GLARRAYELEMENT_MODE,
239 GeomRenderer::GLDRAWELEMENTS_MODE, GeomRenderer::GLARRAYELEMENT_MODE,
240 GeomRenderer::GLDRAWELEMENTS_MODE};
242 bool arraysCompiled[] = {false, false, false, true, true};
244 // Iterate once for all immediate mode styles, then once for retained mode styles.
245 for (int retainedMode=0; retainedMode<2; retainedMode++)
247 for (int testIteration=0; testIteration<5; testIteration++)
249 sphereRenderer.setDrawMethod(drawMethods[testIteration]);
250 if (!sphereRenderer.setArraysCompiled(arraysCompiled[testIteration]))
252 // We don't have the extension... not sure what we should do.
253 // May as well just keep going, it's no big deal (it should still
254 // yield correct results, of course, it's just redundant).
257 // GL_SPHERE_MAP: with spheremap, the UL corner is blue
258 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
259 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
261 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
262 renderSphere(retainedMode, sphereRenderer);
263 glReadPixels(0,0,50,50, GL_RGB, GL_FLOAT, pixels);
265 // Validate it.
266 std::string sphereMapResult;
267 if (!verifyCheckers(pixels, matchBlue, matchRed, sphereMapResult))
269 FailMessage(r, std::string("GL_SPHERE_MAP"), drawMethods[testIteration],
270 arraysCompiled[testIteration], retainedMode, sphereMapResult);
271 r.pass = false;
272 glDeleteTextures(1, &checkerTextureHandle);
273 return;
276 // GL_OBJECT_LINEAR: with object linear and the below planes, the UL corner is red.
277 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
278 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
279 float sObjPlane[4] = {0,0.05,0,1.5}; // We flip the checker by setting W to 1.5 (phases by half a period)
280 float tObjPlane[4] = {0.05,0,0,1};
281 glTexGenfv(GL_S, GL_OBJECT_PLANE, sObjPlane);
282 glTexGenfv(GL_T, GL_OBJECT_PLANE, tObjPlane);
284 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
285 renderSphere(retainedMode, sphereRenderer);
286 glReadPixels(0,0,50,50, GL_RGB, GL_FLOAT, pixels);
288 // Validate it.
289 std::string objectLinearResult;
290 if (!verifyCheckers(pixels, matchRed, matchBlue, objectLinearResult))
292 FailMessage(r, std::string("GL_OBJECT_LINEAR"), drawMethods[testIteration],
293 arraysCompiled[testIteration], retainedMode, objectLinearResult);
294 r.pass = false;
295 glDeleteTextures(1, &checkerTextureHandle);
296 return;
299 // GL_EYE_LINEAR: with eye linear and the below planes, the UL corner is blue.
300 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
301 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
302 float sEyePlane[4] = {0,0.05,0,1};
303 float tEyePlane[4] = {0.05,0,0,1};
304 glTexGenfv(GL_S, GL_EYE_PLANE, sEyePlane);
305 glTexGenfv(GL_T, GL_EYE_PLANE, tEyePlane);
307 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
308 renderSphere(retainedMode, sphereRenderer);
309 glReadPixels(0,0,50,50, GL_RGB, GL_FLOAT, pixels);
311 // Validate it.
312 std::string eyeLinearResult;
313 if (!verifyCheckers(pixels, matchBlue, matchRed, eyeLinearResult))
315 FailMessage(r, std::string("GL_EYE_LINEAR"), drawMethods[testIteration],
316 arraysCompiled[testIteration], retainedMode, eyeLinearResult);
317 r.pass = false;
318 glDeleteTextures(1, &checkerTextureHandle);
319 return;
324 // success
325 r.pass = true;
326 } // TexgenTest::runOne
328 ///////////////////////////////////////////////////////////////////////////////
329 // logOne: Log a single test case
330 ///////////////////////////////////////////////////////////////////////////////
331 void
332 TexgenTest::logOne(BasicResult& r) {
333 if (r.pass) {
334 logPassFail(r);
335 logConcise(r);
337 } // TexgenTest::logOne
339 void
340 TexgenTest::renderSphere(int retainedMode, GeomRenderer& sphereRenderer)
342 bool result;
343 if (retainedMode)
345 GLint displayList;
346 result = sphereRenderer.generateDisplayList(GL_TRIANGLES, displayList);
347 assert(result);
348 glCallList(displayList);
349 glDeleteLists(displayList, 1);
351 else
353 result = sphereRenderer.renderPrimitives(GL_TRIANGLES);
354 assert(result);
356 } // TexgenTest::renderSphere
359 ///////////////////////////////////////////////////////////////////////////////
360 // The test object itself:
361 ///////////////////////////////////////////////////////////////////////////////
362 TexgenTest texgenTest("texgen", "window, rgb",
364 "This test verifies that the three basic OpenGL texture coordinate\n"
365 "modes: object_linear, eye_linear, and sphere_map, work for a simple\n"
366 "case.\n");
369 } // namespace GLEAN