1/* 2 * Test glReadPixels speed 3 * Brian Paul 4 * 9 April 2004 5 * 6 * Compile: 7 * gcc readrate.c -L/usr/X11R6/lib -lglut -lGLU -lGL -lX11 -o readrate 8 */ 9 10#include <assert.h> 11#include <stdio.h> 12#include <stdlib.h> 13#include <math.h> 14#include <GL/glew.h> 15#include "glut_wrap.h" 16 17/* Hack, to test drawing instead of reading */ 18#define DRAW 0 19 20#define MAX_WIDTH 1280 21#define MAX_HEIGHT 1024 22 23#define NUM_WIDTHS 4 24#define NUM_HEIGHTS 4 25static const GLint Widths[] = {256, 512, 1024, 1280}; 26static const GLint Heights[] = {4, 32, 256, 512, 768, 1024}; 27static int WidthIndex = 1, HeightIndex = 3; 28static GLubyte *Buffer = NULL; 29static GLboolean Benchmark = GL_TRUE; 30 31#define NUM_PBO 2 32 33static GLuint PBObjects[4]; 34 35static GLboolean HavePBO = GL_FALSE; 36 37 38struct format_type { 39 const char *Name; 40 GLuint Bytes; 41 GLenum Format; 42 GLenum Type; 43}; 44 45static struct format_type Formats[] = { 46 { "GL_RGB, GLubyte", 3, GL_RGB, GL_UNSIGNED_BYTE }, 47 { "GL_BGR, GLubyte", 3, GL_BGR, GL_UNSIGNED_BYTE }, 48 { "GL_RGBA, GLubyte", 4, GL_RGBA, GL_UNSIGNED_BYTE }, 49 { "GL_BGRA, GLubyte", 4, GL_BGRA, GL_UNSIGNED_BYTE }, 50 { "GL_ABGR, GLubyte", 4, GL_ABGR_EXT, GL_UNSIGNED_BYTE }, 51 { "GL_RGBA, GLuint_8_8_8_8", 4, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8 }, 52 { "GL_BGRA, GLuint_8_8_8_8", 4, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8 }, 53 { "GL_BGRA, GLuint_8_8_8_8_rev", 4, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV }, 54#ifdef GL_EXT_packed_depth_stencil 55 { "GL_DEPTH_STENCIL_EXT, GLuint24+8", 4, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT }, 56#endif 57 { "GL_DEPTH_COMPONENT, GLfloat", 4, GL_DEPTH_COMPONENT, GL_FLOAT }, 58 { "GL_DEPTH_COMPONENT, GLuint", 4, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT } 59}; 60 61#define NUM_FORMATS (sizeof(Formats) / sizeof(struct format_type)) 62 63 64static void 65PrintString(const char *s) 66{ 67 while (*s) { 68 glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s); 69 s++; 70 } 71} 72 73 74static void 75MeasureFormat(struct format_type *fmt, GLint width, GLint height, GLuint pbo) 76{ 77 double t0 = glutGet(GLUT_ELAPSED_TIME) * 0.001; 78 double t1; 79 int j; 80 81 for (j = 0; ; j++) { 82 83 glBegin(GL_POINTS); 84 glVertex2f(1,1); 85 glEnd(); 86 87#if DRAW 88 glWindowPos2iARB(0,0); 89 glDrawPixels(width, height, 90 fmt->Format, fmt->Type, Buffer); 91 glFinish(); 92#else 93 if (pbo) { 94 glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, PBObjects[j % NUM_PBO]); 95 glReadPixels(0, 0, width, height, 96 fmt->Format, fmt->Type, 0); 97 } 98 else { 99 glReadPixels(0, 0, width, height, 100 fmt->Format, fmt->Type, Buffer); 101 } 102#endif 103 104 t1 = glutGet(GLUT_ELAPSED_TIME) * 0.001; 105 if (t1 - t0 > 2.0) { 106 GLdouble rate = width * height / (1024.0 * 1024.0) * j / (t1 - t0); 107#if DRAW 108 printf("%-32s %.2f draws/sec %.2f MPixels/sec %.2f MBytes/sec\n", 109 fmt->Name, j / (t1-t0), rate, rate * fmt->Bytes); 110#else 111 printf("%-32s %.2f reads/sec %.2f MPixels/sec %.2f MBytes/sec\n", 112 fmt->Name, j / (t1-t0), rate, rate * fmt->Bytes); 113#endif 114 break; 115 } 116 117 if (j == 0) { 118 /* check for error */ 119 GLenum err = glGetError(); 120 if (err) { 121 printf("GL Error 0x%x for %s\n", err, fmt->Name); 122 return; 123 } 124 } 125 } 126} 127 128 129 130static void 131Draw(void) 132{ 133 char str[1000]; 134 int width = Widths[WidthIndex]; 135 int height = Heights[HeightIndex]; 136 int y = MAX_HEIGHT - 50; 137 138 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 139 140 glWindowPos2iARB(10, y); 141 sprintf(str, "ReadPixels size: %d x %d", width, height); 142 PrintString(str); 143 y -= 14; 144 145 glWindowPos2iARB(10, y); 146 PrintString("Press up/down/left/right to change image size."); 147 y -= 14; 148 149 glWindowPos2iARB(10, y); 150 PrintString("Press 'b' to run benchmark test."); 151 y -= 14; 152 153 if (Benchmark) { 154 glWindowPos2iARB(10, y); 155 PrintString("Testing..."); 156 } 157 158 glutSwapBuffers(); 159 160 if (Benchmark) { 161 GLuint i, pbo; 162#if DRAW 163 printf("Draw size: Width=%d Height=%d\n", width, height); 164#else 165 printf("Read size: Width=%d Height=%d\n", width, height); 166#endif 167 for (pbo = 0; pbo <= HavePBO; pbo++) { 168 printf("Pixel Buffer Object: %d\n", pbo); 169 170 if (pbo == 0) { 171 glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, 0); 172 } 173 174 for (i = 0; i < NUM_FORMATS; i++) { 175 MeasureFormat(Formats + i, width, height, pbo); 176 } 177 } 178 179 Benchmark = GL_FALSE; 180 181 /* redraw window text */ 182 glutPostRedisplay(); 183 } 184 185} 186 187 188static void 189Reshape(int width, int height) 190{ 191 glViewport(0, 0, width, height); 192 glMatrixMode(GL_PROJECTION); 193 glLoadIdentity(); 194 glOrtho(-1, 1, -1, 1, -1, 1); 195 glMatrixMode(GL_MODELVIEW); 196 glLoadIdentity(); 197} 198 199 200static void 201Key(unsigned char key, int x, int y) 202{ 203 (void) x; 204 (void) y; 205 switch (key) { 206 case 'b': 207 Benchmark = 1; 208 break; 209 case 27: 210 exit(0); 211 break; 212 } 213 glutPostRedisplay(); 214} 215 216 217static void 218SpecialKey(int key, int x, int y) 219{ 220 (void) x; 221 (void) y; 222 switch (key) { 223 case GLUT_KEY_UP: 224 if (HeightIndex + 1 < NUM_WIDTHS) 225 HeightIndex++; 226 break; 227 case GLUT_KEY_DOWN: 228 if (HeightIndex > 0) 229 HeightIndex--; 230 break; 231 case GLUT_KEY_LEFT: 232 if (WidthIndex > 0) 233 WidthIndex--; 234 break; 235 case GLUT_KEY_RIGHT: 236 if (WidthIndex + 1 < NUM_HEIGHTS) 237 WidthIndex++; 238 break; 239 } 240 glutPostRedisplay(); 241} 242 243 244static void 245Init(void) 246{ 247 Buffer = malloc(MAX_WIDTH * MAX_HEIGHT * 4); 248 assert(Buffer); 249#if DRAW 250 printf("glDrawPixels test report:\n"); 251#else 252 printf("glReadPixels test report:\n"); 253#endif 254 printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER)); 255 printf("GL_VERSION: %s\n", (char *) glGetString(GL_VERSION)); 256 257 if (glutExtensionSupported("GL_ARB_pixel_buffer_object")) { 258 int i; 259 HavePBO = 1; 260 glGenBuffersARB(NUM_PBO, PBObjects); 261 for (i = 0; i < NUM_PBO; i++) { 262 glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, PBObjects[i]); 263 glBufferDataARB(GL_PIXEL_PACK_BUFFER_EXT, 264 MAX_WIDTH * MAX_HEIGHT * 4, NULL, GL_STREAM_READ); 265 } 266 } 267} 268 269 270int 271main(int argc, char *argv[]) 272{ 273 glutInit(&argc, argv); 274 glutInitWindowPosition(0, 0); 275 glutInitWindowSize(MAX_WIDTH, MAX_HEIGHT); 276 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_STENCIL); 277 glutCreateWindow(argv[0]); 278 glewInit(); 279 glutReshapeFunc(Reshape); 280 glutKeyboardFunc(Key); 281 glutSpecialFunc(SpecialKey); 282 glutDisplayFunc(Draw); 283 Init(); 284 glutMainLoop(); 285 return 0; 286} 287