| Brian Paul | 7d01c34 | 2004-09-24 23:00:52 +0000 | [diff] [blame] | 1 | /* | 
 | 2 |  * Demo of off-screen Mesa rendering with 32-bit float color channels. | 
 | 3 |  * This requires the libOSMesa32.so library. | 
 | 4 |  * | 
 | 5 |  * Compile with something like this: | 
 | 6 |  * | 
| Brian Paul | 371f576 | 2005-01-29 13:48:27 +0000 | [diff] [blame] | 7 |  * gcc osdemo32.c -I../../include -L../../lib -lglut -lGLU -lOSMesa32 -lm -o osdemo32 | 
| Brian Paul | 7d01c34 | 2004-09-24 23:00:52 +0000 | [diff] [blame] | 8 |  */ | 
 | 9 |  | 
 | 10 |  | 
 | 11 | #include <stdio.h> | 
 | 12 | #include <stdlib.h> | 
 | 13 | #include "GL/osmesa.h" | 
 | 14 | #include "GL/glut.h" | 
 | 15 |  | 
 | 16 |  | 
 | 17 | #define SAVE_TARGA | 
 | 18 |  | 
 | 19 |  | 
 | 20 | #define WIDTH 400 | 
 | 21 | #define HEIGHT 400 | 
 | 22 |  | 
 | 23 |  | 
 | 24 |  | 
 | 25 | static void render_image( void ) | 
 | 26 | { | 
 | 27 |    GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 }; | 
 | 28 |    GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 }; | 
 | 29 |    GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 }; | 
 | 30 |    GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 }; | 
 | 31 |    GLfloat red_mat[]   = { 1.0, 0.2, 0.2, 1.0 }; | 
 | 32 |    GLfloat green_mat[] = { 0.2, 1.0, 0.2, 0.5 }; | 
 | 33 |    GLfloat blue_mat[]  = { 0.2, 0.2, 1.0, 1.0 }; | 
 | 34 |    GLfloat white_mat[]  = { 1.0, 1.0, 1.0, 1.0 }; | 
 | 35 |    GLfloat purple_mat[] = { 1.0, 0.2, 1.0, 1.0 }; | 
 | 36 |    GLUquadricObj *qobj = gluNewQuadric(); | 
 | 37 |  | 
 | 38 |    glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); | 
 | 39 |    glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); | 
 | 40 |    glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); | 
 | 41 |    glLightfv(GL_LIGHT0, GL_POSITION, light_position); | 
 | 42 |      | 
 | 43 |    glEnable(GL_LIGHTING); | 
 | 44 |    glEnable(GL_LIGHT0); | 
 | 45 |    glEnable(GL_DEPTH_TEST); | 
 | 46 |  | 
 | 47 |    glMatrixMode(GL_PROJECTION); | 
 | 48 |    glLoadIdentity(); | 
 | 49 |    glOrtho(-2.5, 2.5, -2.5, 2.5, -10.0, 10.0); | 
 | 50 |    glMatrixMode(GL_MODELVIEW); | 
 | 51 |  | 
 | 52 |    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); | 
 | 53 |  | 
 | 54 |    glPushMatrix(); | 
 | 55 |    glRotatef(20.0, 1.0, 0.0, 0.0); | 
 | 56 |  | 
 | 57 | #if 0 | 
 | 58 |    glPushMatrix(); | 
 | 59 |    glTranslatef(-0.75, 0.5, 0.0);  | 
 | 60 |    glRotatef(90.0, 1.0, 0.0, 0.0); | 
 | 61 |    glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red_mat ); | 
 | 62 |    glutSolidTorus(0.275, 0.85, 20, 20); | 
 | 63 |    glPopMatrix(); | 
 | 64 | #endif | 
 | 65 |  | 
 | 66 |    /* red square */ | 
 | 67 |    glPushMatrix(); | 
 | 68 |    glTranslatef(0.0, -0.5, 0.0);  | 
 | 69 |    glRotatef(90, 1, 0.5, 0); | 
 | 70 |    glScalef(3, 3, 3); | 
 | 71 |    glDisable(GL_LIGHTING); | 
 | 72 |    glColor4f(1, 0, 0, 0.5); | 
 | 73 |    glBegin(GL_POLYGON); | 
 | 74 |    glVertex2f(-1, -1); | 
 | 75 |    glVertex2f( 1, -1); | 
 | 76 |    glVertex2f( 1,  1); | 
 | 77 |    glVertex2f(-1,  1); | 
 | 78 |    glEnd(); | 
 | 79 |    glEnable(GL_LIGHTING); | 
 | 80 |    glPopMatrix(); | 
 | 81 |  | 
 | 82 | #if 0 | 
 | 83 |    /* green square */ | 
 | 84 |    glPushMatrix(); | 
 | 85 |    glTranslatef(0.0, 0.5, 0.1);  | 
 | 86 |    glDisable(GL_LIGHTING); | 
 | 87 |    glColor3f(0, 1, 0); | 
 | 88 |    glBegin(GL_POLYGON); | 
 | 89 |    glVertex2f(-1, -1); | 
 | 90 |    glVertex2f( 1, -1); | 
 | 91 |    glVertex2f( 1,  1); | 
 | 92 |    glVertex2f(-1,  1); | 
 | 93 |    glEnd(); | 
 | 94 |    glEnable(GL_LIGHTING); | 
 | 95 |    glPopMatrix(); | 
 | 96 |  | 
 | 97 |    /* blue square */ | 
 | 98 |    glPushMatrix(); | 
 | 99 |    glTranslatef(0.75, 0.5, 0.3);  | 
 | 100 |    glDisable(GL_LIGHTING); | 
 | 101 |    glColor3f(0, 0, 0.5); | 
 | 102 |    glBegin(GL_POLYGON); | 
 | 103 |    glVertex2f(-1, -1); | 
 | 104 |    glVertex2f( 1, -1); | 
 | 105 |    glVertex2f( 1,  1); | 
 | 106 |    glVertex2f(-1,  1); | 
 | 107 |    glEnd(); | 
 | 108 |    glEnable(GL_LIGHTING); | 
 | 109 |    glPopMatrix(); | 
 | 110 | #endif | 
 | 111 |    glPushMatrix(); | 
 | 112 |    glTranslatef(-0.75, -0.5, 0.0);  | 
 | 113 |    glRotatef(270.0, 1.0, 0.0, 0.0); | 
 | 114 |    glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, green_mat ); | 
 | 115 |    glColor4f(0,1,0,0.5); | 
 | 116 |    glEnable(GL_BLEND); | 
 | 117 |    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | 
 | 118 |    gluCylinder(qobj, 1.0, 0.0, 2.0, 16, 1); | 
 | 119 |    glDisable(GL_BLEND); | 
 | 120 |    glPopMatrix(); | 
 | 121 |  | 
 | 122 |    glPushMatrix(); | 
 | 123 |    glTranslatef(0.75, 1.0, 1.0);  | 
 | 124 |    glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blue_mat ); | 
 | 125 |    gluSphere(qobj, 1.0, 20, 20); | 
 | 126 |    glPopMatrix(); | 
 | 127 |  | 
 | 128 |    glPopMatrix(); | 
 | 129 |  | 
