1 /*
2  * Copyright (c) 2004 Brian Paul
3  * Copyright (c) 2011 VMware, Inc.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22  * IN THE SOFTWARE.
23  */
24 
25 /*
26  * Test packed pixel formats for textures.  Try a bunch of combinations
27  * of various internal texture formats with combinations of packed user
28  * formats/types.  Also test glPixelStore byte swapping.
29  *
30  * Based on mesa-demos/tests/packedpixels.c.
31  * Brian Paul
32  * June 2011
33  */
34 
35 
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <math.h>
39 #include <string.h>
40 #include "piglit-util-gl.h"
41 
42 PIGLIT_GL_TEST_CONFIG_BEGIN
43 
44 config.supports_gl_compat_version = 10;
45 
46 config.window_width = 700;
47 config.window_height = 620;
48 config.window_visual = PIGLIT_GL_VISUAL_RGB | PIGLIT_GL_VISUAL_DOUBLE;
49 config.khr_no_error_support = PIGLIT_NO_ERRORS;
50 
51 PIGLIT_GL_TEST_CONFIG_END
52 
53 struct pixel_format {
54 	GLenum format;
55 	GLenum type;
56 	GLint bytes;
57 	GLuint redTexel, greenTexel; /* with approx 51% alpha, when applicable */
58 };
59 
60 static const struct pixel_format Formats[] = {
61 
62 	{ GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, 4, 0xff000080, 0x00ff0080 },
63 	{ GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, 4, 0x800000ff, 0x8000ff00 },
64 	{ GL_RGBA, GL_UNSIGNED_INT_10_10_10_2, 4, 0xffc00002, 0x3ff002 },
65 	{ GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, 4, 0xc00003ff, 0xc00ffc00 },
66 	{ GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 2, 0xf008, 0x0f08 },
67 	{ GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4_REV, 2, 0x800f, 0x80f0 },
68 	{ GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, 2, 0xf801, 0x7c1 },
69 	{ GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, 2, 0x801f, 0x83e0 },
70 
71 	{ GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, 4, 0x0000ff80, 0x00ff0080 },
72 	{ GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 4, 0x80ff0000, 0x8000ff00 },
73 	{ GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4, 2, 0x00f8, 0x0f08 },
74 	{ GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV, 2, 0x8f00, 0x80f0 },
75 	{ GL_BGRA, GL_UNSIGNED_SHORT_5_5_5_1, 2, 0x3f, 0x7c1 },
76 	{ GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, 2, 0xfc00, 0x83e0 },
77 
78 	{ GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 2, 0xf800, 0x7e0 },
79 	{ GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV, 2, 0x1f, 0x7e0 },
80 	{ GL_RGB, GL_UNSIGNED_BYTE_3_3_2, 1, 0xe0, 0x1c },
81 	{ GL_RGB, GL_UNSIGNED_BYTE_2_3_3_REV, 1, 0x7, 0x38 }
82 };
83 
84 #define NUM_FORMATS (sizeof(Formats) / sizeof(Formats[0]))
85 
86 static const GLenum IntFormats[] = {
87 	GL_RGBA,
88 	GL_RGBA2,
89 	GL_RGBA4,
90 	GL_RGB5_A1,
91 	GL_RGBA8,
92 	GL_RGBA12,
93 	GL_RGBA16,
94 	GL_RGB10_A2,
95 
96 	GL_RGB,
97 	GL_R3_G3_B2,
98 	GL_RGB4,
99 	GL_RGB5,
100 	GL_RGB8,
101 	GL_RGB10,
102 	GL_RGB12,
103 	GL_RGB16,
104 
105 };
106 
107 #define NUM_INT_FORMATS (sizeof(IntFormats) / sizeof(IntFormats[0]))
108 
109 static void
MakeTexture(GLuint dims,const struct pixel_format * format,GLenum intFormat,GLboolean swap)110 MakeTexture(GLuint dims, const struct pixel_format *format,
111             GLenum intFormat, GLboolean swap)
112 {
113 	GLubyte texBuffer[1000];
114 	int i;
115 
116 	assert(dims == 2 || dims == 3);
117 
118 	glPixelStorei(GL_UNPACK_SWAP_BYTES, swap);
119 
120 	if (format->bytes == 1) {
121 		for (i = 0; i < 8; i++) {
122 			texBuffer[i] = format->redTexel;
123 		}
124 		for (i = 8; i < 16; i++) {
125 			texBuffer[i] = format->greenTexel;
126 		}
127 	}
128 	else if (format->bytes == 2) {
129 		GLushort *us = (GLushort *) texBuffer;
130 		for (i = 0; i < 8; i++) {
131 			us[i] = format->redTexel;
132 		}
133 		for (i = 8; i < 16; i++) {
134 			us[i] = format->greenTexel;
135 		}
136 		if (swap) {
137 			for (i = 0; i < 16; i++)
138 				us[i] = (us[i] << 8) | (us[i] >> 8);
139 		}
140 	}
141 	else if (format->bytes == 4) {
142 		GLuint *ui = (GLuint *) texBuffer;
143 		for (i = 0; i < 8; i++) {
144 			ui[i] = format->redTexel;
145 		}
146 		for (i = 8; i < 16; i++) {
147 			ui[i] = format->greenTexel;
148 		}
149 		if (swap) {
150 			for (i = 0; i < 16; i++) {
151 				GLuint b = ui[i];
152 				ui[i] =  (b >> 24)
153 					| ((b >> 8) & 0xff00)
154 					| ((b << 8) & 0xff0000)
155 					| ((b << 24) & 0xff000000);
156 			}
157 		}
158 	}
159 	else {
160 		abort();
161 	}
162 
163 	if (dims == 3) {
164 		/* 4 x 4 x 4 texture, undefined data */
165 		glTexImage3D(GL_TEXTURE_3D, 0, intFormat, 4, 4, 4, 0,
166 			     format->format, format->type, NULL);
167 		/* fill in Z=1 and Z=2 slices with the real texture data */
168 		glTexSubImage3D(GL_TEXTURE_3D, 0,
169 				0, 0, 1,  /* offset */
170 				4, 4, 1,  /* size */
171 				format->format, format->type, texBuffer);
172 		glTexSubImage3D(GL_TEXTURE_3D, 0,
173 				0, 0, 2,  /* offset */
174 				4, 4, 1,  /* size */
175 				format->format, format->type, texBuffer);
176 	}
177 	else {
178 		glTexImage2D(GL_TEXTURE_2D, 0, intFormat, 4, 4, 0,
179 			     format->format, format->type, texBuffer);
180 	}
181 
182 	if (0) {
183 		GLint r, g, b, a, l, i;
184 		glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_RED_SIZE, &r);
185 		glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_GREEN_SIZE, &g);
186 		glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BLUE_SIZE, &b);
187 		glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_ALPHA_SIZE, &a);
188 		glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_LUMINANCE_SIZE, &l);
189 		glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTENSITY_SIZE, &i);
190 		printf("IntFormat: 0x%x  R %d  G %d  B %d  A %d  L %d  I %d\n",
191 		       intFormat, r, g, b, a, l, i);
192 		glGetError();
193 	}
194 }
195 
196 /**
197  * Test a particular internal texture format.  2D or 3D texture.
198  */
199 static GLboolean
Test(GLuint intFmt,GLuint dims)200 Test(GLuint intFmt, GLuint dims)
201 {
202 	static const float red[4] = {1, 0, 0, 1};
203 	static const float green[4] = {0, 1, 0, 1};
204 	int w = 4, h = 4;
205 	int i, swap;
206 	GLboolean pass = GL_TRUE;
207 
208 	piglit_ortho_projection(piglit_width, piglit_height, false);
209 	assert(NUM_FORMATS * 5 < piglit_height);
210 
211 	glClear(GL_COLOR_BUFFER_BIT);
212 
213 	if (dims == 3)
214 		glEnable(GL_TEXTURE_3D);
215 	else
216 		glEnable(GL_TEXTURE_2D);
217 
218 	/* Loop over byteswapping */
219 	for (swap = 0; swap < 2; swap++) {
220 		/* Loop over texture formats */
221 		for (i = 0; i < NUM_FORMATS; i++) {
222 			int x = 5 * swap;
223 			int y = 5 * i;
224 
225 			MakeTexture(dims, Formats + i, IntFormats[intFmt],
226 				    swap);
227 
228 			if (glGetError()) {
229 				printf("Unexpected GL Error for %s\n",
230 				       piglit_get_gl_enum_name(
231 							IntFormats[intFmt]));
232 				return GL_FALSE;
233 			}
234 
235 			glBegin(GL_POLYGON);
236 			glTexCoord3f(0, 0, 0.5);  glVertex2f(x + 0, y + 0);
237 			glTexCoord3f(1, 0, 0.5);  glVertex2f(x + w, y + 0);
238 			glTexCoord3f(1, 1, 0.5);  glVertex2f(x + w, y + h);
239 			glTexCoord3f(0, 1, 0.5);  glVertex2f(x + 0, y + h);
240 			glEnd();
241 		}
242 	}
243 
244 	if (dims == 3)
245 		glDisable(GL_TEXTURE_3D);
246 	else
247 		glDisable(GL_TEXTURE_2D);
248 
249 	/* Loop over byteswapping */
250 	for (swap = 0; swap < 2; swap++) {
251 		/* Loop over texture formats */
252 		for (i = 0; i < NUM_FORMATS; i++) {
253 			int x = 5 * swap;
254 			int y = 5 * i;
255 			char *name;
256 			asprintf(&name, "%s/%s",
257 				 piglit_get_gl_enum_name(Formats[i].format),
258 				 piglit_get_gl_enum_name(Formats[i].type));
259 			/* test rendering */
260 			if (!piglit_probe_rect_rgb(x, y, w, 2, red)) {
261 				printf("Failure for format=%s, swap=%u, "
262 				       "textureDims=%u\n",
263 				       name, swap, dims);
264 				pass = GL_FALSE;
265 			}
266 
267 			if (!piglit_probe_rect_rgb(x, y + 2, w, 2, green)) {
268 				printf("Failure for format=%s, swap=%u, "
269 				       "textureDims=%u\n",
270 				       name, swap, dims);
271 				pass = GL_FALSE;
272 			}
273 			free(name);
274 		}
275 	}
276 
277 	piglit_present_results();
278 
279 	return pass;
280 }
281 
282 enum piglit_result
piglit_display(void)283 piglit_display(void)
284 {
285 	GLboolean pass = 1;
286 	int i;
287 
288 	/* 2D texture */
289 	for (i = 0; i < NUM_INT_FORMATS; i++) {
290 		pass = Test(i, 2) && pass;
291 		if (!pass && !piglit_automatic)
292 			break;
293 	}
294 
295 	/* 3D texture */
296 	for (i = 0; i < NUM_INT_FORMATS; i++) {
297 		pass = Test(i, 3) && pass;
298 		if (!pass && !piglit_automatic)
299 			break;
300 	}
301 
302 	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
303 }
304 
305 
306 void
piglit_init(int argc,char ** argv)307 piglit_init(int argc, char **argv)
308 {
309 	if (0) {
310 		printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
311 		printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
312 	}
313 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
314 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
315 	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
316 	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
317 	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
318 }
319 
320