Changeset 2573 for trunk/packages


Ignore:
Timestamp:
Sep 22, 2011, 8:13:47 PM (13 years ago)
Author:
ldelgass
Message:

Merge vtkvis_threaded branch to trunk. (Threading off by default in Makefile)

Location:
trunk/packages/vizservers/vtkvis
Files:
4 added
17 edited

Legend:

Unmodified
Added
Removed
  • trunk/packages/vizservers/vtkvis/CmdProc.cpp

    r2492 r2573  
    1010
    1111#include "CmdProc.h"
     12
     13using namespace Rappture;
    1214
    1315/**
     
    2224 */
    2325static int
    24 BinaryOpSearch(Rappture::CmdSpec *specs,
     26BinaryOpSearch(CmdSpec *specs,
    2527               int nSpecs,
    2628               char *string)       /* Name of minor operation to search for */
     
    3537    length = strlen(string);
    3638    while (low <= high) {
    37         Rappture::CmdSpec *specPtr;
     39        CmdSpec *specPtr;
    3840        int compare;
    3941        int median;
     
    7678 */
    7779static int
    78 LinearOpSearch(Rappture::CmdSpec *specs,
     80LinearOpSearch(CmdSpec *specs,
    7981               int nSpecs,
    8082               char *string)       /* Name of minor operation to search for */
    8183{
    82     Rappture::CmdSpec *specPtr;
     84    CmdSpec *specPtr;
    8385    char c;
    8486    size_t length;
     
    120122 */
    121123Tcl_ObjCmdProc *
    122 Rappture::GetOpFromObj(Tcl_Interp *interp,              /* Interpreter to report errors to */
    123                        int nSpecs,                      /* Number of specifications in array */
    124                        Rappture::CmdSpec *specs,        /* Op specification array */
    125                        int operPos,                     /* Position of operation in argument
    126                                                          * list. */
    127                        int objc,                        /* Number of arguments in the argument
    128                                                          * vector.  This includes any prefixed
    129                                                          * arguments */
    130                        Tcl_Obj *const *objv,            /* Argument vector */
     124Rappture::GetOpFromObj(Tcl_Interp *interp,      /* Interpreter to report errors to */
     125                       int nSpecs,              /* Number of specifications in array */
     126                       CmdSpec *specs,          /* Op specification array */
     127                       int operPos,             /* Position of operation in argument
     128                                                 * list. */
     129                       int objc,                /* Number of arguments in the argument
     130                                                 * vector.  This includes any prefixed
     131                                                 * arguments */
     132                       Tcl_Obj *const *objv,    /* Argument vector */
    131133                       int flags)
    132134{
  • trunk/packages/vizservers/vtkvis/CmdProc.h

    r2492 r2573  
    1919 * for a function pointer associated with the operation name.
    2020 */
    21 typedef struct {
     21struct CmdSpec {
    2222    const char *name;           /**< Name of operation */
    2323    int minChars;               /**< Minimum # characters to disambiguate */
     
    2626    int maxArgs;                /**< Maximum # args required */
    2727    const char *usage;          /**< Usage message */
    28 } CmdSpec;
     28};
    2929
    30 typedef enum {
     30enum CmdSpecIndex {
    3131    CMDSPEC_ARG0,               /**< Op is the first argument. */
    3232    CMDSPEC_ARG1,               /**< Op is the second argument. */
     
    3434    CMDSPEC_ARG3,               /**< Op is the fourth argument. */
    3535    CMDSPEC_ARG4                /**< Op is the fifth argument. */
    36 } CmdSpecIndex;
     36};
    3737
    3838#define CMDSPEC_LINEAR_SEARCH   1
  • trunk/packages/vizservers/vtkvis/ColorMap.cpp

    r2404 r2573  
    106106        cp.value = 1.0;
    107107
     108#ifdef DEBUG
    108109    TRACE("New control point: %g  = %g %g %g",
    109110          cp.value, cp.color[0], cp.color[1], cp.color[2]);
    110 
     111#endif
    111112    for (std::list<ControlPoint>::iterator itr = _controlPoints.begin();
    112113         itr != _controlPoints.end(); ++itr) {
     
    136137        cp.value = 1.0;
    137138
     139#ifdef DEBUG
    138140    TRACE("New opacity control point: %g  = %g",
    139141          cp.value, cp.alpha);
    140 
     142#endif
    141143    for (std::list<OpacityControlPoint>::iterator itr = _opacityControlPoints.begin();
    142144         itr != _opacityControlPoints.end(); ++itr) {
  • trunk/packages/vizservers/vtkvis/Makefile.in

    r2533 r2573  
    2424
    2525GL_LIB_SPEC     = -lGL -lm
     26PTHREAD_LIB_SPEC= -lpthread
    2627
    2728TCL_LIB_SPEC    = @TCL_LIB_SPEC@
     
    3536
    3637LIBS            = \
    37                 $(GL_LIB_SPEC) \
    3838                $(TCL_LIB_SPEC) \
    3939                $(VTK_LIB_SPEC) \
     40                $(GL_LIB_SPEC) \
     41                $(PTHREAD_LIB_SPEC) \
    4042                -Wl,-rpath,$(LD_RUN_PATH)
    4143
     
    5052USE_GPU_RAYCASTING      = yes
    5153USE_OFFSCREEN_RENDERING = yes
     54USE_THREADS             = #yes
    5255
    5356#vtk uses deprecated strstream header (instead of sstream)
     
    7073DEFINES         += -DUSE_GPU_RAYCAST_MAPPER
    7174endif
     75ifdef USE_THREADS
     76DEFINES         += -DUSE_THREADS
     77endif
    7278CXX_SWITCHES    = $(CXXFLAGS) $(EXTRA_CFLAGS) $(DEFINES) $(INCLUDES)
    7379
     
    7682                ColorMap.cpp \
    7783                PPMWriter.cpp \
     84                ReadBuffer.cpp \
    7885                RpContour2D.cpp \
    7986                RpContour3D.cpp \
     
    96103ifdef USE_CUSTOM_AXES
    97104SERVER_SRCS+=vtkRpCubeAxesActor2D.cpp
     105endif
     106ifdef USE_THREADS
     107SERVER_SRCS+=ResponseQueue.cpp
    98108endif
    99109
     
    130140CmdProc.o: CmdProc.h
    131141ColorMap.o: ColorMap.h RpMolecule.h Trace.h
    132 PPMWriter.o: PPMWriter.h Trace.h
     142PPMWriter.o: PPMWriter.h ResponseQueue.h Trace.h
     143ReadBuffer.o: ReadBuffer.h Trace.h
     144ResponseQueue.o: ResponseQueue.h Trace.h
    133145RpContour2D.o: RpContour2D.h RpVtkGraphicsObject.h RpVtkDataSet.h Trace.h
    134146RpContour3D.o: RpContour3D.h RpVtkGraphicsObject.h RpVtkDataSet.h ColorMap.h Trace.h
     
    143155RpVolume.o: RpVolume.h RpVtkGraphicsObject.h RpVtkDataSet.h ColorMap.h Trace.h
    144156RpVtkDataSet.o: RpVtkDataSet.h Trace.h
    145 RpVtkRenderer.o: RpVtkRenderer.h vtkRpCubeAxesActor2D.h RpVtkDataSet.h RpContour2D.h RpContour3D.h RpGlyphs.h RpHeightMap.h RpLIC.h RpMolecule.h RpPolyData.h RpPseudoColor.h RpStreamlines.h RpVolume.h ColorMap.h Trace.h
    146 RpVtkRendererCmd.o: RpVtkRenderer.h vtkRpCubeAxesActor2D.h RpVtkDataSet.h RpContour2D.h RpContour3D.h RpGlyphs.h RpHeightMap.h RpLIC.h RpMolecule.h RpPolyData.h RpPseudoColor.h RpStreamlines.h RpVolume.h ColorMap.h Trace.h CmdProc.h PPMWriter.h TGAWriter.h
    147 RpVtkRenderServer.o: RpVtkRenderServer.h RpVtkRendererCmd.h RpVtkRenderer.h vtkRpCubeAxesActor2D.h Trace.h PPMWriter.h TGAWriter.h
     157RpVtkRenderer.o: RpVtkRenderer.h vtkRpCubeAxesActor2D.h RpVtkDataSet.h RpContour2D.h RpContour3D.h RpCutplane.h RpGlyphs.h RpHeightMap.h RpLIC.h RpMolecule.h RpPolyData.h RpPseudoColor.h RpStreamlines.h RpVolume.h ColorMap.h Trace.h
     158RpVtkRendererCmd.o: RpVtkRenderer.h vtkRpCubeAxesActor2D.h RpVtkDataSet.h RpContour2D.h RpContour3D.h RpCutplane.h RpGlyphs.h RpHeightMap.h RpLIC.h RpMolecule.h RpPolyData.h RpPseudoColor.h RpStreamlines.h RpVolume.h ColorMap.h ReadBuffer.h ResponseQueue.h Trace.h CmdProc.h PPMWriter.h TGAWriter.h
     159RpVtkRenderServer.o: RpVtkRenderServer.h RpVtkRendererCmd.h RpVtkRenderer.h vtkRpCubeAxesActor2D.h ReadBuffer.h ResponseQueue.h Trace.h PPMWriter.h TGAWriter.h
    148160Trace.o: Trace.h
    149 TGAWriter.o: TGAWriter.h Trace.h
     161TGAWriter.o: TGAWriter.h ResponseQueue.h Trace.h
    150162vtkRpCubeAxesActor2D.o: vtkRpCubeAxesActor2D.h
  • trunk/packages/vizservers/vtkvis/PPMWriter.cpp

    r2492 r2573  
    1212#include <sys/uio.h>
    1313
     14#include "Trace.h"
    1415#include "PPMWriter.h"
    15 #include "Trace.h"
     16#ifdef USE_THREADS
     17#include "ResponseQueue.h"
     18#endif
    1619
    1720using namespace Rappture::VtkVis;
     21
     22#ifdef USE_THREADS
     23
     24/**
     25 * \brief Writes image data as PPM binary data to the client.
     26 *
     27 * The PPM binary format is very simple.
     28 *
     29 *     P6 w h 255\n
     30 *     3-byte RGB pixel data.
     31 *
     32 * The client (using the TkImg library) will do less work to unpack this
     33 * format, as opposed to BMP or PNG.
     34 *
     35 * Note that currently the image data has bottom to top scanlines.  This
     36 * routine could be made even simpler (faster) if the image data had top
     37 * to bottom scanlines.
     38 *
     39 * \param[in] queue Pointer to ResponseQueue to write to
     40 * \param[in] cmdName Command name to send (byte length will be appended)
     41 * \param[in] data Image data
     42 * \param[in] width Width of image in pixels
     43 * \param[in] height Height of image in pixels
     44 */
     45void
     46Rappture::VtkVis::queuePPM(ResponseQueue *queue, const char *cmdName,
     47                           const unsigned char *data, int width, int height)
     48{
     49#define PPM_MAXVAL 255
     50    char header[200];
     51
     52    TRACE("Entering (%dx%d)\n", width, height);
     53    // Generate the PPM binary file header
     54    snprintf(header, sizeof(header), "P6 %d %d %d\n", width, height,
     55             PPM_MAXVAL);
     56
     57    size_t headerLength = strlen(header);
     58    size_t dataLength = width * height * 3;
     59
     60    char command[200];
     61    snprintf(command, sizeof(command), "%s %lu\n", cmdName,
     62             (unsigned long)headerLength + dataLength);
     63
     64    size_t cmdLength;
     65    cmdLength = strlen(command);
     66
     67    size_t length;
     68    unsigned char *mesg;
     69
     70    length = headerLength + dataLength + cmdLength;
     71    mesg = (unsigned char *)malloc(length);
     72    if (mesg == NULL) {
     73        ERROR("can't allocate %ld bytes for the image message", length);
     74        return;
     75    }
     76    memcpy(mesg, command, cmdLength);
     77    memcpy(mesg + cmdLength, header, headerLength);
     78
     79    size_t bytesPerRow = width * 3;
     80    unsigned char *destRowPtr = mesg + length - bytesPerRow;
     81    int y;
     82    unsigned char *srcRowPtr = const_cast<unsigned char *>(data);
     83    for (y = 0; y < height; y++) {
     84        memcpy(destRowPtr, srcRowPtr, bytesPerRow);
     85        srcRowPtr += bytesPerRow;
     86        destRowPtr -= bytesPerRow;
     87    }
     88
     89    Response *response;
     90    if (strncmp(cmdName, "nv>legend", 9) == 0) {
     91        response = new Response(Response::LEGEND);
     92    } else {
     93        response = new Response(Response::IMAGE);
     94    }
     95    response->setMessage(mesg, length, Response::DYNAMIC);
     96    queue->enqueue(response);
     97    TRACE("Leaving (%dx%d)\n", width, height);
     98}
     99#else
    18100
    19101/**
     
    39121 */
    40122void
    41 Rappture::VtkVis::writePPM(int fd, const char *cmdName, const unsigned char *data,
    42                            int width, int height)
     123Rappture::VtkVis::writePPM(int fd, const char *cmdName,
     124                           const unsigned char *data, int width, int height)
    43125{
    44126#define PPM_MAXVAL 255
     
    47129    TRACE("Entering (%dx%d)\n", width, height);
    48130    // Generate the PPM binary file header
    49     snprintf(header, sizeof(header), "P6 %d %d %d\n", width, height, PPM_MAXVAL);
     131    snprintf(header, sizeof(header), "P6 %d %d %d\n", width, height,
     132             PPM_MAXVAL);
    50133
    51134    size_t headerLength = strlen(header);
     
    79162    }
    80163    if (writev(fd, iov, nRecs) < 0) {
    81         ERROR("write failed: %s\n", strerror(errno));
     164        ERROR("write failed: %s\n", strerror(errno));
    82165    }
    83166    free(iov);
     
    85168    TRACE("Leaving (%dx%d)\n", width, height);
    86169}
     170
     171#endif /*USE_THREADS*/
  • trunk/packages/vizservers/vtkvis/PPMWriter.h

    r2492 r2573  
    99#define __RAPPTURE_VTKVIS_PPMWRITER_H__
    1010
     11#ifdef USE_THREADS
     12#include "ResponseQueue.h"
     13#endif
     14
    1115namespace Rappture {
    1216namespace VtkVis {
    13 
     17#ifdef USE_THREADS
    1418extern
    15 void writePPM(int fd, const char *cmdName, const unsigned char *data, int width, int height);
    16 
     19void queuePPM(ResponseQueue *queue, const char *cmdName,
     20              const unsigned char *data, int width, int height);
     21#else
     22extern
     23void writePPM(int fd, const char *cmdName,
     24              const unsigned char *data, int width, int height);
     25#endif
    1726}
    1827}
    19 
    2028#endif
  • trunk/packages/vizservers/vtkvis/RpGlyphs.cpp

    r2492 r2573  
    4444Glyphs::~Glyphs()
    4545{
     46#ifdef WANT_TRACE
     47    if (_dataSet != NULL)
     48        TRACE("Deleting Glyphs for %s", _dataSet->getName().c_str());
     49    else
     50        TRACE("Deleting Glyphs with NULL DataSet");
     51#endif
    4652}
    4753
  • trunk/packages/vizservers/vtkvis/RpLIC.cpp

    r2514 r2573  
    3636LIC::~LIC()
    3737{
     38#ifdef WANT_TRACE
     39    if (_dataSet != NULL)
     40        TRACE("Deleting LIC for %s", _dataSet->getName().c_str());
     41    else
     42        TRACE("Deleting LIC with NULL DataSet");
     43#endif
    3844}
    3945
  • trunk/packages/vizservers/vtkvis/RpStreamlines.cpp

    r2533 r2573  
    5555Streamlines::~Streamlines()
    5656{
     57#ifdef WANT_TRACE
     58    if (_dataSet != NULL)
     59        TRACE("Deleting Streamlines for %s", _dataSet->getName().c_str());
     60    else
     61        TRACE("Deleting Streamlines with NULL DataSet");
     62#endif
    5763}
    5864
     
    189195    bary[2] = 1.0 - bary[0] - bary[1];
    190196
    191     TRACE("bary %g %g %g", bary[0], bary[1], bary[2]);
     197    //TRACE("bary %g %g %g", bary[0], bary[1], bary[2]);
    192198    // Convert to cartesian coords
    193199    for (int i = 0; i < 3; i++) {
     
    221227    }
    222228    bary[3] = 1.0 - bary[0] - bary[1] - bary[2];
    223     TRACE("bary %g %g %g %g", bary[0], bary[1], bary[2], bary[3]);
     229    //TRACE("bary %g %g %g %g", bary[0], bary[1], bary[2], bary[3]);
    224230    // Convert to cartesian coords
    225231    for (int i = 0; i < 3; i++) {
  • trunk/packages/vizservers/vtkvis/RpVtkRenderServer.cpp

    r2423 r2573  
    99#include <cstring>
    1010#include <cstdlib>
    11 #include <string>
    12 #include <sstream>
     11#include <cerrno>
    1312#include <unistd.h>
    1413#include <signal.h>
     
    1817#endif
    1918
     19#include <string>
     20#include <sstream>
     21
    2022#include "Trace.h"
     23#include "ReadBuffer.h"
    2124#include "RpVtkRenderServer.h"
    2225#include "RpVtkRendererCmd.h"
     
    2427#include "PPMWriter.h"
    2528#include "TGAWriter.h"
     29#ifdef USE_THREADS
     30#include <pthread.h>
     31#include "ResponseQueue.h"
     32#endif
    2633
    2734using namespace Rappture::VtkVis;
     
    2936int Rappture::VtkVis::g_fdIn = STDIN_FILENO; ///< Input file descriptor
    3037int Rappture::VtkVis::g_fdOut = STDOUT_FILENO; ///< Output file descriptor
    31 FILE *Rappture::VtkVis::g_fIn = stdin; ///< Input file handle
    3238FILE *Rappture::VtkVis::g_fOut = stdout; ///< Output file handle
    3339FILE *Rappture::VtkVis::g_fLog = NULL; ///< Trace logging file handle
    3440Renderer *Rappture::VtkVis::g_renderer = NULL; ///< Main render worker
     41ReadBuffer *Rappture::VtkVis::g_inBufPtr = NULL; ///< Socket read buffer
    3542
    3643#define ELAPSED_TIME(t1, t2) \
     
    3845     (((t2).tv_sec - (t1).tv_sec))*1.0e+3f + (float)((t2).tv_usec - (t1).tv_usec)/1.0e+3f)
    3946
     47#ifdef USE_THREADS
    4048static void
    41 writeFrame(int fd, vtkUnsignedCharArray *imgData)
     49queueFrame(ResponseQueue *queue, vtkUnsignedCharArray *imgData)
    4250{
    4351#ifdef DEBUG
     
    6573                 TARGA_BYTES_PER_PIXEL,
    6674                 true);
    67 #endif
     75#endif  /*RENDER_TARGA*/
    6876
    6977#else
     
    8290
    8391#ifdef RENDER_TARGA
     92        queueTGA(queue, oss.str().c_str(),
     93                 imgData->GetPointer(0),
     94                 g_renderer->getWindowWidth(),
     95                 g_renderer->getWindowHeight(),
     96                 TARGA_BYTES_PER_PIXEL);
     97#else
     98        queuePPM(queue, oss.str().c_str(),
     99                 imgData->GetPointer(0),
     100                 g_renderer->getWindowWidth(),
     101                 g_renderer->getWindowHeight());
     102#endif  /*RENDER_TARGA*/
     103    } else {
     104#ifdef RENDER_TARGA
     105        queueTGA(queue, "nv>image -type image -bytes",
     106                 imgData->GetPointer(0),
     107                 g_renderer->getWindowWidth(),
     108                 g_renderer->getWindowHeight(),
     109                 TARGA_BYTES_PER_PIXEL);
     110#else
     111        queuePPM(queue, "nv>image -type image -bytes",
     112                 imgData->GetPointer(0),
     113                 g_renderer->getWindowWidth(),
     114                 g_renderer->getWindowHeight());
     115#endif  /*RENDER_TARGA*/
     116    }
     117#endif  /*DEBUG*/
     118}
     119
     120#else
     121
     122static void
     123writeFrame(int fd, vtkUnsignedCharArray *imgData)
     124{
     125#ifdef DEBUG
     126    if (g_renderer->getCameraMode() == Renderer::IMAGE) {
     127        double xywh[4];
     128        g_renderer->getScreenWorldCoords(xywh);
     129        TRACE("Image bbox: %g %g %g %g",
     130              xywh[0],
     131              (xywh[1] + xywh[3]),
     132              (xywh[0] + xywh[2]),
     133              xywh[1]);
     134    }
     135
     136#ifdef RENDER_TARGA
     137    writeTGAFile("/tmp/frame.tga",
     138                 imgData->GetPointer(0),
     139                 g_renderer->getWindowWidth(),
     140                 g_renderer->getWindowHeight(),
     141                 TARGA_BYTES_PER_PIXEL);
     142#else
     143    writeTGAFile("/tmp/frame.tga",
     144                 imgData->GetPointer(0),
     145                 g_renderer->getWindowWidth(),
     146                 g_renderer->getWindowHeight(),
     147                 TARGA_BYTES_PER_PIXEL,
     148                 true);
     149#endif  /*RENDER_TARGA*/
     150
     151#else
     152    if (g_renderer->getCameraMode() == Renderer::IMAGE) {
     153        double xywh[4];
     154        g_renderer->getCameraZoomRegion(xywh);
     155        std::ostringstream oss;
     156        oss.precision(12);
     157        // Send upper left and lower right corners as bbox
     158        oss << "nv>image -type image -bbox {"
     159            << std::scientific
     160            << xywh[0] << " "
     161            << xywh[1] << " "
     162            << xywh[2] << " "
     163            << xywh[3] << "} -bytes";
     164
     165#ifdef RENDER_TARGA
    84166        writeTGA(fd, oss.str().c_str(),
    85167                 imgData->GetPointer(0),
     
    92174                 g_renderer->getWindowWidth(),
    93175                 g_renderer->getWindowHeight());
    94 #endif
     176#endif  /*RENDER_TARGA*/
    95177    } else {
    96178#ifdef RENDER_TARGA
     
    105187                 g_renderer->getWindowWidth(),
    106188                 g_renderer->getWindowHeight());
    107 #endif
    108     }
    109 #endif
    110 }
     189#endif  /*RENDER_TARGA*/
     190    }
     191#endif  /*DEBUG*/
     192}
     193#endif /*USE_THREADS*/
    111194
    112195static void
     
    153236}
    154237
     238#ifdef USE_THREADS
     239static void *
     240readerThread(void *clientData)
     241{
     242    ResponseQueue *queue = (ResponseQueue *)clientData;
     243    Tcl_Interp *interp;
     244
     245    TRACE("Starting reader thread");
     246    interp = (Tcl_Interp *)queue->clientData();
     247    vtkSmartPointer<vtkUnsignedCharArray> imgData =
     248        vtkSmartPointer<vtkUnsignedCharArray>::New();
     249    for (;;) {
     250        if (processCommands(interp, g_inBufPtr, g_fdOut) < 0)
     251            break;
     252
     253        if (g_renderer->render()) {
     254            TRACE("Rendering new frame");
     255            g_renderer->getRenderedFrame(imgData);
     256            queueFrame(queue, imgData);
     257        } else {
     258            TRACE("No render required");
     259        }
     260
     261        if (g_inBufPtr->status() == ReadBuffer::ENDFILE)
     262            break;
     263    }   
     264    return NULL;
     265}
     266
     267static void *
     268writerThread(void *clientData)
     269{
     270    ResponseQueue *queue = (ResponseQueue *)clientData;
     271
     272    TRACE("Starting writer thread");
     273    for (;;) {
     274        Response *response;
     275
     276        response = queue->dequeue();
     277        if (fwrite(response->message(), sizeof(char), response->length(),
     278                   g_fOut) != response->length()) {
     279            ERROR("short write while trying to write %ld bytes",
     280                  response->length());
     281        }
     282        fflush(g_fOut);
     283        delete response;
     284        if (feof(g_fOut))
     285            break;
     286    }   
     287    return NULL;
     288}
     289
     290#endif  /*USE_THREADS*/
     291
    155292int
    156293main(int argc, char *argv[])
     
    159296    signal(SIGPIPE, SIG_IGN);
    160297    initService();
    161     InitLog();
     298    initLog();
    162299
    163300    TRACE("Starting VTKVis Server");
    164 
    165     g_fIn = stdin;
    166     g_fOut = stdout;
    167     g_fdIn = fileno(stdin);
    168     g_fdOut = fileno(stdout);
    169301
    170302    /* This synchronizes the client with the server, so that the client
     
    172304     * also be used to supply information about the server (version, memory
    173305     * size, etc). */
    174     fprintf(stdout, "VtkVis 1.0\n");
    175     fflush(stdout);
     306    fprintf(g_fOut, "VtkVis 1.0\n");
     307    fflush(g_fOut);
    176308
    177309    g_renderer = new Renderer();
     310    g_inBufPtr = new ReadBuffer(g_fdIn, 1<<12);
     311
     312    Tcl_Interp *interp = Tcl_CreateInterp();
     313
     314#ifdef USE_THREADS
     315    ResponseQueue *queue = new ResponseQueue((void *)interp);
     316    initTcl(interp, (ClientData)queue);
     317
     318    pthread_t readerThreadId, writerThreadId;
     319    if (pthread_create(&readerThreadId, NULL, &readerThread, queue) < 0) {
     320        ERROR("Can't create reader thread: %s", strerror(errno));
     321    }
     322    if (pthread_create(&writerThreadId, NULL, &writerThread, queue) < 0) {
     323        ERROR("Can't create writer thread: %s", strerror(errno));
     324    }
     325    if (pthread_join(readerThreadId, NULL) < 0) {
     326        ERROR("Can't join reader thread: %s", strerror(errno));
     327    } else {
     328        TRACE("Reader thread exited");
     329    }
     330    // Writer thread is probably blocked on sem_wait, so cancel instead
     331    // of joining
     332    if (pthread_cancel(writerThreadId) < 0) {
     333        ERROR("Can't cancel writer thread: %s", strerror(errno));
     334    } else {
     335        TRACE("Cancelled writer thread");
     336    }
     337
     338    TRACE("Deleting ResponseQueue");
     339    delete queue;
     340    queue = NULL;
     341#else
     342    initTcl(interp, (ClientData)NULL);
     343
    178344    vtkSmartPointer<vtkUnsignedCharArray> imgData =
    179345        vtkSmartPointer<vtkUnsignedCharArray>::New();
    180 
    181     Tcl_Interp *interp = initTcl();
    182 
    183     int ret = 0;
    184 
    185     while (1) {
    186         ret = processCommands(interp, g_fIn, g_fOut);
    187         if (ret < 0)
     346    for (;;) {
     347        if (processCommands(interp, g_inBufPtr, g_fdOut) < 0)
    188348            break;
    189349
     
    196356        }
    197357
    198         if (feof(g_fIn))
    199             break;
    200     }
    201 
     358        if (g_inBufPtr->status() == ReadBuffer::ENDFILE)
     359            break;
     360    }
     361#endif
     362
     363    TRACE("Stopping Tcl interpreter");
    202364    exitTcl(interp);
    203365    interp = NULL;
    204366
     367    TRACE("Deleting ReadBuffer");
     368    delete g_inBufPtr;
     369    g_inBufPtr = NULL;
     370
     371    TRACE("Deleting renderer");
    205372    delete g_renderer;
    206373    g_renderer = NULL;
     
    208375    TRACE("Exiting VTKVis Server");
    209376
    210     CloseLog();
     377    closeLog();
    211378    exitService();
    212379
    213     return ret;
    214 }
    215 
     380    return 0;
     381}
  • trunk/packages/vizservers/vtkvis/RpVtkRenderServer.h

    r2514 r2573  
    1616extern int g_fdIn;
    1717extern int g_fdOut;
    18 extern FILE *g_fIn;
    1918extern FILE *g_fOut;
    2019extern FILE *g_fLog;
    2120extern Renderer *g_renderer;
     21extern ReadBuffer *g_inBufPtr;
    2222
    2323}
  • trunk/packages/vizservers/vtkvis/RpVtkRendererCmd.cpp

    r2514 r2573  
    1919#include "Trace.h"
    2020#include "CmdProc.h"
     21#include "ReadBuffer.h"
    2122#include "RpVtkRendererCmd.h"
    2223#include "RpVtkRenderServer.h"
     
    2425#include "PPMWriter.h"
    2526#include "TGAWriter.h"
     27#ifdef USE_THREADS
     28#include "ResponseQueue.h"
     29#endif
    2630
    2731using namespace Rappture::VtkVis;
     32
     33static int lastCmdStatus;
     34
     35#ifdef USE_THREADS
     36static void
     37QueueResponse(ClientData clientData, const void *bytes, size_t len,
     38              Response::AllocationType allocType)
     39{
     40    ResponseQueue *queue = (ResponseQueue *)clientData;
     41
     42    Response *response;
     43
     44    response = new Response(Response::DATA);
     45    response->setMessage((unsigned char *)bytes, len, allocType);
     46    queue->enqueue(response);
     47}
     48#else
    2849
    2950static ssize_t
     
    4364}
    4465
    45 static size_t
    46 SocketRead(void *bytes, size_t len)
    47 {
    48 #ifdef notdef
    49     size_t ofs = 0;
    50     ssize_t bytesRead = 0;
    51     while ((bytesRead = read(g_fdIn, bytes + ofs, len - ofs)) > 0) {
    52         ofs += bytesRead;
    53         if (ofs == len)
    54             break;
    55     }
    56     TRACE("bytesRead: %lu", ofs);
    57     return ofs;
    58 #else
    59     size_t bytesRead = fread(bytes, 1, len, g_fIn);
    60     TRACE("bytesRead: %lu", bytesRead);
    61     return bytesRead;
    62 #endif
     66#endif  /*USE_THREADS*/
     67
     68static bool
     69SocketRead(char *bytes, size_t len)
     70{
     71    ReadBuffer::BufferStatus status;
     72    status = g_inBufPtr->followingData((unsigned char *)bytes, len);
     73    TRACE("followingData status: %d", status);
     74    return (status == ReadBuffer::OK);
    6375}
    6476
     
    6880    int result;
    6981
    70     result = Tcl_Eval(interp, Tcl_DStringValue(dsPtr));
     82    TRACE("command: '%s'", Tcl_DStringValue(dsPtr));
     83    lastCmdStatus = TCL_OK;
     84    result = Tcl_EvalEx(interp, Tcl_DStringValue(dsPtr),
     85                        Tcl_DStringLength(dsPtr),
     86                        TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL);
    7187    Tcl_DStringSetLength(dsPtr, 0);
    72 
     88    if (lastCmdStatus == TCL_BREAK) {
     89        return TCL_BREAK;
     90    }
     91    lastCmdStatus = result;
    7392    return result;
    7493}
     
    380399             pos[0], pos[1], pos[2], focalPt[0], focalPt[1], focalPt[2], viewUp[0], viewUp[1], viewUp[2]);
    381400
     401#ifdef USE_THREADS
     402    QueueResponse(clientData, buf, strlen(buf), Response::VOLATILE);
     403#else
    382404    ssize_t bytesWritten = SocketWrite(buf, strlen(buf));
    383 
    384405    if (bytesWritten < 0) {
    385406        return TCL_ERROR;
    386407    }
     408#endif
    387409    return TCL_OK;
    388410}
     
    16561678    }
    16571679    char *data = (char *)malloc(nbytes);
    1658     size_t bytesRead = SocketRead(data, nbytes);
    1659     if (bytesRead < 0) {
     1680    if (!SocketRead(data, nbytes)) {
    16601681        free(data);
    16611682        return TCL_ERROR;
     
    16981719
    16991720    char buf[256];
    1700     snprintf(buf, sizeof(buf), "nv>dataset scalar pixel %d %d %g %s\n", x, y, value, name);
    1701 
    1702     ssize_t bytesWritten = SocketWrite(buf, strlen(buf));
     1721    int length;
     1722
     1723    length = snprintf(buf, sizeof(buf), "nv>dataset scalar pixel %d %d %g %s\n",
     1724                      x, y, value, name);
     1725
     1726#ifdef USE_THREADS
     1727    QueueResponse(clientData, buf, length, Response::VOLATILE);
     1728#else
     1729    ssize_t bytesWritten = SocketWrite(buf, length);
    17031730
    17041731    if (bytesWritten < 0) {
    17051732        return TCL_ERROR;
    17061733    }
     1734#endif
    17071735    return TCL_OK;
    17081736}
     
    17261754
    17271755    char buf[256];
    1728     snprintf(buf, sizeof(buf), "nv>dataset scalar world %g %g %g %g %s\n", x, y, z, value, name);
    1729 
    1730     ssize_t bytesWritten = SocketWrite(buf, strlen(buf));
    1731 
     1756    int length;
     1757
     1758    length = snprintf(buf, sizeof(buf),
     1759                      "nv>dataset scalar world %g %g %g %g %s\n",
     1760                      x, y, z, value, name);
     1761
     1762#ifdef USE_THREADS
     1763    QueueResponse(clientData, buf, length, Response::VOLATILE);
     1764#else
     1765    ssize_t bytesWritten = SocketWrite(buf, length);
    17321766    if (bytesWritten < 0) {
    17331767        return TCL_ERROR;
    17341768    }
     1769#endif
    17351770    return TCL_OK;
    17361771}
     
    17731808
    17741809    char buf[256];
    1775     snprintf(buf, sizeof(buf), "nv>dataset vector pixel %d %d %g %g %g %s\n", x, y,
    1776              value[0], value[1], value[2], name);
    1777 
    1778     ssize_t bytesWritten = SocketWrite(buf, strlen(buf));
     1810    int length;
     1811    length = snprintf(buf, sizeof(buf),
     1812                      "nv>dataset vector pixel %d %d %g %g %g %s\n",
     1813                      x, y,
     1814                      value[0], value[1], value[2], name);
     1815
     1816#ifdef USE_THREADS
     1817    QueueResponse(clientData, buf, length, Response::VOLATILE);
     1818#else
     1819    ssize_t bytesWritten = SocketWrite(buf, length);
    17791820
    17801821    if (bytesWritten < 0) {
    17811822        return TCL_ERROR;
    17821823    }
     1824#endif /*USE_THREADS*/
    17831825    return TCL_OK;
    17841826}
     
    18021844
    18031845    char buf[256];
    1804     snprintf(buf, sizeof(buf), "nv>dataset vector world %g %g %g %g %g %g %s\n", x, y, z,
    1805              value[0], value[1], value[2], name);
    1806 
    1807     ssize_t bytesWritten = SocketWrite(buf, strlen(buf));
     1846    int length;
     1847    length = snprintf(buf, sizeof(buf),
     1848                      "nv>dataset vector world %g %g %g %g %g %g %s\n",
     1849                      x, y, z,
     1850                      value[0], value[1], value[2], name);
     1851#ifdef USE_THREADS
     1852    QueueResponse(clientData, buf, length, Response::VOLATILE);
     1853#else
     1854    ssize_t bytesWritten = SocketWrite(buf, length);
    18081855
    18091856    if (bytesWritten < 0) {
    18101857        return TCL_ERROR;
    18111858    }
     1859#endif /*USE_THREADS*/
    18121860    return TCL_OK;
    18131861}
     
    18721920    oss << "}\n";
    18731921    len += 2;
    1874 
    1875     size_t bytesWritten = SocketWrite(oss.str().c_str(), len);
     1922#ifdef USE_THREADS
     1923    QueueResponse(clientData, oss.str().c_str(), len, Response::VOLATILE);
     1924#else
     1925    ssize_t bytesWritten = SocketWrite(oss.str().c_str(), len);
    18761926
    18771927    if (bytesWritten < 0) {
    18781928        return TCL_ERROR;
    18791929    }
     1930#endif /*USE_THREADS*/
    18801931    return TCL_OK;
    18811932}
     
    29212972
    29222973static int
     2974ImageFlushCmd(ClientData clientData, Tcl_Interp *interp, int objc,
     2975             Tcl_Obj *const *objv)
     2976{
     2977    lastCmdStatus = TCL_BREAK;
     2978    return TCL_OK;
     2979}
     2980
     2981static int
    29232982LegendCmd(ClientData clientData, Tcl_Interp *interp, int objc,
    29242983          Tcl_Obj *const *objv)
     
    29813040
    29823041#ifdef DEBUG
     3042# ifdef RENDER_TARGA
    29833043    writeTGAFile("/tmp/legend.tga", imgData->GetPointer(0), width, height,
    29843044                 TARGA_BYTES_PER_PIXEL);
     3045# else
     3046    writeTGAFile("/tmp/legend.tga", imgData->GetPointer(0), width, height,
     3047                 TARGA_BYTES_PER_PIXEL, true);
     3048# endif
    29853049#else
    29863050    char cmd[256];
    29873051    snprintf(cmd, sizeof(cmd), "nv>legend {%s} {%s} %g %g",
    29883052             colorMapName, title.c_str(), range[0], range[1]);
    2989 #ifdef RENDER_TARGA
     3053
     3054# ifdef USE_THREADS
     3055#  ifdef RENDER_TARGA
     3056    ResponseQueue *queue = (ResponseQueue *)clientData;
     3057    queueTGA(queue, cmd, imgData->GetPointer(0), width, height,
     3058             TARGA_BYTES_PER_PIXEL);
     3059#  else
     3060    ResponseQueue *queue = (ResponseQueue *)clientData;
     3061    queuePPM(queue, cmd, imgData->GetPointer(0), width, height);
     3062#  endif
     3063# else
     3064#  ifdef RENDER_TARGA
    29903065    writeTGA(g_fdOut, cmd, imgData->GetPointer(0), width, height,
    2991                  TARGA_BYTES_PER_PIXEL);
    2992 #else
     3066             TARGA_BYTES_PER_PIXEL);
     3067#  else
    29933068    writePPM(g_fdOut, cmd, imgData->GetPointer(0), width, height);
    2994 #endif
    2995 #endif
    2996 
     3069#  endif
     3070# endif // USE_THREADS
     3071#endif // DEBUG
    29973072    return TCL_OK;
    29983073}
     
    46844759    }
    46854760    char *data = (char *)malloc(nbytes);
    4686     size_t bytesRead = SocketRead(data, nbytes);
    4687     if (bytesRead < 0) {
     4761    if (!SocketRead(data, nbytes)) {
    46884762        free(data);
    46894763        return TCL_ERROR;
     
    47334807    }
    47344808    char *data = (char *)malloc(nbytes);
    4735     size_t bytesRead = SocketRead(data, nbytes);
    4736     if (bytesRead < 0) {
     4809    if (!SocketRead(data, nbytes)) {
    47374810        free(data);
    47384811        return TCL_ERROR;
     
    49735046
    49745047static Rappture::CmdSpec streamlinesOps[] = {
    4975     {"add",       1, StreamlinesAddOp, 2, 3, "?dataSetName?"},
    4976     {"ccolor",    1, StreamlinesColorOp, 5, 6, "r g b ?dataSetName?"},
    4977     {"colormap",  7, StreamlinesColorMapOp, 3, 4, "colorMapName ?dataSetName?"},
    4978     {"colormode", 7, StreamlinesColorModeOp, 3, 4, "mode ?dataSetNme?"},
    4979     {"delete",    1, StreamlinesDeleteOp, 2, 3, "?dataSetName?"},
     5048    {"add",       1, StreamlinesAddOp,            2, 3, "?dataSetName?"},
     5049    {"ccolor",    1, StreamlinesColorOp,          5, 6, "r g b ?dataSetName?"},
     5050    {"colormap",  7, StreamlinesColorMapOp,       3, 4, "colorMapName ?dataSetName?"},
     5051    {"colormode", 7, StreamlinesColorModeOp,      3, 4, "mode ?dataSetNme?"},
     5052    {"delete",    1, StreamlinesDeleteOp,         2, 3, "?dataSetName?"},
    49805053    {"edges",     1, StreamlinesEdgeVisibilityOp, 3, 4, "bool ?dataSetName?"},
    4981     {"length",    2, StreamlinesLengthOp, 3, 4, "length ?dataSetName?"},
    4982     {"lighting",  3, StreamlinesLightingOp, 3, 4, "bool ?dataSetName?"},
    4983     {"linecolor", 5, StreamlinesLineColorOp, 5, 6, "r g b ?dataSetName?"},
    4984     {"lines",     5, StreamlinesLinesOp, 2, 3, "?dataSetName?"},
    4985     {"linewidth", 5, StreamlinesLineWidthOp, 3, 4, "width ?dataSetName?"},
    4986     {"opacity",   2, StreamlinesOpacityOp, 3, 4, "val ?dataSetName?"},
    4987     {"orient",    2, StreamlinesOrientOp, 6, 7, "qw qx qy qz ?dataSetName?"},
    4988     {"pos",       1, StreamlinesPositionOp, 5, 6, "x y z ?dataSetName?"},
    4989     {"ribbons",   1, StreamlinesRibbonsOp, 4, 5, "width angle ?dataSetName?"},
    4990     {"scale",     2, StreamlinesScaleOp, 5, 6, "sx sy sz ?dataSetName?"},
    4991     {"seed",      2, StreamlinesSeedOp, 3, 14, "op params... ?dataSetName?"},
    4992     {"tubes",     1, StreamlinesTubesOp, 4, 5, "numSides radius ?dataSetName?"},
    4993     {"visible",   1, StreamlinesVisibleOp, 3, 4, "bool ?dataSetName?"}
     5054    {"length",    2, StreamlinesLengthOp,         3, 4, "length ?dataSetName?"},
     5055    {"lighting",  3, StreamlinesLightingOp,       3, 4, "bool ?dataSetName?"},
     5056    {"linecolor", 5, StreamlinesLineColorOp,      5, 6, "r g b ?dataSetName?"},
     5057    {"lines",     5, StreamlinesLinesOp,          2, 3, "?dataSetName?"},
     5058    {"linewidth", 5, StreamlinesLineWidthOp,      3, 4, "width ?dataSetName?"},
     5059    {"opacity",   2, StreamlinesOpacityOp,        3, 4, "val ?dataSetName?"},
     5060    {"orient",    2, StreamlinesOrientOp,         6, 7, "qw qx qy qz ?dataSetName?"},
     5061    {"pos",       1, StreamlinesPositionOp,       5, 6, "x y z ?dataSetName?"},
     5062    {"ribbons",   1, StreamlinesRibbonsOp,        4, 5, "width angle ?dataSetName?"},
     5063    {"scale",     2, StreamlinesScaleOp,          5, 6, "sx sy sz ?dataSetName?"},
     5064    {"seed",      2, StreamlinesSeedOp,           3, 14, "op params... ?dataSetName?"},
     5065    {"tubes",     1, StreamlinesTubesOp,          4, 5, "numSides radius ?dataSetName?"},
     5066    {"visible",   1, StreamlinesVisibleOp,        3, 4, "bool ?dataSetName?"}
    49945067};
    49955068static int nStreamlinesOps = NumCmdSpecs(streamlinesOps);
     
    52035276
    52045277static Rappture::CmdSpec volumeShadingOps[] = {
    5205     {"ambient",  1, VolumeShadingAmbientOp, 4, 5, "coeff ?dataSetName?"},
    5206     {"diffuse",  1, VolumeShadingDiffuseOp, 4, 5, "coeff ?dataSetName?"},
     5278    {"ambient",  1, VolumeShadingAmbientOp,  4, 5, "coeff ?dataSetName?"},
     5279    {"diffuse",  1, VolumeShadingDiffuseOp,  4, 5, "coeff ?dataSetName?"},
    52075280    {"specular", 1, VolumeShadingSpecularOp, 5, 6, "coeff power ?dataSetName?"}
    52085281};
     
    52415314
    52425315static Rappture::CmdSpec volumeOps[] = {
    5243     {"add",      1, VolumeAddOp, 2, 3, "?dataSetName?"},
     5316    {"add",      1, VolumeAddOp,      2, 3, "?dataSetName?"},
    52445317    {"colormap", 1, VolumeColorMapOp, 3, 4, "colorMapName ?dataSetName?"},
    5245     {"delete",   1, VolumeDeleteOp, 2, 3, "?dataSetName?"},
     5318    {"delete",   1, VolumeDeleteOp,   2, 3, "?dataSetName?"},
    52465319    {"lighting", 1, VolumeLightingOp, 3, 4, "bool ?dataSetName?"},
    5247     {"opacity",  2, VolumeOpacityOp, 3, 4, "val ?dataSetName?"},
    5248     {"orient",   2, VolumeOrientOp, 6, 7, "qw qx qy qz ?dataSetName?"},
     5320    {"opacity",  2, VolumeOpacityOp,  3, 4, "val ?dataSetName?"},
     5321    {"orient",   2, VolumeOrientOp,   6, 7, "qw qx qy qz ?dataSetName?"},
    52495322    {"pos",      1, VolumePositionOp, 5, 6, "x y z ?dataSetName?"},
    5250     {"scale",    2, VolumeScaleOp, 5, 6, "sx sy sz ?dataSetName?"},
    5251     {"shading",  2, VolumeShadingOp, 4, 6, "oper val ?dataSetName?"},
    5252     {"visible",  1, VolumeVisibleOp, 3, 4, "bool ?dataSetName?"}
     5323    {"scale",    2, VolumeScaleOp,    5, 6, "sx sy sz ?dataSetName?"},
     5324    {"shading",  2, VolumeShadingOp,  4, 6, "oper val ?dataSetName?"},
     5325    {"visible",  1, VolumeVisibleOp,  3, 4, "bool ?dataSetName?"}
    52535326};
    52545327static int nVolumeOps = NumCmdSpecs(volumeOps);
     
    52705343/**
    52715344 * \brief Execute commands from client in Tcl interpreter
     5345 *
     5346 * In this threaded model, the select call is for event compression.  We
     5347 * want to execute render server commands as long as they keep coming. 
     5348 * This lets us execute a stream of many commands but render once.  This
     5349 * benefits camera movements, screen resizing, and opacity changes
     5350 * (using a slider on the client).  The down side is you don't render
     5351 * until there's a lull in the command stream.  If the client needs an
     5352 * image, it can issue an "imgflush" command.  That breaks us out of the
     5353 * read loop.
    52725354 */
    52735355int
    5274 Rappture::VtkVis::processCommands(Tcl_Interp *interp, FILE *fin, FILE *fout)
    5275 {
    5276     Tcl_DString cmdbuffer;
    5277     Tcl_DStringInit(&cmdbuffer);
    5278 
    5279     int fdIn = fileno(fin);
    5280     int fdOut = fileno(fout);
    5281     int flags = fcntl(fdIn, F_GETFL, 0);
    5282     fcntl(fdIn, F_SETFL, flags & ~O_NONBLOCK);
    5283 
     5356Rappture::VtkVis::processCommands(Tcl_Interp *interp, ReadBuffer *inBufPtr,
     5357                                  int fdOut)
     5358{
    52845359    int status = TCL_OK;
    5285     int nCommands = 0;
    5286     bool isComplete = false;
    5287     while ((!feof(fin)) && (status == TCL_OK)) {
    5288         while (!feof(fin)) {
    5289             int c = fgetc(fin);
    5290             if (c <= 0) {
    5291                 if (errno == EWOULDBLOCK) {
    5292                     break;
    5293                 }
    5294                 if (feof(fin))
    5295                     return 1;
    5296                 else
    5297                     return c;
     5360
     5361    Tcl_DString command;
     5362    Tcl_DStringInit(&command);
     5363    fd_set readFds;
     5364    struct timeval tv, *tvPtr;
     5365
     5366    FD_ZERO(&readFds);
     5367    FD_SET(inBufPtr->file(), &readFds);
     5368    tvPtr = NULL;                       /* Wait for the first read. This is so
     5369                                         * that we don't spin when no data is
     5370                                         * available. */
     5371    while (inBufPtr->isLineAvailable() ||
     5372           (select(1, &readFds, NULL, NULL, tvPtr) > 0)) {
     5373        size_t numBytes;
     5374        unsigned char *buffer;
     5375
     5376        /* A short read is treated as an error here because we assume that we
     5377         * will always get commands line by line. */
     5378        if (inBufPtr->getLine(&numBytes, &buffer) != ReadBuffer::OK) {
     5379            /* Terminate the server if we can't communicate with the client
     5380             * anymore. */
     5381            if (inBufPtr->status() == ReadBuffer::ENDFILE) {
     5382                TRACE("Exiting server on EOF from client");
     5383                return -1;
     5384            } else {
     5385                ERROR("Exiting server, failed to read from client: %s",
     5386                      strerror(errno));
     5387                return -1;
    52985388            }
    5299             char ch = (char)c;
    5300             Tcl_DStringAppend(&cmdbuffer, &ch, 1);
    5301             if (ch == '\n') {
    5302                 isComplete = Tcl_CommandComplete(Tcl_DStringValue(&cmdbuffer));
    5303                 if (isComplete) {
    5304                     break;
    5305                 }
     5389        }
     5390        Tcl_DStringAppend(&command, (char *)buffer, numBytes);
     5391        if (Tcl_CommandComplete(Tcl_DStringValue(&command))) {
     5392            status = ExecuteCommand(interp, &command);
     5393            if (status == TCL_BREAK) {
     5394                return 1;               /* This was caused by a "imgflush"
     5395                                         * command. Break out of the read loop
     5396                                         * and allow a new image to be
     5397                                         * rendered. */
    53065398            }
    53075399        }
    5308         // no command? then we're done for now
    5309         if (Tcl_DStringLength(&cmdbuffer) == 0) {
    5310             break;
    5311         }
    5312         if (isComplete) {
    5313             // back to original flags during command evaluation...
    5314             fcntl(fdIn, F_SETFL, flags & ~O_NONBLOCK);
    5315             TRACE("command: '%s'", Tcl_DStringValue(&cmdbuffer));
    5316             status = ExecuteCommand(interp, &cmdbuffer);
    5317             // non-blocking for next read -- we might not get anything
    5318             fcntl(fdIn, F_SETFL, flags | O_NONBLOCK);
    5319             isComplete = false;
    5320             nCommands++;
    5321         }
    5322     }
    5323     fcntl(fdIn, F_SETFL, flags);
     5400        tv.tv_sec = tv.tv_usec = 0L;    /* On successive reads, we break out
     5401                                         * if no data is available. */
     5402        FD_SET(inBufPtr->file(), &readFds);
     5403        tvPtr = &tv;
     5404    }
    53245405
    53255406    if (status != TCL_OK) {
     
    53285409
    53295410        string = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
    5330         TRACE("ERROR errorInfo=(%s)", string);
    5331 
     5411        TRACE("%s: status=%d ERROR errorInfo=(%s)", Tcl_DStringValue(&command),
     5412              status, string);
    53325413        nBytes = strlen(string);
    53335414        struct iovec iov[3];
     
    53395420        iov[2].iov_len = strlen((char *)iov[2].iov_base);
    53405421        if (writev(fdOut, iov, 3) < 0) {
    5341             ERROR("write failed: %s", strerror(errno));
     5422            ERROR("write failed: %s", strerror(errno));
     5423            return -1;
    53425424        }
    53435425        return 0;
     
    53525434 * \return The initialized Tcl interpreter
    53535435 */
    5354 Tcl_Interp *
    5355 Rappture::VtkVis::initTcl()
    5356 {
    5357     Tcl_Interp *interp;
    5358     interp = Tcl_CreateInterp();
    5359 
     5436void
     5437Rappture::VtkVis::initTcl(Tcl_Interp *interp, ClientData clientData)
     5438{
    53605439    Tcl_MakeSafe(interp);
    5361 
    5362     Tcl_CreateObjCommand(interp, "axis",        AxisCmd,        NULL, NULL);
    5363     Tcl_CreateObjCommand(interp, "camera",      CameraCmd,      NULL, NULL);
    5364     Tcl_CreateObjCommand(interp, "colormap",    ColorMapCmd,    NULL, NULL);
    5365     Tcl_CreateObjCommand(interp, "contour2d",   Contour2DCmd,   NULL, NULL);
    5366     Tcl_CreateObjCommand(interp, "contour3d",   Contour3DCmd,   NULL, NULL);
    5367     Tcl_CreateObjCommand(interp, "cutplane",    CutplaneCmd,    NULL, NULL);
    5368     Tcl_CreateObjCommand(interp, "dataset",     DataSetCmd,     NULL, NULL);
    5369     Tcl_CreateObjCommand(interp, "glyphs",      GlyphsCmd,      NULL, NULL);
    5370     Tcl_CreateObjCommand(interp, "heightmap",   HeightMapCmd,   NULL, NULL);
    5371     Tcl_CreateObjCommand(interp, "legend",      LegendCmd,      NULL, NULL);
    5372     Tcl_CreateObjCommand(interp, "lic",         LICCmd,         NULL, NULL);
    5373     Tcl_CreateObjCommand(interp, "molecule",    MoleculeCmd,    NULL, NULL);
    5374     Tcl_CreateObjCommand(interp, "polydata",    PolyDataCmd,    NULL, NULL);
    5375     Tcl_CreateObjCommand(interp, "pseudocolor", PseudoColorCmd, NULL, NULL);
    5376     Tcl_CreateObjCommand(interp, "renderer",    RendererCmd,    NULL, NULL);
    5377     Tcl_CreateObjCommand(interp, "screen",      ScreenCmd,      NULL, NULL);
    5378     Tcl_CreateObjCommand(interp, "streamlines", StreamlinesCmd, NULL, NULL);
    5379     Tcl_CreateObjCommand(interp, "volume",      VolumeCmd,      NULL, NULL);
    5380     return interp;
     5440    Tcl_CreateObjCommand(interp, "axis",        AxisCmd,        clientData, NULL);
     5441    Tcl_CreateObjCommand(interp, "camera",      CameraCmd,      clientData, NULL);
     5442    Tcl_CreateObjCommand(interp, "colormap",    ColorMapCmd,    clientData, NULL);
     5443    Tcl_CreateObjCommand(interp, "contour2d",   Contour2DCmd,   clientData, NULL);
     5444    Tcl_CreateObjCommand(interp, "contour3d",   Contour3DCmd,   clientData, NULL);
     5445    Tcl_CreateObjCommand(interp, "cutplane",    CutplaneCmd,    clientData, NULL);
     5446    Tcl_CreateObjCommand(interp, "dataset",     DataSetCmd,     clientData, NULL);
     5447    Tcl_CreateObjCommand(interp, "glyphs",      GlyphsCmd,      clientData, NULL);
     5448    Tcl_CreateObjCommand(interp, "heightmap",   HeightMapCmd,   clientData, NULL);
     5449    Tcl_CreateObjCommand(interp, "imgflush",    ImageFlushCmd,  clientData, NULL);
     5450    Tcl_CreateObjCommand(interp, "legend",      LegendCmd,      clientData, NULL);
     5451    Tcl_CreateObjCommand(interp, "lic",         LICCmd,         clientData, NULL);
     5452    Tcl_CreateObjCommand(interp, "molecule",    MoleculeCmd,    clientData, NULL);
     5453    Tcl_CreateObjCommand(interp, "polydata",    PolyDataCmd,    clientData, NULL);
     5454    Tcl_CreateObjCommand(interp, "pseudocolor", PseudoColorCmd, clientData, NULL);
     5455    Tcl_CreateObjCommand(interp, "renderer",    RendererCmd,    clientData, NULL);
     5456    Tcl_CreateObjCommand(interp, "screen",      ScreenCmd,      clientData, NULL);
     5457    Tcl_CreateObjCommand(interp, "streamlines", StreamlinesCmd, clientData, NULL);
     5458    Tcl_CreateObjCommand(interp, "volume",      VolumeCmd,      clientData, NULL);
    53815459}
    53825460
    53835461/**
    53845462 * \brief Delete Tcl commands and interpreter
    5385  *
    53865463 */
    53875464void Rappture::VtkVis::exitTcl(Tcl_Interp *interp)
     
    53975474    Tcl_DeleteCommand(interp, "glyphs");
    53985475    Tcl_DeleteCommand(interp, "heightmap");
     5476    Tcl_DeleteCommand(interp, "imgflush");
    53995477    Tcl_DeleteCommand(interp, "legend");
    54005478    Tcl_DeleteCommand(interp, "lic");
  • trunk/packages/vizservers/vtkvis/RpVtkRendererCmd.h

    r2278 r2573  
    1111#include <cstdio>
    1212#include <tcl.h>
     13#include "ReadBuffer.h"
    1314
    1415namespace Rappture {
    1516namespace VtkVis {
    1617
    17 extern int processCommands(Tcl_Interp *interp, FILE *fin, FILE *fout);
    18 extern Tcl_Interp *initTcl();
     18extern int processCommands(Tcl_Interp *interp, ReadBuffer *inBufPtr,
     19                           int fdOut);
     20extern void initTcl(Tcl_Interp *interp, ClientData clientData);
    1921extern void exitTcl(Tcl_Interp *interp);
    2022
  • trunk/packages/vizservers/vtkvis/TGAWriter.cpp

    r2260 r2573  
    1717#include "TGAWriter.h"
    1818#include "Trace.h"
     19#ifdef USE_THREADS
     20#include "ResponseQueue.h"
     21#endif
     22
     23#ifdef USE_THREADS
     24
     25/**
     26 * \brief Writes image command + data to supplied file descriptor.
     27 *
     28 * The image data must be supplied in BGR(A) order with bottom to
     29 * top scanline ordering.
     30 *
     31 * \param[in] queue Pointer to ResponseQueue to write to
     32 * \param[in] cmdName Command name to send (byte length will be appended)
     33 * \param[in] data Image data
     34 * \param[in] width Width of image in pixels
     35 * \param[in] height Height of image in pixels
     36 * \param[in] bytesPerPixel Should be 3 or 4, depending on alpha
     37 */
     38void
     39Rappture::VtkVis::queueTGA(ResponseQueue *queue, const char *cmdName,
     40                           const unsigned char *data,
     41                           int width, int height,
     42                           int bytesPerPixel)
     43{
     44    TRACE("(%dx%d)\n", width, height);
     45
     46    size_t headerLength = 18;
     47
     48    char header[headerLength];
     49    memset(header, 0, headerLength);
     50    header[2] = (char)2;  // image type (2 = uncompressed true-color)
     51    header[12] = (char)width;
     52    header[13] = (char)(width >> 8);
     53    header[14] = (char)height;
     54    header[15] = (char)(height >> 8);
     55    header[16] = (char)(bytesPerPixel*8); // bits per pixel
     56
     57    size_t dataLength = width * height * bytesPerPixel;
     58    size_t cmdLength;
     59
     60    char command[200];
     61    cmdLength = snprintf(command, sizeof(command), "%s %lu\n", cmdName,
     62                         (unsigned long)headerLength + dataLength);
     63
     64    size_t length;
     65    unsigned char *mesg = NULL;
     66
     67    length = headerLength + dataLength + cmdLength;
     68    mesg = (unsigned char *)malloc(length);
     69    if (mesg == NULL) {
     70        ERROR("can't allocate %ld bytes for the image message", length);
     71        return;
     72    }
     73    memcpy(mesg, command, cmdLength);
     74    memcpy(mesg + cmdLength, header, headerLength);
     75    memcpy(mesg + cmdLength + headerLength,
     76           const_cast<unsigned char *>(data), dataLength);
     77
     78    Response *response = NULL;
     79    if (strncmp(cmdName, "nv>legend", 9) == 0) {
     80        response = new Response(Response::LEGEND);
     81    } else {
     82        response = new Response(Response::IMAGE);
     83    }
     84    response->setMessage(mesg, length, Response::DYNAMIC);
     85    queue->enqueue(response);
     86    TRACE("Leaving (%dx%d)\n", width, height);
     87}
     88#else
    1989
    2090/**
     
    79149    TRACE("Leaving (%dx%d)\n", width, height);
    80150}
     151#endif  /*USE_THREADS*/
    81152
    82153/**
  • trunk/packages/vizservers/vtkvis/TGAWriter.h

    r2260 r2573  
    99#define __RAPPTURE_VTKVIS_TGAWRITER_H__
    1010
     11#ifdef USE_THREADS
     12#include "ResponseQueue.h"
     13#endif
     14
    1115namespace Rappture {
    1216namespace VtkVis {
    13 
     17#ifdef USE_THREADS
    1418extern
    15 void writeTGA(int fd, const char *cmdName, const unsigned char *data,
    16               int width, int height, int bytesPerPixel);
    17 
     19void queueTGA(ResponseQueue *queue, const char *cmdName,
     20              const unsigned char *data, int width, int height,
     21              int bytesPerPixel);
     22#else
    1823extern
    19 void writeTGAFile(const char *filename, const unsigned char *data,
    20                   int width, int height, int bytesPerPixel,
    21                   bool srcIsRGB = false);
    22 
     24void writeTGA(int fd, const char *cmdName,
     25              const unsigned char *data, int width, int height,
     26              int bytesPerPixel);
     27#endif
     28extern
     29void writeTGAFile(const char *filename,
     30                  const unsigned char *data, int width, int height,
     31                  int bytesPerPixel, bool srcIsRGB = false);
    2332}
    2433}
  • trunk/packages/vizservers/vtkvis/Trace.cpp

    r2506 r2573  
    2121 */
    2222void
    23 Rappture::VtkVis::InitLog()
     23Rappture::VtkVis::initLog()
    2424{
    2525    openlog("vtkvis", LOG_CONS | LOG_PERROR | LOG_PID,  LOG_USER);
     
    3030 */
    3131void
    32 Rappture::VtkVis::CloseLog()
     32Rappture::VtkVis::closeLog()
    3333{
    3434    closelog();
     
    3939 */
    4040void
    41 Rappture::VtkVis::LogMessage(int priority, const char *funcname,
     41Rappture::VtkVis::logMessage(int priority, const char *funcname,
    4242                             const char *path, int lineNum, const char* fmt, ...)
    4343{
     
    6464    syslog(priority, message, length);
    6565}
    66 
    67 
  • trunk/packages/vizservers/vtkvis/Trace.h

    r2506 r2573  
    1414namespace VtkVis {
    1515
    16 extern void InitLog();
     16extern void initLog();
    1717
    18 extern void CloseLog();
     18extern void closeLog();
    1919
    20 extern void LogMessage(int priority, const char *funcname, const char *fileName, int lineNum,
    21                        const char* format, ...);
     20extern void logMessage(int priority, const char *funcname, const char *fileName,
     21                       int lineNum, const char* format, ...);
    2222
    23 #define ERROR(...)      LogMessage(LOG_ERR, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
     23#define ERROR(...)      Rappture::VtkVis::logMessage(LOG_ERR, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
    2424#ifdef WANT_TRACE
    25 #define TRACE(...)      LogMessage(LOG_DEBUG, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
     25#define TRACE(...)      Rappture::VtkVis::logMessage(LOG_DEBUG, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
    2626#else
    2727#define TRACE(...)
    28 #endif
    29 #define WARN(...)       LogMessage(LOG_WARNING, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
    30 #define INFO(...)       LogMessage(LOG_INFO, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
     28#endif  /*WANT_TRACE*/
     29#define WARN(...)       Rappture::VtkVis::logMessage(LOG_WARNING, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
     30#define INFO(...)       Rappture::VtkVis::logMessage(LOG_INFO, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
    3131
    3232}
Note: See TracChangeset for help on using the changeset viewer.