132001f49Smrg/* 232001f49Smrg * Test glReadPixels speed 332001f49Smrg * Brian Paul 432001f49Smrg * 9 April 2004 532001f49Smrg * 632001f49Smrg * Compile: 732001f49Smrg * gcc readrate.c -L/usr/X11R6/lib -lglut -lGLU -lGL -lX11 -o readrate 832001f49Smrg */ 932001f49Smrg 1032001f49Smrg#include <assert.h> 1132001f49Smrg#include <stdio.h> 1232001f49Smrg#include <stdlib.h> 1332001f49Smrg#include <math.h> 1432001f49Smrg#include <GL/glew.h> 1532001f49Smrg#include "glut_wrap.h" 1632001f49Smrg 1732001f49Smrg/* Hack, to test drawing instead of reading */ 1832001f49Smrg#define DRAW 0 1932001f49Smrg 2032001f49Smrg#define MAX_WIDTH 1280 2132001f49Smrg#define MAX_HEIGHT 1024 2232001f49Smrg 2332001f49Smrg#define NUM_WIDTHS 4 2432001f49Smrg#define NUM_HEIGHTS 4 2532001f49Smrgstatic const GLint Widths[] = {256, 512, 1024, 1280}; 2632001f49Smrgstatic const GLint Heights[] = {4, 32, 256, 512, 768, 1024}; 2732001f49Smrgstatic int WidthIndex = 1, HeightIndex = 3; 2832001f49Smrgstatic GLubyte *Buffer = NULL; 2932001f49Smrgstatic GLboolean Benchmark = GL_TRUE; 3032001f49Smrg 3132001f49Smrg#define NUM_PBO 2 3232001f49Smrg 3332001f49Smrgstatic GLuint PBObjects[4]; 3432001f49Smrg 3532001f49Smrgstatic GLboolean HavePBO = GL_FALSE; 3632001f49Smrg 3732001f49Smrg 3832001f49Smrgstruct format_type { 3932001f49Smrg const char *Name; 4032001f49Smrg GLuint Bytes; 4132001f49Smrg GLenum Format; 4232001f49Smrg GLenum Type; 4332001f49Smrg}; 4432001f49Smrg 4532001f49Smrgstatic struct format_type Formats[] = { 4632001f49Smrg { "GL_RGB, GLubyte", 3, GL_RGB, GL_UNSIGNED_BYTE }, 4732001f49Smrg { "GL_BGR, GLubyte", 3, GL_BGR, GL_UNSIGNED_BYTE }, 4832001f49Smrg { "GL_RGBA, GLubyte", 4, GL_RGBA, GL_UNSIGNED_BYTE }, 4932001f49Smrg { "GL_BGRA, GLubyte", 4, GL_BGRA, GL_UNSIGNED_BYTE }, 5032001f49Smrg { "GL_ABGR, GLubyte", 4, GL_ABGR_EXT, GL_UNSIGNED_BYTE }, 5132001f49Smrg { "GL_RGBA, GLuint_8_8_8_8", 4, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8 }, 5232001f49Smrg { "GL_BGRA, GLuint_8_8_8_8", 4, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8 }, 5332001f49Smrg { "GL_BGRA, GLuint_8_8_8_8_rev", 4, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV }, 5432001f49Smrg#ifdef GL_EXT_packed_depth_stencil 5532001f49Smrg { "GL_DEPTH_STENCIL_EXT, GLuint24+8", 4, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT }, 5632001f49Smrg#endif 5732001f49Smrg { "GL_DEPTH_COMPONENT, GLfloat", 4, GL_DEPTH_COMPONENT, GL_FLOAT }, 5832001f49Smrg { "GL_DEPTH_COMPONENT, GLuint", 4, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT } 5932001f49Smrg}; 6032001f49Smrg 6132001f49Smrg#define NUM_FORMATS (sizeof(Formats) / sizeof(struct format_type)) 6232001f49Smrg 6332001f49Smrg 6432001f49Smrgstatic void 6532001f49SmrgPrintString(const char *s) 6632001f49Smrg{ 6732001f49Smrg while (*s) { 6832001f49Smrg glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s); 6932001f49Smrg s++; 7032001f49Smrg } 7132001f49Smrg} 7232001f49Smrg 7332001f49Smrg 7432001f49Smrgstatic void 7532001f49SmrgMeasureFormat(struct format_type *fmt, GLint width, GLint height, GLuint pbo) 7632001f49Smrg{ 7732001f49Smrg double t0 = glutGet(GLUT_ELAPSED_TIME) * 0.001; 7832001f49Smrg double t1; 7932001f49Smrg int j; 8032001f49Smrg 8132001f49Smrg for (j = 0; ; j++) { 8232001f49Smrg 8332001f49Smrg glBegin(GL_POINTS); 8432001f49Smrg glVertex2f(1,1); 8532001f49Smrg glEnd(); 8632001f49Smrg 8732001f49Smrg#if DRAW 8832001f49Smrg glWindowPos2iARB(0,0); 8932001f49Smrg glDrawPixels(width, height, 9032001f49Smrg fmt->Format, fmt->Type, Buffer); 9132001f49Smrg glFinish(); 9232001f49Smrg#else 9332001f49Smrg if (pbo) { 9432001f49Smrg glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, PBObjects[j % NUM_PBO]); 9532001f49Smrg glReadPixels(0, 0, width, height, 9632001f49Smrg fmt->Format, fmt->Type, 0); 9732001f49Smrg } 9832001f49Smrg else { 9932001f49Smrg glReadPixels(0, 0, width, height, 10032001f49Smrg fmt->Format, fmt->Type, Buffer); 10132001f49Smrg } 10232001f49Smrg#endif 10332001f49Smrg 10432001f49Smrg t1 = glutGet(GLUT_ELAPSED_TIME) * 0.001; 10532001f49Smrg if (t1 - t0 > 2.0) { 10632001f49Smrg GLdouble rate = width * height / (1024.0 * 1024.0) * j / (t1 - t0); 10732001f49Smrg#if DRAW 10832001f49Smrg printf("%-32s %.2f draws/sec %.2f MPixels/sec %.2f MBytes/sec\n", 10932001f49Smrg fmt->Name, j / (t1-t0), rate, rate * fmt->Bytes); 11032001f49Smrg#else 11132001f49Smrg printf("%-32s %.2f reads/sec %.2f MPixels/sec %.2f MBytes/sec\n", 11232001f49Smrg fmt->Name, j / (t1-t0), rate, rate * fmt->Bytes); 11332001f49Smrg#endif 11432001f49Smrg break; 11532001f49Smrg } 11632001f49Smrg 11732001f49Smrg if (j == 0) { 11832001f49Smrg /* check for error */ 11932001f49Smrg GLenum err = glGetError(); 12032001f49Smrg if (err) { 12132001f49Smrg printf("GL Error 0x%x for %s\n", err, fmt->Name); 12232001f49Smrg return; 12332001f49Smrg } 12432001f49Smrg } 12532001f49Smrg } 12632001f49Smrg} 12732001f49Smrg 12832001f49Smrg 12932001f49Smrg 13032001f49Smrgstatic void 13132001f49SmrgDraw(void) 13232001f49Smrg{ 13332001f49Smrg char str[1000]; 13432001f49Smrg int width = Widths[WidthIndex]; 13532001f49Smrg int height = Heights[HeightIndex]; 13632001f49Smrg int y = MAX_HEIGHT - 50; 13732001f49Smrg 13832001f49Smrg glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 13932001f49Smrg 14032001f49Smrg glWindowPos2iARB(10, y); 14132001f49Smrg sprintf(str, "ReadPixels size: %d x %d", width, height); 14232001f49Smrg PrintString(str); 14332001f49Smrg y -= 14; 14432001f49Smrg 14532001f49Smrg glWindowPos2iARB(10, y); 14632001f49Smrg PrintString("Press up/down/left/right to change image size."); 14732001f49Smrg y -= 14; 14832001f49Smrg 14932001f49Smrg glWindowPos2iARB(10, y); 15032001f49Smrg PrintString("Press 'b' to run benchmark test."); 15132001f49Smrg y -= 14; 15232001f49Smrg 15332001f49Smrg if (Benchmark) { 15432001f49Smrg glWindowPos2iARB(10, y); 15532001f49Smrg PrintString("Testing..."); 15632001f49Smrg } 15732001f49Smrg 15832001f49Smrg glutSwapBuffers(); 15932001f49Smrg 16032001f49Smrg if (Benchmark) { 16132001f49Smrg GLuint i, pbo; 16232001f49Smrg#if DRAW 16332001f49Smrg printf("Draw size: Width=%d Height=%d\n", width, height); 16432001f49Smrg#else 16532001f49Smrg printf("Read size: Width=%d Height=%d\n", width, height); 16632001f49Smrg#endif 16732001f49Smrg for (pbo = 0; pbo <= HavePBO; pbo++) { 16832001f49Smrg printf("Pixel Buffer Object: %d\n", pbo); 16932001f49Smrg 17032001f49Smrg if (pbo == 0) { 17132001f49Smrg glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, 0); 17232001f49Smrg } 17332001f49Smrg 17432001f49Smrg for (i = 0; i < NUM_FORMATS; i++) { 17532001f49Smrg MeasureFormat(Formats + i, width, height, pbo); 17632001f49Smrg } 17732001f49Smrg } 17832001f49Smrg 17932001f49Smrg Benchmark = GL_FALSE; 18032001f49Smrg 18132001f49Smrg /* redraw window text */ 18232001f49Smrg glutPostRedisplay(); 18332001f49Smrg } 18432001f49Smrg 18532001f49Smrg} 18632001f49Smrg 18732001f49Smrg 18832001f49Smrgstatic void 18932001f49SmrgReshape(int width, int height) 19032001f49Smrg{ 19132001f49Smrg glViewport(0, 0, width, height); 19232001f49Smrg glMatrixMode(GL_PROJECTION); 19332001f49Smrg glLoadIdentity(); 19432001f49Smrg glOrtho(-1, 1, -1, 1, -1, 1); 19532001f49Smrg glMatrixMode(GL_MODELVIEW); 19632001f49Smrg glLoadIdentity(); 19732001f49Smrg} 19832001f49Smrg 19932001f49Smrg 20032001f49Smrgstatic void 20132001f49SmrgKey(unsigned char key, int x, int y) 20232001f49Smrg{ 20332001f49Smrg (void) x; 20432001f49Smrg (void) y; 20532001f49Smrg switch (key) { 20632001f49Smrg case 'b': 20732001f49Smrg Benchmark = 1; 20832001f49Smrg break; 20932001f49Smrg case 27: 21032001f49Smrg exit(0); 21132001f49Smrg break; 21232001f49Smrg } 21332001f49Smrg glutPostRedisplay(); 21432001f49Smrg} 21532001f49Smrg 21632001f49Smrg 21732001f49Smrgstatic void 21832001f49SmrgSpecialKey(int key, int x, int y) 21932001f49Smrg{ 22032001f49Smrg (void) x; 22132001f49Smrg (void) y; 22232001f49Smrg switch (key) { 22332001f49Smrg case GLUT_KEY_UP: 22432001f49Smrg if (HeightIndex + 1 < NUM_WIDTHS) 22532001f49Smrg HeightIndex++; 22632001f49Smrg break; 22732001f49Smrg case GLUT_KEY_DOWN: 22832001f49Smrg if (HeightIndex > 0) 22932001f49Smrg HeightIndex--; 23032001f49Smrg break; 23132001f49Smrg case GLUT_KEY_LEFT: 23232001f49Smrg if (WidthIndex > 0) 23332001f49Smrg WidthIndex--; 23432001f49Smrg break; 23532001f49Smrg case GLUT_KEY_RIGHT: 23632001f49Smrg if (WidthIndex + 1 < NUM_HEIGHTS) 23732001f49Smrg WidthIndex++; 23832001f49Smrg break; 23932001f49Smrg } 24032001f49Smrg glutPostRedisplay(); 24132001f49Smrg} 24232001f49Smrg 24332001f49Smrg 24432001f49Smrgstatic void 24532001f49SmrgInit(void) 24632001f49Smrg{ 24732001f49Smrg Buffer = malloc(MAX_WIDTH * MAX_HEIGHT * 4); 24832001f49Smrg assert(Buffer); 24932001f49Smrg#if DRAW 25032001f49Smrg printf("glDrawPixels test report:\n"); 25132001f49Smrg#else 25232001f49Smrg printf("glReadPixels test report:\n"); 25332001f49Smrg#endif 25432001f49Smrg printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER)); 25532001f49Smrg printf("GL_VERSION: %s\n", (char *) glGetString(GL_VERSION)); 25632001f49Smrg 25732001f49Smrg if (glutExtensionSupported("GL_ARB_pixel_buffer_object")) { 25832001f49Smrg int i; 25932001f49Smrg HavePBO = 1; 26032001f49Smrg glGenBuffersARB(NUM_PBO, PBObjects); 26132001f49Smrg for (i = 0; i < NUM_PBO; i++) { 26232001f49Smrg glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, PBObjects[i]); 26332001f49Smrg glBufferDataARB(GL_PIXEL_PACK_BUFFER_EXT, 26432001f49Smrg MAX_WIDTH * MAX_HEIGHT * 4, NULL, GL_STREAM_READ); 26532001f49Smrg } 26632001f49Smrg } 26732001f49Smrg} 26832001f49Smrg 26932001f49Smrg 27032001f49Smrgint 27132001f49Smrgmain(int argc, char *argv[]) 27232001f49Smrg{ 27332001f49Smrg glutInit(&argc, argv); 27432001f49Smrg glutInitWindowPosition(0, 0); 27532001f49Smrg glutInitWindowSize(MAX_WIDTH, MAX_HEIGHT); 27632001f49Smrg glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_STENCIL); 27732001f49Smrg glutCreateWindow(argv[0]); 27832001f49Smrg glewInit(); 27932001f49Smrg glutReshapeFunc(Reshape); 28032001f49Smrg glutKeyboardFunc(Key); 28132001f49Smrg glutSpecialFunc(SpecialKey); 28232001f49Smrg glutDisplayFunc(Draw); 28332001f49Smrg Init(); 28432001f49Smrg glutMainLoop(); 28532001f49Smrg return 0; 28632001f49Smrg} 287