texture compression testbed
authorDaniel Borca <dborca@users.sourceforge.net>
Thu, 20 Nov 2003 17:07:31 +0000 (17:07 +0000)
committerDaniel Borca <dborca@users.sourceforge.net>
Thu, 20 Nov 2003 17:07:31 +0000 (17:07 +0000)
progs/tests/texcmp.c [new file with mode: 0644]

diff --git a/progs/tests/texcmp.c b/progs/tests/texcmp.c
new file mode 100644 (file)
index 0000000..fc66a96
--- /dev/null
@@ -0,0 +1,389 @@
+/*
+ * Compressed texture demo.  Written by Daniel Borca.
+ * This program is in the public domain.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#define GL_GLEXT_PROTOTYPES 1
+#include <GL/glut.h>
+
+#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;
+}