Add more structure constructor tests.
[piglit/hramrach.git] / tests / glean / tclipflat.cpp
blob6b35bb948e79f3d03870fb4ebf10cc589cb54086
1 // BEGIN_COPYRIGHT -*- glean -*-
2 //
3 // Copyright (C) 2009 VMware, Inc. 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 VMWARE 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 // Test that the correct provoking vertex is used when a tri/quad/polygon
31 // is clipped for glShadeModel(GL_FLAT).
33 // Test with glDrawArrays and glBegin/End. Test GL_CCW and GL_CW winding.
34 // Back-face polygon culling is enabled so if the winding order of any
35 // primitive is incorrect, nothing may be drawn.
37 // XXX We should also test with two-sided lighting.
39 // If GL_ARB/EXT_provoking_vertex is supported, that feature is tested as well.
41 // Author: Brian Paul
44 #include <cassert>
45 #include <cstring>
46 #include "tclipflat.h"
49 namespace GLEAN {
51 static PFNGLPROVOKINGVERTEXEXTPROC ProvokingVertex_func = NULL;
54 // Note: all correctly rendered tris/quad/polygons will be green.
55 // Any other color indicates that the wrong vertex color was used.
58 // GL_TRIANGLES: provoking vertex = last of tri
59 static const GLfloat TriVerts[6][5] =
61 // R G B X Y
62 { 1, 0, 0, -1, -1 },
63 { 0, 0, 1, 1, -1 },
64 { 0, 1, 0, 1, 1 }, // PV
66 { 0, 0, 1, 1, 1 },
67 { 1, 0, 0, -1, 1 },
68 { 0, 1, 0, -1, -1 } // PV
71 // GL_TRIANGLES: first provoking vertex
72 static const GLfloat TriVertsFirstPV[6][5] =
74 { 0, 1, 0, 1, 1 }, // PV
75 { 1, 0, 0, -1, -1 },
76 { 0, 0, 1, 1, -1 },
78 { 0, 1, 0, -1, -1 }, // PV
79 { 0, 0, 1, 1, 1 },
80 { 1, 0, 0, -1, 1 }
84 // GL_TRIANGLE_STRIP: provoking vertex = last of tri
85 static const GLfloat TriStripVerts[6][5] =
87 { 1, 0, 0, -1, -1 },
88 { 0, 0, 1, 1, -1 },
89 { 0, 1, 0, -1, 0 }, // PV
90 { 0, 1, 0, 1, 0 }, // PV
91 { 0, 1, 0, -1, 1 }, // PV
92 { 0, 1, 0, 1, 1 } // PV
95 // GL_TRIANGLE_STRIP: first provoking vertex
96 static const GLfloat TriStripVertsFirstPV[6][5] =
98 { 0, 1, 0, -1, -1 }, // PV
99 { 0, 1, 0, 1, -1 }, // PV
100 { 0, 1, 0, -1, 0 }, // PV
101 { 0, 1, 0, 1, 0 }, // PV
102 { 1, 0, 0, -1, 1 },
103 { 0, 0, 1, 1, 1 }
107 // GL_TRIANGLE_FAN: provoking vertex = last of tri
108 static const GLfloat TriFanVerts[4][5] =
110 { 1, 0, 0, -1, -1 },
111 { 0, 0, 1, 1, -1 },
112 { 0, 1, 0, 1, 1 }, // PV
113 { 0, 1, 0, -1, 1 } // PV
116 // GL_TRIANGLE_FAN: first provoking vertex
117 static const GLfloat TriFanVertsFirstPV[4][5] =
119 { 0, 0, 1, 1, -1 },
120 { 0, 1, 0, 1, 1 }, // PV
121 { 0, 1, 0, -1, 1 }, // PV
122 { 1, 0, 0, -1, -1 }
126 // GL_QUADS: provoking vertex = last of quad
127 static const GLfloat QuadVerts[4][5] =
129 { 1, 0, 0, -1, -1 },
130 { 0, 0, 1, 1, -1 },
131 { 1, 1, 0, 1, 1 },
132 { 0, 1, 0, -1, 1 } // PV
135 // GL_QUADS: first provoking vertex
136 static const GLfloat QuadVertsFirstPV[4][5] =
138 { 0, 1, 0, -1, 1 }, // PV
139 { 1, 0, 0, -1, -1 },
140 { 0, 0, 1, 1, -1 },
141 { 1, 1, 0, 1, 1 }
145 // GL_QUAD_STRIP: provoking vertex = last of quad
146 static const GLfloat QuadStripVerts[6][5] =
148 { 1, 0, 0, -1, -1 },
149 { 0, 0, 1, 1, -1 },
150 { 1, 1, 0, -1, 0 },
151 { 0, 1, 0, 1, 0 }, // PV
152 { 1, 1, 0, -1, 1 },
153 { 0, 1, 0, 1, 1 } // PV
156 // GL_QUAD_STRIP: first provoking vertex
157 static const GLfloat QuadStripVertsFirstPV[6][5] =
159 { 0, 1, 0, -1, -1 }, // PV
160 { 1, 1, 0, 1, -1 },
161 { 0, 1, 0, -1, 0 }, // PV
162 { 1, 0, 0, 1, 0 },
163 { 0, 0, 1, -1, 1 },
164 { 1, 0, 0, 1, 1 }
168 // GL_POLYGON: provoking vertex = first vertex
169 static const GLfloat PolygonVerts[4][5] =
171 { 0, 1, 0, -1, -1 }, // PV
172 { 1, 0, 0, 1, -1 },
173 { 0, 0, 1, 1, 1 },
174 { 1, 1, 0, -1, 1 }
178 #define Elements(array) (sizeof(array) / sizeof(array[0]))
181 enum draw_mode {
182 BEGIN_END,
183 DRAW_ARRAYS,
184 DRAW_ELEMENTS,
185 NUM_DRAW_MODES
189 ClipFlatResult::ClipFlatResult()
191 pass = false;
195 void
196 ClipFlatTest::setup(void)
198 glDisable(GL_DITHER);
200 glMatrixMode(GL_PROJECTION);
201 glLoadIdentity();
202 glOrtho(-1.25, 1.25, -1.25, 1.25, -1, 1);
203 glMatrixMode(GL_MODELVIEW);
204 glLoadIdentity();
206 glShadeModel(GL_FLAT);
207 glPixelStorei(GL_PACK_ALIGNMENT, 1);
209 glFrontFace(GL_CW);
210 glCullFace(GL_FRONT);
211 glEnable(GL_CULL_FACE);
213 if (GLUtils::haveExtension("GL_ARB_provoking_vertex")) {
214 ProvokingVertex_func = reinterpret_cast<PFNGLPROVOKINGVERTEXPROC>
215 (GLUtils::getProcAddress("glProvokingVertex"));
216 provoking_vertex_first = true;
218 else if (GLUtils::haveExtension("GL_EXT_provoking_vertex")) {
219 ProvokingVertex_func = reinterpret_cast<PFNGLPROVOKINGVERTEXEXTPROC>
220 (GLUtils::getProcAddress("glProvokingVertexEXT"));
221 provoking_vertex_first = true;
224 if (provoking_vertex_first) {
225 GLboolean k;
226 glGetBooleanv(GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT, &k);
227 quads_follows_pv_convention = k;
232 // Draw with glDrawArrays()
233 void
234 ClipFlatTest::drawArrays(GLenum mode, const GLfloat *verts, GLuint count)
236 glColorPointer(3, GL_FLOAT, 5 * sizeof(GLfloat), verts + 0);
237 glVertexPointer(2, GL_FLOAT, 5 * sizeof(GLfloat), verts + 3);
238 glEnableClientState(GL_COLOR_ARRAY);
239 glEnableClientState(GL_VERTEX_ARRAY);
241 glDrawArrays(mode, 0, count);
243 glDisableClientState(GL_COLOR_ARRAY);
244 glDisableClientState(GL_VERTEX_ARRAY);
248 // Draw with glDrawElements()
249 void
250 ClipFlatTest::drawElements(GLenum mode, const GLfloat *verts, GLuint count)
252 static const GLuint elements[6] = { 0, 1, 2, 3, 4, 5 };
253 glColorPointer(3, GL_FLOAT, 5 * sizeof(GLfloat), verts + 0);
254 glVertexPointer(2, GL_FLOAT, 5 * sizeof(GLfloat), verts + 3);
255 glEnableClientState(GL_COLOR_ARRAY);
256 glEnableClientState(GL_VERTEX_ARRAY);
258 assert(count <= Elements(elements));
260 glDrawElements(mode, count, GL_UNSIGNED_INT, elements);
262 glDisableClientState(GL_COLOR_ARRAY);
263 glDisableClientState(GL_VERTEX_ARRAY);
267 // Draw with glBegin/End()
268 void
269 ClipFlatTest::drawBeginEnd(GLenum mode, const GLfloat *verts, GLuint count)
271 GLuint i;
273 glBegin(mode);
274 for (i = 0; i < count; i++) {
275 glColor3fv(verts + i * 5);
276 glVertex2fv(verts + i * 5 + 3);
278 glEnd();
282 // Read pixels and check pixels. All pixels should be green or black.
283 // Any other color indicates a failure.
284 bool
285 ClipFlatTest::checkResult(Window &w, GLfloat badColor[3])
287 GLubyte image[windowSize * windowSize * 3];
288 GLuint i, j;
289 GLboolean anyGreen = GL_FALSE;
291 badColor[0] = badColor[1] = badColor[2] = 0.0f;
293 glReadPixels(0, 0, windowSize, windowSize,
294 GL_RGB, GL_UNSIGNED_BYTE, image);
296 w.swap();
298 for (i = 0; i < windowSize; i++) {
299 for (j = 0; j < windowSize; j++) {
300 GLuint k = (i * windowSize + j) * 3;
302 if (image[k + 0] == 0 &&
303 image[k + 1] == 0 &&
304 image[k + 2] == 0) {
305 // black - OK
307 else if (image[k + 0] == 0 &&
308 image[k + 1] >= 254 &&
309 image[k + 0] == 0) {
310 // green - OK
311 anyGreen = GL_TRUE;
313 else {
314 // any other color = failure
315 badColor[0] = image[k + 0] / 255.0;
316 badColor[1] = image[k + 1] / 255.0;
317 badColor[2] = image[k + 2] / 255.0;
318 // sleep(10);
319 return false;
323 return anyGreen;
327 void
328 ClipFlatTest::reportFailure(GLenum mode, int drawMode, GLuint facing,
329 GLuint fill,
330 const GLfloat badColor[3], GLfloat x, GLfloat y)
332 const char *m, *d, *f, *p;
334 switch (mode) {
335 case GL_TRIANGLES:
336 m = "GL_TRIANGLES";
337 break;
338 case GL_TRIANGLE_STRIP:
339 m = "GL_TRIANGLE_STRIP";
340 break;
341 case GL_TRIANGLE_FAN:
342 m = "GL_TRIANGLE_FAN";
343 break;
344 case GL_QUADS:
345 m = "GL_QUADS";
346 break;
347 case GL_QUAD_STRIP:
348 m = "GL_QUAD_STRIP";
349 break;
350 case GL_POLYGON:
351 m = "GL_POLYGON";
352 break;
353 default:
354 m = "???";
357 switch (drawMode) {
358 case BEGIN_END:
359 d = "glBegin/End";
360 break;
361 case DRAW_ARRAYS:
362 d = "glDrawArrays";
363 break;
364 case DRAW_ELEMENTS:
365 d = "glDrawElements";
366 break;
367 default:
368 assert(0);
371 if (facing == 0)
372 f = "GL_CCW";
373 else
374 f = "GL_CW";
376 if (fill == 0)
377 p = "GL_FILL";
378 else
379 p = "GL_LINE";
381 env->log << name << ": Failure for "
382 << d << "(" << m << "), glFrontFace(" << f
383 << "), glPolygonMode(" << p << ")\n";
385 env->log << "\tTranslation: " << x << ", " << y << "\n";
387 if (testing_first_pv)
388 env->log << "\tGL_EXT_provoking_vertex test: GL_FIRST_VERTEX_CONVENTION_EXT mode\n";
390 env->log << "\tExpected color (0, 1, 0) but found ("
391 << badColor[0] << ", "
392 << badColor[1] << ", "
393 << badColor[2] << ")\n";
397 // Test drawing/clipping at nine positions of which 8 will be clipped.
398 bool
399 ClipFlatTest::testPositions(Window &w, GLenum mode,
400 const GLfloat *verts, GLuint count)
402 GLfloat x, y;
403 GLuint facing, fill;
404 int drawMode;
406 // Loop over polygon mode: filled vs. outline
407 for (fill = 0; fill < 2; fill++) {
409 glPolygonMode(GL_FRONT_AND_BACK, fill ? GL_LINE : GL_FILL);
411 // Loop over drawing mode: glBegin/End vs glDrawArrays vs glDrawElements
412 for (drawMode = 0; drawMode < NUM_DRAW_MODES; drawMode++) {
414 // Loop over CW vs. CCW winding (should make no difference)
415 for (facing = 0; facing < 2; facing++) {
417 if (facing == 0) {
418 glFrontFace(GL_CCW);
419 glCullFace(GL_BACK);
421 else {
422 glFrontFace(GL_CW);
423 glCullFace(GL_FRONT);
426 // Position the geometry at 9 different locations to test
427 // clipping against the left, right, bottom and top edges of
428 // the window.
429 // Only the center location will be unclipped.
430 for (y = -1.0; y <= 1.0; y += 1.0) {
431 for (x = -1.0; x <= 1.0; x += 1.0) {
432 glPushMatrix();
433 glTranslatef(x, y, 0.0);
435 glClear(GL_COLOR_BUFFER_BIT);
437 switch (drawMode) {
438 case BEGIN_END:
439 drawBeginEnd(mode, verts, count);
440 break;
441 case DRAW_ARRAYS:
442 drawArrays(mode, verts, count);
443 break;
444 case DRAW_ELEMENTS:
445 drawElements(mode, verts, count);
446 break;
447 default:
448 assert(0);
451 glPopMatrix();
453 GLfloat badColor[3];
454 if (!checkResult(w, badColor)) {
455 reportFailure(mode, drawMode, facing, fill, badColor, x, y);
456 glFlush();
457 //sleep(25); // enable for debugging
458 return false;
460 //usleep(50000); // enable for debugging
466 return true;
470 void
471 ClipFlatTest::runOne(ClipFlatResult &r, Window &w)
473 setup();
475 testing_first_pv = false;
476 r.pass = true;
478 if (r.pass)
479 r.pass = testPositions(w, GL_TRIANGLES,
480 (GLfloat *) TriVerts,
481 Elements(TriVerts));
483 if (r.pass)
484 r.pass = testPositions(w, GL_TRIANGLE_STRIP,
485 (GLfloat *) TriStripVerts,
486 Elements(TriStripVerts));
488 if (r.pass)
489 r.pass = testPositions(w, GL_TRIANGLE_FAN,
490 (GLfloat *) TriFanVerts,
491 Elements(TriFanVerts));
493 if (r.pass)
494 r.pass = testPositions(w, GL_QUADS,
495 (GLfloat *) QuadVerts,
496 Elements(QuadVerts));
498 if (r.pass)
499 r.pass = testPositions(w, GL_QUAD_STRIP,
500 (GLfloat *) QuadStripVerts,
501 Elements(QuadStripVerts));
503 if (r.pass)
504 r.pass = testPositions(w, GL_POLYGON,
505 (GLfloat *) PolygonVerts,
506 Elements(PolygonVerts));
508 if (provoking_vertex_first) {
509 ProvokingVertex_func(GL_FIRST_VERTEX_CONVENTION_EXT);
510 testing_first_pv = true;
512 if (r.pass)
513 r.pass = testPositions(w, GL_TRIANGLES,
514 (GLfloat *) TriVertsFirstPV,
515 Elements(TriVertsFirstPV));
517 if (r.pass)
518 r.pass = testPositions(w, GL_TRIANGLE_STRIP,
519 (GLfloat *) TriStripVertsFirstPV,
520 Elements(TriStripVertsFirstPV));
522 if (r.pass)
523 r.pass = testPositions(w, GL_TRIANGLE_FAN,
524 (GLfloat *) TriFanVertsFirstPV,
525 Elements(TriFanVertsFirstPV));
527 if (r.pass) {
528 if (quads_follows_pv_convention)
529 r.pass = testPositions(w, GL_QUADS,
530 (GLfloat *) QuadVertsFirstPV,
531 Elements(QuadVertsFirstPV));
532 else
533 r.pass = testPositions(w, GL_QUADS,
534 (GLfloat *) QuadVerts,
535 Elements(QuadVerts));
538 if (r.pass) {
539 if (quads_follows_pv_convention)
540 r.pass = testPositions(w, GL_QUAD_STRIP,
541 (GLfloat *) QuadStripVertsFirstPV,
542 Elements(QuadStripVertsFirstPV));
543 else
544 r.pass = testPositions(w, GL_QUAD_STRIP,
545 (GLfloat *) QuadStripVerts,
546 Elements(QuadStripVerts));
549 if (r.pass) {
550 r.pass = testPositions(w, GL_POLYGON,
551 (GLfloat *) PolygonVerts,
552 Elements(PolygonVerts));
558 void
559 ClipFlatTest::logOne(ClipFlatResult &r)
561 logPassFail(r);
562 logConcise(r);
566 void
567 ClipFlatTest::compareOne(ClipFlatResult &oldR,
568 ClipFlatResult &newR)
570 comparePassFail(oldR, newR);
574 void
575 ClipFlatResult::putresults(ostream &s) const
577 if (pass) {
578 s << "PASS\n";
580 else {
581 s << "FAIL\n";
586 bool
587 ClipFlatResult::getresults(istream &s)
589 char result[1000];
590 s >> result;
592 if (strcmp(result, "FAIL") == 0) {
593 pass = false;
595 else {
596 pass = true;
598 return s.good();
602 // The test object itself:
603 ClipFlatTest newTest("clipFlat", "window, rgb",
605 "Test clipping with flat shading (provoking vertex).\n");
609 } // namespace GLEAN