7 #include <GL/freeglut.h>
12 #define COMP_FMT GL_COMPRESSED_SRGB8_ETC2
14 #define COMP_FMT GL_COMPRESSED_RGB8_ETC2
18 int texcomp(unsigned char *compix, unsigned int tofmt, unsigned char *pixels,
19 int xsz, int ysz, unsigned int fromfmt, unsigned int fromtype);
21 void reshape(int x, int y);
22 void keyb(unsigned char key, int x, int y);
24 void gen_image(unsigned char *pixels, int xsz, int ysz);
25 unsigned char *load_compressed_image(const char *fname, int *cszptr, int *xszptr, int *yszptr);
26 int dump_compressed_image(const char *fname, unsigned char *data, int size, int w, int h);
27 void print_compressed_formats(void);
29 unsigned int tex, tex2, comp_tex;
31 int subtest, copytest, loop;
33 int main(int argc, char **argv)
36 unsigned int glut_flags = GLUT_RGB | GLUT_DOUBLE;
38 glut_flags |= GLUT_SRGB;
41 for(i=1; i<argc; i++) {
42 if(argv[i][0] == '-') {
43 if(strcmp(argv[i], "-subtest") == 0) {
45 } else if(strcmp(argv[i], "-copytest") == 0) {
47 } else if(strcmp(argv[i], "-copytest-loop") == 0) {
51 fprintf(stderr, "invalid option: %s\n", argv[i]);
56 fprintf(stderr, "unexpected argument: %s\n", argv[i]);
63 glutInit(&argc, argv);
64 glutInitWindowSize(800, 600);
65 glutInitDisplayMode(glut_flags);
66 glutCreateWindow("test");
68 glutDisplayFunc(disp);
69 glutReshapeFunc(reshape);
70 glutKeyboardFunc(keyb);
87 unsigned char *pixels, *buf;
94 print_compressed_formats();
97 if(!(pixels = load_compressed_image(texfile, &comp_size, &xsz, &ysz))) {
100 printf("loaded compressed texture file: %s (%dx%d)\n", texfile, xsz, ysz);
103 if(!(pixels = malloc(xsz * ysz * 3))) {
106 gen_image(pixels, xsz, ysz);
108 printf("compressing texture\n");
109 if((comp_size = texcomp(pixels, COMP_FMT, pixels, xsz, ysz, GL_RGB, GL_UNSIGNED_BYTE)) == -1) {
112 printf("compressed texture is %d bytes (uncompressed was: %d)\n", comp_size, xsz * ysz * 3);
114 dump_compressed_image("compressed_texture", pixels, comp_size, xsz, ysz);
117 glGenTextures(1, &tex);
118 glBindTexture(GL_TEXTURE_2D, tex);
119 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
120 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
121 glCompressedTexImage2D(GL_TEXTURE_2D, 0, COMP_FMT, xsz, ysz, 0, comp_size, pixels);
123 fprintf(stderr, "failed to upload compressed texture\n");
127 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED, &is_comp);
129 fprintf(stderr, "texture is not compressed\n");
132 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &tmp);
133 if(tmp != comp_size) {
134 fprintf(stderr, "internal compressed size differs (expected: %d, got: %d)!\n", comp_size, tmp);
138 if(!(buf = malloc(comp_size))) {
139 fprintf(stderr, "failed to allocate comparison image buffer (%d bytes)\n", comp_size);
142 glGetCompressedTexImage(GL_TEXTURE_2D, 0, buf);
144 if(memcmp(pixels, buf, comp_size) != 0) {
145 fprintf(stderr, "submitted and retrieved pixel data differ!\n");
147 printf("submitted and retrieved sizes match (%d bytes)\n", comp_size);
151 printf("testing glGetCompressedTextureSubImage and glCompressedTexSubImage2D\n");
152 memset(buf, 0, comp_size);
153 glGetCompressedTextureSubImage(tex, 0, 192, 64, 0, 64, 64, 1, comp_size, buf);
154 glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 32, 32, 64, 64, COMP_FMT, 2048, buf);
158 printf("testing glCopyImageSubData\n");
160 glGenTextures(1, &tex2);
161 glBindTexture(GL_TEXTURE_2D, tex2);
162 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
163 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
164 glCompressedTexImage2D(GL_TEXTURE_2D, 0, COMP_FMT, xsz, ysz, 0, comp_size, pixels);
165 glBindTexture(GL_TEXTURE_2D, 0);
167 glCopyImageSubData(tex2, GL_TEXTURE_2D, 0, 128, 64, 0,
168 tex, GL_TEXTURE_2D, 0, 32, 32, 0, 64, 64, 1);
170 glBindTexture(GL_TEXTURE_2D, tex);
177 glEnable(GL_FRAMEBUFFER_SRGB);
180 glEnable(GL_TEXTURE_2D);
184 int texcomp(unsigned char *compix, unsigned int tofmt, unsigned char *pixels,
185 int xsz, int ysz, unsigned int fromfmt, unsigned int fromtype)
191 glGenTextures(1, &tex);
192 glBindTexture(GL_TEXTURE_2D, tex);
193 glTexImage2D(GL_TEXTURE_2D, 0, tofmt, xsz, ysz, 0, fromfmt, fromtype, pixels);
195 fprintf(stderr, "failed to compress texture\n");
199 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED, &is_comp);
201 fprintf(stderr, "texture is not compressed\n");
204 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &comp_size);
206 glGetCompressedTexImage(GL_TEXTURE_2D, 0, compix);
212 glClear(GL_COLOR_BUFFER_BIT);
215 glTexCoord2f(0, 1); glVertex2f(-1, -1);
216 glTexCoord2f(1, 1); glVertex2f(1, -1);
217 glTexCoord2f(1, 0); glVertex2f(1, 1);
218 glTexCoord2f(0, 0); glVertex2f(-1, 1);
222 assert(glGetError() == GL_NO_ERROR);
225 void reshape(int x, int y)
227 float aspect = (float)x / (float)y;
228 glViewport(0, 0, x, y);
230 glMatrixMode(GL_PROJECTION);
232 glScalef(1.0 / aspect, 1, 1);
235 void keyb(unsigned char key, int x, int y)
247 void gen_image(unsigned char *pixels, int xsz, int ysz)
251 for(i=0; i<ysz; i++) {
252 for(j=0; j<xsz; j++) {
255 *pixels++ = xor & 0xff;
256 *pixels++ = (xor << 1) & 0xff;
257 *pixels++ = (xor << 2) & 0xff;
262 unsigned char *load_compressed_image(const char *fname, int *cszptr, int *xszptr, int *yszptr)
264 unsigned char *pixels;
265 long start, comp_size;
269 if(!(fp = fopen(texfile, "rb"))) {
270 fprintf(stderr, "failed to open compressed texture file: %s: %s\n", texfile, strerror(errno));
274 if(fread(&xsz, sizeof xsz, 1, fp) < 1 || fread(&ysz, sizeof ysz, 1, fp) < 1) {
275 fprintf(stderr, "failed to read compressed texture file header: %s: %s\n", texfile, strerror(errno));
280 fseek(fp, 0, SEEK_END);
281 comp_size = ftell(fp) - start;
282 fseek(fp, start, SEEK_SET);
284 if(!(pixels = malloc(comp_size))) {
285 perror("failed to allocate pixel buffer");
288 if(fread(pixels, 1, comp_size, fp) < comp_size) {
289 fprintf(stderr, "failed to read compressed texture file: %s: %s\n", texfile, strerror(errno));
302 int dump_compressed_image(const char *fname, unsigned char *data, int size, int w, int h)
306 if(!(fp = fopen(fname, "wb"))) {
307 fprintf(stderr, "failed to open compressed texture dump file: %s: %s\n", fname, strerror(errno));
311 if(fwrite(&w, sizeof w, 1, fp) < 1 ||
312 fwrite(&h, sizeof h, 1, fp) < 1 ||
313 fwrite(data, 1, size, fp) < size) {
314 fprintf(stderr, "failed to dump compressed texture: %s\n", strerror(errno));
320 const char *fmtstr(int fmt)
323 case 0x86b0: return "GL_COMPRESSED_RGB_FXT1_3DFX";
324 case 0x86b1: return "GL_COMPRESSED_RGBA_FXT1_3DFX";
325 case 0x8dbb: return "GL_COMPRESSED_RED_RGTC1";
326 case 0x8dbc: return "GL_COMPRESSED_SIGNED_RED_RGTC1";
327 case 0x8dbd: return "GL_COMPRESSED_RG_RGTC2";
328 case 0x8dbe: return "GL_COMPRESSED_SIGNED_RG_RGTC2";
329 case 0x8e8c: return "GL_COMPRESSED_RGBA_BPTC_UNORM";
330 case 0x8e8d: return "GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM";
331 case 0x8e8e: return "GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT";
332 case 0x8e8f: return "GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT";
333 case 0x9274: return "GL_COMPRESSED_RGB8_ETC2";
334 case 0x9275: return "GL_COMPRESSED_SRGB8_ETC2";
335 case 0x9276: return "GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2";
336 case 0x9277: return "GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2";
337 case 0x9278: return "GL_COMPRESSED_RGBA8_ETC2_EAC";
338 case 0x9279: return "GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC";
339 case 0x9270: return "GL_COMPRESSED_R11_EAC";
340 case 0x9271: return "GL_COMPRESSED_SIGNED_R11_EAC";
341 case 0x9272: return "GL_COMPRESSED_RG11_EAC";
342 case 0x9273: return "GL_COMPRESSED_SIGNED_RG11_EAC";
343 case 0x83F0: return "GL_COMPRESSED_RGB_S3TC_DXT1_EXT";
344 case 0x83F1: return "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT";
345 case 0x83F2: return "GL_COMPRESSED_RGBA_S3TC_DXT3_EXT";
346 case 0x83F3: return "GL_COMPRESSED_RGBA_S3TC_DXT5_EXT";
347 case 0x8C48: return "GL_COMPRESSED_SRGB_EXT";
348 case 0x8C49: return "GL_COMPRESSED_SRGB_ALPHA_EXT";
349 case 0x8C4A: return "GL_COMPRESSED_SLUMINANCE_EXT";
350 case 0x8C4B: return "GL_COMPRESSED_SLUMINANCE_ALPHA_EXT";
351 case 0x8C4C: return "GL_COMPRESSED_SRGB_S3TC_DXT1_EXT";
352 case 0x8C4D: return "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT";
353 case 0x8C4E: return "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT";
354 case 0x8C4F: return "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT";
355 case 0x8B90: return "GL_PALETTE4_RGB8_OES";
356 case 0x8B91: return "GL_PALETTE4_RGBA8_OES";
357 case 0x8B92: return "GL_PALETTE4_R5_G6_B5_OES";
358 case 0x8B93: return "GL_PALETTE4_RGBA4_OES";
359 case 0x8B94: return "GL_PALETTE4_RGB5_A1_OES";
360 case 0x8B95: return "GL_PALETTE8_RGB8_OES";
361 case 0x8B96: return "GL_PALETTE8_RGBA8_OES";
362 case 0x8B97: return "GL_PALETTE8_R5_G6_B5_OES";
363 case 0x8B98: return "GL_PALETTE8_RGBA4_OES";
364 case 0x8B99: return "GL_PALETTE8_RGB5_A1_OES";
365 case 0x93B0: return "GL_COMPRESSED_RGBA_ASTC_4";
366 case 0x93B1: return "GL_COMPRESSED_RGBA_ASTC_5";
367 case 0x93B2: return "GL_COMPRESSED_RGBA_ASTC_5";
368 case 0x93B3: return "GL_COMPRESSED_RGBA_ASTC_6";
369 case 0x93B4: return "GL_COMPRESSED_RGBA_ASTC_6";
370 case 0x93B5: return "GL_COMPRESSED_RGBA_ASTC_8";
371 case 0x93B6: return "GL_COMPRESSED_RGBA_ASTC_8";
372 case 0x93B7: return "GL_COMPRESSED_RGBA_ASTC_8";
373 case 0x93B8: return "GL_COMPRESSED_RGBA_ASTC_10";
374 case 0x93B9: return "GL_COMPRESSED_RGBA_ASTC_10";
375 case 0x93BA: return "GL_COMPRESSED_RGBA_ASTC_10";
376 case 0x93BB: return "GL_COMPRESSED_RGBA_ASTC_10";
377 case 0x93BC: return "GL_COMPRESSED_RGBA_ASTC_12";
378 case 0x93BD: return "GL_COMPRESSED_RGBA_ASTC_12";
379 case 0x93D0: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4";
380 case 0x93D1: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5";
381 case 0x93D2: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5";
382 case 0x93D3: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6";
383 case 0x93D4: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6";
384 case 0x93D5: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8";
385 case 0x93D6: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8";
386 case 0x93D7: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8";
387 case 0x93D8: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10";
388 case 0x93D9: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10";
389 case 0x93DA: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10";
390 case 0x93DB: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10";
391 case 0x93DC: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12";
392 case 0x93DD: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12";
399 void print_compressed_formats(void)
404 glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &num_fmt);
405 printf("%d generic compressed texture formats available:\n", num_fmt);
407 if(!(fmtlist = malloc(num_fmt * sizeof *fmtlist))) {
408 fprintf(stderr, "failed to allocate texture formats enumeration buffer\n");
411 glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, fmtlist);
413 for(i=0; i<num_fmt; i++) {
414 printf(" %05x: %s ", fmtlist[i], fmtstr(fmtlist[i]));
416 glGetInternalformativ(GL_TEXTURE_2D, fmtlist[i], GL_TEXTURE_COMPRESSED, 1, ¶ms);
417 printf("(%s format)\n", params == GL_TRUE ? "compressed" : "not compressed");