Ignore:
Timestamp:
Dec 18, 2014 5:45:38 PM (9 years ago)
Author:
ldelgass
Message:

Add command line options to set I/O file descriptors, merge some refactoring to
prep for merging threading support.

Location:
nanovis/branches/1.1
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • nanovis/branches/1.1

  • nanovis/branches/1.1/nanovis.cpp

    r4820 r4874  
    1616 */
    1717
    18 #include <assert.h>
    19 #include <errno.h>
    20 #include <fcntl.h>
    21 #include <getopt.h>
    22 #include <memory.h>
    23 #include <signal.h>
    24 #include <sys/resource.h>
    25 #include <sys/stat.h>
    2618#include <sys/time.h>
    27 #include <sys/times.h>
    2819#include <sys/types.h>
    29 #include <sys/uio.h> // for readv/writev
    30 #include <time.h>
     20#include <sys/uio.h> // for writev in ppmWrite
    3121#include <unistd.h>
    3222
     23#include <cassert>
    3324#include <cstdlib>
    3425#include <cstdio>
     
    3627#include <cmath>
    3728
    38 #include <iostream>
    39 #include <fstream>
    40 #include <sstream>
    4129#include <string>
    4230
     
    4432#include <GL/glut.h>
    4533
    46 #include <RpEncode.h>
    47 
    4834#include <graphics/RenderContext.h>
    4935#include <vrmath/Vector3f.h>
     
    5743#include "config.h"
    5844#include "nanovis.h"
     45#include "nanovisServer.h"
    5946#include "define.h"
    6047
     
    6653#include "NvShader.h"
    6754#include "NvLIC.h"
    68 #include "NvZincBlendeReconstructor.h"
    6955#include "PlaneRenderer.h"
    7056#include "Switch.h"
    7157#include "Trace.h"
     58#include "TransferFunction.h"
    7259#include "Unirect.h"
    7360#include "VelocityArrowsSlice.h"
    7461#include "VolumeInterpolator.h"
    7562#include "VolumeRenderer.h"
    76 #include "ZincBlendeVolume.h"
    77 
     63
     64using namespace nv;
    7865using namespace nv::graphics;
    7966using namespace nv::util;
     
    8976// STATIC MEMBER DATA
    9077
    91 FILE *NanoVis::stdin = NULL;
    92 FILE *NanoVis::logfile = NULL;
    93 FILE *NanoVis::recfile = NULL;
    94 
    95 NanoVis::Stats NanoVis::stats;
    96 int NanoVis::statsFile = -1;
     78Tcl_Interp *NanoVis::interp = NULL;
    9779
    9880unsigned int NanoVis::flags = 0;
     
    10587unsigned char *NanoVis::screenBuffer = NULL;
    10688Texture2D *NanoVis::legendTexture = NULL;
    107 Grid *NanoVis::grid = NULL;
    10889Fonts *NanoVis::fonts;
    10990int NanoVis::updir = Y_POS;
     
    132113NvLIC *NanoVis::licRenderer = NULL;
    133114PlaneRenderer *NanoVis::planeRenderer = NULL;
    134 
    135 Tcl_Interp *NanoVis::interp;
     115Grid *NanoVis::grid = NULL;
    136116
    137117// Image based flow visualization slice location
     
    210190        flags |= REDRAW_PENDING;
    211191    }
    212 }
    213 
    214 #ifdef KEEPSTATS
    215 
    216 #ifndef STATSDIR
    217 #define STATSDIR        "/var/tmp/visservers"
    218 #endif  /*STATSDIR*/
    219 
    220 int
    221 NanoVis::getStatsFile(Tcl_Obj *objPtr)
    222 {
    223     Tcl_DString ds;
    224     char fileName[33];
    225     char pidstr[200];
    226     const char *path;
    227     md5_state_t state;
    228     md5_byte_t digest[16];
    229     char *string;
    230     int length;
    231 
    232     if ((objPtr == NULL) || (statsFile >= 0)) {
    233         return statsFile;
    234     }
    235     /* By itself the client's key/value pairs aren't unique.  Add in the
    236      * process id of this render server. */
    237     sprintf(pidstr, "%ld", (long)stats.pid);
    238 
    239     /* Create an md5 hash of the key/value pairs and use it as the file name. */
    240     string = Tcl_GetStringFromObj(objPtr, &length);
    241     md5_init(&state);
    242     md5_append(&state, (const md5_byte_t *)string, strlen(string));
    243     md5_append(&state, (const md5_byte_t *)pidstr, strlen(pidstr));
    244     md5_finish(&state, digest);
    245     for (int i = 0; i < 16; i++) {
    246         sprintf(fileName + i * 2, "%02x", digest[i]);
    247     }
    248     Tcl_DStringInit(&ds);
    249     Tcl_DStringAppend(&ds, STATSDIR, -1);
    250     Tcl_DStringAppend(&ds, "/", 1);
    251     Tcl_DStringAppend(&ds, fileName, 32);
    252     path = Tcl_DStringValue(&ds);
    253 
    254     statsFile = open(path, O_EXCL | O_CREAT | O_WRONLY, 0600);
    255     Tcl_DStringFree(&ds);
    256     if (statsFile < 0) {
    257         ERROR("can't open \"%s\": %s", fileName, strerror(errno));
    258         return -1;
    259     }
    260     return statsFile;
    261 }
    262 
    263 int
    264 NanoVis::writeToStatsFile(int f, const char *s, size_t length)
    265 {
    266     if (f >= 0) {
    267         ssize_t numWritten;
    268 
    269         numWritten = write(f, s, length);
    270         if (numWritten == (ssize_t)length) {
    271             close(dup(f));
    272         }
    273     }
    274     return 0;
    275 }
    276 
    277 static int
    278 serverStats(int code)
    279 {
    280     double start, finish;
    281     char buf[BUFSIZ];
    282     Tcl_DString ds;
    283     int result;
    284 
    285     {
    286         struct timeval tv;
    287 
    288         /* Get ending time.  */
    289         gettimeofday(&tv, NULL);
    290         finish = CVT2SECS(tv);
    291         tv = NanoVis::stats.start;
    292         start = CVT2SECS(tv);
    293     }
    294     /*
    295      * Session information:
    296      *   - Name of render server
    297      *   - Process ID
    298      *   - Hostname where server is running
    299      *   - Start date of session
    300      *   - Start date of session in seconds
    301      *   - Number of frames returned
    302      *   - Number of bytes total returned (in frames)
    303      *   - Number of commands received
    304      *   - Total elapsed time of all commands
    305      *   - Total elapsed time of session
    306      *   - Exit code of vizserver
    307      *   - User time
    308      *   - System time
    309      *   - User time of children
    310      *   - System time of children
    311      */
    312 
    313     Tcl_DStringInit(&ds);
    314    
    315     Tcl_DStringAppendElement(&ds, "render_stop");
    316     /* renderer */
    317     Tcl_DStringAppendElement(&ds, "renderer");
    318     Tcl_DStringAppendElement(&ds, "nanovis");
    319     /* pid */
    320     Tcl_DStringAppendElement(&ds, "pid");
    321     sprintf(buf, "%d", NanoVis::stats.pid);
    322     Tcl_DStringAppendElement(&ds, buf);
    323     /* host */
    324     Tcl_DStringAppendElement(&ds, "host");
    325     gethostname(buf, BUFSIZ-1);
    326     buf[BUFSIZ-1] = '\0';
    327     Tcl_DStringAppendElement(&ds, buf);
    328     /* date */
    329     Tcl_DStringAppendElement(&ds, "date");
    330     strcpy(buf, ctime(&NanoVis::stats.start.tv_sec));
    331     buf[strlen(buf) - 1] = '\0';
    332     Tcl_DStringAppendElement(&ds, buf);
    333     /* date_secs */
    334     Tcl_DStringAppendElement(&ds, "date_secs");
    335     sprintf(buf, "%ld", NanoVis::stats.start.tv_sec);
    336     Tcl_DStringAppendElement(&ds, buf);
    337     /* num_frames */
    338     Tcl_DStringAppendElement(&ds, "num_frames");
    339     sprintf(buf, "%lu", (unsigned long)NanoVis::stats.nFrames);
    340     Tcl_DStringAppendElement(&ds, buf);
    341     /* frame_bytes */
    342     Tcl_DStringAppendElement(&ds, "frame_bytes");
    343     sprintf(buf, "%lu", (unsigned long)NanoVis::stats.nBytes);
    344     Tcl_DStringAppendElement(&ds, buf);
    345     /* num_commands */
    346     Tcl_DStringAppendElement(&ds, "num_commands");
    347     sprintf(buf, "%lu", (unsigned long)NanoVis::stats.nCommands);
    348     Tcl_DStringAppendElement(&ds, buf);
    349     /* cmd_time */
    350     Tcl_DStringAppendElement(&ds, "cmd_time");
    351     sprintf(buf, "%g", NanoVis::stats.cmdTime);
    352     Tcl_DStringAppendElement(&ds, buf);
    353     /* session_time */
    354     Tcl_DStringAppendElement(&ds, "session_time");
    355     sprintf(buf, "%g", finish - start);
    356     Tcl_DStringAppendElement(&ds, buf);
    357     /* status */
    358     Tcl_DStringAppendElement(&ds, "status");
    359     sprintf(buf, "%d", code);
    360     Tcl_DStringAppendElement(&ds, buf);
    361     {
    362         long clocksPerSec = sysconf(_SC_CLK_TCK);
    363         double clockRes = 1.0 / clocksPerSec;
    364         struct tms tms;
    365 
    366         memset(&tms, 0, sizeof(tms));
    367         times(&tms);
    368         /* utime */
    369         Tcl_DStringAppendElement(&ds, "utime");
    370         sprintf(buf, "%g", tms.tms_utime * clockRes);
    371         Tcl_DStringAppendElement(&ds, buf);
    372         /* stime */
    373         Tcl_DStringAppendElement(&ds, "stime");
    374         sprintf(buf, "%g", tms.tms_stime * clockRes);
    375         Tcl_DStringAppendElement(&ds, buf);
    376         /* cutime */
    377         Tcl_DStringAppendElement(&ds, "cutime");
    378         sprintf(buf, "%g", tms.tms_cutime * clockRes);
    379         Tcl_DStringAppendElement(&ds, buf);
    380         /* cstime */
    381         Tcl_DStringAppendElement(&ds, "cstime");
    382         sprintf(buf, "%g", tms.tms_cstime * clockRes);
    383         Tcl_DStringAppendElement(&ds, buf);
    384     }
    385     Tcl_DStringAppend(&ds, "\n", -1);
    386     int f = NanoVis::getStatsFile(NULL);
    387     result = NanoVis::writeToStatsFile(f, Tcl_DStringValue(&ds),
    388                                        Tcl_DStringLength(&ds));
    389     close(f);
    390     Tcl_DStringFree(&ds);
    391     return result;
    392 }
    393 
    394 #endif
    395 
    396 static void
    397 initService()
    398 {
    399     TRACE("Enter");
    400 
    401     const char* user = getenv("USER");
    402     char* logName = NULL;
    403     int logNameLen = 0;
    404 
    405     if (user == NULL) {
    406         logNameLen = 20+1;
    407         logName = (char *)calloc(logNameLen, sizeof(char));
    408         strncpy(logName, "/tmp/nanovis_log.txt", logNameLen);
    409     } else {
    410         logNameLen = 17+1+strlen(user);
    411         logName = (char *)calloc(logNameLen, sizeof(char));
    412         strncpy(logName, "/tmp/nanovis_log_", logNameLen);
    413         strncat(logName, user, strlen(user));
    414     }
    415 
    416     //open log and map stderr to log file
    417     NanoVis::logfile = fopen(logName, "w");
    418     dup2(fileno(NanoVis::logfile), 2);
    419     /* dup2(2,1); */
    420 
    421     // clean up malloc'd memory
    422     if (logName != NULL) {
    423         free(logName);
    424     }
    425 
    426     TRACE("Leave");
    427 }
    428 
    429 static void
    430 exitService(int code)
    431 {
    432     TRACE("Enter: %d", code);
    433 
    434     NanoVis::removeAllData();
    435 
    436     NvShader::exitCg();
    437 
    438     //close log file
    439     if (NanoVis::logfile != NULL) {
    440         fclose(NanoVis::logfile);
    441         NanoVis::logfile = NULL;
    442     }
    443 
    444 #ifdef KEEPSTATS
    445     serverStats(code);
    446 #endif
    447     closelog();
    448 
    449     exit(code);
    450 }
    451 
    452 static int
    453 executeCommand(Tcl_Interp *interp, Tcl_DString *dsPtr)
    454 {
    455     struct timeval tv;
    456     double start, finish;
    457     int result;
    458 
    459 #ifdef WANT_TRACE
    460     char *str = Tcl_DStringValue(dsPtr);
    461     std::string cmd(str);
    462     cmd.erase(cmd.find_last_not_of(" \n\r\t")+1);
    463     TRACE("command %lu: '%s'", NanoVis::stats.nCommands+1, cmd.c_str());
    464 #endif
    465 
    466     gettimeofday(&tv, NULL);
    467     start = CVT2SECS(tv);
    468 
    469     if (NanoVis::recfile != NULL) {
    470         fprintf(NanoVis::recfile, "%s", Tcl_DStringValue(dsPtr));
    471         fflush(NanoVis::recfile);
    472     }
    473     result = Tcl_Eval(interp, Tcl_DStringValue(dsPtr));
    474     Tcl_DStringSetLength(dsPtr, 0);
    475 
    476     gettimeofday(&tv, NULL);
    477     finish = CVT2SECS(tv);
    478 
    479     NanoVis::stats.cmdTime += finish - start;
    480     NanoVis::stats.nCommands++;
    481     TRACE("Leave status=%d", result);
    482     return result;
    483192}
    484193
     
    615324    planeRenderer->render();
    616325
    617     // INSOO
     326    //glPixelStorei(GL_PACK_ALIGNMENT, 1);
    618327    glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, screenBuffer);
    619     //glReadPixels(0, 0, width, height, GL_BGR, GL_UNSIGNED_BYTE, screenBuffer); // INSOO's
    620 
    621328    {
    622329        char prefix[200];
    623         ssize_t nWritten;
    624330
    625331        TRACE("Sending ppm legend image %s min:%g max:%g", volArg, min, max);
    626332        sprintf(prefix, "nv>legend %s %g %g", volArg, min, max);
    627333        ppmWrite(prefix);
    628         nWritten = write(1, "\n", 1);
    629         assert(nWritten == 1);
    630334    }
    631335    planeRenderer->removePlane(index);
     
    639343
    640344//initialize frame buffer objects for offscreen rendering
    641 void
     345bool
    642346NanoVis::initOffscreenBuffer()
    643347{
     
    678382    if (!CheckFBO(&status)) {
    679383        PrintFBOStatus(status, "finalFbo");
    680         exitService(3);
     384        return false;
    681385    }
    682386
    683387    TRACE("Leave");
     388    return true;
    684389}
    685390
    686391//resize the offscreen buffer
    687 void
     392bool
    688393NanoVis::resizeOffscreenBuffer(int w, int h)
    689394{
    690395    TRACE("Enter (%d, %d)", w, h);
    691396    if ((w == winWidth) && (h == winHeight)) {
    692         return;
     397        return true;
    693398    }
    694399    winWidth = w;
     
    751456    if (!CheckFBO(&status)) {
    752457        PrintFBOStatus(status, "finalFbo");
    753         exitService(3);
     458        return false;
    754459    }
    755460
     
    760465
    761466    TRACE("Leave (%d, %d)", w, h);
     467    return true;
    762468}
    763469
     
    767473    if (!NvShader::printErrorInfo()) {
    768474        TRACE("Cg error, exiting...");
    769         exitService(-1);
    770     }
    771 }
    772 
    773 void NanoVis::init(const char* path)
     475        exit(1);
     476    }
     477}
     478
     479bool NanoVis::init(const char* path)
    774480{
    775481    // print OpenGL driver information
     
    782488    if (path == NULL) {
    783489        ERROR("No path defined for shaders or resources");
    784         exitService(1);
     490        return false;
    785491    }
    786492    GLenum err = glewInit();
    787493    if (GLEW_OK != err) {
    788494        ERROR("Can't init GLEW: %s", glewGetErrorString(err));
    789         exitService(1);
     495        return false;
    790496    }
    791497    TRACE("Using GLEW %s", glewGetString(GLEW_VERSION));
     
    795501    if (!GLEW_VERSION_2_1) {
    796502        ERROR("OpenGL version 2.1 or greater is required");
    797         exitService(1);
     503        return false;
    798504    }
    799505
     
    802508    if (!GLEW_ARB_pixel_buffer_object) {
    803509        ERROR("Pixel buffer objects are not supported by driver, please check that the user running nanovis has permissions to create a direct rendering context (e.g. user has read/write access to /dev/nvidia* device nodes in Linux).");
    804         exitService(1);
     510        return false;
    805511    }
    806512
     
    810516    if (!GLEW_EXT_framebuffer_object) {
    811517        ERROR("EXT_framebuffer_oject extension is required");
    812         exitService(1);
     518        return false;
    813519    }
    814520    // Rectangle textures were promoted in 3.1
     
    816522    if (!GLEW_ARB_texture_rectangle) {
    817523        ERROR("ARB_texture_rectangle extension is required");
    818         exitService(1);
     524        return false;
    819525    }
    820526#ifdef HAVE_FLOAT_TEXTURES
     
    823529        !GLEW_ARB_color_buffer_float) {
    824530        ERROR("ARB_texture_float and ARB_color_buffer_float extensions are required");
    825         exitService(1);
     531        return false;
    826532    }
    827533#endif
     
    830536        !GLEW_NV_fragment_program2) {
    831537        ERROR("NV_vertex_program3 and NV_fragment_program2 extensions are required");
    832         exitService(1);
     538        return false;
    833539    }
    834540
    835541    if (!FilePath::getInstance()->setPath(path)) {
    836542        ERROR("can't set file path to %s", path);
    837         exitService(1);
     543        return false;
    838544    }
    839545
     
    852558    grid = new Grid();
    853559    grid->setFont(fonts);
    854 }
    855 
    856 void
     560
     561    return true;
     562}
     563
     564bool
    857565NanoVis::initGL()
    858566{
     
    889597    glLightfv(GL_LIGHT1, GL_SPECULAR, white_light);
    890598
    891     initOffscreenBuffer();    //frame buffer object for offscreen rendering
    892 
    893     //create volume renderer
     599    //frame buffer object for offscreen rendering
     600    if (!initOffscreenBuffer()) {
     601        return false;
     602    }
     603
    894604    volRenderer = new VolumeRenderer();
    895605
    896     // create
    897606    renderContext = new RenderContext();
    898607
    899     //create a 2D plane renderer
    900608    planeRenderer = new PlaneRenderer(winWidth, winHeight);
    901609
     
    903611
    904612    TRACE("leaving initGL");
     613
     614    return true;
    905615}
    906616
     
    1035745    char string[200];
    1036746    sprintf(string, "%s %d\n", prefix, fsize);
    1037     nWritten = write(1, string, strlen(string));
     747    nWritten = write(g_fdOut, string, strlen(string));
    1038748    assert(nWritten == (ssize_t)strlen(string));
    1039749    header[pos++] = 'B';
     
    1088798    }
    1089799
    1090     nWritten = write(1, header, SIZEOF_BMP_HEADER);
     800    nWritten = write(g_fdOut, header, SIZEOF_BMP_HEADER);
    1091801    assert(nWritten == SIZEOF_BMP_HEADER);
    1092     nWritten = write(1, screenBuffer, (3*winWidth+pad)*winHeight);
     802    nWritten = write(g_fdOut, screenBuffer, (3*winWidth+pad)*winHeight);
    1093803    assert(nWritten == (3*winWidth+pad)*winHeight);
    1094     stats.nFrames++;
    1095     stats.nBytes += (3*winWidth+pad)*winHeight;
     804    g_stats.nFrames++;
     805    g_stats.nFrameBytes += (3*winWidth+pad)*winHeight;
    1096806}
    1097807
     
    1154864        srcRowPtr += bytesPerRow;
    1155865    }
    1156     if (writev(1, iov, nRecs) < 0) {
     866    if (writev(g_fdOut, iov, nRecs) < 0) {
    1157867        ERROR("write failed: %s", strerror(errno));
    1158868    }
    1159869    free(iov);
    1160     stats.nFrames++;
    1161     stats.nBytes += (bytesPerRow * winHeight);
     870    g_stats.nFrames++;
     871    g_stats.nFrameBytes += (bytesPerRow * winHeight);
    1162872    TRACE("Leave (%dx%d)", winWidth, winHeight);
    1163 }
    1164 
    1165 void
    1166 NanoVis::sendDataToClient(const char *command, const char *data, size_t dlen)
    1167 {
    1168     size_t numRecords = 2;
    1169 
    1170     struct iovec *iov = new iovec[numRecords];
    1171 
    1172     // Write the nanovisviewer command, then the image header and data.
    1173     // Command
    1174     // FIXME: shouldn't have to cast this
    1175     iov[0].iov_base = (char *)command;
    1176     iov[0].iov_len = strlen(command);
    1177     // Data
    1178     // FIXME: shouldn't have to cast this
    1179     iov[1].iov_base = (char *)data;
    1180     iov[1].iov_len = dlen;
    1181     if (writev(1, iov, numRecords) < 0) {
    1182         ERROR("write failed: %s", strerror(errno));
    1183     }
    1184     delete [] iov;
    1185 }
    1186 
    1187 void
    1188 NanoVis::idle()
    1189 {
    1190     TRACE("Enter");
    1191 
    1192     glutSetWindow(renderWindow);
    1193 
    1194     processCommands();
    1195 
    1196     TRACE("Leave");
    1197873}
    1198874
     
    15391215    TRACE("Setting bgcolor to %g %g %g", color[0], color[1], color[2]);
    15401216    glClearColor(color[0], color[1], color[2], 1);
     1217}
     1218
     1219void
     1220NanoVis::removeVolume(Volume *volume)
     1221{
     1222    VolumeHashmap::iterator itr = volumeTable.find(volume->name());
     1223    if (itr != volumeTable.end()) {
     1224        volumeTable.erase(itr);
     1225    }
     1226    delete volume;
    15411227}
    15421228
     
    17941480        draw3dAxis();
    17951481    }
    1796     if (grid->isVisible()) {
    1797         grid->render();
    1798     }
     1482    grid->render();
    17991483    if ((licRenderer != NULL) && (licRenderer->active())) {
    18001484        licRenderer->render();
     
    18031487        velocityArrowsSlice->render();
    18041488    }
    1805     if (!flowTable.empty()) {
    1806         renderFlows();
    1807     }
     1489    renderFlows();
    18081490
    18091491    volRenderer->renderAll();
    18101492
    1811     TRACE("Render heightmaps");
    18121493    HeightMapHashmap::iterator itr;
    18131494    for (itr = heightMapTable.begin();
     
    18241505}
    18251506
    1826 void
    1827 NanoVis::processCommands()
    1828 {
    1829     flags &= ~REDRAW_PENDING;
    1830 
    1831     TRACE("Enter");
    1832 
    1833     int flags = fcntl(0, F_GETFL, 0);
    1834     fcntl(0, F_SETFL, flags & ~O_NONBLOCK);
    1835 
    1836     int status = TCL_OK;
    1837 
    1838     //  Read and execute as many commands as we can from stdin...
    1839     Tcl_DString cmdbuffer;
    1840     Tcl_DStringInit(&cmdbuffer);
    1841     int nCommands = 0;
    1842     bool isComplete = false;
    1843     while ((!feof(NanoVis::stdin)) && (status == TCL_OK)) {
    1844         //
    1845         //  Read the next command from the buffer.  First time through we
    1846         //  block here and wait if necessary until a command comes in.
    1847         //
    1848         //  BE CAREFUL: Read only one command, up to a newline.  The "volume
    1849         //  data follows" command needs to be able to read the data
    1850         //  immediately following the command, and we shouldn't consume it
    1851         //  here.
    1852         //
    1853         while (!feof(NanoVis::stdin)) {
    1854             int c = fgetc(NanoVis::stdin);
    1855             char ch;
    1856             if (c <= 0) {
    1857                 if (errno == EWOULDBLOCK) {
    1858                     break;
    1859                 }
    1860                 exitService(100);
    1861             }
    1862             ch = (char)c;
    1863             Tcl_DStringAppend(&cmdbuffer, &ch, 1);
    1864             if (ch == '\n') {
    1865                 isComplete = Tcl_CommandComplete(Tcl_DStringValue(&cmdbuffer));
    1866                 if (isComplete) {
    1867                     break;
    1868                 }
    1869             }
    1870         }
    1871         // no command? then we're done for now
    1872         if (Tcl_DStringLength(&cmdbuffer) == 0) {
    1873             break;
    1874         }
    1875         if (isComplete) {
    1876             // back to original flags during command evaluation...
    1877             fcntl(0, F_SETFL, flags & ~O_NONBLOCK);
    1878             status = executeCommand(interp, &cmdbuffer);
    1879             // non-blocking for next read -- we might not get anything
    1880             fcntl(0, F_SETFL, flags | O_NONBLOCK);
    1881             isComplete = false;
    1882             nCommands++;
    1883             CHECK_FRAMEBUFFER_STATUS();
    1884         }
    1885     }
    1886     fcntl(0, F_SETFL, flags);
    1887 
    1888     if (status != TCL_OK) {
    1889         char *msg;
    1890         char hdr[200];
    1891         int msgSize, hdrSize;
    1892         Tcl_Obj *objPtr;
    1893 
    1894         objPtr = Tcl_GetObjResult(interp);
    1895         msg = Tcl_GetStringFromObj(objPtr, &msgSize);
    1896         hdrSize = sprintf(hdr, "nv>viserror -type internal_error -bytes %d\n", msgSize);
    1897         {
    1898             struct iovec iov[2];
    1899 
    1900             iov[0].iov_base = hdr;
    1901             iov[0].iov_len = hdrSize;
    1902             iov[1].iov_base = msg;
    1903             iov[1].iov_len = msgSize;
    1904             if (writev(1, iov, 2) < 0) {
    1905                 ERROR("write failed: %s", strerror(errno));
    1906             }
    1907         }
    1908         TRACE("Leaving on ERROR");
    1909         return;
    1910     }
    1911     if (feof(NanoVis::stdin)) {
    1912         TRACE("Exiting server on EOF from client");
    1913         exitService(90);
    1914     }
    1915 
    1916     update();
    1917 
    1918     bindOffscreenBuffer();  //enable offscreen render
    1919     render();
    1920     readScreen();
    1921 
    1922     if (feof(NanoVis::stdin)) {
    1923         exitService(90);
    1924     }
    1925 
    1926     ppmWrite("nv>image -type image -bytes");
    1927 
    1928     TRACE("Leave");
    1929 }
    1930 
    1931 int
    1932 main(int argc, char **argv)
    1933 {
    1934     const char *path;
    1935     char *newPath;
    1936 
    1937     newPath = NULL;
    1938     path = NULL;
    1939     NanoVis::stdin = stdin;
    1940 
    1941     fprintf(stdout, "NanoVis %s (build %s)\n", NANOVIS_VERSION, SVN_VERSION);
    1942     fflush(stdout);
    1943 
    1944     openlog("nanovis", LOG_CONS | LOG_PERROR | LOG_PID, LOG_USER);
    1945     memset(&NanoVis::stats, 0, sizeof(NanoVis::Stats));
    1946     NanoVis::stats.pid = getpid();
    1947     gettimeofday(&NanoVis::stats.start, NULL);
    1948 
    1949     /* Initialize GLUT here so it can parse and remove GLUT-specific
    1950      * command-line options before we parse the command-line below. */
    1951     glutInit(&argc, argv);
    1952     glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
    1953     glutInitWindowSize(NanoVis::winWidth, NanoVis::winHeight);
    1954     glutInitWindowPosition(10, 10);
    1955     NanoVis::renderWindow = glutCreateWindow("nanovis");
    1956     glutIdleFunc(NanoVis::idle);
    1957 
    1958     glutDisplayFunc(NanoVis::render);
    1959     glutReshapeFunc(NanoVis::resizeOffscreenBuffer);
    1960 
    1961     while (1) {
    1962         static struct option long_options[] = {
    1963             {"infile",  required_argument, NULL, 0},
    1964             {"path",    required_argument, NULL, 2},
    1965             {"debug",   no_argument,       NULL, 3},
    1966             {"record",  required_argument, NULL, 4},
    1967             {0, 0, 0, 0}
    1968         };
    1969         int option_index = 0;
    1970         int c;
    1971 
    1972         c = getopt_long(argc, argv, ":dp:i:l:r:", long_options, &option_index);
    1973         if (c == -1) {
    1974             break;
    1975         }
    1976         switch (c) {
    1977         case '?':
    1978             fprintf(stderr, "unknown option -%c\n", optopt);
    1979             return 1;
    1980         case ':':
    1981             if (optopt < 4) {
    1982                 fprintf(stderr, "argument missing for --%s option\n",
    1983                         long_options[optopt].name);
    1984             } else {
    1985                 fprintf(stderr, "argument missing for -%c option\n", optopt);
    1986             }
    1987             return 1;
    1988         case 2:
    1989         case 'p':
    1990             path = optarg;
    1991             break;
    1992         case 3:
    1993         case 'd':
    1994             NanoVis::debugFlag = true;
    1995             break;
    1996         case 0:
    1997         case 'i':
    1998             NanoVis::stdin = fopen(optarg, "r");
    1999             if (NanoVis::stdin == NULL) {
    2000                 perror(optarg);
    2001                 return 2;
    2002             }
    2003             break;
    2004         case 4:
    2005         case 'r':
    2006             Tcl_DString ds;
    2007             char buf[200];
    2008 
    2009             Tcl_DStringInit(&ds);
    2010             Tcl_DStringAppend(&ds, optarg, -1);
    2011             sprintf(buf, ".%d", getpid());
    2012             Tcl_DStringAppend(&ds, buf, -1);
    2013             NanoVis::recfile = fopen(Tcl_DStringValue(&ds), "w");
    2014             if (NanoVis::recfile == NULL) {
    2015                 perror(optarg);
    2016                 return 2;
    2017             }
    2018             break;
    2019         default:
    2020             fprintf(stderr,"unknown option '%c'.\n", c);
    2021             return 1;
    2022         }
    2023     }     
    2024     if (path == NULL) {
    2025         char *p;
    2026 
    2027         // See if we can derive the path from the location of the program.
    2028         // Assume program is in the form <path>/bin/nanovis.
    2029         path = argv[0];
    2030         p = strrchr((char *)path, '/');
    2031         if (p != NULL) {
    2032             *p = '\0';
    2033             p = strrchr((char *)path, '/');
    2034         }
    2035         if (p == NULL) {
    2036             TRACE("path not specified");
    2037             return 1;
    2038         }
    2039         *p = '\0';
    2040         newPath = new char[(strlen(path) + 15) * 2 + 1];
    2041         sprintf(newPath, "%s/lib/shaders:%s/lib/resources", path, path);
    2042         path = newPath;
    2043     }
    2044 
    2045     FilePath::getInstance()->setWorkingDirectory(argc, (const char**) argv);
    2046 
    2047 #ifdef notdef
    2048     signal(SIGPIPE, SIG_IGN);
    2049 #endif
    2050     initService();
    2051 
    2052     NanoVis::init(path);
    2053     if (newPath != NULL) {
    2054         delete [] newPath;
    2055     }
    2056     NanoVis::initGL();
    2057 
    2058     NanoVis::interp = initTcl();
    2059 
    2060     NanoVis::resizeOffscreenBuffer(NanoVis::winWidth, NanoVis::winHeight);
    2061 
    2062     glutMainLoop();
    2063 
    2064     exitService(80);
    2065 }
    2066 
    2067 void
    2068 NanoVis::removeVolume(Volume *volume)
    2069 {
    2070     VolumeHashmap::iterator itr = volumeTable.find(volume->name());
    2071     if (itr != volumeTable.end()) {
    2072         volumeTable.erase(itr);
    2073     }
    2074     delete volume;
    2075 }
Note: See TracChangeset for help on using the changeset viewer.