/* * glReadPixels and glCopyPixels test * * Brian Paul March 1, 2000 This file is in the public domain. */ #include #include #include #include #include #include #include "readtex.h" #define IMAGE_FILE "../images/girl.rgb" static int ImgWidth, ImgHeight; static int WinWidth, WinHeight; static GLenum ImgFormat; static GLubyte *Image = NULL; static int APosX, APosY; /* simple drawpixels */ static int BPosX, BPosY; /* read/draw pixels */ static int CPosX, CPosY; /* copypixels */ static GLboolean DrawFront = GL_FALSE; static GLboolean ScaleAndBias = GL_FALSE; static GLboolean Benchmark = GL_FALSE; static GLboolean Triangle = GL_FALSE; static GLubyte *TempImage = NULL; #define COMBO 1 #if COMBO == 0 #define ReadFormat ImgFormat #define ReadType GL_UNSIGNED_BYTE #elif COMBO == 1 static GLenum ReadFormat = GL_RGBA; static GLenum ReadType = GL_UNSIGNED_BYTE; #elif COMBO == 2 static GLenum ReadFormat = GL_RGB; static GLenum ReadType = GL_UNSIGNED_BYTE; #elif COMBO == 3 static GLenum ReadFormat = GL_RGB; static GLenum ReadType = GL_UNSIGNED_SHORT_5_6_5; #elif COMBO == 4 static GLenum ReadFormat = GL_RGBA; static GLenum ReadType = GL_UNSIGNED_SHORT_1_5_5_5_REV; #elif COMBO == 5 static GLenum ReadFormat = GL_BGRA; static GLenum ReadType = GL_UNSIGNED_SHORT_5_5_5_1; #elif COMBO == 6 static GLenum ReadFormat = GL_BGRA; static GLenum ReadType = GL_UNSIGNED_SHORT_4_4_4_4_REV; #elif COMBO == 7 static GLenum ReadFormat = GL_RGBA; static GLenum ReadType = GL_HALF_FLOAT_ARB; #undef GL_OES_read_format #endif static void Reset( void ) { APosX = 5; APosY = 20; BPosX = APosX + ImgWidth + 5; BPosY = 20; CPosX = BPosX + ImgWidth + 5; CPosY = 20; } static void PrintString(const char *s) { while (*s) { glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s); s++; } } static void SetupPixelTransfer(GLboolean invert) { if (invert) { glPixelTransferf(GL_RED_SCALE, -1.0); glPixelTransferf(GL_RED_BIAS, 1.0); glPixelTransferf(GL_GREEN_SCALE, -1.0); glPixelTransferf(GL_GREEN_BIAS, 1.0); glPixelTransferf(GL_BLUE_SCALE, -1.0); glPixelTransferf(GL_BLUE_BIAS, 1.0); } else { glPixelTransferf(GL_RED_SCALE, 1.0); glPixelTransferf(GL_RED_BIAS, 0.0); glPixelTransferf(GL_GREEN_SCALE, 1.0); glPixelTransferf(GL_GREEN_BIAS, 0.0); glPixelTransferf(GL_BLUE_SCALE, 1.0); glPixelTransferf(GL_BLUE_BIAS, 0.0); } } /** * Exercise Pixel Pack parameters by reading the image in four pieces. */ static void ComplexReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels) { const GLsizei width0 = width / 2; const GLsizei width1 = width - width0; const GLsizei height0 = height / 2; const GLsizei height1 = height - height0; glPixelStorei(GL_PACK_ROW_LENGTH, width); /* lower-left quadrant */ glReadPixels(x, y, width0, height0, format, type, pixels); /* lower-right quadrant */ glPixelStorei(GL_PACK_SKIP_PIXELS, width0); glReadPixels(x + width0, y, width1, height0, format, type, pixels); /* upper-left quadrant */ glPixelStorei(GL_PACK_SKIP_PIXELS, 0); glPixelStorei(GL_PACK_SKIP_ROWS, height0); glReadPixels(x, y + height0, width0, height1, format, type, pixels); /* upper-right quadrant */ glPixelStorei(GL_PACK_SKIP_PIXELS, width0); glPixelStorei(GL_PACK_SKIP_ROWS, height0); glReadPixels(x + width0, y + height0, width1, height1, format, type, pixels); /* restore defaults */ glPixelStorei(GL_PACK_SKIP_PIXELS, 0); glPixelStorei(GL_PACK_SKIP_ROWS, 0); glPixelStorei(GL_PACK_ROW_LENGTH, ImgWidth); } static void Display( void ) { glClearColor(.3, .3, .3, 1); glClear( GL_COLOR_BUFFER_BIT ); glRasterPos2i(5, ImgHeight+25); PrintString("f = toggle front/back s = toggle scale/bias b = benchmark"); /* draw original image */ glRasterPos2i(APosX, 5); PrintString("Original"); if (!Triangle) { glRasterPos2i(APosX, APosY); glEnable(GL_DITHER); SetupPixelTransfer(GL_FALSE); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glDrawPixels(ImgWidth, ImgHeight, ImgFormat, GL_UNSIGNED_BYTE, Image); } else { float z = 0; glViewport(APosX, APosY, ImgWidth, ImgHeight); glMatrixMode( GL_PROJECTION ); glLoadIdentity(); glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); glDisable(GL_CULL_FACE); /* Red should never be seen */ glBegin(GL_POLYGON); glColor3f(1,0,0); glVertex3f(-2, -2, z); glVertex3f(-2, 2, z); glVertex3f(2, 2, z); glVertex3f(2, -2, z); glEnd(); /* Blue background */ glBegin(GL_POLYGON); glColor3f(.5,.5,1); glVertex3f(-1, -1, z); glVertex3f(-1, 1, z); glVertex3f(1, 1, z); glVertex3f(1, -1, z); glEnd(); /* Triangle */ glBegin(GL_TRIANGLES); glColor3f(.8,0,0); glVertex3f(-0.9, -0.9, z); glColor3f(0,.9,0); glVertex3f( 0.9, -0.9, z); glColor3f(0,0,.7); glVertex3f( 0.0, 0.9, z); glEnd(); glColor3f(1,1,1); glViewport( 0, 0, WinWidth, WinHeight ); glMatrixMode( GL_PROJECTION ); glLoadIdentity(); glOrtho( 0.0, WinWidth, 0.0, WinHeight, -1.0, 1.0 ); } /* might try alignment=4 here for testing */ glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_PACK_ALIGNMENT, 1); /* do readpixels, drawpixels */ glRasterPos2i(BPosX, 5); PrintString("Read/DrawPixels"); SetupPixelTransfer(ScaleAndBias); if (Benchmark) { GLint reads = 0; GLint endTime; GLint startTime = glutGet(GLUT_ELAPSED_TIME); GLdouble seconds, mpixels, mpixelsPerSecond; printf("Benchmarking...\n"); do { glReadPixels(APosX, APosY, ImgWidth, ImgHeight, ReadFormat, ReadType, TempImage); reads++; endTime = glutGet(GLUT_ELAPSED_TIME); } while (endTime - startTime < 4000); /* 4 seconds */ seconds = (double) (endTime - startTime) / 1000.0; mpixels = reads * (ImgWidth * ImgHeight / (1000.0 * 1000.0)); mpixelsPerSecond = mpixels / seconds; printf("Result: %d reads in %f seconds = %f Mpixels/sec\n", reads, seconds, mpixelsPerSecond); Benchmark = GL_FALSE; } else { /* clear the temporary image to white (helpful for debugging */ memset(TempImage, 255, ImgWidth * ImgHeight * 4); #if 1 glReadPixels(APosX, APosY, ImgWidth, ImgHeight, ReadFormat, ReadType, TempImage); (void) ComplexReadPixels; #else /* you might use this when debugging */ ComplexReadPixels(APosX, APosY, ImgWidth, ImgHeight, ReadFormat, ReadType, TempImage); #endif } glRasterPos2i(BPosX, BPosY); glDisable(GL_DITHER); SetupPixelTransfer(GL_FALSE); glDrawPixels(ImgWidth, ImgHeight, ReadFormat, ReadType, TempImage); /* do copypixels */ glRasterPos2i(CPosX, 5); PrintString("CopyPixels"); glRasterPos2i(CPosX, CPosY); glDisable(GL_DITHER); SetupPixelTransfer(ScaleAndBias); glCopyPixels(APosX, APosY, ImgWidth, ImgHeight, GL_COLOR); if (!DrawFront) glutSwapBuffers(); else glFinish(); } static void Reshape( int width, int height ) { WinWidth = width; WinHeight = height; glViewport( 0, 0, width, height ); glMatrixMode( GL_PROJECTION ); glLoadIdentity(); glOrtho( 0.0, width, 0.0, height, -1.0, 1.0 ); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); } static void Key( unsigned char key, int x, int y ) { (void) x; (void) y; switch (key) { case 'b': Benchmark = GL_TRUE; break; case 't': Triangle = !Triangle; break; case 's': ScaleAndBias = !ScaleAndBias; break; case 'f': DrawFront = !DrawFront; if (DrawFront) { glDrawBuffer(GL_FRONT); glReadBuffer(GL_FRONT); } else { glDrawBuffer(GL_BACK); glReadBuffer(GL_BACK); } printf("glDrawBuffer(%s)\n", DrawFront ? "GL_FRONT" : "GL_BACK"); break; case 27: exit(0); break; } glutPostRedisplay(); } static void Init( GLboolean ciMode ) { GLboolean have_read_format = GL_FALSE; printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION)); printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); Image = LoadRGBImage( IMAGE_FILE, &ImgWidth, &ImgHeight, &ImgFormat ); if (!Image) { printf("Couldn't read %s\n", IMAGE_FILE); exit(0); } if (ciMode) { /* Convert RGB image to grayscale */ GLubyte *indexImage = (GLubyte *) malloc( ImgWidth * ImgHeight ); GLint i; for (i=0; i 1 && strcmp(argv[1], "-ci")==0) { ciMode = GL_TRUE; } if (ciMode) glutInitDisplayMode( GLUT_INDEX | GLUT_DOUBLE ); else glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE ); glutCreateWindow(argv[0]); Init(ciMode); glutReshapeFunc( Reshape ); glutKeyboardFunc( Key ); glutDisplayFunc( Display ); glutMainLoop(); return 0; }