1/*
2 * Measure glCopyPixels 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 = 1000, WinHeight = 800;
16static GLint ImgWidth, ImgHeight;
17
18static GLenum Buffer = GL_FRONT;
19static GLenum AlphaTest = GL_FALSE;
20static GLboolean UseBlit = GL_FALSE;
21
22
23/**
24 * draw teapot in lower-left corner of window
25 */
26static void
27DrawTestImage(void)
28{
29   GLfloat ar;
30
31   ImgWidth = WinWidth / 3;
32   ImgHeight = WinHeight / 3;
33
34   glViewport(0, 0, ImgWidth, ImgHeight);
35   glScissor(0, 0, ImgWidth, ImgHeight);
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) WinWidth / WinHeight;
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   glutSolidTeapot(2.0);
55   glPopMatrix();
56   glFrontFace(GL_CCW);
57   glDisable(GL_DEPTH_TEST);
58   glDisable(GL_LIGHTING);
59
60   glDisable(GL_SCISSOR_TEST);
61
62   glViewport(0, 0, WinWidth, WinHeight);
63   glFinish();
64}
65
66
67static int
68Rand(int max)
69{
70   return ((int) rand()) % max;
71}
72
73
74static void
75BlitOne(void)
76{
77   int x, y;
78
79   do {
80      x = Rand(WinWidth);
81      y = Rand(WinHeight);
82   } while (x <= ImgWidth && y <= ImgHeight);
83
84#ifdef GL_EXT_framebuffer_blit
85   if (UseBlit)
86   {
87      glBlitFramebufferEXT(0, 0, ImgWidth, ImgHeight,
88                           x, y, x + ImgWidth, y + ImgHeight,
89                           GL_COLOR_BUFFER_BIT, GL_LINEAR);
90   }
91   else
92#endif
93   {
94      glWindowPos2iARB(x, y);
95      glCopyPixels(0, 0, ImgWidth, ImgHeight, GL_COLOR);
96   }
97}
98
99
100/**
101 * Measure glCopyPixels rate
102 */
103static void
104RunTest(void)
105{
106   double t1, t0 = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
107   int iters = 0;
108   float copyRate, mbRate;
109   int r, g, b, a, bpp;
110
111   if (AlphaTest) {
112      glEnable(GL_ALPHA_TEST);
113      glAlphaFunc(GL_GREATER, 0.0);
114   }
115
116   glGetIntegerv(GL_RED_BITS, &r);
117   glGetIntegerv(GL_GREEN_BITS, &g);
118   glGetIntegerv(GL_BLUE_BITS, &b);
119   glGetIntegerv(GL_ALPHA_BITS, &a);
120   bpp = (r + g + b + a) / 8;
121
122   do {
123      BlitOne();
124
125      if (Buffer == GL_FRONT)
126         glFinish(); /* XXX to view progress */
127
128      iters++;
129
130      t1 = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
131   } while (t1 - t0 < 5.0);
132
133   glDisable(GL_ALPHA_TEST);
134
135   copyRate = iters / (t1 - t0);
136   mbRate = ImgWidth * ImgHeight * bpp * copyRate / (1024 * 1024);
137
138   printf("Image size: %d x %d, %d Bpp\n", ImgWidth, ImgHeight, bpp);
139   printf("%d copies in %.2f = %.2f copies/sec, %.2f MB/s\n",
140          iters, t1-t0, copyRate, mbRate);
141}
142
143
144static void
145Draw(void)
146{
147   glClearColor(0.0, 0.0, 0.0, 0.0);
148   glClearColor(0.2, 0.2, 0.8, 0);
149   glReadBuffer(Buffer);
150   glDrawBuffer(Buffer);
151   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
152
153   DrawTestImage();
154
155   RunTest();
156
157   if (Buffer == GL_FRONT)
158      glFinish();
159   else
160      glutSwapBuffers();
161
162#if 1
163   printf("exiting\n");
164   exit(0);
165#endif
166}
167
168
169static void
170Reshape(int width, int height)
171{
172   glViewport(0, 0, width, height);
173   glMatrixMode(GL_PROJECTION);
174   glLoadIdentity();
175   glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
176   glMatrixMode(GL_MODELVIEW);
177   glLoadIdentity();
178   glTranslatef(0.0, 0.0, -15.0);
179}
180
181
182static void
183Key(unsigned char key, int x, int y)
184{
185   (void) x;
186   (void) y;
187   switch (key) {
188   case 'b':
189      BlitOne();
190      break;
191   case 27:
192      exit(0);
193      break;
194   }
195   glutPostRedisplay();
196}
197
198
199static void
200SpecialKey(int key, int x, int y)
201{
202   (void) x;
203   (void) y;
204   switch (key) {
205      case GLUT_KEY_UP:
206         break;
207      case GLUT_KEY_DOWN:
208         break;
209      case GLUT_KEY_LEFT:
210         break;
211      case GLUT_KEY_RIGHT:
212         break;
213   }
214   glutPostRedisplay();
215}
216
217
218static void
219ParseArgs(int argc, char *argv[])
220{
221   int i;
222   for (i = 1; i < argc; i++) {
223      if (strcmp(argv[i], "-back") == 0)
224         Buffer = GL_BACK;
225      else if (strcmp(argv[i], "-alpha") == 0)
226         AlphaTest = GL_TRUE;
227      else if (strcmp(argv[i], "-blit") == 0)
228         UseBlit = GL_TRUE;
229   }
230}
231
232
233static void
234Init(void)
235{
236   if (glutExtensionSupported("GL_EXT_framebuffer_blit")) {
237   }
238   else if (UseBlit) {
239      printf("Warning: GL_EXT_framebuffer_blit not supported.\n");
240      UseBlit = GL_FALSE;
241   }
242}
243
244
245int
246main(int argc, char *argv[])
247{
248   GLint mode = GLUT_RGB | GLUT_ALPHA | GLUT_DOUBLE | GLUT_DEPTH;
249   glutInit(&argc, argv);
250
251   ParseArgs(argc, argv);
252   if (AlphaTest)
253      mode |= GLUT_ALPHA;
254
255   glutInitWindowPosition(0, 0);
256   glutInitWindowSize(WinWidth, WinHeight);
257   glutInitDisplayMode(mode);
258   glutCreateWindow(argv[0]);
259   glewInit();
260   glutReshapeFunc(Reshape);
261   glutKeyboardFunc(Key);
262   glutSpecialFunc(SpecialKey);
263   glutDisplayFunc(Draw);
264
265   printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER));
266   printf("Draw Buffer: %s\n", (Buffer == GL_BACK) ? "Back" : "Front");
267   Init();
268
269   printf("Mode: %s\n", (UseBlit ? "glBlitFramebuffer" : "glCopyPixels"));
270   printf("Alpha Test: %s\n", (AlphaTest ? "yes" : "no"));
271
272   glutMainLoop();
273   return 0;
274}
275