#ifndef GL_LUMINANCE_FLOAT16_APPLE #define GL_LUMINANCE_FLOAT16_APPLE GL_LUMINANCE_FLOAT16_ATI #endif static const char *internal_format_to_string(GLenum internal_format) { if (internal_format == GL_RGBA) { return "RGBA"; } else if (internal_format == GL_LUMINANCE_FLOAT16_APPLE) { return "LUMINANCE_FLOAT16 uploaded as LUMINANCE/FLOAT"; } else { abort(); } } static void upload_texture( GLenum target, GLenum internal_format, GLsizei texture_width, GLsizei texture_height, GLsizei width, GLsizei height) { size_t pixel_size = 0; GLenum format = 0; GLenum type = 0; if (internal_format == GL_RGBA) { pixel_size = 4; format = GL_RGBA; type = GL_UNSIGNED_BYTE; } else if (internal_format == GL_LUMINANCE_FLOAT16_APPLE) { pixel_size = 4; format = GL_LUMINANCE; type = GL_FLOAT; } else { abort(); } void *pixels = calloc(width * height, pixel_size); glBindTexture(target, target); glEnable(target); glTexImage2D( target, 0, internal_format, texture_width, texture_height, 0, format, type, NULL); glTexSubImage2D( target, 0, 0, 0, width, height, format, type, pixels); free(pixels); } static inline unsigned next_power_of_two(unsigned i) { unsigned candidate = 1; while (candidate < i) { candidate <<= 1; } return candidate; } static float upload_twod_texture( GLenum internal_format, GLsizei size) { GLsizei texture_size = next_power_of_two(size); upload_texture( GL_TEXTURE_2D, internal_format, texture_size, texture_size, size, size); return (float)size / (float)texture_size; } #if defined(HAVE_NPOT_TEXTURE_SUPPORT) static float upload_twod_npot_texture( GLenum internal_format, GLsizei size) { upload_texture( GL_TEXTURE_2D, internal_format, size, size, size, size); return 1.0f; } #endif static float upload_rectangle_texture( GLenum internal_format, GLsizei size) { upload_texture( GL_TEXTURE_RECTANGLE_ARB, internal_format, size, size, size, size); return (float)size; } #define TEXTURE_SIZE_COUNT 6 GLsizei TEXTURE_SIZES[TEXTURE_SIZE_COUNT] = { 255, 256, 257, 511, 512, 513 }; #define UPLOAD_TEST_COUNT 1000 static float upload_test( unsigned texture_size, float (* upload_function)(GLenum, GLsizei), GLenum internal_format) { printf("uploading %u: ", texture_size); int then = glutGet(GLUT_ELAPSED_TIME); float max_st; for (unsigned j = 0; j < UPLOAD_TEST_COUNT; ++j) { max_st = upload_function(internal_format, texture_size); } glFinish(); int now = glutGet(GLUT_ELAPSED_TIME); printf("%dms\n", now - then); return max_st; } #define RENDER_TEST_COUNT 100000 static void render_test( unsigned texture_size, float max_s, float max_t) { printf("rendering %u: ", texture_size); int then = glutGet(GLUT_ELAPSED_TIME); for (unsigned j = 0; j < RENDER_TEST_COUNT; ++j) { glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f); glTexCoord2f(max_s, 0.0f); glVertex2f( 1.0f, -1.0f); glTexCoord2f(max_s, max_t); glVertex2f( 1.0f, 1.0f); glTexCoord2f(0.0f, max_t); glVertex2f(-1.0f, 1.0f); glEnd(); } glFinish(); int now = glutGet(GLUT_ELAPSED_TIME); printf("%dms\n", now - then); } static void upload_textures( const char *kind, float (* upload_function)(GLenum, GLsizei), GLenum internal_format) { printf( "=== uploading %s, %s textures ===\n", kind, internal_format_to_string(internal_format)); for (unsigned i = 0; i < TEXTURE_SIZE_COUNT; ++i) { float max_st = upload_test( TEXTURE_SIZES[i], upload_function, internal_format); render_test( TEXTURE_SIZES[i], max_st, max_st); glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_RECTANGLE_ARB); } } static void upload_all_textures(GLenum internal_format) { upload_textures( "2D", upload_twod_texture, internal_format); #if defined(HAVE_NPOT_TEXTURE_SUPPORT) upload_textures( "2D NPOT", upload_twod_npot_texture, internal_format); #endif upload_textures( "RECTANGLE", upload_rectangle_texture, internal_format); } int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE); glutInitWindowSize(512, 512); glutCreateWindow("Rectangle Texture Speed Test"); upload_all_textures(GL_RGBA); upload_all_textures(GL_LUMINANCE_FLOAT16_APPLE); glutReportErrors(); return EXIT_SUCCESS; }