/* * Test packed pixel formats for textures. * Brian Paul * 12 May 2004 */ #include #include #include #include #include struct pixel_format { const char *name; GLenum format; GLenum type; GLint bytes; GLuint redTexel, greenTexel; }; static const struct pixel_format Formats[] = { { "GL_RGBA/GL_UNSIGNED_INT_8_8_8_8", GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, 4, 0xff000000, 0x00ff0000 }, { "GL_RGBA/GL_UNSIGNED_INT_8_8_8_8_REV", GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, 4, 0x000000ff, 0x0000ff00 }, { "GL_RGBA/GL_UNSIGNED_INT_10_10_10_2", GL_RGBA, GL_UNSIGNED_INT_10_10_10_2, 4, 0xffc00000, 0x3ff000 }, { "GL_RGBA/GL_UNSIGNED_INT_2_10_10_10_REV", GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, 4, 0x3ff, 0xffc00 }, { "GL_RGBA/GL_UNSIGNED_SHORT_4_4_4_4", GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 2, 0xf000, 0x0f00 }, { "GL_RGBA/GL_UNSIGNED_SHORT_4_4_4_4_REV", GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4_REV, 2, 0x000f, 0x00f0 }, { "GL_RGBA/GL_UNSIGNED_SHORT_5_5_5_1", GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, 2, 0xf800, 0x7c0 }, { "GL_RGBA/GL_UNSIGNED_SHORT_1_5_5_5_REV", GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, 2, 0x1f, 0x3e0 }, { "GL_BGRA/GL_UNSIGNED_INT_8_8_8_8", GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, 4, 0x0000ff00, 0x00ff0000 }, { "GL_BGRA/GL_UNSIGNED_INT_8_8_8_8_REV", GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 4, 0x00ff0000, 0x0000ff00 }, { "GL_BGRA/GL_UNSIGNED_SHORT_4_4_4_4", GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4, 2, 0x00f0, 0x0f00 }, { "GL_BGRA/GL_UNSIGNED_SHORT_4_4_4_4_REV", GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV, 2, 0x0f00, 0x00f0 }, { "GL_BGRA/GL_UNSIGNED_SHORT_5_5_5_1", GL_BGRA, GL_UNSIGNED_SHORT_5_5_5_1, 2, 0x3e, 0x7c0 }, { "GL_BGRA/GL_UNSIGNED_SHORT_1_5_5_5_REV", GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, 2, 0x7c00, 0x3e0 }, { "GL_ABGR_EXT/GL_UNSIGNED_INT_8_8_8_8", GL_ABGR_EXT, GL_UNSIGNED_INT_8_8_8_8, 4, 0x000000ff, 0x0000ff00 }, { "GL_ABGR_EXT/GL_UNSIGNED_INT_8_8_8_8_REV", GL_ABGR_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, 4, 0xff000000, 0x00ff0000 }, { "GL_ABGR_EXT/GL_UNSIGNED_SHORT_4_4_4_4", GL_ABGR_EXT, GL_UNSIGNED_SHORT_4_4_4_4, 2, 0x000f, 0x00f0 }, { "GL_ABGR_EXT/GL_UNSIGNED_SHORT_4_4_4_4_REV", GL_ABGR_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV, 2, 0xf000, 0x0f00 }, { "GL_ABGR_EXT/GL_UNSIGNED_SHORT_5_5_5_1", GL_ABGR_EXT, GL_UNSIGNED_SHORT_5_5_5_1, 2, 0x1, 0x3e }, { "GL_ABGR_EXT/GL_UNSIGNED_SHORT_1_5_5_5_REV", GL_ABGR_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV, 2, 0x8000, 0x7c00 }, { "GL_RGB/GL_UNSIGNED_SHORT_5_6_5", GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 2, 0xf800, 0x7e0 }, { "GL_RGB/GL_UNSIGNED_SHORT_5_6_5_REV", GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV, 2, 0x1f, 0x7e0 }, { "GL_RGB/GL_UNSIGNED_BYTE_3_3_2", GL_RGB, GL_UNSIGNED_BYTE_3_3_2, 1, 0xe0, 0x1c }, { "GL_RGB/GL_UNSIGNED_BYTE_2_3_3_REV", GL_RGB, GL_UNSIGNED_BYTE_2_3_3_REV, 1, 0x7, 0x38 }, { NULL, 0, 0, 0, 0, 0 } }; struct name_format { const char *name; GLenum format; }; static const struct name_format IntFormats[] = { { "GL_RGBA", GL_RGBA }, { "GL_RGBA2", GL_RGBA2 }, { "GL_RGBA4", GL_RGBA4 }, { "GL_RGB5_A1", GL_RGB5_A1 }, { "GL_RGBA8", GL_RGBA8 }, { "GL_RGBA12", GL_RGBA12 }, { "GL_RGBA16", GL_RGBA16 }, { "GL_RGB10_A2", GL_RGB10_A2 }, { "GL_RGB", GL_RGB }, { "GL_R3_G3_B2", GL_R3_G3_B2 }, { "GL_RGB4", GL_RGB4 }, { "GL_RGB5", GL_RGB5 }, { "GL_RGB8", GL_RGB8 }, { "GL_RGB10", GL_RGB10 }, { "GL_RGB12", GL_RGB12 }, { "GL_RGB16", GL_RGB16 }, }; #define NUM_INT_FORMATS (sizeof(IntFormats) / sizeof(IntFormats[0])) static GLuint CurFormat = 0; static void PrintString(const char *s) { while (*s) { glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s); s++; } } static void MakeTexture(const struct pixel_format *format, GLenum intFormat, GLboolean swap) { GLubyte texBuffer[1000]; int i; glPixelStorei(GL_UNPACK_SWAP_BYTES, swap); if (format->bytes == 1) { for (i = 0; i < 8; i++) { texBuffer[i] = format->redTexel; } for (i = 8; i < 16; i++) { texBuffer[i] = format->greenTexel; } } else if (format->bytes == 2) { GLushort *us = (GLushort *) texBuffer; for (i = 0; i < 8; i++) { us[i] = format->redTexel; } for (i = 8; i < 16; i++) { us[i] = format->greenTexel; } if (swap) { for (i = 0; i < 16; i++) us[i] = (us[i] << 8) | (us[i] >> 8); } } else if (format->bytes == 4) { GLuint *ui = (GLuint *) texBuffer; for (i = 0; i < 8; i++) { ui[i] = format->redTexel; } for (i = 8; i < 16; i++) { ui[i] = format->greenTexel; } if (swap) { for (i = 0; i < 16; i++) { GLuint b = ui[i]; ui[i] = (b >> 24) | ((b >> 8) & 0xff00) | ((b << 8) & 0xff0000) | ((b << 24) & 0xff000000); } } } else { abort(); } glTexImage2D(GL_TEXTURE_2D, 0, intFormat, 4, 4, 0, format->format, format->type, texBuffer); if (glGetError()) { printf("GL Error for %s\n", format->name); memset(texBuffer, 255, 1000); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 4, 4, 0, GL_RGB, GL_UNSIGNED_BYTE, texBuffer); } } static void Draw(void) { char s[1000]; int w = 350, h = 20; int i, swap; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); for (swap = 0; swap < 2; swap++) { for (i = 0; Formats[i].name; i++) { glPushMatrix(); glTranslatef(swap * (w + 2), i * (h + 2), 0); MakeTexture(Formats + i, IntFormats[CurFormat].format, swap); glEnable(GL_TEXTURE_2D); glBegin(GL_POLYGON); glTexCoord2f(0, 0); glVertex2f(0, 0); glTexCoord2f(1, 0); glVertex2f(w, 0); glTexCoord2f(1, 1); glVertex2f(w, h); glTexCoord2f(0, 1); glVertex2f(0, h); glEnd(); glDisable(GL_TEXTURE_2D); glColor3f(0, 0, 0); glRasterPos2i(8, 6); PrintString(Formats[i].name); glPopMatrix(); } } glPushMatrix(); glTranslatef(2, i * (h + 2), 0); glColor3f(1, 1, 1); glRasterPos2i(8, 6); PrintString("Normal"); glRasterPos2i(w + 2, 6); PrintString("Byte Swapped"); glPopMatrix(); glPushMatrix(); glTranslatef(2, (i + 1) * (h + 2), 0); glRasterPos2i(8, 6); sprintf(s, "Internal Texture Format [f/F]: %s (%d of %d)", IntFormats[CurFormat].name, CurFormat + 1, NUM_INT_FORMATS); PrintString(s); glPopMatrix(); glutSwapBuffers(); } static void Reshape(int width, int height) { glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, width, 0, height, -1, 1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } static void Key(unsigned char key, int x, int y) { (void) x; (void) y; switch (key) { case 'F': if (CurFormat == 0) CurFormat = NUM_INT_FORMATS - 1; else CurFormat--; break; case 'f': CurFormat++; if (CurFormat == NUM_INT_FORMATS) CurFormat = 0; break; case 27: exit(0); break; } glutPostRedisplay(); } static void Init(void) { printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION)); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); } int main(int argc, char *argv[]) { glutInit(&argc, argv); glutInitWindowPosition(0, 0); glutInitWindowSize(700, 800); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); glutCreateWindow(argv[0]); glutReshapeFunc(Reshape); glutKeyboardFunc(Key); glutDisplayFunc(Draw); Init(); glutMainLoop(); return 0; }