1 /*
2  * Copyright 2014 VMware, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23 
24 /**
25  * Test resource limits given the maximum supported by the implementation.
26  *
27  * Each component of the fragment output is derived using the following
28  * expression (indexed at the scalar level):
29  *
30  *   result[i] = texture[i] * texture[i] * ... * attrib[i + l * numOutputs]
31  *
32  * Depending on the limits for vertex/fragment image units, the texture
33  * contribution will vary. See the generation of g_expected at the end of
34  * piglit_init.
35  *
36  * Since the scalar inputs are primes, multiplication will yield a unique
37  * result. Results can be diagnosed by evaluating for their missing factor(s).
38  *
39  * Matthew McClure
40  * 7 July 2014
41  */
42 
43 #include "piglit-util-gl.h"
44 
45 PIGLIT_GL_TEST_CONFIG_BEGIN
46 
47         config.supports_gl_compat_version = 30;
48         config.window_visual = PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_RGBA;
49 	config.khr_no_error_support = PIGLIT_NO_ERRORS;
50 
51 PIGLIT_GL_TEST_CONFIG_END
52 
53 
54 /*
55  * Definitions for the runtime behavior.
56  */
57 #define GLSL_VERSION                    "#version 130"
58 #define BUFFER_WIDTH                    32
59 #define BUFFER_HEIGHT                   32
60 #define MAX_SHADER_LINE_CHARS           256
61 #define MAX_SHADER_TEXT_CHARS           16*1024
62 #define MAX_COMPONENTS                  4
63 #define MAX_EXPRESSION_OUTPUTS          1
64 #define MAX_EXPRESSION_ARGUMENTS        2
65 #define MAX_EXPRESSION_TEMPS            1
66 #define TEMP_TEXT_SIZE                  (MAX_EXPRESSION_OUTPUTS +  \
67                                          MAX_EXPRESSION_ARGUMENTS +  \
68                                          MAX_EXPRESSION_ARGUMENTS)
69 
70 #define NUM_PRIMES                      512
71 #define NUM_VERTICES                    3
72 
73 #define DEBUG_INPUT                     0x01
74 #define DEBUG_READBACK                  0x02
75 #define DEBUG_SHADERS                   0x04
76 #define DEBUG_DRAW                      0x08
77 #define DEBUG_DONT_CLAMP_MAX_VARYINGS   0x10
78 
79 /*
80  * Type definitions for our working set.
81  */
82 enum {
83         DRAW_ARRAYS_VBO = 0,
84         DRAW_ELEMENTS_VBO = 1,
85         DRAW_IMMEDIATE = 2,
86 };
87 
88 typedef struct MyVector4 {
89         float x, y, z, w;
90 } MyVector4;
91 
92 typedef struct PackedTypeDesc {
93         char *typeName;
94         unsigned numComponents;
95         char *componentNames[MAX_COMPONENTS];
96         char *defaultValue;
97 } PackedTypeDesc;
98 
99 typedef struct PackedDesc {
100         char *semanticName;
101         char *variableName;
102         bool isArray;
103         unsigned count;
104         const PackedTypeDesc *typeDesc;
105 } PackedDesc;
106 
107 
108 /*
109  * Global variables for the test's state.
110  */
111 static GLint g_maxVaryingFloats = 0;
112 static GLint g_maxVertexAttribs = 0;
113 static GLint g_maxVertexTextureImageUnits = 0;
114 static GLint g_maxTextureImageUnits = 0;
115 static GLint g_maxCombinedTextureImageUnits = 0;
116 
117 static GLint g_maxAuxBuffers = 0;
118 static GLint g_maxDrawBuffers = 0;
119 static GLint g_maxColorAttachments = 0;
120 
121 static GLint g_debugMask = 0x0;
122 static GLint g_drawMode = DRAW_IMMEDIATE;
123 
124 static char *g_fragColor = "gl_FragColor";
125 static char *g_fragData = "gl_FragData";
126 
127 static const GLfloat g_primes[NUM_PRIMES] = {
128 2.0, 3.0, 5.0, 7.0, 11.0, 13.0, 17.0, 19.0,
129 23.0, 29.0, 31.0, 37.0, 41.0, 43.0, 47.0, 53.0,
130 59.0, 61.0, 67.0, 71.0, 73.0, 79.0, 83.0, 89.0,
131 97.0, 101.0, 103.0, 107.0, 109.0, 113.0, 127.0, 131.0,
132 137.0, 139.0, 149.0, 151.0, 157.0, 163.0, 167.0, 173.0,
133 179.0, 181.0, 191.0, 193.0, 197.0, 199.0, 211.0, 223.0,
134 227.0, 229.0, 233.0, 239.0, 241.0, 251.0, 257.0, 263.0,
135 269.0, 271.0, 277.0, 281.0, 283.0, 293.0, 307.0, 311.0,
136 313.0, 317.0, 331.0, 337.0, 347.0, 349.0, 353.0, 359.0,
137 367.0, 373.0, 379.0, 383.0, 389.0, 397.0, 401.0, 409.0,
138 419.0, 421.0, 431.0, 433.0, 439.0, 443.0, 449.0, 457.0,
139 461.0, 463.0, 467.0, 479.0, 487.0, 491.0, 499.0, 503.0,
140 509.0, 521.0, 523.0, 541.0, 547.0, 557.0, 563.0, 569.0,
141 571.0, 577.0, 587.0, 593.0, 599.0, 601.0, 607.0, 613.0,
142 617.0, 619.0, 631.0, 641.0, 643.0, 647.0, 653.0, 659.0,
143 661.0, 673.0, 677.0, 683.0, 691.0, 701.0, 709.0, 719.0,
144 727.0, 733.0, 739.0, 743.0, 751.0, 757.0, 761.0, 769.0,
145 773.0, 787.0, 797.0, 809.0, 811.0, 821.0, 823.0, 827.0,
146 829.0, 839.0, 853.0, 857.0, 859.0, 863.0, 877.0, 881.0,
147 883.0, 887.0, 907.0, 911.0, 919.0, 929.0, 937.0, 941.0,
148 947.0, 953.0, 967.0, 971.0, 977.0, 983.0, 991.0, 997.0,
149 1009.0, 1013.0, 1019.0, 1021.0, 1031.0, 1033.0, 1039.0, 1049.0,
150 1051.0, 1061.0, 1063.0, 1069.0, 1087.0, 1091.0, 1093.0, 1097.0,
151 1103.0, 1109.0, 1117.0, 1123.0, 1129.0, 1151.0, 1153.0, 1163.0,
152 1171.0, 1181.0, 1187.0, 1193.0, 1201.0, 1213.0, 1217.0, 1223.0,
153 1229.0, 1231.0, 1237.0, 1249.0, 1259.0, 1277.0, 1279.0, 1283.0,
154 1289.0, 1291.0, 1297.0, 1301.0, 1303.0, 1307.0, 1319.0, 1321.0,
155 1327.0, 1361.0, 1367.0, 1373.0, 1381.0, 1399.0, 1409.0, 1423.0,
156 1427.0, 1429.0, 1433.0, 1439.0, 1447.0, 1451.0, 1453.0, 1459.0,
157 1471.0, 1481.0, 1483.0, 1487.0, 1489.0, 1493.0, 1499.0, 1511.0,
158 1523.0, 1531.0, 1543.0, 1549.0, 1553.0, 1559.0, 1567.0, 1571.0,
159 1579.0, 1583.0, 1597.0, 1601.0, 1607.0, 1609.0, 1613.0, 1619.0,
160 1621.0, 1627.0, 1637.0, 1657.0, 1663.0, 1667.0, 1669.0, 1693.0,
161 1697.0, 1699.0, 1709.0, 1721.0, 1723.0, 1733.0, 1741.0, 1747.0,
162 1753.0, 1759.0, 1777.0, 1783.0, 1787.0, 1789.0, 1801.0, 1811.0,
163 1823.0, 1831.0, 1847.0, 1861.0, 1867.0, 1871.0, 1873.0, 1877.0,
164 1879.0, 1889.0, 1901.0, 1907.0, 1913.0, 1931.0, 1933.0, 1949.0,
165 1951.0, 1973.0, 1979.0, 1987.0, 1993.0, 1997.0, 1999.0, 2003.0,
166 2011.0, 2017.0, 2027.0, 2029.0, 2039.0, 2053.0, 2063.0, 2069.0,
167 2081.0, 2083.0, 2087.0, 2089.0, 2099.0, 2111.0, 2113.0, 2129.0,
168 2131.0, 2137.0, 2141.0, 2143.0, 2153.0, 2161.0, 2179.0, 2203.0,
169 2207.0, 2213.0, 2221.0, 2237.0, 2239.0, 2243.0, 2251.0, 2267.0,
170 2269.0, 2273.0, 2281.0, 2287.0, 2293.0, 2297.0, 2309.0, 2311.0,
171 2333.0, 2339.0, 2341.0, 2347.0, 2351.0, 2357.0, 2371.0, 2377.0,
172 2381.0, 2383.0, 2389.0, 2393.0, 2399.0, 2411.0, 2417.0, 2423.0,
173 2437.0, 2441.0, 2447.0, 2459.0, 2467.0, 2473.0, 2477.0, 2503.0,
174 2521.0, 2531.0, 2539.0, 2543.0, 2549.0, 2551.0, 2557.0, 2579.0,
175 2591.0, 2593.0, 2609.0, 2617.0, 2621.0, 2633.0, 2647.0, 2657.0,
176 2659.0, 2663.0, 2671.0, 2677.0, 2683.0, 2687.0, 2689.0, 2693.0,
177 2699.0, 2707.0, 2711.0, 2713.0, 2719.0, 2729.0, 2731.0, 2741.0,
178 2749.0, 2753.0, 2767.0, 2777.0, 2789.0, 2791.0, 2797.0, 2801.0,
179 2803.0, 2819.0, 2833.0, 2837.0, 2843.0, 2851.0, 2857.0, 2861.0,
180 2879.0, 2887.0, 2897.0, 2903.0, 2909.0, 2917.0, 2927.0, 2939.0,
181 2953.0, 2957.0, 2963.0, 2969.0, 2971.0, 2999.0, 3001.0, 3011.0,
182 3019.0, 3023.0, 3037.0, 3041.0, 3049.0, 3061.0, 3067.0, 3079.0,
183 3083.0, 3089.0, 3109.0, 3119.0, 3121.0, 3137.0, 3163.0, 3167.0,
184 3169.0, 3181.0, 3187.0, 3191.0, 3203.0, 3209.0, 3217.0, 3221.0,
185 3229.0, 3251.0, 3253.0, 3257.0, 3259.0, 3271.0, 3299.0, 3301.0,
186 3307.0, 3313.0, 3319.0, 3323.0, 3329.0, 3331.0, 3343.0, 3347.0,
187 3359.0, 3361.0, 3371.0, 3373.0, 3389.0, 3391.0, 3407.0, 3413.0,
188 3433.0, 3449.0, 3457.0, 3461.0, 3463.0, 3467.0, 3469.0, 3491.0,
189 3499.0, 3511.0, 3517.0, 3527.0, 3529.0, 3533.0, 3539.0, 3541.0,
190 3547.0, 3557.0, 3559.0, 3571.0, 3581.0, 3583.0, 3593.0, 3607.0,
191 3613.0, 3617.0, 3623.0, 3631.0, 3637.0, 3643.0, 3659.0, 3671.0,
192 };
193 
194 static const PackedTypeDesc g_rgbaDesc = {
195         "vec4", 4, { ".r", ".g", ".b", ".a" },
196         "vec4(1.0, 1.0, 1.0, 1.0)"
197 };
198 
199 static const PackedTypeDesc g_vec4Desc = {
200         "vec4", 4, { ".x", ".y", ".z", ".w" },
201         "vec4(1.0, 1.0, 1.0, 1.0)"
202 };
203 
204 static const PackedTypeDesc g_floatDesc = {
205         "float", 1, { "" },
206         "1.0"
207 };
208 
209 static const PackedTypeDesc g_sampler2DDesc = {
210         "sampler2D", 4, { "" },
211         "vec4(1.0, 1.0, 1.0, 1.0)"
212 };
213 
214 static const char *g_vectorComponents[MAX_COMPONENTS] = {
215         ".x", ".y", ".z", ".w"
216 };
217 
218 //static const MyVector4 one = { 1.0f, 1.0f, 1.0f, 1.0f };
219 //static const MyVector4 zero = { 0.0f, 0.0f, 0.0f, 0.0f };
220 
221 static const MyVector4 g_positionBuffer[NUM_VERTICES] = {
222         { -1.0, -1.0, 0.0, 0.0 },
223         { -1.0, 1.0, 0.0, 0.0 },
224         { 1.0, 1.0, 0.0, 0.0 }
225 };
226 
227 static GLuint g_elementVBO;
228 static const GLushort g_elementBuffer[NUM_VERTICES] = { 0, 1, 2 };
229 static const char *g_vertexShaderText =
230         "#version 110 \n"
231         " \n"
232         "void main() \n"
233         "{ \n"
234         "   gl_Position = gl_Vertex; \n"
235         "} \n";
236 
237 //static char *g_geometryShaderText = NULL;
238 
239 static const char *g_fragmentShaderText =
240         "#version 110 \n"
241         " \n"
242         "void main()\n"
243         "{ \n"
244         "    gl_FragData[0] = vec4(1.0, 2.0, 3.0, 4.0);\n"
245         "    gl_FragData[1] = vec4(5.0, 6.0, 7.0, 8.0);\n"
246         "} \n";
247 
248 static GLuint g_program = 0;
249 static GLfloat *g_expected;
250 
251 
252 /**
253  * Format a string which contains the requested declaration for the variable.
254  * The desc structure will describe the variable, i.e. type, if it is an array,
255  * and how large the array is.
256  *
257  * \param desc Descriptor of the variable referenced. See PackedDesc.
258  * \param tmpStrSize Temporary string size for safe string formatting.
259  * \param tmpStr Temporary staging string.
260  * \param strSize Size of the formatted string.
261  * \param str An allocated temporary string for this function to populate with
262  *            the reference expression.
263  * \return Pointer to str.
264  */
265 
266 static char *
get_packed_decl(const PackedDesc * desc,const unsigned tmpStrSize,char * tmpStr,const unsigned strSize,char * str)267 get_packed_decl(const PackedDesc *desc,
268                 const unsigned tmpStrSize,
269                 char *tmpStr,
270                 const unsigned strSize,
271                 char *str)
272 {
273         int i = 0;
274 
275         if (NULL == str) {
276                 return "";
277         }
278 
279         if (desc->isArray) {
280                 snprintf(tmpStr, tmpStrSize,
281                          "%s %s %s%s%u%s;\n",
282                          desc->semanticName,
283                          desc->typeDesc->typeName,
284                          desc->variableName,
285                          desc->isArray ? "[" : "",
286                          desc->count,
287                          desc->isArray ? "]" : "");
288                 strncat(str, tmpStr, strSize - strlen(str));
289         } else if (desc->count > 1) {
290                 for (i = 0; i < desc->count; i++) {
291                         snprintf(tmpStr, tmpStrSize,
292                                  "%s %s %s%u;\n",
293                                  desc->semanticName,
294                                  desc->typeDesc->typeName,
295                                  desc->variableName, i);
296                         strncat(str, tmpStr, strSize - strlen(str));
297                 }
298         } else {
299                 snprintf(tmpStr, tmpStrSize,
300                          "%s %s %s;\n",
301                          desc->semanticName,
302                          desc->typeDesc->typeName,
303                          desc->variableName);
304                 strncat(str, tmpStr, strSize - strlen(str));
305         }
306 
307         return str;
308 }
309 
310 
311 /**
312  * Format a string which contains the requested referenced value. The desc
313  * structure will describe the variable which is sub-indexed by arrayIndex.
314  * To address individual components, a componentIndex translated to (x,y,z,w)
315  * is applied to the textual representation.
316  *
317  * \param desc Descriptor of the variable referenced. See PackedDesc.
318  * \param arrayIndex Sub-index into the variable described by desc.
319  * \param componentIndex Component of the variable, depends on the desc
320  *                       configuration for the variable.
321  * \param str An allocated temporary string for this function to populate with
322  *            the reference expression.
323  * \return Pointer to str.
324  */
325 
326 static char *
get_packed_reference(const PackedDesc * desc,const unsigned arrayIndex,const unsigned componentIndex,const unsigned strSize,char * str)327 get_packed_reference(const PackedDesc *desc,
328                      const unsigned arrayIndex,
329                      const unsigned componentIndex,
330                      const unsigned strSize,
331                      char *str)
332 {
333         if (g_debugMask & DEBUG_INPUT) {
334                 printf("desc=%p componentIndex=%u\n", desc, componentIndex);
335                 printf("desc->typeDesc=%p\n", desc->typeDesc);
336                 printf("desc->typeDesc->componentNames=%p\n",
337                        desc->typeDesc->componentNames);
338         }
339 
340         if (componentIndex > desc->typeDesc->numComponents) {
341                 snprintf(str, strSize, "%s", g_floatDesc.defaultValue);
342                 return str;
343         }
344 
345         if (arrayIndex > desc->count) {
346                 snprintf(str, strSize, "%s%s",
347                          desc->typeDesc->defaultValue,
348                          desc->typeDesc->componentNames[componentIndex]);
349                 return str;
350         }
351 
352         if (desc->count > 1) {
353                 snprintf(str, strSize, "%s%s%u%s%s",
354                          desc->variableName,
355                          desc->isArray ? "[" : "",
356                          arrayIndex,
357                          desc->isArray ? "]" : "",
358                          desc->typeDesc->componentNames[componentIndex]);
359         } else {
360                 snprintf(str, strSize, "%s%s",
361                          desc->variableName,
362                          desc->typeDesc->componentNames[componentIndex]);
363         }
364 
365         return str;
366 }
367 
368 
369 /**
370  * Set up an FBO for the test.
371  *
372  * \param colorTarget Color attachment index relative to GL_COLOR_ATTACHMENT0
373  * \param internalFormat Internal GL format for the pixel data.
374  * \param format GL format for the pixel data.
375  * \param formatType Data type for the pixel data.
376  * \param width Width of the requested FBO backing store.
377  * \param height Height of the requested FBO backing store.
378  * \param fbo FBO object allocated to bind with this texture.
379  * \param pTexture A pointer to the GLuint identifier storage for the allocated
380  *                 texture.
381  * \return true if the setup succeeded without error
382  *         false otherwise.
383  */
384 
385 static bool
setup_fbo_2d(const GLuint colorTarget,const GLenum internalFormat,const GLenum format,const GLenum formatType,const GLuint width,const GLuint height,const GLuint fbo,GLuint * pTexture)386 setup_fbo_2d(const GLuint colorTarget,
387              const GLenum internalFormat,
388              const GLenum format,
389              const GLenum formatType,
390              const GLuint width,
391              const GLuint height,
392              const GLuint fbo,
393              GLuint *pTexture)
394 {
395         GLenum status;
396 
397         glGenTextures(1, pTexture);
398         glBindTexture(GL_TEXTURE_2D, *pTexture);
399         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
400         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
401         glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0,
402                      format, formatType, NULL);
403 
404         /*
405          * Framebuffer object is implied to be bound.
406          */
407         glFramebufferTexture2D(GL_FRAMEBUFFER,
408                                GL_COLOR_ATTACHMENT0 + colorTarget,
409                                GL_TEXTURE_2D, *pTexture, 0);
410 
411         if (!piglit_check_gl_error(GL_NO_ERROR)) {
412                 fprintf(stderr, "Failed to create FBO %u.\n", colorTarget);
413                 piglit_report_result(PIGLIT_FAIL);
414                 return false;
415         }
416 
417         status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
418         if (status != GL_FRAMEBUFFER_COMPLETE) {
419                 fprintf(stderr, "Incomplete fbo for format %s.%s (status %s)\n",
420                         piglit_get_gl_enum_name(internalFormat),
421                         piglit_get_gl_enum_name(format),
422                         piglit_get_gl_enum_name(status));
423                 piglit_report_result(PIGLIT_FAIL);
424                 return false;
425         }
426 
427         return true;
428 }
429 
430 
431 /**
432  * Set up the vertex buffer objects and element buffer objects for the
433  * test. To ensure constant values across the primitive, populate the same
434  * prime attribute value in each vertex.
435  *
436  * \return true if the setup succeeded without error
437  *         false otherwise.
438  */
439 
440 static bool
setup_vertex_element_buffers(void)441 setup_vertex_element_buffers(void)
442 {
443         MyVector4 attrib[NUM_VERTICES];
444         GLuint buf;
445         GLuint attribLoc;
446         int i;
447 
448         /*
449          * Setup the gl_Position attribute buffer.
450          */
451         glGenBuffers(1, &buf);
452         glBindBuffer(GL_ARRAY_BUFFER, buf);
453         glBufferData(GL_ARRAY_BUFFER, NUM_VERTICES*sizeof(MyVector4),
454                      g_positionBuffer, GL_STATIC_DRAW);
455 
456         attribLoc = glGetAttribLocation(g_program, "InPosition");
457         glEnableVertexAttribArray(attribLoc);
458         glVertexAttribPointer(attribLoc, 4, GL_FLOAT, GL_FALSE, 0, 0);
459         glBindBuffer(GL_ARRAY_BUFFER, 0);
460 
461         /*
462          * Setup the vertex buffer objects.
463          */
464         for (i = 0; i < g_maxVertexAttribs - 1; i++) {
465                 char strTemp[16];
466 
467                 if ((i + 1) * MAX_COMPONENTS < NUM_PRIMES) {
468                         attrib[0].x = attrib[1].x =
469                         attrib[2].x = g_primes[i*MAX_COMPONENTS + 0];
470                         attrib[0].y = attrib[1].y =
471                         attrib[2].y = g_primes[i*MAX_COMPONENTS + 1];
472                         attrib[0].z = attrib[1].z =
473                         attrib[2].z = g_primes[i*MAX_COMPONENTS + 2];
474                         attrib[0].w = attrib[1].w =
475                         attrib[2].w = g_primes[i*MAX_COMPONENTS + 3];
476                 } else {
477                         attrib[0].x = attrib[1].x = attrib[2].x = 1.0;
478                         attrib[0].y = attrib[1].y = attrib[2].y = 1.0;
479                         attrib[0].z = attrib[1].z = attrib[2].z = 1.0;
480                         attrib[0].w = attrib[1].w = attrib[2].w = 1.0;
481                 }
482 
483                 glGenBuffers(1, &buf);
484                 glBindBuffer(GL_ARRAY_BUFFER, buf);
485                 glBufferData(GL_ARRAY_BUFFER, sizeof(MyVector4)*NUM_VERTICES,
486                              attrib, GL_STATIC_DRAW);
487 
488                 snprintf(strTemp, sizeof(strTemp), "InValue%u", i);
489                 attribLoc = glGetAttribLocation(g_program, strTemp);
490                 glEnableVertexAttribArray(attribLoc);
491                 glVertexAttribPointer(attribLoc, 4, GL_FLOAT, GL_FALSE, 0, 0);
492                 glBindBuffer(GL_ARRAY_BUFFER, 0);
493 
494                 if (!piglit_check_gl_error(GL_NO_ERROR)) {
495                          fprintf(stderr, "Failed to create VBO %u.\n", i);
496                          piglit_report_result(PIGLIT_FAIL);
497                          return false;
498                 }
499         }
500 
501         /*
502          * Setup the element buffers.
503          */
504         glGenBuffers(1, &g_elementVBO);
505         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_elementVBO);
506         glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(g_elementBuffer),
507                      g_elementBuffer, GL_STATIC_DRAW);
508         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
509 
510         if (!piglit_check_gl_error(GL_NO_ERROR)) {
511                 fprintf(stderr, "Failed to create IBO.\n");
512                 piglit_report_result(PIGLIT_FAIL);
513                 return false;
514         }
515 
516         return true;
517 }
518 
519 
520 /**
521  * Build a GLSL shader for the given packedInput, packedUniform, packedOutput
522  * descriptors. Each GLSL shader will have inputs, uniforms, and outputs. To
523  * ensure all bound resources are made resident, this shader must use all the
524  * inputs, uniforms, and outputs requested by the describing PackedDesc
525  * structures. If the number of outputs are smaller than the number of inputs,
526  * the inputs will map as follows:
527  *
528  *   outputs[0] = uniforms[0] inputs[0] * ... * inputs[(i % numOutputs == 0)]
529  *
530  * where i >= numOutputs and represents a subsequent pass of inputs up
531  * until i == numInputs.
532  *
533  * If the number of outputs is larger than the number of inputs, the inputs
534  * and uniforms are referenced until exhausted. Once exhausted, an input
535  * or uniform will default to 1.0 to provide a multiplicative identity.
536  *
537  * \param packedInput A descriptor of the type and number of inputs to this
538  *                    shader.
539  * \param packedUniform A descriptor of the type and number of uniforms bound
540  *                      to the shader.
541  * \param packedOutput A descriptor of the type and number of outputs for this
542  *                     shader.
543  * \param outputDefaultSystemValue A required output for the GLSL shader.
544  *                                 i.e. gl_Position for a vertex shader.
545  * \param defaultSystemValueDecl Pre-defined output declaration.
546  * \param defaultSystemValue Pre-defined output value.
547  * \param pShaderText Output pointer for the allocated and generated shader
548  *                    text.
549  * \return true if the setup succeeded without error
550  *         false otherwise.
551  */
552 
553 static bool
build_reduce_glsl_shader(const PackedDesc * packedInput,const PackedDesc * packedUniform,const PackedDesc * packedOutput,const char * outputDefaultSystemValue,const char * defaultSystemValueDecl,const char * defaultSystemValue,char ** pShaderText)554 build_reduce_glsl_shader(const PackedDesc *packedInput,
555                          const PackedDesc *packedUniform,
556                          const PackedDesc *packedOutput,
557                          const char *outputDefaultSystemValue,
558                          const char *defaultSystemValueDecl,
559                          const char *defaultSystemValue,
560                          char **pShaderText)
561 {
562         char *shaderTempText[TEMP_TEXT_SIZE];
563         char *shaderText = NULL;
564         unsigned shaderTextFree = 0;
565         unsigned numScalarInputs =
566                 packedInput->count * packedInput->typeDesc->numComponents;
567         unsigned numScalarUniforms =
568                 packedUniform->count * packedUniform->typeDesc->numComponents;
569         unsigned numScalarOutputs =
570                 packedOutput->count * packedOutput->typeDesc->numComponents;
571 
572         /* Prepare for reduction of input contributions to the output slots */
573         unsigned di_do = numScalarInputs / numScalarOutputs;
574         unsigned r = numScalarInputs % numScalarOutputs;
575         int i, j, k, l;
576 
577         if (g_debugMask & DEBUG_INPUT) {
578                 printf("di_do=%u r=%u\n", di_do, r);
579         }
580 
581         for (i = 0; i < sizeof(shaderTempText) / sizeof(char *); i++) {
582                 shaderTempText[i] = calloc(MAX_SHADER_LINE_CHARS, sizeof(char));
583 
584                 if (NULL == shaderTempText[i]) {
585                         fprintf(stderr,
586                                 "Failed to allocate shader temporary text area\n");
587                         piglit_report_result(PIGLIT_FAIL);
588                         return false;
589                 }
590         }
591 
592         shaderText = calloc(MAX_SHADER_TEXT_CHARS, sizeof(char));
593         if (NULL == shaderText) {
594                 fprintf(stderr, "Failed to allocate space for shader text\n");
595                 piglit_report_result(PIGLIT_FAIL);
596                 return false;
597         }
598 
599         shaderTextFree = MAX_SHADER_TEXT_CHARS - 1;
600 
601         snprintf(shaderTempText[0], MAX_SHADER_LINE_CHARS,
602         "%s\n", GLSL_VERSION);
603         strncat(shaderText, shaderTempText[0], shaderTextFree);
604         shaderTextFree -= strlen(shaderTempText[0]);
605 
606         /*
607          * Declare the default system value input.
608          */
609         if (outputDefaultSystemValue) {
610                 snprintf(shaderTempText[0], MAX_SHADER_LINE_CHARS,
611                          "%s\n", defaultSystemValueDecl);
612                 strncat(shaderText, shaderTempText[0], shaderTextFree);
613                 shaderTextFree -= strlen(defaultSystemValueDecl);
614         }
615 
616         /*
617          * Declare the input attributes.
618          */
619         get_packed_decl(packedInput,
620         MAX_SHADER_LINE_CHARS, shaderTempText[0],
621         MAX_SHADER_TEXT_CHARS, shaderText);
622 
623         /*
624          * Declare the uniform samplers using the vertex texture functionality.
625          */
626         get_packed_decl(packedUniform,
627         MAX_SHADER_LINE_CHARS, shaderTempText[0],
628         MAX_SHADER_TEXT_CHARS, shaderText);
629 
630         /*
631          * Declare the outputs.
632          */
633         if (packedOutput->semanticName) {
634                 get_packed_decl(packedOutput,
635                                 MAX_SHADER_LINE_CHARS, shaderTempText[0],
636                                 MAX_SHADER_TEXT_CHARS, shaderText);
637         }
638 
639         shaderTextFree = MAX_SHADER_TEXT_CHARS - strlen(shaderText);
640 
641         /*
642          * Begin main program block.
643          */
644         snprintf(shaderTempText[0], MAX_SHADER_LINE_CHARS,
645                  "void main()\n{\n");
646         strncat(shaderText, shaderTempText[0], shaderTextFree);
647         shaderTextFree -= strlen(shaderTempText[0]);
648 
649         snprintf(shaderTempText[0], MAX_SHADER_LINE_CHARS,
650                  "  vec4 texel;\n");
651         strncat(shaderText, shaderTempText[0], shaderTextFree);
652         shaderTextFree -= strlen(shaderTempText[0]);
653 
654         /*
655          * Passthru the attributes to the outputs.
656          */
657         i = j = k = l = 0;
658 
659         while (i < numScalarOutputs)  {
660                 char *resultStr = " ", *srcStr = " ";
661 
662                 if ((i < packedUniform->count*packedUniform->typeDesc->numComponents) &&
663                     (j % packedUniform->typeDesc->numComponents) == 0) {
664                         snprintf(shaderTempText[0], MAX_SHADER_LINE_CHARS,
665                                  "  texel = texture2D(Texture[%u], vec2(0.0, 0.0));\n",
666                                  i / packedUniform->typeDesc->numComponents);
667                         strncat(shaderText, shaderTempText[0], shaderTextFree);
668                         shaderTextFree -= strlen(shaderTempText[0]);
669                 }
670 
671                 /*
672                  * Iterate through the contents of the texel
673                  */
674                 resultStr = get_packed_reference(packedOutput,
675                                 (i / packedOutput->typeDesc->numComponents),
676                                 (i % packedOutput->typeDesc->numComponents),
677                                 MAX_SHADER_LINE_CHARS,
678                                 shaderTempText[1]);
679 
680                 /* Reset the temp string to avoid cumulative contributions. */
681                 memset(shaderTempText[2], 0, MAX_SHADER_LINE_CHARS);
682 
683                 if (k < numScalarInputs) {
684                         /* Reduce the scalar multiple of the input contributions. */
685                         for (l = 0; l < di_do; l++) {
686                                 srcStr = get_packed_reference(packedInput,
687                                                 (i + (l * numScalarOutputs)) /
688                                                 packedInput->typeDesc->numComponents,
689                                                 (i + (l * numScalarOutputs)) %
690                                                 packedInput->typeDesc->numComponents,
691                                                 MAX_SHADER_LINE_CHARS,
692                                                 shaderTempText[3]);
693 
694                                 if (l > 0) {
695                                         strncat(shaderTempText[2], " * ",
696                                                 MAX_SHADER_LINE_CHARS - strlen(shaderTempText[2]));
697                                 }
698                                 strncat(shaderTempText[2], srcStr,
699                                         MAX_SHADER_LINE_CHARS - strlen(shaderTempText[2]));
700 
701                                 k++;
702                         }
703 
704                         /* Reduce the remaining scalar contributions until exhausted */
705                         if (r) {
706                                 srcStr = get_packed_reference(packedInput,
707                                                 (i + (l * numScalarOutputs)) /
708                                                 packedInput->typeDesc->numComponents,
709                                                 (i + (l * numScalarOutputs)) %
710                                                 packedInput->typeDesc->numComponents,
711                                                 MAX_SHADER_LINE_CHARS,
712                                                 shaderTempText[3]);
713                                 if (l > 0) {
714                                         strncat(shaderTempText[2], " * ",
715                                                 MAX_SHADER_LINE_CHARS - strlen(shaderTempText[2]));
716                                 }
717                                 strncat(shaderTempText[2], srcStr,
718                                         MAX_SHADER_LINE_CHARS - strlen(shaderTempText[2]));
719                                 k++;
720                                 r--;
721                         }
722                         srcStr = shaderTempText[2];
723                 } else {
724                         snprintf(shaderTempText[2], MAX_SHADER_LINE_CHARS,
725                                  "%s", g_floatDesc.defaultValue);
726                         srcStr = shaderTempText[2];
727                 }
728 
729                 if (j < numScalarUniforms) {
730                         if ((g_debugMask & DEBUG_INPUT) && outputDefaultSystemValue) {
731                                 snprintf(shaderTempText[0], MAX_SHADER_LINE_CHARS,
732                                          "  %s = texel%s;\n", resultStr,
733                                          g_vectorComponents[j %
734                                                 packedUniform->typeDesc->numComponents]);
735                         } else {
736                                 snprintf(shaderTempText[0], MAX_SHADER_LINE_CHARS,
737                                          "  %s = texel%s * %s;\n", resultStr,
738                                          g_vectorComponents[j %
739                                                 packedUniform->typeDesc->numComponents],
740                                          srcStr);
741                         }
742                         strncat(shaderText, shaderTempText[0], shaderTextFree);
743                         shaderTextFree -= strlen(shaderTempText[0]);
744                         j++;
745                 } else {
746                         snprintf(shaderTempText[0], MAX_SHADER_LINE_CHARS,
747                                  "  %s = %s%s * %s;\n", resultStr,
748                                  packedUniform->typeDesc->defaultValue,
749                                  g_vectorComponents[0],
750                                  srcStr);
751                         strncat(shaderText, shaderTempText[0], shaderTextFree);
752                         shaderTextFree -= strlen(shaderTempText[0]);
753                 }
754 
755                 /* Increment to the next output. */
756                 i++;
757         }
758 
759         /*
760          * End the main program block.
761          */
762         if (outputDefaultSystemValue) {
763                 snprintf(shaderTempText[0], MAX_SHADER_LINE_CHARS,
764                          "  %s = %s;\n",
765                          outputDefaultSystemValue, defaultSystemValue);
766                 strncat(shaderText, shaderTempText[0], shaderTextFree);
767                 shaderTextFree -= strlen(shaderTempText[0]);
768         }
769 
770         snprintf(shaderTempText[0], MAX_SHADER_LINE_CHARS, "}\n");
771         strncat(shaderText, shaderTempText[0], shaderTextFree);
772         shaderTextFree -= strlen(shaderTempText[0]);
773 
774         for (i = 0; i < sizeof(shaderTempText) / sizeof(char *); i++) {
775                 if (shaderTempText[i]) {
776                         free(shaderTempText[i]);
777                 }
778         }
779 
780         *pShaderText = shaderText;
781         return true;
782 }
783 
784 
785 /**
786  * Core piglit_display callback. This function will bind the FBOs, Textures,
787  * VBOs, IBOs, and draw a primitive using the GLSL shader generated by
788  * build_reduce_glsl_shader.
789  *
790  * Once rendered, a pixel from each of the color attachments is read back and
791  * compared to the final expression value stored in g_expected given the
792  * associated color attachment index.
793  *
794  * \return PIGLIT_PASS if the setup succeeded without error
795  *         PIGLIT_FAIL otherwise.
796  */
797 
798 enum piglit_result
piglit_display(void)799 piglit_display(void)
800 {
801         GLuint vao = 0;
802         GLuint fbo = 0;
803         GLuint *fboTextures = NULL;
804         GLenum *colorBuffers = NULL;
805         GLuint attribLoc;
806         GLfloat result[4];
807         int i = 0;
808 
809         /*
810          * Reserve memory for the FBO texture objects.
811          */
812         fboTextures = calloc(g_maxColorAttachments, sizeof(GLuint));
813 
814         if (NULL == fboTextures) {
815                 fprintf(stderr, "Failed to create FBO texture object container.\n");
816                 goto fail;
817         }
818 
819         /*
820          * Build the color attachments
821          */
822         colorBuffers = calloc(g_maxColorAttachments, sizeof(GLenum));
823 
824         if (NULL == colorBuffers) {
825                 fprintf(stderr, "Failed to create draw buffers descriptor.\n");
826                 goto fail;
827         }
828 
829         /*
830          * Generate an FBO container to hold the color attachment hierarchy.
831          */
832         glGenFramebuffers(1, &fbo);
833         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
834 
835         for (i = 0; i < g_maxColorAttachments; i++) {
836                 setup_fbo_2d(i, GL_RGBA32F, GL_RGBA, GL_FLOAT,
837                              BUFFER_WIDTH, BUFFER_HEIGHT,
838                              fbo, &fboTextures[i]);
839                 colorBuffers[i] = GL_COLOR_ATTACHMENT0 + i;
840         }
841 
842         /*
843          * Build the textures sampled by the shaders
844          */
845         for (i = 0; i < g_maxCombinedTextureImageUnits; i++) {
846                 GLuint tex;
847                 GLuint uniformLoc;
848                 char strTemp[16];
849 
850                 glGenTextures(1, &tex);
851                 glActiveTexture(GL_TEXTURE0 + i);
852                 glBindTexture(GL_TEXTURE_2D, tex);
853                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
854                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
855 
856                 if (((i+1) * MAX_COMPONENTS) > sizeof(g_primes)) {
857                         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0,
858                                      GL_RGBA, GL_UNSIGNED_BYTE, NULL);
859                 } else {
860                         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0,
861                                      GL_RGBA, GL_FLOAT,
862                                      &g_primes[i * MAX_COMPONENTS]);
863                 }
864 
865                 if (!piglit_check_gl_error(GL_NO_ERROR)) {
866                         fprintf(stderr, "Failed to create texture %u.\n", i);
867                         goto fail;
868                 }
869 
870                 snprintf(strTemp, sizeof(strTemp), "Texture[%u]", i);
871                 uniformLoc = glGetUniformLocation(g_program, strTemp);
872                 glUniform1i(uniformLoc, i);
873 
874                 if (!piglit_check_gl_error(GL_NO_ERROR)) {
875                         fprintf(stderr, "Unable to assign texture %u uniform.\n", i);
876                         goto fail;
877                 }
878         }
879 
880         /*
881          * Setup the vertex and element buffers for drawing our points.
882          */
883         if (g_drawMode != DRAW_IMMEDIATE) {
884                 glGenVertexArrays(1, &vao);
885                 glBindVertexArray(vao);
886 
887                 if (!piglit_check_gl_error(GL_NO_ERROR)) {
888                         fprintf(stderr, "Unable to create VAO.\n");
889                         goto fail;
890                 }
891 
892                 setup_vertex_element_buffers();
893         }
894 
895         /*
896          * Setup the raster state.
897          */
898         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
899         glDrawBuffers(g_maxColorAttachments, colorBuffers);
900 
901         if (!piglit_check_gl_error(GL_NO_ERROR)) {
902                 fprintf(stderr, "Unable to assign draw buffers.\n");
903                 goto fail;
904         }
905 
906         glClearColor(0.0, 1.0, 0.0, 0.0);
907         glClear(GL_COLOR_BUFFER_BIT);
908 
909         /*
910          * Bind the vertex array and enable each attribute.
911          */
912         if (g_drawMode != DRAW_IMMEDIATE) {
913                 glBindVertexArray(vao);
914                 attribLoc = glGetAttribLocation(g_program, "InPosition");
915                 glEnableVertexAttribArray(attribLoc);
916 
917                 if (!piglit_check_gl_error(GL_NO_ERROR)) {
918                         fprintf(stderr,
919                                 "Unable to enable vertex array attribute %u.\n",
920                                 attribLoc);
921                         goto fail;
922                 }
923 
924                 /*
925                  * Enable the rest of the attributes.
926                  */
927                 for (i = 0; i < g_maxVertexAttribs - 1; i++) {
928                         char strTemp[16];
929 
930                         snprintf(strTemp, sizeof(strTemp), "InValue%u", i);
931                         attribLoc = glGetAttribLocation(g_program, strTemp);
932                         glEnableVertexAttribArray(attribLoc);
933 
934                         if (!piglit_check_gl_error(GL_NO_ERROR)) {
935                                 fprintf(stderr,
936                                         "Unable to enable vertex array attribute %u.\n",
937                                         attribLoc);
938                                 goto fail;
939                         }
940                 }
941 
942                 if (g_drawMode == DRAW_ARRAYS_VBO) {
943                         if (g_debugMask & DEBUG_DRAW) {
944                                 fprintf(stderr, "Draw mode DRAW_ARRAYS_VBO\n");
945                         }
946                         glDrawArrays(GL_TRIANGLES, 0, NUM_VERTICES);
947                 }
948 
949                 if (g_drawMode == DRAW_ELEMENTS_VBO) {
950                         if (g_debugMask & DEBUG_DRAW) {
951                                 fprintf(stderr,
952                                         "Draw mode DRAW_ELEMENTS_VBO\n");
953                         }
954                         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_elementVBO);
955                         glDrawElements(GL_TRIANGLES, NUM_VERTICES,
956                                        GL_UNSIGNED_SHORT, 0);
957                         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
958                 }
959 
960                 /*
961                  * Blindly reset all the attributes.
962                  */
963                 for (i = 0; i < g_maxVertexAttribs; i++) {
964                         glDisableVertexAttribArray(i);
965                 }
966         } else {
967                 glBegin(GL_TRIANGLES);
968                 glVertex3f(-1.0, -1.0, 0.0);
969                 glVertex3f(-1.0, 1.0, 0.0);
970                 glVertex3f(1.0, 1.0, 0.0);
971                 glEnd();
972         }
973 
974         if (!piglit_check_gl_error(GL_NO_ERROR))
975                 goto fail;
976 
977         /*
978          * Read back the FBO contents.
979          */
980 
981         /*
982          * Disable color clamping so we don't encounter result
983          * collisions attempting to use a normalized color space.
984          *
985          * Requires OpenGL 3.0
986          */
987         glClampColor(GL_CLAMP_READ_COLOR, GL_FALSE);
988 
989         for (i = 0; i < g_maxColorAttachments; i++) {
990                 if (g_debugMask & DEBUG_READBACK) {
991                         printf("GL_READ_FRAMEBUFFER <- fbo=%u\n", fbo);
992                 }
993 
994                 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
995 
996                 if (!piglit_check_gl_error(GL_NO_ERROR))
997                         goto fail;
998 
999                 glFramebufferTexture2D(GL_READ_FRAMEBUFFER,
1000                                        GL_COLOR_ATTACHMENT0,
1001                                        GL_TEXTURE_2D,
1002                                        fboTextures[i],
1003                                        0);
1004 
1005                 if (!piglit_check_gl_error(GL_NO_ERROR))
1006                         goto fail;
1007 
1008                 glPixelStorei(GL_PACK_ALIGNMENT, 1);
1009                 glReadBuffer(GL_COLOR_ATTACHMENT0);
1010 
1011                 if (!piglit_check_gl_error(GL_NO_ERROR))
1012                         goto fail;
1013 
1014                 glReadPixels(0, BUFFER_HEIGHT - 1,
1015                              1, 1, GL_RGBA, GL_FLOAT, result);
1016 
1017                 if ((g_expected[(i * MAX_COMPONENTS) + 0] != result[0]) ||
1018                     (g_expected[(i * MAX_COMPONENTS) + 1] != result[1]) ||
1019                     (g_expected[(i * MAX_COMPONENTS) + 2] != result[2]) ||
1020                     (g_expected[(i * MAX_COMPONENTS) + 3] != result[3])) {
1021                         fprintf(stderr, "GL_COLOR_ATTACHMENT%u: expected "
1022                                         "(%f, %f, %f, %f) != (%f, %f, %f, %f)\n",
1023                                 i, g_expected[(i * MAX_COMPONENTS) + 0],
1024                                 g_expected[(i * MAX_COMPONENTS) + 1],
1025                                 g_expected[(i * MAX_COMPONENTS) + 2],
1026                                 g_expected[(i * MAX_COMPONENTS) + 3],
1027                                 result[0], result[1], result[2], result[3]);
1028 
1029                         goto fail;
1030                 }
1031         }
1032 
1033         piglit_present_results();
1034 
1035         /*
1036          * Cleanup the allocations.
1037          */
1038         free(colorBuffers);
1039         free(fboTextures);
1040 
1041         piglit_report_result(PIGLIT_PASS);
1042 
1043         return PIGLIT_PASS;
1044 
1045 fail:
1046 
1047         if (colorBuffers)
1048                 free(colorBuffers);
1049 
1050         if (fboTextures)
1051                 free(fboTextures);
1052 
1053         piglit_report_result(PIGLIT_FAIL);
1054 
1055         return PIGLIT_FAIL;
1056 }
1057 
1058 
1059 /**
1060  * Core piglit_init callback. This function will query the implementation for
1061  * the maximum number of supported resources. We attempt to create a GLSL
1062  * shader which references all supported resources bindable within the GL 3.0
1063  * specification.
1064  *
1065  * Each resource will be populated with a unique prime value. This function is
1066  * also responsible for calculating the expected value and storing this in
1067  * the g_expected array.
1068  *
1069  * Note: If the number of primes is insufficient to assign a unique prime to
1070  *       each resource, we will exit with PIGLIT_SKIP.
1071  *
1072  * Results: PIGLIT_PASS if the setup succeeded without error
1073  *          PIGLIT_FAIL otherwise.
1074  */
1075 
1076 void
piglit_init(int argc,char ** argv)1077 piglit_init(int argc, char **argv)
1078 {
1079         GLfloat *var;
1080         PackedDesc vsInput = { "in", "InValue", false, 0, &g_vec4Desc };
1081         PackedDesc vsUniform = { "uniform", "Texture", true, 0, &g_sampler2DDesc };
1082         PackedDesc vsOutput = { "out", "Variable", true, 0, &g_floatDesc };
1083         PackedDesc fsInput = { "in", "Variable", true, 0, &g_floatDesc };
1084         PackedDesc fsUniform = { "uniform", "Texture", true, 0, &g_sampler2DDesc };
1085         PackedDesc fsOutput = { NULL, g_fragData, true, 0, &g_rgbaDesc };
1086         char shaderTempText[MAX_SHADER_LINE_CHARS];
1087         char *vertexShaderText = (char *)g_vertexShaderText;
1088         char *fragmentShaderText = (char *)g_fragmentShaderText;
1089         int i = 0;
1090 
1091         piglit_require_gl_version(30);
1092 
1093         for (i = 1; i < argc; i++) {
1094                 if (strcmp(argv[i], "-drawArraysVBO") == 0) {
1095                         g_drawMode = DRAW_ARRAYS_VBO;
1096                 }
1097                 if (strcmp(argv[i], "-drawElementsVBO") == 0) {
1098                         g_drawMode = DRAW_ELEMENTS_VBO;
1099                 }
1100                 if (strcmp(argv[i], "-drawImmediate") == 0) {
1101                         g_drawMode = DRAW_IMMEDIATE;
1102                 }
1103                 if (strcmp(argv[i], "-debugInput") == 0) {
1104                         g_debugMask |= DEBUG_INPUT;
1105                 }
1106                 if (strcmp(argv[i], "-debugReadback") == 0) {
1107                         g_debugMask |= DEBUG_READBACK;
1108                 }
1109                 if (strcmp(argv[i], "-debugShaders") == 0) {
1110                         g_debugMask |= DEBUG_SHADERS;
1111                 }
1112                 if (strcmp(argv[i], "-debugDraw") == 0) {
1113                         g_debugMask |= DEBUG_DRAW;
1114                 }
1115                 if (strcmp(argv[i], "-dontClampMaxVaryings") == 0) {
1116                         g_debugMask |= DEBUG_DONT_CLAMP_MAX_VARYINGS;
1117                 }
1118         }
1119 
1120         /*
1121          * Query the sampler capabilities.
1122          */
1123         glGetIntegerv(GL_MAX_VARYING_FLOATS, &g_maxVaryingFloats);
1124         glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &g_maxVertexAttribs);
1125         glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,
1126                       &g_maxVertexTextureImageUnits);
1127         glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS,
1128                       &g_maxTextureImageUnits);
1129         glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
1130                       &g_maxCombinedTextureImageUnits);
1131 
1132         printf("GL_MAX_VARYING_FLOATS: %d\n", g_maxVaryingFloats);
1133         printf("GL_MAX_VERTEX_ATTRIBS: %d\n", g_maxVertexAttribs);
1134         printf("GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: %d\n",
1135                g_maxVertexTextureImageUnits);
1136         printf("GL_MAX_TEXTURE_IMAGE_UNITS: %d\n",
1137                g_maxTextureImageUnits);
1138         printf("GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: %d\n",
1139                g_maxCombinedTextureImageUnits);
1140 
1141         /*
1142          * Query the render target capabilities.
1143          */
1144         glGetIntegerv(GL_AUX_BUFFERS, &g_maxAuxBuffers);
1145         glGetIntegerv(GL_MAX_DRAW_BUFFERS, &g_maxDrawBuffers);
1146         glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &g_maxColorAttachments);
1147 
1148         if (g_maxColorAttachments == 1) {
1149                 fsOutput.variableName = g_fragColor;
1150         }
1151 
1152         printf("GL_AUX_BUFFERS: %d\n", g_maxAuxBuffers);
1153         printf("GL_MAX_DRAW_BUFFERS: %d\n", g_maxDrawBuffers);
1154         printf("GL_MAX_COLOR_ATTACHMENTS: %d\n", g_maxColorAttachments);
1155 
1156         if ((g_maxColorAttachments * MAX_COMPONENTS > NUM_PRIMES) ||
1157             (g_maxVaryingFloats > NUM_PRIMES) ||
1158             (g_maxVertexAttribs * MAX_COMPONENTS > NUM_PRIMES) ||
1159             (g_maxVertexTextureImageUnits * MAX_COMPONENTS > NUM_PRIMES) ||
1160             (g_maxTextureImageUnits * MAX_COMPONENTS > NUM_PRIMES)) {
1161                 fprintf(stderr, "Unable to uniquely represent a result path.\n");
1162                 piglit_report_result(PIGLIT_SKIP);
1163         }
1164 
1165         /*
1166          * Clamp the max varyings by default to work around large array
1167          * issues with some GLSL implementations.
1168          */
1169         if ((g_debugMask & DEBUG_DONT_CLAMP_MAX_VARYINGS) == 0) {
1170                 g_maxVaryingFloats = MIN2(g_maxVaryingFloats, 32);
1171                 fprintf(stderr, "Clamped max varying floats to %u.\n",
1172                 g_maxVaryingFloats);
1173         }
1174 
1175         if (g_drawMode == DRAW_IMMEDIATE) {
1176                 g_maxVertexAttribs = 1;
1177                 fprintf(stderr,
1178                         "Immediate mode selected, using only one vertex attrib.\n");
1179         }
1180 
1181         /*
1182          * Build the shaders based upon the queried limits.
1183          */
1184         vsInput.count = g_maxVertexAttribs - 1;
1185         vsUniform.count = g_maxVertexTextureImageUnits;
1186         vsOutput.count = g_maxVaryingFloats;
1187         if (!build_reduce_glsl_shader(&vsInput,
1188                                       &vsUniform,
1189                                       &vsOutput,
1190                                       "gl_Position",
1191                                       "in vec4 InPosition;",
1192                                       "InPosition",
1193                                       &vertexShaderText)) {
1194                 fprintf(stderr, "Failed to build GLSL vertex shader\n");
1195                 piglit_report_result(PIGLIT_SKIP);
1196         }
1197 
1198         if (g_debugMask & DEBUG_SHADERS) {
1199                 printf("vertexShaderText:\n%s", vertexShaderText);
1200         }
1201 
1202         fsInput.count = g_maxVaryingFloats;
1203         fsUniform.count = g_maxTextureImageUnits;
1204         fsOutput.count = g_maxColorAttachments;
1205         if (!build_reduce_glsl_shader(&fsInput,
1206                                       &fsUniform,
1207                                       &fsOutput,
1208                                       NULL,
1209                                       NULL,
1210                                       NULL,
1211                                       &fragmentShaderText)) {
1212                 fprintf(stderr, "Failed to build GLSL vertex shader\n");
1213                 piglit_report_result(PIGLIT_SKIP);
1214         }
1215 
1216         if (g_debugMask & DEBUG_SHADERS) {
1217                 printf("fragmentShaderText:\n%s", fragmentShaderText);
1218         }
1219 
1220         /*
1221          * Build the vertex and fragment shaders.
1222          */
1223         g_program = piglit_build_simple_program(vertexShaderText,
1224                                                 fragmentShaderText);
1225         if (!g_program) {
1226                 fprintf(stderr, "Failed to compile/link program\n");
1227                 piglit_report_result(PIGLIT_SKIP);
1228         }
1229 
1230         snprintf(shaderTempText, sizeof(shaderTempText), "InPosition");
1231         glBindAttribLocation(g_program, 0, shaderTempText);
1232 
1233         for (i = 0; i < g_maxVertexAttribs - 1; i++) {
1234                 snprintf(shaderTempText, sizeof(shaderTempText), "InValue%u", i);
1235                 glBindAttribLocation(g_program, i+1, shaderTempText);
1236         }
1237 
1238         if (g_debugMask & DEBUG_SHADERS) {
1239                 printf("Linking program...\n");
1240         }
1241 
1242         glLinkProgram(g_program);
1243         glUseProgram(g_program);
1244 
1245         if (!piglit_check_gl_error(GL_NO_ERROR)) {
1246                 fprintf(stderr, "Failure to link shaders\n");
1247                 fprintf(stderr, "vertexShaderText:\n%s", vertexShaderText);
1248                 fprintf(stderr, "fragmentShaderText:\n%s", fragmentShaderText);
1249                 free(vertexShaderText);
1250                 free(fragmentShaderText);
1251                 piglit_report_result(PIGLIT_FAIL);
1252         }
1253 
1254         if (g_debugMask & DEBUG_SHADERS) {
1255                 printf("Using program %u...\n", g_program);
1256         }
1257 
1258         /* Delete the interim copies generated by build_reduce_glsl_shader */
1259         free(vertexShaderText);
1260         free(fragmentShaderText);
1261 
1262         /*
1263          * Calculate the expected results for the bound resource limits.
1264          */
1265         var = calloc(g_maxVaryingFloats, sizeof(GLfloat));
1266 
1267         if (NULL == var) {
1268                 fprintf(stderr,
1269                         "Failed to allocate temporary array for expected calculation.\n");
1270                 piglit_report_result(PIGLIT_FAIL);
1271         }
1272 
1273         g_expected = calloc(g_maxColorAttachments, sizeof(GLfloat)*MAX_COMPONENTS);
1274 
1275         if (NULL == g_expected) {
1276                 fprintf(stderr, "Failed to allocate array for expected calculation.\n");
1277                 piglit_report_result(PIGLIT_FAIL);
1278         }
1279 
1280         /*
1281          * Sampler coverage up to the total number of varying floats.
1282          */
1283         for (i = 0; i < g_maxVaryingFloats; i++) {
1284                 if ((i < g_maxVertexTextureImageUnits*MAX_COMPONENTS) &&
1285                     (i < NUM_PRIMES)) {
1286                         var[i] = g_primes[i];
1287                 } else {
1288                         var[i] = 1.0;
1289                 }
1290         }
1291 
1292         /*
1293          * Multiply in all vertex attributes.
1294          */
1295         i = 0;
1296         while (i < (g_maxVertexAttribs-1)*MAX_COMPONENTS) {
1297                 if (i < NUM_PRIMES) {
1298                         var[i % g_maxVaryingFloats] *= g_primes[i];
1299                 } else {
1300                         var[i % g_maxVaryingFloats] *= 1.0;
1301                 }
1302                 i++;
1303         }
1304 
1305         /*
1306          * Calculate the expected values for the FS stage.
1307          *
1308          * Sampler cover up to the total number of varying floats.
1309          */
1310         for (i = 0; i < g_maxColorAttachments*MAX_COMPONENTS; i++) {
1311                 if ((i < g_maxVertexTextureImageUnits*MAX_COMPONENTS) &&
1312                     (i < NUM_PRIMES)) {
1313                         g_expected[i] = g_primes[i];
1314                 } else {
1315                         g_expected[i] = 1.0;
1316                 }
1317         }
1318 
1319         /*
1320          * Multiply in all the varying contributions generated by the VS.
1321          */
1322         i = 0;
1323         while (i < g_maxVaryingFloats) {
1324                 g_expected[i % (g_maxColorAttachments*MAX_COMPONENTS)] *= var[i];
1325                 i++;
1326         }
1327 
1328         for (i = 0; i < g_maxColorAttachments; i++) {
1329                 printf("g_expected[%u]=(%f, %f, %f, %f)\n", i,
1330                        g_expected[(i * MAX_COMPONENTS) + 0],
1331                        g_expected[(i * MAX_COMPONENTS) + 1],
1332                        g_expected[(i * MAX_COMPONENTS) + 2],
1333                        g_expected[(i * MAX_COMPONENTS) + 3]);
1334         }
1335 
1336         free(var);
1337 }
1338