1 /*
2  * Copyright (c) 2011 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  * on the rights to use, copy, modify, merge, publish, distribute, sub
8  * license, and/or sell copies of the Software, and to permit persons to whom
9  * the 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,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18  * NON-INFRINGEMENT.  IN NO EVENT SHALL VMWARE AND/OR THEIR SUPPLIERS
19  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 
25 /**
26  * Tests GL_ARB_texture_float floating point formats
27  */
28 
29 #include "piglit-util-gl.h"
30 
31 PIGLIT_GL_TEST_CONFIG_BEGIN
32 
33 	config.supports_gl_compat_version = 10;
34 
35 	config.window_visual = PIGLIT_GL_VISUAL_RGBA | PIGLIT_GL_VISUAL_DOUBLE;
36 
37 PIGLIT_GL_TEST_CONFIG_END
38 
39 static const char *TestName = "texture-float-formats";
40 static GLint TexWidth = 16, TexHeight = 16;
41 static GLint BiasUniform = -1, ScaleUniform = -1, TexUniform = -1;
42 static const float Scale = 1.0 / 2000.0, Bias = 0.5;
43 static GLboolean HaveRG;
44 
45 
46 struct format_info
47 {
48    GLenum IntFormat, BaseFormat;
49    GLuint BitsPerChannel;
50 };
51 
52 
53 static const struct format_info Formats[] = {
54    { GL_RGBA32F_ARB, GL_RGBA, 32 },
55    { GL_RGB32F_ARB, GL_RGB, 32 },
56    { GL_ALPHA32F_ARB, GL_ALPHA, 32 },
57    { GL_INTENSITY32F_ARB, GL_INTENSITY, 32 },
58    { GL_LUMINANCE32F_ARB, GL_LUMINANCE, 32 },
59    { GL_LUMINANCE_ALPHA32F_ARB, GL_LUMINANCE, 32 },
60 
61    { GL_RGBA16F_ARB, GL_RGBA, 16 },
62    { GL_RGB16F_ARB, GL_RGB, 16 },
63    { GL_ALPHA16F_ARB, GL_ALPHA, 16 },
64    { GL_INTENSITY16F_ARB, GL_INTENSITY, 16 },
65    { GL_LUMINANCE16F_ARB, GL_LUMINANCE, 16 },
66    { GL_LUMINANCE_ALPHA16F_ARB, GL_LUMINANCE, 16 },
67 
68    /* These require GL_ARB_texture_rg */
69    { GL_R32F, GL_RED, 32 },
70    { GL_RG32F, GL_RG, 32 },
71    { GL_R16F, GL_RED, 16 },
72    { GL_RG16F, GL_RG, 16 },
73 };
74 
75 
76 static const char *FragShaderText =
77    "uniform float bias, scale; \n"
78    "uniform sampler2D tex; \n"
79    "void main() \n"
80    "{ \n"
81    "   vec4 t = vec4(texture2D(tex, gl_TexCoord[0].xy)); \n"
82    "   gl_FragColor = t * scale + bias; \n"
83    "} \n";
84 
85 
86 static GLuint Program;
87 
88 
89 
90 static int
num_components(GLenum format)91 num_components(GLenum format)
92 {
93    switch (format) {
94    case GL_RGBA:
95       return 4;
96    case GL_RGB:
97       return 3;
98    case GL_ALPHA:
99       return 1;
100    case GL_INTENSITY:
101       return 1;
102    case GL_LUMINANCE:
103       return 1;
104    case GL_LUMINANCE_ALPHA:
105       return 2;
106    case GL_RED:
107       return 1;
108    case GL_RG:
109       return 2;
110    default:
111       assert(0);
112       return 0;
113    }
114 }
115 
116 
117 static void
fill_array(int comps,int texels,void * buf,const float val[4])118 fill_array(int comps, int texels, void *buf, const float val[4])
119 {
120    GLfloat *f = (GLfloat *) buf;
121    int i, j;
122 
123    for (i = 0; i < texels; i++) {
124       for (j = 0; j < comps; j++) {
125          f[i * comps + j] = val[j];
126       }
127    }
128 }
129 
130 
131 static GLboolean
check_error(const char * file,int line)132 check_error(const char *file, int line)
133 {
134    GLenum err = glGetError();
135    if (err) {
136       printf("%s: error 0x%x at %s:%d\n", TestName, err, file, line);
137       return GL_TRUE;
138    }
139    return GL_FALSE;
140 }
141 
142 
143 /** Scale a float in [-1000, 1000] to [0, 1] */
144 static float
scale_and_bias(float val)145 scale_and_bias(float val)
146 {
147    return val * Scale + Bias;
148 }
149 
150 
151 /**
152  * Get a color to use for filling the texture image.
153  * Range of values is [-1000, 1000]
154  */
155 static void
get_texture_color(GLfloat value[4])156 get_texture_color(GLfloat value[4])
157 {
158    static const GLfloat colors[12][4] = {
159       { 690.0, 633.0, -649.0, -975.0 },
160       { 409.0, -678.0, 624.0, -976.0 },
161       { -460.0, -102.0, -983.0, 120.0 },
162       { 202.0, 75.0, 826.0, -339.0 },
163       { -709.0, 620.0, 204.0, -666.0 },
164       { 718.0, -299.0, 290.0, 383.0 },
165       { 634.0, 235.0, 571.0, -651.0 },
166       { -984.0, -99.0, 448.0, 263.0 },
167       { -466.0, 356.0, -155.0, 500.0 },
168       { 678.0, -531.0, 81.0, -783.0 },
169       { -76.0, 98.0, -106.0, -875.0 },
170       { 730.0, -723.0, -656.0, -980.0 }
171    };
172    static int i = 0;
173    value[0] = colors[i][0];
174    value[1] = colors[i][1];
175    value[2] = colors[i][2];
176    value[3] = colors[i][3];
177    i = (i + 1) % 12;
178 }
179 
180 
181 /** \return GL_TRUE for pass, GL_FALSE for fail */
182 static GLboolean
test_format(const struct format_info * info)183 test_format(const struct format_info *info)
184 {
185    const int comps = num_components(info->BaseFormat);
186    const int texels = TexWidth * TexHeight;
187    const int w = piglit_width / 10;
188    const int h = piglit_height / 10;
189    GLfloat expected[4];
190    void *image;
191    float value[4];
192    GLint f;
193    GLenum userFormat;
194    int p;
195    const char *name = piglit_get_gl_enum_name(info->IntFormat);
196 
197    if ((info->BaseFormat == GL_RED ||
198         info->BaseFormat == GL_RG) && !HaveRG) {
199       /* skip it */
200       return GL_TRUE;
201    }
202 
203    /*printf("Testing %s\n", name);*/
204 
205    get_texture_color(value);
206 
207    /* alloc, fill texture image */
208    image = malloc(comps * texels * sizeof(GLfloat));
209    fill_array(comps, texels, image, value);
210 
211    /* GL_INTENSITY is not a legal src format */
212    userFormat = info->BaseFormat == GL_INTENSITY ? GL_LUMINANCE : info->BaseFormat;
213 
214    glTexImage2D(GL_TEXTURE_2D, 0, info->IntFormat, TexWidth, TexHeight, 0,
215                 userFormat, GL_FLOAT, image);
216    free(image);
217 
218    if (check_error(__FILE__, __LINE__))
219       return GL_FALSE;
220 
221    /* check internal format */
222    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &f);
223    if (f != info->IntFormat) {
224       printf("%s: GL_TEXTURE_INTERNAL_FORMAT query failed for 0x%x\n",
225              TestName,
226              info->IntFormat);
227       return GL_FALSE;
228    }
229 
230    /* check texture datatype info */
231    {
232       static const GLenum queries[] = {
233          GL_TEXTURE_RED_TYPE_ARB,
234          GL_TEXTURE_GREEN_TYPE_ARB,
235          GL_TEXTURE_BLUE_TYPE_ARB,
236          GL_TEXTURE_ALPHA_TYPE_ARB,
237          GL_TEXTURE_LUMINANCE_TYPE_ARB,
238          GL_TEXTURE_INTENSITY_TYPE_ARB,
239          GL_TEXTURE_DEPTH_TYPE_ARB
240       };
241       int i;
242       for (i = 0; i < ARRAY_SIZE(queries); i++) {
243          GLint type = 1;
244          glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, queries[i], &type);
245          if (check_error(__FILE__, __LINE__))
246             return GL_FALSE;
247          if (type != GL_NONE && type != GL_FLOAT) {
248             printf("%s: %s query failed (returned 0x%x)\n",
249                    TestName, piglit_get_gl_enum_name(queries[i]), type);
250             return GL_FALSE;
251          }
252       }
253    }
254 
255    /* compute expected color */
256    switch (info->BaseFormat) {
257    case GL_RGBA:
258       expected[0] = scale_and_bias(value[0]);
259       expected[1] = scale_and_bias(value[1]);
260       expected[2] = scale_and_bias(value[2]);
261       expected[3] = scale_and_bias(value[3]);
262       break;
263    case GL_RGB:
264       expected[0] = scale_and_bias(value[0]);
265       expected[1] = scale_and_bias(value[1]);
266       expected[2] = scale_and_bias(value[2]);
267       expected[3] = scale_and_bias(1.0);
268       break;
269    case GL_ALPHA:
270       expected[0] =
271       expected[1] =
272       expected[2] = scale_and_bias(0.0);
273       expected[3] = scale_and_bias(value[0]);
274       break;
275    case GL_LUMINANCE:
276       expected[0] =
277       expected[1] =
278       expected[2] = scale_and_bias(value[0]);
279       expected[3] = scale_and_bias(1.0);
280       break;
281    case GL_INTENSITY:
282       expected[0] =
283       expected[1] =
284       expected[2] =
285       expected[3] = scale_and_bias(value[0]);
286       break;
287    case GL_LUMINANCE_ALPHA:
288       expected[0] =
289       expected[1] =
290       expected[2] = scale_and_bias(value[0]);
291       expected[3] = scale_and_bias(value[1]);
292       break;
293    case GL_RED:
294       expected[0] = scale_and_bias(value[0]);
295       expected[1] = scale_and_bias(0.0);
296       expected[2] = scale_and_bias(0.0);
297       expected[3] = scale_and_bias(1.0);
298       break;
299    case GL_RG:
300       expected[0] = scale_and_bias(value[0]);
301       expected[1] = scale_and_bias(value[1]);
302       expected[2] = scale_and_bias(0.0);
303       expected[3] = scale_and_bias(1.0);
304       break;
305    default:
306       abort();
307    }
308 
309    /* draw */
310    glClearColor(0.5, 0.5, 0.5, 0.0);
311    glClear(GL_COLOR_BUFFER_BIT);
312    glBegin(GL_POLYGON);
313    glTexCoord2f(0, 0);   glVertex2f(0, 0);
314    glTexCoord2f(1, 0);   glVertex2f(w, 0);
315    glTexCoord2f(1, 1);   glVertex2f(w, h);
316    glTexCoord2f(0, 1);   glVertex2f(0, h);
317    glEnd();
318 
319    /* test */
320    p = piglit_probe_pixel_rgba(w/2, h/2, expected);
321    if (!p) {
322       int i;
323 
324       printf("  Failed with format %s:\n", name);
325       printf("  Texture color = ");
326       for (i = 0; i < comps; i++) {
327          printf("%f", value[i]);
328          if (i + 1 < comps)
329             printf(", ");
330       }
331       printf("\n");
332    }
333 
334    piglit_present_results();
335 
336    return p;
337 }
338 
339 
340 enum piglit_result
piglit_display(void)341 piglit_display(void)
342 {
343    int f;
344    GLboolean pass = GL_TRUE;
345 
346    for (f = 0; f < ARRAY_SIZE(Formats); f++)
347       if (!test_format(&Formats[f]))
348          pass = GL_FALSE;
349 
350    return pass ? PIGLIT_PASS : PIGLIT_FAIL;
351 }
352 
353 
354 void
piglit_init(int argc,char ** argv)355 piglit_init(int argc, char **argv)
356 {
357    GLuint Texture;
358 
359    piglit_require_extension("GL_ARB_texture_float");
360    piglit_require_extension("GL_ARB_fragment_shader");
361 
362    HaveRG = piglit_is_extension_supported("GL_ARB_texture_rg");
363 
364    Program = piglit_build_simple_program(NULL, FragShaderText);
365 
366    glUseProgram(Program);
367 
368    BiasUniform = glGetUniformLocation(Program, "bias");
369    ScaleUniform = glGetUniformLocation(Program, "scale");
370    TexUniform = glGetUniformLocation(Program, "tex");
371 
372    glUniform1f(BiasUniform, Bias);
373    glUniform1f(ScaleUniform, Scale);
374    glUniform1i(TexUniform, 0);  /* tex unit zero */
375 
376    (void) check_error(__FILE__, __LINE__);
377 
378    glGenTextures(1, &Texture);
379    glBindTexture(GL_TEXTURE_2D, Texture);
380    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
381    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
382 
383    piglit_ortho_projection(piglit_width, piglit_height, GL_FALSE);
384 }
385