////////////////////////////////////////////////////////////////////// // // Pixie // // Copyright © 1999 - 2003, Okan Arikan // // Contact: okan@cs.berkeley.edu // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // // File : rndr.cpp // Classes : - // Description : rib parser // //////////////////////////////////////////////////////////////////////// #include #include "common/global.h" #include "common/os.h" #include "common/containers.h" #include "ri/ri.h" #ifdef WIN32 #include #else #include #include #endif #define BUFFERSIZE 1024 #define DEFAULT_PORT 24666 // Prototype for main int main(int argc, char* argv[]); static int gargc; static char **gargv; static int deamon; static int silent; static int noRestart; static SOCKET listenSock; /////////////////////////////////////////////////////////////////////// // Function : exitFunction // Description : This function is called before exitting so that if // we're running a server, it can spawn another one // Return Value : - // Comments : // Date last edited : 12/01/2001 void exitFunction() { if (deamon == TRUE) { // Close socket before respawning int i = closesocket(listenSock); if (noRestart == FALSE) { char **argv = new char*[gargc+2]; int i; for (i=0;i: Render only a subsequence of frames\n"); fprintf(stdout," -f 43 = Render only 43'rd frame\n"); fprintf(stdout," -f 5:15 = Render frames 5 thru 15\n"); fprintf(stdout," -f 5:2:15 = Render frames 5 thru 15 skipping every other one\n"); fprintf(stdout," -q : Quiet mode (errors/warning ignored)\n"); fprintf(stdout," -d : Ignore the display drivers and use framebuffer\n"); fprintf(stdout," -t : Print renderer statistics after every frame\n"); fprintf(stdout," -p : Display the progress\n\n"); fprintf(stdout,"To render a RIB file:\n"); fprintf(stdout," rndr \n\n"); fprintf(stdout,"To start a net rendering deamon:\n"); fprintf(stdout," rndr -r \n"); fprintf(stdout," *** WARNING: The deamon will restart itself after each frame\n\n"); fprintf(stdout,"To kill a net rendering deamon:\n"); fprintf(stdout," rndr -k \n\n"); fprintf(stdout,"To render a RIB file on network:\n"); fprintf(stdout," rndr -s \n\n"); } /////////////////////////////////////////////////////////////////////// // Function : riThread // Description : The main rendering thread // Return Value : // Comments : // Date last edited : 11/28/2001 void riThread(void *w) { T32 *buffer = (T32 *) w; char managerString[1024]; T32 a; a.integer = 0; send((SOCKET) buffer[0].integer,(char *) &a,sizeof(T32),0); sprintf(managerString,"#rib:%s net:client=%d",(char *) &buffer[1].character,buffer[0].integer); // I may want to do this in a seperate process RiBegin(managerString); RiReadArchive((char *) &buffer[1].character,NULL,NULL); RiEnd(); } /////////////////////////////////////////////////////////////////////// // Function : rndrd // Description : Run the network deamon // Return Value : - // Comments : // Date last edited : 12/01/2001 void rndrd(int port) { SOCKET sock; struct sockaddr_in me; socklen_t myLength = sizeof(me); T32 buffer[BUFFERSIZE]; int running = TRUE; #ifdef WIN32 WSADATA wsaData; // Init the winsock if (WSAStartup(0x202,&wsaData) == SOCKET_ERROR) { WSACleanup(); if (silent == FALSE) fprintf(stderr,"Winsock init error\n"); } #else // For platforms where we can't disable sigpipe per socket, do it globally #ifndef SO_NOSIGPIPE signal(SIGPIPE,SIG_IGN); #endif #endif // Create the socket sock = socket(AF_INET, SOCK_STREAM, 0); if (sock == INVALID_SOCKET) { if (silent == FALSE) fprintf(stderr,"Socket error\n"); return; } int val = 1; setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(const char *) &val,sizeof(int)); val = 1; setsockopt(sock,IPPROTO_TCP,TCP_NODELAY,(const char *) &val,sizeof(int)); // Bind to the port me.sin_family = AF_INET; me.sin_addr.s_addr = htonl(INADDR_ANY); me.sin_port = htons(port); if (bind(sock, (struct sockaddr *) &me, sizeof(me)) < 0) { if (silent == FALSE) fprintf(stderr,"Bind error\n"); return; } // Display the information { char hostName[128]; hostent *hostinfo; if(gethostname(hostName,sizeof(hostName)) == 0) { if((hostinfo = gethostbyname(hostName)) != NULL) { if (silent == FALSE) fprintf(stdout,"Active at %s:%d\n",inet_ntoa (*(struct in_addr *)*hostinfo->h_addr_list),ntohs(me.sin_port)); } } } // We're running a deamon deamon = TRUE; // Save socket so we can close it on fatal errors listenSock = sock; // Listen to incoming connections listen(sock,SOMAXCONN); while(running == TRUE) { SOCKET peer; socklen_t servLen = sizeof(sockaddr_in); sockaddr_in serv; peer = accept(sock,(sockaddr *) &serv,&servLen); if (peer != INVALID_SOCKET) { // If supported / needed, disable sigpipe (needs to be an connected socket) #ifdef SO_NOSIGPIPE val = 1; setsockopt(peer,SOL_SOCKET,SO_NOSIGPIPE,(const char *) &val,sizeof(int)); #endif // Handle the message recv(peer,(char *) &buffer[1].character,(BUFFERSIZE-1)*sizeof(T32),0); if (strncmp((char *) &buffer[1].character," quit",5) == 0) { noRestart = TRUE; running = FALSE; } else { buffer[0].integer = peer; riThread((void *) buffer); running = TRUE; } // Close peer socket int i = closesocket(peer); } } // Close socket before exiting int i = closesocket(sock); } /////////////////////////////////////////////////////////////////////// // Function : main // Description : The god // Return Value : - // Comments : // Date last edited : 12/01/2001 int main(int argc, char* argv[]) { int i; char managerString[1024]; char managerString2[1024]; int server = FALSE; int client = FALSE; int killservers = FALSE; char *source = NULL; int port = 0; const char *frameRange = NULL; int frameBufferOnly = FALSE; int displayStats = FALSE; int displayProgress = FALSE; #ifndef USE_MEMORY_MANAGER // Enable memory leak detection _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); #endif // Init the memory manager memoryManagerInit(); // Register the exit stuff sprintf(managerString,""); gargc = argc; gargv = argv; deamon = FALSE; silent = FALSE; atexit(exitFunction); for (i=1;i= argc) { if (silent == FALSE) fprintf(stderr,"Was expecting client name\n"); exit(0); } sprintf(managerString,"client=%s",argv[i]); } else if (strcmp(argv[i],"-s") == 0) { server = TRUE; i++; if (i >= argc) { if (silent == FALSE) fprintf(stderr,"Was expecting list of servers\n"); exit(0); } sprintf(managerString,"servers=%s",argv[i]); } else if (strcmp(argv[i],"-k") == 0) { server = TRUE; killservers = TRUE; i++; if (i >= argc) { if (silent == FALSE) fprintf(stderr,"Was expecting list of servers\n"); exit(0); } sprintf(managerString,"killservers=%s",argv[i]); } else if (strcmp(argv[i],"-f") == 0) { i++; if (i >= argc) { if (silent == FALSE) fprintf(stderr,"Was expecting the frame range\n"); exit(0); } frameRange = argv[i]; } else if (strcmp(argv[i],"-d") == 0) { frameBufferOnly = TRUE; } else if (strcmp(argv[i],"-t") == 0) { displayStats = TRUE; } else if (strcmp(argv[i],"-p") == 0) { displayProgress = TRUE; } else { source = argv[i]; } } if (port != 0) { noRestart = FALSE; rndrd(port); exit(0); } // If no source, get the input from stdin if (source == NULL) source = "-"; // Deal with stdin renders if (strcmp(source,"-") == 0) { if ((client | server) && (silent == FALSE) && (killservers != TRUE)) { fprintf(stderr,"You cannot use stdin for network renders\n"); exit(0); } } // Create the command line for the ri if (client | server) { sprintf(managerString2,"#rib:%s net:%s",source,managerString); } else { sprintf(managerString2,"#"); } if (frameRange != NULL) { strcat(managerString2," frames:"); strcat(managerString2,frameRange); } if (frameBufferOnly) { strcat(managerString2," fbonly:"); } RiBegin(managerString2); if (silent == TRUE) RiErrorHandler(RiErrorIgnore); if (displayStats == TRUE) { RtInt level = 3; RiOption(RI_STATISTICS,RI_ENDOFFRAME,&level,RI_NULL); } if (displayProgress == TRUE) { RtInt progress = 1; RiOption(RI_STATISTICS,RI_PROGRESS,&progress,RI_NULL); } if (!killservers) RiReadArchive(source,NULL,NULL); RiEnd(); memoryManagerTini(); return (RiLastError != RIE_NOERROR) ? -1 : 0; }