#include #include #define COLOR_FORMAT_COUNT 3 struct { const char *extension; GLenum internal_format; } COLOR_FORMATS[] = { { NULL, GL_RGBA }, { "GL_ATI_texture_float", GL_RGBA_FLOAT16_ATI }, { "GL_ATI_texture_float", GL_RGBA_FLOAT32_ATI } }; #define TARGET_AND_DIMENSION_COUNT 4 struct { const char *extension; GLenum target; GLuint width; GLuint height; } TARGETS_AND_DIMENSIONS[] = { { NULL, GL_TEXTURE_2D, 512, 512 }, { "GL_ARB_texture_non_power_of_two", GL_TEXTURE_2D, 640, 480 }, { "GL_ARB_texture_rectangle", GL_TEXTURE_RECTANGLE_ARB, 512, 512 }, { "GL_ARB_texture_rectangle", GL_TEXTURE_RECTANGLE_ARB, 640, 480 }, }; #define DEPTH_FORMAT_COUNT 5 struct { const char *extension; GLenum internal_format; GLenum format; GLenum type; } DEPTH_FORMATS[] = { { "GL_ARB_depth_texture", GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE }, { "GL_ARB_depth_texture", GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE }, { "GL_ARB_depth_texture", GL_DEPTH_COMPONENT16_ARB, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE }, { "GL_EXT_packed_depth_stencil", GL_DEPTH_STENCIL_EXT, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT }, { "GL_EXT_packed_depth_stencil", GL_DEPTH24_STENCIL8_EXT, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT }, }; int extension_supported(const char *name) { return name == NULL || gluCheckExtension((const GLubyte *)name, glGetString(GL_EXTENSIONS)); } const char *enum_to_string(GLenum constant) { switch (constant) { case GL_RGBA : return "RGBA"; case GL_RGBA_FLOAT16_ATI: return "RGBA_FLOAT16_ATI"; case GL_RGBA_FLOAT32_ATI: return "RGBA_FLOAT32_ATI"; case GL_TEXTURE_2D : return "TEXTURE_2D"; case GL_TEXTURE_RECTANGLE_ARB: return "TEXTURE_RECTANGLE_ARB"; case GL_DEPTH_COMPONENT : return "DEPTH_COMPONENT"; case GL_DEPTH_COMPONENT24_ARB: return "DEPTH_COMPONENT24_ARB"; case GL_DEPTH_COMPONENT16_ARB: return "DEPTH_COMPONENT16_ARB"; case GL_DEPTH_STENCIL_EXT : return "DEPTH_STENCIL_EXT"; case GL_DEPTH24_STENCIL8_EXT : return "DEPTH24_STENCIL8_EXT"; case GL_FRAMEBUFFER_COMPLETE_EXT : return "FRAMEBUFFER_COMPLETE_EXT "; case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT : return "FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT "; case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: return "FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT"; case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT : return "FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT "; case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT : return "FRAMEBUFFER_INCOMPLETE_FORMATS_EXT "; case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT : return "FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT "; case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT : return "FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT "; case GL_FRAMEBUFFER_UNSUPPORTED_EXT : return "FRAMEBUFFER_UNSUPPORTED_EXT "; default: { char *string; // deliberate leakage, yay! asprintf(&string, "0x%04x", (unsigned)constant); return string; } } } void print_report( GLenum color_internal_format, GLenum target, GLuint width, GLuint height, GLenum depth_internal_format, GLenum framebuffer_status) { printf( "Received %s for %s, %s %ux%u, %s\n", enum_to_string(framebuffer_status), enum_to_string(color_internal_format), enum_to_string(target), (unsigned)width, (unsigned)height, enum_to_string(depth_internal_format)); } void run_test( GLenum color_internal_format, GLenum target, GLuint width, GLuint height, GLenum depth_internal_format, GLenum depth_format, GLenum depth_type) { GLuint color_texture; glGenTextures(1, &color_texture); glBindTexture(target, color_texture); glTexImage2D( target, 0, color_internal_format, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); GLuint depth_texture; glGenTextures(1, &depth_texture); glBindTexture(target, depth_texture); glTexImage2D( target, 0, depth_internal_format, width, height, 0, depth_format, depth_type, NULL); glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glBindTexture(target, 0); GLuint fbo; glGenFramebuffersEXT(1, &fbo); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo); glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, target, color_texture, 0); glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, target, depth_texture, 0); GLenum framebuffer_status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); print_report( color_internal_format, target, width, height, depth_internal_format, framebuffer_status); } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); glutInitWindowSize(640, 480); glutCreateWindow("FBO Format Tester"); int count = 0; int color, texture, depth; for (color = 0; color < COLOR_FORMAT_COUNT; ++color) { if (!extension_supported(COLOR_FORMATS[color].extension)) { continue; } for (texture = 0; texture < TARGET_AND_DIMENSION_COUNT; ++texture) { if (!extension_supported(TARGETS_AND_DIMENSIONS[texture].extension)) { continue; } for (depth = 0; depth < DEPTH_FORMAT_COUNT; ++depth) { if (!extension_supported(DEPTH_FORMATS[depth].extension)) { continue; } ++count; GLenum color_internal_format = COLOR_FORMATS[color].internal_format; GLenum target = TARGETS_AND_DIMENSIONS[texture].target; GLuint width = TARGETS_AND_DIMENSIONS[texture].width; GLuint height = TARGETS_AND_DIMENSIONS[texture].height; GLenum depth_internal_format = DEPTH_FORMATS[depth].internal_format; GLenum depth_format = DEPTH_FORMATS[depth].format; GLenum depth_type = DEPTH_FORMATS[depth].type; run_test( color_internal_format, target, width, height, depth_internal_format, depth_format, depth_type); } } } printf( "\nRan %d tests of a potential %d\n", count, COLOR_FORMAT_COUNT * TARGET_AND_DIMENSION_COUNT * DEPTH_FORMAT_COUNT); return EXIT_SUCCESS; }