subtexrate.c revision 32001f49
1/* 2 * Measure glTexSubImage and glCopyTexSubImage speed 3 * 4 * Brian Paul 5 * 26 Jan 2006 6 */ 7 8#include <stdio.h> 9#include <stdlib.h> 10#include <string.h> 11#include <math.h> 12#include <GL/glew.h> 13#include "glut_wrap.h" 14 15static GLint WinWidth = 1024, WinHeight = 512; 16static GLint TexWidth = 512, TexHeight = 512; 17 18static GLuint TexObj = 1; 19 20static GLenum IntFormat = GL_RGBA8; 21static GLenum ReadFormat = GL_RGBA; /* for glReadPixels */ 22 23static GLboolean DrawQuad = GL_TRUE; 24 25 26/** 27 * draw teapot image, size TexWidth by TexHeight 28 */ 29static void 30DrawTestImage(void) 31{ 32 GLfloat ar; 33 34 glViewport(0, 0, TexWidth, TexHeight); 35 glScissor(0, 0, TexWidth, TexHeight); 36 glEnable(GL_SCISSOR_TEST); 37 38 glClearColor(0.5, 0.5, 0.5, 0.0); 39 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 40 41 ar = (float) TexWidth / TexHeight; 42 43 glMatrixMode(GL_PROJECTION); 44 glLoadIdentity(); 45 glFrustum(-ar, ar, -1.0, 1.0, 5.0, 25.0); 46 glMatrixMode(GL_MODELVIEW); 47 48 glEnable(GL_LIGHTING); 49 glEnable(GL_LIGHT0); 50 glEnable(GL_DEPTH_TEST); 51 glFrontFace(GL_CW); 52 glPushMatrix(); 53 glRotatef(45, 1, 0, 0); 54 glRotatef(45, 0, 1, 0); 55 glutSolidTeapot(2.3); 56 glPopMatrix(); 57 glFrontFace(GL_CCW); 58 glDisable(GL_DEPTH_TEST); 59 glDisable(GL_LIGHTING); 60 61 glDisable(GL_SCISSOR_TEST); 62 63 glViewport(0, 0, WinWidth, WinHeight); 64 glFinish(); 65} 66 67 68/** 69 * Do glCopyTexSubImage2D call (update texture with framebuffer data) 70 * If doSubRect is true, do the copy in four pieces instead of all at once. 71 */ 72static void 73DoCopyTex(GLboolean doSubRect) 74{ 75 if (doSubRect) { 76 /* copy in four parts */ 77 int w = TexWidth / 2, h = TexHeight / 2; 78 int x0 = 0, y0 = 0; 79 int x1 = w, y1 = h; 80#if 1 81 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x0, y0, x0, y0, w, h); 82 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x1, y0, x1, y0, w, h); 83 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x0, y1, x0, y1, w, h); 84 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x1, y1, x1, y1, w, h); 85#else 86 /* scramble */ 87 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x0, y0, x1, y1, w, h); 88 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x1, y0, x0, y1, w, h); 89 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x0, y1, x1, y0, w, h); 90 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x1, y1, x0, y0, w, h); 91#endif 92 } 93 else { 94 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, TexWidth, TexHeight); 95 } 96} 97 98 99/** 100 * Do glTexSubImage2D (update texture w/ user data) 101 * If doSubRect, do update in four pieces, else all at once. 102 */ 103static void 104SubTex(GLboolean doSubRect, const GLubyte *image) 105{ 106 if (doSubRect) { 107 /* four pieces */ 108 int w = TexWidth / 2, h = TexHeight / 2; 109 int x0 = 0, y0 = 0; 110 int x1 = w, y1 = h; 111 glPixelStorei(GL_UNPACK_ROW_LENGTH, TexWidth); 112 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 113 114 glPixelStorei(GL_UNPACK_SKIP_ROWS, y0); 115 glPixelStorei(GL_UNPACK_SKIP_PIXELS, x0); 116 glTexSubImage2D(GL_TEXTURE_2D, 0, x0, y0, w, h, 117 ReadFormat, GL_UNSIGNED_BYTE, image); 118 119 glPixelStorei(GL_UNPACK_SKIP_ROWS, y0); 120 glPixelStorei(GL_UNPACK_SKIP_PIXELS, x1); 121 glTexSubImage2D(GL_TEXTURE_2D, 0, x1, y0, w, h, 122 ReadFormat, GL_UNSIGNED_BYTE, image); 123 124 glPixelStorei(GL_UNPACK_SKIP_ROWS, y1); 125 glPixelStorei(GL_UNPACK_SKIP_PIXELS, x0); 126 glTexSubImage2D(GL_TEXTURE_2D, 0, x0, y1, w, h, 127 ReadFormat, GL_UNSIGNED_BYTE, image); 128 129 glPixelStorei(GL_UNPACK_SKIP_ROWS, y1); 130 glPixelStorei(GL_UNPACK_SKIP_PIXELS, x1); 131 glTexSubImage2D(GL_TEXTURE_2D, 0, x1, y1, w, h, 132 ReadFormat, GL_UNSIGNED_BYTE, image); 133 } 134 else { 135 /* all at once */ 136 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, TexWidth, TexHeight, 137 ReadFormat, GL_UNSIGNED_BYTE, image); 138 } 139} 140 141 142/** 143 * Measure gl[Copy]TexSubImage rate. 144 * This actually also includes time to render a quad and SwapBuffers. 145 */ 146static void 147RunTest(GLboolean copyTex, GLboolean doSubRect) 148{ 149 double t0, t1; 150 int iters = 0; 151 float copyRate, mbRate; 152 float rot = 0.0; 153 int bpp, r, g, b, a; 154 int w, h; 155 GLubyte *image = NULL; 156 157 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_RED_SIZE, &r); 158 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_GREEN_SIZE, &g); 159 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BLUE_SIZE, &b); 160 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_ALPHA_SIZE, &a); 161 bpp = (r + g + b + a) / 8; 162 163 if (!copyTex) { 164 /* read image from frame buffer */ 165 image = (GLubyte *) malloc(TexWidth * TexHeight * bpp); 166 glPixelStorei(GL_PACK_ALIGNMENT, 1); 167 glReadPixels(0, 0, TexWidth, TexHeight, 168 ReadFormat, GL_UNSIGNED_BYTE, image); 169 } 170 171 glEnable(GL_TEXTURE_2D); 172 glViewport(WinWidth / 2, 0, WinWidth / 2, WinHeight); 173 174 t0 = glutGet(GLUT_ELAPSED_TIME) / 1000.0; 175 176 do { 177 if (copyTex) 178 /* Framebuffer -> Texture */ 179 DoCopyTex(doSubRect); 180 else { 181 /* Main Mem -> Texture */ 182 SubTex(doSubRect, image); 183 } 184 185 /* draw textured quad */ 186 if (DrawQuad) { 187 glPushMatrix(); 188 glRotatef(rot, 0, 0, 1); 189 glTranslatef(1, 0, 0); 190 glBegin(GL_POLYGON); 191 glTexCoord2f(0, 0); glVertex2f(-1, -1); 192 glTexCoord2f(1, 0); glVertex2f( 1, -1); 193 glTexCoord2f(1, 1); glVertex2f( 1, 1); 194 glTexCoord2f(0, 1); glVertex2f(-1, 1); 195 glEnd(); 196 glPopMatrix(); 197 } 198 199 iters++; 200 rot += 2.0; 201 202 t1 = glutGet(GLUT_ELAPSED_TIME) / 1000.0; 203 if (DrawQuad) { 204 glutSwapBuffers(); 205 } 206 } while (t1 - t0 < 5.0); 207 208 glDisable(GL_TEXTURE_2D); 209 if (image) 210 free(image); 211 212 if (doSubRect) { 213 w = TexWidth / 2; 214 h = TexHeight / 2; 215 iters *= 4; 216 } 217 else { 218 w = TexWidth; 219 h = TexHeight; 220 } 221 222 copyRate = iters / (t1 - t0); 223 mbRate = w * h * bpp * copyRate / (1024 * 1024); 224 225 if (copyTex) 226 printf("glCopyTexSubImage: %d x %d, %d Bpp:\n", w, h, bpp); 227 else 228 printf("glTexSubImage: %d x %d, %d Bpp:\n", w, h, bpp); 229 printf(" %d calls in %.2f = %.2f calls/sec, %.2f MB/s\n", 230 iters, t1-t0, copyRate, mbRate); 231} 232 233 234static void 235Draw(void) 236{ 237 glClearColor(0.2, 0.2, 0.8, 0); 238 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 239 240 DrawTestImage(); 241 if (!DrawQuad) { 242 glutSwapBuffers(); 243 } 244 245 RunTest(GL_FALSE, GL_FALSE); 246 RunTest(GL_FALSE, GL_TRUE); 247 RunTest(GL_TRUE, GL_FALSE); 248 RunTest(GL_TRUE, GL_TRUE); 249 250 glutSwapBuffers(); 251 252 printf("exiting\n"); 253 exit(0); 254} 255 256 257static void 258Reshape(int width, int height) 259{ 260 glViewport(0, 0, width, height); 261 glMatrixMode(GL_PROJECTION); 262 glLoadIdentity(); 263 glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0); 264 glMatrixMode(GL_MODELVIEW); 265 glLoadIdentity(); 266 glTranslatef(0.0, 0.0, -15.0); 267} 268 269 270static void 271Key(unsigned char key, int x, int y) 272{ 273 (void) x; 274 (void) y; 275 switch (key) { 276 case 27: 277 exit(0); 278 break; 279 } 280 glutPostRedisplay(); 281} 282 283 284static void 285SpecialKey(int key, int x, int y) 286{ 287 (void) x; 288 (void) y; 289 switch (key) { 290 case GLUT_KEY_UP: 291 break; 292 case GLUT_KEY_DOWN: 293 break; 294 case GLUT_KEY_LEFT: 295 break; 296 case GLUT_KEY_RIGHT: 297 break; 298 } 299 glutPostRedisplay(); 300} 301 302 303static void 304Init(void) 305{ 306 /* create initial, empty teximage */ 307 glBindTexture(GL_TEXTURE_2D, TexObj); 308 glTexImage2D(GL_TEXTURE_2D, 0, IntFormat, TexWidth, TexHeight, 0, 309 GL_RGBA, GL_UNSIGNED_BYTE, NULL); 310 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 311 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 312 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 313} 314 315 316 317static void 318ParseArgs(int argc, char *argv[]) 319{ 320 int i; 321 for (i = 1; i < argc; i++) { 322 if (strcmp(argv[i], "-nodraw") == 0) 323 DrawQuad = GL_FALSE; 324 } 325} 326 327 328int 329main(int argc, char *argv[]) 330{ 331 GLint mode = GLUT_RGB | GLUT_ALPHA | GLUT_DOUBLE | GLUT_DEPTH; 332 glutInit(&argc, argv); 333 334 ParseArgs(argc, argv); 335 336 glutInitWindowPosition(0, 0); 337 glutInitWindowSize(WinWidth, WinHeight); 338 glutInitDisplayMode(mode); 339 glutCreateWindow(argv[0]); 340 glewInit(); 341 glutReshapeFunc(Reshape); 342 glutKeyboardFunc(Key); 343 glutSpecialFunc(SpecialKey); 344 glutDisplayFunc(Draw); 345 346 printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER)); 347 Init(); 348 349 glutMainLoop(); 350 return 0; 351} 352