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