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 <string.h> 13#include "glut_wrap.h" 14 15#include "readtex.h" 16 17#define IMAGE_FILE DEMOS_DATA_DIR "girl.rgb" 18 19static int ImgWidth, ImgHeight; 20static int WinWidth, WinHeight; 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; 31static GLboolean Triangle = GL_FALSE; 32static GLubyte *TempImage = NULL; 33 34#define COMBO 1 35#if COMBO == 0 36#define ReadFormat ImgFormat 37#define ReadType GL_UNSIGNED_BYTE 38#elif COMBO == 1 39static GLenum ReadFormat = GL_RGBA; 40static GLenum ReadType = GL_UNSIGNED_BYTE; 41#elif COMBO == 2 42static GLenum ReadFormat = GL_RGB; 43static GLenum ReadType = GL_UNSIGNED_BYTE; 44#elif COMBO == 3 45static GLenum ReadFormat = GL_RGB; 46static GLenum ReadType = GL_UNSIGNED_SHORT_5_6_5; 47#elif COMBO == 4 48static GLenum ReadFormat = GL_RGBA; 49static GLenum ReadType = GL_UNSIGNED_SHORT_1_5_5_5_REV; 50#elif COMBO == 5 51static GLenum ReadFormat = GL_BGRA; 52static GLenum ReadType = GL_UNSIGNED_SHORT_5_5_5_1; 53#elif COMBO == 6 54static GLenum ReadFormat = GL_BGRA; 55static GLenum ReadType = GL_UNSIGNED_SHORT_4_4_4_4_REV; 56#elif COMBO == 7 57static GLenum ReadFormat = GL_RGBA; 58static GLenum ReadType = GL_HALF_FLOAT_ARB; 59#undef GL_OES_read_format 60#endif 61 62 63static void 64Reset( void ) 65{ 66 APosX = 5; APosY = 20; 67 BPosX = APosX + ImgWidth + 5; BPosY = 20; 68 CPosX = BPosX + ImgWidth + 5; CPosY = 20; 69} 70 71 72static void 73PrintString(const char *s) 74{ 75 while (*s) { 76 glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s); 77 s++; 78 } 79} 80 81 82static void 83SetupPixelTransfer(GLboolean invert) 84{ 85 if (invert) { 86 glPixelTransferf(GL_RED_SCALE, -1.0); 87 glPixelTransferf(GL_RED_BIAS, 1.0); 88 glPixelTransferf(GL_GREEN_SCALE, -1.0); 89 glPixelTransferf(GL_GREEN_BIAS, 1.0); 90 glPixelTransferf(GL_BLUE_SCALE, -1.0); 91 glPixelTransferf(GL_BLUE_BIAS, 1.0); 92 } 93 else { 94 glPixelTransferf(GL_RED_SCALE, 1.0); 95 glPixelTransferf(GL_RED_BIAS, 0.0); 96 glPixelTransferf(GL_GREEN_SCALE, 1.0); 97 glPixelTransferf(GL_GREEN_BIAS, 0.0); 98 glPixelTransferf(GL_BLUE_SCALE, 1.0); 99 glPixelTransferf(GL_BLUE_BIAS, 0.0); 100 } 101} 102 103 104/** 105 * Exercise Pixel Pack parameters by reading the image in four pieces. 106 */ 107static void 108ComplexReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, 109 GLenum format, GLenum type, GLvoid *pixels) 110{ 111 const GLsizei width0 = width / 2; 112 const GLsizei width1 = width - width0; 113 const GLsizei height0 = height / 2; 114 const GLsizei height1 = height - height0; 115 116 glPixelStorei(GL_PACK_ROW_LENGTH, width); 117 118 /* lower-left quadrant */ 119 glReadPixels(x, y, width0, height0, format, type, pixels); 120 121 /* lower-right quadrant */ 122 glPixelStorei(GL_PACK_SKIP_PIXELS, width0); 123 glReadPixels(x + width0, y, width1, height0, format, type, pixels); 124 125 /* upper-left quadrant */ 126 glPixelStorei(GL_PACK_SKIP_PIXELS, 0); 127 glPixelStorei(GL_PACK_SKIP_ROWS, height0); 128 glReadPixels(x, y + height0, width0, height1, format, type, pixels); 129 130 /* upper-right quadrant */ 131 glPixelStorei(GL_PACK_SKIP_PIXELS, width0); 132 glPixelStorei(GL_PACK_SKIP_ROWS, height0); 133 glReadPixels(x + width0, y + height0, width1, height1, format, type, pixels); 134 135 /* restore defaults */ 136 glPixelStorei(GL_PACK_SKIP_PIXELS, 0); 137 glPixelStorei(GL_PACK_SKIP_ROWS, 0); 138 glPixelStorei(GL_PACK_ROW_LENGTH, ImgWidth); 139} 140 141 142 143static void 144Display( void ) 145{ 146 glClearColor(.3, .3, .3, 1); 147 glClear( GL_COLOR_BUFFER_BIT ); 148 149 glRasterPos2i(5, ImgHeight+25); 150 PrintString("f = toggle front/back s = toggle scale/bias b = benchmark"); 151 152 /* draw original image */ 153 glRasterPos2i(APosX, 5); 154 PrintString("Original"); 155 if (!Triangle) { 156 glRasterPos2i(APosX, APosY); 157 glEnable(GL_DITHER); 158 SetupPixelTransfer(GL_FALSE); 159 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 160 glDrawPixels(ImgWidth, ImgHeight, ImgFormat, GL_UNSIGNED_BYTE, Image); 161 } 162 else { 163 float z = 0; 164 165 glViewport(APosX, APosY, ImgWidth, ImgHeight); 166 glMatrixMode( GL_PROJECTION ); 167 glLoadIdentity(); 168 glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); 169 glDisable(GL_CULL_FACE); 170 171 /* Red should never be seen 172 */ 173 glBegin(GL_POLYGON); 174 glColor3f(1,0,0); 175 glVertex3f(-2, -2, z); 176 glVertex3f(-2, 2, z); 177 glVertex3f(2, 2, z); 178 glVertex3f(2, -2, z); 179 glEnd(); 180 181 /* Blue background 182 */ 183 glBegin(GL_POLYGON); 184 glColor3f(.5,.5,1); 185 glVertex3f(-1, -1, z); 186 glVertex3f(-1, 1, z); 187 glVertex3f(1, 1, z); 188 glVertex3f(1, -1, z); 189 glEnd(); 190 191 /* Triangle 192 */ 193 glBegin(GL_TRIANGLES); 194 glColor3f(.8,0,0); 195 glVertex3f(-0.9, -0.9, z); 196 glColor3f(0,.9,0); 197 glVertex3f( 0.9, -0.9, z); 198 glColor3f(0,0,.7); 199 glVertex3f( 0.0, 0.9, z); 200 glEnd(); 201 202 glColor3f(1,1,1); 203 204 glViewport( 0, 0, WinWidth, WinHeight ); 205 glMatrixMode( GL_PROJECTION ); 206 glLoadIdentity(); 207 glOrtho( 0.0, WinWidth, 0.0, WinHeight, -1.0, 1.0 ); 208 } 209 210 /* might try alignment=4 here for testing */ 211 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 212 glPixelStorei(GL_PACK_ALIGNMENT, 1); 213 214 /* do readpixels, drawpixels */ 215 glRasterPos2i(BPosX, 5); 216 PrintString("Read/DrawPixels"); 217 SetupPixelTransfer(ScaleAndBias); 218 if (Benchmark) { 219 GLint reads = 0; 220 GLint endTime; 221 GLint startTime = glutGet(GLUT_ELAPSED_TIME); 222 GLdouble seconds, mpixels, mpixelsPerSecond; 223 printf("Benchmarking...\n"); 224 do { 225 glReadPixels(APosX, APosY, ImgWidth, ImgHeight, 226 ReadFormat, ReadType, TempImage); 227 reads++; 228 endTime = glutGet(GLUT_ELAPSED_TIME); 229 } while (endTime - startTime < 4000); /* 4 seconds */ 230 seconds = (double) (endTime - startTime) / 1000.0; 231 mpixels = reads * (ImgWidth * ImgHeight / (1000.0 * 1000.0)); 232 mpixelsPerSecond = mpixels / seconds; 233 printf("Result: %d reads in %f seconds = %f Mpixels/sec\n", 234 reads, seconds, mpixelsPerSecond); 235 Benchmark = GL_FALSE; 236 } 237 else { 238 /* clear the temporary image to white (helpful for debugging */ 239 memset(TempImage, 255, ImgWidth * ImgHeight * 4); 240#if 1 241 glReadPixels(APosX, APosY, ImgWidth, ImgHeight, 242 ReadFormat, ReadType, TempImage); 243 (void) ComplexReadPixels; 244#else 245 /* you might use this when debugging */ 246 ComplexReadPixels(APosX, APosY, ImgWidth, ImgHeight, 247 ReadFormat, ReadType, TempImage); 248#endif 249 } 250 glRasterPos2i(BPosX, BPosY); 251 glDisable(GL_DITHER); 252 SetupPixelTransfer(GL_FALSE); 253 glDrawPixels(ImgWidth, ImgHeight, ReadFormat, ReadType, TempImage); 254 255 /* do copypixels */ 256 glRasterPos2i(CPosX, 5); 257 PrintString("CopyPixels"); 258 glRasterPos2i(CPosX, CPosY); 259 glDisable(GL_DITHER); 260 SetupPixelTransfer(ScaleAndBias); 261 glCopyPixels(APosX, APosY, ImgWidth, ImgHeight, GL_COLOR); 262 263 if (!DrawFront) 264 glutSwapBuffers(); 265 else 266 glFinish(); 267} 268 269 270static void 271Reshape( int width, int height ) 272{ 273 WinWidth = width; 274 WinHeight = height; 275 276 glViewport( 0, 0, width, height ); 277 glMatrixMode( GL_PROJECTION ); 278 glLoadIdentity(); 279 glOrtho( 0.0, width, 0.0, height, -1.0, 1.0 ); 280 glMatrixMode( GL_MODELVIEW ); 281 glLoadIdentity(); 282} 283 284 285static void 286Key( unsigned char key, int x, int y ) 287{ 288 (void) x; 289 (void) y; 290 switch (key) { 291 case 'b': 292 Benchmark = GL_TRUE; 293 break; 294 case 't': 295 Triangle = !Triangle; 296 break; 297 case 's': 298 ScaleAndBias = !ScaleAndBias; 299 break; 300 case 'f': 301 DrawFront = !DrawFront; 302 if (DrawFront) { 303 glDrawBuffer(GL_FRONT); 304 glReadBuffer(GL_FRONT); 305 } 306 else { 307 glDrawBuffer(GL_BACK); 308 glReadBuffer(GL_BACK); 309 } 310 printf("glDrawBuffer(%s)\n", DrawFront ? "GL_FRONT" : "GL_BACK"); 311 break; 312 case 27: 313 exit(0); 314 break; 315 } 316 glutPostRedisplay(); 317} 318 319 320static void 321Init( GLboolean ciMode ) 322{ 323 GLboolean have_read_format = GL_FALSE; 324 325 printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION)); 326 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); 327 328 Image = LoadRGBImage( IMAGE_FILE, &ImgWidth, &ImgHeight, &ImgFormat ); 329 if (!Image) { 330 printf("Couldn't read %s\n", IMAGE_FILE); 331 exit(0); 332 } 333 334 if (ciMode) { 335 /* Convert RGB image to grayscale */ 336 GLubyte *indexImage = (GLubyte *) malloc( ImgWidth * ImgHeight ); 337 GLint i; 338 for (i=0; i<ImgWidth*ImgHeight; i++) { 339 int gray = Image[i*3] + Image[i*3+1] + Image[i*3+2]; 340 indexImage[i] = gray / 3; 341 } 342 free(Image); 343 Image = indexImage; 344 ImgFormat = GL_COLOR_INDEX; 345 346 for (i=0;i<255;i++) { 347 float g = i / 255.0; 348 glutSetColor(i, g, g, g); 349 } 350 } 351 352#ifdef GL_OES_read_format 353 if ( glutExtensionSupported( "GL_OES_read_format" ) ) { 354 glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE_OES, (GLint *) &ReadType); 355 glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES, (GLint *) &ReadFormat); 356 357 have_read_format = GL_TRUE; 358 } 359#endif 360 361 printf( "GL_OES_read_format %ssupported. " 362 "Using type / format = 0x%04x / 0x%04x\n", 363 (have_read_format) ? "" : "not ", 364 ReadType, ReadFormat ); 365 366 printf("Loaded %d by %d image\n", ImgWidth, ImgHeight ); 367 368 glPixelStorei(GL_UNPACK_ROW_LENGTH, ImgWidth); 369 glPixelStorei(GL_PACK_ROW_LENGTH, ImgWidth); 370 371 Reset(); 372 373 /* allocate large TempImage to store and image data type, plus an 374 * extra 1KB in case we're tinkering with pack alignment. 375 */ 376 TempImage = (GLubyte *) malloc(ImgWidth * ImgHeight * 4 * 4 377 + 1000); 378 assert(TempImage); 379} 380 381 382int 383main( int argc, char *argv[] ) 384{ 385 GLboolean ciMode = GL_FALSE; 386 glutInitWindowSize( 750, 250 ); 387 glutInit( &argc, argv ); 388 if (argc > 1 && strcmp(argv[1], "-ci")==0) { 389 ciMode = GL_TRUE; 390 } 391 if (ciMode) 392 glutInitDisplayMode( GLUT_INDEX | GLUT_DOUBLE ); 393 else 394 glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE ); 395 glutCreateWindow(argv[0]); 396 Init(ciMode); 397 glutReshapeFunc( Reshape ); 398 glutKeyboardFunc( Key ); 399 glutDisplayFunc( Display ); 400 glutMainLoop(); 401 return 0; 402} 403