| Brian Paul | c84cde7 | 2005-01-29 12:57:36 +0000 | [diff] [blame] | 130 |    /* This is very important!!! | 
 | 131 |     * Make sure buffered commands are finished!!! | 
 | 132 |     */ | 
 | 133 |    glFinish(); | 
 | 134 |  | 
| Brian Paul | 7d01c34 | 2004-09-24 23:00:52 +0000 | [diff] [blame] | 135 |    gluDeleteQuadric(qobj); | 
 | 136 |  | 
 | 137 |    { | 
 | 138 |       GLint r, g, b, a; | 
 | 139 |       glGetIntegerv(GL_RED_BITS, &r); | 
 | 140 |       glGetIntegerv(GL_GREEN_BITS, &g); | 
 | 141 |       glGetIntegerv(GL_BLUE_BITS, &b); | 
 | 142 |       glGetIntegerv(GL_ALPHA_BITS, &a); | 
 | 143 |       printf("channel sizes: %d %d %d %d\n", r, g, b, a); | 
 | 144 |    } | 
 | 145 | } | 
 | 146 |  | 
 | 147 |  | 
 | 148 |  | 
 | 149 | static void | 
 | 150 | write_targa(const char *filename, const GLfloat *buffer, int width, int height) | 
 | 151 | { | 
 | 152 |    FILE *f = fopen( filename, "w" ); | 
 | 153 |    if (f) { | 
 | 154 |       int i, x, y; | 
 | 155 |       const GLfloat *ptr = buffer; | 
 | 156 |       printf ("osdemo, writing tga file \n"); | 
 | 157 |       fputc (0x00, f);	/* ID Length, 0 => No ID	*/ | 
 | 158 |       fputc (0x00, f);	/* Color Map Type, 0 => No color map included	*/ | 
 | 159 |       fputc (0x02, f);	/* Image Type, 2 => Uncompressed, True-color Image */ | 
 | 160 |       fputc (0x00, f);	/* Next five bytes are about the color map entries */ | 
 | 161 |       fputc (0x00, f);	/* 2 bytes Index, 2 bytes length, 1 byte size */ | 
 | 162 |       fputc (0x00, f); | 
 | 163 |       fputc (0x00, f); | 
 | 164 |       fputc (0x00, f); | 
 | 165 |       fputc (0x00, f);	/* X-origin of Image	*/ | 
 | 166 |       fputc (0x00, f); | 
 | 167 |       fputc (0x00, f);	/* Y-origin of Image	*/ | 
 | 168 |       fputc (0x00, f); | 
 | 169 |       fputc (WIDTH & 0xff, f);      /* Image Width	*/ | 
 | 170 |       fputc ((WIDTH>>8) & 0xff, f); | 
 | 171 |       fputc (HEIGHT & 0xff, f);     /* Image Height	*/ | 
 | 172 |       fputc ((HEIGHT>>8) & 0xff, f); | 
 | 173 |       fputc (0x18, f);		/* Pixel Depth, 0x18 => 24 Bits	*/ | 
 | 174 |       fputc (0x20, f);		/* Image Descriptor	*/ | 
 | 175 |       fclose(f); | 
 | 176 |       f = fopen( filename, "ab" );  /* reopen in binary append mode */ | 
 | 177 |       for (y=height-1; y>=0; y--) { | 
 | 178 |          for (x=0; x<width; x++) { | 
 | 179 |             int r, g, b; | 
 | 180 |             i = (y*width + x) * 4; | 
 | 181 |             r = (int) (ptr[i+0] * 255.0); | 
 | 182 |             g = (int) (ptr[i+1] * 255.0); | 
 | 183 |             b = (int) (ptr[i+2] * 255.0); | 
 | 184 |             if (r > 255) r = 255; | 
 | 185 |             if (g > 255) g = 255; | 
 | 186 |             if (b > 255) b = 255; | 
 | 187 |             fputc(b, f); /* write blue */ | 
 | 188 |             fputc(g, f); /* write green */ | 
 | 189 |             fputc(r, f); /* write red */ | 
 | 190 |          } | 
 | 191 |       } | 
 | 192 |    } | 
 | 193 | } | 
 | 194 |  | 
 | 195 |  | 
 | 196 | static void | 
