From 08e6fb367efc28b449a11df3057f966cada10f4c Mon Sep 17 00:00:00 2001 From: Daniel Borca Date: Thu, 20 Nov 2003 17:07:31 +0000 Subject: [PATCH] texture compression testbed --- progs/tests/texcmp.c | 389 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 389 insertions(+) create mode 100644 progs/tests/texcmp.c diff --git a/progs/tests/texcmp.c b/progs/tests/texcmp.c new file mode 100644 index 0000000..fc66a96 --- /dev/null +++ b/progs/tests/texcmp.c @@ -0,0 +1,389 @@ +/* + * Compressed texture demo. Written by Daniel Borca. + * This program is in the public domain. + */ + +#include +#include +#include +#include +#define GL_GLEXT_PROTOTYPES 1 +#include + +#include "readtex.c" /* I know, this is a hack. */ +#define TEXTURE_FILE "../images/tree2.rgba" + + +static float Rot = 0.0; +static GLboolean Anim = 1; + +typedef struct { + GLubyte *data; + GLuint size; + GLenum format; + GLuint w, h; + + GLenum TC; + + GLubyte *cData; + GLuint cSize; + GLenum cFormat; +} TEXTURE; + +static TEXTURE *Tx, t1, t2, t3; +static GLboolean fxt1, dxtc, s3tc; + + +static const char *TextureName (GLenum TC) +{ + switch (TC) { + case GL_RGBA: + return "RGBA"; + case GL_COMPRESSED_RGB: + return "COMPRESSED_RGB"; + case GL_COMPRESSED_RGBA: + return "COMPRESSED_RGBA"; + case GL_COMPRESSED_RGB_FXT1_3DFX: + return "GL_COMPRESSED_RGB_FXT1_3DFX"; + case GL_COMPRESSED_RGBA_FXT1_3DFX: + return "GL_COMPRESSED_RGBA_FXT1_3DFX"; + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + return "GL_COMPRESSED_RGB_S3TC_DXT1_EXT"; + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + return "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT"; + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + return "GL_COMPRESSED_RGBA_S3TC_DXT3_EXT"; + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + return "GL_COMPRESSED_RGBA_S3TC_DXT5_EXT"; + case GL_RGB_S3TC: + return "GL_RGB_S3TC"; + case GL_RGB4_S3TC: + return "GL_RGB4_S3TC"; + case GL_RGBA_S3TC: + return "GL_RGBA_S3TC"; + case GL_RGBA4_S3TC: + return "GL_RGBA4_S3TC"; + default: + return "?"; + } +} + + +static void +PrintString(const char *s) +{ + while (*s) { + glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s); + s++; + } +} + + +static void Idle( void ) +{ + float t = glutGet(GLUT_ELAPSED_TIME) * 0.001; /* in seconds */ + Rot = t * 360 / 4; /* 1 rotation per 4 seconds */ + glutPostRedisplay(); +} + + +static void Display( void ) +{ + /* draw background gradient */ + glDisable(GL_TEXTURE_2D); + glBegin(GL_POLYGON); + glColor3f(1.0, 0.0, 0.2); glVertex2f(-1.5, -1.0); + glColor3f(1.0, 0.0, 0.2); glVertex2f( 1.5, -1.0); + glColor3f(0.0, 0.0, 1.0); glVertex2f( 1.5, 1.0); + glColor3f(0.0, 0.0, 1.0); glVertex2f(-1.5, 1.0); + glEnd(); + + glPushMatrix(); + glRotatef(Rot, 0, 0, 1); + + glEnable(GL_TEXTURE_2D); + glBegin(GL_POLYGON); + glTexCoord2f(0, 1); glVertex2f(-1, -0.5); + glTexCoord2f(1, 1); glVertex2f( 1, -0.5); + glTexCoord2f(1, 0); glVertex2f( 1, 0.5); + glTexCoord2f(0, 0); glVertex2f(-1, 0.5); + glEnd(); + + glPopMatrix(); + + /* info */ + glColor4f(1, 1, 1, 1); + + glRasterPos3f(-1.2, -0.7, 0); + PrintString("Selected: "); + PrintString(TextureName(Tx->TC)); + if (Tx->cData) { + char tmp[64]; + glRasterPos3f(-1.2, -0.8, 0); + PrintString("Internal: "); + PrintString(TextureName(Tx->cFormat)); + glRasterPos3f(-1.2, -0.9, 0); + PrintString("Size : "); + sprintf(tmp, "%d (%d%% of %d)", Tx->cSize, Tx->cSize * 100 / Tx->size, Tx->size); + PrintString(tmp); + } + + glutSwapBuffers(); +} + + +static void Reshape( int width, int height ) +{ + glViewport( 0, 0, width, height ); + glMatrixMode( GL_PROJECTION ); + glLoadIdentity(); + glOrtho( -1.5, 1.5, -1.0, 1.0, -1.0, 1.0 ); + glMatrixMode( GL_MODELVIEW ); + glLoadIdentity(); +} + + +static void ReInit( GLenum TC, TEXTURE *Tx ) +{ + GLint rv; + + if ((Tx->TC == TC) && (Tx->cData != NULL)) { + glCompressedTexImage2DARB(GL_TEXTURE_2D, /* target */ + 0, /* level */ + Tx->cFormat, /* real format */ + Tx->w, /* original width */ + Tx->h, /* original height */ + 0, /* border */ + Tx->cSize, /* compressed size*/ + Tx->cData); /* compressed data*/ + } else { + glTexImage2D(GL_TEXTURE_2D, /* target */ + 0, /* level */ + TC, /* internal format */ + Tx->w, Tx->h, /* width, height */ + 0, /* border */ + Tx->format, /* texture format */ + GL_UNSIGNED_BYTE, /* texture type */ + Tx->data); /* the texture */ + + /* okay, now cache the compressed texture */ + Tx->TC = TC; + if (Tx->cData != NULL) { + free(Tx->cData); + Tx->cData = NULL; + } + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_ARB, &rv); + if (rv) { + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, (GLint *)&Tx->cFormat); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB, (GLint *)&Tx->cSize); + if ((Tx->cData = malloc(Tx->cSize)) != NULL) { + glGetCompressedTexImageARB(GL_TEXTURE_2D, 0, Tx->cData); + } + } + } +} + + +static void Init( void ) +{ + /* HEIGHT * WIDTH + 1 (for trailing '\0') */ + static char pattern[8 * 32 + 1] = {"\ + \ + MMM EEEE SSS AAA \ + M M M E S S A A \ + M M M EEEE SS A A \ + M M M E SS AAAAA \ + M M E S S A A \ + M M EEEE SSS A A \ + " + }; + + GLuint i, j; + + GLubyte (*texture1)[8 * 32][4]; + GLubyte (*texture2)[256][256][4]; + + t1.w = 32; + t1.h = 8; + t1.size = t1.w * t1.h * 4; + t1.data = malloc(t1.size); + t1.format = GL_RGBA; + t1.TC = GL_RGBA; + + texture1 = (GLubyte (*)[8 * 32][4])t1.data; + for (i = 0; i < sizeof(pattern) - 1; i++) { + switch (pattern[i]) { + default: + case ' ': + (*texture1)[i][0] = 255; + (*texture1)[i][1] = 255; + (*texture1)[i][2] = 255; + (*texture1)[i][3] = 64; + break; + case 'M': + (*texture1)[i][0] = 255; + (*texture1)[i][1] = 0; + (*texture1)[i][2] = 0; + (*texture1)[i][3] = 255; + break; + case 'E': + (*texture1)[i][0] = 0; + (*texture1)[i][1] = 255; + (*texture1)[i][2] = 0; + (*texture1)[i][3] = 255; + break; + case 'S': + (*texture1)[i][0] = 0; + (*texture1)[i][1] = 0; + (*texture1)[i][2] = 255; + (*texture1)[i][3] = 255; + break; + case 'A': + (*texture1)[i][0] = 255; + (*texture1)[i][1] = 255; + (*texture1)[i][2] = 0; + (*texture1)[i][3] = 255; + break; + } + } + + t2.w = 256; + t2.h = 256; + t2.size = t2.w * t2.h * 4; + t2.data = malloc(t2.size); + t2.format = GL_RGBA; + t2.TC = GL_RGBA; + + texture2 = (GLubyte (*)[256][256][4])t2.data; + for (j = 0; j < t2.h; j++) { + for (i = 0; i < t2.w; i++) { + (*texture2)[j][i][0] = sqrt(i * j * 255 * 255 / (t2.w * t2.h)); + (*texture2)[j][i][1] = 0; + (*texture2)[j][i][2] = 0; + (*texture2)[j][i][3] = 255; + } + } + + t3.data = LoadRGBImage(TEXTURE_FILE, (GLint *)&t3.w, (GLint *)&t3.h, &t3.format); + t3.size = t3.w * t3.h * ((t3.format == GL_RGB) ? 3 : 4); + t3.TC = GL_RGBA; + + ReInit(GL_RGBA, Tx = &t1); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glEnable(GL_TEXTURE_2D); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +} + + +static void Key( unsigned char key, int x, int y ) +{ + (void) x; + (void) y; + switch (key) { + case 27: + exit(0); + break; + case ' ': + Anim = !Anim; + if (Anim) + glutIdleFunc( Idle ); + else + glutIdleFunc( NULL ); + break; + case 't': + if (Tx == &t1) { + Tx = &t2; + } else if (Tx == &t2) { + Tx = &t3; + } else { + Tx = &t1; + } + ReInit(Tx->TC, Tx); + break; + case '0': + ReInit(GL_RGBA, Tx); + break; + case '1': + ReInit(GL_COMPRESSED_RGB, Tx); + break; + case '2': + ReInit(GL_COMPRESSED_RGBA, Tx); + break; + case '3': + if (fxt1) ReInit(GL_COMPRESSED_RGB_FXT1_3DFX, Tx); + break; + case '4': + if (fxt1) ReInit(GL_COMPRESSED_RGBA_FXT1_3DFX, Tx); + break; + case '5': + if (dxtc) ReInit(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, Tx); + break; + case '6': + if (dxtc) ReInit(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, Tx); + break; + case '7': + if (dxtc) ReInit(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, Tx); + break; + case '8': + if (dxtc) ReInit(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, Tx); + break; + case 'a': + if (s3tc) ReInit(GL_RGB_S3TC, Tx); + break; + case 's': + if (s3tc) ReInit(GL_RGB4_S3TC, Tx); + break; + case 'd': + if (s3tc) ReInit(GL_RGBA_S3TC, Tx); + break; + case 'f': + if (s3tc) ReInit(GL_RGBA4_S3TC, Tx); + break; + } + glutPostRedisplay(); +} + + +int main( int argc, char *argv[] ) +{ + glutInit( &argc, argv ); + glutInitWindowPosition( 0, 0 ); + glutInitWindowSize( 400, 300 ); + + glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE ); + + if (glutCreateWindow(argv[0]) <= 0) { + printf("Couldn't create window\n"); + exit(0); + } + + if (!glutExtensionSupported("GL_ARB_texture_compression")) { + printf("Sorry, GL_ARB_texture_compression not supported\n"); + exit(0); + } + if (glutExtensionSupported("GL_3DFX_texture_compression_FXT1")) { + fxt1 = GL_TRUE; + } + if (glutExtensionSupported("GL_EXT_texture_compression_s3tc")) { + dxtc = GL_TRUE; + } + if (glutExtensionSupported("GL_S3_s3tc")) { + s3tc = GL_TRUE; + } + + Init(); + + glutReshapeFunc( Reshape ); + glutKeyboardFunc( Key ); + glutDisplayFunc( Display ); + if (Anim) + glutIdleFunc( Idle ); + + glutMainLoop(); + return 0; +} -- 2.7.4