Commit 3df76ee1 authored by Edward Vigmond's avatar Edward Vigmond
Browse files

mesalyzer can now be run to process sequences across multiple CPUs by using the --nproc option.

parent 9522ce46
#include <GLee.h>
#include "Frame.h"
#ifdef OSMESA
#include <GL/osmesa.h>
#endif
#define COUT_ERROR(A) if(gle==A)cout<<#A<<endl;
Frame :: Frame( TBmeshWin *t ) : _tbwm(t), _buffer(NULL)
{
}
Frame :: Frame( TBmeshWin *t, int w, int h, string fname ) : _tbwm(t), _buffer(NULL)
{
dump( w, h, fname );
}
Frame :: ~Frame()
{
delete_objs();
}
void
Frame :: delete_objs()
{
#ifdef OSMESA
OSMesaDestroyContext( _ctx );
#else
delete[] _buffer;
glDeleteRenderbuffersEXT(1, &_color_rb);
glDeleteRenderbuffersEXT(1, &_depth_rb);
glDeleteFramebuffersEXT(1, &_fb);
#endif // OSMESA
}
/** output specified frames
*
* \param w output image width
* \param h output image height
* \param fname base file name
* \param f0 first frame number
* \param f1 largest frame = f0+n-1
* \param stride output frame number stride
*
* \note \p fname will have ".png" removed if present and XXXXX.png
* where XXXXX is the frame number
*
* \note the frame numbers written are those which satisfy f0<=n<=f1
*
* \return the number of frames written
*/
int
Frame :: write( int w, int h, string fname, int f0, int f1, int stride )
{
if( !_tbwm->set_time(f0) ) return 0;
if( fname.length()>=4 && (fname.substr(fname.length()-4)==".png") )
fname = fname.substr(0,fname.length()-4);
int numout=0;
for( int f=f0; f<=f1; f+=stride) {
if( !_tbwm->set_time(f) )
break;
string file=fname;
char strnum[8];
sprintf( strnum, "%05d.png", f );
file += strnum;
dump( w, h, file );
numout++;
}
return numout;
}
/** output specified frame
*
* \param w output image width
* \param h output image height
* \param fname file name
* \param f frame number
*
* \note \p fname will have ".png" appended if not present
*/
int
Frame :: write( int w, int h, string fname, int f )
{
if( !_tbwm->set_time(f) ) return 0;
if( fname.length()<4 || (fname.substr(fname.length()-4)!=".png") )
fname+= ".png";
dump( w, h, fname );
return 1;
}
/* dump the frame buffer into a file
*
* \param w
* \param h
* \param fname
*/
void
Frame :: dump( int w, int h, string fname )
{
FILE *out = fopen( fname.c_str(), "w" );
PNGwrite* pngimg = new PNGwrite( out );
pngimg->size( w, h );
pngimg->depth( 8*sizeof(GLubyte) );
if( _tbwm->transBgd() )
pngimg->colour_type( PNG_COLOR_TYPE_RGB_ALPHA );
else
pngimg->colour_type( PNG_COLOR_TYPE_RGB );
if( _buffer==NULL || _w!=w || _h!=h ) { // resize
if( _buffer ) // not first time, destroy old buffers/contexts
delete_objs();
_w = w;
_h = h;
_buffer = new GLubyte[w*h*4];
#ifdef OSMESA
_ctx = OSMesaCreateContext(OSMESA_RGBA, NULL);
if (!OSMesaMakeCurrent(_ctx, _buffer, GL_UNSIGNED_BYTE, w, h)) {
cout << "Failed OSMesaMakeCurrent" << endl;
throw 1;
}
#else
// create new frame buffer object
glGenFramebuffersEXT(1, &_fb);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _fb);
glGenRenderbuffersEXT(1, &_color_rb);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, _color_rb);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA8, w, h );
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_RENDERBUFFER_EXT, _color_rb);
glGenRenderbuffersEXT(1, &_depth_rb);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, _depth_rb);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, w, h );
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, _depth_rb);
GLenum gle=glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
COUT_ERROR(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
COUT_ERROR(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT);
COUT_ERROR(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT);
COUT_ERROR(GL_FRAMEBUFFER_UNSUPPORTED_EXT);
COUT_ERROR(GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT);
COUT_ERROR(GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT);
COUT_ERROR(GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT);
COUT_ERROR(GL_FRAMEBUFFER_UNDEFINED);
COUT_ERROR(GL_FRAMEBUFFER_UNSUPPORTED);
COUT_ERROR(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE);
if( gle!=GL_FRAMEBUFFER_COMPLETE ) {
cout << "aborting:" << gle << endl;
throw 1;
}
#endif //OSMESA
}
#ifdef OSMESA
#else
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _fb);
#endif //OSMESA
_tbwm->invalidate();
_tbwm->draw();
glReadBuffer(GL_BACK);
if( _tbwm->transBgd() )
glReadPixels(0,0,w,h,GL_RGBA,GL_UNSIGNED_BYTE,(GLvoid *)_buffer);
else
glReadPixels(0,0,w,h,GL_RGB,GL_UNSIGNED_BYTE,(GLvoid *)_buffer);
int align;
glGetIntegerv(GL_PACK_ALIGNMENT, &align);
pngimg->write( _buffer, align );
delete pngimg;
#ifdef OSMESA
#else
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // restore the display
#endif //OSMESA
}
#ifndef FRAME_H
#include <string>
#include "TBmeshWin.h"
#include "PNGwrite.h"
#ifdef OSMESA
#include <GL/osmesa.h>
#endif
class Frame {
public:
Frame( TBmeshWin *t );
~Frame();
Frame( TBmeshWin *t, int, int, string );
int write( int, int, string, int );
int write( int, int, string, int, int,int stride=1 );
void dump( int, int, string );
private:
GLubyte* _buffer;
int _w;
int _h;
TBmeshWin *_tbwm;
void delete_objs();
#ifdef OSMESA
OSMesaContext _ctx;
#else
GLuint _fb, _color_rb, _depth_rb;
#endif
};
#endif
......@@ -34,7 +34,7 @@ OBJS = $(FLTK_SOURCES:.fl=.o)\
$(patsubst %.C,%.o,$(wildcard *.C))
#the files in OS_files contain OSMESA dependent clauses
OS_files= main.o TBmeshWin.o
OS_files= main.o Frame.o
OS_OBJS=$(filter-out $(OS_files),$(OBJS)) $(OS_files:.o=_os.o)
all: meshalyzer
......
#include <GLee.h>
#include "trimesh.h"
#include <signal.h>
#include <FL/Fl_File_Chooser.H>
......@@ -10,20 +9,14 @@
# include <GL/glext.h>
#endif
#include "gl2ps.h"
#include "PNGwrite.h"
#ifdef USE_HDF5
#include <ch5/ch5.h>
#endif
//#define OSMESA
#ifdef OSMESA
#include <GL/osmesa.h>
#endif
#include "Frame.h"
#define HITBUFSIZE 10000
#define OPAQUE_LIMIT 0.95 //!< consider opaque if alpha level above this
#define MAX_SURFELE_REALTIME 400000 //!< max \#ele's to draw while moving
#define COUT_ERROR(A) if(gle==A)cout<<#A<<endl;
unsigned int TBmeshWin::MAX_MESSAGES_READ = 100;
......@@ -39,132 +32,6 @@ void translucency( bool b );
int intcomp( const void *a, const void *b );
/* dump the frame buffer into a file
*
* \param fname
* \param w
* \param h
* \param tbwm
*/
void write_frame( string fname, int w, int h, TBmeshWin *tbwm )
{
#ifdef ONSCREEN_DUMP
GLubyte* buffer = new GLubyte[4*w*h];
#else
static GLubyte* buffer;
static int oldw=-1, oldh;
#ifdef OSMESA
static OSMesaContext ctx;
#else
static GLuint fb, color_rb, depth_rb, textureId;
#endif //OSMESA
#endif //ONSCREEN_DUMP
FILE *out = fopen( fname.c_str(), "w" );
PNGwrite* pngimg = new PNGwrite( out );
pngimg->size( w, h );
pngimg->depth( 8*sizeof(GLubyte) );
if( tbwm->transBgd() )
pngimg->colour_type( PNG_COLOR_TYPE_RGB_ALPHA );
else
pngimg->colour_type( PNG_COLOR_TYPE_RGB );
#ifndef ONSCREEN_DUMP
if( oldw==-1 || oldw!=w || oldh!=h ) { // resize
if( oldw != -1 ) { // not first time, destroy old buffers/contexts
#ifdef OSMESA
OSMesaDestroyContext( ctx );
#else
delete[] buffer;
glDeleteRenderbuffersEXT(1, &color_rb);
glDeleteRenderbuffersEXT(1, &depth_rb);
glDeleteFramebuffersEXT(1, &fb);
#endif // OSMESA
}
oldw = w;
oldh = h;
#ifdef OSMESA
ctx = OSMesaCreateContext(OSMESA_RGBA, NULL);
buffer = new GLubyte[w*h*4];
if (!OSMesaMakeCurrent(ctx, buffer, GL_UNSIGNED_BYTE, w, h)) {
cout << "Failed OSMesaMakeCurrent" << endl;
exit(1);
}
#else
// create new frame buffer object
buffer = new GLubyte[w*h*4];
glGenFramebuffersEXT(1, &fb);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
glGenRenderbuffersEXT(1, &color_rb);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, color_rb);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA8, w, h );
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_RENDERBUFFER_EXT, color_rb);
glGenRenderbuffersEXT(1, &depth_rb);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_rb);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, w, h );
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, depth_rb);
GLenum gle=glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
COUT_ERROR(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
COUT_ERROR(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT);
COUT_ERROR(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT);
COUT_ERROR(GL_FRAMEBUFFER_UNSUPPORTED_EXT);
COUT_ERROR(GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT);
COUT_ERROR(GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT);
COUT_ERROR(GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT);
COUT_ERROR(GL_FRAMEBUFFER_UNDEFINED);
COUT_ERROR(GL_FRAMEBUFFER_UNSUPPORTED);
COUT_ERROR(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE);
if( gle!=GL_FRAMEBUFFER_COMPLETE ) {
cout << "aborting:" << gle << endl;
return;
}
#endif //OSMESA
}
#ifdef OSMESA
#else
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
#endif //OSMESA
tbwm->invalidate();
tbwm->draw();
#endif // ONSCREEN_DUMP
glReadBuffer(GL_BACK);
if( tbwm->transBgd() )
glReadPixels(0,0,w,h,GL_RGBA,GL_UNSIGNED_BYTE,(GLvoid *)buffer);
else
glReadPixels(0,0,w,h,GL_RGB,GL_UNSIGNED_BYTE,(GLvoid *)buffer);
int align;
glGetIntegerv(GL_PACK_ALIGNMENT, &align);
pngimg->write( buffer, align );
delete pngimg;
#ifdef ONSCREEN_DUMP
delete[] buffer;
#else
#ifdef OSMESA
#else
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // restore the display
#endif //OSMESA
#endif //ONSCREEN_DUMP
}
int intcomp( const void *a, const void *b )
{
if ( *((int *)a) < *((int *)b) )
......@@ -1161,6 +1028,7 @@ void TBmeshWin::output_png( const char* fn, Sequence *seqwidget )
int update_period = 5; // number of frames after which to update progress
int last_update=tm-update_period-10;
int frameskip=int(contwin->frameskip->value());
Frame frame( this );
for ( ; tm<=stop; tm+=frameskip ) {
if( model->pt.num_tm() ) model->pt.time(tm);//dynamic points
......@@ -1185,7 +1053,7 @@ void TBmeshWin::output_png( const char* fn, Sequence *seqwidget )
redraw();
Fl::check();
Fl::flush();
write_frame( foutname, w(), h(), this );
frame.dump( w(), h(), foutname );
}
if ( sequence )
seqwidget->movieprog->label("100%");
......@@ -1652,6 +1520,7 @@ void TBmeshWin::record_events( char* fn )
unsigned long old_framenum=framenum;
int num=0;
Frame frame( this );
while ( recording ) {
Fl::wait(); // process events one at a time
if ( old_framenum != framenum ) { // see if the draw routine has been called
......@@ -1662,7 +1531,7 @@ void TBmeshWin::record_events( char* fn )
char fnum[32];
sprintf( fnum, "%05d", num++ );
fname = fname + fnum + ".png";
write_frame( fname, w(), h(), this );
frame.dump( w(), h(), fname );
}
}
ostringstream msg;
......
......@@ -12,6 +12,8 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include "Frame.h"
#include <unistd.h>
#ifdef USE_HDF5
#include <hdf5.h>
#include <ch5/ch5.h>
......@@ -24,7 +26,6 @@
static Controls *ctrl_ptr;
static Meshwin *win_ptr;
void write_frame( string fname, int w, int h, TBmeshWin *tbwm );
sem_t *meshProcSem; // global semaphore for temporal linking
sem_t *linkingProcSem; // global semaphore for process linking
......@@ -35,6 +36,7 @@ sem_t *linkingProcSem; // global semaphore for process linking
else \
control.A##hi->deactivate();
/** animate in response to a signal received: SIGUSR1 for forward,
* SIGUSR2 for backward
*
......@@ -106,9 +108,10 @@ read_version_info( Fl_Text_Display *txt )
* \param size image width/height
*/
void
os_png_seq( string filename, int f0, int numf, TBmeshWin *tbwm, int size )
os_png_seq( string filename, int f0, int numf, TBmeshWin *tbwm, int size, int nproc )
{
#ifndef OSMESA
// need to create an OpenGL context
int argc = 1;
char *argv = strdup("-iconic");
glutInit(&argc, &argv);
......@@ -119,39 +122,67 @@ os_png_seq( string filename, int f0, int numf, TBmeshWin *tbwm, int size )
// determine first and last frame numbers
if( f0<0 )
f0 = tbwm->time();
int f1 = f0 + numf - 1;
int f1 = f0+numf-1;
// strip ".png" from file name if present
if( filename.length()>4 && (filename.substr(filename.length()-4)==".png") )
filename.erase(filename.length()-4);
// output sequence into a directory and frame to a file
// output sequence into a directory which we may need to create
if( numf>1 ) {
tbwm->transBgd(false);
if( mkdir( filename.c_str(), 0744 )==-1 && errno!=EEXIST ) {
cerr << "Exiting: Cannot create directory "<<filename<<endl;
exit(1);
}
} else {
filename += ".png";
filename += "/frame"; // base name for images
}
tbwm->resize(0,0,size,size);
Frame frame( tbwm );
while( f0<=f1 && tbwm->set_time( f0 ) ){
string fname = filename;
if( numf>1 ) {
char strnum[8];
sprintf( strnum, "/frame%05d.png", f0 );
fname += strnum;
if( numf==1 ) {
frame.write( size, size, filename, f0 );
} else {
#ifdef OSMESA
// create 2 semaphores needed for interprocess communication
stringstream nw_name("/nw_");
nw_name << getpid();
stringstream fini_name("/fini_");
fini_name << getpid();
sem_t *finished = sem_open( fini_name.str().c_str(), O_CREAT, S_IRWXU, 0 );
sem_t *nw_cnt = sem_open( nw_name.str().c_str(), O_CREAT, S_IRWXU, 0 );
// fork since it is too difficult to copy tbwm with all of its dynamic allocations
for( int i=1; i<nproc;i++ ) {
if( !fork() ) {
f0 += i;
break;
}
}
int nw = frame.write( size, size, filename, f0, f1, nproc );
for( int a=0; a<nw; a++ )
sem_post( nw_cnt );
sem_post( finished );
// wait for everyone to finish and count the number of frames written
int nfin;
sem_getvalue( finished, &nfin );
if( nfin==nproc ) {
sem_getvalue( nw_cnt, &nw );
if( nw != numf )
cerr << "\nOnly " << nw << " of " << numf << " frames written\n" << endl;
sem_unlink(nw_name.str().c_str() );
sem_unlink(fini_name.str().c_str() );
}
write_frame( fname.c_str(), size, size, tbwm );
f0++;
}
// check if all frames output
if( f0<=f1 )
cerr << "Warning: "<< f1-f0+1 << " frames of " << numf << " requested not written" << endl;
#else
int nw = frame.write( size, size, filename, f0, f1 );
if( nw != numf )
cerr << "Only " << nw << " of " << numf << " frames written" << endl;
#endif
}
exit(0);
}
......@@ -275,6 +306,7 @@ print_usage(void)
cout << "--frame=file first frame for PNG dump (-1=do not set)" << endl;
cout << "--numframe=num number of frames to output (default=1)" << endl;
cout << "--size=num output size of PNG in pixels (default=512)" << endl;
cout << "--nproc=num #parallel procs for PNG sequences" << endl;
exit(0);
}
......@@ -283,12 +315,13 @@ static struct option longopts[] = {
{ "iconifycontrols", no_argument, NULL, 'i' },
{ "no_elem" , no_argument, NULL, 'n' },
{ "help" , no_argument, NULL, 'h' },
{ "thrdRdr" , no_argument, NULL, 't' },
{ "gpoupID" , 1 , NULL, 'g' },
{ "PNGfile" , 1 , NULL, 'P' },
{ "frame" , 1 , NULL, 'f' },
{ "numframe" , 1 , NULL, 'N' },
{ "size" , 1 , NULL, 's' },
{ "thrdRdr" , no_argument, NULL, 't' },
{ "nproc" , 1 , NULL, 'p' },
{ NULL , 0 , NULL, 0 }
};
......@@ -301,7 +334,6 @@ main( int argc, char *argv[] )
H5Eset_auto1(NULL, NULL);// silence HDF errors
#endif
bool iconcontrols = false;
bool no_elems = false;
bool threadedReader = false;
......@@ -310,6 +342,7 @@ main( int argc, char *argv[] )
const char *grpID = "0";
int frame0 = -1,
numframe = 1;
int nproc = 1;
int ch;
while( (ch=getopt_long(argc, argv, "inhg:", longopts, NULL)) != -1 )
......@@ -335,6 +368,9 @@ main( int argc, char *argv[] )
case 'f':
frame0 = atoi(optarg);
break;
case 'p':
nproc = atoi(optarg);
break;
case 't':
threadedReader = true;
break;
......@@ -473,10 +509,11 @@ main( int argc, char *argv[] )
if (linkingProcSem == SEM_FAILED)
cerr << "Message Queue inter-process communication not possible"
<< endl;
// just output images, no interaction
if( PNGfile )
os_png_seq( PNGfile, frame0, numframe, win.trackballwin, pngsize );
os_png_seq( PNGfile, frame0, numframe, win.trackballwin, pngsize, nproc );
Fl::run();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment