b31b36cc12177f8c5f4611917ce0f25fcff3646d
[mesa.git] / progs / tests / pbo.c
1 /*
2 * GL_EXT_pixel_buffer_object test
3 *
4 * Brian Paul
5 * 11 March 2004
6 */
7
8 #define GL_GLEXT_PROTOTYPES
9
10 #include <assert.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <math.h>
14 #include <GL/glut.h>
15
16 #include "../util/readtex.c" /* a hack, I know */
17
18 #define IMAGE_FILE "../images/girl.rgb"
19
20 static int ImgWidth, ImgHeight;
21 static GLenum ImgFormat;
22 static GLubyte *Image = NULL;
23
24 static int APosX, APosY; /* simple drawpixels */
25 static int BPosX, BPosY; /* read/draw pixels */
26 static int CPosX, CPosY; /* copypixels */
27
28 static GLboolean DrawFront = GL_FALSE;
29 static GLboolean ScaleAndBias = GL_FALSE;
30 static GLboolean Benchmark = GL_FALSE;
31
32 static GLuint DrawPBO, TempPBO;
33
34
35 static GLenum ReadFormat = GL_BGRA;
36 static GLenum ReadType = GL_UNSIGNED_INT_8_8_8_8_REV;
37
38
39
40 static void
41 CheckError(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
50 static void
51 Reset( void )
52 {
53 APosX = 5; APosY = 20;
54 BPosX = APosX + ImgWidth + 5; BPosY = 20;
55 CPosX = BPosX + ImgWidth + 5; CPosY = 20;
56 }
57
58
59 static void
60 PrintString(const char *s)
61 {
62 while (*s) {
63 glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s);
64 s++;
65 }
66 }
67
68
69 static void
70 SetupPixelTransfer(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
91 static void
92 Display( 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
181 static void
182 Reshape( 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
193 static void
194 Key( 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
225 static void
226 Init(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
282 int
283 main( 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 Init();
291 glutReshapeFunc( Reshape );
292 glutKeyboardFunc( Key );
293 glutDisplayFunc( Display );
294 glutMainLoop();
295 return 0;
296 }