1/*
2 * Test texture compression.
3 */
4
5
6#include <assert.h>
7#include <stdio.h>
8#include <GL/glew.h>
9#include "glut_wrap.h"
10#include "readtex.c"
11
12#define IMAGE_FILE DEMOS_DATA_DIR "arch.rgb"
13
14static int ImgWidth, ImgHeight;
15static GLenum ImgFormat;
16static GLenum CompFormat;
17static GLfloat EyeDist = 5.0;
18static GLfloat Rot = 0.0;
19const GLenum Target = GL_TEXTURE_2D;
20
21
22static void
23CheckError(int line)
24{
25   GLenum err = glGetError();
26   if (err) {
27      printf("GL Error %d at line %d\n", (int) err, line);
28   }
29}
30
31
32static const char *
33LookupFormat(GLenum format)
34{
35   switch (format) {
36   case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
37      return "GL_COMPRESSED_RGB_S3TC_DXT1_EXT";
38   case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
39      return "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT";
40   case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
41      return "GL_COMPRESSED_RGBA_S3TC_DXT3_EXT";
42   default:
43      return "other";
44   }
45}
46
47
48static void
49TestSubTex(void)
50{
51   GLboolean all = 0*GL_TRUE;
52   GLubyte *buffer;
53   GLint size, fmt;
54
55   glGetTexLevelParameteriv(Target, 0,
56                            GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB, &size);
57   glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt);
58
59   buffer = (GLubyte *) malloc(size);
60   glGetCompressedTexImageARB(Target, 0, buffer);
61
62   printf("Testing sub-texture replacement\n");
63   if (all)
64      glCompressedTexImage2DARB(Target, 0,
65                                fmt, ImgWidth, ImgHeight, 0,
66                                size, buffer);
67   else {
68      /* bottom half */
69      glCompressedTexSubImage2DARB(Target, 0,
70                                   0, 0, /* pos */
71                                   ImgWidth, ImgHeight / 2,
72                                   fmt, size/2, buffer);
73      /* top half */
74      glCompressedTexSubImage2DARB(Target, 0,
75                                   0, ImgHeight / 2, /* pos */
76                                   ImgWidth, ImgHeight / 2,
77                                   fmt, size/2, buffer + size / 2);
78   }
79
80   free(buffer);
81}
82
83
84static void
85TestGetTex(void)
86{
87   GLubyte *buffer;
88
89   buffer = (GLubyte *) malloc(3 * ImgWidth * ImgHeight);
90
91   glGetTexImage(GL_TEXTURE_2D,
92                 0,
93                 GL_RGB,
94                 GL_UNSIGNED_BYTE,
95                 buffer);
96
97   free(buffer);
98}
99
100
101static void
102LoadCompressedImage(const char *file)
103{
104   const GLenum filter = GL_LINEAR;
105   GLubyte *image;
106   GLint p;
107
108   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
109   glPixelStorei(GL_PACK_ALIGNMENT, 1);
110
111   /*
112    * Load image and scale if needed.
113    */
114   image = LoadRGBImage( file, &ImgWidth, &ImgHeight, &ImgFormat );
115   if (!image) {
116      printf("Couldn't read %s\n", IMAGE_FILE);
117      exit(0);
118   }
119   printf("Image is %d x %d\n", ImgWidth, ImgHeight);
120
121   /* power of two */
122   assert(ImgWidth == 128 || ImgWidth == 256 || ImgWidth == 512);
123   assert(ImgWidth == 128 || ImgHeight == 256 || ImgHeight == 512);
124
125   if (ImgFormat == GL_RGB)
126      CompFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
127   else
128      CompFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
129
130   if (ImgFormat == GL_RGBA) {
131      int i, numAlpha = 0;
132      for (i = 0; i < ImgWidth * ImgHeight; i++) {
133         if (image[i*4+3] != 0 && image[i*4+3] != 0xff) {
134            numAlpha++;
135         }
136         if (image[i*4+3] == 0)
137            image[i*4+3] = 4 * i / ImgWidth;
138      }
139      printf("Num Alpha !=0,255: %d\n", numAlpha);
140   }
141
142   CompFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
143
144
145   /*
146    * Give image to OpenGL and have it compress it.
147    */
148   glTexImage2D(Target, 0, CompFormat, ImgWidth, ImgHeight, 0,
149                ImgFormat, GL_UNSIGNED_BYTE, image);
150   CheckError(__LINE__);
151
152   free(image);
153
154   glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_INTERNAL_FORMAT, &p);
155   printf("Compressed Internal Format: %s (0x%x)\n", LookupFormat(p), p);
156   assert(p == CompFormat);
157
158   printf("Original size:   %d bytes\n", ImgWidth * ImgHeight * 3);
159   glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB, &p);
160   printf("Compressed size: %d bytes\n", p);
161
162   glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, filter);
163   glTexParameteri(Target, GL_TEXTURE_MAG_FILTER, filter);
164
165   if (0)
166      TestSubTex();
167   else
168      TestGetTex();
169
170}
171
172
173static void
174Init(const char *file)
175{
176   GLint numFormats, formats[100];
177   GLint p;
178
179   if (!glutExtensionSupported("GL_ARB_texture_compression")) {
180      printf("Sorry, GL_ARB_texture_compression is required.\n");
181      exit(1);
182   }
183   if (!glutExtensionSupported("GL_EXT_texture_compression_s3tc")) {
184      printf("Sorry, GL_EXT_texture_compression_s3tc is required.\n");
185      exit(1);
186   }
187
188   printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
189   printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
190
191   glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB, &numFormats);
192   glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS_ARB, formats);
193   printf("%d supported compression formats: ", numFormats);
194   for (p = 0; p < numFormats; p++)
195      printf("0x%x ", formats[p]);
196   printf("\n");
197
198   LoadCompressedImage(file);
199
200   glEnable(GL_TEXTURE_2D);
201
202   if (ImgFormat == GL_RGBA) {
203      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
204      glEnable(GL_BLEND);
205   }
206}
207
208
209static void
210Reshape( int width, int height )
211{
212   glViewport( 0, 0, width, height );
213   glMatrixMode( GL_PROJECTION );
214   glLoadIdentity();
215   glFrustum(-1, 1, -1, 1, 4, 100);
216   glMatrixMode( GL_MODELVIEW );
217   glLoadIdentity();
218}
219
220
221static void
222Key( unsigned char key, int x, int y )
223{
224   (void) x;
225   (void) y;
226   switch (key) {
227      case 'd':
228         EyeDist -= 1.0;
229         if (EyeDist < 4.0)
230            EyeDist = 4.0;
231         break;
232      case 'D':
233         EyeDist += 1.0;
234         break;
235      case 'z':
236         Rot += 5.0;
237         break;
238      case 'Z':
239         Rot -= 5.0;
240         break;
241      case 27:
242         exit(0);
243         break;
244   }
245   glutPostRedisplay();
246}
247
248
249static void
250Draw( void )
251{
252   glClearColor(0.3, 0.3, .8, 0);
253   glClear(GL_COLOR_BUFFER_BIT);
254
255   glPushMatrix();
256   glTranslatef(0, 0, -(EyeDist+0.01));
257   glRotatef(Rot, 0, 0, 1);
258   glBegin(GL_POLYGON);
259   glTexCoord2f(0, 0);  glVertex2f(-1, -1);
260   glTexCoord2f(1, 0);  glVertex2f( 1, -1);
261   glTexCoord2f(1, 1);  glVertex2f( 1,  1);
262   glTexCoord2f(0, 1);  glVertex2f(-1,  1);
263   glEnd();
264   glPopMatrix();
265
266   glutSwapBuffers();
267}
268
269
270int
271main( int argc, char *argv[] )
272{
273   glutInit( &argc, argv );
274   glutInitWindowSize( 600, 600 );
275
276   glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE);
277
278   glutCreateWindow(argv[0]);
279   glewInit();
280
281   glutReshapeFunc( Reshape );
282   glutKeyboardFunc( Key );
283   glutDisplayFunc( Draw );
284
285   if (argc > 1)
286      Init(argv[1]);
287   else
288      Init(IMAGE_FILE);
289
290   glutMainLoop();
291   return 0;
292}
293