1/*
2 * Test packed pixel formats for textures.
3 * Brian Paul
4 * 12 May 2004
5 */
6
7#include <stdio.h>
8#include <stdlib.h>
9#include <math.h>
10#include <string.h>
11#include <GL/glew.h>
12#include "glut_wrap.h"
13
14
15struct pixel_format {
16   const char *name;
17   GLenum format;
18   GLenum type;
19   GLint bytes;
20   GLuint redTexel, greenTexel; /* with approx 51% alpha, when applicable */
21};
22
23static const struct pixel_format Formats[] = {
24
25   { "GL_RGBA/GL_UNSIGNED_INT_8_8_8_8",
26     GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, 4, 0xff000080, 0x00ff0080 },
27   { "GL_RGBA/GL_UNSIGNED_INT_8_8_8_8_REV",
28     GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, 4, 0x800000ff, 0x8000ff00 },
29   { "GL_RGBA/GL_UNSIGNED_INT_10_10_10_2",
30     GL_RGBA, GL_UNSIGNED_INT_10_10_10_2, 4, 0xffc00002, 0x3ff002 },
31   { "GL_RGBA/GL_UNSIGNED_INT_2_10_10_10_REV",
32     GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, 4, 0xc00003ff, 0xc00ffc00 },
33   { "GL_RGBA/GL_UNSIGNED_SHORT_4_4_4_4",
34     GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 2, 0xf008, 0x0f08 },
35   { "GL_RGBA/GL_UNSIGNED_SHORT_4_4_4_4_REV",
36     GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4_REV, 2, 0x800f, 0x80f0 },
37   { "GL_RGBA/GL_UNSIGNED_SHORT_5_5_5_1",
38     GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, 2, 0xf801, 0x7c1 },
39   { "GL_RGBA/GL_UNSIGNED_SHORT_1_5_5_5_REV",
40     GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, 2, 0x801f, 0x83e0 },
41
42   { "GL_BGRA/GL_UNSIGNED_INT_8_8_8_8",
43     GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, 4, 0x0000ff80, 0x00ff0080 },
44   { "GL_BGRA/GL_UNSIGNED_INT_8_8_8_8_REV",
45     GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 4, 0x80ff0000, 0x8000ff00 },
46   { "GL_BGRA/GL_UNSIGNED_SHORT_4_4_4_4",
47     GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4, 2, 0x00f8, 0x0f08 },
48   { "GL_BGRA/GL_UNSIGNED_SHORT_4_4_4_4_REV",
49     GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV, 2, 0x8f00, 0x80f0 },
50   { "GL_BGRA/GL_UNSIGNED_SHORT_5_5_5_1",
51     GL_BGRA, GL_UNSIGNED_SHORT_5_5_5_1, 2, 0x3f, 0x7c1 },
52   { "GL_BGRA/GL_UNSIGNED_SHORT_1_5_5_5_REV",
53     GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, 2, 0xfc00, 0x83e0 },
54
55   { "GL_ABGR_EXT/GL_UNSIGNED_INT_8_8_8_8",
56     GL_ABGR_EXT, GL_UNSIGNED_INT_8_8_8_8, 4, 0x800000ff, 0x8000ff00 },
57   { "GL_ABGR_EXT/GL_UNSIGNED_INT_8_8_8_8_REV",
58     GL_ABGR_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, 4, 0xff000080, 0x00ff0080 },
59   { "GL_ABGR_EXT/GL_UNSIGNED_SHORT_4_4_4_4",
60     GL_ABGR_EXT, GL_UNSIGNED_SHORT_4_4_4_4, 2, 0x800f, 0x80f0 },
61   { "GL_ABGR_EXT/GL_UNSIGNED_SHORT_4_4_4_4_REV",
62     GL_ABGR_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV, 2, 0xf008, 0x0f08 },
63   { "GL_ABGR_EXT/GL_UNSIGNED_SHORT_5_5_5_1",
64     GL_ABGR_EXT, GL_UNSIGNED_SHORT_5_5_5_1, 2, 0xf801, 0xf83e },
65   { "GL_ABGR_EXT/GL_UNSIGNED_SHORT_1_5_5_5_REV",
66     GL_ABGR_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV, 2, 0x800f, 0x7c0f },
67
68   { "GL_RGB/GL_UNSIGNED_SHORT_5_6_5",
69     GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 2, 0xf800, 0x7e0 },
70   { "GL_RGB/GL_UNSIGNED_SHORT_5_6_5_REV",
71     GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV, 2, 0x1f, 0x7e0 },
72   { "GL_RGB/GL_UNSIGNED_BYTE_3_3_2",
73     GL_RGB, GL_UNSIGNED_BYTE_3_3_2, 1, 0xe0, 0x1c },
74   { "GL_RGB/GL_UNSIGNED_BYTE_2_3_3_REV",
75     GL_RGB, GL_UNSIGNED_BYTE_2_3_3_REV, 1, 0x7, 0x38 },
76
77   { NULL, 0, 0, 0, 0, 0 }
78};
79
80
81struct name_format {
82   const char *name;
83   GLenum format;
84};
85
86static const struct name_format IntFormats[] = {
87   { "GL_RGBA", GL_RGBA },
88   { "GL_RGBA2", GL_RGBA2 },
89   { "GL_RGBA4", GL_RGBA4 },
90   { "GL_RGB5_A1", GL_RGB5_A1 },
91   { "GL_RGBA8", GL_RGBA8 },
92   { "GL_RGBA12", GL_RGBA12 },
93   { "GL_RGBA16", GL_RGBA16 },
94   { "GL_RGB10_A2", GL_RGB10_A2 },
95
96   { "GL_RGB", GL_RGB },
97   { "GL_R3_G3_B2", GL_R3_G3_B2 },
98   { "GL_RGB4", GL_RGB4 },
99   { "GL_RGB5", GL_RGB5 },
100   { "GL_RGB8", GL_RGB8 },
101   { "GL_RGB10", GL_RGB10 },
102   { "GL_RGB12", GL_RGB12 },
103   { "GL_RGB16", GL_RGB16 },
104
105};
106
107#define NUM_INT_FORMATS (sizeof(IntFormats) / sizeof(IntFormats[0]))
108static GLuint CurFormat = 0;
109
110static GLboolean Test3D = GL_FALSE;
111static GLboolean Blend = GL_FALSE;
112
113
114static void
115PrintString(const char *s)
116{
117   while (*s) {
118      glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s);
119      s++;
120   }
121}
122
123
124static void
125MakeTexture(const struct pixel_format *format, GLenum intFormat, GLboolean swap)
126{
127   GLubyte texBuffer[1000];
128   int i;
129
130   glPixelStorei(GL_UNPACK_SWAP_BYTES, swap);
131
132   if (format->bytes == 1) {
133      for (i = 0; i < 8; i++) {
134         texBuffer[i] = format->redTexel;
135      }
136      for (i = 8; i < 16; i++) {
137         texBuffer[i] = format->greenTexel;
138      }
139   }
140   else if (format->bytes == 2) {
141      GLushort *us = (GLushort *) texBuffer;
142      for (i = 0; i < 8; i++) {
143         us[i] = format->redTexel;
144      }
145      for (i = 8; i < 16; i++) {
146         us[i] = format->greenTexel;
147      }
148      if (swap) {
149         for (i = 0; i < 16; i++)
150            us[i] = (us[i] << 8) | (us[i] >> 8);
151      }
152   }
153   else if (format->bytes == 4) {
154      GLuint *ui = (GLuint *) texBuffer;
155      for (i = 0; i < 8; i++) {
156         ui[i] = format->redTexel;
157      }
158      for (i = 8; i < 16; i++) {
159         ui[i] = format->greenTexel;
160      }
161      if (swap) {
162         for (i = 0; i < 16; i++) {
163            GLuint b = ui[i];
164            ui[i] =  (b >> 24)
165                  | ((b >> 8) & 0xff00)
166                  | ((b << 8) & 0xff0000)
167                  | ((b << 24) & 0xff000000);
168         }
169      }
170   }
171   else {
172      abort();
173   }
174
175   if (Test3D) {
176      /* 4 x 4 x 4 texture, undefined data */
177      glTexImage3D(GL_TEXTURE_3D, 0, intFormat, 4, 4, 4, 0,
178                   format->format, format->type, NULL);
179      /* fill in Z=1 and Z=2 slices with the real texture data */
180      glTexSubImage3D(GL_TEXTURE_3D, 0,
181                      0, 0, 1,  /* offset */
182                      4, 4, 1,  /* size */
183                      format->format, format->type, texBuffer);
184      glTexSubImage3D(GL_TEXTURE_3D, 0,
185                      0, 0, 2,  /* offset */
186                      4, 4, 1,  /* size */
187                      format->format, format->type, texBuffer);
188   }
189   else {
190      glTexImage2D(GL_TEXTURE_2D, 0, intFormat, 4, 4, 0,
191                   format->format, format->type, texBuffer);
192   }
193
194   if (0) {
195      GLint r, g, b, a, l, i;
196      glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_RED_SIZE, &r);
197      glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_GREEN_SIZE, &g);
198      glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BLUE_SIZE, &b);
199      glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_ALPHA_SIZE, &a);
200      glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_LUMINANCE_SIZE, &l);
201      glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTENSITY_SIZE, &i);
202      printf("IntFormat: 0x%x  R %d  G %d  B %d  A %d  L %d  I %d\n",
203             intFormat, r, g, b, a, l, i);
204      glGetError();
205   }
206
207   if (glGetError()) {
208      printf("GL Error for %s\n", format->name);
209      memset(texBuffer, 255, 1000);
210      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 4, 4, 0,
211                   GL_RGB, GL_UNSIGNED_BYTE, texBuffer);
212   }
213}
214
215
216
217static void
218Draw(void)
219{
220   char s[1000];
221   int w = 350, h = 20;
222   int i, swap;
223
224   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
225
226   for (swap = 0; swap < 2; swap++) {
227     for (i = 0; Formats[i].name; i++) {
228        glPushMatrix();
229        glTranslatef(swap * (w + 2), i * (h + 2), 0);
230
231        MakeTexture(Formats + i, IntFormats[CurFormat].format, swap);
232
233        if (Test3D)
234           glEnable(GL_TEXTURE_3D);
235        else
236           glEnable(GL_TEXTURE_2D);
237
238        if (Blend)
239           glEnable(GL_BLEND);
240
241        glBegin(GL_POLYGON);
242        glTexCoord3f(0, 0, 0.5);  glVertex2f(0, 0);
243        glTexCoord3f(1, 0, 0.5);  glVertex2f(w, 0);
244        glTexCoord3f(1, 1, 0.5);  glVertex2f(w, h);
245        glTexCoord3f(0, 1, 0.5);  glVertex2f(0, h);
246        glEnd();
247
248        if (Test3D)
249           glDisable(GL_TEXTURE_3D);
250        else
251           glDisable(GL_TEXTURE_2D);
252
253        glDisable(GL_BLEND);
254
255        glColor3f(0, 0, 0);
256        glRasterPos2i(8, 6);
257        PrintString(Formats[i].name);
258
259        glPopMatrix();
260     }
261   }
262
263   glPushMatrix();
264   glTranslatef(2, i * (h + 2), 0);
265   glColor3f(1, 1, 1);
266   glRasterPos2i(8, 6);
267   PrintString("Normal");
268   glRasterPos2i(w + 2, 6);
269   PrintString("Byte Swapped");
270   glPopMatrix();
271
272   glPushMatrix();
273   glTranslatef(2, (i + 1) * (h + 2), 0);
274   glRasterPos2i(8, 6);
275   sprintf(s, "Internal Texture Format [f/F]: %s (%d of %lu)",
276           IntFormats[CurFormat].name, CurFormat + 1, (unsigned long) NUM_INT_FORMATS);
277   PrintString(s);
278   glPopMatrix();
279
280   glPushMatrix();
281   glTranslatef(2, (i + 2) * (h + 2), 0);
282   glRasterPos2i(8, 6);
283   if (Test3D)
284      PrintString("Target [2/3]: GL_TEXTURE_3D");
285   else
286      PrintString("Target [2/3]: GL_TEXTURE_2D");
287   glPopMatrix();
288
289   glPushMatrix();
290   glTranslatef(2, (i + 3) * (h + 2), 0);
291   glRasterPos2i(8, 6);
292   if (Blend)
293      PrintString("Blend: Yes");
294   else
295      PrintString("Blend: No");
296   glPopMatrix();
297
298   glutSwapBuffers();
299}
300
301
302static void
303Reshape(int width, int height)
304{
305   glViewport(0, 0, width, height);
306   glMatrixMode(GL_PROJECTION);
307   glLoadIdentity();
308   glOrtho(0, width, 0, height, -1, 1);
309   glMatrixMode(GL_MODELVIEW);
310   glLoadIdentity();
311}
312
313
314static void
315Key(unsigned char key, int x, int y)
316{
317   (void) x;
318   (void) y;
319   switch (key) {
320      case 'b':
321         Blend = !Blend;
322         break;
323      case 'F':
324         if (CurFormat == 0)
325            CurFormat = NUM_INT_FORMATS - 1;
326         else
327            CurFormat--;
328         break;
329      case 'f':
330         CurFormat++;
331         if (CurFormat == NUM_INT_FORMATS)
332            CurFormat = 0;
333         break;
334      case '2':
335         Test3D = GL_FALSE;
336         break;
337      case '3':
338         Test3D = GL_TRUE;
339         break;
340      case 27:
341         exit(0);
342         break;
343   }
344   glutPostRedisplay();
345}
346
347
348static void
349Init(void)
350{
351   printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
352   printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
353   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
354   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
355   glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
356   glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
357   glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
358   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
359}
360
361
362int
363main(int argc, char *argv[])
364{
365   glutInit(&argc, argv);
366   glutInitWindowPosition(0, 0);
367   glutInitWindowSize(700, 800);
368   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
369   glutCreateWindow(argv[0]);
370   glewInit();
371   glutReshapeFunc(Reshape);
372   glutKeyboardFunc(Key);
373   glutDisplayFunc(Draw);
374   Init();
375   glutMainLoop();
376   return 0;
377}
378