texture compression testbed
[mesa.git] / progs / tests / texcmp.c
1 /*
2 * Compressed texture demo. Written by Daniel Borca.
3 * This program is in the public domain.
4 */
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <math.h>
9 #include <string.h>
10 #define GL_GLEXT_PROTOTYPES 1
11 #include <GL/glut.h>
12
13 #include "readtex.c" /* I know, this is a hack. */
14 #define TEXTURE_FILE "../images/tree2.rgba"
15
16
17 static float Rot = 0.0;
18 static GLboolean Anim = 1;
19
20 typedef struct {
21 GLubyte *data;
22 GLuint size;
23 GLenum format;
24 GLuint w, h;
25
26 GLenum TC;
27
28 GLubyte *cData;
29 GLuint cSize;
30 GLenum cFormat;
31 } TEXTURE;
32
33 static TEXTURE *Tx, t1, t2, t3;
34 static GLboolean fxt1, dxtc, s3tc;
35
36
37 static const char *TextureName (GLenum TC)
38 {
39 switch (TC) {
40 case GL_RGBA:
41 return "RGBA";
42 case GL_COMPRESSED_RGB:
43 return "COMPRESSED_RGB";
44 case GL_COMPRESSED_RGBA:
45 return "COMPRESSED_RGBA";
46 case GL_COMPRESSED_RGB_FXT1_3DFX:
47 return "GL_COMPRESSED_RGB_FXT1_3DFX";
48 case GL_COMPRESSED_RGBA_FXT1_3DFX:
49 return "GL_COMPRESSED_RGBA_FXT1_3DFX";
50 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
51 return "GL_COMPRESSED_RGB_S3TC_DXT1_EXT";
52 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
53 return "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT";
54 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
55 return "GL_COMPRESSED_RGBA_S3TC_DXT3_EXT";
56 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
57 return "GL_COMPRESSED_RGBA_S3TC_DXT5_EXT";
58 case GL_RGB_S3TC:
59 return "GL_RGB_S3TC";
60 case GL_RGB4_S3TC:
61 return "GL_RGB4_S3TC";
62 case GL_RGBA_S3TC:
63 return "GL_RGBA_S3TC";
64 case GL_RGBA4_S3TC:
65 return "GL_RGBA4_S3TC";
66 default:
67 return "?";
68 }
69 }
70
71
72 static void
73 PrintString(const char *s)
74 {
75 while (*s) {
76 glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s);
77 s++;
78 }
79 }
80
81
82 static void Idle( void )
83 {
84 float t = glutGet(GLUT_ELAPSED_TIME) * 0.001; /* in seconds */
85 Rot = t * 360 / 4; /* 1 rotation per 4 seconds */
86 glutPostRedisplay();
87 }
88
89
90 static void Display( void )
91 {
92 /* draw background gradient */
93 glDisable(GL_TEXTURE_2D);
94 glBegin(GL_POLYGON);
95 glColor3f(1.0, 0.0, 0.2); glVertex2f(-1.5, -1.0);
96 glColor3f(1.0, 0.0, 0.2); glVertex2f( 1.5, -1.0);
97 glColor3f(0.0, 0.0, 1.0); glVertex2f( 1.5, 1.0);
98 glColor3f(0.0, 0.0, 1.0); glVertex2f(-1.5, 1.0);
99 glEnd();
100
101 glPushMatrix();
102 glRotatef(Rot, 0, 0, 1);
103
104 glEnable(GL_TEXTURE_2D);
105 glBegin(GL_POLYGON);
106 glTexCoord2f(0, 1); glVertex2f(-1, -0.5);
107 glTexCoord2f(1, 1); glVertex2f( 1, -0.5);
108 glTexCoord2f(1, 0); glVertex2f( 1, 0.5);
109 glTexCoord2f(0, 0); glVertex2f(-1, 0.5);
110 glEnd();
111
112 glPopMatrix();
113
114 /* info */
115 glColor4f(1, 1, 1, 1);
116
117 glRasterPos3f(-1.2, -0.7, 0);
118 PrintString("Selected: ");
119 PrintString(TextureName(Tx->TC));
120 if (Tx->cData) {
121 char tmp[64];
122 glRasterPos3f(-1.2, -0.8, 0);
123 PrintString("Internal: ");
124 PrintString(TextureName(Tx->cFormat));
125 glRasterPos3f(-1.2, -0.9, 0);
126 PrintString("Size : ");
127 sprintf(tmp, "%d (%d%% of %d)", Tx->cSize, Tx->cSize * 100 / Tx->size, Tx->size);
128 PrintString(tmp);
129 }
130
131 glutSwapBuffers();
132 }
133
134
135 static void Reshape( int width, int height )
136 {
137 glViewport( 0, 0, width, height );
138 glMatrixMode( GL_PROJECTION );
139 glLoadIdentity();
140 glOrtho( -1.5, 1.5, -1.0, 1.0, -1.0, 1.0 );
141 glMatrixMode( GL_MODELVIEW );
142 glLoadIdentity();
143 }
144
145
146 static void ReInit( GLenum TC, TEXTURE *Tx )
147 {
148 GLint rv;
149
150 if ((Tx->TC == TC) && (Tx->cData != NULL)) {
151 glCompressedTexImage2DARB(GL_TEXTURE_2D, /* target */
152 0, /* level */
153 Tx->cFormat, /* real format */
154 Tx->w, /* original width */
155 Tx->h, /* original height */
156 0, /* border */
157 Tx->cSize, /* compressed size*/
158 Tx->cData); /* compressed data*/
159 } else {
160 glTexImage2D(GL_TEXTURE_2D, /* target */
161 0, /* level */
162 TC, /* internal format */
163 Tx->w, Tx->h, /* width, height */
164 0, /* border */
165 Tx->format, /* texture format */
166 GL_UNSIGNED_BYTE, /* texture type */
167 Tx->data); /* the texture */
168
169 /* okay, now cache the compressed texture */
170 Tx->TC = TC;
171 if (Tx->cData != NULL) {
172 free(Tx->cData);
173 Tx->cData = NULL;
174 }
175 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_ARB, &rv);
176 if (rv) {
177 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, (GLint *)&Tx->cFormat);
178 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB, (GLint *)&Tx->cSize);
179 if ((Tx->cData = malloc(Tx->cSize)) != NULL) {
180 glGetCompressedTexImageARB(GL_TEXTURE_2D, 0, Tx->cData);
181 }
182 }
183 }
184 }
185
186
187 static void Init( void )
188 {
189 /* HEIGHT * WIDTH + 1 (for trailing '\0') */
190 static char pattern[8 * 32 + 1] = {"\
191 \
192 MMM EEEE SSS AAA \
193 M M M E S S A A \
194 M M M EEEE SS A A \
195 M M M E SS AAAAA \
196 M M E S S A A \
197 M M EEEE SSS A A \
198 "
199 };
200
201 GLuint i, j;
202
203 GLubyte (*texture1)[8 * 32][4];
204 GLubyte (*texture2)[256][256][4];
205
206 t1.w = 32;
207 t1.h = 8;
208 t1.size = t1.w * t1.h * 4;
209 t1.data = malloc(t1.size);
210 t1.format = GL_RGBA;
211 t1.TC = GL_RGBA;
212
213 texture1 = (GLubyte (*)[8 * 32][4])t1.data;
214 for (i = 0; i < sizeof(pattern) - 1; i++) {
215 switch (pattern[i]) {
216 default:
217 case ' ':
218 (*texture1)[i][0] = 255;
219 (*texture1)[i][1] = 255;
220 (*texture1)[i][2] = 255;
221 (*texture1)[i][3] = 64;
222 break;
223 case 'M':
224 (*texture1)[i][0] = 255;
225 (*texture1)[i][1] = 0;
226 (*texture1)[i][2] = 0;
227 (*texture1)[i][3] = 255;
228 break;
229 case 'E':
230 (*texture1)[i][0] = 0;
231 (*texture1)[i][1] = 255;
232 (*texture1)[i][2] = 0;
233 (*texture1)[i][3] = 255;
234 break;
235 case 'S':
236 (*texture1)[i][0] = 0;
237 (*texture1)[i][1] = 0;
238 (*texture1)[i][2] = 255;
239 (*texture1)[i][3] = 255;
240 break;
241 case 'A':
242 (*texture1)[i][0] = 255;
243 (*texture1)[i][1] = 255;
244 (*texture1)[i][2] = 0;
245 (*texture1)[i][3] = 255;
246 break;
247 }
248 }
249
250 t2.w = 256;
251 t2.h = 256;
252 t2.size = t2.w * t2.h * 4;
253 t2.data = malloc(t2.size);
254 t2.format = GL_RGBA;
255 t2.TC = GL_RGBA;
256
257 texture2 = (GLubyte (*)[256][256][4])t2.data;
258 for (j = 0; j < t2.h; j++) {
259 for (i = 0; i < t2.w; i++) {
260 (*texture2)[j][i][0] = sqrt(i * j * 255 * 255 / (t2.w * t2.h));
261 (*texture2)[j][i][1] = 0;
262 (*texture2)[j][i][2] = 0;
263 (*texture2)[j][i][3] = 255;
264 }
265 }
266
267 t3.data = LoadRGBImage(TEXTURE_FILE, (GLint *)&t3.w, (GLint *)&t3.h, &t3.format);
268 t3.size = t3.w * t3.h * ((t3.format == GL_RGB) ? 3 : 4);
269 t3.TC = GL_RGBA;
270
271 ReInit(GL_RGBA, Tx = &t1);
272
273 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
274 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
275 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
276 glEnable(GL_TEXTURE_2D);
277
278 glEnable(GL_BLEND);
279 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
280 }
281
282
283 static void Key( unsigned char key, int x, int y )
284 {
285 (void) x;
286 (void) y;
287 switch (key) {
288 case 27:
289 exit(0);
290 break;
291 case ' ':
292 Anim = !Anim;
293 if (Anim)
294 glutIdleFunc( Idle );
295 else
296 glutIdleFunc( NULL );
297 break;
298 case 't':
299 if (Tx == &t1) {
300 Tx = &t2;
301 } else if (Tx == &t2) {
302 Tx = &t3;
303 } else {
304 Tx = &t1;
305 }
306 ReInit(Tx->TC, Tx);
307 break;
308 case '0':
309 ReInit(GL_RGBA, Tx);
310 break;
311 case '1':
312 ReInit(GL_COMPRESSED_RGB, Tx);
313 break;
314 case '2':
315 ReInit(GL_COMPRESSED_RGBA, Tx);
316 break;
317 case '3':
318 if (fxt1) ReInit(GL_COMPRESSED_RGB_FXT1_3DFX, Tx);
319 break;
320 case '4':
321 if (fxt1) ReInit(GL_COMPRESSED_RGBA_FXT1_3DFX, Tx);
322 break;
323 case '5':
324 if (dxtc) ReInit(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, Tx);
325 break;
326 case '6':
327 if (dxtc) ReInit(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, Tx);
328 break;
329 case '7':
330 if (dxtc) ReInit(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, Tx);
331 break;
332 case '8':
333 if (dxtc) ReInit(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, Tx);
334 break;
335 case 'a':
336 if (s3tc) ReInit(GL_RGB_S3TC, Tx);
337 break;
338 case 's':
339 if (s3tc) ReInit(GL_RGB4_S3TC, Tx);
340 break;
341 case 'd':
342 if (s3tc) ReInit(GL_RGBA_S3TC, Tx);
343 break;
344 case 'f':
345 if (s3tc) ReInit(GL_RGBA4_S3TC, Tx);
346 break;
347 }
348 glutPostRedisplay();
349 }
350
351
352 int main( int argc, char *argv[] )
353 {
354 glutInit( &argc, argv );
355 glutInitWindowPosition( 0, 0 );
356 glutInitWindowSize( 400, 300 );
357
358 glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE );
359
360 if (glutCreateWindow(argv[0]) <= 0) {
361 printf("Couldn't create window\n");
362 exit(0);
363 }
364
365 if (!glutExtensionSupported("GL_ARB_texture_compression")) {
366 printf("Sorry, GL_ARB_texture_compression not supported\n");
367 exit(0);
368 }
369 if (glutExtensionSupported("GL_3DFX_texture_compression_FXT1")) {
370 fxt1 = GL_TRUE;
371 }
372 if (glutExtensionSupported("GL_EXT_texture_compression_s3tc")) {
373 dxtc = GL_TRUE;
374 }
375 if (glutExtensionSupported("GL_S3_s3tc")) {
376 s3tc = GL_TRUE;
377 }
378
379 Init();
380
381 glutReshapeFunc( Reshape );
382 glutKeyboardFunc( Key );
383 glutDisplayFunc( Display );
384 if (Anim)
385 glutIdleFunc( Idle );
386
387 glutMainLoop();
388 return 0;
389 }