Changeset 4937 for nanovis/branches


Ignore:
Timestamp:
Jan 18, 2015, 5:28:38 AM (5 years ago)
Author:
ldelgass
Message:

merge threading

Location:
nanovis/branches/1.2
Files:
6 added
10 edited

Legend:

Unmodified
Added
Removed
  • nanovis/branches/1.2/Command.cpp

    r4904 r4937  
    5050#include "nanovis.h"
    5151#include "ReadBuffer.h"
     52#ifdef USE_THREADS
     53#include "ResponseQueue.h"
     54#endif
    5255#include "Command.h"
    5356#include "CmdProc.h"
     
    5558#include "dxReader.h"
    5659#include "VtkReader.h"
     60#include "BMPWriter.h"
     61#include "PPMWriter.h"
    5762#include "Grid.h"
    5863#include "HeightMap.h"
     
    108113static int lastCmdStatus;
    109114
     115#ifdef USE_THREADS
     116void
     117nv::queueResponse(const void *bytes, size_t len,
     118                  Response::AllocationType allocType,
     119                  Response::ResponseType type)
     120{
     121    Response *response = new Response(type);
     122    response->setMessage((unsigned char *)bytes, len, allocType);
     123    g_queue->enqueue(response);
     124}
     125#else
     126
    110127ssize_t
    111128nv::SocketWrite(const void *bytes, size_t len)
     
    123140    return bytesWritten;
    124141}
     142
     143#endif /*USE_THREADS*/
    125144
    126145bool
     
    143162    TRACE("command %lu: '%s'", g_stats.nCommands+1, cmd.c_str());
    144163#endif
    145 
    146164    lastCmdStatus = TCL_OK;
    147165    result = Tcl_EvalEx(interp, Tcl_DStringValue(dsPtr),
     
    149167                        TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL);
    150168    Tcl_DStringSetLength(dsPtr, 0);
    151 
    152169    if (lastCmdStatus == TCL_BREAK) {
    153170        return TCL_BREAK;
     
    512529nv::GetDataStream(Tcl_Interp *interp, Rappture::Buffer &buf, int nBytes)
    513530{
    514 #ifdef USE_NEW_EVENT_LOOP
     531#if defined(USE_NEW_EVENT_LOOP) || defined(USE_THREADS)
    515532    if (!SocketRead((char *)buf.bytes(), nBytes)) {
    516533        return TCL_ERROR;
     
    687704    NanoVis::render();
    688705    NanoVis::readScreen();
    689 
    690     NanoVis::ppmWrite("nv>image -type print -bytes");
     706#ifdef USE_THREADS
     707    queuePPM(g_queue, "nv>image -type print -bytes",
     708             NanoVis::screenBuffer, width, height);
     709#else
     710    writePPM(g_fdOut, "nv>image -type print -bytes",
     711             NanoVis::screenBuffer, width, height);
     712#endif
    691713    NanoVis::resizeOffscreenBuffer(origWidth, origHeight);
    692714
     
    11881210            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboOrig);
    11891211
    1190             NanoVis::bmpWriteToFile(frameNum, dirName);
     1212            /* FIXME: this function requires 4-byte aligned RGB rows,
     1213             * but screen buffer is now 1 byte aligned for PPM images.
     1214             */
     1215            writeBMPFile(frameNum, dirName,
     1216                         NanoVis::screenBuffer,
     1217                         NanoVis::winWidth, NanoVis::winHeight);
    11911218        }
    11921219    }
     
    13561383                    volume->wAxis.min(), volume->wAxis.max(),
    13571384                    Volume::valueMin, Volume::valueMax);
     1385#ifdef USE_THREADS
     1386        queueResponse(info, cmdLength, Response::VOLATILE);
     1387#else
    13581388        if (SocketWrite(info, (size_t)cmdLength) != (ssize_t)cmdLength) {
    13591389            ERROR("Short write");
    13601390            return TCL_ERROR;
    13611391        }
     1392#endif
    13621393    }
    13631394
     
    22902321            nBytes = ostr.length();
    22912322
     2323#ifdef USE_THREADS
     2324            queueResponse(ostr.c_str(), nBytes, Response::VOLATILE, Response::ERROR);
     2325#else
    22922326            if (write(fdOut, oss.str().c_str(), nBytes) < 0) {
    22932327                ERROR("write failed: %s", strerror(errno));
    22942328                return -1;
    22952329            }
     2330#endif
    22962331        }
    22972332    }
     
    23082343        nBytes = ostr.length();
    23092344
     2345#ifdef USE_THREADS
     2346        queueResponse(ostr.c_str(), nBytes, Response::VOLATILE, Response::ERROR);
     2347#else
    23102348        if (write(fdOut, ostr.c_str(), nBytes) < 0) {
    23112349            ERROR("write failed: %s", strerror(errno));
    23122350            return -1;
    23132351        }
     2352#endif
    23142353        clearUserMessages();
    23152354    }
  • nanovis/branches/1.2/Command.h

    r4889 r4937  
    1616#include <tcl.h>
    1717
     18#include "ResponseQueue.h"
     19
    1820namespace Rappture {
    1921class Buffer;
     
    2527class Volume;
    2628
     29#ifdef USE_THREADS
     30extern void queueResponse(const void *bytes, size_t len,
     31                          Response::AllocationType allocType,
     32                          Response::ResponseType type = Response::DATA);
     33#else
    2734extern ssize_t SocketWrite(const void *bytes, size_t len);
     35#endif
    2836
    2937extern bool SocketRead(char *bytes, size_t len);
  • nanovis/branches/1.2/FlowCmd.cpp

    r4904 r4937  
    55 */
    66#include <assert.h>
    7 #include <errno.h>
    87#define _OPEN_SYS
    98#include <fcntl.h>
     
    3231#include "CmdProc.h"
    3332#include "Command.h"
     33#include "PPMWriter.h"
    3434#include "FlowCmd.h"
    3535#include "FlowTypes.h"
     
    232232            sprintf(info, "nv>data tag %s min %g max %g\n",
    233233                    flow->name(), unirect->magMin(), unirect->magMax());
     234#ifdef USE_THREADS
     235        queueResponse(info, (size_t)length, Response::VOLATILE);
     236#else
    234237        if (SocketWrite(info, (size_t)length) < 0) {
    235238            return TCL_ERROR;
    236239        }
     240#endif
    237241    }
    238242    Flow::updatePending = true;
     
    10021006
    10031007static bool
    1004 ppmWriteToFile(const char *path, const unsigned char *imgData,
    1005                int width, int height)
    1006 {
    1007     /* Open the named file for writing. */
    1008     int fdOut = creat(path, 0600);
    1009     if (fdOut < 0) {
    1010         ERROR("can't open temporary image file \"%s\": %s", path, strerror(errno));
    1011         return false;
    1012     }
    1013     // Generate the PPM binary file header
    1014     char header[200];
    1015 #define PPM_MAXVAL 255
    1016     sprintf(header, "P6 %d %d %d\n", width, height,
    1017         PPM_MAXVAL);
    1018 
    1019     size_t header_length = strlen(header);
    1020     size_t wordsPerRow = (width * 24 + 31) / 32;
    1021     size_t bytesPerRow = wordsPerRow * 4;
    1022     size_t rowLength = width * 3;
    1023     size_t numRecords = height + 1;
    1024 
    1025     struct iovec *iov;
    1026     iov = (struct iovec *)malloc(sizeof(struct iovec) * numRecords);
    1027 
    1028     // Add the PPM image header.
    1029     iov[0].iov_base = header;
    1030     iov[0].iov_len = header_length;
    1031 
    1032     // Now add the image data, reversing the order of the rows.
    1033     int y;
    1034     unsigned char *srcRowPtr = const_cast<unsigned char *>(imgData);
    1035     /* Reversing the pointers for the image rows.  PPM is top-to-bottom. */
    1036     for (y = height; y >= 1; y--) {
    1037         iov[y].iov_base = srcRowPtr;
    1038         iov[y].iov_len = rowLength;
    1039         srcRowPtr += bytesPerRow;
    1040     }
    1041     if (writev(fdOut, iov, numRecords) < 0) {
    1042         ERROR("writing image to \"%s\" failed: %s", path, strerror(errno));
    1043         free(iov);
    1044         close(fdOut);
    1045         return false;
    1046     }
    1047     close(fdOut);
    1048     free(iov);
    1049     return true;
    1050 }
    1051 
    1052 static bool
    10531008MakeImageFiles(char *tmpFileName,
    10541009               int width, int height, int numFrames,
     
    10811036            break;
    10821037        }
     1038
    10831039        NanoVis::licRenderer->convolve();
    10841040        NanoVis::advectFlows();
     
    10941050
    10951051        sprintf(tmpFileName + length, "/image%d.ppm", i);
    1096         result = ppmWriteToFile(tmpFileName, NanoVis::screenBuffer,
    1097                                 width, height);
     1052        result = nv::writePPMFile(tmpFileName, NanoVis::screenBuffer,
     1053                                  width, height);
    10981054        if (!result) {
    10991055            break;
     
    11301086    /* The ffmpeg command is
    11311087     *   ffmpeg -f image2 -i /var/tmp/xxxxx/image%d.ppm                 \
    1132      *      -b bitrate -f framerate /var/tmp/xxxxx/movie.mpeg
     1088     *      -f outformat -b bitrate -r framerate /var/tmp/xxxxx/movie.mpeg
    11331089     */
    11341090#ifndef FFMPEG
     
    11461102        return TCL_ERROR;
    11471103    }
    1148     Rappture::Buffer data;
     1104    char *data = NULL;
    11491105    size_t total = 0;
    11501106    for (;;) {
    11511107        char buffer[BUFSIZ];
    11521108       
    1153         ssize_t numRead = fread(buffer, sizeof(unsigned char), BUFSIZ, f);
     1109        ssize_t numRead = fread(buffer, sizeof(char), BUFSIZ, f);
    11541110        total += numRead;
    11551111        if (numRead == 0) {             // EOF
     
    11631119            return TCL_ERROR;
    11641120        }
    1165         if (!data.append(buffer, numRead)) {
     1121        data = (char *)realloc(data, total);
     1122        if (data == NULL) {
    11661123            ERROR("Can't append movie data to buffer %d bytes",
    11671124                  numRead);
     
    11701127            return TCL_ERROR;
    11711128        }
    1172     }
    1173     if (data.size() == 0) {
     1129        memcpy(data + (total - numRead), buffer, numRead);
     1130    }
     1131    if (total == 0) {
    11741132        ERROR("ffmpeg returned 0 bytes");
    11751133    }
    11761134    // Send zero length to client so it can deal with error
    11771135    sprintf(cmd,"nv>image -type movie -token \"%s\" -bytes %lu\n",
    1178             token, (unsigned long)data.size());
    1179     nv::sendDataToClient(cmd, data.bytes(), data.size());
     1136            token, total);
     1137    // Memory for data payload is freed by this call
     1138    nv::sendDataToClient(cmd, data, total);
    11801139    return TCL_OK;
    11811140}
  • nanovis/branches/1.2/Makefile.in

    r4920 r4937  
    11TRACE                   = #yes
     2USE_THREADS             = yes
    23USE_POINTSET_RENDERER   = #yes
    34USE_PARTICLE_SYSTEM     = #yes
     
    6263LD_RUN_PATH     = $(libdir):@LD_RPATH@
    6364
    64 SVN_VERSION     = $(shell svnversion $(srcdir))
     65SVN_VERSION     = $(shell svnversion $(srcdir) | sed 's/Unversioned directory/unknown/')
    6566STATSDIR        = @STATSDIR@
    6667
     
    9798DEFINES         += -DWANT_TRACE
    9899endif
     100ifdef USE_THREADS
     101DEFINES         += -DUSE_THREADS
     102endif
    99103ifdef USE_POINTSET_RENDERER
    100104DEFINES         += -DUSE_POINTSET_RENDERER
     
    104108OBJS            = \
    105109                Axis.o \
     110                BMPWriter.o \
    106111                Camera.o \
    107112                Chain.o \
     
    124129                Plane.o \
    125130                PlaneRenderer.o \
     131                PPMWriter.o \
    126132                ReadBuffer.o \
    127133                ReaderCommon.o \
    128134                RegularVolumeShader.o \
    129135                RenderVertexArray.o \
     136                ResponseQueue.o \
    130137                Shader.o \
    131138                StdVertexShader.o \
     
    271278
    272279Axis.o: Axis.cpp Axis.h Chain.h
     280BMPWriter.o: BMPWriter.cpp BMPWriter.h nanovis.h
    273281BucketSort.o: BucketSort.cpp BucketSort.h $(VRMATH_DIR)/include/vrmath/Vector3f.h $(VRMATH_DIR)/include/vrmath/Vector4f.h $(VRMATH_DIR)/include/vrmath/Matrix4x4d.h PCASplit.h
    274282Camera.o: Camera.cpp Camera.h config.h $(VRMATH_DIR)/include/vrmath/Matrix4x4d.h
     
    276284CmdProc.o: CmdProc.cpp CmdProc.h
    277285ColorTableShader.o: ColorTableShader.cpp ColorTableShader.h Shader.h
    278 Command.o: Command.cpp nanovis.h nanovisServer.h ReadBuffer.h config.h define.h FlowCmd.h CmdProc.h Trace.h PlaneRenderer.h dxReader.h Grid.h HeightMap.h Camera.h ZincBlendeReconstructor.h Unirect.h Volume.h VolumeRenderer.h
     286Command.o: Command.cpp nanovis.h nanovisServer.h ReadBuffer.h ResponseQueue.h config.h define.h FlowCmd.h CmdProc.h Trace.h PlaneRenderer.h PPMWriter.h BMPWriter.h dxReader.h Grid.h HeightMap.h Camera.h ZincBlendeReconstructor.h Unirect.h Volume.h VolumeRenderer.h
    279287ContourLineFilter.o: ContourLineFilter.cpp ContourLineFilter.h
    280288ConvexPolygon.o: ConvexPolygon.cpp ConvexPolygon.h $(VRMATH_DIR)/include/vrmath/Vector4f.h $(VRMATH_DIR)/include/vrmath/Matrix4x4d.h Plane.h
    281289Flow.o: Flow.cpp Flow.h FlowCmd.h FlowTypes.h FlowBox.h FlowParticles.h LIC.h VelocityArrowsSlice.h Switch.h Unirect.h Volume.h TransferFunction.h Trace.h
    282290FlowBox.o: FlowBox.cpp FlowBox.h FlowTypes.h Switch.h Trace.h Volume.h $(VRMATH_DIR)/include/vrmath/Vector3f.h $(VRMATH_DIR)/include/vrmath/Vector4f.h $(VRMATH_DIR)/include/vrmath/Matrix4x4d.h
    283 <FlowCmd.o: FlowCmd.cpp FlowCmd.h FlowParticles.h FlowBox.h FlowTypes.h Command.h Switch.h Trace.h TransferFunction.h nanovis.h nanovisServer.h CmdProc.h LIC.h Unirect.h Volume.h VelocityArrowsSlice.h $(VRMATH_DIR)/include/vrmath/Vector3f.h
     291FlowCmd.o: FlowCmd.cpp FlowCmd.h FlowParticles.h FlowBox.h FlowTypes.h Command.h PPMWriter.h Switch.h Trace.h TransferFunction.h nanovis.h nanovisServer.h CmdProc.h LIC.h Unirect.h Volume.h VelocityArrowsSlice.h $(VRMATH_DIR)/include/vrmath/Vector3f.h
    284292FlowParticles.o: FlowParticles.cpp FlowParticles.h FlowTypes.h FlowCmd.h Switch.h Trace.h ParticleRenderer.h Volume.h $(VRMATH_DIR)/include/vrmath/Vector3f.h $(VRMATH_DIR)/include/vrmath/Vector4f.h
    285293GradientFilter.o: GradientFilter.cpp GradientFilter.h
     
    299307PointSetRenderer.o: PointSetRenderer.cpp PointSetRenderer.h
    300308PointShader.o: PointShader.cpp PointShader.h
     309PPMWriter.o: PPMWriter.cpp PPMWriter.h
    301310ReadBuffer.o: ReadBuffer.cpp ReadBuffer.h Trace.h
    302311ReaderCommon.o: ReaderCommon.cpp ReaderCommon.h GradientFilter.h $(VRMATH_DIR)/include/vrmath/Vector3f.h
     
    324333md5.o: md5.h
    325334nanovis.o: nanovis.cpp nanovis.h nanovisServer.h config.h define.h Command.h Flow.h Grid.h HeightMap.h Camera.h LIC.h ZincBlendeReconstructor.h PerfQuery.h PlaneRenderer.h PointSetRenderer.h PointSet.h Switch.h Trace.h Unirect.h VelocityArrowsSlice.h VolumeInterpolator.h VolumeRenderer.h ZincBlendeVolume.h Axis.h Chain.h $(UTIL_DIR)/Fonts.h
    326 nanovisServer.o: nanovisServer.cpp nanovisServer.h config.h nanovis.h define.h Command.h ReadBuffer.h Shader.h Trace.h
     335nanovisServer.o: nanovisServer.cpp nanovisServer.h config.h nanovis.h define.h Command.h PPMWriter.h ReadBuffer.h Shader.h ResponseQueue.h Trace.h
  • nanovis/branches/1.2/configure

    r4904 r4937  
    11#! /bin/sh
    22# Guess values for system-dependent variables and create Makefiles.
    3 # Generated by GNU Autoconf 2.69 for nanovis 1.1.
     3# Generated by GNU Autoconf 2.69 for nanovis 1.2.
    44#
    55# Report bugs to <rappture@nanohub.org>.
     
    581581PACKAGE_NAME='nanovis'
    582582PACKAGE_TARNAME='nanovis'
    583 PACKAGE_VERSION='1.1'
    584 PACKAGE_STRING='nanovis 1.1'
     583PACKAGE_VERSION='1.2'
     584PACKAGE_STRING='nanovis 1.2'
    585585PACKAGE_BUGREPORT='rappture@nanohub.org'
    586586PACKAGE_URL=''
     
    12561256  # This message is too long to be a string in the A/UX 3.1 sh.
    12571257  cat <<_ACEOF
    1258 \`configure' configures nanovis 1.1 to adapt to many kinds of systems.
     1258\`configure' configures nanovis 1.2 to adapt to many kinds of systems.
    12591259
    12601260Usage: $0 [OPTION]... [VAR=VALUE]...
     
    13171317if test -n "$ac_init_help"; then
    13181318  case $ac_init_help in
    1319      short | recursive ) echo "Configuration of nanovis 1.1:";;
     1319     short | recursive ) echo "Configuration of nanovis 1.2:";;
    13201320   esac
    13211321  cat <<\_ACEOF
     
    14111411if $ac_init_version; then
    14121412  cat <<\_ACEOF
    1413 nanovis configure 1.1
     1413nanovis configure 1.2
    14141414generated by GNU Autoconf 2.69
    14151415
     
    18551855running configure, to aid debugging if configure makes a mistake.
    18561856
    1857 It was created by nanovis $as_me 1.1, which was
     1857It was created by nanovis $as_me 1.2, which was
    18581858generated by GNU Autoconf 2.69.  Invocation command line was
    18591859
     
    55065506# values after options handling.
    55075507ac_log="
    5508 This file was extended by nanovis $as_me 1.1, which was
     5508This file was extended by nanovis $as_me 1.2, which was
    55095509generated by GNU Autoconf 2.69.  Invocation command line was
    55105510
     
    55685568ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
    55695569ac_cs_version="\\
    5570 nanovis config.status 1.1
     5570nanovis config.status 1.2
    55715571configured by $0, generated by GNU Autoconf 2.69,
    55725572  with options \\"\$ac_cs_config\\"
  • nanovis/branches/1.2/configure.in

    r4904 r4937  
    11AC_PREREQ([2.60])
    2 AC_INIT([nanovis], [1.1], [rappture@nanohub.org])
     2AC_INIT([nanovis], [1.2], [rappture@nanohub.org])
    33AC_CONFIG_AUX_DIR(cf)
    44AC_CONFIG_HEADERS([nvconf.h])
  • nanovis/branches/1.2/nanovis.cpp

    r4904 r4937  
    1717
    1818#include <sys/time.h>
    19 #include <sys/types.h>
    20 #include <sys/uio.h> // for writev in ppmWrite
    21 #include <unistd.h>
    22 
    2319#include <cassert>
    24 #include <cerrno>
    25 #include <cstdlib>
    2620#include <cstdio>
    27 #include <cstring>
    28 #include <cmath>
    29 
    30 #include <string>
    3121
    3222#include <GL/glew.h>
     
    5444#include "Shader.h"
    5545#include "PlaneRenderer.h"
     46#include "PPMWriter.h"
    5647#include "Texture2D.h"
    5748#include "Trace.h"
     
    6758using namespace nv::util;
    6859using namespace vrmath;
    69 
    70 #define SIZEOF_BMP_HEADER   54
    7160
    7261// STATIC MEMBER DATA
     
    332321    planeRenderer->render();
    333322
    334     //glPixelStorei(GL_PACK_ALIGNMENT, 1);
     323    glPixelStorei(GL_PACK_ALIGNMENT, 1);
    335324    glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, screenBuffer);
    336325    {
     
    339328        TRACE("Sending ppm legend image %s min:%g max:%g", volArg, min, max);
    340329        sprintf(prefix, "nv>legend %s %g %g", volArg, min, max);
    341         ppmWrite(prefix);
     330#ifdef USE_THREADS
     331        queuePPM(g_queue, prefix, screenBuffer, width, height);
     332#else
     333        writePPM(g_fdOut, prefix, screenBuffer, width, height);
     334#endif
    342335    }
    343336    planeRenderer->removePlane(index);
     
    361354    glGenTextures(1, &_finalColorTex);
    362355    glBindTexture(GL_TEXTURE_2D, _finalColorTex);
    363 
    364     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    365     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    366     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    367 
     356    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
     357    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    368358#if defined(HAVE_FLOAT_TEXTURES) && defined(USE_HALF_FLOAT)
    369359    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, winWidth, winHeight, 0,
     
    418408    }
    419409
    420     screenBuffer = new unsigned char[4*winWidth*winHeight];
     410    screenBuffer = new unsigned char[3*winWidth*winHeight];
    421411    assert(screenBuffer != NULL);
    422412
     
    435425    glGenTextures(1, &_finalColorTex);
    436426    glBindTexture(GL_TEXTURE_2D, _finalColorTex);
    437 
    438     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    439     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    440     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    441 
     427    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
     428    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    442429#if defined(HAVE_FLOAT_TEXTURES) && defined(USE_HALF_FLOAT)
    443430    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, winWidth, winHeight, 0,
     
    557544        screenBuffer = NULL;
    558545    }
    559     screenBuffer = new unsigned char[4*winWidth*winHeight];
     546    screenBuffer = new unsigned char[3*winWidth*winHeight];
    560547    assert(screenBuffer != NULL);
    561548
     
    609596
    610597    return true;
    611 }
    612 
    613 // used internally to build up the BMP file header
    614 // Writes an integer value into the header data structure at pos
    615 static inline void
    616 bmpHeaderAddInt(unsigned char* header, int& pos, int data)
    617 {
    618 #ifdef WORDS_BIGENDIAN
    619     header[pos++] = (data >> 24) & 0xFF;
    620     header[pos++] = (data >> 16) & 0xFF;
    621     header[pos++] = (data >> 8)  & 0xFF;
    622     header[pos++] = (data)       & 0xFF;
    623 #else
    624     header[pos++] = data & 0xff;
    625     header[pos++] = (data >> 8) & 0xff;
    626     header[pos++] = (data >> 16) & 0xff;
    627     header[pos++] = (data >> 24) & 0xff;
    628 #endif
    629 }
    630 
    631 void
    632 NanoVis::bmpWriteToFile(int frame_number, const char *directory_name)
    633 {
    634     unsigned char header[SIZEOF_BMP_HEADER];
    635     int pos = 0;
    636     header[pos++] = 'B';
    637     header[pos++] = 'M';
    638 
    639     // BE CAREFUL:  BMP files must have an even multiple of 4 bytes
    640     // on each scan line.  If need be, we add padding to each line.
    641     int pad = 0;
    642     if ((3*winWidth) % 4 > 0) {
    643         pad = 4 - ((3*winWidth) % 4);
    644     }
    645 
    646     // file size in bytes
    647     int fsize = (3*winWidth+pad)*winHeight + SIZEOF_BMP_HEADER;
    648     bmpHeaderAddInt(header, pos, fsize);
    649 
    650     // reserved value (must be 0)
    651     bmpHeaderAddInt(header, pos, 0);
    652 
    653     // offset in bytes to start of bitmap data
    654     bmpHeaderAddInt(header, pos, SIZEOF_BMP_HEADER);
    655 
    656     // size of the BITMAPINFOHEADER
    657     bmpHeaderAddInt(header, pos, 40);
    658 
    659     // width of the image in pixels
    660     bmpHeaderAddInt(header, pos, winWidth);
    661 
    662     // height of the image in pixels
    663     bmpHeaderAddInt(header, pos, winHeight);
    664 
    665     // 1 plane + (24 bits/pixel << 16)
    666     bmpHeaderAddInt(header, pos, 1572865);
    667 
    668     // no compression
    669     // size of image for compression
    670     bmpHeaderAddInt(header, pos, 0);
    671     bmpHeaderAddInt(header, pos, 0);
    672 
    673     // x pixels per meter
    674     // y pixels per meter
    675     bmpHeaderAddInt(header, pos, 0);
    676     bmpHeaderAddInt(header, pos, 0);
    677 
    678     // number of colors used (0 = compute from bits/pixel)
    679     // number of important colors (0 = all colors important)
    680     bmpHeaderAddInt(header, pos, 0);
    681     bmpHeaderAddInt(header, pos, 0);
    682 
    683     // BE CAREFUL: BMP format wants BGR ordering for screen data
    684     unsigned char* scr = screenBuffer;
    685     for (int row=0; row < winHeight; row++) {
    686         for (int col=0; col < winWidth; col++) {
    687             unsigned char tmp = scr[2];
    688             scr[2] = scr[0];  // B
    689             scr[0] = tmp;     // R
    690             scr += 3;
    691         }
    692         scr += pad;  // skip over padding already in screen data
    693     }
    694 
    695     FILE* f;
    696     char filename[100];
    697     if (frame_number >= 0) {
    698         if (directory_name)
    699             sprintf(filename, "%s/image%03d.bmp", directory_name, frame_number);
    700         else
    701             sprintf(filename, "/tmp/flow_animation/image%03d.bmp", frame_number);
    702 
    703         TRACE("Writing %s", filename);
    704         f = fopen(filename, "wb");
    705         if (f == 0) {
    706             ERROR("cannot create file");
    707         }
    708     } else {
    709         f = fopen("/tmp/image.bmp", "wb");
    710         if (f == 0) {
    711             ERROR("cannot create file");
    712         }
    713     }
    714     if (fwrite(header, SIZEOF_BMP_HEADER, 1, f) != 1) {
    715         ERROR("can't write header: short write");
    716     }
    717     if (fwrite(screenBuffer, (3*winWidth+pad)*winHeight, 1, f) != 1) {
    718         ERROR("can't write data: short write");
    719     }
    720     fclose(f);
    721 }
    722 
    723 void
    724 NanoVis::bmpWrite(const char *prefix)
    725 {
    726     unsigned char header[SIZEOF_BMP_HEADER];
    727     ssize_t nWritten;
    728     int pos = 0;
    729 
    730     // BE CAREFUL:  BMP files must have an even multiple of 4 bytes
    731     // on each scan line.  If need be, we add padding to each line.
    732     int pad = 0;
    733     if ((3*winWidth) % 4 > 0) {
    734         pad = 4 - ((3*winWidth) % 4);
    735     }
    736     pad = 0;
    737     int fsize = (3*winWidth+pad)*winHeight + sizeof(header);
    738 
    739     char string[200];
    740     sprintf(string, "%s %d\n", prefix, fsize);
    741     nWritten = write(g_fdOut, string, strlen(string));
    742     assert(nWritten == (ssize_t)strlen(string));
    743     header[pos++] = 'B';
    744     header[pos++] = 'M';
    745 
    746     // file size in bytes
    747     bmpHeaderAddInt(header, pos, fsize);
    748 
    749     // reserved value (must be 0)
    750     bmpHeaderAddInt(header, pos, 0);
    751 
    752     // offset in bytes to start of bitmap data
    753     bmpHeaderAddInt(header, pos, SIZEOF_BMP_HEADER);
    754 
    755     // size of the BITMAPINFOHEADER
    756     bmpHeaderAddInt(header, pos, 40);
    757 
    758     // width of the image in pixels
    759     bmpHeaderAddInt(header, pos, winWidth);
    760 
    761     // height of the image in pixels
    762     bmpHeaderAddInt(header, pos, winHeight);
    763 
    764     // 1 plane + (24 bits/pixel << 16)
    765     bmpHeaderAddInt(header, pos, 1572865);
    766 
    767     // no compression
    768     // size of image for compression
    769     bmpHeaderAddInt(header, pos, 0);
    770     bmpHeaderAddInt(header, pos, 0);
    771 
    772     // x pixels per meter
    773     // y pixels per meter
    774     bmpHeaderAddInt(header, pos, 0);
    775     bmpHeaderAddInt(header, pos, 0);
    776 
    777     // number of colors used (0 = compute from bits/pixel)
    778     // number of important colors (0 = all colors important)
    779     bmpHeaderAddInt(header, pos, 0);
    780     bmpHeaderAddInt(header, pos, 0);
    781 
    782     // BE CAREFUL: BMP format wants BGR ordering for screen data
    783     unsigned char* scr = screenBuffer;
    784     for (int row=0; row < winHeight; row++) {
    785         for (int col=0; col < winWidth; col++) {
    786             unsigned char tmp = scr[2];
    787             scr[2] = scr[0];  // B
    788             scr[0] = tmp;     // R
    789             scr += 3;
    790         }
    791         scr += pad;  // skip over padding already in screen data
    792     }
    793 
    794     nWritten = write(g_fdOut, header, SIZEOF_BMP_HEADER);
    795     assert(nWritten == SIZEOF_BMP_HEADER);
    796     nWritten = write(g_fdOut, screenBuffer, (3*winWidth+pad)*winHeight);
    797     assert(nWritten == (3*winWidth+pad)*winHeight);
    798     g_stats.nFrames++;
    799     g_stats.nFrameBytes += (3*winWidth+pad)*winHeight;
    800 }
    801 
    802 /*
    803  * ppmWrite --
    804  *
    805  *  Writes the screen image as PPM binary data to the nanovisviewer
    806  *  client.  The PPM binary format is very simple.
    807  *
    808  *      P6 w h 255\n
    809  *      3-byte RGB pixel data.
    810  *
    811  *  The nanovisviewer client (using the TkImg library) will do less work
    812  *  to unpack this format, as opposed to BMP or PNG.  (This doesn't
    813  *  eliminate the need to look into DXT compression performed on the GPU).
    814  *
    815  *      Note that currently the image data from the screen is both row-padded
    816  *      and the scan lines are reversed.  This routine could be made even
    817  *      simpler (faster) if the screen buffer is an array of packed 3-bytes
    818  *      per pixels (no padding) and where the origin is the top-left corner.
    819  */
    820 void
    821 NanoVis::ppmWrite(const char *prefix)
    822 {
    823 #define PPM_MAXVAL 255
    824     char header[200];
    825 
    826     TRACE("Enter (%dx%d)", winWidth, winHeight);
    827     // Generate the PPM binary file header
    828     sprintf(header, "P6 %d %d %d\n", winWidth, winHeight, PPM_MAXVAL);
    829 
    830     size_t header_length = strlen(header);
    831     size_t data_length = winWidth * winHeight * 3;
    832 
    833     char command[200];
    834     sprintf(command, "%s %lu\n", prefix,
    835             (unsigned long)header_length + data_length);
    836 
    837     size_t wordsPerRow = (winWidth * 24 + 31) / 32;
    838     size_t bytesPerRow = wordsPerRow * 4;
    839     size_t rowLength = winWidth * 3;
    840     size_t nRecs = winHeight + 2;
    841 
    842     struct iovec *iov;
    843     iov = (struct iovec *)malloc(sizeof(struct iovec) * nRecs);
    844 
    845     // Write the nanovisviewer command, then the image header and data.
    846     // Command
    847     iov[0].iov_base = command;
    848     iov[0].iov_len = strlen(command);
    849     // Header of image data
    850     iov[1].iov_base = header;
    851     iov[1].iov_len = header_length;
    852     // Image data.
    853     int y;
    854     unsigned char *srcRowPtr = screenBuffer;
    855     for (y = winHeight + 1; y >= 2; y--) {
    856         iov[y].iov_base = srcRowPtr;
    857         iov[y].iov_len = rowLength;
    858         srcRowPtr += bytesPerRow;
    859     }
    860     if (writev(g_fdOut, iov, nRecs) < 0) {
    861         ERROR("write failed: %s", strerror(errno));
    862     }
    863     free(iov);
    864     g_stats.nFrames++;
    865     g_stats.nFrameBytes += (bytesPerRow * winHeight);
    866     TRACE("Leave (%dx%d)", winWidth, winHeight);
    867598}
    868599
  • nanovis/branches/1.2/nanovis.h

    r4904 r4937  
    8989    static void eventuallyRedraw();
    9090
    91     static void ppmWrite(const char *prefix);
    92     static void bmpWrite(const char *prefix);
    93     static void bmpWriteToFile(int frameNum, const char* dirName);
    94  
    9591    static TransferFunction *getTransferFunction(const TransferFunctionId& id);
    9692    static TransferFunction *defineTransferFunction(const TransferFunctionId& id,
     
    108104    static void readScreen()
    109105    {
    110         //glPixelStorei(GL_PACK_ALIGNMENT, 1);
     106        glPixelStorei(GL_PACK_ALIGNMENT, 1);
    111107        glReadPixels(0, 0, winWidth, winHeight, GL_RGB, GL_UNSIGNED_BYTE,
    112108                     screenBuffer);
  • nanovis/branches/1.2/nanovisServer.cpp

    r4904 r4937  
    1010#include <cstring>
    1111#include <csignal>
    12 #include <ctime>
    1312
    1413#include <fcntl.h>
     
    3433#include "define.h"
    3534#include "Command.h"
     35#include "PPMWriter.h"
    3636#include "ReadBuffer.h"
    3737#include "Shader.h"
     38#ifdef USE_THREADS
     39#include <pthread.h>
     40#include "ResponseQueue.h"
     41#endif
    3842#include "Trace.h"
    3943
     
    4347Stats nv::g_stats;
    4448int nv::g_statsFile = -1; ///< Stats output file descriptor.
     49
    4550int nv::g_fdIn = STDIN_FILENO;     ///< Input file descriptor
    4651int nv::g_fdOut = STDOUT_FILENO;   ///< Output file descriptor
     
    4954FILE *nv::g_fLog = NULL;           ///< Trace logging file handle
    5055ReadBuffer *nv::g_inBufPtr = NULL; ///< Socket read buffer
     56#ifdef USE_THREADS
     57ResponseQueue *nv::g_queue = NULL;
     58#endif
     59
     60#ifdef USE_THREADS
     61
     62static void
     63queueFrame(ResponseQueue *queue, unsigned char *imgData)
     64{
     65    queuePPM(queue, "nv>image -type image -bytes",
     66             imgData,
     67             NanoVis::winWidth,
     68             NanoVis::winHeight);
     69}
     70
     71#else
    5172
    5273static void
    5374writeFrame(int fd, unsigned char *imgData)
    5475{
    55 #if 0
    5676    writePPM(fd, "nv>image -type image -bytes",
    5777             imgData,
    5878             NanoVis::winWidth,
    5979             NanoVis::winHeight);
    60 #else
    61     NanoVis::ppmWrite("nv>image -type image -bytes");
    62 #endif
    63 }
     80}
     81
     82#endif /*USE_THREADS*/
    6483
    6584static int
     
    7291
    7392    TRACE("Sending OK for commands through %lu", g_stats.nCommands);
     93#ifdef USE_THREADS
     94    queueResponse(str.c_str(), numBytes, Response::VOLATILE, Response::OK);
     95#else
    7496    if (write(g_fdOut, str.c_str(), numBytes) < 0) {
    7597        ERROR("write failed: %s", strerror(errno));
    7698        return -1;
    7799    }
     100#endif
    78101    return 0;
    79102}
     
    263286/**
    264287 * \brief Send a command with data payload
     288 *
     289 * data pointer is freed on completion of the response
    265290 */
    266291void
    267 nv::sendDataToClient(const char *command, const char *data, size_t dlen)
    268 {
     292nv::sendDataToClient(const char *command, char *data, size_t dlen)
     293{
     294#ifdef USE_THREADS
     295    char *buf = (char *)malloc(strlen(command) + dlen);
     296    memcpy(buf, command, strlen(command));
     297    memcpy(buf + strlen(command), data, dlen);
     298    queueResponse(buf, strlen(command) + dlen, Response::DYNAMIC);
     299#else
    269300    size_t numRecords = 2;
    270301    struct iovec *iov = new iovec[numRecords];
     
    275306    iov[0].iov_len = strlen(command);
    276307    // Data
    277     iov[1].iov_base = const_cast<char *>(data);
     308    iov[1].iov_base = data;
    278309    iov[1].iov_len = dlen;
    279310    if (writev(g_fdOut, iov, numRecords) < 0) {
     
    281312    }
    282313    delete [] iov;
     314#endif
     315    free(data);
    283316}
    284317
     
    349382}
    350383
    351 #ifndef USE_NEW_EVENT_LOOP
     384#if !defined(USE_NEW_EVENT_LOOP) && !defined(USE_THREADS)
    352385
    353386static int
     
    452485    glutSetWindow(NanoVis::renderWindow);
    453486
    454 #ifdef USE_NEW_EVENT_LOOP
     487#if defined(USE_NEW_EVENT_LOOP) || defined(USE_THREADS)
    455488    if (nv::processCommands(NanoVis::interp, g_inBufPtr, g_fdOut) < 0) {
    456489        exitService(1);
     
    469502        TRACE("Rendering new frame");
    470503        NanoVis::readScreen();
     504#ifdef USE_THREADS
     505        queueFrame(g_queue, NanoVis::screenBuffer);
     506#else
    471507        writeFrame(g_fdOut, NanoVis::screenBuffer);
     508#endif
     509        g_stats.nFrames++;
     510        g_stats.nFrameBytes += NanoVis::winWidth * NanoVis::winHeight * 3;
    472511    } else {
    473512        TRACE("No render required");
     
    475514    }
    476515
    477 #ifdef USE_NEW_EVENT_LOOP
     516#if defined(USE_NEW_EVENT_LOOP) || defined(USE_THREADS)
    478517    if (g_inBufPtr->status() == ReadBuffer::ENDFILE) {
    479518        exitService(0);
     
    487526    TRACE("Leave");
    488527}
     528
     529#ifdef USE_THREADS
     530
     531static void *
     532writerThread(void *clientData)
     533{
     534    ResponseQueue *queue = (ResponseQueue *)clientData;
     535
     536    TRACE("Starting writer thread");
     537    for (;;) {
     538        Response *response = queue->dequeue();
     539        if (response == NULL)
     540            continue;
     541        if (fwrite(response->message(), sizeof(char), response->length(),
     542                   g_fOut) != response->length()) {
     543            ERROR("short write while trying to write %ld bytes",
     544                  response->length());
     545        }
     546        fflush(g_fOut);
     547        TRACE("Wrote response of type %d", response->type());
     548        delete response;
     549        if (feof(g_fOut))
     550            break;
     551    }
     552    return NULL;
     553}
     554
     555#endif /*USE_THREADS*/
    489556
    490557static
     
    579646    fflush(g_fOut);
    580647
    581 #ifdef USE_NEW_EVENT_LOOP
     648#if defined(USE_NEW_EVENT_LOOP) || defined(USE_THREADS)
    582649    g_inBufPtr = new ReadBuffer(g_fdIn, 1<<12);
    583650#endif
     
    585652    Tcl_Interp *interp = Tcl_CreateInterp();
    586653    ClientData clientData = NULL;
    587 
     654#ifdef USE_THREADS
     655    g_queue = new ResponseQueue();
     656    clientData = (ClientData)g_queue;
    588657    initTcl(interp, clientData);
     658
     659    pthread_t writerThreadId;
     660    if (pthread_create(&writerThreadId, NULL, &writerThread, g_queue) < 0) {
     661        ERROR("Can't create writer thread: %s", strerror(errno));
     662    }
     663#else
     664    initTcl(interp, clientData);
     665#endif
    589666    NanoVis::interp = interp;
    590667
  • nanovis/branches/1.2/nanovisServer.h

    r4934 r4937  
    2626namespace nv {
    2727    class ReadBuffer;
     28    class ResponseQueue;
    2829
    2930    typedef struct {
     
    4647    extern FILE *g_fLog;           ///< Trace logging file handle
    4748    extern ReadBuffer *g_inBufPtr; ///< Socket read buffer
     49#ifdef USE_THREADS
     50    extern ResponseQueue *g_queue;
     51#endif
    4852
    4953#ifdef KEEPSTATS
     
    5155    extern int writeToStatsFile(int f, const char *s, size_t length);
    5256#endif
    53     extern void sendDataToClient(const char *command, const char *data,
     57    extern void sendDataToClient(const char *command, char *data,
    5458                                 size_t dlen);
    5559}
Note: See TracChangeset for help on using the changeset viewer.