Test glTexSubImage and glCopyTexSubImage rate.
[mesa.git] / progs / tests / subtexrate.c
1 /*
2 * Measure glTexSubImage and glCopyTexSubImage speed
3 *
4 * Brian Paul
5 * 26 Jan 2006
6 */
7
8 #define GL_GLEXT_PROTOTYPES
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <math.h>
13 #include <GL/glut.h>
14
15 static GLint WinWidth = 1024, WinHeight = 512;
16 static GLint TexWidth = 512, TexHeight = 512;
17
18 static GLuint TexObj = 1;
19
20 static GLenum IntFormat = GL_RGBA8;
21 static GLenum ReadFormat = GL_RGBA; /* for glReadPixels */
22
23 static GLboolean DrawQuad = GL_TRUE;
24
25
26 /**
27 * draw teapot image, size TexWidth by TexHeight
28 */
29 static void
30 DrawTestImage(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 */
72 static void
73 DoCopyTex(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 */
103 static void
104 SubTex(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 */
146 static void
147 RunTest(GLboolean copyTex, GLboolean doSubRect)
148 {
149 double t1, t0 = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
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 do {
175 if (copyTex)
176 /* Framebuffer -> Texture */
177 DoCopyTex(doSubRect);
178 else {
179 /* Main Mem -> Texture */
180 SubTex(doSubRect, image);
181 }
182
183 /* draw textured quad */
184 if (DrawQuad) {
185 glPushMatrix();
186 glRotatef(rot, 0, 0, 1);
187 glTranslatef(1, 0, 0);
188 glBegin(GL_POLYGON);
189 glTexCoord2f(0, 0); glVertex2f(-1, -1);
190 glTexCoord2f(1, 0); glVertex2f( 1, -1);
191 glTexCoord2f(1, 1); glVertex2f( 1, 1);
192 glTexCoord2f(0, 1); glVertex2f(-1, 1);
193 glEnd();
194 glPopMatrix();
195 }
196
197 iters++;
198 rot += 2.0;
199
200 t1 = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
201 glutSwapBuffers();
202 } while (t1 - t0 < 5.0);
203
204 glDisable(GL_TEXTURE_2D);
205 if (image)
206 free(image);
207
208 if (doSubRect) {
209 w = TexWidth / 2;
210 h = TexHeight / 2;
211 iters *= 4;
212 }
213 else {
214 w = TexWidth;
215 h = TexHeight;
216 }
217
218 copyRate = iters / (t1 - t0);
219 mbRate = w * h * bpp * copyRate / (1024 * 1024);
220
221 if (copyTex)
222 printf("glCopyTexSubImage: %d x %d, %d Bpp:\n", w, h, bpp);
223 else
224 printf("glTexSubImage: %d x %d, %d Bpp:\n", w, h, bpp);
225 printf(" %d calls in %.2f = %.2f calls/sec, %.2f MB/s\n",
226 iters, t1-t0, copyRate, mbRate);
227 }
228
229
230 static void
231 Draw(void)
232 {
233 glClearColor(0.2, 0.2, 0.8, 0);
234 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
235
236 DrawTestImage();
237
238 RunTest(GL_FALSE, GL_FALSE);
239 RunTest(GL_FALSE, GL_TRUE);
240 RunTest(GL_TRUE, GL_FALSE);
241 RunTest(GL_TRUE, GL_TRUE);
242
243 glutSwapBuffers();
244
245 printf("exiting\n");
246 exit(0);
247 }
248
249
250 static void
251 Reshape(int width, int height)
252 {
253 glViewport(0, 0, width, height);
254 glMatrixMode(GL_PROJECTION);
255 glLoadIdentity();
256 glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
257 glMatrixMode(GL_MODELVIEW);
258 glLoadIdentity();
259 glTranslatef(0.0, 0.0, -15.0);
260 }
261
262
263 static void
264 Key(unsigned char key, int x, int y)
265 {
266 (void) x;
267 (void) y;
268 switch (key) {
269 case 27:
270 exit(0);
271 break;
272 }
273 glutPostRedisplay();
274 }
275
276
277 static void
278 SpecialKey(int key, int x, int y)
279 {
280 (void) x;
281 (void) y;
282 switch (key) {
283 case GLUT_KEY_UP:
284 break;
285 case GLUT_KEY_DOWN:
286 break;
287 case GLUT_KEY_LEFT:
288 break;
289 case GLUT_KEY_RIGHT:
290 break;
291 }
292 glutPostRedisplay();
293 }
294
295
296 static void
297 Init(void)
298 {
299 /* create initial, empty teximage */
300 glBindTexture(GL_TEXTURE_2D, TexObj);
301 glTexImage2D(GL_TEXTURE_2D, 0, IntFormat, TexWidth, TexHeight, 0,
302 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
303 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
304 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
305 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
306 }
307
308
309
310 static void
311 ParseArgs(int argc, char *argv[])
312 {
313 int i;
314 for (i = 1; i < argc; i++) {
315 if (strcmp(argv[i], "-nodraw") == 0)
316 DrawQuad = GL_FALSE;
317 }
318 }
319
320
321 int
322 main(int argc, char *argv[])
323 {
324 GLint mode = GLUT_RGB | GLUT_ALPHA | GLUT_DOUBLE | GLUT_DEPTH;
325 glutInit(&argc, argv);
326
327 ParseArgs(argc, argv);
328
329 glutInitWindowPosition(0, 0);
330 glutInitWindowSize(WinWidth, WinHeight);
331 glutInitDisplayMode(mode);
332 glutCreateWindow(argv[0]);
333 glutReshapeFunc(Reshape);
334 glutKeyboardFunc(Key);
335 glutSpecialFunc(SpecialKey);
336 glutDisplayFunc(Draw);
337
338 printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER));
339 Init();
340
341 glutMainLoop();
342 return 0;
343 }