Merge branch '7.8'
[mesa.git] / progs / tests / subtexrate.c
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 <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 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
234 static void
235 Draw(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
257 static void
258 Reshape(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
270 static void
271 Key(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
284 static void
285 SpecialKey(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
303 static void
304 Init(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
317 static void
318 ParseArgs(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
328 int
329 main(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 }