1/* 2 * GL_ARB_pixel_buffer_object test 3 * 4 * Command line options: 5 * -w WIDTH -h HEIGHT sets window size 6 * 7 */ 8 9#include <math.h> 10#include <stdio.h> 11#include <stdlib.h> 12#include <string.h> 13#include <GL/glew.h> 14#include "glut_wrap.h" 15 16 17#define ANIMATE 10 18#define PBO 11 19#define QUIT 100 20 21static GLuint DrawPBO; 22 23static GLboolean Animate = GL_TRUE; 24static GLboolean use_pbo = 1; 25static GLboolean whole_rect = 1; 26 27static GLfloat Drift = 0.0; 28static GLfloat drift_increment = 1/255.0; 29static GLfloat Xrot = 20.0, Yrot = 30.0; 30 31static GLuint Width = 1024; 32static GLuint Height = 512; 33 34 35static void Idle( void ) 36{ 37 if (Animate) { 38 39 Drift += drift_increment; 40 if (Drift >= 1.0) 41 Drift = 0.0; 42 43 glutPostRedisplay(); 44 } 45} 46 47/*static int max( int a, int b ) { return a > b ? a : b; }*/ 48 49#ifndef min 50static int min( int a, int b ) { return a < b ? a : b; } 51#endif 52 53static void DrawObject(void) 54{ 55 GLint size = Width * Height * 4; 56 57 if (use_pbo) { 58 /* XXX: This is extremely important - semantically makes the buffer 59 * contents undefined, but in practice means that the driver can 60 * release the old copy of the texture and allocate a new one 61 * without waiting for outstanding rendering to complete. 62 */ 63 glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, DrawPBO); 64 glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_EXT, size, NULL, GL_STREAM_DRAW_ARB); 65 66 { 67 char *image = glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, GL_WRITE_ONLY_ARB); 68 69 printf("char %d\n", (unsigned char)(Drift * 255)); 70 71 memset(image, (unsigned char)(Drift * 255), size); 72 73 glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT); 74 } 75 76 77 /* BGRA is required for most hardware paths: 78 */ 79 glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, Width, Height, 0, 80 GL_BGRA, GL_UNSIGNED_BYTE, NULL); 81 } 82 else { 83 static char *image = NULL; 84 85 if (image == NULL) 86 image = malloc(size); 87 88 glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0); 89 90 memset(image, (unsigned char)(Drift * 255), size); 91 92 /* BGRA should be the fast path for regular uploads as well. 93 */ 94 glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, Width, Height, 0, 95 GL_BGRA, GL_UNSIGNED_BYTE, image); 96 } 97 98 { 99 int x,y,w,h; 100 101 if (whole_rect) { 102 x = y = 0; 103 w = Width; 104 h = Height; 105 } 106 else { 107 x = y = 0; 108 w = min(10, Width); 109 h = min(10, Height); 110 } 111 112 glBegin(GL_QUADS); 113 114 glTexCoord2f( x, y); 115 glVertex2f( x, y ); 116 117 glTexCoord2f( x, y + h); 118 glVertex2f( x, y + h); 119 120 glTexCoord2f( x + w + .5, y + h); 121 glVertex2f( x + w, y + h ); 122 123 glTexCoord2f( x + w, y + .5); 124 glVertex2f( x + w, y ); 125 126 glEnd(); 127 } 128} 129 130 131 132static void Display( void ) 133{ 134 static GLint T0 = 0; 135 static GLint Frames = 0; 136 GLint t; 137 138 glClear( GL_COLOR_BUFFER_BIT ); 139 140 glPushMatrix(); 141 DrawObject(); 142 glPopMatrix(); 143 144 glutSwapBuffers(); 145 146 Frames++; 147 148 t = glutGet(GLUT_ELAPSED_TIME); 149 if (t - T0 >= 1000) { 150 GLfloat seconds = (t - T0) / 1000.0; 151 152 GLfloat fps = Frames / seconds; 153 printf("%d frames in %6.3f seconds = %6.3f FPS\n", Frames, seconds, fps); 154 fflush(stdout); 155 156 drift_increment = 2.2 * seconds / Frames; 157 T0 = t; 158 Frames = 0; 159 } 160} 161 162 163static void Reshape( int width, int height ) 164{ 165 glViewport( 0, 0, width, height ); 166 glMatrixMode( GL_PROJECTION ); 167 glLoadIdentity(); 168/* glFrustum( -1.0, 1.0, -1.0, 1.0, 10.0, 100.0 ); */ 169 gluOrtho2D( 0, width, height, 0 ); 170 glMatrixMode( GL_MODELVIEW ); 171 glLoadIdentity(); 172 glTranslatef(0.375, 0.375, 0); 173} 174 175 176static void ModeMenu(int entry) 177{ 178 if (entry==ANIMATE) { 179 Animate = !Animate; 180 } 181 else if (entry==PBO) { 182 use_pbo = !use_pbo; 183 } 184 else if (entry==QUIT) { 185 exit(0); 186 } 187 188 glutPostRedisplay(); 189} 190 191 192static void Key( unsigned char key, int x, int y ) 193{ 194 (void) x; 195 (void) y; 196 switch (key) { 197 case 27: 198 exit(0); 199 break; 200 } 201 glutPostRedisplay(); 202} 203 204 205static void SpecialKey( int key, int x, int y ) 206{ 207 float step = 3.0; 208 (void) x; 209 (void) y; 210 211 switch (key) { 212 case GLUT_KEY_UP: 213 Xrot += step; 214 break; 215 case GLUT_KEY_DOWN: 216 Xrot -= step; 217 break; 218 case GLUT_KEY_LEFT: 219 Yrot += step; 220 break; 221 case GLUT_KEY_RIGHT: 222 Yrot -= step; 223 break; 224 } 225 glutPostRedisplay(); 226} 227 228 229static void Init( int argc, char *argv[] ) 230{ 231 const char *exten = (const char *) glGetString(GL_EXTENSIONS); 232 GLuint texObj; 233 GLint size; 234 235 236 if (!strstr(exten, "GL_ARB_pixel_buffer_object")) { 237 printf("Sorry, GL_ARB_pixel_buffer_object not supported by this renderer.\n"); 238 exit(1); 239 } 240 241 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &size); 242 printf("%d x %d max texture size\n", size, size); 243 244 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 245 246 /* allocate two texture objects */ 247 glGenTextures(1, &texObj); 248 249 /* setup the texture objects */ 250 glActiveTextureARB(GL_TEXTURE0_ARB); 251 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texObj); 252 253 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 254 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 255 256 glGenBuffersARB(1, &DrawPBO); 257 258 glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, DrawPBO); 259 glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_EXT, 260 Width * Height * 4, NULL, GL_STREAM_DRAW); 261 262 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 263 264 glEnable(GL_TEXTURE_RECTANGLE_ARB); 265 266 glShadeModel(GL_SMOOTH); 267 glClearColor(0.3, 0.3, 0.4, 1.0); 268 269 if (argc > 1 && strcmp(argv[1], "-info")==0) { 270 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); 271 printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION)); 272 printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR)); 273 printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS)); 274 } 275} 276 277 278int main( int argc, char *argv[] ) 279{ 280 GLint i; 281 282 glutInit( &argc, argv ); 283 284 for (i = 1; i < argc; i++) { 285 if (strcmp(argv[i], "-w") == 0) { 286 Width = atoi(argv[i+1]); 287 if (Width <= 0) { 288 printf("Error, bad width\n"); 289 exit(1); 290 } 291 i++; 292 } 293 else if (strcmp(argv[i], "-h") == 0) { 294 Height = atoi(argv[i+1]); 295 if (Height <= 0) { 296 printf("Error, bad height\n"); 297 exit(1); 298 } 299 i++; 300 } 301 } 302 303 glutInitWindowSize( Width, Height ); 304 glutInitWindowPosition( 0, 0 ); 305 glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE ); 306 glutCreateWindow(argv[0] ); 307 glewInit(); 308 309 Init( argc, argv ); 310 311 glutReshapeFunc( Reshape ); 312 glutKeyboardFunc( Key ); 313 glutSpecialFunc( SpecialKey ); 314 glutDisplayFunc( Display ); 315 glutIdleFunc( Idle ); 316 317 glutCreateMenu(ModeMenu); 318 glutAddMenuEntry("Toggle Animation", ANIMATE); 319 glutAddMenuEntry("Toggle PBO", PBO); 320 glutAddMenuEntry("Quit", QUIT); 321 glutAttachMenu(GLUT_RIGHT_BUTTON); 322 323 glutMainLoop(); 324 return 0; 325} 326