--- /dev/null
+/*
+ * Measure glCopyPixels speed
+ *
+ * Brian Paul
+ * 26 Jan 2006
+ */
+
+#define GL_GLEXT_PROTOTYPES
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <GL/glut.h>
+
+static GLint WinWidth = 1000, WinHeight = 800;
+static GLint ImgWidth, ImgHeight;
+
+static GLenum Buffer = GL_FRONT;
+static GLenum AlphaTest = GL_FALSE;
+
+
+/**
+ * draw teapot in lower-left corner of window
+ */
+static void
+DrawTestImage(void)
+{
+ GLfloat ar;
+
+ ImgWidth = WinWidth / 3;
+ ImgHeight = WinHeight / 3;
+
+ glViewport(0, 0, ImgWidth, ImgHeight);
+ glScissor(0, 0, ImgWidth, ImgHeight);
+ glEnable(GL_SCISSOR_TEST);
+
+ glClearColor(0.5, 0.5, 0.5, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ ar = (float) WinWidth / WinHeight;
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glFrustum(-ar, ar, -1.0, 1.0, 5.0, 25.0);
+ glMatrixMode(GL_MODELVIEW);
+
+ glEnable(GL_LIGHTING);
+ glEnable(GL_LIGHT0);
+ glEnable(GL_DEPTH_TEST);
+ glFrontFace(GL_CW);
+ glPushMatrix();
+ glRotatef(45, 1, 0, 0);
+ glutSolidTeapot(2.0);
+ glPopMatrix();
+ glFrontFace(GL_CCW);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_LIGHTING);
+
+ glDisable(GL_SCISSOR_TEST);
+
+ glViewport(0, 0, WinWidth, WinHeight);
+ glFinish();
+}
+
+
+static int
+Rand(int max)
+{
+ return ((int) random()) % max;
+}
+
+
+/**
+ * Measure glCopyPixels rate
+ */
+static void
+RunTest(void)
+{
+ double t1, t0 = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
+ int iters = 0;
+ float copyRate, mbRate;
+ int r, g, b, a, bpp;
+
+ if (AlphaTest) {
+ glEnable(GL_ALPHA_TEST);
+ glAlphaFunc(GL_GREATER, 0.0);
+ }
+
+ glGetIntegerv(GL_RED_BITS, &r);
+ glGetIntegerv(GL_GREEN_BITS, &g);
+ glGetIntegerv(GL_BLUE_BITS, &b);
+ glGetIntegerv(GL_ALPHA_BITS, &a);
+ bpp = (r + g + b + a) / 8;
+
+ do {
+ int x, y;
+ x = Rand(WinWidth);
+ y = Rand(WinHeight);
+
+ if (x > ImgWidth || y > ImgHeight) {
+ glWindowPos2iARB(x, y);
+ glCopyPixels(0, 0, ImgWidth, ImgHeight, GL_COLOR);
+ glFinish(); /* XXX OK? */
+
+ iters++;
+
+ t1 = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
+ }
+ } while (t1 - t0 < 5.0);
+
+ glDisable(GL_ALPHA_TEST);
+
+ copyRate = iters / (t1 - t0);
+ mbRate = ImgWidth * ImgHeight * bpp * copyRate / (1024 * 1024);
+
+ printf("Image size: %d x %d, %d Bpp\n", ImgWidth, ImgHeight, bpp);
+ printf("%d copies in %.2f = %.2f copies/sec, %.2f MB/s\n",
+ iters, t1-t0, copyRate, mbRate);
+}
+
+
+static void
+Draw(void)
+{
+ glClearColor(0.0, 0.0, 0.0, 0.0);
+ glClearColor(0.2, 0.2, 0.8, 0);
+ glReadBuffer(Buffer);
+ glDrawBuffer(Buffer);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ DrawTestImage();
+
+ RunTest();
+
+ if (Buffer == GL_FRONT)
+ glFinish();
+ else
+ glutSwapBuffers();
+
+ printf("exiting\n");
+ exit(0);
+}
+
+
+static void
+Reshape(int width, int height)
+{
+ glViewport(0, 0, width, height);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glTranslatef(0.0, 0.0, -15.0);
+}
+
+
+static void
+Key(unsigned char key, int x, int y)
+{
+ (void) x;
+ (void) y;
+ switch (key) {
+ case 27:
+ exit(0);
+ break;
+ }
+ glutPostRedisplay();
+}
+
+
+static void
+SpecialKey(int key, int x, int y)
+{
+ (void) x;
+ (void) y;
+ switch (key) {
+ case GLUT_KEY_UP:
+ break;
+ case GLUT_KEY_DOWN:
+ break;
+ case GLUT_KEY_LEFT:
+ break;
+ case GLUT_KEY_RIGHT:
+ break;
+ }
+ glutPostRedisplay();
+}
+
+
+static void
+ParseArgs(int argc, char *argv[])
+{
+ int i;
+ for (i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-back") == 0)
+ Buffer = GL_BACK;
+ else if (strcmp(argv[i], "-alpha") == 0)
+ AlphaTest = GL_TRUE;
+ }
+}
+
+
+int
+main(int argc, char *argv[])
+{
+ GLint mode = GLUT_RGB | GLUT_ALPHA | GLUT_DOUBLE | GLUT_DEPTH;
+ glutInit(&argc, argv);
+
+ ParseArgs(argc, argv);
+ if (AlphaTest)
+ mode |= GLUT_ALPHA;
+
+ glutInitWindowPosition(0, 0);
+ glutInitWindowSize(WinWidth, WinHeight);
+ glutInitDisplayMode(mode);
+ glutCreateWindow(argv[0]);
+ glutReshapeFunc(Reshape);
+ glutKeyboardFunc(Key);
+ glutSpecialFunc(SpecialKey);
+ glutDisplayFunc(Draw);
+
+ printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER));
+ printf("Draw Buffer: %s\n", (Buffer == GL_BACK) ? "Back" : "Front");
+
+ glutMainLoop();
+ return 0;
+}