132001f49Smrg/* 232001f49Smrg * Demo of off-screen Mesa rendering with 32-bit float color channels. 332001f49Smrg * This requires the libOSMesa32.so library. 432001f49Smrg * 532001f49Smrg * Compile with something like this: 632001f49Smrg * 732001f49Smrg * gcc osdemo32.c -I../../include -L../../lib -lglut -lGLU -lOSMesa32 -lm -o osdemo32 832001f49Smrg */ 932001f49Smrg 1032001f49Smrg 1132001f49Smrg#include <stdio.h> 1232001f49Smrg#include <stdlib.h> 1332001f49Smrg#include "GL/osmesa.h" 1432001f49Smrg#include "glut_wrap.h" 1532001f49Smrg 1632001f49Smrg 1732001f49Smrg#define SAVE_TARGA 1832001f49Smrg 1932001f49Smrg 2032001f49Smrg#define WIDTH 400 2132001f49Smrg#define HEIGHT 400 2232001f49Smrg 2332001f49Smrg 2432001f49Smrg 2532001f49Smrgstatic void render_image( void ) 2632001f49Smrg{ 2732001f49Smrg GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 }; 2832001f49Smrg GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 }; 2932001f49Smrg GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 }; 3032001f49Smrg GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 }; 3132001f49Smrg GLfloat red_mat[] = { 1.0, 0.2, 0.2, 1.0 }; 3232001f49Smrg GLfloat green_mat[] = { 0.2, 1.0, 0.2, 0.5 }; 3332001f49Smrg GLfloat blue_mat[] = { 0.2, 0.2, 1.0, 1.0 }; 3432001f49Smrg GLfloat white_mat[] = { 1.0, 1.0, 1.0, 1.0 }; 3532001f49Smrg GLfloat purple_mat[] = { 1.0, 0.2, 1.0, 1.0 }; 3632001f49Smrg GLUquadricObj *qobj = gluNewQuadric(); 3732001f49Smrg 3832001f49Smrg glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); 3932001f49Smrg glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); 4032001f49Smrg glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); 4132001f49Smrg glLightfv(GL_LIGHT0, GL_POSITION, light_position); 4232001f49Smrg 4332001f49Smrg glEnable(GL_LIGHTING); 4432001f49Smrg glEnable(GL_LIGHT0); 4532001f49Smrg glEnable(GL_DEPTH_TEST); 4632001f49Smrg 4732001f49Smrg glMatrixMode(GL_PROJECTION); 4832001f49Smrg glLoadIdentity(); 4932001f49Smrg glOrtho(-2.5, 2.5, -2.5, 2.5, -10.0, 10.0); 5032001f49Smrg glMatrixMode(GL_MODELVIEW); 5132001f49Smrg 5232001f49Smrg glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); 5332001f49Smrg 5432001f49Smrg glPushMatrix(); 5532001f49Smrg glRotatef(20.0, 1.0, 0.0, 0.0); 5632001f49Smrg 5732001f49Smrg /* red square */ 5832001f49Smrg glPushMatrix(); 5932001f49Smrg glTranslatef(0.0, -0.5, 0.0); 6032001f49Smrg glRotatef(90, 1, 0.5, 0); 6132001f49Smrg glScalef(3, 3, 3); 6232001f49Smrg glDisable(GL_LIGHTING); 6332001f49Smrg glColor4f(1, 0, 0, 0.5); 6432001f49Smrg glBegin(GL_POLYGON); 6532001f49Smrg glVertex2f(-1, -1); 6632001f49Smrg glVertex2f( 1, -1); 6732001f49Smrg glVertex2f( 1, 1); 6832001f49Smrg glVertex2f(-1, 1); 6932001f49Smrg glEnd(); 7032001f49Smrg glEnable(GL_LIGHTING); 7132001f49Smrg glPopMatrix(); 7232001f49Smrg 7332001f49Smrg#if 0 7432001f49Smrg /* green square */ 7532001f49Smrg glPushMatrix(); 7632001f49Smrg glTranslatef(0.0, 0.5, 0.1); 7732001f49Smrg glDisable(GL_LIGHTING); 7832001f49Smrg glColor3f(0, 1, 0); 7932001f49Smrg glBegin(GL_POLYGON); 8032001f49Smrg glVertex2f(-1, -1); 8132001f49Smrg glVertex2f( 1, -1); 8232001f49Smrg glVertex2f( 1, 1); 8332001f49Smrg glVertex2f(-1, 1); 8432001f49Smrg glEnd(); 8532001f49Smrg glEnable(GL_LIGHTING); 8632001f49Smrg glPopMatrix(); 8732001f49Smrg 8832001f49Smrg /* blue square */ 8932001f49Smrg glPushMatrix(); 9032001f49Smrg glTranslatef(0.75, 0.5, 0.3); 9132001f49Smrg glDisable(GL_LIGHTING); 9232001f49Smrg glColor3f(0, 0, 0.5); 9332001f49Smrg glBegin(GL_POLYGON); 9432001f49Smrg glVertex2f(-1, -1); 9532001f49Smrg glVertex2f( 1, -1); 9632001f49Smrg glVertex2f( 1, 1); 9732001f49Smrg glVertex2f(-1, 1); 9832001f49Smrg glEnd(); 9932001f49Smrg glEnable(GL_LIGHTING); 10032001f49Smrg glPopMatrix(); 10132001f49Smrg#endif 10232001f49Smrg 10332001f49Smrg glPushMatrix(); 10432001f49Smrg glTranslatef(-0.75, -0.5, 0.0); 10532001f49Smrg glRotatef(270.0, 1.0, 0.0, 0.0); 10632001f49Smrg glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, green_mat ); 10732001f49Smrg glEnable(GL_BLEND); 10832001f49Smrg glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 10932001f49Smrg gluCylinder(qobj, 1.0, 0.0, 2.0, 16, 1); 11032001f49Smrg glDisable(GL_BLEND); 11132001f49Smrg glPopMatrix(); 11232001f49Smrg 11332001f49Smrg glPushMatrix(); 11432001f49Smrg glTranslatef(0.75, 1.0, 1.0); 11532001f49Smrg glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blue_mat ); 11632001f49Smrg gluSphere(qobj, 1.0, 20, 20); 11732001f49Smrg glPopMatrix(); 11832001f49Smrg 11932001f49Smrg glPopMatrix(); 12032001f49Smrg 12132001f49Smrg /* This is very important!!! 12232001f49Smrg * Make sure buffered commands are finished!!! 12332001f49Smrg */ 12432001f49Smrg glFinish(); 12532001f49Smrg 12632001f49Smrg gluDeleteQuadric(qobj); 12732001f49Smrg 12832001f49Smrg { 12932001f49Smrg GLint r, g, b, a, d; 13032001f49Smrg glGetIntegerv(GL_RED_BITS, &r); 13132001f49Smrg glGetIntegerv(GL_GREEN_BITS, &g); 13232001f49Smrg glGetIntegerv(GL_BLUE_BITS, &b); 13332001f49Smrg glGetIntegerv(GL_ALPHA_BITS, &a); 13432001f49Smrg glGetIntegerv(GL_DEPTH_BITS, &d); 13532001f49Smrg printf("channel sizes: %d %d %d %d\n", r, g, b, a); 13632001f49Smrg printf("depth bits %d\n", d); 13732001f49Smrg } 13832001f49Smrg} 13932001f49Smrg 14032001f49Smrg 14132001f49Smrg 14232001f49Smrgstatic void 14332001f49Smrgwrite_targa(const char *filename, const GLfloat *buffer, int width, int height) 14432001f49Smrg{ 14532001f49Smrg FILE *f = fopen( filename, "w" ); 14632001f49Smrg if (f) { 14732001f49Smrg int i, x, y; 14832001f49Smrg const GLfloat *ptr = buffer; 14932001f49Smrg printf ("osdemo, writing tga file \n"); 15032001f49Smrg fputc (0x00, f); /* ID Length, 0 => No ID */ 15132001f49Smrg fputc (0x00, f); /* Color Map Type, 0 => No color map included */ 15232001f49Smrg fputc (0x02, f); /* Image Type, 2 => Uncompressed, True-color Image */ 15332001f49Smrg fputc (0x00, f); /* Next five bytes are about the color map entries */ 15432001f49Smrg fputc (0x00, f); /* 2 bytes Index, 2 bytes length, 1 byte size */ 15532001f49Smrg fputc (0x00, f); 15632001f49Smrg fputc (0x00, f); 15732001f49Smrg fputc (0x00, f); 15832001f49Smrg fputc (0x00, f); /* X-origin of Image */ 15932001f49Smrg fputc (0x00, f); 16032001f49Smrg fputc (0x00, f); /* Y-origin of Image */ 16132001f49Smrg fputc (0x00, f); 16232001f49Smrg fputc (WIDTH & 0xff, f); /* Image Width */ 16332001f49Smrg fputc ((WIDTH>>8) & 0xff, f); 16432001f49Smrg fputc (HEIGHT & 0xff, f); /* Image Height */ 16532001f49Smrg fputc ((HEIGHT>>8) & 0xff, f); 16632001f49Smrg fputc (0x18, f); /* Pixel Depth, 0x18 => 24 Bits */ 16732001f49Smrg fputc (0x20, f); /* Image Descriptor */ 16832001f49Smrg fclose(f); 16932001f49Smrg f = fopen( filename, "ab" ); /* reopen in binary append mode */ 17032001f49Smrg for (y=height-1; y>=0; y--) { 17132001f49Smrg for (x=0; x<width; x++) { 17232001f49Smrg int r, g, b; 17332001f49Smrg i = (y*width + x) * 4; 17432001f49Smrg r = (int) (ptr[i+0] * 255.0); 17532001f49Smrg g = (int) (ptr[i+1] * 255.0); 17632001f49Smrg b = (int) (ptr[i+2] * 255.0); 17732001f49Smrg if (r > 255) r = 255; 17832001f49Smrg if (g > 255) g = 255; 17932001f49Smrg if (b > 255) b = 255; 18032001f49Smrg fputc(b, f); /* write blue */ 18132001f49Smrg fputc(g, f); /* write green */ 18232001f49Smrg fputc(r, f); /* write red */ 18332001f49Smrg } 18432001f49Smrg } 18532001f49Smrg } 18632001f49Smrg} 18732001f49Smrg 18832001f49Smrg 18932001f49Smrgstatic void 19032001f49Smrgwrite_ppm(const char *filename, const GLfloat *buffer, int width, int height) 19132001f49Smrg{ 19232001f49Smrg const int binary = 0; 19332001f49Smrg FILE *f = fopen( filename, "w" ); 19432001f49Smrg if (f) { 19532001f49Smrg int i, x, y; 19632001f49Smrg const GLfloat *ptr = buffer; 19732001f49Smrg if (binary) { 19832001f49Smrg fprintf(f,"P6\n"); 19932001f49Smrg fprintf(f,"# ppm-file created by osdemo.c\n"); 20032001f49Smrg fprintf(f,"%i %i\n", width,height); 20132001f49Smrg fprintf(f,"255\n"); 20232001f49Smrg fclose(f); 20332001f49Smrg f = fopen( filename, "ab" ); /* reopen in binary append mode */ 20432001f49Smrg for (y=height-1; y>=0; y--) { 20532001f49Smrg for (x=0; x<width; x++) { 20632001f49Smrg int r, g, b; 20732001f49Smrg i = (y*width + x) * 4; 20832001f49Smrg r = (int) (ptr[i+0] * 255.0); 20932001f49Smrg g = (int) (ptr[i+1] * 255.0); 21032001f49Smrg b = (int) (ptr[i+2] * 255.0); 21132001f49Smrg if (r > 255) r = 255; 21232001f49Smrg if (g > 255) g = 255; 21332001f49Smrg if (b > 255) b = 255; 21432001f49Smrg fputc(r, f); /* write red */ 21532001f49Smrg fputc(g, f); /* write green */ 21632001f49Smrg fputc(b, f); /* write blue */ 21732001f49Smrg } 21832001f49Smrg } 21932001f49Smrg } 22032001f49Smrg else { 22132001f49Smrg /*ASCII*/ 22232001f49Smrg int counter = 0; 22332001f49Smrg fprintf(f,"P3\n"); 22432001f49Smrg fprintf(f,"# ascii ppm file created by osdemo.c\n"); 22532001f49Smrg fprintf(f,"%i %i\n", width, height); 22632001f49Smrg fprintf(f,"255\n"); 22732001f49Smrg for (y=height-1; y>=0; y--) { 22832001f49Smrg for (x=0; x<width; x++) { 22932001f49Smrg int r, g, b; 23032001f49Smrg i = (y*width + x) * 4; 23132001f49Smrg r = (int) (ptr[i+0] * 255.0); 23232001f49Smrg g = (int) (ptr[i+1] * 255.0); 23332001f49Smrg b = (int) (ptr[i+2] * 255.0); 23432001f49Smrg if (r > 255) r = 255; 23532001f49Smrg if (g > 255) g = 255; 23632001f49Smrg if (b > 255) b = 255; 23732001f49Smrg fprintf(f, " %3d %3d %3d", r, g, b); 23832001f49Smrg counter++; 23932001f49Smrg if (counter % 5 == 0) 24032001f49Smrg fprintf(f, "\n"); 24132001f49Smrg } 24232001f49Smrg } 24332001f49Smrg } 24432001f49Smrg fclose(f); 24532001f49Smrg } 24632001f49Smrg} 24732001f49Smrg 24832001f49Smrg 24932001f49Smrg 25032001f49Smrgint main( int argc, char *argv[] ) 25132001f49Smrg{ 25232001f49Smrg GLfloat *buffer; 25332001f49Smrg 25432001f49Smrg /* Create an RGBA-mode context */ 25532001f49Smrg#if OSMESA_MAJOR_VERSION * 100 + OSMESA_MINOR_VERSION >= 305 25632001f49Smrg /* specify Z, stencil, accum sizes */ 25732001f49Smrg OSMesaContext ctx = OSMesaCreateContextExt( GL_RGBA, 32, 0, 0, NULL ); 25832001f49Smrg#else 25932001f49Smrg OSMesaContext ctx = OSMesaCreateContext( GL_RGBA, NULL ); 26032001f49Smrg#endif 26132001f49Smrg if (!ctx) { 26232001f49Smrg printf("OSMesaCreateContext failed!\n"); 26332001f49Smrg return 0; 26432001f49Smrg } 26532001f49Smrg 26632001f49Smrg /* Allocate the image buffer */ 26732001f49Smrg buffer = (GLfloat *) malloc( WIDTH * HEIGHT * 4 * sizeof(GLfloat)); 26832001f49Smrg if (!buffer) { 26932001f49Smrg printf("Alloc image buffer failed!\n"); 27032001f49Smrg return 0; 27132001f49Smrg } 27232001f49Smrg 27332001f49Smrg /* Bind the buffer to the context and make it current */ 27432001f49Smrg if (!OSMesaMakeCurrent( ctx, buffer, GL_FLOAT, WIDTH, HEIGHT )) { 27532001f49Smrg printf("OSMesaMakeCurrent failed!\n"); 27632001f49Smrg return 0; 27732001f49Smrg } 27832001f49Smrg 27932001f49Smrg render_image(); 28032001f49Smrg 28132001f49Smrg if (argc>1) { 28232001f49Smrg#ifdef SAVE_TARGA 28332001f49Smrg write_targa(argv[1], buffer, WIDTH, HEIGHT); 28432001f49Smrg#else 28532001f49Smrg write_ppm(argv[1], buffer, WIDTH, HEIGHT); 28632001f49Smrg#endif 28732001f49Smrg } 28832001f49Smrg else { 28932001f49Smrg printf("Specify a filename if you want to make an image file\n"); 29032001f49Smrg } 29132001f49Smrg 29232001f49Smrg printf("all done\n"); 29332001f49Smrg 29432001f49Smrg /* free the image buffer */ 29532001f49Smrg free( buffer ); 29632001f49Smrg 29732001f49Smrg /* destroy the context */ 29832001f49Smrg OSMesaDestroyContext( ctx ); 29932001f49Smrg 30032001f49Smrg return 0; 30132001f49Smrg} 302