Add more structure constructor tests.
[piglit/hramrach.git] / tests / glean / tfragprog1.cpp
blob88369454c6dbad7cbc5b710aaf683f656385957f
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
29 // tfragprog.cpp: Test GL_ARB_fragment_program extension.
30 // Brian Paul 22 October 2005
32 // This is pretty simple. Specific fragment programs are run, we read back
33 // the framebuffer color and compare the color to the expected result.
34 // Pretty much any fragment program can be tested in the manner.
35 // Ideally, an additional fragment program test should be developed which
36 // exhaustively tests instruction combinations with all the various swizzle
37 // and masking options, etc.
38 // But this test is good for regression testing to be sure that particular or
39 // unique programs work correctly.
41 #include <cstdlib>
42 #include <cstring>
43 #include <cassert>
44 #include <cmath>
45 #include <math.h>
46 #include "tfragprog1.h"
49 namespace GLEAN {
52 static PFNGLPROGRAMLOCALPARAMETER4FVARBPROC glProgramLocalParameter4fvARB_func;
53 static PFNGLGENPROGRAMSARBPROC glGenProgramsARB_func;
54 static PFNGLPROGRAMSTRINGARBPROC glProgramStringARB_func;
55 static PFNGLBINDPROGRAMARBPROC glBindProgramARB_func;
56 static PFNGLISPROGRAMARBPROC glIsProgramARB_func;
57 static PFNGLDELETEPROGRAMSARBPROC glDeleteProgramsARB_func;
58 static PFNGLGETPROGRAMIVARBPROC glGetProgramivARB_func;
59 static PFNGLFOGCOORDFPROC glFogCoordf_func;
62 // Clamp X to [0, 1]
63 #define CLAMP01( X ) ( (X)<(0.0) ? (0.0) : ((X)>(1.0) ? (1.0) : (X)) )
64 // Absolute value
65 #define ABS(X) ( (X) < 0.0 ? -(X) : (X) )
66 // Max
67 #define MAX( A, B ) ( (A) > (B) ? (A) : (B) )
68 // Min
69 #define MIN( A, B ) ( (A) < (B) ? (A) : (B) )
70 // Duplicate value four times
71 #define SMEAR(X) (X), (X), (X), (X)
73 #define DONT_CARE_Z -1.0
74 #define DONT_CARE_COLOR -1.0
76 #define FRAGCOLOR { 0.25, 0.75, 0.5, 0.25 }
77 #define PARAM0 { 0.0, 0.0, 0.0, 0.0 }
78 #define PARAM1 { 0.5, 0.25, 1.0, 0.5 }
79 #define PARAM2 { -1.0, 0.0, 0.25, -0.5 }
80 static const GLfloat FragColor[4] = FRAGCOLOR;
81 static const GLfloat Param0[4] = PARAM0;
82 static const GLfloat Param1[4] = PARAM1;
83 static const GLfloat Param2[4] = PARAM2;
84 static GLfloat InfNan[4];
85 static GLfloat FogColor[4] = {1.0, 1.0, 0.0, 0.0};
86 static GLfloat FogStart = 10.0;
87 static GLfloat FogEnd = 100.0;
88 static GLfloat FogDensity = 0.03;
89 static GLfloat FogCoord = 50.0; /* Between FogStart and FogEnd */
92 // These are the specific fragment programs which we'll test
93 // Alphabetical order, please
94 static const FragmentProgram Programs[] = {
96 "ABS test",
97 "!!ARBfp1.0\n"
98 "PARAM p = program.local[2]; \n"
99 "ABS result.color, p; \n"
100 "END \n",
101 { ABS(Param2[0]),
102 ABS(Param2[1]),
103 ABS(Param2[2]),
104 ABS(Param2[3])
106 DONT_CARE_Z,
109 "ADD test",
110 "!!ARBfp1.0\n"
111 "PARAM p = program.local[1]; \n"
112 "ADD result.color, fragment.color, p; \n"
113 "END \n",
114 { CLAMP01(FragColor[0] + Param1[0]),
115 CLAMP01(FragColor[1] + Param1[1]),
116 CLAMP01(FragColor[2] + Param1[2]),
117 CLAMP01(FragColor[3] + Param1[3])
119 DONT_CARE_Z
122 "ADD with saturation",
123 "!!ARBfp1.0\n"
124 "PARAM p = program.local[1]; \n"
125 "TEMP t; \n"
126 "ADD t, p, p; \n"
127 "ADD_SAT result.color, t, p; \n"
128 "END \n",
129 { CLAMP01(Param1[0] + Param1[0] + Param1[0]),
130 CLAMP01(Param1[1] + Param1[1] + Param1[1]),
131 CLAMP01(Param1[2] + Param1[2] + Param1[2]),
132 CLAMP01(Param1[3] + Param1[3] + Param1[3]),
134 DONT_CARE_Z
137 "CMP test",
138 "!!ARBfp1.0\n"
139 "PARAM zero = program.local[0]; \n"
140 "PARAM p1 = program.local[1]; \n"
141 "PARAM p2 = program.local[2]; \n"
142 "CMP result.color, p2, zero, p1; \n"
143 "END \n",
144 { Param0[0], Param1[1], Param1[2], Param0[3] },
145 DONT_CARE_Z
148 "COS test",
149 "!!ARBfp1.0\n"
150 "PARAM values = { 0.0, 3.14159, 0.5, 1.0 }; \n"
151 "COS result.color.x, values.x; \n"
152 "COS result.color.y, values.y; \n"
153 "COS result.color.z, values.z; \n"
154 "COS result.color.w, values.w; \n"
155 "END \n",
156 { CLAMP01(1.0),
157 CLAMP01(-1.0),
158 CLAMP01(0.8775),
159 CLAMP01(0.5403)
161 DONT_CARE_Z
164 "COS test 2",
165 "!!ARBfp1.0\n"
166 "PARAM values = { 6.78318, 7.28318, 6.28318, -5.78318 }; \n"
167 "COS result.color.x, values.x; \n"
168 "COS result.color.y, values.y; \n"
169 "COS result.color.z, values.z; \n"
170 "COS result.color.w, values.w; \n"
171 "END \n",
172 { CLAMP01(0.8775),
173 CLAMP01(0.5403),
174 CLAMP01(1.0),
175 CLAMP01(0.8775)
177 DONT_CARE_Z
180 "DP3 test",
181 "!!ARBfp1.0\n"
182 "PARAM p1 = program.local[1]; \n"
183 "DP3 result.color, p1, fragment.color; \n"
184 "END \n",
185 { SMEAR(CLAMP01(Param1[0] * FragColor[0] +
186 Param1[1] * FragColor[1] +
187 Param1[2] * FragColor[2]))
189 DONT_CARE_Z
192 "DP4 test",
193 "!!ARBfp1.0\n"
194 "PARAM p1 = program.local[1]; \n"
195 "DP4 result.color, p1, fragment.color; \n"
196 "END \n",
197 { SMEAR(CLAMP01(Param1[0] * FragColor[0] +
198 Param1[1] * FragColor[1] +
199 Param1[2] * FragColor[2] +
200 Param1[3] * FragColor[3]))
202 DONT_CARE_Z
205 "DPH test",
206 "!!ARBfp1.0\n"
207 "PARAM p1 = program.local[1]; \n"
208 "PARAM scale = {0.1, 0.1, 0.1, 0.1}; \n"
209 "TEMP t; \n"
210 "DPH t, p1, fragment.color; \n"
211 "MUL result.color, t, scale; \n"
212 "END \n",
213 { SMEAR(CLAMP01((Param1[0] * FragColor[0] +
214 Param1[1] * FragColor[1] +
215 Param1[2] * FragColor[2] +
216 FragColor[3]) * 0.1))
218 DONT_CARE_Z
221 "DST test",
222 "!!ARBfp1.0\n"
223 "# let d = 0.4 \n"
224 "PARAM v1 = {9.9, 0.16, 0.16, 9.9}; \n"
225 "PARAM v2 = {9.9, 2.5, 9.9, 2.5}; \n"
226 "DST result.color, v1, v2; \n"
227 "END \n",
228 { 1.0,
229 0.4, // v1.y * v2.y
230 0.16, // v1.z
231 CLAMP01(2.5) // v2.w
233 DONT_CARE_Z
236 "EX2 test",
237 "!!ARBfp1.0\n"
238 "PARAM scale = {0.01, 0.01, 0.01, 0.01}; \n"
239 "PARAM values = {0.0, 1.0, 4.0, -2.0 }; \n"
240 "TEMP t; \n"
241 "EX2 t.x, values.x; \n"
242 "EX2 t.y, values.y; \n"
243 "EX2 t.z, values.z; \n"
244 "EX2 t.w, values.w; \n"
245 "MUL result.color, t, scale; \n"
246 "END \n",
247 { 1.0 * 0.01,
248 2.0 * 0.01,
249 16.0 * 0.01,
250 0.25 * 0.01 },
251 DONT_CARE_Z
254 "FLR test",
255 "!!ARBfp1.0\n"
256 "PARAM values = {4.8, 0.3, -0.2, 1.2}; \n"
257 "PARAM scale = {0.1, 0.1, 0.1, 0.1}; \n"
258 "TEMP t; \n"
259 "FLR t, values; \n"
260 "MUL result.color, t, scale; \n"
261 "END \n",
262 { 0.4,
263 0.0,
264 CLAMP01(-0.1),
267 DONT_CARE_Z
270 "FRC test",
271 "!!ARBfp1.0\n"
272 "PARAM values = {-1.1, 0.1, -2.2, 2.4 }; \n"
273 "FRC result.color, values; \n"
274 "END \n",
275 { 0.9, 0.1, 0.8, 0.4 },
276 DONT_CARE_Z
279 "LG2 test",
280 "!!ARBfp1.0\n"
281 "PARAM values = {64.0, 1, 30, 4}; \n"
282 "PARAM scale = {0.1, 0.1, 0.1, 0.1}; \n"
283 "TEMP t; \n"
284 "LG2 t.x, values.x; \n"
285 "LG2 t.y, values.y; \n"
286 "LG2 t.z, values.z; \n"
287 "LG2 t.w, values.w; \n"
288 "MUL result.color, t, scale; \n"
289 "END \n",
290 { 0.6,
291 0.0,
292 0.49,
295 DONT_CARE_Z
298 "LIT test 1",
299 "!!ARBfp1.0\n"
300 "PARAM values = {0.65, 0.9, 0.0, 8.0}; \n"
301 "LIT result.color, values; \n"
302 "END \n",
303 { 1.0,
304 0.65, // values.x
305 0.433, // roughly Pow(values.y, values.w)
308 DONT_CARE_Z
311 "LIT test 2 (degenerate case: 0 ^ 0 -> 1)",
312 "!!ARBfp1.0\n"
313 "PARAM values = {0.65, 0.0, 0.0, 0.0}; \n"
314 "LIT result.color, values; \n"
315 "END \n",
316 { 1.0,
317 0.65, // values.x
318 1.0, // 0^0
321 DONT_CARE_Z
324 "LIT test 3 (case x < 0)",
325 "!!ARBfp1.0\n"
326 "PARAM values = {-0.5, 0.0, 0.0, 0.0}; \n"
327 "LIT result.color, values; \n"
328 "END \n",
329 { 1.0,
330 CLAMP01(-0.5), // values.x
331 0.0,
334 DONT_CARE_Z
337 "LRP test",
338 "!!ARBfp1.0\n"
339 "PARAM p1 = program.local[1]; \n"
340 "PARAM t = {0.2, 0.5, 1.0, 0.0}; \n"
341 "LRP result.color, t, fragment.color, p1; \n"
342 "END \n",
343 { 0.2 * FragColor[0] + (1.0 - 0.2) * Param1[0],
344 0.5 * FragColor[1] + (1.0 - 0.5) * Param1[1],
345 1.0 * FragColor[2] + (1.0 - 1.0) * Param1[2],
346 0.0 * FragColor[3] + (1.0 - 0.0) * Param1[3]
348 DONT_CARE_Z
351 "MAD test",
352 "!!ARBfp1.0\n"
353 "PARAM p1 = program.local[1]; \n"
354 "PARAM p2 = program.local[2]; \n"
355 "MAD result.color, fragment.color, p1, p2; \n"
356 "END \n",
357 { CLAMP01(FragColor[0] * Param1[0] + Param2[0]),
358 CLAMP01(FragColor[1] * Param1[1] + Param2[1]),
359 CLAMP01(FragColor[2] * Param1[2] + Param2[2]),
360 CLAMP01(FragColor[3] * Param1[3] + Param2[3])
362 DONT_CARE_Z
365 "MAX test",
366 "!!ARBfp1.0\n"
367 "PARAM p1 = program.local[1]; \n"
368 "PARAM p2 = program.local[2]; \n"
369 "MAX result.color, p1, p2; \n"
370 "END \n",
371 { MAX(Param1[0], Param2[0]),
372 MAX(Param1[1], Param2[1]),
373 MAX(Param1[2], Param2[2]),
374 MAX(Param1[3], Param2[3]),
376 DONT_CARE_Z
379 "MIN test",
380 "!!ARBfp1.0\n"
381 "PARAM p1 = program.local[1]; \n"
382 "MIN result.color, p1, fragment.color; \n"
383 "END \n",
384 { MIN(Param1[0], FragColor[0]),
385 MIN(Param1[1], FragColor[1]),
386 MIN(Param1[2], FragColor[2]),
387 MIN(Param1[3], FragColor[3]),
389 DONT_CARE_Z
392 "MOV test",
393 "!!ARBfp1.0\n"
394 "MOV result.color, fragment.color; \n"
395 "END \n",
396 FRAGCOLOR,
397 DONT_CARE_Z,
400 "MUL test",
401 "!!ARBfp1.0\n"
402 "PARAM p = program.local[1]; \n"
403 "MUL result.color, fragment.color, p; \n"
404 "END \n",
405 { CLAMP01(FragColor[0] * Param1[0]),
406 CLAMP01(FragColor[1] * Param1[1]),
407 CLAMP01(FragColor[2] * Param1[2]),
408 CLAMP01(FragColor[3] * Param1[3])
410 DONT_CARE_Z
413 "masked MUL test",
414 "!!ARBfp1.0\n"
415 "PARAM zero = program.local[0]; \n"
416 "PARAM p = program.local[1]; \n"
417 "MOV result.color, zero; \n"
418 "MUL result.color.xy, fragment.color, p; \n"
419 "END \n",
420 { CLAMP01(FragColor[0] * Param1[0]),
421 CLAMP01(FragColor[1] * Param1[1]),
422 0.0,
425 DONT_CARE_Z
428 "POW test (exponentiation)",
429 "!!ARBfp1.0\n"
430 "PARAM values = {0.5, 2, 3, 4}; \n"
431 "POW result.color.x, values.x, values.y; \n"
432 "POW result.color.y, values.x, values.z; \n"
433 "POW result.color.z, values.x, values.w; \n"
434 "POW result.color.w, values.w, values.x; \n"
435 "END \n",
436 { 0.5 * 0.5,
437 0.5 * 0.5 * 0.5,
438 0.5 * 0.5 * 0.5 * 0.5,
439 CLAMP01(2.0) },
440 DONT_CARE_Z
443 "RCP test (reciprocal)",
444 "!!ARBfp1.0\n"
445 "PARAM values = {8, -10, 1, 12 }; \n"
446 "RCP result.color.x, values.x; \n"
447 "RCP result.color.y, values.y; \n"
448 "RCP result.color.z, values.z; \n"
449 "RCP result.color.w, values.w; \n"
450 "END \n",
451 { 1.0 / 8.0, CLAMP01(1.0 / -10.0), 1, 1.0 / 12.0 },
452 DONT_CARE_Z
455 /* check that RCP result is replicated across XYZW */
456 "RCP test 2 (reciprocal)",
457 "!!ARBfp1.0\n"
458 "PARAM values = {8, -10, 1, 12 }; \n"
459 "MOV result.color, values; \n"
460 "RCP result.color, values.x; \n"
461 "END \n",
462 { 1.0 / 8.0, 1.0 / 8.0, 1.0 / 8.0, 1.0 / 8.0 },
463 DONT_CARE_Z
466 "RSQ test 1 (reciprocal square root)",
467 "!!ARBfp1.0\n"
468 "PARAM values = {1, 4, 9, 100 }; \n"
469 "RSQ result.color.x, values.x; \n"
470 "RSQ result.color.y, values.y; \n"
471 "RSQ result.color.z, values.z; \n"
472 "RSQ result.color.w, values.w; \n"
473 "END \n",
474 { 1.0, 0.5, 0.3333, 0.1 },
475 DONT_CARE_Z
478 "RSQ test 2 (reciprocal square root of negative value)",
479 "!!ARBfp1.0\n"
480 "PARAM values = {0, -100, -5, -1}; \n"
481 "RSQ result.color.x, values.x; \n"
482 "RSQ result.color.y, values.y; \n"
483 "RSQ result.color.z, values.z; \n"
484 "RSQ result.color.w, values.w; \n"
485 "END \n",
486 { DONT_CARE_COLOR,
487 0.1,
488 0.447,
489 1.0,
491 DONT_CARE_Z
494 "SCS test",
495 "!!ARBfp1.0\n"
496 "PARAM values = { 0.5, 0.5, 0.0, 0.0 }; \n"
497 "SCS result.color.x, values.x; \n"
498 "SCS result.color.y, values.y; \n"
499 "END \n",
500 { CLAMP01(0.8775),
501 CLAMP01(0.4794),
502 DONT_CARE_COLOR,
503 DONT_CARE_COLOR,
505 DONT_CARE_Z
508 "SGE test",
509 "!!ARBfp1.0\n"
510 "PARAM p0 = program.local[0]; \n"
511 "PARAM p2 = program.local[2]; \n"
512 "SGE result.color, p2, p0; \n"
513 "END \n",
514 { Param2[0] >= Param0[0] ? 1.0 : 0.0,
515 Param2[1] >= Param0[1] ? 1.0 : 0.0,
516 Param2[2] >= Param0[2] ? 1.0 : 0.0,
517 Param2[3] >= Param0[3] ? 1.0 : 0.0,
519 DONT_CARE_Z
522 "SIN test",
523 "!!ARBfp1.0\n"
524 "PARAM values = { 1.57079, -1.57079, 0.5, 1.0 }; \n"
525 "SIN result.color.x, values.x; \n"
526 "SIN result.color.y, values.y; \n"
527 "SIN result.color.z, values.z; \n"
528 "SIN result.color.w, values.w; \n"
529 "END \n",
530 { CLAMP01(1.0),
531 CLAMP01(-1.0),
532 CLAMP01(0.4794),
533 CLAMP01(0.8414)
535 DONT_CARE_Z
538 "SIN test 2",
539 "!!ARBfp1.0\n"
540 "PARAM values = { 3.14159, -3.14159, 6.78319, -5.78319 }; \n"
541 "SIN result.color.x, values.x; \n"
542 "SIN result.color.y, values.y; \n"
543 "SIN result.color.z, values.z; \n"
544 "SIN result.color.w, values.w; \n"
545 "END \n",
546 { CLAMP01(0.0),
547 CLAMP01(0.0),
548 CLAMP01(0.4794),
549 CLAMP01(0.4794)
551 DONT_CARE_Z
554 "SLT test",
555 "!!ARBfp1.0\n"
556 "PARAM p1 = program.local[1]; \n"
557 "SLT result.color, fragment.color, p1; \n"
558 "END \n",
559 { FragColor[0] < Param1[0] ? 1.0 : 0.0,
560 FragColor[1] < Param1[1] ? 1.0 : 0.0,
561 FragColor[2] < Param1[2] ? 1.0 : 0.0,
562 FragColor[3] < Param1[3] ? 1.0 : 0.0,
564 DONT_CARE_Z
567 "SUB test (with swizzle)",
568 "!!ARBfp1.0\n"
569 "PARAM p1 = program.local[1]; \n"
570 "SUB result.color, p1.yxwz, fragment.color.yxwz; \n"
571 "END \n",
572 { CLAMP01(Param1[1] - FragColor[1]),
573 CLAMP01(Param1[0] - FragColor[0]),
574 CLAMP01(Param1[3] - FragColor[3]),
575 CLAMP01(Param1[2] - FragColor[2])
577 DONT_CARE_Z
580 "SUB with saturation",
581 "!!ARBfp1.0\n"
582 "PARAM p1 = program.local[1]; \n"
583 "PARAM bias = {0.1, 0.1, 0.1, 0.1}; \n"
584 "TEMP t; \n"
585 "SUB_SAT t, fragment.color, p1; \n"
586 "ADD result.color, t, bias; \n"
587 "END \n",
588 { CLAMP01(FragColor[0] - Param1[1]) + 0.1,
589 CLAMP01(FragColor[1] - Param1[1]) + 0.1,
590 CLAMP01(FragColor[2] - Param1[2]) + 0.1,
591 CLAMP01(FragColor[3] - Param1[3]) + 0.1
593 DONT_CARE_Z
596 "SWZ test",
597 "!!ARBfp1.0\n"
598 "PARAM p = program.local[1]; \n"
599 "SWZ result.color, p, -1,-y,z,0; \n"
600 "END \n",
601 { CLAMP01(-1.0),
602 CLAMP01(-Param1[1]),
603 CLAMP01(Param1[2]),
604 CLAMP01(0.0)
606 DONT_CARE_Z
609 // this test checks that SOA execution is handled correctly
610 "swizzled move test",
611 "!!ARBfp1.0\n"
612 "TEMP t; \n"
613 "PARAM p = program.local[1]; \n"
614 "MOV t, p; \n"
615 "MOV t, t.yxwz; \n" // "in-place" swizzle
616 "MOV result.color, t; \n"
617 "END \n",
618 { Param1[1], Param1[0], Param1[3], Param1[2] },
619 DONT_CARE_Z
622 // this test checks that SOA execution is handled correctly
623 "swizzled add test",
624 "!!ARBfp1.0\n"
625 "TEMP t; \n"
626 "PARAM p = program.local[1]; \n"
627 "MOV t, p; \n"
628 "ADD t, t, t.yxwz; \n" // "in-place" swizzled add
629 "MOV result.color, t; \n"
630 "END \n",
631 { CLAMP01(Param1[0] + Param1[1]),
632 CLAMP01(Param1[1] + Param1[0]),
633 CLAMP01(Param1[2] + Param1[3]),
634 CLAMP01(Param1[3] + Param1[2]) },
635 DONT_CARE_Z
638 "XPD test 1",
639 "!!ARBfp1.0\n"
640 "PARAM p1 = program.local[1]; \n"
641 "PARAM p2 = program.local[2]; \n"
642 "XPD result.color, p1, p2; \n"
643 "END \n",
644 { CLAMP01(Param1[1] * Param2[2] - Param1[2] * Param2[1]),
645 CLAMP01(Param1[2] * Param2[0] - Param1[0] * Param2[2]),
646 CLAMP01(Param1[0] * Param2[1] - Param1[1] * Param2[0]),
647 DONT_CARE_COLOR
649 DONT_CARE_Z
652 "Z-write test",
653 "!!ARBfp1.0\n"
654 "PARAM p = program.local[1]; \n"
655 "MOV result.color, p; \n"
656 "MOV result.depth.z, p.y; \n"
657 "END \n",
658 { Param1[0],
659 Param1[1],
660 Param1[2],
661 Param1[3]
663 Param1[1]
666 // ============= Numeric stress tests =================================
667 // Basically just check that we don't crash when we do divides by
668 // zero, etc.
670 "Divide by zero test",
671 "!!ARBfp1.0\n"
672 "PARAM zero = program.local[0]; \n"
673 "RCP result.color.x, zero.x; \n"
674 "RCP result.color.y, zero.y; \n"
675 "RCP result.color.z, zero.z; \n"
676 "RCP result.color.w, zero.w; \n"
677 "END \n",
678 { DONT_CARE_COLOR,
679 DONT_CARE_COLOR,
680 DONT_CARE_COLOR,
681 DONT_CARE_COLOR
683 DONT_CARE_Z
686 "Infinity and nan test",
687 "!!ARBfp1.0\n"
688 "PARAM zero = program.local[0]; \n"
689 "PARAM infNan = program.local[9]; \n"
690 "ADD result.color, infNan, zero; \n"
691 "END \n",
692 { DONT_CARE_COLOR,
693 DONT_CARE_COLOR,
694 DONT_CARE_COLOR,
695 DONT_CARE_COLOR
697 DONT_CARE_Z
700 // ============= Fog tests ============================================
701 // Linear fog
702 #define FOG_FACT ((FogEnd - FogCoord) / (FogEnd - FogStart))
704 "ARB_fog_linear test",
705 "!!ARBfp1.0\n"
706 "OPTION ARB_fog_linear; \n"
707 "MOV result.color, fragment.color; \n"
708 "END \n",
709 { FragColor[0] * FOG_FACT + FogColor[0] * (1.0 - FOG_FACT),
710 FragColor[1] * FOG_FACT + FogColor[1] * (1.0 - FOG_FACT),
711 FragColor[2] * FOG_FACT + FogColor[2] * (1.0 - FOG_FACT),
712 FragColor[3]
714 DONT_CARE_Z
717 "Computed fog linear test",
718 "!!ARBfp1.0\n"
719 "# fogParams.x = density \n"
720 "# fogParams.y = start \n"
721 "# fogParams.z = end \n"
722 "# fogParams.w = 1/(end-start) \n"
723 "PARAM fogParams = state.fog.params; \n"
724 "ATTRIB fogCoord = fragment.fogcoord; \n"
725 "PARAM fogColor = state.fog.color; \n"
726 "TEMP numerator, f; \n"
727 "# f = (end - coord) / (end - start) \n"
728 "SUB numerator, fogParams.z, fogCoord.x; \n"
729 "MUL_SAT f, numerator, fogParams.w; \n"
730 "LRP result.color.rgb, f, fragment.color, fogColor; \n"
731 "MOV result.color.a, fragment.color.a; \n"
732 "END \n",
733 { FragColor[0] * FOG_FACT + FogColor[0] * (1.0 - FOG_FACT),
734 FragColor[1] * FOG_FACT + FogColor[1] * (1.0 - FOG_FACT),
735 FragColor[2] * FOG_FACT + FogColor[2] * (1.0 - FOG_FACT),
736 FragColor[3]
738 DONT_CARE_Z
740 #undef FOG_FACT
742 // Exp fog
743 #define FOG_FACT 0.2231 // = exp(-Density * Coord)
745 "ARB_fog_exp test",
746 "!!ARBfp1.0\n"
747 "OPTION ARB_fog_exp; \n"
748 "MOV result.color, fragment.color; \n"
749 "END \n",
750 { FragColor[0] * FOG_FACT + FogColor[0] * (1.0 - FOG_FACT),
751 FragColor[1] * FOG_FACT + FogColor[1] * (1.0 - FOG_FACT),
752 FragColor[2] * FOG_FACT + FogColor[2] * (1.0 - FOG_FACT),
753 FragColor[3]
755 DONT_CARE_Z
757 #undef FOG_FACT
758 #define FOG_FACT 0.3535 // = ex2(-Density * Coord)
760 // NOTE: we could also do this with the POW instruction
761 "Computed fog exp test",
762 "!!ARBfp1.0\n"
763 "# fogParams.x = density \n"
764 "# fogParams.y = start \n"
765 "# fogParams.z = end \n"
766 "# fogParams.w = 1/(end-start) \n"
767 "PARAM fogParams = state.fog.params; \n"
768 "ATTRIB fogCoord = fragment.fogcoord; \n"
769 "PARAM fogColor = state.fog.color; \n"
770 "TEMP f, dc; \n"
771 "# f = exp(-density * coord) \n"
772 "MUL dc.x, fogParams.x, fogCoord.x; \n"
773 "EX2_SAT f, -dc.x; \n"
774 "LRP result.color.rgb, f, fragment.color, fogColor; \n"
775 "MOV result.color.a, fragment.color.a; \n"
776 "END \n",
777 { FragColor[0] * FOG_FACT + FogColor[0] * (1.0 - FOG_FACT),
778 FragColor[1] * FOG_FACT + FogColor[1] * (1.0 - FOG_FACT),
779 FragColor[2] * FOG_FACT + FogColor[2] * (1.0 - FOG_FACT),
780 FragColor[3]
782 DONT_CARE_Z
784 #undef FOG_FACT
786 // Exp2 fog
787 #define FOG_FACT 0.1054 // = exp(-(Density * Coord)^2)
789 "ARB_fog_exp2 test",
790 "!!ARBfp1.0\n"
791 "OPTION ARB_fog_exp2; \n"
792 "MOV result.color, fragment.color; \n"
793 "END \n",
794 { FragColor[0] * FOG_FACT + FogColor[0] * (1.0 - FOG_FACT),
795 FragColor[1] * FOG_FACT + FogColor[1] * (1.0 - FOG_FACT),
796 FragColor[2] * FOG_FACT + FogColor[2] * (1.0 - FOG_FACT),
797 FragColor[3]
799 DONT_CARE_Z
801 #undef FOG_FACT
802 #define FOG_FACT 0.2102 // = ex2(-(Density * Coord)^2)
804 // NOTE: we could also do this with the POW instruction
805 "Computed fog exp2 test",
806 "!!ARBfp1.0\n"
807 "# fogParams.x = density \n"
808 "# fogParams.y = start \n"
809 "# fogParams.z = end \n"
810 "# fogParams.w = 1/(end-start) \n"
811 "PARAM fogParams = state.fog.params; \n"
812 "ATTRIB fogCoord = fragment.fogcoord; \n"
813 "PARAM fogColor = state.fog.color; \n"
814 "TEMP f, dc; \n"
815 "# f = exp(-(density * coord)^2) \n"
816 "MUL dc.x, fogParams.x, fogCoord.x; \n"
817 "MUL dc.x, dc.x, dc.x; \n"
818 "EX2_SAT f, -dc.x; \n"
819 "LRP result.color.rgb, f, fragment.color, fogColor; \n"
820 "MOV result.color.a, fragment.color.a; \n"
821 "END \n",
822 { FragColor[0] * FOG_FACT + FogColor[0] * (1.0 - FOG_FACT),
823 FragColor[1] * FOG_FACT + FogColor[1] * (1.0 - FOG_FACT),
824 FragColor[2] * FOG_FACT + FogColor[2] * (1.0 - FOG_FACT),
825 FragColor[3]
827 DONT_CARE_Z
829 #undef FOG_FACT
831 // XXX add lots more tests here!
832 { NULL, NULL, {0,0,0,0}, 0 } // end of list sentinal
837 void
838 FragmentProgramTest::setup(void)
840 // setup Infinity, Nan values
841 int nan;
842 float *nanPtr;
844 nan = (0xff << 23) | (1 << 0);
845 nanPtr = (float *) &nan;
846 InfNan[0] = HUGE_VAL;
847 InfNan[1] = -HUGE_VAL;
848 InfNan[2] = (float) (*nanPtr);
849 InfNan[3] = 1.0 / HUGE_VAL;
851 // get function pointers
852 glProgramLocalParameter4fvARB_func = (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) GLUtils::getProcAddress("glProgramLocalParameter4fvARB");
853 assert(glProgramLocalParameter4fvARB_func);
855 glGenProgramsARB_func = (PFNGLGENPROGRAMSARBPROC) GLUtils::getProcAddress("glGenProgramsARB");
856 assert(glGenProgramsARB_func);
858 glProgramStringARB_func = (PFNGLPROGRAMSTRINGARBPROC) GLUtils::getProcAddress("glProgramStringARB");
859 assert(glProgramStringARB_func);
861 glBindProgramARB_func = (PFNGLBINDPROGRAMARBPROC) GLUtils::getProcAddress("glBindProgramARB");
862 assert(glBindProgramARB_func);
864 glIsProgramARB_func = (PFNGLISPROGRAMARBPROC) GLUtils::getProcAddress("glIsProgramARB");
865 assert(glIsProgramARB_func);
867 glDeleteProgramsARB_func = (PFNGLDELETEPROGRAMSARBPROC) GLUtils::getProcAddress("glDeleteProgramsARB");
868 assert(glDeleteProgramsARB_func);
870 glGetProgramivARB_func = (PFNGLGETPROGRAMIVARBPROC) GLUtils::getProcAddress("glGetProgramivARB");
871 assert(glGetProgramivARB_func);
873 glFogCoordf_func = (PFNGLFOGCOORDFPROC) GLUtils::getProcAddress("glFogCoordf");
874 assert(glFogCoordf_func);
876 GLuint progID;
877 glGenProgramsARB_func(1, &progID);
878 glBindProgramARB_func(GL_FRAGMENT_PROGRAM_ARB, progID);
879 glEnable(GL_FRAGMENT_PROGRAM_ARB);
881 // load program inputs
882 glColor4fv(FragColor);
883 glProgramLocalParameter4fvARB_func(GL_FRAGMENT_PROGRAM_ARB, 0, Param0);
884 glProgramLocalParameter4fvARB_func(GL_FRAGMENT_PROGRAM_ARB, 1, Param1);
885 glProgramLocalParameter4fvARB_func(GL_FRAGMENT_PROGRAM_ARB, 2, Param2);
886 glProgramLocalParameter4fvARB_func(GL_FRAGMENT_PROGRAM_ARB, 9, InfNan);
888 GLenum err = glGetError();
889 assert(!err); // should be OK
891 // setup vertex transform (we'll draw a quad in middle of window)
892 glMatrixMode(GL_PROJECTION);
893 glLoadIdentity();
894 #if DEVEL_MODE
895 glOrtho(-1.0, 1.0, -1.0, 1.0, 0.0, 1.0);
896 #else
897 glOrtho(-4.0, 4.0, -4.0, 4.0, 0.0, 1.0);
898 #endif
899 glMatrixMode(GL_MODELVIEW);
900 glLoadIdentity();
901 glDrawBuffer(GL_FRONT);
902 glReadBuffer(GL_FRONT);
904 // other GL state
905 glFogf(GL_FOG_START, FogStart);
906 glFogf(GL_FOG_END, FogEnd);
907 glFogf(GL_FOG_DENSITY, FogDensity);
908 glFogfv(GL_FOG_COLOR, FogColor);
909 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
910 glFogCoordf_func(FogCoord);
912 // compute error tolerances (may need fine-tuning)
913 int bufferBits[5];
914 glGetIntegerv(GL_RED_BITS, &bufferBits[0]);
915 glGetIntegerv(GL_GREEN_BITS, &bufferBits[1]);
916 glGetIntegerv(GL_BLUE_BITS, &bufferBits[2]);
917 glGetIntegerv(GL_ALPHA_BITS, &bufferBits[3]);
918 glGetIntegerv(GL_DEPTH_BITS, &bufferBits[4]);
920 tolerance[0] = 2.0 / (1 << bufferBits[0]);
921 tolerance[1] = 2.0 / (1 << bufferBits[1]);
922 tolerance[2] = 2.0 / (1 << bufferBits[2]);
923 if (bufferBits[3])
924 tolerance[3] = 2.0 / (1 << bufferBits[3]);
925 else
926 tolerance[3] = 1.0;
927 if (bufferBits[4])
928 tolerance[4] = 16.0 / (1 << bufferBits[4]);
929 else
930 tolerance[4] = 1.0;
934 void
935 FragmentProgramTest::reportFailure(const char *programName,
936 const GLfloat expectedColor[4],
937 const GLfloat actualColor[4] ) const
939 env->log << "FAILURE:\n";
940 env->log << " Program: " << programName << "\n";
941 env->log << " Expected color: ";
942 env->log << expectedColor[0] << ", ";
943 env->log << expectedColor[1] << ", ";
944 env->log << expectedColor[2] << ", ";
945 env->log << expectedColor[3] << "\n";
946 env->log << " Observed color: ";
947 env->log << actualColor[0] << ", ";
948 env->log << actualColor[1] << ", ";
949 env->log << actualColor[2] << ", ";
950 env->log << actualColor[3] << "\n";
954 void
955 FragmentProgramTest::reportZFailure(const char *programName,
956 GLfloat expectedZ, GLfloat actualZ) const
958 env->log << "FAILURE:\n";
959 env->log << " Program: " << programName << "\n";
960 env->log << " Expected Z: " << expectedZ << "\n";
961 env->log << " Observed Z: " << actualZ << "\n";
965 // Compare actual and expected colors
966 bool
967 FragmentProgramTest::equalColors(const GLfloat act[4], const GLfloat exp[4]) const
969 if (fabsf(act[0] - exp[0]) > tolerance[0] && exp[0] != DONT_CARE_COLOR)
970 return false;
971 if (fabsf(act[1] - exp[1]) > tolerance[1] && exp[1] != DONT_CARE_COLOR)
972 return false;
973 if (fabsf(act[2] - exp[2]) > tolerance[2] && exp[2] != DONT_CARE_COLOR)
974 return false;
975 if (fabsf(act[3] - exp[3]) > tolerance[3] && exp[3] != DONT_CARE_COLOR)
976 return false;
977 return true;
981 bool
982 FragmentProgramTest::equalDepth(GLfloat z0, GLfloat z1) const
984 if (fabsf(z0 - z1) > tolerance[4])
985 return false;
986 else
987 return true;
991 bool
992 FragmentProgramTest::testProgram(const FragmentProgram &p)
994 glProgramStringARB_func(GL_FRAGMENT_PROGRAM_ARB,
995 GL_PROGRAM_FORMAT_ASCII_ARB,
996 strlen(p.progString),
997 (const GLubyte *) p.progString);
999 GLenum err = glGetError();
1000 if (err) {
1001 env->log << "OpenGL error " << (int) err << "\n";
1002 env->log << "Invalid Fragment Program:\n";
1003 env->log << p.progString;
1004 env->log << glGetString(GL_PROGRAM_ERROR_STRING_ARB) << "\n";
1005 return false;
1008 // to avoid potential issue with undefined result.depth.z
1009 if (p.expectedZ == DONT_CARE_Z)
1010 glDisable(GL_DEPTH_TEST);
1011 else
1012 glEnable(GL_DEPTH_TEST);
1014 #if !DEVEL_MODE
1015 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1016 #endif
1017 glBegin(GL_POLYGON);
1018 glVertex2f(-1, -1);
1019 glVertex2f( 1, -1);
1020 glVertex2f( 1, 1);
1021 glVertex2f(-1, 1);
1022 glEnd();
1024 #if !DEVEL_MODE
1025 GLfloat pixel[4];
1026 glReadPixels(windowWidth / 2, windowHeight / 2, 1, 1,
1027 GL_RGBA, GL_FLOAT, pixel);
1029 if (0) // debug
1030 printf("%s: Expect: %.3f %.3f %.3f %.3f found: %.3f %.3f %.3f %.3f\n",
1031 p.name,
1032 p.expectedColor[0], p.expectedColor[1],
1033 p.expectedColor[2], p.expectedColor[3],
1034 pixel[0], pixel[1], pixel[2], pixel[3]);
1036 if (!equalColors(pixel, p.expectedColor)) {
1037 reportFailure(p.name, p.expectedColor, pixel);
1038 return false;
1041 if (p.expectedZ != DONT_CARE_Z) {
1042 GLfloat z;
1043 glReadPixels(windowWidth / 2, windowHeight / 2, 1, 1,
1044 GL_DEPTH_COMPONENT, GL_FLOAT, &z);
1045 if (!equalDepth(z, p.expectedZ)) {
1046 reportZFailure(p.name, p.expectedZ, z);
1047 return false;
1050 #endif
1051 return true;
1054 void
1055 FragmentProgramTest::runOne(MultiTestResult &r, Window &w)
1057 // to test a single sub-test, set the name here:
1058 const char *single = getenv("PIGLIT_TEST");
1060 (void) w;
1061 setup();
1063 #if DEVEL_MODE
1064 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1065 #endif
1066 for (int i = 0; Programs[i].name; i++) {
1068 if (!single || strcmp(single, Programs[i].name) == 0) {
1070 #if DEVEL_MODE
1071 glViewport(0, i * 20, windowWidth, 20);
1072 #endif
1073 if (!testProgram(Programs[i])) {
1074 r.numFailed++;
1076 else {
1077 r.numPassed++;
1082 #if DEVEL_MODE
1083 glFinish();
1084 sleep(100);
1085 #endif
1086 r.pass = (r.numFailed == 0);
1090 // The test object itself:
1091 FragmentProgramTest fragmentProgramTest("fragProg1", "window, rgb, z",
1092 "GL_ARB_fragment_program",
1093 "Fragment Program test 1: test a specific set of fragment programs.\n");
1097 } // namespace GLEAN