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