1 /*
2  * Test texture compression.
3  */
4 
5 
6 #include <assert.h>
7 #include <stdio.h>
8 #include <glad/glad.h>
9 #include "glut_wrap.h"
10 #include "readtex.c"
11 
12 #define IMAGE_FILE DEMOS_DATA_DIR "arch.rgb"
13 
14 static int ImgWidth, ImgHeight;
15 static GLenum ImgFormat;
16 static GLenum CompFormat;
17 static GLfloat EyeDist = 5.0;
18 static GLfloat Rot = 0.0;
19 const GLenum Target = GL_TEXTURE_2D;
20 
21 
22 static void
CheckError(int line)23 CheckError(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 
32 static const char *
LookupFormat(GLenum format)33 LookupFormat(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 
48 static void
TestSubTex(void)49 TestSubTex(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 
84 static void
TestGetTex(void)85 TestGetTex(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 
101 static void
LoadCompressedImage(const char * file)102 LoadCompressedImage(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 
173 static void
Init(const char * file)174 Init(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 
209 static void
Reshape(int width,int height)210 Reshape( 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 
221 static void
Key(unsigned char key,int x,int y)222 Key( 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 
249 static void
Draw(void)250 Draw( 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 
270 int
main(int argc,char * argv[])271 main( 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    gladLoadGL();
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