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 >
Wrap
C/C++ Source or Header
|
1999-08-18
|
6KB
|
233 lines
/*
* mt_osdemo.c
*
* Demo of off-screen Mesa rendering with multithreading support .
*
* IMPORTANT NOTE: The code in this file is in alpha stage. It is used
* as an example how multithreaded programming with Mesa could look
* like. YOU MUST HAVE COMPILED THE MESA WITH POSIX THREADS SUPPORT TO
* COMPILE AND RUN THIS DEMO! - poliwoda@volumegraphics.com
*
* The original "osdemo" by Brian Paul can be found in "../demos"
*
* See Mesa/include/GL/osmesa.h for documentation of the OSMesa functions.
*
* If you want to render BIG images you'll probably have to increase
* MAX_WIDTH and MAX_HEIGHT in src/config.h.
*
* This program is in the public domain.
*
* Brian Paul
*
* modified for multithread usage by Christop Poliwoda (poliwoda@volumegraphics.com)
* PPM output provided by Joerg Schmalzl.
* ASCII PPM output added by Brian Paul.
*
*/
#ifndef THREADS
#ifndef PTHREADS
#error This code compiles and runs with POSIX threads support only. \
Compile the Mesa and this demo as threaded version.
#endif
#endif
#include <stdio.h>
#include <stdlib.h>
#include "GL/osmesa.h"
#include "GL/glut.h"
#include <pthread.h> /* POSIX thread interface */
#include <time.h> /* for time measurements, maybe non-portable */
#define WIDTH 512
#define HEIGHT 512
#define REPETITIONS 4
#define MAXTHREADS 4
void * buffers[MAXTHREADS]; /* these are the different result buffers */
OSMesaContext ctx[MAXTHREADS]; /* and these the used contexts */
/*
* Timer code...
*/
static struct timeval starttime, endtime;
static struct timezone tz;
static void timerstart(void) {
gettimeofday(&starttime, &tz);
}
static void timerstop(void) {
gettimeofday(&endtime, &tz);
}
static float timertime(void) {
double ttime, start, end;
start = (starttime.tv_sec+1.0*starttime.tv_usec / 1000000.0);
end = (endtime.tv_sec+1.0*endtime.tv_usec / 1000000.0);
ttime = end - start;
return ttime;
}
/*
* renders an image with 3 teapots, colorized in red, green, blue
*/
static void render_image( void ) {
GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 };
GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };
GLfloat red_mat[] = { 1.0, 0.2, 0.2, 1.0 };
GLfloat green_mat[] = { 0.2, 1.0, 0.2, 1.0 };
GLfloat blue_mat[] = { 0.2, 0.2, 1.0, 1.0 };
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-2.5, 2.5, -2.5, 2.5, -10.0, 10.0);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glRotatef(20.0, 1.0, 0.0, 0.0);
glPushMatrix();
glTranslatef(-0.75, 0.5, 0.0);
glRotatef(90.0, 1.0, 0.0, 0.0);
glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red_mat );
glutSolidTeapot(1.5);
glPopMatrix();
glPopMatrix();
glPushMatrix();
glRotatef(20.0, 1.0, 0.0, 0.0);
glPushMatrix();
glTranslatef(-0.75, -0.5, 0.0);
glRotatef(270.0, 1.0, 0.0, 0.0);
glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, green_mat );
glutSolidTeapot(1.0);
glPopMatrix();
glPopMatrix();
glPushMatrix();
glRotatef(20.0, 1.0, 0.0, 0.0);
glPushMatrix();
glTranslatef(0.75, 0.0, -1.0);
glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blue_mat );
glutSolidTeapot(1.0);
glPopMatrix();
glPopMatrix();
glFinish();
}
/*
* Do rendering for a thread.
*/
static void * thread_function(void * threadNr) {
int i = (int)threadNr;
OSMesaMakeCurrent(ctx[i], buffers[i], GL_UNSIGNED_BYTE, WIDTH, HEIGHT);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
render_image();
return NULL;
}
int main( int argc, char *argv[] ) {
pthread_t threads[MAXTHREADS];
int i, k;
int p, x, y;
FILE *f;
GLubyte *ptr;
#ifdef __sun
thr_setconcurrency(MAXTHREADS);
#endif
for (i=0; i<MAXTHREADS; i++) {
/* create the OS Mesa contexts and result buffers */
ctx[i] = OSMesaCreateContext( GL_RGBA, NULL );
buffers[i] = malloc(WIDTH * HEIGHT * 4);
}
/* to compare rendering time, we do a single threaded rendering pass */
printf("Main thread rendering %d %dx%d-images (no threads)...\n",
MAXTHREADS*REPETITIONS, WIDTH, HEIGHT);
fflush(stdout);
timerstart();
for (k=0; k<REPETITIONS; k++) {
for (i=0; i<MAXTHREADS; i++) {
thread_function((void*)i);
}
}
timerstop();
printf("Single thread runtime: %6.2f seconds\n\n", timertime());
/* now we run the multithreaded code */
printf("%d threads rendering %d %dx%d-images (multithreaded)...\n",
MAXTHREADS, MAXTHREADS*REPETITIONS, WIDTH, HEIGHT);
fflush(stdout);
timerstart();
for (k=0; k<REPETITIONS; k++) {
for (i=0; i<MAXTHREADS; i++) {
pthread_create(&threads[i], NULL, thread_function, (void*)i);
}
for (i=0; i<MAXTHREADS; i++) {
pthread_join(threads[i], NULL); /* wait for threads to finish */
}
}
timerstop();
printf("Multithreaded runtime: %6.2f seconds\n\n", timertime());
for (i=0; i<MAXTHREADS; i++) {
/* write PPM (binary) file */
if ((argc>i+1) &&
(f = fopen( argv[i+1], "w" ))) {
printf("write buffer #%d to file %s\n", i, argv[i+1]);
ptr = (GLubyte *) buffers[i];
fprintf(f,"P6\n");
fprintf(f,"# ppm-file created by %s\n", argv[0]);
fprintf(f,"%i %i\n", WIDTH,HEIGHT);
fprintf(f,"255\n");
fclose(f);
f = fopen( argv[i+1], "ab" ); /* reopen in binary append mode */
for (y=HEIGHT-1; y>=0; y--) {
for (x=0; x<WIDTH; x++) {
p = (y*WIDTH + x) * 4;
fputc(ptr[p], f); /* write red */
fputc(ptr[p+1], f); /* write green */
fputc(ptr[p+2], f); /* write blue */
}
}
fclose(f);
}
/* destroy OS Mesa contexts and result buffers */
OSMesaDestroyContext(ctx[i]);
free(buffers[i]);
}
printf("\nall done.\n");
return 0;
}