home *** CD-ROM | disk | FTP | other *** search
/ Amiga Magazin: Amiga-CD 2000 April & May / AMIGA_2000_04.iso / patches / mesa3.1 / mtdemos / mt_osdemo.c < prev    next >
C/C++ Source or Header  |  1999-08-18  |  6KB  |  233 lines

  1. /* 
  2.  * mt_osdemo.c 
  3.  *
  4.  * Demo of off-screen Mesa rendering with multithreading support .
  5.  * 
  6.  * IMPORTANT NOTE: The code in this file is in alpha stage. It is used
  7.  * as an example how multithreaded programming with Mesa could look
  8.  * like. YOU MUST HAVE COMPILED THE MESA WITH POSIX THREADS SUPPORT TO
  9.  * COMPILE AND RUN THIS DEMO! - poliwoda@volumegraphics.com
  10.  *
  11.  * The original "osdemo" by Brian Paul can be found in "../demos"
  12.  *
  13.  * See Mesa/include/GL/osmesa.h for documentation of the OSMesa functions.
  14.  *
  15.  * If you want to render BIG images you'll probably have to increase
  16.  * MAX_WIDTH and MAX_HEIGHT in src/config.h.
  17.  *
  18.  * This program is in the public domain.
  19.  *
  20.  * Brian Paul
  21.  *
  22.  * modified for multithread usage by Christop Poliwoda (poliwoda@volumegraphics.com) 
  23.  * PPM output provided by Joerg Schmalzl.
  24.  * ASCII PPM output added by Brian Paul.
  25.  *
  26.  */
  27.  
  28. #ifndef THREADS
  29. #ifndef PTHREADS
  30. #error This code compiles and runs with POSIX threads support only. \
  31. Compile the Mesa and this demo as threaded version.
  32. #endif
  33. #endif
  34.  
  35. #include <stdio.h>
  36. #include <stdlib.h>
  37. #include "GL/osmesa.h"
  38. #include "GL/glut.h"
  39.  
  40. #include <pthread.h>            /* POSIX thread interface */
  41. #include <time.h>               /* for time measurements, maybe non-portable */
  42.  
  43. #define WIDTH 512
  44. #define HEIGHT 512
  45. #define REPETITIONS 4
  46. #define MAXTHREADS 4
  47.  
  48. void * buffers[MAXTHREADS];    /* these are the different result buffers */
  49. OSMesaContext ctx[MAXTHREADS];    /* and these the used contexts */
  50.  
  51. /*
  52.  * Timer code...
  53.  */
  54. static struct timeval starttime, endtime;
  55. static struct timezone tz;
  56.  
  57. static void timerstart(void) {
  58.   gettimeofday(&starttime, &tz);
  59. }
  60.  
  61. static void timerstop(void) {
  62.   gettimeofday(&endtime, &tz);
  63. }
  64.  
  65. static float timertime(void) {
  66.   double ttime, start, end;
  67.  
  68.   start = (starttime.tv_sec+1.0*starttime.tv_usec / 1000000.0);
  69.     end = (endtime.tv_sec+1.0*endtime.tv_usec / 1000000.0);
  70.   ttime = end - start;
  71.  
  72.   return ttime;
  73. }
  74.  
  75. /*
  76.  * renders an image with 3 teapots, colorized in red, green, blue 
  77.  */
  78. static void render_image( void ) {
  79.    GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 };
  80.    GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
  81.    GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
  82.    GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };
  83.    GLfloat red_mat[]   = { 1.0, 0.2, 0.2, 1.0 };
  84.    GLfloat green_mat[] = { 0.2, 1.0, 0.2, 1.0 };
  85.    GLfloat blue_mat[]  = { 0.2, 0.2, 1.0, 1.0 };
  86.  
  87.    glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
  88.    glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
  89.    glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
  90.    glLightfv(GL_LIGHT0, GL_POSITION, light_position);
  91.     
  92.    glEnable(GL_LIGHTING);
  93.    glEnable(GL_LIGHT0);
  94.    glEnable(GL_DEPTH_TEST);
  95.  
  96.    glMatrixMode(GL_PROJECTION);
  97.    glLoadIdentity();
  98.    glOrtho(-2.5, 2.5, -2.5, 2.5, -10.0, 10.0);
  99.    glMatrixMode(GL_MODELVIEW);
  100.  
  101.    glPushMatrix();
  102.    glRotatef(20.0, 1.0, 0.0, 0.0);
  103.  
  104.    glPushMatrix();
  105.    glTranslatef(-0.75, 0.5, 0.0); 
  106.    glRotatef(90.0, 1.0, 0.0, 0.0);
  107.    glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red_mat );
  108.    glutSolidTeapot(1.5);
  109.    glPopMatrix();
  110.    glPopMatrix();
  111.  
  112.    glPushMatrix();
  113.    glRotatef(20.0, 1.0, 0.0, 0.0);
  114.  
  115.    glPushMatrix();
  116.    glTranslatef(-0.75, -0.5, 0.0); 
  117.    glRotatef(270.0, 1.0, 0.0, 0.0);
  118.    glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, green_mat );
  119.    glutSolidTeapot(1.0);
  120.    glPopMatrix();
  121.    glPopMatrix();
  122.  
  123.    glPushMatrix();
  124.    glRotatef(20.0, 1.0, 0.0, 0.0);
  125.  
  126.    glPushMatrix();
  127.    glTranslatef(0.75, 0.0, -1.0); 
  128.    glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blue_mat );
  129.    glutSolidTeapot(1.0);
  130.    glPopMatrix();
  131.    glPopMatrix();
  132.  
  133.    glFinish();
  134. }
  135.  
  136.  
  137. /* 
  138.  * Do rendering for a thread.
  139.  */
  140. static void * thread_function(void * threadNr) {
  141.  
  142.   int i = (int)threadNr;
  143.  
  144.   OSMesaMakeCurrent(ctx[i], buffers[i], GL_UNSIGNED_BYTE, WIDTH, HEIGHT);
  145.   glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
  146.   render_image();
  147.  
  148.   return NULL;
  149. }
  150.  
  151.  
  152.  
  153. int main( int argc, char *argv[] ) {
  154.   pthread_t threads[MAXTHREADS]; 
  155.   int i, k;
  156.   int p, x, y;
  157.   FILE *f;
  158.   GLubyte *ptr;
  159.  
  160. #ifdef __sun
  161.   thr_setconcurrency(MAXTHREADS);
  162. #endif
  163.  
  164.   for (i=0; i<MAXTHREADS; i++) {
  165.     /* create the OS Mesa contexts and result buffers */
  166.     ctx[i] = OSMesaCreateContext( GL_RGBA, NULL );
  167.     buffers[i] = malloc(WIDTH * HEIGHT * 4);
  168.   }
  169.  
  170.   /* to compare rendering time, we do a single threaded rendering pass */
  171.   printf("Main thread rendering %d %dx%d-images (no threads)...\n", 
  172.          MAXTHREADS*REPETITIONS, WIDTH, HEIGHT); 
  173.   fflush(stdout);
  174.  
  175.   timerstart();
  176.   for (k=0; k<REPETITIONS; k++) {
  177.     for (i=0; i<MAXTHREADS; i++) {
  178.       thread_function((void*)i); 
  179.     }
  180.   }
  181.   timerstop();
  182.   printf("Single thread runtime: %6.2f seconds\n\n", timertime());
  183.  
  184.  
  185.   /* now we run the multithreaded code */
  186.   printf("%d threads rendering %d %dx%d-images (multithreaded)...\n", 
  187.          MAXTHREADS, MAXTHREADS*REPETITIONS, WIDTH, HEIGHT); 
  188.   fflush(stdout);
  189.  
  190.   timerstart();
  191.   for (k=0; k<REPETITIONS; k++) {
  192.     for (i=0; i<MAXTHREADS; i++) {
  193.       pthread_create(&threads[i], NULL, thread_function, (void*)i);
  194.     }
  195.     for (i=0; i<MAXTHREADS; i++) {
  196.       pthread_join(threads[i], NULL);  /* wait for threads to finish */
  197.     }
  198.   }
  199.   timerstop();
  200.   printf("Multithreaded runtime: %6.2f seconds\n\n", timertime());
  201.  
  202.   for (i=0; i<MAXTHREADS; i++) {
  203.     /* write PPM (binary) file */
  204.     if ((argc>i+1) &&
  205.     (f = fopen( argv[i+1], "w" ))) {
  206.       printf("write buffer #%d to file %s\n", i, argv[i+1]);
  207.       ptr = (GLubyte *) buffers[i];
  208.       fprintf(f,"P6\n");
  209.       fprintf(f,"# ppm-file created by %s\n",  argv[0]);
  210.       fprintf(f,"%i %i\n", WIDTH,HEIGHT);
  211.       fprintf(f,"255\n");
  212.       fclose(f);
  213.       f = fopen( argv[i+1], "ab" );  /* reopen in binary append mode */
  214.       for (y=HEIGHT-1; y>=0; y--) {
  215.     for (x=0; x<WIDTH; x++) {
  216.       p = (y*WIDTH + x) * 4;
  217.       fputc(ptr[p], f);   /* write red */
  218.       fputc(ptr[p+1], f); /* write green */
  219.       fputc(ptr[p+2], f); /* write blue */
  220.     }
  221.       }
  222.       fclose(f);
  223.     }
  224.     /* destroy OS Mesa contexts and result buffers */
  225.     OSMesaDestroyContext(ctx[i]);
  226.     free(buffers[i]);
  227.   }
  228.  
  229.   printf("\nall done.\n");
  230.  
  231.   return 0;
  232. }
  233.