--- /dev/null
+/*
+ * Test texture compression.
+ */
+
+
+#define GL_GLEXT_PROTOTYPES
+#include <assert.h>
+#include <stdio.h>
+#include <GL/glut.h>
+#include <GL/glx.h>
+#include "readtex.c"
+
+#define IMAGE_FILE "../images/arch.rgb"
+
+static int ImgWidth, ImgHeight;
+static GLenum ImgFormat;
+static GLenum CompFormat;
+static GLfloat EyeDist = 5.0;
+static GLfloat Rot = 0.0;
+const GLenum Target = GL_TEXTURE_2D;
+
+
+static void
+CheckError(int line)
+{
+ GLenum err = glGetError();
+ if (err) {
+ printf("GL Error %d at line %d\n", (int) err, line);
+ }
+}
+
+
+static const char *
+LookupFormat(GLenum format)
+{
+ switch (format) {
+ 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";
+ default:
+ return "other";
+ }
+}
+
+
+static void
+TestSubTex(void)
+{
+ GLboolean all = 0*GL_TRUE;
+ GLubyte *buffer;
+ GLint size, fmt;
+ int i;
+
+ glGetTexLevelParameteriv(Target, 0,
+ GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB, &size);
+ glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt);
+
+ buffer = (GLubyte *) malloc(size);
+ glGetCompressedTexImageARB(Target, 0, buffer);
+
+ printf("Testing sub-texture replacement\n");
+ if (all)
+ glCompressedTexImage2DARB(Target, 0,
+ fmt, ImgWidth, ImgHeight, 0,
+ size, buffer);
+ else {
+ /* bottom half */
+ glCompressedTexSubImage2DARB(Target, 0,
+ 0, 0, /* pos */
+ ImgWidth, ImgHeight / 2,
+ fmt, size/2, buffer);
+ /* top half */
+ glCompressedTexSubImage2DARB(Target, 0,
+ 0, ImgHeight / 2, /* pos */
+ ImgWidth, ImgHeight / 2,
+ fmt, size/2, buffer + size / 2);
+ }
+
+ free(buffer);
+}
+
+
+static void
+LoadCompressedImage(const char *file)
+{
+ const GLenum filter = GL_LINEAR;
+ GLubyte *image;
+ GLint p;
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ glPixelStorei(GL_PACK_ALIGNMENT, 1);
+
+ /*
+ * Load image and scale if needed.
+ */
+ image = LoadRGBImage( file, &ImgWidth, &ImgHeight, &ImgFormat );
+ if (!image) {
+ printf("Couldn't read %s\n", IMAGE_FILE);
+ exit(0);
+ }
+ printf("Image is %d x %d\n", ImgWidth, ImgHeight);
+
+ /* power of two */
+ assert(ImgWidth == 128 || ImgWidth == 256 || ImgWidth == 512);
+ assert(ImgWidth == 128 || ImgHeight == 256 || ImgHeight == 512);
+
+ if (ImgFormat == GL_RGB)
+ CompFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
+ else
+ CompFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+
+ if (ImgFormat == GL_RGBA) {
+ int i, numAlpha = 0;
+ for (i = 0; i < ImgWidth * ImgHeight; i++) {
+ if (image[i*4+3] != 0 && image[i*4+3] != 0xff) {
+ numAlpha++;
+ }
+ if (image[i*4+3] == 0)
+ image[i*4+3] = 4 * i / ImgWidth;
+ }
+ printf("Num Alpha !=0,255: %d\n", numAlpha);
+ }
+
+ CompFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+
+
+ /*
+ * Give image to OpenGL and have it compress it.
+ */
+ glTexImage2D(Target, 0, CompFormat, ImgWidth, ImgHeight, 0,
+ ImgFormat, GL_UNSIGNED_BYTE, image);
+ CheckError(__LINE__);
+
+ free(image);
+
+ glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_INTERNAL_FORMAT, &p);
+ printf("Compressed Internal Format: %s (0x%x)\n", LookupFormat(p), p);
+ assert(p == CompFormat);
+
+ printf("Original size: %d bytes\n", ImgWidth * ImgHeight * 3);
+ glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB, &p);
+ printf("Compressed size: %d bytes\n", p);
+
+ glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, filter);
+ glTexParameteri(Target, GL_TEXTURE_MAG_FILTER, filter);
+
+ TestSubTex();
+
+}
+
+
+static void
+Init(const char *file)
+{
+ GLint numFormats, formats[100];
+ GLint p;
+
+ if (!glutExtensionSupported("GL_ARB_texture_compression")) {
+ printf("Sorry, GL_ARB_texture_compression is required.\n");
+ exit(1);
+ }
+ if (!glutExtensionSupported("GL_EXT_texture_compression_s3tc")) {
+ printf("Sorry, GL_EXT_texture_compression_s3tc is required.\n");
+ exit(1);
+ }
+
+ printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
+ printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
+
+ glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB, &numFormats);
+ glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS_ARB, formats);
+ printf("%d supported compression formats: ", numFormats);
+ for (p = 0; p < numFormats; p++)
+ printf("0x%x ", formats[p]);
+ printf("\n");
+
+ LoadCompressedImage(file);
+
+ glEnable(GL_TEXTURE_2D);
+
+ if (ImgFormat == GL_RGBA) {
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ }
+}
+
+
+static void
+Reshape( int width, int height )
+{
+ glViewport( 0, 0, width, height );
+ glMatrixMode( GL_PROJECTION );
+ glLoadIdentity();
+ glFrustum(-1, 1, -1, 1, 4, 100);
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+}
+
+
+static void
+Key( unsigned char key, int x, int y )
+{
+ (void) x;
+ (void) y;
+ switch (key) {
+ case 'd':
+ EyeDist -= 1.0;
+ if (EyeDist < 4.0)
+ EyeDist = 4.0;
+ break;
+ case 'D':
+ EyeDist += 1.0;
+ break;
+ case 'z':
+ Rot += 5.0;
+ break;
+ case 'Z':
+ Rot -= 5.0;
+ break;
+ case 27:
+ exit(0);
+ break;
+ }
+ glutPostRedisplay();
+}
+
+
+static void
+Draw( void )
+{
+ glClearColor(0.3, 0.3, .8, 0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glPushMatrix();
+ glTranslatef(0, 0, -(EyeDist+0.01));
+ glRotatef(Rot, 0, 0, 1);
+ glBegin(GL_POLYGON);
+ glTexCoord2f(0, 0); glVertex2f(-1, -1);
+ glTexCoord2f(1, 0); glVertex2f( 1, -1);
+ glTexCoord2f(1, 1); glVertex2f( 1, 1);
+ glTexCoord2f(0, 1); glVertex2f(-1, 1);
+ glEnd();
+ glPopMatrix();
+
+ glutSwapBuffers();
+}
+
+
+int
+main( int argc, char *argv[] )
+{
+ glutInit( &argc, argv );
+ glutInitWindowSize( 600, 600 );
+
+ glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE);
+
+ glutCreateWindow(argv[0]);
+
+ glutReshapeFunc( Reshape );
+ glutKeyboardFunc( Key );
+ glutDisplayFunc( Draw );
+
+ if (argc > 1)
+ Init(argv[1]);
+ else
+ Init(IMAGE_FILE);
+
+ glutMainLoop();
+ return 0;
+}