132001f49Smrg 232001f49Smrg/* 332001f49Smrg * glReadPixels and glCopyPixels test 432001f49Smrg * 532001f49Smrg * Brian Paul March 1, 2000 This file is in the public domain. 632001f49Smrg */ 732001f49Smrg 832001f49Smrg#include <assert.h> 932001f49Smrg#include <stdio.h> 1032001f49Smrg#include <stdlib.h> 1132001f49Smrg#include <math.h> 1232001f49Smrg#include <string.h> 1332001f49Smrg#include "glut_wrap.h" 1432001f49Smrg 1532001f49Smrg#include "readtex.h" 1632001f49Smrg 1732001f49Smrg#define IMAGE_FILE DEMOS_DATA_DIR "girl.rgb" 1832001f49Smrg 1932001f49Smrgstatic int ImgWidth, ImgHeight; 2032001f49Smrgstatic int WinWidth, WinHeight; 2132001f49Smrgstatic GLenum ImgFormat; 2232001f49Smrgstatic GLubyte *Image = NULL; 2332001f49Smrg 2432001f49Smrgstatic int APosX, APosY; /* simple drawpixels */ 2532001f49Smrgstatic int BPosX, BPosY; /* read/draw pixels */ 2632001f49Smrgstatic int CPosX, CPosY; /* copypixels */ 2732001f49Smrg 2832001f49Smrgstatic GLboolean DrawFront = GL_FALSE; 2932001f49Smrgstatic GLboolean ScaleAndBias = GL_FALSE; 3032001f49Smrgstatic GLboolean Benchmark = GL_FALSE; 3132001f49Smrgstatic GLboolean Triangle = GL_FALSE; 3232001f49Smrgstatic GLubyte *TempImage = NULL; 3332001f49Smrg 3432001f49Smrg#define COMBO 1 3532001f49Smrg#if COMBO == 0 3632001f49Smrg#define ReadFormat ImgFormat 3732001f49Smrg#define ReadType GL_UNSIGNED_BYTE 3832001f49Smrg#elif COMBO == 1 3932001f49Smrgstatic GLenum ReadFormat = GL_RGBA; 4032001f49Smrgstatic GLenum ReadType = GL_UNSIGNED_BYTE; 4132001f49Smrg#elif COMBO == 2 4232001f49Smrgstatic GLenum ReadFormat = GL_RGB; 4332001f49Smrgstatic GLenum ReadType = GL_UNSIGNED_BYTE; 4432001f49Smrg#elif COMBO == 3 4532001f49Smrgstatic GLenum ReadFormat = GL_RGB; 4632001f49Smrgstatic GLenum ReadType = GL_UNSIGNED_SHORT_5_6_5; 4732001f49Smrg#elif COMBO == 4 4832001f49Smrgstatic GLenum ReadFormat = GL_RGBA; 4932001f49Smrgstatic GLenum ReadType = GL_UNSIGNED_SHORT_1_5_5_5_REV; 5032001f49Smrg#elif COMBO == 5 5132001f49Smrgstatic GLenum ReadFormat = GL_BGRA; 5232001f49Smrgstatic GLenum ReadType = GL_UNSIGNED_SHORT_5_5_5_1; 5332001f49Smrg#elif COMBO == 6 5432001f49Smrgstatic GLenum ReadFormat = GL_BGRA; 5532001f49Smrgstatic GLenum ReadType = GL_UNSIGNED_SHORT_4_4_4_4_REV; 5632001f49Smrg#elif COMBO == 7 5732001f49Smrgstatic GLenum ReadFormat = GL_RGBA; 5832001f49Smrgstatic GLenum ReadType = GL_HALF_FLOAT_ARB; 5932001f49Smrg#undef GL_OES_read_format 6032001f49Smrg#endif 6132001f49Smrg 6232001f49Smrg 6332001f49Smrgstatic void 6432001f49SmrgReset( void ) 6532001f49Smrg{ 6632001f49Smrg APosX = 5; APosY = 20; 6732001f49Smrg BPosX = APosX + ImgWidth + 5; BPosY = 20; 6832001f49Smrg CPosX = BPosX + ImgWidth + 5; CPosY = 20; 6932001f49Smrg} 7032001f49Smrg 7132001f49Smrg 7232001f49Smrgstatic void 7332001f49SmrgPrintString(const char *s) 7432001f49Smrg{ 7532001f49Smrg while (*s) { 7632001f49Smrg glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s); 7732001f49Smrg s++; 7832001f49Smrg } 7932001f49Smrg} 8032001f49Smrg 8132001f49Smrg 8232001f49Smrgstatic void 8332001f49SmrgSetupPixelTransfer(GLboolean invert) 8432001f49Smrg{ 8532001f49Smrg if (invert) { 8632001f49Smrg glPixelTransferf(GL_RED_SCALE, -1.0); 8732001f49Smrg glPixelTransferf(GL_RED_BIAS, 1.0); 8832001f49Smrg glPixelTransferf(GL_GREEN_SCALE, -1.0); 8932001f49Smrg glPixelTransferf(GL_GREEN_BIAS, 1.0); 9032001f49Smrg glPixelTransferf(GL_BLUE_SCALE, -1.0); 9132001f49Smrg glPixelTransferf(GL_BLUE_BIAS, 1.0); 9232001f49Smrg } 9332001f49Smrg else { 9432001f49Smrg glPixelTransferf(GL_RED_SCALE, 1.0); 9532001f49Smrg glPixelTransferf(GL_RED_BIAS, 0.0); 9632001f49Smrg glPixelTransferf(GL_GREEN_SCALE, 1.0); 9732001f49Smrg glPixelTransferf(GL_GREEN_BIAS, 0.0); 9832001f49Smrg glPixelTransferf(GL_BLUE_SCALE, 1.0); 9932001f49Smrg glPixelTransferf(GL_BLUE_BIAS, 0.0); 10032001f49Smrg } 10132001f49Smrg} 10232001f49Smrg 10332001f49Smrg 10432001f49Smrg/** 10532001f49Smrg * Exercise Pixel Pack parameters by reading the image in four pieces. 10632001f49Smrg */ 10732001f49Smrgstatic void 10832001f49SmrgComplexReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, 10932001f49Smrg GLenum format, GLenum type, GLvoid *pixels) 11032001f49Smrg{ 11132001f49Smrg const GLsizei width0 = width / 2; 11232001f49Smrg const GLsizei width1 = width - width0; 11332001f49Smrg const GLsizei height0 = height / 2; 11432001f49Smrg const GLsizei height1 = height - height0; 11532001f49Smrg 11632001f49Smrg glPixelStorei(GL_PACK_ROW_LENGTH, width); 11732001f49Smrg 11832001f49Smrg /* lower-left quadrant */ 11932001f49Smrg glReadPixels(x, y, width0, height0, format, type, pixels); 12032001f49Smrg 12132001f49Smrg /* lower-right quadrant */ 12232001f49Smrg glPixelStorei(GL_PACK_SKIP_PIXELS, width0); 12332001f49Smrg glReadPixels(x + width0, y, width1, height0, format, type, pixels); 12432001f49Smrg 12532001f49Smrg /* upper-left quadrant */ 12632001f49Smrg glPixelStorei(GL_PACK_SKIP_PIXELS, 0); 12732001f49Smrg glPixelStorei(GL_PACK_SKIP_ROWS, height0); 12832001f49Smrg glReadPixels(x, y + height0, width0, height1, format, type, pixels); 12932001f49Smrg 13032001f49Smrg /* upper-right quadrant */ 13132001f49Smrg glPixelStorei(GL_PACK_SKIP_PIXELS, width0); 13232001f49Smrg glPixelStorei(GL_PACK_SKIP_ROWS, height0); 13332001f49Smrg glReadPixels(x + width0, y + height0, width1, height1, format, type, pixels); 13432001f49Smrg 13532001f49Smrg /* restore defaults */ 13632001f49Smrg glPixelStorei(GL_PACK_SKIP_PIXELS, 0); 13732001f49Smrg glPixelStorei(GL_PACK_SKIP_ROWS, 0); 13832001f49Smrg glPixelStorei(GL_PACK_ROW_LENGTH, ImgWidth); 13932001f49Smrg} 14032001f49Smrg 14132001f49Smrg 14232001f49Smrg 14332001f49Smrgstatic void 14432001f49SmrgDisplay( void ) 14532001f49Smrg{ 14632001f49Smrg glClearColor(.3, .3, .3, 1); 14732001f49Smrg glClear( GL_COLOR_BUFFER_BIT ); 14832001f49Smrg 14932001f49Smrg glRasterPos2i(5, ImgHeight+25); 15032001f49Smrg PrintString("f = toggle front/back s = toggle scale/bias b = benchmark"); 15132001f49Smrg 15232001f49Smrg /* draw original image */ 15332001f49Smrg glRasterPos2i(APosX, 5); 15432001f49Smrg PrintString("Original"); 15532001f49Smrg if (!Triangle) { 15632001f49Smrg glRasterPos2i(APosX, APosY); 15732001f49Smrg glEnable(GL_DITHER); 15832001f49Smrg SetupPixelTransfer(GL_FALSE); 15932001f49Smrg glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 16032001f49Smrg glDrawPixels(ImgWidth, ImgHeight, ImgFormat, GL_UNSIGNED_BYTE, Image); 16132001f49Smrg } 16232001f49Smrg else { 16332001f49Smrg float z = 0; 16432001f49Smrg 16532001f49Smrg glViewport(APosX, APosY, ImgWidth, ImgHeight); 16632001f49Smrg glMatrixMode( GL_PROJECTION ); 16732001f49Smrg glLoadIdentity(); 16832001f49Smrg glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); 16932001f49Smrg glDisable(GL_CULL_FACE); 17032001f49Smrg 17132001f49Smrg /* Red should never be seen 17232001f49Smrg */ 17332001f49Smrg glBegin(GL_POLYGON); 17432001f49Smrg glColor3f(1,0,0); 17532001f49Smrg glVertex3f(-2, -2, z); 17632001f49Smrg glVertex3f(-2, 2, z); 17732001f49Smrg glVertex3f(2, 2, z); 17832001f49Smrg glVertex3f(2, -2, z); 17932001f49Smrg glEnd(); 18032001f49Smrg 18132001f49Smrg /* Blue background 18232001f49Smrg */ 18332001f49Smrg glBegin(GL_POLYGON); 18432001f49Smrg glColor3f(.5,.5,1); 18532001f49Smrg glVertex3f(-1, -1, z); 18632001f49Smrg glVertex3f(-1, 1, z); 18732001f49Smrg glVertex3f(1, 1, z); 18832001f49Smrg glVertex3f(1, -1, z); 18932001f49Smrg glEnd(); 19032001f49Smrg 19132001f49Smrg /* Triangle 19232001f49Smrg */ 19332001f49Smrg glBegin(GL_TRIANGLES); 19432001f49Smrg glColor3f(.8,0,0); 19532001f49Smrg glVertex3f(-0.9, -0.9, z); 19632001f49Smrg glColor3f(0,.9,0); 19732001f49Smrg glVertex3f( 0.9, -0.9, z); 19832001f49Smrg glColor3f(0,0,.7); 19932001f49Smrg glVertex3f( 0.0, 0.9, z); 20032001f49Smrg glEnd(); 20132001f49Smrg 20232001f49Smrg glColor3f(1,1,1); 20332001f49Smrg 20432001f49Smrg glViewport( 0, 0, WinWidth, WinHeight ); 20532001f49Smrg glMatrixMode( GL_PROJECTION ); 20632001f49Smrg glLoadIdentity(); 20732001f49Smrg glOrtho( 0.0, WinWidth, 0.0, WinHeight, -1.0, 1.0 ); 20832001f49Smrg } 20932001f49Smrg 21032001f49Smrg /* might try alignment=4 here for testing */ 21132001f49Smrg glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 21232001f49Smrg glPixelStorei(GL_PACK_ALIGNMENT, 1); 21332001f49Smrg 21432001f49Smrg /* do readpixels, drawpixels */ 21532001f49Smrg glRasterPos2i(BPosX, 5); 21632001f49Smrg PrintString("Read/DrawPixels"); 21732001f49Smrg SetupPixelTransfer(ScaleAndBias); 21832001f49Smrg if (Benchmark) { 21932001f49Smrg GLint reads = 0; 22032001f49Smrg GLint endTime; 22132001f49Smrg GLint startTime = glutGet(GLUT_ELAPSED_TIME); 22232001f49Smrg GLdouble seconds, mpixels, mpixelsPerSecond; 22332001f49Smrg printf("Benchmarking...\n"); 22432001f49Smrg do { 22532001f49Smrg glReadPixels(APosX, APosY, ImgWidth, ImgHeight, 22632001f49Smrg ReadFormat, ReadType, TempImage); 22732001f49Smrg reads++; 22832001f49Smrg endTime = glutGet(GLUT_ELAPSED_TIME); 22932001f49Smrg } while (endTime - startTime < 4000); /* 4 seconds */ 23032001f49Smrg seconds = (double) (endTime - startTime) / 1000.0; 23132001f49Smrg mpixels = reads * (ImgWidth * ImgHeight / (1000.0 * 1000.0)); 23232001f49Smrg mpixelsPerSecond = mpixels / seconds; 23332001f49Smrg printf("Result: %d reads in %f seconds = %f Mpixels/sec\n", 23432001f49Smrg reads, seconds, mpixelsPerSecond); 23532001f49Smrg Benchmark = GL_FALSE; 23632001f49Smrg } 23732001f49Smrg else { 23832001f49Smrg /* clear the temporary image to white (helpful for debugging */ 23932001f49Smrg memset(TempImage, 255, ImgWidth * ImgHeight * 4); 24032001f49Smrg#if 1 24132001f49Smrg glReadPixels(APosX, APosY, ImgWidth, ImgHeight, 24232001f49Smrg ReadFormat, ReadType, TempImage); 24332001f49Smrg (void) ComplexReadPixels; 24432001f49Smrg#else 24532001f49Smrg /* you might use this when debugging */ 24632001f49Smrg ComplexReadPixels(APosX, APosY, ImgWidth, ImgHeight, 24732001f49Smrg ReadFormat, ReadType, TempImage); 24832001f49Smrg#endif 24932001f49Smrg } 25032001f49Smrg glRasterPos2i(BPosX, BPosY); 25132001f49Smrg glDisable(GL_DITHER); 25232001f49Smrg SetupPixelTransfer(GL_FALSE); 25332001f49Smrg glDrawPixels(ImgWidth, ImgHeight, ReadFormat, ReadType, TempImage); 25432001f49Smrg 25532001f49Smrg /* do copypixels */ 25632001f49Smrg glRasterPos2i(CPosX, 5); 25732001f49Smrg PrintString("CopyPixels"); 25832001f49Smrg glRasterPos2i(CPosX, CPosY); 25932001f49Smrg glDisable(GL_DITHER); 26032001f49Smrg SetupPixelTransfer(ScaleAndBias); 26132001f49Smrg glCopyPixels(APosX, APosY, ImgWidth, ImgHeight, GL_COLOR); 26232001f49Smrg 26332001f49Smrg if (!DrawFront) 26432001f49Smrg glutSwapBuffers(); 26532001f49Smrg else 26632001f49Smrg glFinish(); 26732001f49Smrg} 26832001f49Smrg 26932001f49Smrg 27032001f49Smrgstatic void 27132001f49SmrgReshape( int width, int height ) 27232001f49Smrg{ 27332001f49Smrg WinWidth = width; 27432001f49Smrg WinHeight = height; 27532001f49Smrg 27632001f49Smrg glViewport( 0, 0, width, height ); 27732001f49Smrg glMatrixMode( GL_PROJECTION ); 27832001f49Smrg glLoadIdentity(); 27932001f49Smrg glOrtho( 0.0, width, 0.0, height, -1.0, 1.0 ); 28032001f49Smrg glMatrixMode( GL_MODELVIEW ); 28132001f49Smrg glLoadIdentity(); 28232001f49Smrg} 28332001f49Smrg 28432001f49Smrg 28532001f49Smrgstatic void 28632001f49SmrgKey( unsigned char key, int x, int y ) 28732001f49Smrg{ 28832001f49Smrg (void) x; 28932001f49Smrg (void) y; 29032001f49Smrg switch (key) { 29132001f49Smrg case 'b': 29232001f49Smrg Benchmark = GL_TRUE; 29332001f49Smrg break; 29432001f49Smrg case 't': 29532001f49Smrg Triangle = !Triangle; 29632001f49Smrg break; 29732001f49Smrg case 's': 29832001f49Smrg ScaleAndBias = !ScaleAndBias; 29932001f49Smrg break; 30032001f49Smrg case 'f': 30132001f49Smrg DrawFront = !DrawFront; 30232001f49Smrg if (DrawFront) { 30332001f49Smrg glDrawBuffer(GL_FRONT); 30432001f49Smrg glReadBuffer(GL_FRONT); 30532001f49Smrg } 30632001f49Smrg else { 30732001f49Smrg glDrawBuffer(GL_BACK); 30832001f49Smrg glReadBuffer(GL_BACK); 30932001f49Smrg } 31032001f49Smrg printf("glDrawBuffer(%s)\n", DrawFront ? "GL_FRONT" : "GL_BACK"); 31132001f49Smrg break; 31232001f49Smrg case 27: 31332001f49Smrg exit(0); 31432001f49Smrg break; 31532001f49Smrg } 31632001f49Smrg glutPostRedisplay(); 31732001f49Smrg} 31832001f49Smrg 31932001f49Smrg 32032001f49Smrgstatic void 32132001f49SmrgInit( GLboolean ciMode ) 32232001f49Smrg{ 32332001f49Smrg GLboolean have_read_format = GL_FALSE; 32432001f49Smrg 32532001f49Smrg printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION)); 32632001f49Smrg printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); 32732001f49Smrg 32832001f49Smrg Image = LoadRGBImage( IMAGE_FILE, &ImgWidth, &ImgHeight, &ImgFormat ); 32932001f49Smrg if (!Image) { 33032001f49Smrg printf("Couldn't read %s\n", IMAGE_FILE); 33132001f49Smrg exit(0); 33232001f49Smrg } 33332001f49Smrg 33432001f49Smrg if (ciMode) { 33532001f49Smrg /* Convert RGB image to grayscale */ 33632001f49Smrg GLubyte *indexImage = (GLubyte *) malloc( ImgWidth * ImgHeight ); 33732001f49Smrg GLint i; 33832001f49Smrg for (i=0; i<ImgWidth*ImgHeight; i++) { 33932001f49Smrg int gray = Image[i*3] + Image[i*3+1] + Image[i*3+2]; 34032001f49Smrg indexImage[i] = gray / 3; 34132001f49Smrg } 34232001f49Smrg free(Image); 34332001f49Smrg Image = indexImage; 34432001f49Smrg ImgFormat = GL_COLOR_INDEX; 34532001f49Smrg 34632001f49Smrg for (i=0;i<255;i++) { 34732001f49Smrg float g = i / 255.0; 34832001f49Smrg glutSetColor(i, g, g, g); 34932001f49Smrg } 35032001f49Smrg } 35132001f49Smrg 35232001f49Smrg#ifdef GL_OES_read_format 35332001f49Smrg if ( glutExtensionSupported( "GL_OES_read_format" ) ) { 35432001f49Smrg glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE_OES, (GLint *) &ReadType); 35532001f49Smrg glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES, (GLint *) &ReadFormat); 35632001f49Smrg 35732001f49Smrg have_read_format = GL_TRUE; 35832001f49Smrg } 35932001f49Smrg#endif 36032001f49Smrg 36132001f49Smrg printf( "GL_OES_read_format %ssupported. " 36232001f49Smrg "Using type / format = 0x%04x / 0x%04x\n", 36332001f49Smrg (have_read_format) ? "" : "not ", 36432001f49Smrg ReadType, ReadFormat ); 36532001f49Smrg 36632001f49Smrg printf("Loaded %d by %d image\n", ImgWidth, ImgHeight ); 36732001f49Smrg 36832001f49Smrg glPixelStorei(GL_UNPACK_ROW_LENGTH, ImgWidth); 36932001f49Smrg glPixelStorei(GL_PACK_ROW_LENGTH, ImgWidth); 37032001f49Smrg 37132001f49Smrg Reset(); 37232001f49Smrg 37332001f49Smrg /* allocate large TempImage to store and image data type, plus an 37432001f49Smrg * extra 1KB in case we're tinkering with pack alignment. 37532001f49Smrg */ 37632001f49Smrg TempImage = (GLubyte *) malloc(ImgWidth * ImgHeight * 4 * 4 37732001f49Smrg + 1000); 37832001f49Smrg assert(TempImage); 37932001f49Smrg} 38032001f49Smrg 38132001f49Smrg 38232001f49Smrgint 38332001f49Smrgmain( int argc, char *argv[] ) 38432001f49Smrg{ 38532001f49Smrg GLboolean ciMode = GL_FALSE; 38632001f49Smrg glutInitWindowSize( 750, 250 ); 38732001f49Smrg glutInit( &argc, argv ); 38832001f49Smrg if (argc > 1 && strcmp(argv[1], "-ci")==0) { 38932001f49Smrg ciMode = GL_TRUE; 39032001f49Smrg } 39132001f49Smrg if (ciMode) 39232001f49Smrg glutInitDisplayMode( GLUT_INDEX | GLUT_DOUBLE ); 39332001f49Smrg else 39432001f49Smrg glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE ); 39532001f49Smrg glutCreateWindow(argv[0]); 39632001f49Smrg Init(ciMode); 39732001f49Smrg glutReshapeFunc( Reshape ); 39832001f49Smrg glutKeyboardFunc( Key ); 39932001f49Smrg glutDisplayFunc( Display ); 40032001f49Smrg glutMainLoop(); 40132001f49Smrg return 0; 40232001f49Smrg} 403