132001f49Smrg/*
232001f49Smrg * Test glReadPixels speed
332001f49Smrg * Brian Paul
432001f49Smrg * 9 April 2004
532001f49Smrg *
632001f49Smrg * Compile:
732001f49Smrg * gcc readrate.c -L/usr/X11R6/lib -lglut -lGLU -lGL -lX11 -o readrate
832001f49Smrg */
932001f49Smrg
1032001f49Smrg#include <assert.h>
1132001f49Smrg#include <stdio.h>
1232001f49Smrg#include <stdlib.h>
1332001f49Smrg#include <math.h>
1432001f49Smrg#include <GL/glew.h>
1532001f49Smrg#include "glut_wrap.h"
1632001f49Smrg
1732001f49Smrg/* Hack, to test drawing instead of reading */
1832001f49Smrg#define DRAW 0
1932001f49Smrg
2032001f49Smrg#define MAX_WIDTH 1280
2132001f49Smrg#define MAX_HEIGHT 1024
2232001f49Smrg
2332001f49Smrg#define NUM_WIDTHS 4
2432001f49Smrg#define NUM_HEIGHTS 4
2532001f49Smrgstatic const GLint Widths[] = {256, 512, 1024, 1280};
2632001f49Smrgstatic const GLint Heights[] = {4, 32, 256, 512, 768, 1024};
2732001f49Smrgstatic int WidthIndex = 1, HeightIndex = 3;
2832001f49Smrgstatic GLubyte *Buffer = NULL;
2932001f49Smrgstatic GLboolean Benchmark = GL_TRUE;
3032001f49Smrg
3132001f49Smrg#define NUM_PBO 2
3232001f49Smrg
3332001f49Smrgstatic GLuint PBObjects[4];
3432001f49Smrg
3532001f49Smrgstatic GLboolean HavePBO = GL_FALSE;
3632001f49Smrg
3732001f49Smrg
3832001f49Smrgstruct format_type {
3932001f49Smrg   const char *Name;
4032001f49Smrg   GLuint Bytes;
4132001f49Smrg   GLenum Format;
4232001f49Smrg   GLenum Type;
4332001f49Smrg};
4432001f49Smrg
4532001f49Smrgstatic struct format_type Formats[] = {
4632001f49Smrg   { "GL_RGB, GLubyte", 3, GL_RGB, GL_UNSIGNED_BYTE },
4732001f49Smrg   { "GL_BGR, GLubyte", 3, GL_BGR, GL_UNSIGNED_BYTE },
4832001f49Smrg   { "GL_RGBA, GLubyte", 4, GL_RGBA, GL_UNSIGNED_BYTE },
4932001f49Smrg   { "GL_BGRA, GLubyte", 4, GL_BGRA, GL_UNSIGNED_BYTE },
5032001f49Smrg   { "GL_ABGR, GLubyte", 4, GL_ABGR_EXT, GL_UNSIGNED_BYTE },
5132001f49Smrg   { "GL_RGBA, GLuint_8_8_8_8", 4, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8 },
5232001f49Smrg   { "GL_BGRA, GLuint_8_8_8_8", 4, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8 },
5332001f49Smrg   { "GL_BGRA, GLuint_8_8_8_8_rev", 4, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV },
5432001f49Smrg#ifdef GL_EXT_packed_depth_stencil
5532001f49Smrg   { "GL_DEPTH_STENCIL_EXT, GLuint24+8", 4, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT },
5632001f49Smrg#endif
5732001f49Smrg   { "GL_DEPTH_COMPONENT, GLfloat", 4, GL_DEPTH_COMPONENT, GL_FLOAT },
5832001f49Smrg   { "GL_DEPTH_COMPONENT, GLuint", 4, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT }
5932001f49Smrg};
6032001f49Smrg
6132001f49Smrg#define NUM_FORMATS (sizeof(Formats) / sizeof(struct format_type))
6232001f49Smrg
6332001f49Smrg
6432001f49Smrgstatic void
6532001f49SmrgPrintString(const char *s)
6632001f49Smrg{
6732001f49Smrg   while (*s) {
6832001f49Smrg      glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s);
6932001f49Smrg      s++;
7032001f49Smrg   }
7132001f49Smrg}
7232001f49Smrg
7332001f49Smrg
7432001f49Smrgstatic void
7532001f49SmrgMeasureFormat(struct format_type *fmt, GLint width, GLint height, GLuint pbo)
7632001f49Smrg{
7732001f49Smrg   double t0 = glutGet(GLUT_ELAPSED_TIME) * 0.001;
7832001f49Smrg   double t1;
7932001f49Smrg   int j;
8032001f49Smrg
8132001f49Smrg   for (j = 0; ; j++) {
8232001f49Smrg
8332001f49Smrg      glBegin(GL_POINTS);
8432001f49Smrg      glVertex2f(1,1);
8532001f49Smrg      glEnd();
8632001f49Smrg
8732001f49Smrg#if DRAW
8832001f49Smrg      glWindowPos2iARB(0,0);
8932001f49Smrg      glDrawPixels(width, height,
9032001f49Smrg                   fmt->Format, fmt->Type, Buffer);
9132001f49Smrg      glFinish();
9232001f49Smrg#else
9332001f49Smrg      if (pbo) {
9432001f49Smrg         glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, PBObjects[j % NUM_PBO]);
9532001f49Smrg         glReadPixels(0, 0, width, height,
9632001f49Smrg                      fmt->Format, fmt->Type, 0);
9732001f49Smrg      }
9832001f49Smrg      else {
9932001f49Smrg         glReadPixels(0, 0, width, height,
10032001f49Smrg                      fmt->Format, fmt->Type, Buffer);
10132001f49Smrg      }
10232001f49Smrg#endif
10332001f49Smrg
10432001f49Smrg      t1 = glutGet(GLUT_ELAPSED_TIME) * 0.001;
10532001f49Smrg      if (t1 - t0 > 2.0) {
10632001f49Smrg         GLdouble rate = width * height / (1024.0 * 1024.0) * j / (t1 - t0);
10732001f49Smrg#if DRAW
10832001f49Smrg         printf("%-32s  %.2f draws/sec %.2f MPixels/sec  %.2f MBytes/sec\n",
10932001f49Smrg                fmt->Name, j / (t1-t0), rate, rate * fmt->Bytes);
11032001f49Smrg#else
11132001f49Smrg         printf("%-32s  %.2f reads/sec %.2f MPixels/sec  %.2f MBytes/sec\n",
11232001f49Smrg                fmt->Name, j / (t1-t0), rate, rate * fmt->Bytes);
11332001f49Smrg#endif
11432001f49Smrg         break;
11532001f49Smrg      }
11632001f49Smrg
11732001f49Smrg      if (j == 0) {
11832001f49Smrg         /* check for error */
11932001f49Smrg         GLenum err = glGetError();
12032001f49Smrg         if (err) {
12132001f49Smrg            printf("GL Error 0x%x for %s\n", err, fmt->Name);
12232001f49Smrg            return;
12332001f49Smrg         }
12432001f49Smrg      }
12532001f49Smrg   }
12632001f49Smrg}
12732001f49Smrg
12832001f49Smrg
12932001f49Smrg
13032001f49Smrgstatic void
13132001f49SmrgDraw(void)
13232001f49Smrg{
13332001f49Smrg   char str[1000];
13432001f49Smrg   int width = Widths[WidthIndex];
13532001f49Smrg   int height = Heights[HeightIndex];
13632001f49Smrg   int y = MAX_HEIGHT - 50;
13732001f49Smrg
13832001f49Smrg   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
13932001f49Smrg
14032001f49Smrg   glWindowPos2iARB(10, y);
14132001f49Smrg   sprintf(str, "ReadPixels size: %d x %d", width, height);
14232001f49Smrg   PrintString(str);
14332001f49Smrg   y -= 14;
14432001f49Smrg
14532001f49Smrg   glWindowPos2iARB(10, y);
14632001f49Smrg   PrintString("Press up/down/left/right to change image size.");
14732001f49Smrg   y -= 14;
14832001f49Smrg
14932001f49Smrg   glWindowPos2iARB(10, y);
15032001f49Smrg   PrintString("Press 'b' to run benchmark test.");
15132001f49Smrg   y -= 14;
15232001f49Smrg
15332001f49Smrg   if (Benchmark) {
15432001f49Smrg      glWindowPos2iARB(10, y);
15532001f49Smrg      PrintString("Testing...");
15632001f49Smrg   }
15732001f49Smrg
15832001f49Smrg   glutSwapBuffers();
15932001f49Smrg
16032001f49Smrg   if (Benchmark) {
16132001f49Smrg      GLuint i, pbo;
16232001f49Smrg#if DRAW
16332001f49Smrg      printf("Draw size: Width=%d Height=%d\n", width, height);
16432001f49Smrg#else
16532001f49Smrg      printf("Read size: Width=%d Height=%d\n", width, height);
16632001f49Smrg#endif
16732001f49Smrg      for (pbo = 0; pbo <= HavePBO; pbo++) {
16832001f49Smrg         printf("Pixel Buffer Object: %d\n", pbo);
16932001f49Smrg
17032001f49Smrg         if (pbo == 0) {
17132001f49Smrg            glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, 0);
17232001f49Smrg         }
17332001f49Smrg
17432001f49Smrg         for (i = 0; i < NUM_FORMATS; i++) {
17532001f49Smrg            MeasureFormat(Formats + i, width, height, pbo);
17632001f49Smrg         }
17732001f49Smrg      }
17832001f49Smrg
17932001f49Smrg      Benchmark = GL_FALSE;
18032001f49Smrg
18132001f49Smrg      /* redraw window text */
18232001f49Smrg      glutPostRedisplay();
18332001f49Smrg   }
18432001f49Smrg
18532001f49Smrg}
18632001f49Smrg
18732001f49Smrg
18832001f49Smrgstatic void
18932001f49SmrgReshape(int width, int height)
19032001f49Smrg{
19132001f49Smrg   glViewport(0, 0, width, height);
19232001f49Smrg   glMatrixMode(GL_PROJECTION);
19332001f49Smrg   glLoadIdentity();
19432001f49Smrg   glOrtho(-1, 1, -1, 1, -1, 1);
19532001f49Smrg   glMatrixMode(GL_MODELVIEW);
19632001f49Smrg   glLoadIdentity();
19732001f49Smrg}
19832001f49Smrg
19932001f49Smrg
20032001f49Smrgstatic void
20132001f49SmrgKey(unsigned char key, int x, int y)
20232001f49Smrg{
20332001f49Smrg   (void) x;
20432001f49Smrg   (void) y;
20532001f49Smrg   switch (key) {
20632001f49Smrg      case 'b':
20732001f49Smrg         Benchmark = 1;
20832001f49Smrg         break;
20932001f49Smrg      case 27:
21032001f49Smrg         exit(0);
21132001f49Smrg         break;
21232001f49Smrg   }
21332001f49Smrg   glutPostRedisplay();
21432001f49Smrg}
21532001f49Smrg
21632001f49Smrg
21732001f49Smrgstatic void
21832001f49SmrgSpecialKey(int key, int x, int y)
21932001f49Smrg{
22032001f49Smrg   (void) x;
22132001f49Smrg   (void) y;
22232001f49Smrg   switch (key) {
22332001f49Smrg      case GLUT_KEY_UP:
22432001f49Smrg         if (HeightIndex + 1 < NUM_WIDTHS)
22532001f49Smrg            HeightIndex++;
22632001f49Smrg         break;
22732001f49Smrg      case GLUT_KEY_DOWN:
22832001f49Smrg         if (HeightIndex > 0)
22932001f49Smrg            HeightIndex--;
23032001f49Smrg         break;
23132001f49Smrg      case GLUT_KEY_LEFT:
23232001f49Smrg         if (WidthIndex > 0)
23332001f49Smrg            WidthIndex--;
23432001f49Smrg         break;
23532001f49Smrg      case GLUT_KEY_RIGHT:
23632001f49Smrg         if (WidthIndex + 1 < NUM_HEIGHTS)
23732001f49Smrg            WidthIndex++;
23832001f49Smrg         break;
23932001f49Smrg   }
24032001f49Smrg   glutPostRedisplay();
24132001f49Smrg}
24232001f49Smrg
24332001f49Smrg
24432001f49Smrgstatic void
24532001f49SmrgInit(void)
24632001f49Smrg{
24732001f49Smrg   Buffer = malloc(MAX_WIDTH * MAX_HEIGHT * 4);
24832001f49Smrg   assert(Buffer);
24932001f49Smrg#if DRAW
25032001f49Smrg   printf("glDrawPixels test report:\n");
25132001f49Smrg#else
25232001f49Smrg   printf("glReadPixels test report:\n");
25332001f49Smrg#endif
25432001f49Smrg   printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER));
25532001f49Smrg   printf("GL_VERSION: %s\n", (char *) glGetString(GL_VERSION));
25632001f49Smrg
25732001f49Smrg   if (glutExtensionSupported("GL_ARB_pixel_buffer_object")) {
25832001f49Smrg      int i;
25932001f49Smrg      HavePBO = 1;
26032001f49Smrg      glGenBuffersARB(NUM_PBO, PBObjects);
26132001f49Smrg      for (i = 0; i < NUM_PBO; i++) {
26232001f49Smrg         glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, PBObjects[i]);
26332001f49Smrg         glBufferDataARB(GL_PIXEL_PACK_BUFFER_EXT,
26432001f49Smrg                         MAX_WIDTH * MAX_HEIGHT * 4, NULL, GL_STREAM_READ);
26532001f49Smrg      }
26632001f49Smrg   }
26732001f49Smrg}
26832001f49Smrg
26932001f49Smrg
27032001f49Smrgint
27132001f49Smrgmain(int argc, char *argv[])
27232001f49Smrg{
27332001f49Smrg   glutInit(&argc, argv);
27432001f49Smrg   glutInitWindowPosition(0, 0);
27532001f49Smrg   glutInitWindowSize(MAX_WIDTH, MAX_HEIGHT);
27632001f49Smrg   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_STENCIL);
27732001f49Smrg   glutCreateWindow(argv[0]);
27832001f49Smrg   glewInit();
27932001f49Smrg   glutReshapeFunc(Reshape);
28032001f49Smrg   glutKeyboardFunc(Key);
28132001f49Smrg   glutSpecialFunc(SpecialKey);
28232001f49Smrg   glutDisplayFunc(Draw);
28332001f49Smrg   Init();
28432001f49Smrg   glutMainLoop();
28532001f49Smrg   return 0;
28632001f49Smrg}
287