| Brian Paul | 371f576 | 2005-01-29 13:48:27 +0000 | [diff] [blame] | 197 | write_ppm(const char *filename, const GLfloat *buffer, int width, int height) | 
| Brian Paul | 7d01c34 | 2004-09-24 23:00:52 +0000 | [diff] [blame] | 198 | { | 
 | 199 |    const int binary = 0; | 
 | 200 |    FILE *f = fopen( filename, "w" ); | 
 | 201 |    if (f) { | 
 | 202 |       int i, x, y; | 
| Brian Paul | 371f576 | 2005-01-29 13:48:27 +0000 | [diff] [blame] | 203 |       const GLfloat *ptr = buffer; | 
| Brian Paul | 7d01c34 | 2004-09-24 23:00:52 +0000 | [diff] [blame] | 204 |       if (binary) { | 
 | 205 |          fprintf(f,"P6\n"); | 
 | 206 |          fprintf(f,"# ppm-file created by osdemo.c\n"); | 
 | 207 |          fprintf(f,"%i %i\n", width,height); | 
 | 208 |          fprintf(f,"255\n"); | 
 | 209 |          fclose(f); | 
 | 210 |          f = fopen( filename, "ab" );  /* reopen in binary append mode */ | 
 | 211 |          for (y=height-1; y>=0; y--) { | 
 | 212 |             for (x=0; x<width; x++) { | 
| Brian Paul | 371f576 | 2005-01-29 13:48:27 +0000 | [diff] [blame] | 213 |                int r, g, b; | 
| Brian Paul | 7d01c34 | 2004-09-24 23:00:52 +0000 | [diff] [blame] | 214 |                i = (y*width + x) * 4; | 
| Brian Paul | 371f576 | 2005-01-29 13:48:27 +0000 | [diff] [blame] | 215 |                r = (int) (ptr[i+0] * 255.0); | 
 | 216 |                g = (int) (ptr[i+1] * 255.0); | 
 | 217 |                b = (int) (ptr[i+2] * 255.0); | 
 | 218 |                if (r > 255) r = 255; | 
 | 219 |                if (g > 255) g = 255; | 
 | 220 |                if (b > 255) b = 255; | 
 | 221 |                fputc(r, f);   /* write red */ | 
 | 222 |                fputc(g, f); /* write green */ | 
 | 223 |                fputc(b, f); /* write blue */ | 
| Brian Paul | 7d01c34 | 2004-09-24 23:00:52 +0000 | [diff] [blame] | 224 |             } | 
 | 225 |          } | 
 | 226 |       } | 
 | 227 |       else { | 
 | 228 |          /*ASCII*/ | 
 | 229 |          int counter = 0; | 
 | 230 |          fprintf(f,"P3\n"); | 
 | 231 |          fprintf(f,"# ascii ppm file created by osdemo.c\n"); | 
 | 232 |          fprintf(f,"%i %i\n", width, height); | 
 | 233 |          fprintf(f,"255\n"); | 
 | 234 |          for (y=height-1; y>=0; y--) { | 
 | 235 |             for (x=0; x<width; x++) { | 
| Brian Paul | 371f576 | 2005-01-29 13:48:27 +0000 | [diff] [blame] | 236 |                int r, g, b; | 
| Brian Paul | 7d01c34 | 2004-09-24 23:00:52 +0000 | [diff] [blame] | 237 |                i = (y*width + x) * 4; | 
| Brian Paul | 371f576 | 2005-01-29 13:48:27 +0000 | [diff] [blame] | 238 |                r = (int) (ptr[i+0] * 255.0); | 
 | 239 |                g = (int) (ptr[i+1] * 255.0); | 
 | 240 |                b = (int) (ptr[i+2] * 255.0); | 
 | 241 |                if (r > 255) r = 255; | 
 | 242 |                if (g > 255) g = 255; | 
 | 243 |                if (b > 255) b = 255; | 
 | 244 |                fprintf(f, " %3d %3d %3d", r, g, b); | 
| Brian Paul | 7d01c34 | 2004-09-24 23:00:52 +0000 | [diff] [blame] | 245 |                counter++; | 
 | 246 |                if (counter % 5 == 0) | 
 | 247 |                   fprintf(f, "\n"); | 
 | 248 |             } | 
 | 249 |          } | 
 | 250 |       } | 
 | 251 |       fclose(f); | 
 | 252 |    } | 
 | 253 | } | 
 | 254 |  | 
 | 255 |  | 
 | 256 |  | 
 | 257 | int main( int argc, char *argv[] ) | 
 | 258 | { | 
| Brian Paul | 371f576 | 2005-01-29 13:48:27 +0000 | [diff] [blame] | 259 |    GLfloat *buffer; | 
| Brian Paul | 7d01c34 | 2004-09-24 23:00:52 +0000 | [diff] [blame] | 260 |  | 
 | 261 |    /* Create an RGBA-mode context */ | 
 | 262 | #if OSMESA_MAJOR_VERSION * 100 + OSMESA_MINOR_VERSION >= 305 | 
 | 263 |    /* specify Z, stencil, accum sizes */ | 
 | 264 |    OSMesaContext ctx = OSMesaCreateContextExt( GL_RGBA, 16, 0, 0, NULL ); | 
 | 265 | #else | 
 | 266 |    OSMesaContext ctx = OSMesaCreateContext( GL_RGBA, NULL ); | 
 | 267 | #endif | 
 | 268 |    if (!ctx) { | 
 | 269 |       printf("OSMesaCreateContext failed!\n"); | 
 | 270 |       return 0; | 
 | 271 |    } | 
 | 272 |  | 
 | 273 |    /* Allocate the image buffer */ | 
| Brian Paul | 371f576 | 2005-01-29 13:48:27 +0000 | [diff] [blame] | 274 |    buffer = (GLfloat *) malloc( WIDTH * HEIGHT * 4 * sizeof(GLfloat)); | 
| Brian Paul | 7d01c34 | 2004-09-24 23:00:52 +0000 | [diff] [blame] | 275 |    if (!buffer) { | 
 | 276 |       printf("Alloc image buffer failed!\n"); | 
 | 277 |       return 0; | 
 | 278 |    } | 
 | 279 |  | 
 | 280 |    /* Bind the buffer to the context and make it current */ | 
 | 281 |    if (!OSMesaMakeCurrent( ctx, buffer, GL_FLOAT, WIDTH, HEIGHT )) { | 
 | 282 |       printf("OSMesaMakeCurrent failed!\n"); | 
 | 283 |       return 0; | 
 | 284 |    } | 
 | 285 |       | 
 | 286 |    render_image(); | 
 | 287 |  | 
 | 288 |    if (argc>1) { | 
 | 289 | #ifdef SAVE_TARGA | 
 | 290 |       write_targa(argv[1], buffer, WIDTH, HEIGHT); | 
 | 291 | #else | 
 | 292 |       write_ppm(argv[1], buffer, WIDTH, HEIGHT); | 
 | 293 | #endif | 
 | 294 |    } | 
 | 295 |    else { | 
 | 296 |       printf("Specify a filename if you want to make an image file\n"); | 
 | 297 |    } | 
 | 298 |  | 
 | 299 |    printf("all done\n"); | 
 | 300 |  | 
 | 301 |    /* free the image buffer */ | 
 | 302 |    free( buffer ); | 
 | 303 |  | 
 | 304 |    /* destroy the context */ | 
 | 305 |    OSMesaDestroyContext( ctx ); | 
 | 306 |  | 
 | 307 |    return 0; | 
 | 308 | } |