pbo.c revision 32001f49
1/*
2 * GL_EXT_pixel_buffer_object test
3 *
4 * Brian Paul
5 * 11 March 2004
6 */
7
8
9#include <assert.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <math.h>
13#include <GL/glew.h>
14#include "glut_wrap.h"
15
16#include "../util/readtex.c"  /* a hack, I know */
17
18#define IMAGE_FILE DEMOS_DATA_DIR "girl.rgb"
19
20static int ImgWidth, ImgHeight;
21static GLenum ImgFormat;
22static GLubyte *Image = NULL;
23
24static int APosX, APosY;  /* simple drawpixels */
25static int BPosX, BPosY;  /* read/draw pixels */
26static int CPosX, CPosY;  /* copypixels */
27
28static GLboolean DrawFront = GL_FALSE;
29static GLboolean ScaleAndBias = GL_FALSE;
30static GLboolean Benchmark = GL_FALSE;
31
32static GLuint DrawPBO, TempPBO;
33
34
35static GLenum ReadFormat = GL_BGRA;
36static GLenum ReadType = GL_UNSIGNED_INT_8_8_8_8_REV;
37
38
39
40static void
41CheckError(int line)
42{
43   GLenum err = glGetError();
44   if (err) {
45      printf("GL Error 0x%x at line %d\n", (int) err, line);
46   }
47}
48
49
50static void
51Reset( void )
52{
53   APosX = 5;     APosY = 20;
54   BPosX = APosX + ImgWidth + 5;   BPosY = 20;
55   CPosX = BPosX + ImgWidth + 5;   CPosY = 20;
56}
57
58
59static void
60PrintString(const char *s)
61{
62   while (*s) {
63      glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s);
64      s++;
65   }
66}
67
68
69static void
70SetupPixelTransfer(GLboolean invert)
71{
72   if (invert) {
73      glPixelTransferf(GL_RED_SCALE, -1.0);
74      glPixelTransferf(GL_RED_BIAS, 1.0);
75      glPixelTransferf(GL_GREEN_SCALE, -1.0);
76      glPixelTransferf(GL_GREEN_BIAS, 1.0);
77      glPixelTransferf(GL_BLUE_SCALE, -1.0);
78      glPixelTransferf(GL_BLUE_BIAS, 1.0);
79   }
80   else {
81      glPixelTransferf(GL_RED_SCALE, 1.0);
82      glPixelTransferf(GL_RED_BIAS, 0.0);
83      glPixelTransferf(GL_GREEN_SCALE, 1.0);
84      glPixelTransferf(GL_GREEN_BIAS, 0.0);
85      glPixelTransferf(GL_BLUE_SCALE, 1.0);
86      glPixelTransferf(GL_BLUE_BIAS, 0.0);
87   }
88}
89
90
91static void
92Display( void )
93{
94   glClearColor(.3, .3, .3, 1);
95   glClear( GL_COLOR_BUFFER_BIT );
96
97   CheckError(__LINE__);
98
99   /** Unbind UNPACK pixel buffer before calling glBitmap */
100   glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0);
101
102   glRasterPos2i(5, ImgHeight+25);
103   PrintString("f = toggle front/back  s = toggle scale/bias  b = benchmark");
104
105   glRasterPos2i(5, ImgHeight+40);
106   PrintString("GL_EXT_pixel_buffer_object test");
107
108   /* draw original image */
109   glRasterPos2i(APosX, 5);
110   PrintString("Original");
111   glRasterPos2i(APosX, APosY);
112   glEnable(GL_DITHER);
113   SetupPixelTransfer(GL_FALSE);
114   /*** Draw from the DrawPBO */
115   glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, DrawPBO);
116   glDrawPixels(ImgWidth, ImgHeight, ImgFormat, GL_UNSIGNED_BYTE, 0);
117   glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0);
118
119   CheckError(__LINE__);
120
121   /* do readpixels, drawpixels */
122   glRasterPos2i(BPosX, 5);
123   PrintString("Read/DrawPixels");
124   SetupPixelTransfer(ScaleAndBias);
125   /*** read into the Temp PBO */
126   glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, TempPBO);
127   CheckError(__LINE__);
128   if (Benchmark) {
129      GLint reads = 0;
130      GLint endTime;
131      GLint startTime = glutGet(GLUT_ELAPSED_TIME);
132      GLdouble seconds, pixelsPerSecond;
133      printf("Benchmarking...\n");
134      do {
135         glReadPixels(APosX, APosY, ImgWidth, ImgHeight,
136                      ReadFormat, ReadType, 0);
137         reads++;
138         endTime = glutGet(GLUT_ELAPSED_TIME);
139      } while (endTime - startTime < 4000);   /* 4 seconds */
140      seconds = (double) (endTime - startTime) / 1000.0;
141      pixelsPerSecond = reads * ImgWidth * ImgHeight / seconds;
142      printf("Result:  %d reads in %f seconds = %f pixels/sec\n",
143             reads, seconds, pixelsPerSecond);
144      Benchmark = GL_FALSE;
145   }
146   else {
147      glReadPixels(APosX, APosY, ImgWidth, ImgHeight,
148                   ReadFormat, ReadType, 0);
149   }
150   CheckError(__LINE__);
151   glRasterPos2i(BPosX, BPosY);
152   glDisable(GL_DITHER);
153   SetupPixelTransfer(GL_FALSE);
154
155   CheckError(__LINE__);
156
157   /*** draw from the Temp PBO */
158   glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, TempPBO);
159   glDrawPixels(ImgWidth, ImgHeight, ReadFormat, ReadType, 0);
160   glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0);
161
162   CheckError(__LINE__);
163
164   /* do copypixels */
165   glRasterPos2i(CPosX, 5);
166   PrintString("CopyPixels");
167   glRasterPos2i(CPosX, CPosY);
168   glDisable(GL_DITHER);
169   SetupPixelTransfer(ScaleAndBias);
170   glCopyPixels(APosX, APosY, ImgWidth, ImgHeight, GL_COLOR);
171
172   CheckError(__LINE__);
173
174   if (!DrawFront)
175      glutSwapBuffers();
176   else
177      glFinish();
178}
179
180
181static void
182Reshape( int width, int height )
183{
184   glViewport( 0, 0, width, height );
185   glMatrixMode( GL_PROJECTION );
186   glLoadIdentity();
187   glOrtho( 0.0, width, 0.0, height, -1.0, 1.0 );
188   glMatrixMode( GL_MODELVIEW );
189   glLoadIdentity();
190}
191
192
193static void
194Key( unsigned char key, int x, int y )
195{
196   (void) x;
197   (void) y;
198   switch (key) {
199      case 'b':
200         Benchmark = GL_TRUE;
201         break;
202      case 's':
203         ScaleAndBias = !ScaleAndBias;
204         break;
205      case 'f':
206         DrawFront = !DrawFront;
207         if (DrawFront) {
208            glDrawBuffer(GL_FRONT);
209            glReadBuffer(GL_FRONT);
210         }
211         else {
212            glDrawBuffer(GL_BACK);
213            glReadBuffer(GL_BACK);
214         }
215         printf("glDrawBuffer(%s)\n", DrawFront ? "GL_FRONT" : "GL_BACK");
216         break;
217      case 27:
218         exit(0);
219         break;
220   }
221   glutPostRedisplay();
222}
223
224
225static void
226Init(void)
227{
228   printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
229   printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
230
231   if (!glutExtensionSupported("GL_EXT_pixel_buffer_object")) {
232      printf("Sorry, this demo requires GL_EXT_pixel_buffer_object\n");
233      exit(0);
234   }
235
236   Image = LoadRGBImage( IMAGE_FILE, &ImgWidth, &ImgHeight, &ImgFormat );
237   if (!Image) {
238      printf("Couldn't read %s\n", IMAGE_FILE);
239      exit(0);
240   }
241
242   printf("Loaded %d by %d image\n", ImgWidth, ImgHeight );
243
244   if (ImgFormat == GL_RGB) {
245      /* convert to RGBA */
246      int i;
247      GLubyte *image2 = (GLubyte *) malloc(ImgWidth * ImgHeight * 4);
248      printf("Converting RGB image to RGBA\n");
249      for (i = 0; i < ImgWidth * ImgHeight; i++) {
250         image2[i*4+0] = Image[i*3+0];
251         image2[i*4+1] = Image[i*3+1];
252         image2[i*4+2] = Image[i*3+2];
253         image2[i*4+3] = 255;
254      }
255      free(Image);
256      Image = image2;
257      ImgFormat = GL_RGBA;
258   }
259
260   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
261   glPixelStorei(GL_UNPACK_ROW_LENGTH, ImgWidth);
262   glPixelStorei(GL_PACK_ALIGNMENT, 1);
263   glPixelStorei(GL_PACK_ROW_LENGTH, ImgWidth);
264
265   Reset();
266
267   /* put image into DrawPBO */
268   glGenBuffersARB(1, &DrawPBO);
269   glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, DrawPBO);
270   glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_EXT,
271                   ImgWidth * ImgHeight * 4, Image, GL_STATIC_DRAW);
272
273   /* Setup TempPBO - used for glReadPixels & glDrawPixels */
274   glGenBuffersARB(1, &TempPBO);
275   glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, TempPBO);
276   glBufferDataARB(GL_PIXEL_PACK_BUFFER_EXT,
277                   ImgWidth * ImgHeight * 4, NULL, GL_DYNAMIC_COPY);
278
279}
280
281
282int
283main( int argc, char *argv[] )
284{
285   glutInit( &argc, argv );
286   glutInitWindowPosition( 0, 0 );
287   glutInitWindowSize( 750, 250 );
288   glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE );
289   glutCreateWindow(argv[0]);
290   glewInit();
291   Init();
292   glutReshapeFunc( Reshape );
293   glutKeyboardFunc( Key );
294   glutDisplayFunc( Display );
295   glutMainLoop();
296   return 0;
297}
298