Changeset 4937
- Timestamp:
- Jan 18, 2015, 2:28:38 AM (10 years ago)
- Location:
- nanovis/branches/1.2
- Files:
-
- 6 added
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
nanovis/branches/1.2/Command.cpp
r4904 r4937 50 50 #include "nanovis.h" 51 51 #include "ReadBuffer.h" 52 #ifdef USE_THREADS 53 #include "ResponseQueue.h" 54 #endif 52 55 #include "Command.h" 53 56 #include "CmdProc.h" … … 55 58 #include "dxReader.h" 56 59 #include "VtkReader.h" 60 #include "BMPWriter.h" 61 #include "PPMWriter.h" 57 62 #include "Grid.h" 58 63 #include "HeightMap.h" … … 108 113 static int lastCmdStatus; 109 114 115 #ifdef USE_THREADS 116 void 117 nv::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 110 127 ssize_t 111 128 nv::SocketWrite(const void *bytes, size_t len) … … 123 140 return bytesWritten; 124 141 } 142 143 #endif /*USE_THREADS*/ 125 144 126 145 bool … … 143 162 TRACE("command %lu: '%s'", g_stats.nCommands+1, cmd.c_str()); 144 163 #endif 145 146 164 lastCmdStatus = TCL_OK; 147 165 result = Tcl_EvalEx(interp, Tcl_DStringValue(dsPtr), … … 149 167 TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL); 150 168 Tcl_DStringSetLength(dsPtr, 0); 151 152 169 if (lastCmdStatus == TCL_BREAK) { 153 170 return TCL_BREAK; … … 512 529 nv::GetDataStream(Tcl_Interp *interp, Rappture::Buffer &buf, int nBytes) 513 530 { 514 #if def USE_NEW_EVENT_LOOP531 #if defined(USE_NEW_EVENT_LOOP) || defined(USE_THREADS) 515 532 if (!SocketRead((char *)buf.bytes(), nBytes)) { 516 533 return TCL_ERROR; … … 687 704 NanoVis::render(); 688 705 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 691 713 NanoVis::resizeOffscreenBuffer(origWidth, origHeight); 692 714 … … 1188 1210 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboOrig); 1189 1211 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); 1191 1218 } 1192 1219 } … … 1356 1383 volume->wAxis.min(), volume->wAxis.max(), 1357 1384 Volume::valueMin, Volume::valueMax); 1385 #ifdef USE_THREADS 1386 queueResponse(info, cmdLength, Response::VOLATILE); 1387 #else 1358 1388 if (SocketWrite(info, (size_t)cmdLength) != (ssize_t)cmdLength) { 1359 1389 ERROR("Short write"); 1360 1390 return TCL_ERROR; 1361 1391 } 1392 #endif 1362 1393 } 1363 1394 … … 2290 2321 nBytes = ostr.length(); 2291 2322 2323 #ifdef USE_THREADS 2324 queueResponse(ostr.c_str(), nBytes, Response::VOLATILE, Response::ERROR); 2325 #else 2292 2326 if (write(fdOut, oss.str().c_str(), nBytes) < 0) { 2293 2327 ERROR("write failed: %s", strerror(errno)); 2294 2328 return -1; 2295 2329 } 2330 #endif 2296 2331 } 2297 2332 } … … 2308 2343 nBytes = ostr.length(); 2309 2344 2345 #ifdef USE_THREADS 2346 queueResponse(ostr.c_str(), nBytes, Response::VOLATILE, Response::ERROR); 2347 #else 2310 2348 if (write(fdOut, ostr.c_str(), nBytes) < 0) { 2311 2349 ERROR("write failed: %s", strerror(errno)); 2312 2350 return -1; 2313 2351 } 2352 #endif 2314 2353 clearUserMessages(); 2315 2354 } -
nanovis/branches/1.2/Command.h
r4889 r4937 16 16 #include <tcl.h> 17 17 18 #include "ResponseQueue.h" 19 18 20 namespace Rappture { 19 21 class Buffer; … … 25 27 class Volume; 26 28 29 #ifdef USE_THREADS 30 extern void queueResponse(const void *bytes, size_t len, 31 Response::AllocationType allocType, 32 Response::ResponseType type = Response::DATA); 33 #else 27 34 extern ssize_t SocketWrite(const void *bytes, size_t len); 35 #endif 28 36 29 37 extern bool SocketRead(char *bytes, size_t len); -
nanovis/branches/1.2/FlowCmd.cpp
r4904 r4937 5 5 */ 6 6 #include <assert.h> 7 #include <errno.h>8 7 #define _OPEN_SYS 9 8 #include <fcntl.h> … … 32 31 #include "CmdProc.h" 33 32 #include "Command.h" 33 #include "PPMWriter.h" 34 34 #include "FlowCmd.h" 35 35 #include "FlowTypes.h" … … 232 232 sprintf(info, "nv>data tag %s min %g max %g\n", 233 233 flow->name(), unirect->magMin(), unirect->magMax()); 234 #ifdef USE_THREADS 235 queueResponse(info, (size_t)length, Response::VOLATILE); 236 #else 234 237 if (SocketWrite(info, (size_t)length) < 0) { 235 238 return TCL_ERROR; 236 239 } 240 #endif 237 241 } 238 242 Flow::updatePending = true; … … 1002 1006 1003 1007 static 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 header1014 char header[200];1015 #define PPM_MAXVAL 2551016 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 bool1053 1008 MakeImageFiles(char *tmpFileName, 1054 1009 int width, int height, int numFrames, … … 1081 1036 break; 1082 1037 } 1038 1083 1039 NanoVis::licRenderer->convolve(); 1084 1040 NanoVis::advectFlows(); … … 1094 1050 1095 1051 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); 1098 1054 if (!result) { 1099 1055 break; … … 1130 1086 /* The ffmpeg command is 1131 1087 * ffmpeg -f image2 -i /var/tmp/xxxxx/image%d.ppm \ 1132 * - b bitrate -fframerate /var/tmp/xxxxx/movie.mpeg1088 * -f outformat -b bitrate -r framerate /var/tmp/xxxxx/movie.mpeg 1133 1089 */ 1134 1090 #ifndef FFMPEG … … 1146 1102 return TCL_ERROR; 1147 1103 } 1148 Rappture::Buffer data;1104 char *data = NULL; 1149 1105 size_t total = 0; 1150 1106 for (;;) { 1151 1107 char buffer[BUFSIZ]; 1152 1108 1153 ssize_t numRead = fread(buffer, sizeof( unsignedchar), BUFSIZ, f);1109 ssize_t numRead = fread(buffer, sizeof(char), BUFSIZ, f); 1154 1110 total += numRead; 1155 1111 if (numRead == 0) { // EOF … … 1163 1119 return TCL_ERROR; 1164 1120 } 1165 if (!data.append(buffer, numRead)) { 1121 data = (char *)realloc(data, total); 1122 if (data == NULL) { 1166 1123 ERROR("Can't append movie data to buffer %d bytes", 1167 1124 numRead); … … 1170 1127 return TCL_ERROR; 1171 1128 } 1172 } 1173 if (data.size() == 0) { 1129 memcpy(data + (total - numRead), buffer, numRead); 1130 } 1131 if (total == 0) { 1174 1132 ERROR("ffmpeg returned 0 bytes"); 1175 1133 } 1176 1134 // Send zero length to client so it can deal with error 1177 1135 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); 1180 1139 return TCL_OK; 1181 1140 } -
nanovis/branches/1.2/Makefile.in
r4920 r4937 1 1 TRACE = #yes 2 USE_THREADS = yes 2 3 USE_POINTSET_RENDERER = #yes 3 4 USE_PARTICLE_SYSTEM = #yes … … 62 63 LD_RUN_PATH = $(libdir):@LD_RPATH@ 63 64 64 SVN_VERSION = $(shell svnversion $(srcdir) )65 SVN_VERSION = $(shell svnversion $(srcdir) | sed 's/Unversioned directory/unknown/') 65 66 STATSDIR = @STATSDIR@ 66 67 … … 97 98 DEFINES += -DWANT_TRACE 98 99 endif 100 ifdef USE_THREADS 101 DEFINES += -DUSE_THREADS 102 endif 99 103 ifdef USE_POINTSET_RENDERER 100 104 DEFINES += -DUSE_POINTSET_RENDERER … … 104 108 OBJS = \ 105 109 Axis.o \ 110 BMPWriter.o \ 106 111 Camera.o \ 107 112 Chain.o \ … … 124 129 Plane.o \ 125 130 PlaneRenderer.o \ 131 PPMWriter.o \ 126 132 ReadBuffer.o \ 127 133 ReaderCommon.o \ 128 134 RegularVolumeShader.o \ 129 135 RenderVertexArray.o \ 136 ResponseQueue.o \ 130 137 Shader.o \ 131 138 StdVertexShader.o \ … … 271 278 272 279 Axis.o: Axis.cpp Axis.h Chain.h 280 BMPWriter.o: BMPWriter.cpp BMPWriter.h nanovis.h 273 281 BucketSort.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 274 282 Camera.o: Camera.cpp Camera.h config.h $(VRMATH_DIR)/include/vrmath/Matrix4x4d.h … … 276 284 CmdProc.o: CmdProc.cpp CmdProc.h 277 285 ColorTableShader.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.h286 Command.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 279 287 ContourLineFilter.o: ContourLineFilter.cpp ContourLineFilter.h 280 288 ConvexPolygon.o: ConvexPolygon.cpp ConvexPolygon.h $(VRMATH_DIR)/include/vrmath/Vector4f.h $(VRMATH_DIR)/include/vrmath/Matrix4x4d.h Plane.h 281 289 Flow.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 282 290 FlowBox.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.h291 FlowCmd.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 284 292 FlowParticles.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 285 293 GradientFilter.o: GradientFilter.cpp GradientFilter.h … … 299 307 PointSetRenderer.o: PointSetRenderer.cpp PointSetRenderer.h 300 308 PointShader.o: PointShader.cpp PointShader.h 309 PPMWriter.o: PPMWriter.cpp PPMWriter.h 301 310 ReadBuffer.o: ReadBuffer.cpp ReadBuffer.h Trace.h 302 311 ReaderCommon.o: ReaderCommon.cpp ReaderCommon.h GradientFilter.h $(VRMATH_DIR)/include/vrmath/Vector3f.h … … 324 333 md5.o: md5.h 325 334 nanovis.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.h335 nanovisServer.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 1 1 #! /bin/sh 2 2 # 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. 4 4 # 5 5 # Report bugs to <rappture@nanohub.org>. … … 581 581 PACKAGE_NAME='nanovis' 582 582 PACKAGE_TARNAME='nanovis' 583 PACKAGE_VERSION='1. 1'584 PACKAGE_STRING='nanovis 1. 1'583 PACKAGE_VERSION='1.2' 584 PACKAGE_STRING='nanovis 1.2' 585 585 PACKAGE_BUGREPORT='rappture@nanohub.org' 586 586 PACKAGE_URL='' … … 1256 1256 # This message is too long to be a string in the A/UX 3.1 sh. 1257 1257 cat <<_ACEOF 1258 \`configure' configures nanovis 1. 1to adapt to many kinds of systems.1258 \`configure' configures nanovis 1.2 to adapt to many kinds of systems. 1259 1259 1260 1260 Usage: $0 [OPTION]... [VAR=VALUE]... … … 1317 1317 if test -n "$ac_init_help"; then 1318 1318 case $ac_init_help in 1319 short | recursive ) echo "Configuration of nanovis 1. 1:";;1319 short | recursive ) echo "Configuration of nanovis 1.2:";; 1320 1320 esac 1321 1321 cat <<\_ACEOF … … 1411 1411 if $ac_init_version; then 1412 1412 cat <<\_ACEOF 1413 nanovis configure 1. 11413 nanovis configure 1.2 1414 1414 generated by GNU Autoconf 2.69 1415 1415 … … 1855 1855 running configure, to aid debugging if configure makes a mistake. 1856 1856 1857 It was created by nanovis $as_me 1. 1, which was1857 It was created by nanovis $as_me 1.2, which was 1858 1858 generated by GNU Autoconf 2.69. Invocation command line was 1859 1859 … … 5506 5506 # values after options handling. 5507 5507 ac_log=" 5508 This file was extended by nanovis $as_me 1. 1, which was5508 This file was extended by nanovis $as_me 1.2, which was 5509 5509 generated by GNU Autoconf 2.69. Invocation command line was 5510 5510 … … 5568 5568 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" 5569 5569 ac_cs_version="\\ 5570 nanovis config.status 1. 15570 nanovis config.status 1.2 5571 5571 configured by $0, generated by GNU Autoconf 2.69, 5572 5572 with options \\"\$ac_cs_config\\" -
nanovis/branches/1.2/configure.in
r4904 r4937 1 1 AC_PREREQ([2.60]) 2 AC_INIT([nanovis], [1. 1], [rappture@nanohub.org])2 AC_INIT([nanovis], [1.2], [rappture@nanohub.org]) 3 3 AC_CONFIG_AUX_DIR(cf) 4 4 AC_CONFIG_HEADERS([nvconf.h]) -
nanovis/branches/1.2/nanovis.cpp
r4904 r4937 17 17 18 18 #include <sys/time.h> 19 #include <sys/types.h>20 #include <sys/uio.h> // for writev in ppmWrite21 #include <unistd.h>22 23 19 #include <cassert> 24 #include <cerrno>25 #include <cstdlib>26 20 #include <cstdio> 27 #include <cstring>28 #include <cmath>29 30 #include <string>31 21 32 22 #include <GL/glew.h> … … 54 44 #include "Shader.h" 55 45 #include "PlaneRenderer.h" 46 #include "PPMWriter.h" 56 47 #include "Texture2D.h" 57 48 #include "Trace.h" … … 67 58 using namespace nv::util; 68 59 using namespace vrmath; 69 70 #define SIZEOF_BMP_HEADER 5471 60 72 61 // STATIC MEMBER DATA … … 332 321 planeRenderer->render(); 333 322 334 //glPixelStorei(GL_PACK_ALIGNMENT, 1);323 glPixelStorei(GL_PACK_ALIGNMENT, 1); 335 324 glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, screenBuffer); 336 325 { … … 339 328 TRACE("Sending ppm legend image %s min:%g max:%g", volArg, min, max); 340 329 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 342 335 } 343 336 planeRenderer->removePlane(index); … … 361 354 glGenTextures(1, &_finalColorTex); 362 355 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); 368 358 #if defined(HAVE_FLOAT_TEXTURES) && defined(USE_HALF_FLOAT) 369 359 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, winWidth, winHeight, 0, … … 418 408 } 419 409 420 screenBuffer = new unsigned char[ 4*winWidth*winHeight];410 screenBuffer = new unsigned char[3*winWidth*winHeight]; 421 411 assert(screenBuffer != NULL); 422 412 … … 435 425 glGenTextures(1, &_finalColorTex); 436 426 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); 442 429 #if defined(HAVE_FLOAT_TEXTURES) && defined(USE_HALF_FLOAT) 443 430 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, winWidth, winHeight, 0, … … 557 544 screenBuffer = NULL; 558 545 } 559 screenBuffer = new unsigned char[ 4*winWidth*winHeight];546 screenBuffer = new unsigned char[3*winWidth*winHeight]; 560 547 assert(screenBuffer != NULL); 561 548 … … 609 596 610 597 return true; 611 }612 613 // used internally to build up the BMP file header614 // Writes an integer value into the header data structure at pos615 static inline void616 bmpHeaderAddInt(unsigned char* header, int& pos, int data)617 {618 #ifdef WORDS_BIGENDIAN619 header[pos++] = (data >> 24) & 0xFF;620 header[pos++] = (data >> 16) & 0xFF;621 header[pos++] = (data >> 8) & 0xFF;622 header[pos++] = (data) & 0xFF;623 #else624 header[pos++] = data & 0xff;625 header[pos++] = (data >> 8) & 0xff;626 header[pos++] = (data >> 16) & 0xff;627 header[pos++] = (data >> 24) & 0xff;628 #endif629 }630 631 void632 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 bytes640 // 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 bytes647 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 data654 bmpHeaderAddInt(header, pos, SIZEOF_BMP_HEADER);655 656 // size of the BITMAPINFOHEADER657 bmpHeaderAddInt(header, pos, 40);658 659 // width of the image in pixels660 bmpHeaderAddInt(header, pos, winWidth);661 662 // height of the image in pixels663 bmpHeaderAddInt(header, pos, winHeight);664 665 // 1 plane + (24 bits/pixel << 16)666 bmpHeaderAddInt(header, pos, 1572865);667 668 // no compression669 // size of image for compression670 bmpHeaderAddInt(header, pos, 0);671 bmpHeaderAddInt(header, pos, 0);672 673 // x pixels per meter674 // y pixels per meter675 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 data684 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]; // B689 scr[0] = tmp; // R690 scr += 3;691 }692 scr += pad; // skip over padding already in screen data693 }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 else701 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 void724 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 bytes731 // 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 bytes747 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 data753 bmpHeaderAddInt(header, pos, SIZEOF_BMP_HEADER);754 755 // size of the BITMAPINFOHEADER756 bmpHeaderAddInt(header, pos, 40);757 758 // width of the image in pixels759 bmpHeaderAddInt(header, pos, winWidth);760 761 // height of the image in pixels762 bmpHeaderAddInt(header, pos, winHeight);763 764 // 1 plane + (24 bits/pixel << 16)765 bmpHeaderAddInt(header, pos, 1572865);766 767 // no compression768 // size of image for compression769 bmpHeaderAddInt(header, pos, 0);770 bmpHeaderAddInt(header, pos, 0);771 772 // x pixels per meter773 // y pixels per meter774 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 data783 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]; // B788 scr[0] = tmp; // R789 scr += 3;790 }791 scr += pad; // skip over padding already in screen data792 }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 nanovisviewer806 * client. The PPM binary format is very simple.807 *808 * P6 w h 255\n809 * 3-byte RGB pixel data.810 *811 * The nanovisviewer client (using the TkImg library) will do less work812 * to unpack this format, as opposed to BMP or PNG. (This doesn't813 * 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-padded816 * and the scan lines are reversed. This routine could be made even817 * simpler (faster) if the screen buffer is an array of packed 3-bytes818 * per pixels (no padding) and where the origin is the top-left corner.819 */820 void821 NanoVis::ppmWrite(const char *prefix)822 {823 #define PPM_MAXVAL 255824 char header[200];825 826 TRACE("Enter (%dx%d)", winWidth, winHeight);827 // Generate the PPM binary file header828 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 // Command847 iov[0].iov_base = command;848 iov[0].iov_len = strlen(command);849 // Header of image data850 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);867 598 } 868 599 -
nanovis/branches/1.2/nanovis.h
r4904 r4937 89 89 static void eventuallyRedraw(); 90 90 91 static void ppmWrite(const char *prefix);92 static void bmpWrite(const char *prefix);93 static void bmpWriteToFile(int frameNum, const char* dirName);94 95 91 static TransferFunction *getTransferFunction(const TransferFunctionId& id); 96 92 static TransferFunction *defineTransferFunction(const TransferFunctionId& id, … … 108 104 static void readScreen() 109 105 { 110 //glPixelStorei(GL_PACK_ALIGNMENT, 1);106 glPixelStorei(GL_PACK_ALIGNMENT, 1); 111 107 glReadPixels(0, 0, winWidth, winHeight, GL_RGB, GL_UNSIGNED_BYTE, 112 108 screenBuffer); -
nanovis/branches/1.2/nanovisServer.cpp
r4904 r4937 10 10 #include <cstring> 11 11 #include <csignal> 12 #include <ctime>13 12 14 13 #include <fcntl.h> … … 34 33 #include "define.h" 35 34 #include "Command.h" 35 #include "PPMWriter.h" 36 36 #include "ReadBuffer.h" 37 37 #include "Shader.h" 38 #ifdef USE_THREADS 39 #include <pthread.h> 40 #include "ResponseQueue.h" 41 #endif 38 42 #include "Trace.h" 39 43 … … 43 47 Stats nv::g_stats; 44 48 int nv::g_statsFile = -1; ///< Stats output file descriptor. 49 45 50 int nv::g_fdIn = STDIN_FILENO; ///< Input file descriptor 46 51 int nv::g_fdOut = STDOUT_FILENO; ///< Output file descriptor … … 49 54 FILE *nv::g_fLog = NULL; ///< Trace logging file handle 50 55 ReadBuffer *nv::g_inBufPtr = NULL; ///< Socket read buffer 56 #ifdef USE_THREADS 57 ResponseQueue *nv::g_queue = NULL; 58 #endif 59 60 #ifdef USE_THREADS 61 62 static void 63 queueFrame(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 51 72 52 73 static void 53 74 writeFrame(int fd, unsigned char *imgData) 54 75 { 55 #if 056 76 writePPM(fd, "nv>image -type image -bytes", 57 77 imgData, 58 78 NanoVis::winWidth, 59 79 NanoVis::winHeight); 60 #else 61 NanoVis::ppmWrite("nv>image -type image -bytes"); 62 #endif 63 } 80 } 81 82 #endif /*USE_THREADS*/ 64 83 65 84 static int … … 72 91 73 92 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 74 96 if (write(g_fdOut, str.c_str(), numBytes) < 0) { 75 97 ERROR("write failed: %s", strerror(errno)); 76 98 return -1; 77 99 } 100 #endif 78 101 return 0; 79 102 } … … 263 286 /** 264 287 * \brief Send a command with data payload 288 * 289 * data pointer is freed on completion of the response 265 290 */ 266 291 void 267 nv::sendDataToClient(const char *command, const char *data, size_t dlen) 268 { 292 nv::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 269 300 size_t numRecords = 2; 270 301 struct iovec *iov = new iovec[numRecords]; … … 275 306 iov[0].iov_len = strlen(command); 276 307 // Data 277 iov[1].iov_base = const_cast<char *>(data);308 iov[1].iov_base = data; 278 309 iov[1].iov_len = dlen; 279 310 if (writev(g_fdOut, iov, numRecords) < 0) { … … 281 312 } 282 313 delete [] iov; 314 #endif 315 free(data); 283 316 } 284 317 … … 349 382 } 350 383 351 #if ndef USE_NEW_EVENT_LOOP384 #if !defined(USE_NEW_EVENT_LOOP) && !defined(USE_THREADS) 352 385 353 386 static int … … 452 485 glutSetWindow(NanoVis::renderWindow); 453 486 454 #if def USE_NEW_EVENT_LOOP487 #if defined(USE_NEW_EVENT_LOOP) || defined(USE_THREADS) 455 488 if (nv::processCommands(NanoVis::interp, g_inBufPtr, g_fdOut) < 0) { 456 489 exitService(1); … … 469 502 TRACE("Rendering new frame"); 470 503 NanoVis::readScreen(); 504 #ifdef USE_THREADS 505 queueFrame(g_queue, NanoVis::screenBuffer); 506 #else 471 507 writeFrame(g_fdOut, NanoVis::screenBuffer); 508 #endif 509 g_stats.nFrames++; 510 g_stats.nFrameBytes += NanoVis::winWidth * NanoVis::winHeight * 3; 472 511 } else { 473 512 TRACE("No render required"); … … 475 514 } 476 515 477 #if def USE_NEW_EVENT_LOOP516 #if defined(USE_NEW_EVENT_LOOP) || defined(USE_THREADS) 478 517 if (g_inBufPtr->status() == ReadBuffer::ENDFILE) { 479 518 exitService(0); … … 487 526 TRACE("Leave"); 488 527 } 528 529 #ifdef USE_THREADS 530 531 static void * 532 writerThread(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*/ 489 556 490 557 static … … 579 646 fflush(g_fOut); 580 647 581 #if def USE_NEW_EVENT_LOOP648 #if defined(USE_NEW_EVENT_LOOP) || defined(USE_THREADS) 582 649 g_inBufPtr = new ReadBuffer(g_fdIn, 1<<12); 583 650 #endif … … 585 652 Tcl_Interp *interp = Tcl_CreateInterp(); 586 653 ClientData clientData = NULL; 587 654 #ifdef USE_THREADS 655 g_queue = new ResponseQueue(); 656 clientData = (ClientData)g_queue; 588 657 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 589 666 NanoVis::interp = interp; 590 667 -
nanovis/branches/1.2/nanovisServer.h
r4934 r4937 26 26 namespace nv { 27 27 class ReadBuffer; 28 class ResponseQueue; 28 29 29 30 typedef struct { … … 46 47 extern FILE *g_fLog; ///< Trace logging file handle 47 48 extern ReadBuffer *g_inBufPtr; ///< Socket read buffer 49 #ifdef USE_THREADS 50 extern ResponseQueue *g_queue; 51 #endif 48 52 49 53 #ifdef KEEPSTATS … … 51 55 extern int writeToStatsFile(int f, const char *s, size_t length); 52 56 #endif 53 extern void sendDataToClient(const char *command, c onst char *data,57 extern void sendDataToClient(const char *command, char *data, 54 58 size_t dlen); 55 59 }
Note: See TracChangeset
for help on using the changeset viewer.