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