├── webcontrol ├── server │ ├── apps │ │ ├── __init__.py │ │ └── lesson05.py │ ├── util │ │ ├── __init__.py │ │ ├── webserver.py │ │ └── cglrunner.py │ ├── config.py │ └── server.py ├── invoke.php ├── css │ └── main.css ├── index.php ├── configure.php └── utils.php ├── runtime ├── tests │ ├── row │ │ ├── data │ │ │ └── texture.bmp │ │ └── Makefile │ ├── texture │ │ ├── data │ │ │ └── texture.bmp │ │ ├── Makefile │ │ └── README │ ├── Makefile │ ├── lesson05 │ │ ├── Makefile │ │ └── README │ └── drawelements │ │ └── Makefile ├── symphonycgl ├── single.conf ├── cgl-capture ├── test.conf ├── lg.conf ├── symphony.conf └── cgl.conf ├── README.md ├── description-pak ├── .gitignore ├── src ├── mod_multicastclient.cpp ├── mod_app_dummy.cpp ├── include │ ├── instruction.h │ ├── libs.h │ ├── main.h │ ├── utils.h │ ├── config.h │ ├── module.h │ └── lru_cache.h ├── stats.cpp ├── mod_insert.cpp ├── Makefile ├── instruction.cpp ├── dlintercept.cpp ├── mod_compress.cpp ├── mod_duplicatebuffer.cpp ├── mod_netsrv.cpp ├── mod_netclient.cpp ├── main.cpp ├── lru_cache.cpp ├── mod_delta.cpp ├── config.cpp └── viewmode.cpp ├── util ├── presentation │ ├── Makefile │ └── src │ │ ├── include │ │ ├── glutil.h │ │ ├── surface.h │ │ ├── texture.h │ │ ├── main.h │ │ ├── libs.h │ │ ├── misc.h │ │ ├── presentation.h │ │ └── vector.h │ │ ├── render.cpp │ │ ├── init.cpp │ │ ├── update.cpp │ │ ├── main.cpp │ │ ├── Makefile │ │ ├── texture.cpp │ │ ├── events.cpp │ │ ├── surface.cpp │ │ ├── glutil.cpp │ │ └── presentation.cpp ├── dist │ ├── make_deb.sh │ └── make_deb_i386.sh ├── getconsts.py ├── getsize │ └── parse.py └── codegen │ └── parse.py ├── libcglinput ├── libcglinput.cfg ├── web │ ├── js │ │ └── libcglinput.js │ ├── test.html │ └── css │ │ └── bootstrap-responsive.min.css ├── src │ ├── main.cpp │ ├── include │ │ └── main.h │ ├── sdl.cpp │ ├── config.cpp │ ├── xorg.cpp │ ├── spacenav.cpp │ └── web.cpp └── Makefile └── Makefile /webcontrol/server/apps/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /webcontrol/server/util/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /runtime/tests/row/data/texture.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bieh/clustergl/HEAD/runtime/tests/row/data/texture.bmp -------------------------------------------------------------------------------- /runtime/tests/texture/data/texture.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bieh/clustergl/HEAD/runtime/tests/texture/data/texture.bmp -------------------------------------------------------------------------------- /runtime/tests/row/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc -Wall -ansi 2 | 3 | all: 4 | $(CC) row.c -o row -lGL -lGLU `sdl-config --cflags --libs` --std=c99 5 | 6 | clean: 7 | @rm row -f 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ClusterGL 2 | ========= 3 | 4 | Transparent parallel 3D rendering for display walls and Google Liquid Galaxy 5 | 6 | See http://clustergl.org for more information 7 | -------------------------------------------------------------------------------- /description-pak: -------------------------------------------------------------------------------- 1 | ClusterGL 2 | ========= 3 | 4 | Transparent parallel 3D rendering for display walls and Google Liquid Galaxy 5 | 6 | See http://clustergl.org for more information 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | 6 | # Compiled Dynamic libraries 7 | *.so 8 | 9 | # Compiled Static libraries 10 | *.lai 11 | *.la 12 | *.a 13 | -------------------------------------------------------------------------------- /src/mod_multicastclient.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************** 2 | TODO: Multicast that doesn't suck 3 | ********************************************************/ 4 | 5 | -------------------------------------------------------------------------------- /util/presentation/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | $(MAKE) -C src 3 | 4 | clean: 5 | $(MAKE) clean -C src 6 | 7 | 8 | run-app: 9 | cd runtime && ./presentation /home/paul/Desktop/presentation/*.png 10 | -------------------------------------------------------------------------------- /runtime/tests/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | make -C lesson05 3 | make -C texture 4 | make -C drawelements 5 | 6 | clean: 7 | make clean -C lesson05 8 | make clean -C texture 9 | make clean -C drawelements 10 | -------------------------------------------------------------------------------- /util/presentation/src/include/glutil.h: -------------------------------------------------------------------------------- 1 | class GLUtil{ 2 | public: 3 | void cube(float x, float y, float z); 4 | void plane(float x, float y, float z); 5 | 6 | Vector3 calculateMousePoint(); 7 | Vector2 utilProject(float x, float y, float z); 8 | }; 9 | -------------------------------------------------------------------------------- /util/presentation/src/render.cpp: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | 3 | void Application::render(){ 4 | 5 | //LOG("2\n"); 6 | 7 | mSurface.beginRender(); 8 | 9 | mPresentation.render(); 10 | 11 | mSurface.begin2D(); 12 | 13 | mPresentation.render2D(); 14 | 15 | mSurface.endRender(); 16 | } 17 | -------------------------------------------------------------------------------- /webcontrol/invoke.php: -------------------------------------------------------------------------------- 1 | 16 | -------------------------------------------------------------------------------- /util/presentation/src/include/surface.h: -------------------------------------------------------------------------------- 1 | class Surface{ 2 | 3 | int videoFlags; 4 | SDL_Surface *surface; 5 | 6 | void resizeWindow( int width, int height ); 7 | 8 | public: 9 | 10 | bool init(int w, int h, bool f); 11 | void beginRender(); 12 | void begin2D(); 13 | void endRender(); 14 | bool shutdown(); 15 | 16 | void onResize(int x, int y); 17 | }; 18 | -------------------------------------------------------------------------------- /util/presentation/src/include/texture.h: -------------------------------------------------------------------------------- 1 | //loading flags 2 | #define TEXTURE_NO_GL 1 3 | 4 | class Texture{ 5 | GLuint mHandle; 6 | ILuint iDevilID; 7 | int iSizeX, iSizeY; 8 | bool bIsLoaded; 9 | public: 10 | Texture(string filename); 11 | ~Texture(){destroy();} 12 | 13 | bool load(string filename, int flags); 14 | void bind(); 15 | void destroy(); 16 | 17 | bool isLoaded(){ return bIsLoaded; } 18 | }; 19 | -------------------------------------------------------------------------------- /runtime/tests/lesson05/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc -Wall -ansi 2 | UNAME := $(shell uname -s) 3 | FILE=lesson05 4 | 5 | all: 6 | ifeq ($(UNAME),Darwin) 7 | gcc -g -I/opt/local/include -I/usr/X11R6/include -L/opt/local/lib -lSDLmain -lSDL -Wl,-framework,Cocoa -framework OpenGL $(FILE).c -o $(FILE) 8 | endif 9 | ifeq ($(UNAME),Linux) 10 | $(CC) $(FILE).c -o $(FILE) -lGL -lGLU `sdl-config --cflags --libs` -L/usr/X11/lib/ -lSDLmain 11 | endif 12 | clean: 13 | @rm $(FILE) -f 14 | 15 | 16 | -------------------------------------------------------------------------------- /runtime/tests/texture/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc -Wall -ansi 2 | UNAME := $(shell uname -s) 3 | FILE=texture 4 | 5 | all: 6 | ifeq ($(UNAME),Darwin) 7 | gcc -g -I/opt/local/include -I/usr/X11R6/include -L/opt/local/lib -lSDLmain -lSDL -Wl,-framework,Cocoa -framework OpenGL $(FILE).c -o $(FILE) 8 | endif 9 | ifeq ($(UNAME),Linux) 10 | $(CC) $(FILE).c -o $(FILE) -lGL -lGLU `sdl-config --cflags --libs` -L/usr/X11/lib/ -lSDLmain 11 | endif 12 | clean: 13 | @rm $(FILE) -f 14 | 15 | 16 | -------------------------------------------------------------------------------- /runtime/tests/drawelements/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc -Wall -ansi 2 | UNAME := $(shell uname -s) 3 | FILE=drawelements 4 | 5 | all: 6 | ifeq ($(UNAME),Darwin) 7 | gcc -g -I/opt/local/include -I/usr/X11R6/include -L/opt/local/lib -lSDLmain -lSDL -Wl,-framework,Cocoa -framework OpenGL $(FILE).c -o $(FILE) 8 | endif 9 | ifeq ($(UNAME),Linux) 10 | $(CC) $(FILE).c -o $(FILE) -lGL -lGLU `sdl-config --cflags --libs` -L/usr/X11/lib/ -lSDLmain --std=c99 11 | endif 12 | clean: 13 | @rm $(FILE) -f 14 | 15 | 16 | -------------------------------------------------------------------------------- /runtime/symphonycgl: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SCRIPTNAME=runcgl 4 | 5 | LOCATION=$(cd ${0%/*} && echo $PWD/${0##*/}) 6 | DIR=`dirname "$LOCATION"` 7 | 8 | echo Using clusterGL from ${DIR}... 9 | for i in `seq 1 5`; do 10 | ssh dn$i "cd ${DIR} && DISPLAY=:0 ./cgl-render dn$i > dn$i.log" & 11 | echo "Launched dn$i" 12 | done 13 | sleep 2 14 | echo "Launching capture" 15 | DISPLAY=:0 LD_PRELOAD="${DIR}/libcgl-capture.so" $@ 16 | 17 | #for i in `seq 1 5`; do 18 | # ssh dn$i "killall -9 cgl-render" 19 | #done 20 | -------------------------------------------------------------------------------- /util/presentation/src/init.cpp: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | 3 | bool Application::init(vector args){ 4 | 5 | if(!mSurface.init(1024, 768, false)){ //888, 456 6 | return false; 7 | } 8 | 9 | if(!mPresentation.init(args)){ 10 | return false; 11 | } 12 | 13 | LOG("Init done!\n"); 14 | 15 | return true; 16 | } 17 | 18 | bool Application::shutdown(){ 19 | 20 | if(!mSurface.shutdown()){ 21 | return false; 22 | } 23 | 24 | mPresentation.shutdown(); 25 | 26 | return true; 27 | } 28 | -------------------------------------------------------------------------------- /util/dist/make_deb.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | CGL_RUNTIME="../../../runtime" 3 | REVISION=`git shortlog | grep -E '^[ ]+\w+' | wc -l` 4 | 5 | echo "Making amd64 .deb package for r$REVISION" 6 | 7 | cd ../../ 8 | #make clean 9 | #make 10 | 11 | #Debian package 12 | sudo checkinstall -D -y\ 13 | --pkgname=clustergl\ 14 | --pkgversion=$REVISION-git\ 15 | --pkgsource=src\ 16 | --pakdir=util/dist\ 17 | --maintainer=paul\@bieh.net\ 18 | --requires="libsdl1.2debian, libsdl-net1.2, libglew1.6, liblzo2-2, libconfuse0, libzip1"\ 19 | --nodoc\ 20 | --install=no 21 | 22 | -------------------------------------------------------------------------------- /libcglinput/libcglinput.cfg: -------------------------------------------------------------------------------- 1 | device="/dev/input/spacenavigator" 2 | thresh=125 3 | 4 | axis y{ 5 | id=1 6 | positive=114 7 | negative=102 8 | } 9 | 10 | axis pitch{ 11 | id=3 12 | positive=119 13 | negative=115 14 | } 15 | 16 | axis roll{ 17 | id=4 18 | positive=101 19 | negative=113 20 | } 21 | 22 | axis yaw{ 23 | id=5 24 | positive=97 25 | negative=100 26 | } 27 | 28 | button leftbutton{ 29 | id=256 30 | keycode=114 31 | } 32 | 33 | button rightbutton{ 34 | id=257 35 | keycode=102 36 | } 37 | -------------------------------------------------------------------------------- /webcontrol/server/config.py: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # Configuration 3 | ################################################################################ 4 | 5 | #Location of the ClusterGL install to run 6 | CGL_LOCATION = "/home/paul/Projects/clustergl2" 7 | 8 | #Default configuration file 9 | CGL_CONFIG_FILE = CGL_LOCATION + "/runtime/single.conf" 10 | 11 | #Hostnames or IPs of rendering machines that we will ssh into 12 | #CGL_RENDERERS = ["dn1", "dn2", "dn3", "dn4", "dn5"] 13 | CGL_RENDERERS = ["localhost"] 14 | 15 | CGL_PID_FILE = "/tmp/cglcapture.pid" 16 | -------------------------------------------------------------------------------- /runtime/single.conf: -------------------------------------------------------------------------------- 1 | # CGL config file for a single output. Used for testing. 2 | 3 | totalWidth = 640 4 | totalHeight = 480 5 | syncRate = 20 6 | fakeWindowX = 64 7 | fakeWindowY = 64 8 | enableStats = True 9 | interceptMode = "sdl" 10 | networkCompression = 3 11 | capturePidFile = "/tmp/cglcapture.pid" 12 | capturePipeline = {"app", "netclient"} 13 | outputPipeline = {"netsrv", "exec"} 14 | remoteConfigServerEnabled = True 15 | 16 | output center { 17 | sizeX = 640 18 | sizeY = 480 19 | offsetX = 0 20 | offsetY = 0 21 | address = "127.0.0.1" 22 | port = 12345 23 | viewmode = "viewport" 24 | angle = 0 25 | } 26 | 27 | -------------------------------------------------------------------------------- /src/mod_app_dummy.cpp: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | 3 | /************************************** 4 | Interception module stuff 5 | **************************************/ 6 | AppModule::AppModule(string command) 7 | { 8 | init(command); 9 | } 10 | 11 | 12 | bool AppModule::init(string command) 13 | { 14 | 15 | LOG("Created dummy AppModule! This shouldn't be used\n"); 16 | return false; 17 | } 18 | 19 | 20 | bool AppModule::process(vector *list) 21 | { 22 | 23 | LOG("Dummy AppModule can't do stuff\n"); 24 | return false; 25 | } 26 | 27 | 28 | bool AppModule::sync() 29 | { 30 | 31 | LOG("Dummy AppModule can't do stuff\n"); 32 | return true; 33 | } 34 | -------------------------------------------------------------------------------- /libcglinput/web/js/libcglinput.js: -------------------------------------------------------------------------------- 1 | function define_key(keycode, caption, x, y){ 2 | var html = ""; 3 | 4 | html += "" + 14 | ""; 15 | 16 | $("#keyboard").append(html); 17 | } 18 | 19 | function keydown(keycode){ 20 | $.ajax({url:"/kbdown/" + keycode}); 21 | } 22 | 23 | function keyup(keycode){ 24 | $.ajax({url:"/kbup/" + keycode}); 25 | } -------------------------------------------------------------------------------- /runtime/cgl-capture: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #Find the location of the CGL library 4 | # - Could be in the same directory as this script (development) 5 | # - Could be in /usr/lib/ (deployment) 6 | 7 | LOCATION=$(cd ${0%/*} && echo $PWD/${0##*/}) 8 | DIR=`dirname "$LOCATION"` 9 | 10 | if [ -f $DIR/libcgl-capture.so ] 11 | then 12 | LIB=$DIR/libcgl-capture.so 13 | elif [ -f /usr/lib/libcgl-capture.so ] 14 | then 15 | LIB=/usr/lib/libcgl-capture.so 16 | else 17 | echo "Couldn't find a libcgl-capture.so" 18 | exit 19 | fi 20 | 21 | echo "(cgl-capture: Using $LIB)" 22 | 23 | LD_PRELOAD=$LIB $@ 24 | #cd $RUNTIME_DIR && LD_PRELOAD=$DIR/libcgl-capture.so gdb -ex run -quiet --args ./`basename $@` 25 | -------------------------------------------------------------------------------- /util/getconsts.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | params = {} 3 | 4 | 5 | for line in open("/usr/include/GL/gl.h").readlines(): 6 | if line.find("#define GL_") >= 0: 7 | line = line.replace("\t", " ").strip() 8 | parts = line.split(" ") 9 | name = parts[1].strip() 10 | val = int(parts[-1].strip(), 16) 11 | 12 | if val in params: 13 | params[val] = params[val] + " OR " + name 14 | else: 15 | params[val] = name 16 | 17 | print "#include \"main.h\"" 18 | print 19 | print "const char *getGLParamName(unsigned int param){" 20 | print 21 | print "\tswitch (param){" 22 | 23 | for k,v in params.iteritems(): 24 | print "\t\tcase " + str(hex(k)) + ": return \"" + v + "\";" 25 | 26 | print "\t\tdefault: return \"Unknown\";" 27 | print "\t}" 28 | print "}" 29 | -------------------------------------------------------------------------------- /runtime/tests/lesson05/README: -------------------------------------------------------------------------------- 1 | Readme for NeHe's OpenGL Tutorial Lesson 05 Linux/SDL port 2 | ========================================================== 3 | 4 | Compilation: 5 | 6 | make 7 | 8 | Running: 9 | 10 | ./lesson05 11 | 12 | Requirements: 13 | 14 | - OpenGL headers and libraries 15 | - SDL headers and libraries (I've used version 1.1.7 and 1.2.0) 16 | - gcc (any other ANSI C compiler should do it too; I used gcc 2.96) 17 | 18 | Known bugs/issues: 19 | 20 | Contact: 21 | 22 | If you have any problems, comments, or have useful hints, 23 | email to leggett@eecs.tulane.edu 24 | 25 | Credits: 26 | Jeff Molofee (nehe@connect.ab.ca) for writing the tutorials. 27 | Ti Leggett for the port to linux/SDL 28 | Mihael Vrbanec for the Makefile and this README template 29 | -------------------------------------------------------------------------------- /runtime/tests/texture/README: -------------------------------------------------------------------------------- 1 | Readme for NeHe's OpenGL Tutorial Lesson 05 Linux/SDL port 2 | ========================================================== 3 | 4 | Compilation: 5 | 6 | make 7 | 8 | Running: 9 | 10 | ./lesson05 11 | 12 | Requirements: 13 | 14 | - OpenGL headers and libraries 15 | - SDL headers and libraries (I've used version 1.1.7 and 1.2.0) 16 | - gcc (any other ANSI C compiler should do it too; I used gcc 2.96) 17 | 18 | Known bugs/issues: 19 | 20 | Contact: 21 | 22 | If you have any problems, comments, or have useful hints, 23 | email to leggett@eecs.tulane.edu 24 | 25 | Credits: 26 | Jeff Molofee (nehe@connect.ab.ca) for writing the tutorials. 27 | Ti Leggett for the port to linux/SDL 28 | Mihael Vrbanec for the Makefile and this README template 29 | -------------------------------------------------------------------------------- /util/presentation/src/update.cpp: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | 3 | extern bool presentationFinished; 4 | 5 | bool Application::update(){ 6 | 7 | processEvents(); 8 | 9 | if(presentationFinished){ 10 | requestShutdown(); 11 | } 12 | 13 | return true; 14 | } 15 | 16 | 17 | void Application::onMouseEvent(int button, int event){ 18 | 19 | } 20 | 21 | void Application::onKeyEvent(int keycode, int event){ 22 | 23 | if(event != SDL_KEYUP){ 24 | return; 25 | } 26 | 27 | if(keycode == SDLK_ESCAPE){ 28 | requestShutdown(); 29 | } 30 | 31 | if(keycode == SDLK_SPACE){ 32 | mPresentation.next(); 33 | } 34 | 35 | if(keycode == SDLK_p){ 36 | mPresentation.prev(); 37 | } 38 | 39 | if(keycode == SDLK_r){ 40 | mPresentation.toggleReadabilityMovement(); 41 | } 42 | } 43 | 44 | -------------------------------------------------------------------------------- /util/presentation/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | 3 | bool bRequestShutdown = false; 4 | 5 | void requestShutdown(){ 6 | LOG("Shutting down!\n"); 7 | bRequestShutdown = true; 8 | } 9 | 10 | int Application::run(vector args){ 11 | 12 | if(!init(args)){ 13 | return 1; 14 | } 15 | 16 | while(!bRequestShutdown){ 17 | if(!update()){ 18 | break; 19 | } 20 | render(); 21 | } 22 | 23 | return shutdown() ? 0 : 1; 24 | } 25 | 26 | Application::Application(){ 27 | 28 | } 29 | 30 | 31 | 32 | 33 | 34 | int main(int argc, char **argv){ 35 | Application *a = new Application(); 36 | 37 | vector args; 38 | for(int i=1;irun(args); 43 | 44 | delete a; 45 | 46 | return ret; 47 | } 48 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | @export ARCH 3 | $(MAKE) -C src 4 | $(MAKE) -C runtime/tests 5 | 6 | clean: 7 | $(MAKE) clean -C src 8 | $(MAKE) clean -C runtime/tests 9 | 10 | test: 11 | cd runtime && \ 12 | gnome-terminal -e "./cgl-render left" && \ 13 | gnome-terminal -e "./cgl-render center" && \ 14 | gnome-terminal -e "./cgl-render right" && \ 15 | sleep 1 && \ 16 | gnome-terminal -e "./cgl-capture tests/row/row" 17 | 18 | debugrender: 19 | cd runtime && \ 20 | gdb -ex run -quiet --args ./cgl-render left 21 | 22 | 23 | install: 24 | @cp runtime/cgl-render /usr/bin/ -v 25 | @cp runtime/cgl-capture /usr/bin/ -v 26 | @cp runtime/libcgl-capture.so /usr/lib -v 27 | @cp runtime/cgl.conf /etc/ -v 28 | 29 | uninstall: 30 | @rm -fv /usr/bin/cgl-render /usr/bin/cgl-capture /usr/lib/libcgl-capture.so /etc/cgl.conf -------------------------------------------------------------------------------- /src/include/instruction.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | instruction.h 3 | *******************************************************************************/ 4 | 5 | //TODO: will this be enough? 6 | #define MAX_ARG_LEN 48 7 | 8 | class InstructionBuffer 9 | { 10 | public: 11 | byte *buffer; 12 | uint32_t len; 13 | bool needClear; 14 | bool needReply; 15 | bool needRemoteReply; 16 | uint32_t hash; 17 | uint32_t hashlen; 18 | }; 19 | 20 | class Instruction 21 | { 22 | public: 23 | Instruction(); 24 | void clear(); 25 | bool compare(Instruction *other); 26 | Instruction *copy(); 27 | bool needReply(); 28 | 29 | uint16_t id; 30 | byte arglen; 31 | 32 | InstructionBuffer buffers[3]; 33 | 34 | //Must be the last thing... 35 | byte args[MAX_ARG_LEN]; 36 | }; 37 | -------------------------------------------------------------------------------- /runtime/test.conf: -------------------------------------------------------------------------------- 1 | # Config file used for the example in documentation 2 | 3 | totalWidth = 640 4 | totalHeight = 480 5 | syncRate = 20 6 | fakeWindowX = 32 7 | fakeWindowY = 32 8 | enableStats = True 9 | interceptMode = "sdl" 10 | networkCompression = 3 11 | capturePidFile = "/tmp/cglcapture.pid" 12 | capturePipeline = {"app", "netclient"} 13 | outputPipeline = {"netsrv", "exec"} 14 | 15 | output leftbottom { 16 | sizeX = 640 17 | sizeY = 240 18 | positionX = 20 19 | positionY = 260 20 | offsetX = 0 21 | offsetY = 0 22 | address = "127.0.0.1" 23 | port = 12345 24 | viewmode = "viewport" 25 | angle = 0 26 | } 27 | 28 | output lefttop { 29 | sizeX = 640 30 | sizeY = 240 31 | positionX = 20 32 | positionY = 0 33 | offsetX = 0 34 | offsetY = 240 35 | address = "127.0.0.1" 36 | port = 12346 37 | viewmode = "viewport" 38 | angle = 0 39 | } 40 | -------------------------------------------------------------------------------- /runtime/lg.conf: -------------------------------------------------------------------------------- 1 | # Example CGL config file for a liquid galaxy 2 | 3 | totalWidth = 1080 4 | totalHeight = 1820 5 | syncRate = 20 6 | fakeWindowX = 1080 7 | fakeWindowY = 1820 8 | enableStats = False 9 | interceptMode = "sdl" 10 | capturePipeline = {"app", "netclient"} 11 | outputPipeline = {"netsrv", "exec"} 12 | 13 | output left { 14 | sizeX = 1080 15 | sizeY = 1820 16 | offsetX = 0 17 | offsetY = 0 18 | address = "localhost" 19 | port = 12345 20 | viewmode = "curve" 21 | angle = -35 22 | } 23 | 24 | output center { 25 | sizeX = 1080 26 | sizeY = 1820 27 | offsetX = 0 28 | offsetY = 0 29 | address = "localhost" 30 | port = 12346 31 | viewmode = "curve" 32 | angle = 0 33 | } 34 | 35 | output right { 36 | sizeX = 1080 37 | sizeY = 1820 38 | offsetX = 0 39 | offsetY = 0 40 | address = "localhost" 41 | port = 12347 42 | viewmode = "curve" 43 | angle = 35 44 | } 45 | -------------------------------------------------------------------------------- /webcontrol/css/main.css: -------------------------------------------------------------------------------- 1 | body{ 2 | background-color:#fff; 3 | color:#000; 4 | font-family:sans-serif; 5 | } 6 | 7 | #header{ 8 | font-size:24pt; 9 | background:#222; 10 | font-size:16pt; 11 | text-align:left; 12 | position:absolute; 13 | top:0px; 14 | left:0px; 15 | width:98%; 16 | height:30px; 17 | color:#fff; 18 | padding:1%; 19 | border-bottom: 3px solid #00AEFF; 20 | } 21 | 22 | #rightheader{ 23 | font-size:10pt; 24 | text-align:right; 25 | position:absolute; 26 | top:0px; 27 | right:0px; 28 | padding:1%; 29 | } 30 | 31 | #content{ 32 | font-size:12pt; 33 | position:absolute; 34 | top:100px; 35 | left:5%; 36 | width:90%; 37 | 38 | } 39 | 40 | .input_text{ 41 | width:500px; 42 | } 43 | 44 | A:link {text-decoration: none; color:#00AEFF} 45 | A:visited {text-decoration: none; color: purple} 46 | A:active {text-decoration: none} 47 | A:hover {text-decoration: underline; color: #00AEFF;} 48 | -------------------------------------------------------------------------------- /webcontrol/index.php: -------------------------------------------------------------------------------- 1 | 5 | 6 |
7 | 8 | 9 | Current display wall contents: 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |

18 | 19 | Available applications: 20 | 21 | 22 | "; 27 | echo ""; 28 | echo ""; 29 | echo ""; 30 | } 31 | ?> 32 | 33 |
".$app->name."".$app->descr."
34 | 35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /libcglinput/src/main.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | libcglinput 3 | *******************************************************************************/ 4 | #include "main.h" 5 | 6 | //Globals 7 | IInject *mInject = NULL; 8 | Config *mConfig = NULL; 9 | 10 | /******************************************************************************* 11 | Entry point 12 | *******************************************************************************/ 13 | bool run(string method){ 14 | LOG("run(%s)\n", method.c_str()); 15 | 16 | 17 | char *configFile = (char *)"/etc/libcglinput.conf"; 18 | 19 | if(getenv("CGLINPUT_CONFIG_FILE")){ 20 | configFile = getenv("CGLINPUT_CONFIG_FILE"); 21 | } 22 | 23 | mConfig = new Config(configFile); 24 | 25 | if(!mInject){ 26 | LOG("Injection method wasn't initialised!"); 27 | return false; 28 | } 29 | 30 | if(!begin_web()){ 31 | LOG("Failed to start web server\n"); 32 | return false; 33 | } 34 | 35 | if(!begin_spacenav()){ 36 | LOG("Failed to start spacenav listener"); 37 | } 38 | 39 | return true; 40 | } 41 | 42 | -------------------------------------------------------------------------------- /webcontrol/configure.php: -------------------------------------------------------------------------------- 1 | 5 | 6 |
7 | 8 | $_REQUEST["name"])); 10 | 11 | echo "Configuring ".$request->name."
\n"; 12 | echo "".$request->descr."

\n"; 13 | echo "
\n"; 14 | echo ""; 15 | echo "name."\">"; 16 | echo "\n"; 17 | 18 | foreach($request->options as $option){ 19 | echo "\n"; 20 | echo "\n"; 21 | echo "\n"; 22 | echo "\n"; 23 | echo "\n"; 24 | } 25 | 26 | echo "
".$option[0]."".$option[1]."
\n"; 27 | 28 | echo "

"; 29 | echo " or "; 30 | echo "Cancel "; 31 | echo "
\n"; 32 | 33 | ?> 34 | 35 | 36 | 37 |
38 | 39 | 40 | -------------------------------------------------------------------------------- /util/getsize/parse.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | def n(s): 4 | if s.find("one value") > 0: 5 | return 1 6 | elif s.find("single boolean value") > 0: 7 | return 1 8 | elif s.find("single enumerated value") > 0: 9 | return 1 10 | elif s.find("a single integer value") > 0: 11 | return 1 12 | elif s.find("a single floating-point value") > 0: 13 | return 1 14 | elif s.find("a single positive floating-point value") > 0: 15 | return 1 16 | elif s.find("a single value") > 0: 17 | return 1 18 | elif s.find("two values") > 0: 19 | return 2 20 | elif s.find("three values") > 0: 21 | return 3 22 | elif s.find("four values") > 0: 23 | return 4 24 | elif s.find("four boolean values") > 0: 25 | return 4 26 | elif s.find("16 values") > 0: 27 | return 16 28 | elif s.find("sixteen values") > 0: 29 | return 16 30 | print "*** " + s 31 | return -1 32 | 33 | param = "" 34 | 35 | for line in open("input.txt").readlines(): 36 | line = line.strip() 37 | 38 | if line.find("GL_") == 0: 39 | param = line 40 | 41 | elif line.find("params returns ") >= 0: 42 | print "case " + param + ": return " + str(n(line)) + ";" 43 | -------------------------------------------------------------------------------- /util/presentation/src/include/main.h: -------------------------------------------------------------------------------- 1 | #include "libs.h" 2 | #include "vector.h" 3 | #include "misc.h" 4 | #include "glutil.h" 5 | #include "surface.h" 6 | #include "texture.h" 7 | #include "presentation.h" 8 | 9 | //global configuration 10 | extern int iScreenX; 11 | extern int iScreenY; 12 | extern bool bFullscreen; 13 | 14 | //global functions 15 | extern void requestShutdown(); 16 | 17 | //other global objects 18 | extern GLUtil mGLU; 19 | 20 | #define LOG printf 21 | #define ERR printf 22 | 23 | 24 | /******************************************************************************* 25 | Main app class 26 | *******************************************************************************/ 27 | class Application{ 28 | public: 29 | Application(); 30 | int run(vector args); 31 | 32 | //event handling 33 | void processEvents(); 34 | void onMouseEvent(int button, int event); 35 | void onKeyEvent(int keycode, int event); 36 | 37 | private: 38 | 39 | Surface mSurface; 40 | Presentation mPresentation; 41 | 42 | //mainloop functions 43 | bool init(vector args); 44 | bool update(); 45 | void render(); 46 | bool shutdown(); 47 | 48 | }; 49 | -------------------------------------------------------------------------------- /util/presentation/src/Makefile: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------# 2 | # Configuration 3 | #------------------------------------------------------# 4 | 5 | 6 | #Output filename 7 | NAME= presentation 8 | 9 | 10 | #files 11 | SOURCES := $(wildcard *.cpp) 12 | OBJS := $(patsubst %.cpp, %.o, $(SOURCES)) 13 | DEPS := $(wildcard include/*.h) 14 | 15 | #compiler-type things 16 | CXXFLAGS=-Iinclude -O3 -Wall 17 | LDFLAGS=-L../lib/ -lGL -lGLU `sdl-config --cflags --libs` -lIL -lILU -lILUT -lSDL_ttf -lSDL_net -lconfuse -lGLEW 18 | #CGL libs 19 | #-lCg -lCgGL 20 | 21 | #------------------------------------------------------# 22 | # Compile 23 | #------------------------------------------------------# 24 | all: $(OBJS) $(NAME) 25 | 26 | $(NAME): $(OBJS) 27 | $(CXX) -o ../runtime/$@ $^ $(CXXFLAGS) $(LDFLAGS) 28 | 29 | #------------------------------------------------------# 30 | # Test 31 | #------------------------------------------------------# 32 | run-app: 33 | @../runtime/$(NAME) 34 | 35 | #------------------------------------------------------# 36 | # Clean 37 | #------------------------------------------------------# 38 | clean: 39 | rm -f *.o 40 | rm -f ../runtime/$(NAME) 41 | -------------------------------------------------------------------------------- /util/dist/make_deb_i386.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | CGL_RUNTIME="../../../runtime" 3 | REVISION=`git shortlog | grep -E '^[ ]+\w+' | wc -l` 4 | 5 | echo "Making i386 .deb package for r$REVISION" 6 | 7 | cd ../../../ 8 | 9 | make clean 10 | ARCH=-m32 make 11 | cd util/dist 12 | 13 | rm -rf files 14 | mkdir files 15 | cd files 16 | 17 | cp -v $CGL_RUNTIME/cgl-render . 18 | cp -v $CGL_RUNTIME/cgl-capture . 19 | cp -v $CGL_RUNTIME/libcgl-capture.so . 20 | cp -v $CGL_RUNTIME/cgl.conf . 21 | 22 | #Build the package control file. TODO, this should be a template file 23 | CONTROL_FILE="clustergl-r$REVISION" 24 | 25 | echo "Package: clustergl" > $CONTROL_FILE 26 | echo "Version: $REVISION-git" >> $CONTROL_FILE 27 | echo "Maintainer: Paul Hunkin " >> $CONTROL_FILE 28 | echo "Architecture: amd64" >> $CONTROL_FILE 29 | echo "Depends: libsdl1.2 libsdl-net1.2 libglew liblzo2 libconfuse libzip" 30 | echo "Files: cgl-render /usr/bin/cgl-render" >> $CONTROL_FILE 31 | echo " cgl-capture /usr/bin/cgl-capture" >> $CONTROL_FILE 32 | echo " libcgl-capture.so /usr/lib/libcgl-capture.so" >> $CONTROL_FILE 33 | echo " cgl.conf /etc/cgl.conf" >> $CONTROL_FILE 34 | 35 | equivs-build ./clustergl-r$REVISION > /dev/null 36 | 37 | mv *.deb ../ 38 | -------------------------------------------------------------------------------- /util/presentation/src/texture.cpp: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | 3 | Texture::Texture(string filename){ 4 | load(filename, 0); 5 | } 6 | 7 | bool Texture::load(string filename, int flags){ 8 | 9 | bIsLoaded = false; 10 | 11 | ilGenImages(1, &iDevilID); 12 | ilBindImage(iDevilID); 13 | 14 | //Load the data 15 | if(!ilLoadImage((char *)filename.c_str())){ 16 | int err = ilGetError(); 17 | ERR("error: %s, %d!\n", filename.c_str(), err); 18 | return false; 19 | } 20 | 21 | iSizeX = ilGetInteger(IL_IMAGE_WIDTH); 22 | iSizeY = ilGetInteger(IL_IMAGE_HEIGHT); 23 | 24 | //if(flags != TEXTURE_NO_GL){ 25 | 26 | mHandle = ilutGLBindTexImage(); // 27 | 28 | if(mHandle == 0){ 29 | LOG("Failed to get handle!\n"); 30 | return false; 31 | } 32 | //} 33 | 34 | ilDeleteImages(1, &iDevilID); 35 | 36 | bIsLoaded = true; 37 | 38 | return true; 39 | } 40 | 41 | void Texture::bind(){ 42 | 43 | if(!isLoaded()){ 44 | LOG("Tried to bind a null texture!\n"); 45 | return; 46 | } 47 | 48 | 49 | 50 | glEnable(GL_TEXTURE_2D); 51 | glBindTexture(GL_TEXTURE_2D, mHandle); 52 | 53 | 54 | } 55 | 56 | void Texture::destroy(){ 57 | glDeleteTextures(1, &mHandle); 58 | bIsLoaded = false; 59 | } 60 | -------------------------------------------------------------------------------- /webcontrol/server/apps/lesson05.py: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # Simple rotating cube program 3 | ################################################################################ 4 | 5 | #Name of the application. 6 | def name(): 7 | return "lesson05" 8 | 9 | #Free-form text description of the application 10 | def descr(): 11 | return "This is a rotating cube. It's pretty exciting" 12 | 13 | #Return a list of configurable options that will be rendered in html 14 | #Each individual option is a [name, description, type] 15 | def options(): 16 | return [ ["arg1", "The first argument", "text"], 17 | ["arg2", "The second argument", "text"], 18 | ["arg3", "The third and most awesome argument", "text"] ] 19 | 20 | #Called when the app is being launched. A dict with the arguments is provided 21 | #We return the command line to launch the app. Use the full path! 22 | #We could also create config files or something here 23 | #If you want to validate arguments in here, return None if you want to abort 24 | #the run 25 | def on_run(args): 26 | return "/home/paul/Projects/clustergl2/runtime/tests/lesson05/lesson05 " + args["arg1"] 27 | 28 | #Called when we are being shut down. 29 | def on_shutdown(): 30 | return 31 | 32 | -------------------------------------------------------------------------------- /libcglinput/Makefile: -------------------------------------------------------------------------------- 1 | 2 | #Architectecture 3 | UNAME := $(shell uname -s) 4 | 5 | #Output filename 6 | NAME= cglinput 7 | 8 | #files 9 | SOURCES := $(wildcard src/*.cpp) 10 | OBJS := $(patsubst %.cpp, %.o, $(SOURCES)) 11 | 12 | OBJS_APP := $(patsubst mod_app.o,,$(OBJS)) 13 | DEPS := $(wildcard include/*.h) 14 | 15 | #Compiler flags. Note the arch-specific ones 16 | CXXFLAGS=$(ARCH) -I/opt/local/include/ -Isrc/include -O3 -Wextra -g -fPIC -fvisibility-inlines-hidden 17 | LDFLAGS=-lconfuse -lpthread 18 | DARWIN_LDFLAGS= -lintl -L/opt/local/lib -lSDL 19 | LINUX_LDFLAGS=-lSDL 20 | 21 | #Compile 22 | all: testprog $(OBJS) $(NAME) 23 | 24 | $(NAME): $(OBJS) 25 | ifeq ($(UNAME),Darwin) 26 | $(CXX) -shared -o ./lib$@.so $(OBJS) $(CXXFLAGS) $(LDFLAGS) $(DARWIN_LDFLAGS) 27 | endif 28 | ifeq ($(UNAME),Linux) 29 | $(CXX) -shared -o ./lib$@.so $(OBJS) $(CXXFLAGS) $(LDFLAGS) $(LINUX_LDFLAGS) 30 | endif 31 | 32 | testprog: 33 | ifeq ($(UNAME),Darwin) 34 | gcc --std=c99 -g -I/opt/local/include -I/usr/X11R6/include -L/opt/local/lib -lSDLmain -lSDL -Wl,-framework,Cocoa -framework OpenGL lesson05.c -o lesson05 35 | endif 36 | ifeq ($(UNAME),Linux) 37 | gcc --std=c99 -g `sdl-config --cflags --libs` lesson05.c -o lesson05 -lGL -lGLU -lSDL 38 | endif 39 | 40 | #Cleanup 41 | clean: 42 | rm -f src/*.o 43 | rm -f ./lib$(NAME).so 44 | rm -f lesson05 45 | -------------------------------------------------------------------------------- /runtime/symphony.conf: -------------------------------------------------------------------------------- 1 | # CGL config file for the Symphony display wall 2 | 3 | totalWidth = 8880 4 | totalHeight = 4560 5 | syncRate = 20 6 | fakeWindowX = 640 7 | fakeWindowY = 480 8 | enableStats = False 9 | interceptMode = "sdl" 10 | networkCompression = 3 11 | capturePidFile = "/tmp/cglcapture.pid" 12 | capturePipeline = {"app", "netclient"} 13 | outputPipeline = {"netsrv", "exec"} 14 | 15 | #Individual outputs 16 | output dn1 { 17 | sizeX = 1680 18 | sizeY = 4560 19 | offsetX = 0 20 | offsetY = 0 21 | address = "192.168.22.201" 22 | port = 12345 23 | viewmode = "viewport" 24 | angle = 0 25 | } 26 | 27 | output dn2 { 28 | sizeX = 1680 29 | sizeY = 4560 30 | offsetX = 1800 31 | offsetY = 0 32 | address = "192.168.22.202" 33 | port = 12345 34 | viewmode = "viewport" 35 | angle = 0 36 | } 37 | 38 | output dn3 { 39 | sizeX = 1680 40 | sizeY = 4560 41 | offsetX = 3600 42 | offsetY = 0 43 | address = "192.168.22.203" 44 | port = 12345 45 | viewmode = "viewport" 46 | angle = 0 47 | } 48 | 49 | output dn4 { 50 | sizeX = 1680 51 | sizeY = 4560 52 | offsetX = 5400 53 | offsetY = 0 54 | address = "192.168.22.204" 55 | port = 12345 56 | viewmode = "viewport" 57 | angle = 0 58 | } 59 | 60 | output dn5 { 61 | sizeX = 1680 62 | sizeY = 4560 63 | offsetX = 7200 64 | offsetY = 0 65 | address = "192.168.22.205" 66 | port = 12345 67 | viewmode = "viewport" 68 | angle = 0 69 | } 70 | 71 | -------------------------------------------------------------------------------- /src/stats.cpp: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | 3 | #define INTERVAL 1000 4 | 5 | std::map mCounts; 6 | std::map mIncrements; 7 | int lastOutputTime = 0; 8 | int frames = 0; 9 | 10 | void Stats::count(string key, int count){ 11 | 12 | if(mCounts.find(key) != mCounts.end()){ 13 | mCounts[key] += count; 14 | }else{ 15 | mCounts[key] = count; 16 | } 17 | } 18 | 19 | void Stats::increment(string key, int count){ 20 | 21 | if(mIncrements.find(key) != mIncrements.end()){ 22 | mIncrements[key] += count; 23 | }else{ 24 | mIncrements[key] = count; 25 | } 26 | } 27 | 28 | void Stats::update(){ 29 | int time = SDL_GetTicks(); 30 | frames++; 31 | 32 | increment("ticks"); 33 | 34 | if(time - lastOutputTime > INTERVAL){ 35 | output(); 36 | lastOutputTime = time; 37 | frames = 0; 38 | mCounts.clear(); 39 | mIncrements.clear(); 40 | } 41 | } 42 | 43 | void Stats::output(){ 44 | 45 | printf("\n********************************************\n"); 46 | 47 | printf("Total over the last %dms:\n", INTERVAL); 48 | for (map::iterator i = mIncrements.begin(); i != mIncrements.end(); i++){ 49 | int val = i->second; 50 | printf(" %s: %d\n", i->first.c_str(), val); 51 | } 52 | 53 | printf("\nAverage per tick over the last %dms:\n", INTERVAL); 54 | for (map::iterator i = mCounts.begin(); i != mCounts.end(); i++){ 55 | int val = i->second; 56 | val /= frames; 57 | printf(" %s: %d\n", i->first.c_str(), val); 58 | } 59 | printf("********************************************\n"); 60 | } 61 | -------------------------------------------------------------------------------- /src/mod_insert.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************** 2 | Headers 3 | ********************************************************/ 4 | 5 | #include "main.h" 6 | 7 | /********************************************************* 8 | Insertion Globals 9 | *********************************************************/ 10 | 11 | Instruction mInst[100]; 12 | //the number of instructions used 13 | int instCount = 0; 14 | //current instruction 15 | Instruction *mCurrInst = NULL; 16 | byte *mArgs = NULL; 17 | 18 | /********************************************************* 19 | Interception module stuff 20 | *********************************************************/ 21 | InsertModule::InsertModule() 22 | { 23 | init(); 24 | } 25 | 26 | 27 | bool InsertModule::init() 28 | { 29 | /* create the list we are going to add to each frame */ 30 | return true; 31 | } 32 | 33 | 34 | bool InsertModule::process(vector *list) 35 | { 36 | Instruction *lastInstruction = list->back(); 37 | //i.e. swap buffers 38 | if(lastInstruction->id == 1499) { 39 | 40 | //remove swap buffers 41 | list->pop_back(); 42 | 43 | //add our instructions 44 | for(int i=0;ipush_back(&mInst[i]); 46 | } 47 | 48 | //add swap buffers 49 | list->push_back(lastInstruction); 50 | } 51 | 52 | return true; 53 | } 54 | 55 | 56 | void InsertModule::reply(Instruction *instr, int i) 57 | { 58 | LOG("InsertModule::reply: Shouldn't happen!\n"); 59 | } 60 | 61 | 62 | bool InsertModule::sync() 63 | { 64 | return true; 65 | } 66 | -------------------------------------------------------------------------------- /webcontrol/utils.php: -------------------------------------------------------------------------------- 1 | $value) { 16 | //so that we can just pass $_REQUEST 17 | if(strcmp($key, "op") != 0){ 18 | $url = $url."&".urlencode($key)."=".urlencode($value); 19 | } 20 | } 21 | return $url; 22 | } 23 | 24 | function api_get($url){ 25 | 26 | $data = file_get_contents($url); 27 | 28 | if($data === FALSE){ 29 | die("(Could not contact webcontrol API (request)"); 30 | } 31 | 32 | return json_decode($data); 33 | } 34 | 35 | 36 | 37 | function makeHeader(){ 38 | 39 | ?> 40 | 41 | 42 | Symphony - ClusterGL WebControl 43 | 44 | 45 | 46 | 63 | 64 | 69 | -------------------------------------------------------------------------------- /webcontrol/server/util/webserver.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | ################################################################################ 3 | # Simple HTTP server 4 | ################################################################################ 5 | import string, cgi, time 6 | import json as simplejson 7 | from os import curdir, sep 8 | from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer 9 | #import pri 10 | 11 | _get_handler = None 12 | 13 | def extract_args(path): 14 | if path.find("?") < 0: 15 | return {"path":path} 16 | base = path[:path.find("?")] 17 | ret = {"path":base} 18 | for kv in path[path.find("?")+1:].split("&"): 19 | s = kv.split("=") 20 | ret[s[0].strip().lower()] = s[1].strip() 21 | return ret 22 | 23 | 24 | class WebRequestHandler(BaseHTTPRequestHandler): 25 | def do_GET(self): 26 | try: 27 | ret = _get_handler(extract_args(self.path)) 28 | 29 | if ret == None: 30 | self.send_error(404,'Not found: %s' % self.path) 31 | return 32 | 33 | self.send_response(200) 34 | self.send_header('Content-type', 'text/plain') 35 | self.end_headers() 36 | self.wfile.write(simplejson.dumps(ret, sort_keys=True, indent=4)) 37 | except IOError: 38 | self.send_error(500,'Error handling request: %s' % self.path) 39 | 40 | 41 | def run(get_handler): 42 | 43 | global _get_handler 44 | _get_handler = get_handler 45 | 46 | try: 47 | server = HTTPServer(('', 8080), WebRequestHandler) 48 | print 'Waiting for requests' 49 | server.serve_forever() 50 | except KeyboardInterrupt: 51 | print 'Shutting down server' 52 | server.socket.close() 53 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | ################################# 2 | # ClusterGL main makefile 3 | ################################# 4 | 5 | #Architectecture 6 | UNAME := $(shell uname -s) 7 | 8 | #Output filename 9 | NAME= cgl 10 | 11 | #files 12 | SOURCES := $(wildcard *.cpp) 13 | OBJS := $(patsubst %.cpp, %.o, $(SOURCES)) 14 | 15 | #OK. So, we don't want to link mod_app with the standalone app. So we link in 16 | #a dummy one instead. This works, as at runtime we don't use it, it just makes 17 | #the linker happy. In order to do this, we build up two objects lines 18 | OBJS_SHARED := $(patsubst mod_app_dummy.o,,$(OBJS)) 19 | OBJS_APP := $(patsubst mod_app.o,,$(OBJS)) 20 | DEPS := $(wildcard include/*.h) 21 | 22 | #Compiler flags. Note the arch-specific ones 23 | CXXFLAGS=$(ARCH) -I/opt/local/include/ -Iinclude -O3 -Wextra -g -fPIC -fvisibility-inlines-hidden 24 | LDFLAGS=-lconfuse -llzo2 -lz `sdl-config --cflags --libs` -lSDL_net -lconfuse -lGLEW 25 | DARWIN_LDFLAGS=-framework,Cocoa -framework OpenGL -lintl 26 | LINUX_LDFLAGS=-lGL -lGLU 27 | 28 | #Compile 29 | all: $(OBJS) $(NAME) 30 | 31 | $(NAME): $(OBJS) 32 | ifeq ($(UNAME),Darwin) 33 | $(CXX) -o ../runtime/$@-render $(OBJS_APP) $(CXXFLAGS) $(LDFLAGS) $(DARWIN_LDFLAGS) 34 | $(CXX) -shared -o ../runtime/lib$@-capture.so $(OBJS_SHARED) $(CXXFLAGS) $(LDFLAGS) $(DARWIN_LDFLAGS) 35 | endif 36 | ifeq ($(UNAME),Linux) 37 | $(CXX) -o ../runtime/$@-render $(OBJS_APP) $(CXXFLAGS) $(LDFLAGS) $(LINUX_LDFLAGS) 38 | $(CXX) -shared -o ../runtime/lib$@-capture.so $(OBJS_SHARED) $(CXXFLAGS) $(LDFLAGS) $(LINUX_LDFLAGS) 39 | endif 40 | 41 | #Cleanup 42 | clean: 43 | rm -f *.o 44 | rm -f ../runtime/$(NAME) 45 | rm -f ../runtime/lib$(NAME).so.1 46 | -------------------------------------------------------------------------------- /util/presentation/src/events.cpp: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | 3 | 4 | /********************************************* 5 | SDL event loop 6 | **********************************************/ 7 | void Application::processEvents(){ 8 | 9 | SDL_Event event; 10 | 11 | while ( SDL_PollEvent( &event ) ){ 12 | 13 | switch( event.type ){ 14 | 15 | case SDL_VIDEORESIZE: 16 | mSurface.onResize(event.resize.w, event.resize.h); 17 | break; 18 | 19 | case SDL_QUIT: 20 | //handle quit requests 21 | requestShutdown(); 22 | break; 23 | 24 | case SDL_MOUSEBUTTONDOWN: 25 | onMouseEvent(event.button.button, event.type); 26 | break; 27 | 28 | case SDL_MOUSEBUTTONUP: 29 | onMouseEvent(event.button.button, event.type); 30 | break; 31 | 32 | case SDL_KEYDOWN: 33 | onKeyEvent(event.key.keysym.sym, event.type); 34 | break; 35 | 36 | case SDL_KEYUP: 37 | onKeyEvent(event.key.keysym.sym, event.type); 38 | break; 39 | 40 | default: 41 | break; 42 | } 43 | } 44 | 45 | /* 46 | if (!done){ 47 | 48 | //Do one frames worth of work and figure out the length of time 49 | uint32_t startTime = SDL_GetTicks(); 50 | renderMain(); 51 | updateMain(); 52 | uint32_t endTime = SDL_GetTicks(); 53 | 54 | //Figure out the scaling factor for FPS-independent movement 55 | uint32_t diff = endTime - startTime; 56 | fTimeScale = (float)diff * fTimeScaleScale; 57 | 58 | //Every hour, do a cleanup 59 | if(fCleanupTimer < 0.0f){ 60 | ps()->doPeriodicCleanup(); 61 | fCleanupTimer = CLEANUP_TIMER; 62 | } 63 | 64 | //Update our various timers 65 | fCleanupTimer -= fTimeScale; 66 | fUptime += fTimeScale; 67 | fParticleFPS = fTimeScale; 68 | } 69 | */ 70 | 71 | } 72 | 73 | 74 | -------------------------------------------------------------------------------- /libcglinput/src/include/main.h: -------------------------------------------------------------------------------- 1 | 2 | /******************************************************************************* 3 | libcglinput 4 | *******************************************************************************/ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | using std::vector; 15 | using std::string; 16 | 17 | #define LOG printf 18 | 19 | 20 | /******************************************************************************* 21 | Main functions 22 | *******************************************************************************/ 23 | extern bool run(string methods); 24 | extern bool begin_web(); 25 | extern bool begin_spacenav(); 26 | 27 | 28 | /******************************************************************************* 29 | Configuration 30 | *******************************************************************************/ 31 | static const int MAX_AXIS = 512; 32 | 33 | class Config{ 34 | public: 35 | Config(string filename); 36 | int axis_actions[MAX_AXIS][2]; 37 | string device; 38 | int num_axis; 39 | int thresh[MAX_AXIS]; 40 | }; 41 | 42 | extern Config *mConfig; 43 | 44 | /******************************************************************************* 45 | Injection interface 46 | *******************************************************************************/ 47 | 48 | class IInject{ 49 | public: 50 | virtual void keydown(int keycode)=0; 51 | virtual void keyup(int keycode)=0; 52 | }; 53 | 54 | class SDLInject : public IInject{ 55 | public: 56 | void keydown(int keycode); 57 | void keyup(int keycode); 58 | }; 59 | 60 | class XInject : public IInject{ 61 | public: 62 | void keydown(int keycode); 63 | void keyup(int keycode); 64 | }; 65 | 66 | extern IInject *mInject; 67 | -------------------------------------------------------------------------------- /util/presentation/src/include/libs.h: -------------------------------------------------------------------------------- 1 | 2 | /********************************************* 3 | STL 4 | **********************************************/ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | 20 | using std::string; 21 | using std::vector; 22 | using std::list; 23 | using std::stack; 24 | using std::map; 25 | 26 | /********************************************* 27 | C stdlib 28 | **********************************************/ 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #ifdef _WINDOWS 35 | #include 36 | #include 37 | #else 38 | #include 39 | #include 40 | #include 41 | #endif 42 | 43 | //libconfuse 44 | #include 45 | 46 | 47 | /********************************************* 48 | OpenGL 49 | **********************************************/ 50 | #ifdef ENABLE_CGL_COMPAT 51 | #define GL_GLEXT_PROTOTYPES 52 | #else 53 | #include 54 | #endif 55 | 56 | #include 57 | #include 58 | 59 | /********************************************* 60 | SDL* 61 | **********************************************/ 62 | #ifdef _WINDOWS 63 | #include 64 | #include 65 | #include 66 | #else 67 | #include 68 | #include 69 | #include 70 | #include 71 | #include 72 | #endif 73 | 74 | 75 | #define ILUT_USE_OPENGL 76 | 77 | //DevIL 78 | #include 79 | #include 80 | #include 81 | 82 | 83 | -------------------------------------------------------------------------------- /libcglinput/src/sdl.cpp: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | #include 3 | 4 | /******************************************************************************* 5 | SDL intercept 6 | *******************************************************************************/ 7 | 8 | //SDL functors 9 | static int (*_SDL_Init)(unsigned int flags) = NULL; 10 | 11 | static bool bHasInit = false; 12 | 13 | extern "C" int SDL_Init(unsigned int flags) { 14 | 15 | LOG("SDL_Init (%d)\n", bHasInit); 16 | if (_SDL_Init == NULL) { 17 | _SDL_Init = (int (*)(unsigned int)) dlsym(RTLD_NEXT, "SDL_Init"); 18 | } 19 | 20 | if(!_SDL_Init){ 21 | printf("Couldn't find SDL_Init: %s\n", dlerror()); 22 | exit(0); 23 | } 24 | 25 | int r = (*_SDL_Init)(flags); 26 | 27 | //Set up our internals 28 | if(!bHasInit && !mInject){ 29 | bHasInit = true; 30 | 31 | mInject = new SDLInject(); 32 | 33 | if(!run("sdl")){ 34 | exit(1); 35 | } 36 | }else{ 37 | LOG("Ignored a second/non-video SDL_Init()\n"); 38 | } 39 | 40 | //LOG("SDL_Init finished\n"); 41 | return r; 42 | } 43 | 44 | 45 | /******************************************************************************* 46 | SDL injection 47 | *******************************************************************************/ 48 | void SDLInject::keydown(int keycode){ 49 | // Create a user event to call the game loop. 50 | SDL_Event event; 51 | 52 | 53 | event.type = SDL_KEYDOWN; 54 | event.user.code = 0; 55 | event.key.keysym.sym = (SDLKey)keycode; 56 | event.user.data2 = 0; 57 | 58 | SDL_PushEvent(&event); 59 | } 60 | 61 | void SDLInject::keyup(int keycode){ 62 | // Create a user event to call the game loop. 63 | SDL_Event event; 64 | 65 | event.type = SDL_KEYUP; 66 | event.user.code = 0; 67 | event.key.keysym.sym = (SDLKey)keycode; 68 | event.user.data2 = 0; 69 | 70 | SDL_PushEvent(&event); 71 | } 72 | -------------------------------------------------------------------------------- /runtime/cgl.conf: -------------------------------------------------------------------------------- 1 | # Example CGL config file with comments 2 | 3 | totalWidth = 640 #The width the capturing app expects (ie: full width of your display wall) 4 | totalHeight = 480 #The height the capturing app expects (ie: full height of your display wall) 5 | syncRate = 20 #How often to send sync packets 6 | fakeWindowX = 640 #The width of the captured window. 7 | fakeWindowY = 480 #The height of the captured window 8 | enableStats = True #Output stats to stdout 9 | interceptMode = "sdl" #sdl or xorg, depending on the type of app you're trying to capture 10 | networkCompression = 3 #different types of network compression, 0-3. 0 is off. 11 | capturePidFile = "/tmp/cglcapture.pid" #set this to a temporary directory 12 | capturePipeline = {"app", "netclient"} #The modules used by the .so 13 | outputPipeline = {"netsrv", "exec"} #The modules used by the output 14 | 15 | 16 | 17 | 18 | #Individual outputs 19 | 20 | output leftbottom { 21 | sizeX = 320 #Size of this output 22 | sizeY = 240 23 | offsetX = 0 #Offset of this output from top-left in viewport mode 24 | offsetY = 0 25 | address = "127.0.0.1" #The IP this will be running on 26 | port = 12345 #The port this wll be running on 27 | viewmode = "viewport" #viewport or curve 28 | angle = 0 #for curve mode, the amount of angle 29 | } 30 | 31 | #Individual outputs 32 | output rightbottom { 33 | sizeX = 320 34 | sizeY = 240 35 | offsetX = 320 36 | offsetY = 0 37 | address = "127.0.0.1" 38 | port = 12346 39 | viewmode = "viewport" 40 | angle = 0 41 | } 42 | 43 | output lefttop { 44 | sizeX = 320 45 | sizeY = 240 46 | offsetX = 0 47 | offsetY = 240 48 | address = "127.0.0.1" 49 | port = 12347 50 | viewmode = "viewport" 51 | angle = 0 52 | } 53 | 54 | output righttop { 55 | sizeX = 320 56 | sizeY = 240 57 | offsetX = 320 58 | offsetY = 240 59 | address = "127.0.0.1" 60 | port = 12348 61 | viewmode = "viewport" 62 | angle = 0 63 | } 64 | 65 | -------------------------------------------------------------------------------- /src/include/libs.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | libs.h 3 | *******************************************************************************/ 4 | 5 | /********************************************* 6 | STL 7 | **********************************************/ 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | using std::string; 24 | using std::vector; 25 | using std::list; 26 | using std::stack; 27 | using std::map; 28 | 29 | /********************************************* 30 | C stdlib 31 | **********************************************/ 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | 46 | #include 47 | 48 | #include 49 | 50 | #include 51 | #include 52 | 53 | 54 | /********************************************* 55 | OpenGL 56 | **********************************************/ 57 | 58 | //Sometimes we don't want the GL headers interfering 59 | #ifndef NO_OPENGL_HEADERS 60 | #ifdef __APPLE__ 61 | #include 62 | #else 63 | #include 64 | #include 65 | #include 66 | #endif 67 | #endif 68 | 69 | 70 | /********************************************* 71 | SDL* 72 | **********************************************/ 73 | #include 74 | #include 75 | #include 76 | #include 77 | #include 78 | 79 | typedef unsigned char byte; 80 | 81 | #define MAX(a,b) ((a < b) ? (b) : (a)) 82 | #define MIN(a,b) ((((a)-(b))&0x80000000) >> 31)? (a) : (b) 83 | -------------------------------------------------------------------------------- /src/include/main.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | ClusterGL - main.h 3 | *******************************************************************************/ 4 | 5 | //#define ENABLE_DL_INTERCEPT 6 | 7 | #ifdef __APPLE__ 8 | #pragma clang diagnostic ignored "-Wunused-variable" 9 | #pragma clang diagnostic ignored "-Wunused-parameter" 10 | //#pragma clang diagnostic pop 11 | #endif 12 | 13 | /******************************************************************************* 14 | Internal headers 15 | *******************************************************************************/ 16 | #include "libs.h" 17 | #include "config.h" 18 | #include "utils.h" 19 | #include "instruction.h" 20 | #include "lru_cache.h" 21 | #include "module.h" 22 | #include "mongoose.h" 23 | 24 | 25 | /******************************************************************************* 26 | Statistics collector 27 | *******************************************************************************/ 28 | class Stats{ 29 | static void output(); 30 | public: 31 | static void count(string key, int count); 32 | static void increment(string key, int count=1); 33 | static void update(); 34 | }; 35 | 36 | /******************************************************************************* 37 | Main application object 38 | *******************************************************************************/ 39 | class App 40 | { 41 | vector mModules; 42 | 43 | void init(bool shared, const char *id); 44 | 45 | void stats_begin(); 46 | void stats_end(); 47 | 48 | public: 49 | 50 | //called when we're invoked from the command line 51 | int run(int argc, char **argv); 52 | 53 | //called when we're invoked from LD_PRELOAD 54 | //Will return false if we're not configured to run off this source 55 | bool run_shared(string src); 56 | 57 | bool tick(); 58 | 59 | void debug(); 60 | 61 | }; 62 | 63 | extern bool bIsIntercept; 64 | 65 | //Global config instance 66 | extern Config *gConfig; 67 | 68 | //mod_text 69 | void LOG_INSTRUCTION(Instruction *instr); 70 | 71 | //automatically generated, consts.cpp 72 | const char *getGLParamName(unsigned int param); 73 | -------------------------------------------------------------------------------- /src/include/utils.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | Compile-time configuration 3 | *******************************************************************************/ 4 | 5 | #define CGL_REPEAT_INSTRUCTION 1498 6 | #define MAX_INSTRUCTIONS 500000 7 | 8 | //Quick LOG hack that we can make a proper log system out of later 9 | #define LOG printf("[\e[32m%20s:%5d\e[m]\t", __FILE__, __LINE__); printf 10 | 11 | template T stringTo(const std::string& s) { 12 | std::istringstream iss(s); 13 | T x; 14 | iss >> x; 15 | return x; 16 | } 17 | 18 | template std::string toString(const T& x) { 19 | std::ostringstream oss; 20 | oss << x; 21 | return oss.str(); 22 | } 23 | 24 | 25 | 26 | 27 | /************************************** 28 | Network Buffer 29 | **************************************/ 30 | class BufferedFd 31 | { 32 | private: 33 | int fd; 34 | char buffer[1024*1024]; 35 | int bufferOffset; 36 | int bufferLength; 37 | public: 38 | BufferedFd(int fd_) : fd(fd_), bufferOffset(0), bufferLength(0) {} 39 | int read(byte *dest, int bytes) { 40 | int bytesCopied=0; 41 | do { 42 | if (bytes>bufferLength-bufferOffset) { 43 | /* Migrate all the data to the beginning of the buffer */ 44 | memcpy(&buffer[0],&buffer[bufferOffset],bufferLength-bufferOffset); 45 | bufferLength-=bufferOffset; 46 | bufferOffset=0; 47 | int ret=0; 48 | 49 | /* Read in that many bytes */ 50 | ret=::read(fd,&buffer[bufferLength],sizeof(buffer)-bufferLength); 51 | 52 | /* Deal with errors prematurely */ 53 | if (ret == -1) 54 | return -1; 55 | if (ret == 0) 56 | return 0;/* EOF */ 57 | 58 | bufferLength+=ret; 59 | } 60 | //printf("Buffer Length:%d Offset:%d Size:%d\n",bufferLength,bufferOffset,sizeof(buffer)); 61 | 62 | int todo=bytes; 63 | 64 | if (todo > bufferLength) 65 | todo = bufferLength; 66 | 67 | memcpy(dest,&buffer[bufferOffset],todo); 68 | bufferOffset+=todo; 69 | dest+=todo; 70 | bytes-=todo; 71 | bytesCopied+=todo; 72 | 73 | } while (bytes>0); 74 | //printf("bout to return bytes copied:%d\n",bytesCopied); 75 | return bytesCopied; 76 | } 77 | 78 | int write(byte *src, int bytes) { 79 | int ret; 80 | ret=::write(fd, src, bytes); 81 | return ret; 82 | } 83 | }; 84 | -------------------------------------------------------------------------------- /util/presentation/src/include/misc.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | BSOD2 Client - misc.h 3 | 4 | Basically anything weird that didn't fit got lumped into here :) 5 | *******************************************************************************/ 6 | 7 | 8 | /********************************************* 9 | Other #defines and stuff 10 | **********************************************/ 11 | #define MAX(a, b) (((a) > (b)) ? (a) : (b)) 12 | #define MIN(a, b) (((a) < (b)) ? (a) : (b)) 13 | #define ABS(a) (((a) < 0) ? -(a) : (a)) 14 | 15 | #ifndef PI 16 | #define PI 3.14159265 17 | #endif 18 | 19 | //const float infinity = std::numeric_limits::infinity(); 20 | 21 | 22 | 23 | 24 | /********************************************* 25 | Typedefs 26 | **********************************************/ 27 | typedef unsigned char byte; 28 | 29 | 30 | 31 | 32 | 33 | 34 | /********************************************* 35 | Simple Color object 36 | **********************************************/ 37 | class Color{ 38 | public: 39 | float r, g, b; 40 | 41 | Color(); 42 | Color(float _r, float _g, float _b){ 43 | r = _r; g=_g; b=_b; 44 | 45 | //hack! 46 | if(r > 1.0f || g > 1.0f || b > 1.0f){ 47 | r /= 255.0f; 48 | g /= 255.0f; 49 | b /= 255.0f; 50 | } 51 | } 52 | 53 | void copy(Color *c); 54 | 55 | float sum(){ 56 | return (r * 1) + (g * 10) + (b * 100); 57 | } 58 | 59 | //The same formatting that CEGUI uses 60 | string toString(){ 61 | byte rb = (byte)(r * 255); 62 | byte gb = (byte)(g * 255); 63 | byte bb = (byte)(b * 255); 64 | 65 | char buf[32]; 66 | sprintf(buf, "FF%s%X%s%X%s%X", rb < 0xF ? "0" : "", rb, 67 | gb < 0xF ? "0" : "", gb, 68 | bb < 0xF ? "0" : "", bb); 69 | 70 | return string(buf); 71 | } 72 | 73 | void bind(){ 74 | glColor3f(r,g,b); 75 | } 76 | 77 | 78 | }; 79 | 80 | struct ColorSort{ 81 | public: bool operator() (Color *a, Color *b){ 82 | return a->sum() > b->sum(); 83 | } 84 | }; 85 | 86 | #define glError() { \ 87 | GLenum err = glGetError(); \ 88 | while (err != GL_NO_ERROR) { \ 89 | fprintf(stderr, "glError: %s caught at %s:%u\n", (char *)gluErrorString(err), __FILE__, __LINE__); \ 90 | err = glGetError(); \ 91 | } \ 92 | } 93 | -------------------------------------------------------------------------------- /src/include/config.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | Runtime configuration 3 | *******************************************************************************/ 4 | class Config{ 5 | public: 6 | Config(string filename, string id); 7 | 8 | /******************************************************************************* 9 | Rendering output config 10 | *******************************************************************************/ 11 | 12 | //The id of this node. We look for a config file section with this name 13 | //id is set on the command line on startup 14 | string id; 15 | 16 | //Size of this renderer 17 | int sizeX; 18 | int sizeY; 19 | 20 | //Position on screen of this renderer 21 | int positionX; 22 | int positionY; 23 | 24 | //The position of this renderer inside the total screen size 25 | int offsetX; 26 | int offsetY; 27 | 28 | //for VIEWMODE_CURVE 29 | int angle; 30 | 31 | //Size of the entire viewport 32 | int totalWidth; 33 | int totalHeight; 34 | 35 | int screenWidth; 36 | int screenGap; 37 | 38 | int syncRate; 39 | bool enableStats; 40 | 41 | float scaleX; 42 | float scaleY; 43 | 44 | int clientPort; 45 | 46 | int viewMode; 47 | string viewModeString; 48 | 49 | int networkCompression; 50 | 51 | /******************************************************************************* 52 | Capture configuration 53 | *******************************************************************************/ 54 | int serverPort; 55 | 56 | string interceptMode; 57 | 58 | //Size of the client window 59 | int fakeWindowX; 60 | int fakeWindowY; 61 | 62 | //Location of renderers. Automatically calculated 63 | int numOutputs; 64 | vector outputAddresses; 65 | vector outputPorts; 66 | 67 | string capturePidFile; 68 | 69 | 70 | /******************************************************************************* 71 | Offset remote configuration 72 | *******************************************************************************/ 73 | bool remoteConfigServerEnabled; 74 | 75 | void startRemoteConfigServer(); 76 | }; 77 | 78 | /* 79 | main.h:const float SYMPHONY_SCREEN_WIDTH = 1680.0; 80 | main.h:const float SYMPHONY_SCREEN_TOTAL_WIDTH = 8880.0; 81 | main.h:const float SYMPHONY_SCREEN_TOTAL_HEIGHT = 4560.0; 82 | main.h:const float SYMPHONY_SCREEN_GAP = 120.0; 83 | */ 84 | 85 | const int VIEWMODE_VIEWPORT = 1; 86 | const int VIEWMODE_CURVE = 2; 87 | -------------------------------------------------------------------------------- /libcglinput/web/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Virtual Keyboard 6 | 7 | 8 | 9 | 10 | 11 | 12 | 17 | 18 | 19 | 22 | 23 | 24 | 25 | 26 | 27 | 45 | 46 |
47 | 48 |
49 | 50 | 51 | 52 |
53 | 54 | 55 | 56 | 58 | 59 | 60 | 61 | 62 | 76 | 77 |
78 | Made by paulh for GSOC2012, intended to be used with ClusterGL 79 |
80 | 81 | 82 | -------------------------------------------------------------------------------- /libcglinput/src/config.cpp: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | #include 3 | 4 | Config::Config(string filename){ 5 | 6 | LOG("Loading configuration from '%s'\n", filename.c_str()); 7 | 8 | cfg_t *cfg; 9 | 10 | //Output options 11 | static cfg_opt_t axis_opts[] = { 12 | CFG_INT( (char *)("id"), 0, CFGF_NONE), 13 | CFG_INT( (char *)("positive"), 0, CFGF_NONE), 14 | CFG_INT( (char *)("negative"), 0, CFGF_NONE), 15 | CFG_END() 16 | }; 17 | 18 | 19 | //Output options 20 | static cfg_opt_t button_opts[] = { 21 | CFG_INT( (char *)("id"), 0, CFGF_NONE), 22 | CFG_INT( (char *)("keycode"), 0, CFGF_NONE), 23 | CFG_END() 24 | }; 25 | 26 | //Top level options 27 | static cfg_opt_t opts[] = { 28 | CFG_INT( (char *)("thresh"), 0, CFGF_NONE), 29 | CFG_STR( (char *)("device"), 0, CFGF_NONE), 30 | CFG_SEC( (char *)"axis", axis_opts, CFGF_MULTI | CFGF_TITLE), 31 | CFG_SEC( (char *)"button", button_opts, CFGF_MULTI | CFGF_TITLE), 32 | CFG_END() 33 | }; 34 | 35 | 36 | 37 | cfg = cfg_init(opts, CFGF_NONE); 38 | 39 | int parse_result = cfg_parse(cfg, filename.c_str()); 40 | 41 | 42 | if(parse_result == CFG_FILE_ERROR){ 43 | LOG("Error with the file (does it exist?)\n"); 44 | exit(1); 45 | } 46 | 47 | if(parse_result == CFG_PARSE_ERROR){ 48 | LOG("Couldn't parse config file\n"); 49 | exit(1); 50 | } 51 | 52 | device = string(cfg_getstr(cfg, "device")); 53 | 54 | 55 | int axis_thresh = cfg_getint(cfg, "thresh"); 56 | 57 | int n = cfg_size(cfg, "axis"); 58 | num_axis = 0; 59 | 60 | for(int i=0;i= MAX_AXIS || id < 0){ 77 | LOG("Axis id %d outside of range 0-%d\n", id, MAX_AXIS); 78 | continue; 79 | } 80 | 81 | axis_actions[id][0] = pos; 82 | axis_actions[id][1] = neg; 83 | 84 | thresh[id] = axis_thresh; 85 | } 86 | 87 | 88 | n = cfg_size(cfg, "button"); 89 | 90 | for(int i=0;i= MAX_AXIS || id < 0){ 99 | LOG("Button id %d outside of range 0-%d\n", id, MAX_AXIS); 100 | continue; 101 | } 102 | 103 | axis_actions[id][0] = key; 104 | axis_actions[id][1] = key; 105 | 106 | thresh[id] = 1; 107 | } 108 | 109 | 110 | 111 | 112 | cfg_free(cfg); 113 | 114 | } 115 | -------------------------------------------------------------------------------- /src/instruction.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | ClusterGL - Instruction object utils 3 | *******************************************************************************/ 4 | 5 | #include "main.h" 6 | 7 | 8 | Instruction::Instruction() { 9 | id = 0; 10 | for(int i=0;i<3;i++) { 11 | buffers[i].buffer = NULL; 12 | buffers[i].len = 0; 13 | buffers[i].needClear = false; 14 | buffers[i].needReply = false; 15 | buffers[i].needRemoteReply = false; 16 | buffers[i].hash = 0; 17 | } 18 | 19 | memset(args, 0, MAX_ARG_LEN); 20 | } 21 | 22 | Instruction *Instruction::copy(){ 23 | Instruction *r = new Instruction(); 24 | memcpy(r, this, (sizeof(Instruction) - MAX_ARG_LEN) + arglen); 25 | for(int i=0;i<3;i++) { 26 | if(buffers[i].buffer) { 27 | r->buffers[i].buffer = (byte*) malloc(buffers[i].len); 28 | memcpy(r->buffers[i].buffer, buffers[i].buffer, buffers[i].len); 29 | } 30 | } 31 | return r; 32 | } 33 | 34 | void Instruction::clear() { 35 | //printf("Deleted\n"); 36 | arglen = 0; 37 | 38 | for(int i=0;i<3;i++) { 39 | if(buffers[i].buffer && buffers[i].needClear) { 40 | //printf("deleted (%d)\n", id); 41 | //previously delete buffers[i].buffer 42 | free(buffers[i].buffer); 43 | buffers[i].buffer = NULL; 44 | buffers[i].len = 0; 45 | buffers[i].hash = 0; 46 | } 47 | } 48 | 49 | } 50 | 51 | bool Instruction::needReply(){ 52 | for(int i=0;i<3;i++) { 53 | if(buffers[i].buffer && buffers[i].needReply){ 54 | return true; 55 | } 56 | } 57 | return false; 58 | } 59 | 60 | bool Instruction::compare(Instruction *other){ 61 | 62 | //instr id 63 | if(other->id != id){ 64 | return false; 65 | } 66 | 67 | if(other->arglen != arglen){ 68 | return false; 69 | } 70 | 71 | //argument data. 72 | if(memcmp((void *)args, (void *)other->args, arglen) != 0){ 73 | return false; 74 | } 75 | 76 | //buffers 77 | for(int i=0;i<3;i++){ 78 | 79 | //if one has a buffer and another doesn't... 80 | if(buffers[i].buffer && !other->buffers[i].buffer){ 81 | return false; 82 | } 83 | 84 | if(!buffers[i].buffer && other->buffers[i].buffer){ 85 | return false; 86 | } 87 | 88 | //if we have a buffer at all 89 | if(!buffers[i].buffer){ 90 | continue; 91 | } 92 | 93 | //if sizes of buffers are different 94 | if(buffers[i].len != other->buffers[i].len){ 95 | return false; 96 | } 97 | 98 | //finally check the memory. this is the most expensive bit 99 | if(memcmp( (void *)buffers[i].buffer, 100 | (void *)other->buffers[i].buffer, 101 | buffers[i].len) != 0){ 102 | return false; 103 | } 104 | } 105 | 106 | 107 | //the same! 108 | return true; 109 | } 110 | 111 | -------------------------------------------------------------------------------- /src/dlintercept.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | ClusterGL - dynamic library interception 3 | *******************************************************************************/ 4 | 5 | #include "main.h" 6 | 7 | #ifdef ENABLE_DL_INTERCEPT 8 | 9 | #include 10 | #include 11 | 12 | typedef unsigned char GLubyte; 13 | 14 | /* 15 | (notes on what this is and why, as it feels like something I'll forget) 16 | 17 | Many apps use glxGetProcAddress() to load function pointers manually 18 | This means they don't call our functions and so they don't get intercepted. 19 | 20 | Apps obtain the address of glXGetProcAddress() through calling 21 | dlopen("/usr/lib/libGL.so"), then dlsym("glxGetProcAddress") with that handle 22 | 23 | We intercept dlsym(), and return our own copy of glXGetProcAddress() instead. 24 | Our function uses RTLD_DEFAULT to return pointers to functions inside CGL. This 25 | specifies local scope, instead of "go look in another library" scope, so our 26 | functions are found instead of those in libGL 27 | 28 | Note we have to use dlvsym() to look up the address to dlsym() in order to 29 | handle the normal cases. TODO: is using "GLIBC_2.0" safe? Probably not. 30 | 31 | */ 32 | 33 | static void* (*o_dlsym) ( void *handle, const char *name )=0; 34 | 35 | //Try lots of different glibc versions. In my testing, only one is ever valid, 36 | //so it's okay to return the first one we find. 37 | void find_dlsym(){ 38 | 39 | char buf[32]; 40 | 41 | int maxver = 40; 42 | 43 | //Works on Ubuntu 44 | for(int a=0;a /dev/null; DISPLAY=:0 CGL_CONFIG_FILE='" +\ 33 | config.CGL_CONFIG_FILE + "' '" +\ 34 | config.CGL_LOCATION + "/runtime/cgl-render' " + hostname + "\" > /dev/null" 35 | if pid != 0: 36 | continue 37 | os.system(cmdline) 38 | 39 | #All done, bail out! 40 | os._exit(0) 41 | 42 | #let them start up... 43 | time.sleep(2) 44 | 45 | #okay, now start up the capture 46 | cmdline = "LD_PRELOAD=\"" + config.CGL_LOCATION + "/runtime/libcgl-capture.so\" " +\ 47 | "CGL_CONFIG_FILE=\"" + config.CGL_CONFIG_FILE + "\" " + args["appcmd"] + " > /dev/null" 48 | 49 | os.system(cmdline) 50 | 51 | #All done, bail out! 52 | os._exit(0) 53 | 54 | 55 | ################################################################################ 56 | # Kill all running renderers and (if possible) the last host process 57 | ################################################################################ 58 | def stop(args): 59 | 60 | global running_pid 61 | 62 | #First start up the renderers 63 | for hostname in config.CGL_RENDERERS: 64 | cmdline = "ssh \"" + hostname + "\" \"" +\ 65 | "killall cgl-render -9 2> /dev/null\"" 66 | os.system(cmdline) 67 | 68 | #Now go look for the CGL capture PID 69 | if os.path.exists(config.CGL_PID_FILE): 70 | pid = open(config.CGL_PID_FILE).read() 71 | cmdline = "kill -9 " + pid + " " 72 | print cmdline 73 | os.system(cmdline) 74 | else: 75 | print "No CGL_PID_FILE" 76 | 77 | running_pid = 0 78 | 79 | return True 80 | 81 | ################################################################################ 82 | # Return some information about the current CGL process 83 | ################################################################################ 84 | def status(args): 85 | if running_pid <= 0: 86 | return {"status":"stopped"} 87 | 88 | return {"status":"running", 89 | "pid":running_pid} 90 | 91 | -------------------------------------------------------------------------------- /libcglinput/src/xorg.cpp: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | 3 | 4 | //http://www.doctort.org/adam/nerd-notes/x11-fake-keypress-event.html 5 | //http://technofetish.net/repos/buffaloplay/xtest/keylockx.c 6 | 7 | //Requires libxcb-xtest0-dev libxtst-dev 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | // The key code to be sent. 15 | // A full list of available codes can be found in /usr/include/X11/keysymdef.h 16 | #define KEYCODE XK_Down 17 | 18 | /******************************************************************************* 19 | Xorg intercept 20 | *******************************************************************************/ 21 | static Display *(*_XOpenDisplay)(const char *) = NULL; 22 | 23 | 24 | static bool bHasInit = false; 25 | 26 | extern "C" Display *XOpenDisplay(const char *display_name){ 27 | 28 | LOG("XOpenDisplay (%d)\n", bHasInit); 29 | if (_XOpenDisplay == NULL) { 30 | _XOpenDisplay = (Display *(*)(const char *)) dlsym(RTLD_NEXT, "XOpenDisplay"); 31 | } 32 | 33 | if(!_XOpenDisplay){ 34 | LOG("Couldn't find XOpenDisplay(): %s\n", dlerror()); 35 | exit(0); 36 | } 37 | 38 | Display *r = (*_XOpenDisplay)(display_name); 39 | 40 | //Set up our internals 41 | if(!bHasInit && !mInject){ 42 | bHasInit = true; 43 | 44 | mInject = new XInject(); 45 | 46 | if(!run("xorg")){ 47 | exit(1); 48 | } 49 | }else{ 50 | LOG("Ignored a second/non-video XOpenDisplay()\n"); 51 | } 52 | 53 | return r; 54 | } 55 | 56 | 57 | 58 | 59 | // Function to create a keyboard event 60 | XKeyEvent createKeyEvent(Display *display, Window &win, 61 | Window &winRoot, bool press, 62 | int keycode, int modifiers) 63 | { 64 | XKeyEvent event; 65 | 66 | event.display = display; 67 | event.window = win; 68 | event.root = winRoot; 69 | event.subwindow = None; 70 | event.time = CurrentTime; 71 | event.x = 1; 72 | event.y = 1; 73 | event.x_root = 1; 74 | event.y_root = 1; 75 | event.same_screen = True; 76 | event.keycode = XKeysymToKeycode(display, keycode); 77 | event.state = modifiers; 78 | 79 | if(press) 80 | event.type = KeyPress; 81 | else 82 | event.type = KeyRelease; 83 | 84 | return event; 85 | } 86 | 87 | void event(int keycode, bool press){ 88 | 89 | // Obtain the X11 display. 90 | Display *display = _XOpenDisplay(0); 91 | if(display == NULL){ 92 | LOG("Couldn't XOpenDisplay(0)\n"); 93 | return; 94 | } 95 | 96 | // Get the root window for the current display. 97 | Window winRoot = XDefaultRootWindow(display); 98 | 99 | // Find the window which has the current keyboard focus. 100 | Window winFocus; 101 | int revert; 102 | XGetInputFocus(display, &winFocus, &revert); 103 | 104 | // Send a fake key press event to the window. 105 | XKeyEvent event = createKeyEvent(display, winFocus, winRoot, press, keycode, 0); 106 | //XSendEvent(event.display, event.window, True, KeyPressMask, (XEvent *)&event); 107 | XTestFakeKeyEvent(event.display, event.keycode, press, CurrentTime); 108 | 109 | // Done. 110 | XCloseDisplay(display); 111 | } 112 | 113 | void XInject::keydown(int keycode){ 114 | event(keycode, true); 115 | } 116 | 117 | void XInject::keyup(int keycode){ 118 | event(keycode, false); 119 | } 120 | 121 | 122 | -------------------------------------------------------------------------------- /util/presentation/src/include/presentation.h: -------------------------------------------------------------------------------- 1 | 2 | /******************************************************************************* 3 | transitions 4 | *******************************************************************************/ 5 | class Transition{ 6 | public: 7 | virtual bool init()=0; 8 | virtual bool render()=0; 9 | }; 10 | 11 | class HitInFace : public Transition{ 12 | 13 | float fZoom; 14 | float fZoomVel; 15 | float x; 16 | float xVel; 17 | float xTarget; 18 | public: 19 | bool init(); 20 | bool render(); 21 | }; 22 | 23 | class Collapse : public Transition{ 24 | 25 | int stage; 26 | float size; 27 | public: 28 | bool init(); 29 | bool render(); 30 | }; 31 | 32 | class Rotate : public Transition{ 33 | 34 | int stage; 35 | float size; 36 | 37 | int AX, AY, AZ; 38 | public: 39 | 40 | Rotate(int x, int y, int z); 41 | 42 | bool init(); 43 | bool render(); 44 | }; 45 | 46 | 47 | 48 | class Fade : public Transition{ 49 | 50 | int stage; 51 | float size; 52 | public: 53 | bool init(); 54 | bool render(); 55 | }; 56 | 57 | class StarWars : public Transition{ 58 | 59 | int stage; 60 | float size; 61 | public: 62 | bool init(); 63 | bool render(); 64 | }; 65 | 66 | class Tumble : public Transition{ 67 | 68 | int stage; 69 | float size; 70 | public: 71 | bool init(); 72 | bool render(); 73 | }; 74 | 75 | 76 | class Shatter : public Transition{ 77 | 78 | int stage; 79 | float size; 80 | public: 81 | bool init(); 82 | bool render(); 83 | }; 84 | 85 | 86 | class Bounce : public Transition{ 87 | 88 | int stage; 89 | float size; 90 | 91 | float top; 92 | float bottom; 93 | float topvel; 94 | float bottomvel; 95 | public: 96 | bool init(); 97 | bool render(); 98 | }; 99 | 100 | class Spin : public Transition{ 101 | 102 | int stage; 103 | float size; 104 | float vel; 105 | 106 | 107 | int AX, AY, AZ; 108 | public: 109 | 110 | Spin(int x, int y, int z); 111 | 112 | bool init(); 113 | bool render(); 114 | }; 115 | 116 | 117 | 118 | /******************************************************************************* 119 | individual slide 120 | *******************************************************************************/ 121 | class Slide{ 122 | public: 123 | Slide(); 124 | 125 | Texture *mThumb; 126 | Texture *mFull; 127 | 128 | string mFullFilename; 129 | string mThumbFilename; 130 | 131 | bool loadFull(); 132 | }; 133 | 134 | /******************************************************************************* 135 | Controls slides 136 | *******************************************************************************/ 137 | class Presentation{ 138 | public: 139 | bool init(vector files); 140 | void render(); 141 | void render2D(); 142 | void update(); 143 | void shutdown(); 144 | 145 | //controls 146 | void next(); 147 | void prev(); 148 | void start(); 149 | 150 | //slide getters 151 | Slide *getNextSlide(); 152 | Slide *getCurrentSlide(); 153 | Slide *getPrevSlide(); 154 | 155 | //transitions 156 | void doSimpleTransition(bool init); 157 | 158 | bool isTransition; 159 | bool transitionInit; 160 | 161 | vector mTransitions; 162 | Transition *mCurrentTransition; 163 | 164 | bool allowCache; 165 | bool bUseReadabilityMovement; 166 | 167 | bool toggleReadabilityMovement(); 168 | }; 169 | 170 | //hacky - these are globals so transitions can access em 171 | extern vector mSlides; 172 | extern int iCurrentSlide; 173 | 174 | 175 | -------------------------------------------------------------------------------- /src/mod_compress.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************** 2 | Headers 3 | ********************************************************/ 4 | 5 | #include "main.h" 6 | 7 | const int SEND_BUFFER_SIZE = (1024 * 1024 * 32); 8 | 9 | //big buffer to store compressed stuff in 10 | static byte mCompressBuf[SEND_BUFFER_SIZE]; 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | byte *Compression::getBuf(){ 18 | return mCompressBuf; 19 | } 20 | 21 | /********************************************************* 22 | Compress Method 23 | *********************************************************/ 24 | 25 | int Compression::compress(void *input, int nByte) 26 | { 27 | void *output = getBuf(); 28 | int compressingMethod = gConfig->networkCompression; 29 | 30 | uLongf CompBuffSize = 0; 31 | if(compressingMethod == 1) 32 | CompBuffSize = (uLongf)(nByte + (nByte * 0.1) + 12); 33 | else 34 | CompBuffSize = (uLongf)(nByte + (nByte/1024 * 16 ) + 16); 35 | 36 | unsigned char * workingMemory = NULL; 37 | if(compressingMethod == 2) 38 | workingMemory = (unsigned char*)malloc(LZO1B_MEM_COMPRESS); 39 | else if(compressingMethod == 3) 40 | workingMemory = (unsigned char*)malloc(LZO1X_1_15_MEM_COMPRESS); 41 | int ret = 0; 42 | if(nByte > 4) { 43 | int compressLevel = 1; 44 | if(compressingMethod == 1) 45 | ret = compress2((Bytef *) output, &CompBuffSize, (Bytef *) input, nByte, compressLevel); 46 | else if(compressingMethod == 2) 47 | ret = lzo1b_compress((Bytef *) input, nByte, (Bytef *) output, &CompBuffSize, workingMemory, compressLevel); 48 | else if(compressingMethod == 3) 49 | ret = lzo1x_1_15_compress((Bytef *) input, nByte, (Bytef *) output, &CompBuffSize, workingMemory); 50 | 51 | if(compressingMethod == 1) { 52 | if(ret != Z_OK) { 53 | if(ret == Z_MEM_ERROR){ 54 | LOG("ERROR compressing: memory error\n"); 55 | }else if(ret == Z_BUF_ERROR){ 56 | LOG("ERROR compressing: buffer error\n"); 57 | }else if(ret == Z_STREAM_ERROR){ 58 | LOG("ERROR compressing: compressLevel not (1-9), %d\n", compressLevel); 59 | } 60 | } 61 | } 62 | } 63 | else { 64 | memcpy(output, input, nByte); 65 | CompBuffSize = nByte; 66 | } 67 | if(compressingMethod == 2 || compressingMethod == 3) 68 | free(workingMemory); 69 | return CompBuffSize; 70 | } 71 | 72 | 73 | /********************************************************* 74 | Decompress Method 75 | *********************************************************/ 76 | int Compression::decompress(void *dest, int destLen, int sourceLen) 77 | { 78 | void *source = getBuf(); 79 | int compressingMethod = gConfig->networkCompression; 80 | 81 | uLongf newSource = sourceLen; 82 | uLongf newDest = destLen; 83 | int ret = 0; 84 | if(sourceLen > 4) { 85 | if(compressingMethod == 1) 86 | ret = uncompress((Bytef*) dest, (uLongf*) &newDest, (const Bytef*)source, newSource); 87 | else if(compressingMethod == 2) 88 | ret = lzo1b_decompress((const Bytef*)source, newSource, (Bytef*) dest, &newDest, NULL); 89 | else if(compressingMethod == 3) 90 | ret = lzo1x_decompress((const Bytef*)source, newSource, (Bytef*) dest, &newDest, NULL); 91 | 92 | if(compressingMethod == 1) { 93 | if(ret != Z_OK) { 94 | if(ret == Z_MEM_ERROR){ 95 | LOG("ERROR decompressing: memory error\n"); 96 | }else if(ret == Z_BUF_ERROR){ 97 | LOG("ERROR decompressing: buffer error\n"); 98 | }else if(ret == Z_DATA_ERROR){ 99 | LOG("ERROR decompressing: data error,\n"); 100 | } 101 | } 102 | } 103 | } 104 | else { 105 | memcpy(dest, source, sourceLen); 106 | } 107 | return (int)newDest; 108 | } 109 | -------------------------------------------------------------------------------- /libcglinput/src/spacenav.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | Space Navigator interface 3 | *******************************************************************************/ 4 | 5 | #include "main.h" 6 | 7 | ///We disable spacenav on non-linux, as we used linux-specific headers below 8 | #ifndef __linux__ 9 | 10 | bool begin_spacenav(){ 11 | LOG("No spacenav on OSX yet!\n"); 12 | return true; 13 | } 14 | 15 | #else 16 | 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | 34 | pthread_t thread; 35 | 36 | 37 | /* 38 | //write a single axis input_event 39 | void write_axis(int axid, float amount){ 40 | struct input_event ev; 41 | 42 | ev.code = axid; 43 | ev.value = amount; 44 | ev.type = EV_REL; 45 | 46 | gettimeofday(&ev.time, NULL); 47 | 48 | write(fd, &ev, sizeof(ev)); 49 | } 50 | 51 | void update_dev_file(){ 52 | write_axis(0, x); 53 | write_axis(1, y); 54 | write_axis(2, z); 55 | write_axis(3, pitch); 56 | write_axis(4, roll); 57 | write_axis(5, yaw); 58 | }*/ 59 | 60 | int read_axis(int fd, int *axis){ 61 | struct input_event ev; 62 | 63 | int r = read(fd, &ev, sizeof(ev)); 64 | 65 | if(r == 0){ 66 | *axis = -1; 67 | return 0; 68 | } 69 | 70 | //printf("%d, %d, %d\n", ev.code, ev.type, ev.value); 71 | 72 | *axis = ev.code; 73 | 74 | return ev.value; 75 | } 76 | 77 | void on_axis_down(int axis, int dir){ 78 | if(mConfig->axis_actions[axis][dir]){ 79 | LOG("AXIS ACTIVE %d %s %d\n", axis, dir ? "up" : "down", mConfig->axis_actions[axis][dir]); 80 | mInject->keydown(mConfig->axis_actions[axis][dir]); 81 | } 82 | } 83 | 84 | void on_axis_up(int axis, int dir){ 85 | if(mConfig->axis_actions[axis][dir]){ 86 | LOG("AXIS INACTIVE %d %s %d\n", axis, dir ? "up" : "down", mConfig->axis_actions[axis][dir]); 87 | mInject->keyup(mConfig->axis_actions[axis][dir]); 88 | } 89 | } 90 | 91 | void *spacenav_thread(void *data){ 92 | LOG("Input device: attemting to open %s\n", mConfig->device.c_str()); 93 | 94 | int fd = open(mConfig->device.c_str(), O_RDONLY); 95 | 96 | if(fd <= 0){ 97 | LOG("No input device found\n"); 98 | pthread_exit(NULL); 99 | } 100 | 101 | int states[MAX_AXIS]; 102 | 103 | for(int i=0;i= MAX_AXIS){ 116 | continue; 117 | } 118 | 119 | if(val > 1024){ 120 | continue; //TODO: better solution! 121 | } 122 | 123 | int thresh = mConfig->thresh[axis]; 124 | 125 | //Positive 126 | if(val >= thresh && states[axis] == 0){ 127 | states[axis] = 1; 128 | on_axis_down(axis, 0); 129 | } 130 | 131 | if(val < thresh && states[axis] == 1){ 132 | states[axis] = 0; 133 | on_axis_up(axis, 0); 134 | } 135 | 136 | 137 | //Negative 138 | if(val <= -thresh && states[axis] == 0){ 139 | states[axis] = -1; 140 | on_axis_down(axis, 1); 141 | } 142 | 143 | if(val > -thresh && states[axis] == -1){ 144 | states[axis] = 0; 145 | on_axis_up(axis, 1); 146 | } 147 | 148 | SDL_Delay(1); 149 | 150 | } 151 | 152 | } 153 | 154 | bool begin_spacenav(){ 155 | 156 | //Fire up a background thread to deal with this 157 | pthread_create(&thread, NULL, spacenav_thread, NULL); 158 | 159 | 160 | return true; 161 | } 162 | 163 | #endif 164 | -------------------------------------------------------------------------------- /libcglinput/src/web.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | Web server stuff for the touchscreen 3 | *******************************************************************************/ 4 | #include "main.h" 5 | #include "mongoose.h" 6 | 7 | static void *callback(enum mg_event event, struct mg_connection *conn); 8 | static struct mg_context *ctx; 9 | 10 | /******************************************************************************* 11 | Set up and start the embedded web server 12 | *******************************************************************************/ 13 | bool begin_web(){ 14 | 15 | //Set up the webserver for the touchscreen 16 | 17 | const char *options[] = {"listening_ports", "8080", NULL}; 18 | 19 | ctx = mg_start(&callback, NULL, options); 20 | 21 | if(!ctx){ 22 | return false; 23 | } 24 | 25 | LOG("Web server started on port 8080\n"); 26 | return true; 27 | } 28 | 29 | void end_web(){ 30 | mg_stop(ctx); 31 | 32 | LOG("Web server terminated"); 33 | } 34 | 35 | 36 | /******************************************************************************* 37 | Utility functions 38 | *******************************************************************************/ 39 | string read_file(string filepath){ 40 | FILE *f = fopen(filepath.c_str(), "r"); 41 | 42 | if(!f){ 43 | return ""; 44 | } 45 | 46 | const int len = 1024 * 100; 47 | 48 | char buf[len]; 49 | memset(buf, 0, len); 50 | fread(buf, len, 1, f); 51 | fclose(f); 52 | 53 | return string(buf); 54 | } 55 | 56 | int keycode_from_uri(string uri){ 57 | int start = uri.rfind("/")+1; 58 | string substr = uri.substr(start, uri.size()); 59 | 60 | int result; 61 | std::stringstream(substr) >> result; 62 | 63 | return result; 64 | } 65 | 66 | /******************************************************************************* 67 | Web server high-level callback 68 | *******************************************************************************/ 69 | string request(string url){ 70 | LOG("WEB: %s\n", url.c_str()); 71 | 72 | //See if it's a keyboard event request 73 | if(url.find("/kbdown/") != string::npos){ 74 | mInject->keydown(keycode_from_uri(url)); 75 | return "okay\n"; 76 | } 77 | 78 | if(url.find("/kbup/") != string::npos){ 79 | mInject->keyup(keycode_from_uri(url)); 80 | return "okay\n"; 81 | } 82 | 83 | //OK, if it's not a keyboard request, maybe it's a file request 84 | string html = read_file("web" + url); //turns into web/foo.html or whatever 85 | 86 | if(html.length() > 0){ 87 | return html; 88 | } 89 | 90 | LOG("WEB: 404 NOT FOUND %s\n", url.c_str()); 91 | 92 | //Give up! 93 | return string("404 not found: ") + url + "\n"; 94 | } 95 | 96 | string guess_content_type(string url){ 97 | if(url.find(".css") != string::npos){ 98 | return "text/css"; 99 | } 100 | 101 | if(url.find(".js") != string::npos){ 102 | return "script/javascript"; 103 | } 104 | 105 | return "text/html"; 106 | } 107 | 108 | /******************************************************************************* 109 | Web server low-level callback 110 | *******************************************************************************/ 111 | static void *callback(enum mg_event event, struct mg_connection *conn) { 112 | const struct mg_request_info *request_info = mg_get_request_info(conn); 113 | 114 | if (event == MG_NEW_REQUEST) { 115 | string content = request(string(request_info->uri)); 116 | mg_printf(conn, 117 | "HTTP/1.1 200 OK\r\n" 118 | "Content-Type: %s\r\n" 119 | "Content-Length: %d\r\n" 120 | "\r\n" 121 | "%s", 122 | guess_content_type(string(request_info->uri)).c_str(), 123 | (int)content.length(), 124 | content.c_str()); 125 | // Mark as processed 126 | return (void *)""; 127 | } else if(event == MG_EVENT_LOG) { 128 | printf("Webserver: %s\n", request_info->log_message); 129 | return NULL; 130 | } 131 | 132 | return NULL; 133 | } 134 | -------------------------------------------------------------------------------- /webcontrol/server/server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | ################################################################################ 3 | # ClusterGL webcontrol - server component 4 | # (This runs on the master CGL machine - in Symphony, DN1) 5 | # 6 | # It provides a JSON interface for configuring, launching and managing apps 7 | # running under CGL. Intended to be used by the php frontend. 8 | ################################################################################ 9 | 10 | import util.webserver 11 | import util.cglrunner 12 | import glob, imp 13 | from os.path import join, basename, splitext 14 | 15 | ################################################################################ 16 | # Some hackery to locate and load all app plugins dynamically 17 | ################################################################################ 18 | def load_apps(dir): 19 | return dict( _load(path) for path in glob.glob(join(dir,'[!_]*.py')) ) 20 | 21 | def _load(path): 22 | name, ext = splitext(basename(path)) 23 | return name, imp.load_source(name, path) 24 | 25 | app_modules = load_apps("apps") 26 | 27 | ################################################################################ 28 | # List configured apps 29 | ################################################################################ 30 | def on_list_apps(args): 31 | ret = [] 32 | for name,app in app_modules.iteritems(): 33 | a = {"name":app.name(), "descr":app.descr(), "options":app.options()} 34 | ret.append(a) 35 | return ret 36 | 37 | ################################################################################ 38 | # Details of one app 39 | ################################################################################ 40 | def on_app_details(args): 41 | for name,app in app_modules.iteritems(): 42 | if args["name"] == app.name(): 43 | a = {"name":app.name(), "descr":app.descr(), "options":app.options()} 44 | return a 45 | return {} 46 | 47 | ################################################################################ 48 | # Run CGL with a selected configuration 49 | ################################################################################ 50 | def on_run(args): 51 | 52 | #TODO: What if someone else is already running? 53 | #TODO: Validate user 54 | 55 | #First get the command line from the application and validate that 56 | app = app_modules[args["app"]] 57 | appcmd = app.on_run(args) 58 | 59 | if appcmd == None: 60 | raise Exception("Failed to configure app") 61 | 62 | args["appcmd"] = appcmd 63 | 64 | return util.cglrunner.run(args) 65 | 66 | ################################################################################ 67 | # Return the status of the running CGL (if any) 68 | ################################################################################ 69 | def on_status(args): 70 | return util.cglrunner.status(args) 71 | 72 | ################################################################################ 73 | # Kill the current CGL instance 74 | ################################################################################ 75 | def on_stop(args): 76 | return util.cglrunner.stop(args) 77 | 78 | 79 | ################################################################################ 80 | # Main web request dispatcher 81 | ################################################################################ 82 | 83 | #these are the handlers for various operations 84 | dispatcher_lookup = { 85 | "list_apps" : on_list_apps, 86 | "run": on_run, 87 | "status": on_status, 88 | "stop": on_stop, 89 | "app_details" : on_app_details, 90 | } 91 | 92 | def on_request(args): 93 | 94 | if args["op"] in dispatcher_lookup: 95 | return dispatcher_lookup[args["op"]](args) 96 | 97 | return None #will 404 98 | 99 | ################################################################################ 100 | # Entry 101 | ################################################################################ 102 | def main(): 103 | util.webserver.run(on_request) 104 | 105 | if __name__ == '__main__': 106 | main() 107 | 108 | -------------------------------------------------------------------------------- /util/presentation/src/include/vector.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | BSOD2 Client - vector.h 3 | 4 | Defines some simple 2D/3D math objects that can perform various 3D operations 5 | *******************************************************************************/ 6 | 7 | /********************************************* 8 | 3D point class 9 | **********************************************/ 10 | class Vector3{ 11 | public: 12 | float x; 13 | float y; 14 | float z; 15 | 16 | Vector3(float X,float Y,float Z){ 17 | x=X; y=Y; z=Z; 18 | } 19 | Vector3(){ 20 | x=y=z=0; 21 | } 22 | 23 | Vector3 operator+(Vector3 vVector){ 24 | return Vector3(vVector.x + x, vVector.y + y, vVector.z + z); 25 | } 26 | 27 | Vector3 operator-(Vector3 vVector){ 28 | return Vector3(x - vVector.x, y - vVector.y, z - vVector.z); 29 | } 30 | 31 | Vector3 operator*(float num){ 32 | return Vector3(x * num, y * num, z * num); 33 | } 34 | 35 | Vector3 operator/(float num){ 36 | return Vector3(x / num, y / num, z / num); 37 | } 38 | 39 | Vector3 clone(){ 40 | return Vector3(x,y,z); 41 | } 42 | 43 | float distTo(Vector3 p){ 44 | float xd = p.x - x; 45 | float yd = p.y - y; 46 | float zd = p.z - z; 47 | 48 | return sqrt(xd*xd + yd*yd + zd*zd); 49 | } 50 | 51 | float fastDistTo(Vector3 p){ 52 | float xd = p.x - x; 53 | float yd = p.y - y; 54 | float zd = p.z - z; 55 | 56 | return xd*xd + yd*yd + zd*zd; 57 | } 58 | 59 | Vector3 cross(Vector3 vVector2){ 60 | Vector3 vNormal; 61 | 62 | vNormal.x = y*vVector2.z - z*vVector2.y; 63 | vNormal.y = z*vVector2.x - x*vVector2.z; 64 | vNormal.z = x*vVector2.y - y*vVector2.x; 65 | 66 | return vNormal; 67 | } 68 | 69 | float mag(){ 70 | return (float)sqrt(x*x + y*y + z*z); 71 | } 72 | 73 | Vector3 normalized(){ 74 | return Vector3(clone() / mag()); 75 | } 76 | 77 | float dot(Vector3 p){ 78 | return x*p.x + y*p.y + z*p.z; 79 | } 80 | 81 | std::string str(){ 82 | //return "(" + toString(x) + "," + toString(y) + "," + toString(z) + ")"; 83 | return ""; 84 | } 85 | 86 | float innerProduct(Vector3 p){ 87 | return x * p.x + y * p.y + z * p.z; 88 | } 89 | 90 | }; 91 | 92 | 93 | /********************************************* 94 | 2D point class 95 | **********************************************/ 96 | class Vector2{ 97 | public: 98 | float x; 99 | float y; 100 | float z; 101 | 102 | Vector2(float X,float Y){ 103 | x=X; y=Y; 104 | } 105 | Vector2(){ 106 | x=y=0; 107 | } 108 | 109 | Vector2 operator+(Vector2 vVector){ 110 | return Vector2(vVector.x + x, vVector.y + y); 111 | } 112 | 113 | Vector2 operator-(Vector2 vVector){ 114 | return Vector2(x - vVector.x, y - vVector.y); 115 | } 116 | 117 | Vector2 operator*(float num){ 118 | return Vector2(x * num, y * num); 119 | } 120 | 121 | Vector2 operator/(float num){ 122 | return Vector2(x / num, y / num); 123 | } 124 | 125 | Vector2 clone(){ 126 | return Vector2(x,y); 127 | } 128 | 129 | float distTo(Vector2 p){ 130 | float xd = p.x - x; 131 | float yd = p.y - y; 132 | 133 | return sqrt(xd*xd + yd*yd); 134 | } 135 | 136 | float fastDistTo(Vector2 p){ 137 | float xd = p.x - x; 138 | float yd = p.y - y; 139 | 140 | return xd*xd + yd*yd; 141 | } 142 | 143 | 144 | float mag(){ 145 | return (float)sqrt(x*x + y*y); 146 | } 147 | 148 | Vector2 normalized(){ 149 | return Vector2(clone() / mag()); 150 | } 151 | 152 | float dot(Vector2 p){ 153 | return x*p.x + y*p.y; 154 | } 155 | 156 | std::string str(){ 157 | //return "(" + toString(x) + "," + toString(y) + "," + toString(z) + ")"; 158 | return ""; 159 | } 160 | 161 | }; 162 | 163 | /********************************************* 164 | Quaternion class 165 | **********************************************/ 166 | class Quaternion{ 167 | public: 168 | float w, x, y, z; 169 | 170 | Quaternion(float W, float X, float Y, float Z){ 171 | w=W; x=X; y=Y; z=Z; 172 | } 173 | 174 | Quaternion(){ 175 | x=y=z=0; 176 | w=1; //identity 177 | } 178 | }; 179 | 180 | -------------------------------------------------------------------------------- /src/mod_duplicatebuffer.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | Duplicate buffer module 3 | *******************************************************************************/ 4 | 5 | #include "main.h" 6 | 7 | #undef get16bits 8 | #if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ 9 | || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) 10 | #define get16bits(d) (*((const uint16_t *) (d))) 11 | #endif 12 | 13 | #if !defined (get16bits) 14 | #define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\ 15 | +(uint32_t)(((const uint8_t *)(d))[0]) ) 16 | #endif 17 | 18 | #define MAX_LRU 8192 19 | #define MIN_BUF_SIZE 128 20 | 21 | uint32_t hash(byte *data, int len); 22 | 23 | /******************************************************************************* 24 | Encode stage 25 | *******************************************************************************/ 26 | DuplicateBufferEncodeModule::DuplicateBufferEncodeModule(){ 27 | mLRU = new lru_cache(MAX_LRU); 28 | } 29 | 30 | 31 | bool DuplicateBufferEncodeModule::process(vector *list){ 32 | 33 | for(int n=0;n<(int)list->size();n++){ 34 | Instruction *instr = (*list)[n]; 35 | 36 | for(int i=0;i<3;i++){ 37 | InstructionBuffer *buf = &instr->buffers[i]; 38 | 39 | if(!buf->buffer || buf->needReply || buf->len < MIN_BUF_SIZE){ 40 | buf->hash = 0; 41 | continue; 42 | } 43 | 44 | int h = hash(buf->buffer, buf->len); 45 | 46 | buf->hash = h; 47 | buf->hashlen = buf->len; 48 | 49 | if(mLRU->exists(h)){ 50 | 51 | //LOG("Encoding: already had hash %d, freeing buffer (%d)\n", h, buf->len); 52 | 53 | if(buf->needClear){ 54 | free(buf->buffer); 55 | } 56 | 57 | buf->buffer = NULL; 58 | buf->len = 0; 59 | buf->needClear = false; 60 | }else{ 61 | //LOG("Encoding: adding hash %d!\n", h); 62 | mLRU->insert(h,0); //we don't need to copy the actual bytes 63 | } 64 | } 65 | } 66 | 67 | mListResult = list; 68 | 69 | //LOG("Delta: %d from %d\n", list->size() - totalSkip, list->size()); 70 | 71 | return true; 72 | } 73 | 74 | //output 75 | vector *DuplicateBufferEncodeModule::resultAsList(){ 76 | return mListResult; 77 | } 78 | 79 | 80 | 81 | 82 | 83 | /******************************************************************************* 84 | Decode stage 85 | *******************************************************************************/ 86 | DuplicateBufferDecodeModule::DuplicateBufferDecodeModule(){ 87 | mLRU = new lru_cache(MAX_LRU); 88 | } 89 | 90 | bool DuplicateBufferDecodeModule::process(vector *list){ 91 | 92 | int hitCount = 0; 93 | int missCount = 0; 94 | 95 | for(int n=0;n<(int)list->size();n++){ 96 | Instruction *instr = (*list)[n]; 97 | 98 | for(int i=0;i<3;i++){ 99 | InstructionBuffer *buf = &instr->buffers[i]; 100 | 101 | if(buf->buffer && buf->hash){ 102 | //we've got data /and/ a hash. Enter it into the LRU 103 | byte *copy = (byte *)malloc(buf->len); 104 | memcpy(copy, buf->buffer, buf->len); 105 | 106 | mLRU->insert(buf->hash,copy); 107 | 108 | missCount++; 109 | 110 | //LOG("Added %d to LRU (%d)\n", buf->hash, buf->len); 111 | continue; 112 | } 113 | 114 | else if(!buf->buffer && buf->hash){ 115 | 116 | //No data, but we have a hash. Pull the data from the LRU 117 | if(!mLRU->exists(buf->hash)){ 118 | LOG("ERROR: decode side didn't have hash %d in LRU\n", buf->hash); 119 | return false; 120 | } 121 | 122 | buf->buffer = mLRU->fetch(buf->hash); 123 | buf->len = buf->hashlen; 124 | buf->needClear = false; //we'll clean up our own mess 125 | 126 | //LOG("Read %d from LRU (%d)\n", buf->hash, buf->hashlen); 127 | hitCount++; 128 | } 129 | } 130 | } 131 | 132 | //LOG("Hit: %d, Miss: %d\n", hitCount, missCount); 133 | 134 | Stats::count("mod_duplicatebuffer hits", hitCount); 135 | Stats::count("mod_duplicatebuffer misses", missCount); 136 | 137 | mListResult = list; 138 | 139 | return true; 140 | } 141 | 142 | //output 143 | vector *DuplicateBufferDecodeModule::resultAsList(){ 144 | return mListResult; 145 | } 146 | 147 | 148 | 149 | //http://www.azillionmonkeys.com/qed/hash.html 150 | uint32_t hash(byte *data, int len){ 151 | 152 | //Makes it rather a lot faster...if you don't mind inaccuracies 153 | //if(len > 64){ 154 | // return hash(data, 32) + hash(data, len-32); 155 | //} 156 | 157 | uint32_t hash = len, tmp; 158 | int rem; 159 | 160 | if (len <= 0 || data == NULL) return 0; 161 | 162 | rem = len & 3; 163 | len >>= 2; 164 | 165 | /* Main loop */ 166 | for (;len > 0; len--) { 167 | hash += get16bits (data); 168 | tmp = (get16bits (data+2) << 11) ^ hash; 169 | hash = (hash << 16) ^ tmp; 170 | data += 2*sizeof (uint16_t); 171 | hash += hash >> 11; 172 | } 173 | 174 | /* Handle end cases */ 175 | switch (rem) { 176 | case 3: hash += get16bits (data); 177 | hash ^= hash << 16; 178 | hash ^= data[sizeof (uint16_t)] << 18; 179 | hash += hash >> 11; 180 | break; 181 | case 2: hash += get16bits (data); 182 | hash ^= hash << 11; 183 | hash += hash >> 17; 184 | break; 185 | case 1: hash += *data; 186 | hash ^= hash << 10; 187 | hash += hash >> 1; 188 | } 189 | 190 | /* Force "avalanching" of final 127 bits */ 191 | hash ^= hash << 3; 192 | hash += hash >> 5; 193 | hash ^= hash << 4; 194 | hash += hash >> 17; 195 | hash ^= hash << 25; 196 | hash += hash >> 6; 197 | 198 | return hash; 199 | } 200 | 201 | 202 | 203 | -------------------------------------------------------------------------------- /util/presentation/src/surface.cpp: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | 3 | int iScreenX, iScreenY; 4 | bool bFullscreen; 5 | 6 | void Surface::beginRender(){ 7 | glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); 8 | 9 | glViewport(0,0, iScreenX, iScreenY); 10 | 11 | glMatrixMode(GL_PROJECTION); 12 | glLoadIdentity(); 13 | 14 | float ar = (float)iScreenX / (float)iScreenY; 15 | 16 | gluPerspective(70.0f,ar,0.5f,1000.0f); 17 | 18 | glMatrixMode(GL_MODELVIEW); 19 | glLoadIdentity(); 20 | 21 | glEnable(GL_DEPTH_TEST); 22 | 23 | //Now in 3D 24 | } 25 | 26 | void Surface::begin2D(){ 27 | 28 | glMatrixMode(GL_PROJECTION); 29 | glLoadIdentity(); 30 | 31 | #ifndef ENABLE_CGL_COMPAT 32 | //Make it ortho 33 | //(0,0) == top-left 34 | 35 | glOrtho(0, iScreenX, iScreenY, 0, 0, 1); 36 | 37 | glMatrixMode(GL_MODELVIEW); 38 | glLoadIdentity(); 39 | glDisable(GL_DEPTH_TEST); 40 | 41 | //now in 2D mode 42 | #endif 43 | 44 | } 45 | 46 | void Surface::endRender(){ 47 | 48 | SDL_GL_SwapBuffers( ); 49 | } 50 | 51 | 52 | void Surface::resizeWindow( int width, int height ) 53 | { 54 | // Height / width ration 55 | GLfloat ratio; 56 | 57 | // Protect against a divide by zero 58 | if ( height == 0 ) 59 | height = 1; 60 | 61 | ratio = ( GLfloat )width / ( GLfloat )height; 62 | 63 | //Setup our viewport. 64 | glViewport( 0, 0, ( GLsizei )width, ( GLsizei )height ); 65 | 66 | //change to the projection matrix and set our viewing volume. 67 | glMatrixMode( GL_PROJECTION ); 68 | glLoadIdentity( ); 69 | 70 | //Set our perspective 71 | // gluPerspective( 45.0f, ratio, 0.1f, 100.0f ); 72 | 73 | //#ifndef ENABLE_CGL_COMPAT 74 | gluPerspective(70.0f,ratio,1.0f,10000.0f); 75 | //#endif 76 | 77 | // Make sure we're chaning the model view and not the projection 78 | glMatrixMode( GL_MODELVIEW ); 79 | 80 | //Reset The View 81 | glLoadIdentity( ); 82 | 83 | iScreenX = width; 84 | iScreenY = height; 85 | 86 | } 87 | 88 | 89 | 90 | 91 | /********************************************* 92 | Creates a window with specified attribs 93 | **********************************************/ 94 | bool Surface::init(int sizeX, int sizeY, bool fullscreen){ 95 | 96 | int bpp = 32; 97 | iScreenX = sizeX; 98 | iScreenY = sizeY; 99 | bFullscreen = fullscreen; 100 | 101 | //this holds some info about our display 102 | const SDL_VideoInfo *videoInfo; 103 | //initialize SDL 104 | if ( SDL_Init( SDL_INIT_VIDEO ) < 0 ){ 105 | LOG( "Video initialization failed: %s\n", SDL_GetError( ) ); 106 | return false; 107 | } 108 | 109 | SDL_EnableUNICODE(1); 110 | 111 | // Fetch the video info 112 | videoInfo = SDL_GetVideoInfo( ); 113 | 114 | if ( !videoInfo ){ 115 | LOG( "Video query failed: %s\n", SDL_GetError( ) ); 116 | return false; 117 | } 118 | 119 | //If the size is 0, detect the native res 120 | if(sizeX <= 0.0f){ 121 | sizeX = videoInfo->current_w; 122 | } 123 | 124 | if(sizeY <= 0.0f){ 125 | sizeY = videoInfo->current_h; 126 | } 127 | 128 | if(bpp == 0){ 129 | bpp = videoInfo->vfmt->BitsPerPixel; 130 | } 131 | 132 | //the flags to pass to SDL_SetVideoMode 133 | videoFlags = SDL_OPENGL; 134 | videoFlags |= SDL_GL_DOUBLEBUFFER; 135 | videoFlags |= SDL_HWPALETTE; 136 | 137 | //Quick hack - our resizing doesn't work properly under windows. 138 | //easier just to disable it 139 | #ifndef _WINDOWS 140 | videoFlags |= SDL_RESIZABLE; 141 | #endif 142 | 143 | //This checks to see if surfaces can be stored in memory 144 | if ( videoInfo->hw_available ) 145 | videoFlags |= SDL_HWSURFACE; 146 | else 147 | videoFlags |= SDL_SWSURFACE; 148 | 149 | // This checks if hardware blits can be done 150 | if ( videoInfo->blit_hw ) 151 | videoFlags |= SDL_HWACCEL; 152 | 153 | //Sets up OpenGL double buffering 154 | SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); 155 | 156 | // Fullscreen? 157 | if(fullscreen){ 158 | videoFlags |= SDL_FULLSCREEN; 159 | } 160 | 161 | // get a SDL surface 162 | 163 | surface = SDL_SetVideoMode( iScreenX, iScreenY, bpp, videoFlags ); 164 | 165 | // Verify there is a surface 166 | if ( !surface ){ 167 | LOG( "Video mode set failed: %s\n", SDL_GetError( ) ); 168 | //return false; 169 | } 170 | 171 | //Set the window caption 172 | SDL_WM_SetCaption( "window", NULL ); 173 | 174 | //Enable smooth shading 175 | glShadeModel( GL_SMOOTH ); 176 | 177 | //Set the background black 178 | glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); 179 | 180 | //Depth buffer setup 181 | glClearDepth( 1.0f ); 182 | 183 | //Enables Depth Testing 184 | glEnable( GL_DEPTH_TEST ); 185 | 186 | //The Type Of Depth Test To Do 187 | glDepthFunc( GL_LEQUAL ); 188 | 189 | // Really Nice Perspective Calculations 190 | glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST ); 191 | 192 | //Set up GLEW 193 | #ifndef ENABLE_CGL_COMPAT 194 | GLenum err = glewInit(); 195 | if (GLEW_OK != err){ 196 | ERR("Couldn't start GLEW: %s!\n", glewGetErrorString(err)); 197 | return false; 198 | } 199 | #endif 200 | 201 | //resize the initial window 202 | resizeWindow( sizeX, sizeY ); 203 | 204 | LOG("Made a %d/%d window @ %d bpp\n", sizeX, sizeY, bpp ); 205 | 206 | 207 | 208 | if (ilGetInteger(IL_VERSION_NUM) < IL_VERSION || 209 | iluGetInteger(ILU_VERSION_NUM) < ILU_VERSION || 210 | ilutGetInteger(ILUT_VERSION_NUM) < ILUT_VERSION) 211 | { 212 | LOG("DevIL version is different...exiting!\n"); 213 | return false; 214 | } 215 | 216 | ilInit(); 217 | ilutRenderer(ILUT_OPENGL); 218 | 219 | 220 | return true; 221 | } 222 | 223 | 224 | bool Surface::shutdown(){ 225 | return true; 226 | } 227 | 228 | 229 | void Surface::onResize(int x, int y){ 230 | 231 | //handle resize event 232 | surface = SDL_SetVideoMode( x, y, 32, videoFlags ); 233 | if ( !surface ){ 234 | ERR( "Could not get a surface after resize: %s\n", 235 | SDL_GetError( ) ); 236 | requestShutdown(); 237 | } 238 | resizeWindow( x, y ); 239 | } 240 | -------------------------------------------------------------------------------- /util/presentation/src/glutil.cpp: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | 3 | GLUtil mGLU; //global 4 | 5 | /********************************************* 6 | Draws a box in 3space 7 | **********************************************/ 8 | void GLUtil::cube(float x, float y, float z){ 9 | 10 | x/=2; y/=2; z/=2; 11 | 12 | glBegin(GL_QUADS); 13 | // Front Face 14 | glNormal3f( 0.0f, 0.0f, 1.0f); // Normal Pointing Towards Viewer 15 | glTexCoord2f(0.0f, 0.0f); glVertex3f(-x, -y, z); // Point 1 (Front) 16 | glTexCoord2f(1.0f, 0.0f); glVertex3f( x, -y, z); // Point 2 (Front) 17 | glTexCoord2f(1.0f, 1.0f); glVertex3f( x, y, z); // Point 3 (Front) 18 | glTexCoord2f(0.0f, 1.0f); glVertex3f(-x, y, z); // Point 4 (Front) 19 | // Back Face 20 | glNormal3f( 0.0f, 0.0f,-1.0f); // Normal Pointing Away From Viewer 21 | glTexCoord2f(1.0f, 0.0f); glVertex3f(-x, -y, -z); // Point 1 (Back) 22 | glTexCoord2f(1.0f, 1.0f); glVertex3f(-x, y, -z); // Point 2 (Back) 23 | glTexCoord2f(0.0f, 1.0f); glVertex3f( x, y, -z); // Point 3 (Back) 24 | glTexCoord2f(0.0f, 0.0f); glVertex3f( x, -y, -z); // Point 4 (Back) 25 | // Top Face 26 | glNormal3f( 0.0f, 1.0f, 0.0f); // Normal Pointing Up 27 | glTexCoord2f(0.0f, 1.0f); glVertex3f(-x, y, -z); // Point 1 (Top) 28 | glTexCoord2f(0.0f, 0.0f); glVertex3f(-x, y, z); // Point 2 (Top) 29 | glTexCoord2f(1.0f, 0.0f); glVertex3f( x, y, z); // Point 3 (Top) 30 | glTexCoord2f(1.0f, 1.0f); glVertex3f( x, y, -z); // Point 4 (Top) 31 | // Bottom Face 32 | glNormal3f( 0.0f,-1.0f, 0.0f); // Normal Pointing Down 33 | glTexCoord2f(1.0f, 1.0f); glVertex3f(-x, -y, -z); // Point 1 (Bottom) 34 | glTexCoord2f(0.0f, 1.0f); glVertex3f( x, -y, -z); // Point 2 (Bottom) 35 | glTexCoord2f(0.0f, 0.0f); glVertex3f( x, -y, z); // Point 3 (Bottom) 36 | glTexCoord2f(1.0f, 0.0f); glVertex3f(-x, -y, z); // Point 4 (Bottom) 37 | // Right face 38 | glNormal3f( 1.0f, 0.0f, 0.0f); // Normal Pointing Right 39 | glTexCoord2f(1.0f, 0.0f); glVertex3f( x, -y, -z); // Point 1 (Right) 40 | glTexCoord2f(1.0f, 1.0f); glVertex3f( x, y, -z); // Point 2 (Right) 41 | glTexCoord2f(0.0f, 1.0f); glVertex3f( x, y, z); // Point 3 (Right) 42 | glTexCoord2f(0.0f, 0.0f); glVertex3f( x, -y, z); // Point 4 (Right) 43 | // Left Face 44 | glNormal3f(-1.0f, 0.0f, 0.0f); // Normal Pointing Left 45 | glTexCoord2f(0.0f, 0.0f); glVertex3f(-x, -y, -z); // Point 1 (Left) 46 | glTexCoord2f(1.0f, 0.0f); glVertex3f(-x, -y, z); // Point 2 (Left) 47 | glTexCoord2f(1.0f, 1.0f); glVertex3f(-x, y, z); // Point 3 (Left) 48 | glTexCoord2f(0.0f, 1.0f); glVertex3f(-x, y, -z); // Point 4 (Left) 49 | glEnd(); 50 | } 51 | 52 | /********************************************* 53 | Turns the 2D mouse coords into a 3D 54 | intersection point of the plane 55 | **********************************************/ 56 | Vector3 GLUtil::calculateMousePoint(){ 57 | 58 | //First get the mouse point 59 | int x, y; 60 | SDL_GetMouseState(&x, &y); 61 | 62 | //Temp storage 63 | GLint viewport[4]; 64 | GLdouble modelview[16]; 65 | GLdouble projection[16]; 66 | GLfloat winX, winY, winZ; 67 | GLdouble posX, posY, posZ; 68 | 69 | //Get the various matrixes to put into gluUnProject 70 | glGetDoublev( GL_MODELVIEW_MATRIX, modelview ); 71 | glGetDoublev( GL_PROJECTION_MATRIX, projection ); 72 | glGetIntegerv( GL_VIEWPORT, viewport ); 73 | 74 | winX = (float)x; 75 | winY = (float)viewport[3] - (float)y; //GL inverts Y, so fix that 76 | 77 | //Get the depth 78 | glReadPixels( x, int(winY), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ ); 79 | 80 | //LOG("%f\n", winZ); 81 | 82 | //Unproject. This gives us the 3D point that the mouse is hovered over 83 | //Now we throw some maths at it and it will give us the intersection point 84 | gluUnProject( winX, winY, winZ, 85 | modelview, projection, viewport, 86 | &posX, &posY, &posZ ); 87 | 88 | return Vector3(posX, posY, posZ); 89 | } 90 | 91 | /********************************************* 92 | Turns a 3D point into a 2D screen pos 93 | **********************************************/ 94 | Vector2 GLUtil::utilProject(float x, float y, float z){ 95 | GLdouble pX, pY, pZ; 96 | 97 | // arrays to hold matrix information 98 | 99 | GLdouble model_view[16]; 100 | glGetDoublev(GL_MODELVIEW_MATRIX, model_view); 101 | 102 | GLdouble projection[16]; 103 | glGetDoublev(GL_PROJECTION_MATRIX, projection); 104 | 105 | GLint viewport[4]; 106 | glGetIntegerv(GL_VIEWPORT, viewport); 107 | 108 | // get 3D coordinates based on window coordinates 109 | gluProject( x, y, z, 110 | model_view, projection, viewport, 111 | &pX, &pY, &pZ); 112 | 113 | return Vector2(pX, iScreenY - pY); 114 | } 115 | 116 | /********************************************* 117 | Draws the plane 118 | **********************************************/ 119 | void GLUtil::plane(float x, float y, float z){ 120 | 121 | x/=2; y/=2; z/=2; 122 | 123 | glBegin(GL_QUADS); 124 | // Front Face 125 | glNormal3f( 0.0f, 0.0f, 1.0f); // Normal Pointing Towards Viewer 126 | glTexCoord2f(0.0f, 0.0f); glVertex3f(-x, -y, z); // Point 1 (Front) 127 | glTexCoord2f(1.0f, 0.0f); glVertex3f( x, -y, z); // Point 2 (Front) 128 | 129 | //*facepalm* 130 | #ifdef _WINDOWS 131 | glTexCoord2f(1.0f, 1.0f); glVertex3f( x, y, z); // Point 3 (Front) 132 | glTexCoord2f(0.0f, 1.0f); glVertex3f(-x, y, z); // Point 4 (Front) 133 | #else 134 | glTexCoord2f(1.0f, -1.0f); glVertex3f( x, y, z); // Point 3 (Front) 135 | glTexCoord2f(0.0f, -1.0f); glVertex3f(-x, y, z); // Point 4 (Front) 136 | #endif 137 | glEnd(); // Done Drawing Quads 138 | 139 | glDisable(GL_DEPTH_TEST); 140 | glDisable(GL_TEXTURE_2D); 141 | glColor3f(0.25f, 0.25f, 0.25f); 142 | glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 143 | 144 | glBegin(GL_QUADS); 145 | // Front Face 146 | glNormal3f( 0.0f, 0.0f, 1.0f); // Normal Pointing Towards Viewer 147 | glVertex3f(-x, -y, z); // Point 1 (Front) 148 | glVertex3f( x, -y, z); // Point 2 (Front) 149 | glVertex3f( x, y, z); // Point 3 (Front) 150 | glVertex3f(-x, y, z); // Point 4 (Front) 151 | glEnd(); // Done Drawing Quads 152 | 153 | glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 154 | glEnable(GL_DEPTH_TEST); 155 | glEnable(GL_TEXTURE_2D); 156 | 157 | 158 | } 159 | -------------------------------------------------------------------------------- /src/mod_netsrv.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************** 2 | Headers 3 | ********************************************************/ 4 | 5 | #include "main.h" 6 | 7 | const int recieveBufferSize = 268435456; 8 | //const int recieveBufferSize = sizeof(Instruction) * MAX_INSTRUCTIONS; 9 | uint32_t iRecieveBufPos = 0; 10 | uint32_t bytesRemaining = 0; 11 | 12 | int totalRead = 0; 13 | 14 | //big buffers 15 | static byte mRecieveBuf[recieveBufferSize]; 16 | static Instruction mInstructions[MAX_INSTRUCTIONS]; 17 | static int iInstructionCount = 0; 18 | 19 | /********************************************************* 20 | Net Server Module 21 | *********************************************************/ 22 | 23 | NetSrvModule::NetSrvModule() 24 | { 25 | 26 | if ((mSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 27 | LOG("Failed to create socket\n"); 28 | exit(1); 29 | } 30 | 31 | struct sockaddr_in addr, clientaddr; 32 | 33 | //Construct the server sockaddr_in structure 34 | memset(&addr, 0, sizeof(addr)); 35 | addr.sin_family = AF_INET; 36 | addr.sin_addr.s_addr = htonl(INADDR_ANY); 37 | addr.sin_port = htons(gConfig->serverPort); 38 | 39 | //set TCP options 40 | int one = 1; 41 | setsockopt(mSocket, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one)); 42 | setsockopt(mSocket, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); 43 | 44 | //Bind the server socket 45 | if (bind(mSocket, (struct sockaddr *) &addr, 46 | sizeof(addr)) < 0) { 47 | LOG("Failed to bind the server socket NetSrvModule\n"); 48 | exit(1); 49 | } 50 | //Listen 51 | if (listen(mSocket, 1) < 0) { 52 | LOG("Failed to listen on server socket\n"); 53 | exit(1); 54 | } 55 | 56 | LOG("Waiting for connection on port %d\n", gConfig->serverPort); 57 | 58 | unsigned int clientlen = sizeof(clientaddr); 59 | int client = 0; 60 | // Wait for client connection 61 | if ((client = accept(mSocket, (struct sockaddr *) &clientaddr, &clientlen)) < 0) { 62 | LOG("Failed to accept client connection\n"); 63 | exit(1); 64 | } 65 | mClientSocket = new BufferedFd(client); 66 | LOG("%s connected\n", string(inet_ntoa(clientaddr.sin_addr)).c_str() ); 67 | } 68 | 69 | 70 | /********************************************************* 71 | Net Server Process Instructions 72 | *********************************************************/ 73 | 74 | bool NetSrvModule::process(vector *list) 75 | { 76 | //Read instructions off the network and insert them into the list 77 | //First read the uint32 that tells us how many instructions we will have 78 | uint32_t num = 0; 79 | 80 | iInstructionCount = 0; 81 | 82 | int len = internalRead((byte *)&num, sizeof(uint32_t)); 83 | if(len != sizeof(uint32_t) ) { 84 | LOG("Read error\n"); 85 | return false; 86 | } 87 | 88 | //LOG("Reading %d instructions\n", num); 89 | 90 | for(uint32_t x=0;xbuffers[n].len; 121 | 122 | //LOG("%d - %d\n", n, l); 123 | 124 | if(l > 0) { 125 | i->buffers[n].buffer = (byte *) malloc(l); 126 | i->buffers[n].needClear = true; 127 | i->buffers[n].needRemoteReply = i->buffers[n].needReply; 128 | 129 | internalRead(i->buffers[n].buffer, l); 130 | } 131 | } 132 | 133 | list->push_back(i); 134 | 135 | //LOG_INSTRUCTION(i); 136 | 137 | //LOG(" \n"); 138 | } 139 | 140 | //LOG("Done\n\n"); 141 | 142 | if(totalRead == 0){ 143 | //Other side has hung up 144 | LOG("Connection dropped\n"); 145 | return false; 146 | } 147 | 148 | Stats::count("mod_netsrv read bytes", totalRead); 149 | Stats::increment("mod_netsrv read bytes", totalRead); 150 | 151 | totalRead = 0; 152 | 153 | return true; 154 | } 155 | 156 | 157 | void NetSrvModule::reply(Instruction *instr, int i) 158 | { 159 | internalWrite(instr->buffers[i].buffer, instr->buffers[i].len); 160 | } 161 | 162 | 163 | /********************************************************* 164 | Net Server Sync 165 | *********************************************************/ 166 | 167 | bool NetSrvModule::sync() 168 | { 169 | /* 170 | if(mClientSocket->read((byte *)&a, sizeof(uint32_t)) != sizeof(uint32_t)) { 171 | LOG("Connection problem NetSrvModule (didn't recv sync)!\n"); 172 | return false; 173 | } 174 | if(mClientSocket->write((byte *)&a, sizeof(uint32_t)) != sizeof(uint32_t)) { 175 | LOG("Connection problem NetSrvModule (didn't send sync)!\n"); 176 | return false; 177 | } 178 | */ 179 | 180 | return true; 181 | } 182 | 183 | 184 | /********************************************************* 185 | Net Server Run Decompression 186 | *********************************************************/ 187 | 188 | int NetSrvModule::internalRead(byte *input, int nByte) 189 | { 190 | //LOG("Read: %d (%d)\n", nByte, bytesRemaining); 191 | 192 | if(bytesRemaining <= 0){ 193 | recieveBuffer(); 194 | } 195 | 196 | memcpy(input, mRecieveBuf + iRecieveBufPos, nByte); 197 | iRecieveBufPos += nByte; 198 | bytesRemaining -= nByte; 199 | 200 | return nByte; 201 | } 202 | 203 | 204 | void NetSrvModule::recieveBuffer(void) 205 | { 206 | int compSize = 0; 207 | 208 | //first read the original number of bytes coming 209 | mClientSocket->read((byte *)&bytesRemaining, sizeof(uint32_t)); 210 | 211 | //LOG("Reading %d\n", bytesRemaining); 212 | totalRead += bytesRemaining; 213 | 214 | //then read the buffer 215 | if(gConfig->networkCompression){ 216 | int n = mClientSocket->read(Compression::getBuf(), bytesRemaining); 217 | bytesRemaining = Compression::decompress(mRecieveBuf, recieveBufferSize, n); 218 | }else{ 219 | mClientSocket->read(mRecieveBuf, bytesRemaining); 220 | } 221 | iRecieveBufPos = 0; 222 | 223 | //LOG("bytesRemaining = %d\n", bytesRemaining); 224 | 225 | totalRead += sizeof(uint32_t); 226 | 227 | //LOG("read ok\n"); 228 | } 229 | 230 | 231 | /********************************************************* 232 | Net Server Run Compression 233 | *********************************************************/ 234 | 235 | int NetSrvModule::internalWrite(byte *input, int nByte) 236 | { 237 | //LOG("internalWrite %d\n", nByte); 238 | int ret = mClientSocket->write(input, nByte); 239 | //LOG("done!\n"); 240 | return ret; 241 | } 242 | -------------------------------------------------------------------------------- /src/mod_netclient.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | Network client module 3 | *******************************************************************************/ 4 | 5 | #include "main.h" 6 | 7 | 8 | const int SEND_BUFFER_SIZE = 268435456;//1294276 9 | 10 | uint32_t iSendBufPos = 0; 11 | uint32_t bytesLeft = SEND_BUFFER_SIZE; 12 | 13 | //big buffer to store instructions before sending 14 | byte mSendBuf[SEND_BUFFER_SIZE]; 15 | 16 | int totalSent; 17 | 18 | /******************************************************************************* 19 | Network client module connect / setup 20 | *******************************************************************************/ 21 | NetClientModule::NetClientModule() 22 | { 23 | //Make each socket 24 | for(int i=0;inumOutputs;i++){ 25 | struct addrinfo hints, *res; 26 | 27 | memset(&hints, 0, sizeof hints); 28 | hints.ai_family = AF_UNSPEC; 29 | hints.ai_socktype = SOCK_STREAM; 30 | 31 | string addr = gConfig->outputAddresses[i]; 32 | int port = gConfig->outputPorts[i]; 33 | 34 | getaddrinfo(addr.c_str(), toString(port).c_str(), &hints, &res); 35 | 36 | int s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 37 | 38 | if(s == 0){ 39 | LOG("Couldn't make socket!\n"); 40 | return; 41 | } 42 | 43 | //set TCP options 44 | int one = 1; 45 | 46 | setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one)); 47 | setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); 48 | 49 | struct sockaddr_in mAddr; 50 | 51 | int c = connect(s, res->ai_addr, res->ai_addrlen); 52 | 53 | if(c < 0) { 54 | LOG("Failed to connect with server '%s:%d' - error %s\n", 55 | addr.c_str(), port, strerror( errno )); 56 | exit(1); 57 | } 58 | LOG("Connected to remote pipeline on %s:%d\n", addr.c_str(), port); 59 | 60 | mSockets.push_back(s); 61 | } 62 | 63 | } 64 | 65 | 66 | 67 | /******************************************************************************* 68 | Send each instruction 69 | *******************************************************************************/ 70 | bool NetClientModule::process(vector *list) 71 | { 72 | 73 | //First send the total number 74 | uint32_t num = list->size(); 75 | 76 | if(!internalWrite(&num, sizeof(uint32_t))) { 77 | LOG("Connection problem!\n"); 78 | return false; 79 | } 80 | 81 | //Now send the instructions 82 | int counter = 0; 83 | for(int n=0;n<(int)list->size();n++){ 84 | 85 | Instruction *i = (*list)[n]; 86 | 87 | //Check for NULL buffers and reset length if necessary 88 | for(int n=0;n<3;n++) { 89 | int l = i->buffers[n].len; 90 | 91 | if(l > 0 && !i->buffers[n].buffer) { 92 | i->buffers[n].len = 0; 93 | } 94 | } 95 | 96 | /* 97 | byte len = (sizeof(Instruction) - MAX_ARG_LEN) + i->arglen; 98 | 99 | // now send the new instruction 100 | //first the length byte 101 | if(internalWrite(&len, 1) != 1) { 102 | LOG("Connection problem (didn't send instruction)!\n"); 103 | } 104 | 105 | //now the struct itself 106 | if(internalWrite(i, len) != len) { 107 | LOG("Connection problem (didn't send instruction)!\n"); 108 | return false; 109 | } 110 | */ 111 | //now the struct itself 112 | if(internalWrite(i, sizeof(Instruction)) != sizeof(Instruction)) { 113 | LOG("Connection problem (didn't send instruction)!\n"); 114 | return false; 115 | } 116 | 117 | //Now see if we need to send any buffers 118 | for(int n=0;n<3;n++) { 119 | int l = i->buffers[n].len; 120 | 121 | if(l > 0) { 122 | 123 | if(internalWrite(i->buffers[n].buffer, l) != l) { 124 | LOG("Connection problem (didn't write buffer %d)!\n", l); 125 | return false; 126 | } 127 | //And check if we're expecting a buffer back in response 128 | if(i->buffers[n].needReply) { 129 | 130 | sendBuffer(); 131 | if(int x = internalRead(i->buffers[n].buffer, l) != l) { 132 | LOG("Connection problem: NetClient (didn't recv buffer %d got: %d)!\n", l, x); 133 | return false; 134 | } 135 | //LOG("got buffer back!\n"); 136 | } 137 | } 138 | } 139 | counter++; 140 | } 141 | 142 | sendBuffer(); //send anything that's outstanding 143 | 144 | Stats::count("mod_netclient write", totalSent); 145 | totalSent = 0; 146 | 147 | return true; 148 | } 149 | 150 | 151 | 152 | /******************************************************************************* 153 | Sync 154 | *******************************************************************************/ 155 | bool NetClientModule::sync() 156 | { 157 | LOG("NetClientModule::sync() requested, but not implemented\n"); 158 | 159 | return true; 160 | } 161 | 162 | 163 | 164 | 165 | /******************************************************************************* 166 | Write to the network 167 | *******************************************************************************/ 168 | int NetClientModule::internalWrite(void* buf, int nByte) 169 | { 170 | if(bytesLeft - nByte > 0) { 171 | memcpy(mSendBuf + iSendBufPos, buf, nByte); 172 | iSendBufPos += nByte; 173 | bytesLeft -= nByte; 174 | } 175 | else { 176 | sendBuffer(); 177 | } 178 | return nByte; 179 | } 180 | 181 | void NetClientModule::sendBuffer() 182 | { 183 | if(iSendBufPos == 0){ 184 | return; 185 | } 186 | 187 | byte *mCompressedBuf = NULL; 188 | 189 | if(gConfig->networkCompression){ 190 | mCompressedBuf = Compression::getBuf(); 191 | iSendBufPos = Compression::compress(mSendBuf, iSendBufPos); 192 | } 193 | 194 | //LOG("NetClientModule::sendBuffer(%d)\n", iSendBufPos); 195 | for(int i=0;i<(int)mSockets.size();i++){ 196 | uint32_t a = write(mSockets[i], &iSendBufPos, sizeof(iSendBufPos)); 197 | uint32_t b = 0; 198 | if(!gConfig->networkCompression){ 199 | b = write(mSockets[i], mSendBuf, iSendBufPos); 200 | }else{ 201 | b = write(mSockets[i], mCompressedBuf, iSendBufPos); 202 | } 203 | if(a != sizeof(iSendBufPos) && b != iSendBufPos){ 204 | LOG("Failure to send: %d/%d\n", i, iSendBufPos); 205 | } 206 | totalSent += a; 207 | totalSent += b; 208 | } 209 | //LOG("sent ok\n"); 210 | iSendBufPos = 0; 211 | bytesLeft = SEND_BUFFER_SIZE; 212 | 213 | } 214 | 215 | 216 | 217 | /******************************************************************************* 218 | Read from the network 219 | *******************************************************************************/ 220 | int NetClientModule::internalRead(void *buf, size_t count) 221 | { 222 | //LOG("About to read %d\n", count); 223 | uint32_t n = 0; 224 | //Read from each renderer 225 | for(int i=0;i<(int)mSockets.size();i++){ 226 | n = 0; 227 | byte *d = (byte *)buf; 228 | while(n < count){ 229 | n += read(mSockets[i], d + n, count); 230 | //LOG("%d\n", n); 231 | } 232 | } 233 | //LOG("done\n"); 234 | return n; 235 | } 236 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | ClusterGL - main.cpp 3 | *******************************************************************************/ 4 | #include "main.h" 5 | 6 | 7 | /******************************************************************************* 8 | Globals 9 | *******************************************************************************/ 10 | static bool bHasInit = false; 11 | bool bIsIntercept = false; 12 | 13 | Config *gConfig = NULL; 14 | 15 | /******************************************************************************* 16 | Entry if invoked as a renderer output 17 | *******************************************************************************/ 18 | int App::run(int argc, char **argv) 19 | { 20 | if (argc != 2) { 21 | fprintf(stderr,"usage: %s \n", argv[0]); 22 | exit(0); 23 | } 24 | 25 | if(bHasInit) { 26 | return 1; 27 | } 28 | 29 | init(false, argv[1]); 30 | 31 | //Set up the module chain 32 | mModules.push_back(new NetSrvModule()); 33 | mModules.push_back(new DeltaDecodeModule()); 34 | //mModules.push_back(new DuplicateBufferDecodeModule()); 35 | mModules.push_back(new ExecModule()); 36 | 37 | while( tick() ){ 38 | //run tick() until we decide to bail 39 | } 40 | 41 | return 0; 42 | } 43 | 44 | 45 | /******************************************************************************* 46 | Entry if invoked as capture (shared library) 47 | *******************************************************************************/ 48 | bool App::run_shared(string src) 49 | { 50 | //This is needed to ensure that multiple calls to SDL_Init() don't cause 51 | //us to do the wrong thing. 52 | if(bHasInit) { 53 | return false; 54 | } 55 | 56 | //Load the config file 57 | init(true, "capture"); 58 | 59 | //Make sure we're launching from the correct source. This means that mixing 60 | //SDL and Xorg works properly when we're fork()'ing. ie: OpenArena 61 | if(src != gConfig->interceptMode){ 62 | LOG("Ignored spurious launch (possibly fork()?): %s vs %s\n", 63 | src.c_str(), gConfig->interceptMode.c_str()); 64 | LOG("If this is intended, change 'interceptMode' to '%s' in the config file\n", src.c_str()); 65 | return false; 66 | } 67 | 68 | for(int i=0;inumOutputs;i++){ 69 | LOG("Found output: %s:%d\n", 70 | gConfig->outputAddresses[i].c_str(), 71 | gConfig->outputPorts[i]); 72 | } 73 | 74 | //Write our pid out 75 | if(gConfig->capturePidFile != ""){ 76 | FILE *f = fopen(gConfig->capturePidFile.c_str(), "w"); 77 | char pid[64]; 78 | sprintf(pid, "%d", getpid()); 79 | fwrite(pid, strlen(pid), 1, f); 80 | fclose(f); 81 | } 82 | 83 | 84 | //Set up the module chain 85 | mModules.push_back(new AppModule("")); 86 | mModules.push_back(new DeltaEncodeModule()); 87 | //mModules.push_back(new DuplicateBufferEncodeModule()); 88 | mModules.push_back(new NetClientModule()); 89 | 90 | //Return control to the parent process. 91 | return true; 92 | } 93 | 94 | /******************************************************************************* 95 | Load the config file, init various internal variables 96 | *******************************************************************************/ 97 | void App::init(bool shared, const char *id) 98 | { 99 | printf("**********************************************\n"); 100 | printf(" ClusterGL(%s - %s)\n", bIsIntercept ? "intercept" : "renderer", id); 101 | printf("**********************************************\n"); 102 | 103 | bIsIntercept = shared; 104 | 105 | char *configFile = (char *)"/etc/cgl.conf"; 106 | 107 | if(getenv("CGL_CONFIG_FILE")){ 108 | configFile = getenv("CGL_CONFIG_FILE"); 109 | } 110 | 111 | gConfig = new Config(configFile, string(id ? id : "null")); 112 | 113 | bHasInit = true; 114 | } 115 | 116 | 117 | /******************************************************************************* 118 | Main loop 119 | *******************************************************************************/ 120 | bool App::tick() 121 | { 122 | //LOG("tick()\n"); 123 | 124 | vector *thisFrame = new vector(); 125 | 126 | if(gConfig->enableStats){ 127 | stats_begin(); 128 | } 129 | 130 | //Go through each module and process the frame 131 | for(int i=0;i<(int)mModules.size();i++) { 132 | Module *m = mModules[i]; 133 | 134 | m->setListResult(thisFrame); 135 | 136 | if( !m->process(thisFrame) ) { 137 | LOG("Failed to process frame (in %d), bailing out\n", i); 138 | return false; 139 | } 140 | 141 | //TODO: handle bytes and such 142 | thisFrame = m->resultAsList(); 143 | 144 | if(!thisFrame){ 145 | LOG("!thisFrame\n"); 146 | return false; 147 | } 148 | } 149 | 150 | //return appropriate frames 151 | for(int n=0;n<(int)thisFrame->size();n++){ 152 | Instruction *iter = (*thisFrame)[n]; 153 | for(int i=0;i<3;i++) { 154 | //If we need a reply, send it 155 | //But only do so if /we/ created the instruction 156 | if(iter->buffers[i].needReply && iter->buffers[i].needRemoteReply) { 157 | //LOG("need a reply %d\n", i); 158 | //LOG_INSTRUCTION(iter); 159 | mModules[0]->reply(iter, i); 160 | 161 | iter->buffers[i].needReply = false; 162 | 163 | Stats::increment("Pipeline stalls due to replies"); 164 | } 165 | } 166 | } 167 | 168 | 169 | if(gConfig->enableStats){ 170 | stats_end(); 171 | } 172 | 173 | for(int i=0;i<(int)thisFrame->size();i++){ 174 | bool mustdelete = false; 175 | Instruction *iter = (*thisFrame)[i]; 176 | if(iter->id==CGL_REPEAT_INSTRUCTION) 177 | mustdelete = true; 178 | //LOG_INSTRUCTION(iter); 179 | iter->clear(); 180 | 181 | // this has to be deleted on renderers only 182 | // because they dynamically copy instructions in DeltaDecodeModule 183 | if(!bIsIntercept || mustdelete) 184 | delete iter; 185 | } 186 | thisFrame->clear(); 187 | 188 | delete thisFrame; 189 | 190 | //LOG("tick() done\n"); 191 | 192 | return true; 193 | } 194 | 195 | /******************************************************************************* 196 | Begin stats run 197 | *******************************************************************************/ 198 | void App::stats_begin(){ 199 | 200 | } 201 | 202 | /******************************************************************************* 203 | End stats run 204 | *******************************************************************************/ 205 | void App::stats_end(){ 206 | Stats::update(); 207 | } 208 | 209 | 210 | /******************************************************************************* 211 | main() 212 | *******************************************************************************/ 213 | App *theApp = NULL; 214 | 215 | int main( int argc, char **argv ) 216 | { 217 | theApp = new App(); 218 | int ret = theApp->run(argc, argv); 219 | delete theApp; 220 | return ret; 221 | } 222 | 223 | //The shared object entry is now in mod_app 224 | -------------------------------------------------------------------------------- /src/lru_cache.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2004-2011 by Patrick Audley * 3 | * paudley@blackcat.ca * 4 | * http://patrickaudley.com * 5 | * * 6 | ***************************************************************************/ 7 | /** 8 | * @file lru_cache.cpp Template cache with an LRU removal policy (unit tests) 9 | * @author Patrick Audley 10 | */ 11 | #include "lru_cache.h" 12 | 13 | #ifdef UNITTEST 14 | #include "unit_test.h" 15 | #include 16 | #include 17 | 18 | /// LRUCache type for use in the unit tests 19 | typedef LRUCache unit_lru_type; 20 | /// LRUCache POD type for use in the unit tests 21 | typedef LRUCache unit_lru_type2; 22 | /// Data class for testing the scoping issues with const refs 23 | class test_big_data { 24 | public: 25 | char buffer[1000]; 26 | }; 27 | /// LRUCache with large data for use in the unit tests 28 | typedef LRUCache unit_lru_type3; 29 | 30 | /// Dumps the cache for debugging. 31 | std::string dump( unit_lru_type *L ) { 32 | unit_lru_type::Key_List _list( L->get_all_keys() ); 33 | std::string ret(""); 34 | for( unit_lru_type::Key_List_Iter liter = _list.begin(); liter != _list.end(); liter++ ) { 35 | ret.append( *liter ); 36 | ret.append( ":" ); 37 | ret.append( L->fetch( *liter, false ) ); 38 | ret.append( "\n" ); 39 | } 40 | //std::cout << "Dump--" << std::endl << ret << "----" << std::endl; 41 | return ret; 42 | } 43 | 44 | /// Scoping test object 45 | unit_lru_type3* L3; 46 | 47 | UNIT_TEST_DEFINES 48 | 49 | /** @test Basic creation and desctruction test */ 50 | DEFINE_TEST( lru_cache_1cycle ) { 51 | const std::string unit_data_1cycle_a("foo:4\n"); 52 | const std::string unit_data_1cycle_b("bar:flower\nfoo:4\n"); 53 | const std::string unit_data_1cycle_c("foo:4\nbar:flower\n"); 54 | const std::string unit_data_1cycle_d("foo:moose\nbaz:Stalin\nbar:flower\n"); 55 | const std::string unit_data_1cycle_e("foo:moose\nbar:flower\n"); 56 | const std::string unit_data_1cycle_f("quz:xyzzy\nbaz:monkey\nfoo:moose\n"); 57 | const std::string unit_data_1cycle_g("coat:mouse\npants:cat\nsocks:bear\n"); 58 | 59 | unit_lru_type *L = new unit_lru_type(3); 60 | unit_assert( "size==0", (L->size() == 0) ); 61 | unit_assert( "maxsize==3", (L->max_size() == 3) ); 62 | 63 | // Checking a bogus key shouldn't alter the cache. 64 | L->exists( "foo" ); 65 | unit_assert( "exists() doesn't increase size", (L->size() == 0) ); 66 | 67 | // Check insert() and exists() 68 | L->insert( "foo", "4" ); 69 | unit_assert( "size==1 after insert(foo,4)", (L->size() == 1) ); 70 | unit_assert( "check exists(foo)", L->exists( "foo" ) ); 71 | unit_assert( "contents check a)", unit_data_1cycle_a.compare( dump( L ) ) == 0 ); 72 | 73 | // Check second insert and ordering 74 | L->insert( "bar", "flower" ); 75 | unit_assert( "size==2 after insert(bar,flower)", (L->size() == 2) ); 76 | unit_assert( "contents check b)", unit_data_1cycle_b.compare( dump( L ) ) == 0 ); 77 | 78 | // Check touching 79 | L->touch( "foo" ); 80 | unit_assert( "contents check c)", unit_data_1cycle_c.compare( dump( L ) ) == 0 ); 81 | 82 | // Insert of an existing element should result in only a touch 83 | L->insert( "bar", "flower" ); 84 | unit_assert( "verify insert touches", unit_data_1cycle_b.compare( dump( L ) ) == 0 ); 85 | 86 | // Verify that fetch works 87 | unit_assert( "verify fetch(bar)", ( std::string("flower").compare( L->fetch("bar") ) == 0 ) ); 88 | 89 | // Insert of an existing element with new data should replace and touch 90 | L->insert( "baz", "Stalin" ); 91 | L->insert( "foo", "moose" ); 92 | unit_assert( "verify insert replaces", unit_data_1cycle_d.compare( dump( L ) ) == 0 ); 93 | 94 | // Test removal of an existing member. 95 | L->remove( "baz" ); 96 | unit_assert( "verify remove works", unit_data_1cycle_e.compare( dump( L ) ) == 0 ); 97 | 98 | // Test LRU removal as we add more members than max_size() 99 | L->insert( "baz", "monkey" ); 100 | L->insert( "quz", "xyzzy" ); 101 | unit_assert( "verify LRU semantics", unit_data_1cycle_f.compare( dump( L ) ) == 0 ); 102 | 103 | // Stress test the implementation a little.. 104 | const char *names[10] = { "moose", "dog", "bear", "cat", "mouse", "hat", "mittens", "socks", "pants", "coat" }; 105 | for( int i = 0; i < 50; i++ ) { 106 | L->insert( names[ i % 10 ], names[ i % 9 ] ); 107 | } 108 | unit_assert( "stress test a little", unit_data_1cycle_g.compare( dump( L ) ) == 0 ); 109 | 110 | // Setup a little for the third test which verifies that scoped references inserted into the cache don't disappear. 111 | L3 = new unit_lru_type3(2); 112 | for( int i = 0; i < 10; i++ ) { 113 | test_big_data B; 114 | snprintf( B.buffer, 1000, "%d\n", i ); 115 | L3->insert( i, B ); 116 | } 117 | 118 | unit_pass(); 119 | } 120 | 121 | #define TRANSACTIONS 50000 122 | /** @test Insert lots of objects and benchmark the rate. */ 123 | DEFINE_TEST( lru_cache_stress ) { 124 | // Stress test the implementation a little more using no objects 125 | unit_lru_type2 *L2 = new unit_lru_type2(5); 126 | double t0 = cputime(); 127 | for( int i = 0; i < TRANSACTIONS; i++ ) { 128 | L2->insert( i, i-1 ); 129 | } 130 | double t1 = cputime(); 131 | delete L2; 132 | print_cputime( "(int,int) inserts", t1-t0, TRANSACTIONS ); 133 | unit_pass(); 134 | } 135 | 136 | /** @test Check that objects inserted in a different scope are still there. */ 137 | DEFINE_TEST( lru_cache_scope_check ) { 138 | test_big_data* B = L3->fetch_ptr( 9 ); 139 | unit_assert( "scope check element L3[1]", ( strncmp( B->buffer, "9\n", 1000 ) == 0 ) ); 140 | B = L3->fetch_ptr( 8 ); 141 | unit_assert( "scope check element L3[2]", ( strncmp( B->buffer, "8\n", 1000 ) == 0 ) ); 142 | delete L3; 143 | unit_pass(); 144 | } 145 | 146 | #ifdef _REENTRANT 147 | #include 148 | 149 | #define THREAD_TRANS 20000 150 | #define THREAD_COUNT 10 151 | 152 | unit_lru_type2 *L4; 153 | 154 | void insert_junk(){ 155 | for( int i = 0; i < THREAD_TRANS; i++ ) { 156 | L4->insert( i, i+1 ); 157 | L4->remove( i-5 ); 158 | L4->fetch( i-3 ); 159 | L4->touch( i-10 ); 160 | } 161 | } 162 | 163 | /** @test Check for badness with multithreaded access, this is more of a stress test than an empirical test. */ 164 | DEFINE_TEST( lru_cache_threads ) { 165 | L4 = new unit_lru_type2( 20 ); 166 | boost::thread_group thrds; 167 | double t0 = cputime(); 168 | for (int i=0; i < THREAD_COUNT; ++i) 169 | thrds.create_thread(&insert_junk); 170 | thrds.join_all(); 171 | double t1 = cputime(); 172 | print_cputime( "(int,int) multithreaded inserts", t1-t0, THREAD_TRANS*THREAD_COUNT*4 ); 173 | delete L4; 174 | unit_pass(); 175 | } 176 | 177 | #endif 178 | 179 | UNIT_TEST_RUN( "LRU Cache" ); 180 | ADD_TEST( lru_cache_1cycle ); 181 | ADD_TEST( lru_cache_stress ); 182 | ADD_TEST( lru_cache_scope_check ); 183 | #ifdef _REENTRANT 184 | ADD_TEST( lru_cache_threads ); 185 | #endif 186 | UNIT_TEST_END; 187 | 188 | #endif 189 | -------------------------------------------------------------------------------- /util/presentation/src/presentation.cpp: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | 3 | 4 | vector mSlides; 5 | int iCurrentSlide; 6 | 7 | char *textFileRead(const char *filename) 8 | { 9 | FILE *fp; 10 | char *content = NULL; 11 | 12 | int count=0; 13 | 14 | if (filename != NULL) { 15 | 16 | fp = fopen(filename,"rt"); 17 | 18 | if (fp != NULL) { 19 | 20 | fseek(fp, 0, SEEK_END); 21 | count = ftell(fp); 22 | rewind(fp); 23 | 24 | if (count > 0) { 25 | content = (char *)malloc(sizeof(char) * (count+1)); 26 | count = fread(content,sizeof(char),count,fp); 27 | content[count] = '\0'; 28 | } 29 | fclose(fp); 30 | 31 | } 32 | } 33 | 34 | return content; 35 | } 36 | 37 | 38 | bool presentationFinished = false; 39 | 40 | bool Presentation::init(vector files){ 41 | 42 | srand((unsigned int)time(0)); 43 | 44 | LOG("Starting presentation init\n"); 45 | 46 | mSlides.clear(); 47 | 48 | for(int i=0;i<(int)files.size();i++){ 49 | 50 | //LOG("loading '%s'\n", files[i].c_str()); 51 | 52 | string thumbFile = files[i]; 53 | 54 | //thumbnail is in a 'thumbs' directory 55 | //man, c++ is annoying to do this in 56 | unsigned int r = thumbFile.rfind("/"); 57 | if(r == string::npos){ r = 2; thumbFile = "./" + thumbFile; } 58 | thumbFile.replace(r, 1, "/thumbs/"); 59 | 60 | //LOG("thumb: %s, %s\n", files[i].c_str(), thumbFile.c_str()); 61 | 62 | Texture *thumb = new Texture(thumbFile); 63 | 64 | if(thumb->isLoaded()){ 65 | 66 | Slide *s = new Slide(); 67 | s->mThumb = thumb; 68 | s->mFull = NULL; 69 | s->mFullFilename = files[i]; 70 | s->mThumbFilename = thumbFile; 71 | 72 | mSlides.push_back(s); 73 | LOG("Loaded thumb '%s'\n", thumbFile.c_str()); 74 | }else{ 75 | ERR("Failed to load slide '%s'\n", thumbFile.c_str()); 76 | delete thumb; 77 | return false; 78 | } 79 | 80 | } 81 | 82 | LOG("Done presentation init (%d slides)\n", (int)mSlides.size()); 83 | 84 | iCurrentSlide = 0; 85 | isTransition = false; 86 | bUseReadabilityMovement = false; 87 | 88 | mTransitions.clear(); 89 | 90 | //set up transitions 91 | 92 | 93 | mTransitions.push_back(new HitInFace()); 94 | mTransitions.push_back(new Collapse()); 95 | mTransitions.push_back(new Rotate(1, 0, 0)); 96 | mTransitions.push_back(new Rotate(0, 1, 0)); 97 | mTransitions.push_back(new Rotate(1, 0, 1)); 98 | mTransitions.push_back(new Fade()); 99 | mTransitions.push_back(new Tumble()); 100 | mTransitions.push_back(new Bounce()); 101 | mTransitions.push_back(new Bounce()); 102 | mTransitions.push_back(new StarWars()); 103 | mTransitions.push_back(new Spin(1,0,0)); 104 | mTransitions.push_back(new Spin(0,0,1)); 105 | mTransitions.push_back(new Spin(0,1,0)); 106 | mTransitions.push_back(new Spin(1,1,0)); 107 | mTransitions.push_back(new Spin(1,1,1)); 108 | 109 | 110 | 111 | 112 | 113 | //mTransitions.push_back(new Shatter()); 114 | 115 | 116 | 117 | return true; 118 | } 119 | 120 | Slide *Presentation::getNextSlide(){ 121 | if((iCurrentSlide + 1) < (int)mSlides.size()){ 122 | return mSlides[iCurrentSlide + 1]; 123 | }else{ 124 | return NULL; 125 | } 126 | } 127 | 128 | Slide *Presentation::getCurrentSlide(){ 129 | return mSlides[iCurrentSlide]; 130 | } 131 | 132 | Slide *Presentation::getPrevSlide(){ 133 | if((iCurrentSlide - 1) >= 0){ 134 | return mSlides[iCurrentSlide - 1]; 135 | }else{ 136 | return NULL; 137 | } 138 | } 139 | 140 | void Presentation::render2D(){ 141 | if(isTransition){ 142 | 143 | }else{ 144 | 145 | Slide *s = getCurrentSlide(); 146 | Slide *n = getNextSlide(); 147 | Slide *p = getPrevSlide(); 148 | 149 | 150 | bool didLoad = false; 151 | 152 | if(!s->mFull || !s->mFull->isLoaded()){ 153 | LOG("need to load %d\n", iCurrentSlide); 154 | if(!s->loadFull()){ 155 | LOG("Failed to load full texture!\n"); 156 | return; 157 | } 158 | didLoad = true; 159 | } 160 | 161 | /* 162 | if(p && p->mFull && p->mFull->isLoaded()){ 163 | p->mFull->destroy(); 164 | } 165 | */ 166 | 167 | if(allowCache && !didLoad){ 168 | 169 | if(n && (!n->mFull || !n->mFull->isLoaded())){ 170 | LOG("caching %d\n", iCurrentSlide + 1); 171 | if(!n->loadFull()){ 172 | LOG("Failed to load full texture!\n"); 173 | return; 174 | } 175 | } 176 | 177 | allowCache = false; 178 | didLoad = true; 179 | 180 | if(p && p->mFull && p->mFull->isLoaded()){ 181 | p->mFull->destroy(); 182 | } 183 | } 184 | 185 | 186 | 187 | s->mFull->bind(); 188 | 189 | float x = 0; 190 | float y = 0; 191 | float w = 1024;//888 192 | float h = 768;//456 193 | 194 | if(bUseReadabilityMovement){ 195 | static float move = 0.0f; 196 | move += 0.01f; 197 | 198 | float scale = 1.0f; 199 | 200 | glTranslatef(sinf(move) * scale, cosf(move) * scale, 0); 201 | 202 | x -= scale; 203 | y -= scale; 204 | w += scale; 205 | h += scale; 206 | } 207 | 208 | glBegin(GL_QUADS); 209 | // Front Face 210 | glTexCoord2f(0.0f, 0.0f); glVertex2f(x, y); // Point 1 (Front) 211 | glTexCoord2f(1.0f, 0.0f); glVertex2f(w, y); // Point 2 (Front) 212 | glTexCoord2f(1.0f, -1.0f); glVertex2f(w, h); // Point 3 (Front) 213 | glTexCoord2f(0.0f, -1.0f); glVertex2f(x, h); // Point 4 (Front) 214 | glEnd(); 215 | 216 | allowCache = true; 217 | } 218 | } 219 | 220 | void Presentation::render(){ 221 | 222 | if(isTransition){ 223 | if(transitionInit){ 224 | mCurrentTransition->init(); 225 | } 226 | transitionInit = false; 227 | 228 | isTransition = mCurrentTransition->render(); 229 | 230 | if(!isTransition){ 231 | allowCache = false; 232 | } 233 | }else{ 234 | 235 | } 236 | } 237 | 238 | void Presentation::update(){ 239 | 240 | 241 | } 242 | 243 | void Presentation::next(){ 244 | iCurrentSlide++; 245 | 246 | if(iCurrentSlide >= (int)mSlides.size()){ 247 | iCurrentSlide = 0; 248 | presentationFinished = true; 249 | } 250 | 251 | LOG("Next! (%d, %d)\n", iCurrentSlide, (int)mTransitions.size()); 252 | 253 | mCurrentTransition = mTransitions[rand() % mTransitions.size()]; 254 | 255 | isTransition = true; 256 | transitionInit = true; 257 | 258 | } 259 | 260 | void Presentation::prev(){ 261 | iCurrentSlide--; 262 | 263 | if(iCurrentSlide < 0) iCurrentSlide = mSlides.size() - 1; 264 | 265 | LOG("Prev! (%d)\n", iCurrentSlide); 266 | isTransition = false; 267 | } 268 | 269 | 270 | void Presentation::shutdown(){ 271 | 272 | LOG("presentation shutdown (%d slides)\n", (int)mSlides.size()); 273 | 274 | for(int i=0;i<(int)mSlides.size();i++){ 275 | delete mSlides[i]; 276 | } 277 | mSlides.clear(); 278 | } 279 | 280 | bool Presentation::toggleReadabilityMovement(){ 281 | bUseReadabilityMovement = !bUseReadabilityMovement; 282 | return bUseReadabilityMovement; 283 | } 284 | -------------------------------------------------------------------------------- /util/codegen/parse.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | import xml.dom.minidom 3 | import re 4 | 5 | #clientsource = open("glapi.cpp", "w") 6 | lastOffset = 0 7 | 8 | def getchildren(node, name): 9 | ret = [] 10 | for e2 in node.childNodes: 11 | if e2.localName == name: 12 | ret.append(e2) 13 | return ret 14 | 15 | def getparams(node): 16 | 17 | ret = "(" 18 | 19 | params = getchildren(node, "param") 20 | 21 | for e in params: 22 | t = e.attributes["type"].value; 23 | v = e.attributes["name"].value 24 | 25 | if v != None and t != None: 26 | ret += t + " " + v 27 | 28 | if e != params[len(params)-1]: 29 | ret += ", " 30 | 31 | ret += ")" 32 | 33 | return ret 34 | 35 | def isReturn(node): 36 | 37 | ret = getchildren(node, "return") 38 | if len(ret) > 0: 39 | #print "//Ignored retval '" + ret[0].attributes["type"].value + "'" + " (" + str(count - good) + " ignored so far )" 40 | return True 41 | return False 42 | 43 | def hasBuf(node): 44 | params = getchildren(node, "param") 45 | 46 | for e in params: 47 | t = e.attributes["type"].value; 48 | v = e.attributes["name"].value 49 | 50 | if t.find("*") > 0: 51 | 52 | #Check to see if it's a nice simple buffer... 53 | if "count" in e.attributes.keys(): 54 | return False 55 | 56 | if v == "v": 57 | return False 58 | 59 | #print "//Ignored buffer '" + t + " " + v + "'" + " (" + str(count - good) + " ignored so far )" 60 | return True 61 | 62 | return False 63 | 64 | def getCmdId(n): 65 | if "offset" in n.attributes.keys() and n.attributes["offset"].value != "assign": 66 | lastOffset = int(n.attributes["offset"].value) 67 | return n.attributes["offset"].value 68 | else: 69 | lastOffset = count 70 | return str(lastOffset) 71 | 72 | def getType(letter): 73 | if letter == "d": 74 | return "GLdouble" 75 | elif letter == "f": 76 | return "GLfloat" 77 | elif letter == "s": 78 | return "GLshort" 79 | elif letter == "i": 80 | return "GLint" 81 | 82 | return "**ERROR " + letter + "**" 83 | 84 | # Client side intercept function 85 | def doFunction(n): 86 | 87 | cmdid = getCmdId(n) 88 | name = n.attributes["name"].value 89 | skip = False 90 | 91 | ret = getchildren(n, "return") 92 | retType = "void" 93 | if len(ret) > 0: 94 | retType = ret[0].attributes["type"].value 95 | 96 | 97 | #if retType != "void": 98 | # skip = True 99 | 100 | if hasBuf(n): 101 | skip = True 102 | 103 | print "//" + cmdid 104 | print "extern \"C\" " + retType + " gl" + n.attributes["name"].value + getparams(n) + "{" 105 | 106 | if skip: 107 | print "\tLOG(\"Called unimplemted stub " + name + "!\\n\");" 108 | else: 109 | print "\tpushOp(" + cmdid + ");" 110 | 111 | params = getchildren(n, "param") 112 | for e in params: 113 | 114 | v = e.attributes["name"].value 115 | name = n.attributes["name"].value; 116 | name = name.replace("MESA", "") 117 | name = name.replace("ARB", "") 118 | 119 | number_regex = re.compile('\d+').search(name) 120 | number = "" 121 | if number_regex != None: 122 | number = number_regex.group(0) 123 | 124 | l = "0" 125 | 126 | t = e.attributes["type"].value.replace(" *", "") 127 | 128 | if "count" in e.attributes.keys(): 129 | l = " sizeof(" + t + ") * " + e.attributes["count"].value 130 | else: 131 | end = " sizeof(" + t + ") * " + number 132 | 133 | l = end 134 | 135 | if e.attributes["type"].value.find("*") > 0: 136 | print "\tpushBuf(" + v + "," + l + ");" 137 | else: 138 | print "\tpushParam(" + v + ");" 139 | 140 | # Handle returns from this function 141 | if retType != "void": 142 | print "\n\t" + retType + " ret;" 143 | print "\tpushBuf(&ret, sizeof(" + retType + "), true);" 144 | print "\twaitForReturn();" 145 | print "\n\treturn ret;" 146 | 147 | print "}\n" 148 | 149 | return not skip 150 | 151 | # Server side function that executes this given the CGL command object 152 | def doExecute(n): 153 | 154 | cmdid = getCmdId(n) 155 | name = n.attributes["name"].value 156 | 157 | #if isReturn(n): 158 | # print "//Skipped " + cmdid + " (" + name + ")\n" 159 | # return False 160 | 161 | #if hasBuf(n): 162 | # print "//Skipped " + cmdid + " (" + name + ")\n" 163 | # return False 164 | 165 | print "//" + cmdid 166 | print "void EXEC_gl" + name + "(byte *commandbuf){"; 167 | 168 | 169 | invoke = "\n\t"; 170 | 171 | if isReturn(n): 172 | invoke += "pushRet(" 173 | invoke += "gl" + name + "(" 174 | 175 | params = getchildren(n, "param") 176 | for e in params: 177 | v = e.attributes["name"].value 178 | t = e.attributes["type"].value 179 | 180 | if t.find("*") <= 0: 181 | print "\t" + t + " *" + v + " = (" + t + "*)commandbuf;\t commandbuf += sizeof(" + t + ");" 182 | 183 | if t.find("*") > 0: 184 | invoke += "(" + t + ")popBuf()" 185 | else: 186 | invoke += "*" + v 187 | 188 | if e != params[len(params)-1]: 189 | invoke += ", " 190 | 191 | if isReturn(n): 192 | invoke += ")" 193 | 194 | invoke += ");" 195 | 196 | 197 | print invoke 198 | 199 | print "}\n" 200 | 201 | return True 202 | 203 | #Server side function that prints the command to stdout 204 | def doText(n): 205 | 206 | cmdid = getCmdId(n) 207 | name = n.attributes["name"].value 208 | 209 | 210 | #if isReturn(n): 211 | #print "//Skipped " + cmdid + " (" + name + ")\n" 212 | # return False 213 | 214 | #if hasBuf(n): 215 | #print "//Skipped " + cmdid + " (" + name + ")\n" 216 | # return False 217 | 218 | 219 | #print "\tmFunctions[" + cmdid + "] = EXEC_gl" + name + ";"; 220 | #return 221 | 222 | 223 | print "//" + cmdid 224 | print "void EXEC_gl" + name + "(byte *commandbuf){"; 225 | 226 | if not hasBuf(n): 227 | 228 | logcmd = "\n\tLOG(\"gl" + name + "(" 229 | p = "" 230 | 231 | params = getchildren(n, "param") 232 | for e in params: 233 | v = e.attributes["name"].value 234 | t = e.attributes["type"].value 235 | 236 | print "\t" + t + " *" + v + " = (" + t + "*)commandbuf;\t commandbuf += sizeof(" + t + ");" 237 | 238 | logcmd += v + "=%0.1f" 239 | p += "(float)*" + v 240 | 241 | if e != params[len(params)-1]: 242 | logcmd += ", " 243 | p += ", " 244 | 245 | if len(p) > 0: 246 | logcmd += ")\\n\", " + p + ");" 247 | else: 248 | logcmd += ")\\n\");" 249 | 250 | print logcmd 251 | else: 252 | print "\n\tLOG(\"gl" + name + "()\\n\");\n" 253 | 254 | print "}\n" 255 | 256 | return True 257 | 258 | 259 | 260 | #entry 261 | #print "Parsing!" 262 | 263 | thefile = xml.dom.minidom.parse("gl_API.xml") 264 | 265 | count = 0 266 | good = 0 267 | lastOffset = 0 268 | 269 | # We want to find the 'function' bits 270 | for e in thefile.childNodes[1].childNodes: 271 | for e2 in e.childNodes: 272 | if e2.nodeType == e2.ELEMENT_NODE and e2.localName == "function": 273 | 274 | #print e2.attributes.keys() 275 | 276 | #if doFunction(e2): 277 | # good += 1 278 | 279 | if doExecute(e2): 280 | good+=1 281 | 282 | #if doText(e2): 283 | # good += 1 284 | 285 | count+=1 286 | 287 | #if count > 7: 288 | # break 289 | 290 | #if count > 7: 291 | # break 292 | 293 | #print 294 | print "Total:\t " + str(count) 295 | print "Good:\t " + str(good) 296 | print "Bad:\t " + str(count - good) 297 | 298 | 299 | #clientsource.close() 300 | -------------------------------------------------------------------------------- /src/include/module.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | ClusterGL - module.h 3 | *******************************************************************************/ 4 | 5 | /******************************************************************************* 6 | The main module interface 7 | *******************************************************************************/ 8 | class Module 9 | { 10 | protected: 11 | vector *mListResult; 12 | 13 | public: 14 | Module(){} 15 | 16 | //input 17 | virtual bool process(vector *i){return i != NULL;} 18 | virtual bool process(byte *buf, int len){return (buf != NULL && len);} 19 | 20 | //output 21 | virtual vector *resultAsList(){return mListResult;} 22 | 23 | void setListResult(vector *i){ 24 | mListResult = i; 25 | } 26 | 27 | virtual void reply(Instruction *instr, int i){} 28 | virtual bool sync()=0; 29 | }; 30 | 31 | 32 | 33 | /******************************************************************************* 34 | Capture from a program 35 | *******************************************************************************/ 36 | class AppModule : public Module 37 | { 38 | public: 39 | AppModule(string command); 40 | 41 | bool init(string command); 42 | bool process(vector *i); 43 | bool sync(); 44 | }; 45 | 46 | 47 | /******************************************************************************* 48 | Output to stdout 49 | *******************************************************************************/ 50 | class TextModule : public Module 51 | { 52 | public: 53 | TextModule(); 54 | bool init(); 55 | bool process(vector *i); 56 | bool sync(); 57 | }; 58 | 59 | 60 | 61 | /******************************************************************************* 62 | Output to OpenGL (executing the commands) 63 | *******************************************************************************/ 64 | class ExecModule : public Module 65 | { 66 | bool makeWindow(); 67 | 68 | bool handleViewMode(Instruction *i); 69 | 70 | public: 71 | ExecModule(); 72 | 73 | bool init(); 74 | bool process(vector *i); 75 | bool sync(); 76 | }; 77 | 78 | /******************************************************************************* 79 | Network server module. This recvs commands and thus should go at the *start* 80 | of the local pipeline. Blocks till a client connects. 81 | *******************************************************************************/ 82 | class NetSrvModule : public Module 83 | { 84 | int mSocket; 85 | BufferedFd *mClientSocket; 86 | 87 | int internalRead(byte *input, int nByte); 88 | int internalWrite(byte *input, int nByte); 89 | 90 | void recieveBuffer(void); 91 | 92 | public: 93 | NetSrvModule(); 94 | 95 | bool process(vector *i); 96 | void reply(Instruction *instr, int i); 97 | bool sync(); 98 | 99 | }; 100 | 101 | 102 | /******************************************************************************* 103 | Network client module. This sends commands, and thus should go at the *end* 104 | of the local pipe (probably on the app side). 105 | *******************************************************************************/ 106 | class NetClientModule : public Module 107 | { 108 | vector mSockets; 109 | int numConnections; 110 | 111 | int internalWrite(void* buf, int nByte); 112 | int internalRead(void *buf, size_t count); 113 | 114 | void sendBuffer(); 115 | 116 | public: 117 | NetClientModule(); 118 | 119 | bool process(vector *i); 120 | bool sync(); 121 | }; 122 | 123 | 124 | /******************************************************************************* 125 | Network server and client modules that uses OpenPGM for multicast 126 | *******************************************************************************/ 127 | class MulticastSrvModule : public Module 128 | { 129 | int mSocket; 130 | BufferedFd *mClientSocket; 131 | 132 | int internalRead(byte *input, int nByte); 133 | int internalWrite(byte *input, int nByte); 134 | 135 | void recieveBuffer(void); 136 | 137 | public: 138 | MulticastSrvModule(); 139 | 140 | bool process(vector *i); 141 | void reply(Instruction *instr, int i); 142 | bool sync(); 143 | 144 | }; 145 | 146 | class MulticastClientModule : public Module 147 | { 148 | vector mSockets; 149 | int numConnections; 150 | 151 | int internalWrite(void* buf, int nByte); 152 | int internalRead(void *buf, size_t count); 153 | 154 | void sendBuffer(); 155 | 156 | public: 157 | MulticastClientModule(); 158 | 159 | bool process(vector *i); 160 | bool sync(); 161 | }; 162 | 163 | /******************************************************************************* 164 | Insertion module. Insert instructions into a frame at runtime 165 | *******************************************************************************/ 166 | class InsertModule : public Module 167 | { 168 | public: 169 | InsertModule(); 170 | 171 | bool init(); 172 | bool process(vector *i); 173 | void reply(Instruction *instr, int i); 174 | bool sync(); 175 | }; 176 | 177 | 178 | /******************************************************************************* 179 | Profiling module 180 | *******************************************************************************/ 181 | class ProfileModule : public Module 182 | { 183 | public: 184 | ProfileModule(); 185 | 186 | bool process(vector *i); 187 | void reply(Instruction *instr, int i); 188 | bool sync(); 189 | void resetCounts(); 190 | void output(); 191 | void outputBuffers(); 192 | }; 193 | 194 | 195 | 196 | /******************************************************************************* 197 | Delta module. Remove duplicate instructions, replace with CGL_REPEAT's 198 | *******************************************************************************/ 199 | class DeltaEncodeModule : public Module 200 | { 201 | vector lastFrame; 202 | 203 | Instruction *makeSkip(uint32_t n); 204 | public: 205 | DeltaEncodeModule(); 206 | 207 | //input 208 | bool process(vector *i); 209 | 210 | //output 211 | vector *resultAsList(); 212 | 213 | bool sync(){return true;} 214 | }; 215 | 216 | class DeltaDecodeModule : public Module 217 | { 218 | vector lastFrame; 219 | public: 220 | DeltaDecodeModule(); 221 | 222 | //input 223 | bool process(vector *i); 224 | 225 | //output 226 | vector *resultAsList(); 227 | 228 | bool sync(){return true;} 229 | }; 230 | 231 | 232 | 233 | /******************************************************************************* 234 | DuplicateBuffer module. Keeps a LRU of buffers+hash. 235 | *******************************************************************************/ 236 | typedef LRUCache lru_cache; 237 | 238 | class DuplicateBufferEncodeModule : public Module 239 | { 240 | lru_cache *mLRU; 241 | public: 242 | DuplicateBufferEncodeModule(); 243 | 244 | //input 245 | bool process(vector *i); 246 | 247 | //output 248 | vector *resultAsList(); 249 | 250 | bool sync(){return true;} 251 | }; 252 | 253 | class DuplicateBufferDecodeModule : public Module 254 | { 255 | lru_cache *mLRU; 256 | public: 257 | DuplicateBufferDecodeModule(); 258 | 259 | //input 260 | bool process(vector *i); 261 | 262 | //output 263 | vector *resultAsList(); 264 | 265 | bool sync(){return true;} 266 | }; 267 | 268 | 269 | 270 | /******************************************************************************* 271 | Data compression global. Not really a global, but it used to be 272 | *******************************************************************************/ 273 | class Compression{ 274 | public: 275 | static int decompress(void *dest, int destLen, int sourceLen); 276 | static int compress(void *input, int nByte); 277 | static byte *getBuf(); 278 | }; 279 | -------------------------------------------------------------------------------- /src/mod_delta.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | Delta/Framediff module 3 | *******************************************************************************/ 4 | 5 | #include "main.h" 6 | 7 | 8 | /******************************************************************************* 9 | Encode stage 10 | *******************************************************************************/ 11 | DeltaEncodeModule::DeltaEncodeModule(){ 12 | 13 | } 14 | 15 | Instruction *DeltaEncodeModule::makeSkip(uint32_t n){ 16 | Instruction *skip = new Instruction(); 17 | skip->id = CGL_REPEAT_INSTRUCTION; 18 | memcpy(skip->args, &n, sizeof(uint32_t)); 19 | 20 | //LOG("Skip %d\n", n); 21 | 22 | return skip; 23 | } 24 | 25 | bool DeltaEncodeModule::process(vector *list){ 26 | 27 | if(lastFrame.size() == 0){ 28 | //this must be the first frame 29 | mListResult = list; 30 | lastFrame = *list; 31 | return true; 32 | } 33 | 34 | vector *result = new vector(); 35 | 36 | int sameCount = 0; 37 | int totalSkip = 0; 38 | 39 | for(int n=0;n<(int)list->size();n++){ 40 | Instruction *instr = (*list)[n]; 41 | 42 | if((int)lastFrame.size() > n){ 43 | Instruction *last = lastFrame[n]; 44 | 45 | if(!instr->needReply() && instr->compare(last)){ 46 | sameCount++; 47 | totalSkip++; 48 | }else{ 49 | 50 | if(sameCount) 51 | result->push_back(makeSkip(sameCount)); 52 | 53 | result->push_back(instr); 54 | sameCount = 0; 55 | } 56 | }else{ 57 | result->push_back(instr); 58 | } 59 | } 60 | 61 | if(sameCount){ 62 | result->push_back(makeSkip(sameCount)); 63 | } 64 | 65 | lastFrame = *list; 66 | delete list; 67 | 68 | mListResult = result; 69 | 70 | //LOG("Delta: %d from %d\n", list->size() - totalSkip, list->size()); 71 | Stats::count("Delta replace", totalSkip); 72 | 73 | return true; 74 | } 75 | 76 | //output 77 | vector *DeltaEncodeModule::resultAsList(){ 78 | return mListResult; 79 | } 80 | 81 | 82 | 83 | 84 | 85 | 86 | /******************************************************************************* 87 | Decode stage 88 | *******************************************************************************/ 89 | DeltaDecodeModule::DeltaDecodeModule(){ 90 | lastFrame.clear(); 91 | } 92 | 93 | bool DeltaDecodeModule::process(vector *list){ 94 | 95 | vector *result = new vector(); 96 | 97 | int instrCount = 0; 98 | 99 | 100 | for(int n=0;n<(int)list->size();n++){ 101 | Instruction *instr = (*list)[n]; 102 | 103 | 104 | if((int)lastFrame.size() > n){ 105 | 106 | if(instr->id == CGL_REPEAT_INSTRUCTION){ 107 | 108 | uint32_t *num = (uint32_t *)instr->args; 109 | for(int i=0;i<(int)*num;i++){ 110 | Instruction *last = lastFrame[instrCount]; 111 | // we have to copy here because otherwise lru-processing 112 | // would fail if we just saved another reference to 113 | // the same instruction ... 114 | result->push_back(last->copy()); 115 | instrCount++; 116 | } 117 | }else{ 118 | // ... but then we _have_ to copy here as well 119 | // (otherwise we would mess up dynamically created 120 | // with static referenced objects in one list) 121 | result->push_back(instr->copy()); 122 | instrCount++; 123 | } 124 | }else{ 125 | // ... and here (same reason) 126 | result->push_back(instr->copy()); 127 | instrCount++; 128 | } 129 | } 130 | 131 | 132 | 133 | //copy into lastFrame 134 | //This is probably the slowest bit, but we don't have any other option, we 135 | //need a copy of the frame 136 | for(int n=0;n<(int)lastFrame.size();n++){ 137 | lastFrame[n]->clear(); 138 | delete lastFrame[n]; 139 | } 140 | 141 | lastFrame.clear(); 142 | for(int n=0;n<(int)result->size();n++){ 143 | Instruction *src = (*result)[n]; 144 | Instruction *dst = src->copy(); 145 | 146 | lastFrame.push_back(dst); 147 | 148 | //reset the buffers so they don't get cleared later 149 | for(int i=0;i<3;i++){ 150 | src->buffers[i].needClear = false; 151 | } 152 | } 153 | 154 | for(int n=0;n<(int)list->size();n++) { 155 | Instruction *iter = (*list)[n]; 156 | iter->clear(); 157 | } 158 | 159 | delete list; 160 | 161 | 162 | mListResult = result; 163 | 164 | return true; 165 | } 166 | 167 | //output 168 | vector *DeltaDecodeModule::resultAsList(){ 169 | return mListResult; 170 | } 171 | 172 | 173 | 174 | /* 175 | //Now send the instructions 176 | int counter = 0; 177 | for(std::list::iterator iter = list.begin(), 178 | pIter = (*prevFrame).begin();iter != list.end(); iter++) { 179 | Instruction *i = &(*iter); 180 | 181 | bool mustSend = false; 182 | 183 | for(int n=0;n<3;n++) { 184 | if(i->buffers[n].len > 0) { 185 | //If we expect a buffer back then we must send Instruction 186 | if(i->buffers[n].needReply) mustSend = true; 187 | } 188 | }; 189 | 190 | if (useRepeat //value from config to enable/disable deltas 191 | && i->id == pIter->id//if the instruction has the same id as previous 192 | && !mustSend && i->id//mustSend is set when expecting a reply 193 | // && sameCount < 150//stops sameBuffer filling up indefinitely (is this needed?) 194 | && i->id != 1499 195 | ) { 196 | //assume the instruction is the same 197 | bool same = true; 198 | //compare all arguments 199 | for (int a=0;aargs[a]!=pIter->args[a]) { 201 | same = false; 202 | break; 203 | } 204 | } 205 | 206 | //if arguments the same, compare all buffers 207 | if (same) { 208 | for (int a=0;a<3;a++) { 209 | if (i->buffers[a].len > 0) { 210 | if(i->buffers[a].len != pIter->buffers[a].len) { 211 | same = false; 212 | break; 213 | } 214 | else if (i->buffers[a].needClear != pIter->buffers[a].needClear) { 215 | same = false; 216 | break; 217 | } 218 | else if (memcmp(i->buffers[a].buffer,pIter->buffers[a].buffer,i->buffers[a].len) != 0) { 219 | same = false; 220 | break; 221 | } 222 | } 223 | } 224 | } 225 | 226 | //if arguments and buffers match, the instruction is identical 227 | if (same) { 228 | sameCount++; 229 | if (pIter != (*prevFrame).end()) 230 | pIter++; 231 | continue; 232 | } 233 | } 234 | //printf("same count: %d\n", sameCount); 235 | if (sameCount> 0) { // send a count of the duplicates before this instruction 236 | Instruction * skip = (Instruction *)malloc(sizeof(Instruction)); 237 | if (skip == 0) { 238 | LOG("ERROR: Out of memory\n"); 239 | exit(-1); 240 | } 241 | skip->id = CGL_REPEAT_INSTRUCTION; 242 | memcpy(skip->args, &sameCount, sizeof(uint32_t)); 243 | //printf("sameCount: %d\n", sameCount); 244 | for(int i=0;i<3;i++) { 245 | skip->buffers[i].buffer = NULL; 246 | skip->buffers[i].len = 0; 247 | skip->buffers[i].needClear = false; 248 | } 249 | if(multicast) { 250 | netBytes += sizeof(Instruction); 251 | } 252 | else { 253 | netBytes += sizeof(Instruction) * numConnections; 254 | } 255 | if(myWrite(skip, sizeof(Instruction))!= sizeof(Instruction)) { 256 | LOG("Connection problem (didn't send instruction)!\n"); 257 | return false; 258 | } 259 | sameCount = 0; // reset the count and free the memory 260 | free(skip); 261 | } 262 | 263 | // now send the new instruction 264 | netBytes += sizeof(Instruction) * numConnections; 265 | if(myWrite(i, sizeof(Instruction)) != sizeof(Instruction)) { 266 | LOG("Connection problem (didn't send instruction)!\n"); 267 | return false; 268 | } 269 | 270 | //Now see if we need to send any buffers 271 | for(int n=0;n<3;n++) { 272 | int l = i->buffers[n].len; 273 | 274 | if(l > 0) { 275 | netBytes += l * numConnections; 276 | if(myWrite(i->buffers[n].buffer, l) != l) { 277 | LOG("Connection problem (didn't write buffer %d)!\n", l); 278 | return false; 279 | } 280 | //And check if we're expecting a buffer back in response 281 | if(i->buffers[n].needReply) { 282 | 283 | sendBuffer(); 284 | if(int x = myRead(i->buffers[n].buffer, l) != l) { 285 | LOG("Connection problem NetClient (didn't recv buffer %d got: %d)!\n", l, x); 286 | return false; 287 | } 288 | //LOG("got buffer back!\n"); 289 | } 290 | } 291 | } 292 | if (pIter != (*prevFrame).end()) pIter++; 293 | counter++; 294 | } 295 | 296 | //send any instructions that are remaining in the CGL_REPEAT_INSTRUCTION buffer 297 | if (sameCount> 0) { // send a count of the duplicates before this instruction 298 | Instruction * skip = (Instruction *)malloc(sizeof(Instruction)); 299 | if (skip == 0) { 300 | LOG("ERROR: Out of memory\n"); 301 | exit(-1); 302 | } 303 | skip->id = CGL_REPEAT_INSTRUCTION; 304 | skip->args[0] = (uint32_t) sameCount; 305 | //printf("sameCount: %d\n", sameCount); 306 | for(int i=0;i<3;i++) { 307 | skip->buffers[i].buffer = NULL; 308 | skip->buffers[i].len = 0; 309 | skip->buffers[i].needClear = false; 310 | } 311 | netBytes += sizeof(Instruction) * numConnections; 312 | if(myWrite(skip, sizeof(Instruction))!= sizeof(Instruction)) { 313 | LOG("Connection problem (didn't send instruction)!\n"); 314 | return false; 315 | } 316 | sameCount = 0; // reset the count and free the memory 317 | free(skip); 318 | } 319 | sendBuffer(); 320 | */ 321 | -------------------------------------------------------------------------------- /src/config.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | ClusterGL - config.cpp 3 | *******************************************************************************/ 4 | #include "main.h" 5 | 6 | Config::Config(string filename, string id){ 7 | 8 | LOG("Loading configuration for '%s' from '%s'\n", 9 | id.c_str(), filename.c_str()); 10 | 11 | this->id = id; 12 | 13 | //Output options 14 | static cfg_opt_t output_opts[] = { 15 | CFG_INT( (char *)("sizeX"), 0, CFGF_NONE), 16 | CFG_INT( (char *)("sizeY"), 0, CFGF_NONE), 17 | CFG_INT( (char *)("positionX"), 0, CFGF_NONE), 18 | CFG_INT( (char *)("positionY"), 0, CFGF_NONE), 19 | CFG_INT( (char *)("offsetX"), 0, CFGF_NONE), 20 | CFG_INT( (char *)("offsetY"), 0, CFGF_NONE), 21 | CFG_INT( (char *)("port"), 0, CFGF_NONE), 22 | CFG_INT( (char *)("angle"), 0, CFGF_NONE), 23 | CFG_STR( (char *)("address"), 0, CFGF_NONE), 24 | CFG_FLOAT( (char *)("scaleX"), 1.0, CFGF_NONE), 25 | CFG_FLOAT( (char *)("scaleY"), 1.0, CFGF_NONE), 26 | CFG_STR( (char *)("viewmode"), 0, CFGF_NONE), 27 | CFG_END() 28 | }; 29 | 30 | //Top level options 31 | static cfg_opt_t opts[] = { 32 | CFG_SIMPLE_INT( (char *)("totalWidth"), &totalWidth), 33 | CFG_SIMPLE_INT( (char *)("totalHeight"), &totalHeight), 34 | CFG_SIMPLE_INT( (char *)("fakeWindowX"), &fakeWindowX), 35 | CFG_SIMPLE_INT( (char *)("fakeWindowY"), &fakeWindowY), 36 | CFG_SIMPLE_INT( (char *)("syncRate"), &syncRate), 37 | CFG_SIMPLE_INT( (char *)("networkCompression"), &networkCompression), 38 | CFG_SIMPLE_BOOL( (char *)("enableStats"), &enableStats), 39 | CFG_STR_LIST( (char *)"capturePipeline", (char *)"{}", CFGF_NONE), 40 | CFG_STR_LIST( (char *)"outputPipeline", (char *)"{}", CFGF_NONE), 41 | CFG_SEC( (char *)"output", output_opts, CFGF_MULTI | CFGF_TITLE), 42 | CFG_STR( (char *)("interceptMode"), 0, CFGF_NONE), 43 | CFG_STR( (char *)("capturePidFile"), 0, CFGF_NONE), 44 | CFG_SIMPLE_BOOL( (char *)("remoteConfigServerEnabled"), 45 | &remoteConfigServerEnabled), 46 | CFG_END() 47 | }; 48 | 49 | cfg_t *cfg; 50 | 51 | cfg = cfg_init(opts, CFGF_NONE); 52 | 53 | int parse_result = cfg_parse(cfg, filename.c_str()); 54 | 55 | if(parse_result == CFG_FILE_ERROR){ 56 | LOG("Error with the file (does it exist?)\n"); 57 | exit(1); 58 | } 59 | 60 | if(parse_result == CFG_PARSE_ERROR){ 61 | LOG("Couldn't parse config file\n"); 62 | exit(1); 63 | } 64 | 65 | if(!cfg_getstr(cfg, "interceptMode")){ 66 | LOG("No interceptMode specified, assuming \"x11\"\n"); 67 | interceptMode = "x11"; 68 | }else{ 69 | interceptMode = string(cfg_getstr(cfg, "interceptMode")); 70 | } 71 | 72 | if(!cfg_getstr(cfg, "capturePidFile")){ 73 | capturePidFile = ""; 74 | }else{ 75 | capturePidFile = string(cfg_getstr(cfg, "capturePidFile")); 76 | } 77 | 78 | numOutputs = 0; 79 | 80 | int n = cfg_size(cfg, "output"); 81 | 82 | if(n == 0){ 83 | LOG("No outputs specified, aborting\n"); 84 | exit(1); 85 | } 86 | 87 | bool found_section = false; 88 | 89 | for(int i=0;i> result; 197 | 198 | return result; 199 | } 200 | 201 | bool handled = false; 202 | int config_result = 0; 203 | 204 | void handle_config_attrib(string attrib, string uri, int *ptr){ 205 | if(uri.find(attrib) == string::npos){ 206 | return; 207 | } 208 | 209 | handled = true; 210 | 211 | string var = variable_from_uri(uri); 212 | 213 | if(var.find("/") == string::npos){ 214 | config_result = *ptr; 215 | LOG("GET %s = %d\n", var.c_str(), *ptr); 216 | return; 217 | } 218 | 219 | int value = value_from_variable(var); 220 | *ptr = value; 221 | config_result = 1; 222 | 223 | LOG("SET %s = %d\n", attrib.c_str(), value); 224 | } 225 | 226 | /******************************************************************************* 227 | Web server high-level callback 228 | *******************************************************************************/ 229 | string request(string url){ 230 | //LOG("WEB: %s\n", url.c_str()); 231 | 232 | handled = false; 233 | config_result = 0; 234 | 235 | handle_config_attrib("sizeX", url, &gConfig->sizeX); 236 | handle_config_attrib("sizeY", url, &gConfig->sizeY); 237 | handle_config_attrib("positionX", url, &gConfig->positionX); 238 | handle_config_attrib("positionY", url, &gConfig->positionY); 239 | handle_config_attrib("offsetX", url, &gConfig->offsetX); 240 | handle_config_attrib("offsetY", url, &gConfig->offsetY); 241 | handle_config_attrib("angle", url, &gConfig->angle); 242 | handle_config_attrib("totalWidth", url, &gConfig->totalWidth); 243 | handle_config_attrib("totalHeight", url, &gConfig->totalHeight); 244 | handle_config_attrib("screenGap", url, &gConfig->screenGap); 245 | //handle_config_attrib("scaleX", url, &gConfig->sizeX); 246 | //handle_config_attrib("scaleY", url, &gConfig->sizeX); 247 | handle_config_attrib("fakeWindowX", url, &gConfig->fakeWindowX); 248 | handle_config_attrib("fakeWindowY", url, &gConfig->fakeWindowY); 249 | 250 | if(handled){ 251 | std::stringstream out; 252 | out << config_result; 253 | return out.str() + "\n"; 254 | } 255 | 256 | string html = read_file("web" + url); 257 | 258 | if(url == "/"){ 259 | html = read_file("web/index.html"); 260 | } 261 | 262 | if(html.length() > 0){ 263 | return html; 264 | } 265 | 266 | LOG("WEB: 404 NOT FOUND %s\n", url.c_str()); 267 | 268 | //Give up! 269 | return string("404 not found: ") + url + "\n"; 270 | } 271 | 272 | string guess_content_type(string url){ 273 | if(url.find(".css") != string::npos){ 274 | return "text/css"; 275 | } 276 | 277 | if(url.find(".js") != string::npos){ 278 | return "script/javascript"; 279 | } 280 | 281 | return "text/html"; 282 | } 283 | 284 | /******************************************************************************* 285 | Web server low-level callback 286 | *******************************************************************************/ 287 | static void *callback(enum mg_event event, struct mg_connection *conn) { 288 | const struct mg_request_info *request_info = mg_get_request_info(conn); 289 | 290 | if (event == MG_NEW_REQUEST) { 291 | string content = request(string(request_info->uri)); 292 | mg_printf(conn, 293 | "HTTP/1.1 200 OK\r\n" 294 | "Content-Type: %s\r\n" 295 | "Content-Length: %d\r\n" 296 | "\r\n" 297 | "%s", 298 | guess_content_type(string(request_info->uri)).c_str(), 299 | (int)content.length(), 300 | content.c_str()); 301 | // Mark as processed 302 | return (void *)""; 303 | } else if(event == MG_EVENT_LOG) { 304 | printf("Webserver: %s\n", request_info->log_message); 305 | return NULL; 306 | } 307 | 308 | return NULL; 309 | } 310 | -------------------------------------------------------------------------------- /src/viewmode.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | mod_exec helper 3 | *******************************************************************************/ 4 | 5 | #include "main.h" 6 | 7 | 8 | 9 | extern int displayNumber; //this is the reason the fancier offsets don't work... 10 | extern int currentBuffer; 11 | extern bool glFrustumUsage; 12 | extern bool bezelCompensation; 13 | extern GLenum currentMode; 14 | 15 | void handleLoadMatrix(Instruction *iter); 16 | void handlePerspective(Instruction *iter); 17 | void handleOrtho(Instruction *iter); 18 | void handleScissor(Instruction *iter); 19 | void handleViewport(Instruction *iter); 20 | 21 | bool ExecModule::handleViewMode(Instruction *iter){ 22 | //We override some methods here for view adjustment 23 | //TODO: Clean this up some more 24 | 25 | if(gConfig->viewMode == VIEWMODE_VIEWPORT){ 26 | if (iter->id == 305) { //glViewPort 27 | handleViewport(iter); 28 | return true; 29 | } 30 | }else if(gConfig->viewMode == VIEWMODE_CURVE){ 31 | 32 | if (iter->id == 305) { //glViewPort 33 | glViewport(0, 0, 34 | gConfig->totalWidth, gConfig->totalHeight); 35 | return true; 36 | } 37 | 38 | if (iter->id == 290) { //glLoadIdentity 39 | 40 | if(currentMode == GL_MODELVIEW){ 41 | glLoadIdentity(); 42 | glRotatef(gConfig->angle, 0, 1, 0); 43 | return true; 44 | } 45 | } 46 | } 47 | 48 | /* 49 | else if (iter->id == 176) { 50 | handleScissor(iter); //glScissor 51 | }else if (iter->id == 296) { 52 | handleOrtho(iter); //glOrtho 53 | }else if (iter->id == 1539) { 54 | handlePerspective(iter); //gluPerspective 55 | }else if (iter->id == 291) { 56 | handleLoadMatrix(iter); //glLoadMatrixf 57 | }*/ 58 | return false; 59 | } 60 | 61 | 62 | 63 | 64 | 65 | /******************************************************************************* 66 | Special functions we handle seperately 67 | *******************************************************************************/ 68 | void handleViewport(Instruction *iter){ 69 | /* 70 | if(!glFrustumUsage){ 71 | //no nothing, will be handled later (in gluPerpespective or glLoadMatrix) 72 | return 73 | } 74 | */ 75 | 76 | float magic = 1800; 77 | 78 | GLint x = *((GLint*)iter->args); 79 | GLint y = *((GLint*)(iter->args+ sizeof(GLint))); 80 | GLsizei w = *((GLsizei*)(iter->args+ sizeof(GLint)*2)); 81 | GLsizei h = *((GLsizei*)(iter->args+ sizeof(GLint)*2+ sizeof(GLsizei))); 82 | 83 | glViewport(-gConfig->offsetX*gConfig->scaleX,-gConfig->offsetY*gConfig->scaleY, 84 | gConfig->totalWidth*gConfig->scaleX, gConfig->totalHeight*gConfig->scaleY); 85 | //glViewport(x,y,w,h); 86 | 87 | 88 | //if(bezelCompensation){ 89 | 90 | //}else{ 91 | // glViewport((-offsetX*screenWidth)/magic,0, gConfig->totalWidth, 4560*3.0/4.0); 92 | //} 93 | 94 | //LOG("handleViewport(%d,%d,%d,%d)\n",x,y,w,h); 95 | } 96 | 97 | void handleScissor(Instruction *iter){ 98 | //read original values from the instruction 99 | GLint x = *((GLint*)iter->args); 100 | GLint y = *((GLint*)(iter->args+ sizeof(GLint))); 101 | GLsizei w = *((GLsizei*)(iter->args+ sizeof(GLint)*2)); 102 | GLsizei h = *((GLsizei*)(iter->args+ sizeof(GLint)*2+ sizeof(GLsizei))); 103 | 104 | //LOG("glScissor values %d %d %d %d\n", x, y, w, h); 105 | 106 | glScissor(0, 0, gConfig->totalWidth, gConfig->totalHeight); 107 | 108 | LOG("handleScissor\n"); 109 | } 110 | 111 | void handleOrtho(Instruction *iter){ 112 | 113 | //read original values from the instruction 114 | GLdouble left = *((GLdouble*)iter->args); 115 | GLdouble right = *((GLdouble*)(iter->args+ sizeof(GLdouble))); 116 | GLdouble bottom = *((GLdouble*)(iter->args+ sizeof(GLdouble)*2)); 117 | GLdouble top = *((GLdouble*)(iter->args+ sizeof(GLdouble)*3)); 118 | GLdouble nearVal = *((GLdouble*)(iter->args+ sizeof(GLdouble)*4)); 119 | GLdouble farVal = *((GLdouble*)(iter->args+ sizeof(GLdouble)*5)); 120 | 121 | //LOG("glOrtho values %lf %lf %lf %lf %lf %lf\n", left, right, bottom, top, nearVal, farVal); 122 | 123 | GLdouble totalWidth = right - left; 124 | GLdouble singleWidth = totalWidth * (gConfig->screenWidth / gConfig->totalWidth); 125 | GLdouble bezelWidth = totalWidth * (gConfig->screenGap / gConfig->totalWidth); 126 | 127 | GLdouble startingPoint = left + (displayNumber * (singleWidth + bezelWidth)); 128 | 129 | //if ratio is correct, do nothing 130 | if(right/bottom == (double)gConfig->sizeX/gConfig->sizeY || 131 | right/top == (double)gConfig->sizeX/gConfig->sizeY){ 132 | glOrtho(startingPoint, 133 | startingPoint + singleWidth, 134 | bottom, 135 | top, 136 | nearVal, 137 | farVal); 138 | } 139 | 140 | //if ratio incorrect, adjust so things dont get stretched 141 | else{ 142 | if(bottom > 0){ 143 | glOrtho(startingPoint, 144 | startingPoint + singleWidth, 145 | right * gConfig->totalHeight/gConfig->totalWidth, 146 | top, 147 | nearVal, 148 | farVal); 149 | }else{ 150 | glOrtho(startingPoint, 151 | startingPoint + singleWidth, 152 | bottom, 153 | right * gConfig->totalHeight/gConfig->totalWidth, 154 | nearVal, 155 | farVal); 156 | 157 | } 158 | } 159 | 160 | /* 161 | else { 162 | //if ratio is correct, do nothing 163 | if(right/bottom == (double) sizeX/sizeY || right/top == (double) sizeX/sizeY) 164 | glOrtho(left, right, bottom, top, nearVal, farVal); 165 | else { //if ratio incorrect, adjust so things dont get stretched 166 | if(bottom > 0) glOrtho(left, right, right * sizeY/sizeX, top, nearVal, farVal); 167 | else glOrtho(left, right ,bottom, right * sizeY/sizeX, nearVal, farVal); 168 | } 169 | } 170 | */ 171 | 172 | LOG("handleOrtho\n"); 173 | } 174 | 175 | void handlePerspective(Instruction *iter){ 176 | 177 | if(!glFrustumUsage) { 178 | #ifdef __APPLE__ 179 | LOG("**** WANTED TO CALL gluPerspective\n"); 180 | #else 181 | gluPerspective(45.0,8880.0/4560.0, 0.9f, 100.0f); 182 | #endif 183 | return; 184 | } 185 | 186 | //read original values from the instruction 187 | GLdouble fovy = *((GLdouble*)iter->args); 188 | GLdouble aspect = *((GLdouble*)(iter->args+ sizeof(GLdouble))); 189 | GLdouble zNear = *((GLdouble*)(iter->args+ sizeof(GLdouble)*2)); 190 | GLdouble zFar = *((GLdouble*)(iter->args+ sizeof(GLdouble)*3)); 191 | 192 | //LOG("gluPerspective values %lf %lf %lf %lf\n", fovy, aspect, zNear, zFar); 193 | 194 | /* diagram to explain how frustum works (without bezels, ignoring fov) 195 | (-1,-1) (-0.6,-1) (-0.2,-1) (0.2,-1) (0.6,-1) (1,-1) 196 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 197 | |---------||---------||---------||---------||---------| 198 | |---------||---------||---------||---------||---------| 199 | |---------||---------||---------||---------||---------| 200 | |---------||---------||---------||---------||---------| 201 | |---------||---------||---------||---------||---------| 202 | |---------||---------||---------||---------||---------| 203 | |---------||---------||---------||---------||---------| 204 | |---------||---------||---------||---------||---------| 205 | |---------||---------||---------||---------||---------| 206 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 207 | (-1,1) (1,1) 208 | */ 209 | 210 | const GLdouble pi = 3.1415926535897932384626433832795; 211 | GLdouble fW, fH; 212 | 213 | //calculate height, then adjust according to how different the 214 | //programs aspect ratio and our ratio is 215 | //fW and fH are the equivalent glFrustum calculations using the gluPerspective values 216 | fH = tan( (fovy / 360.0) * pi ) * gConfig->scaleY * zNear * 217 | (1.0/((gConfig->totalWidth/gConfig->totalHeight) / aspect)); 218 | fW = tan( (fovy / 360.0) * pi ) * gConfig->scaleX * zNear * aspect; 219 | 220 | GLdouble totalWidth = fW * 2; 221 | GLdouble singleWidth = totalWidth * (gConfig->screenWidth / gConfig->totalWidth); 222 | GLdouble bezelWidth = totalWidth * (gConfig->screenGap / gConfig->totalWidth); 223 | if(!bezelCompensation) { 224 | singleWidth = totalWidth * ((gConfig->screenWidth + gConfig->screenGap) / gConfig->totalWidth); 225 | bezelWidth = 0; 226 | } 227 | GLdouble startingPoint = -fW + (displayNumber * (singleWidth + bezelWidth)); 228 | 229 | glFrustum(startingPoint, startingPoint + singleWidth, -fH, fH, zNear, zFar); 230 | 231 | /* 232 | else { 233 | fH = tan( (fovy / 360.0) * pi ) * scaleY * zNear * (1.0/((sizeX * 1.0/sizeY) / aspect)); 234 | fW = tan( (fovy / 360.0) * pi ) * scaleX * zNear * aspect; 235 | 236 | glFrustum(-fW, fW, -fH, fH, zNear, zFar); 237 | 238 | //gluPerspective(fovy, aspect, zNear, zFar); 239 | } 240 | */ 241 | 242 | LOG("handlePerspective\n"); 243 | } 244 | 245 | void handleLoadMatrix(Instruction *iter){ 246 | GLfloat * m = (GLfloat *)iter->buffers[0].buffer; 247 | GLfloat * mSaved = (GLfloat *) malloc(sizeof(GLfloat) * 16); 248 | //copy matrix, otherwise CGLRepeat buffers doesn't work 249 | memcpy(mSaved, m, sizeof(GLfloat) * 16); 250 | if(currentMode == GL_PROJECTION) { 251 | //if(symphony) { 252 | //m[0]= (whatever is is when we are given it) * (proportion that will be seen_ 253 | mSaved[0]= mSaved[0] * (5/((gConfig->screenWidth * 5)/gConfig->totalWidth)); 254 | //m[8] = (left + right)/(left-right) + screenOffset * bezel (from API) 255 | mSaved[8]= -(2-(2*gConfig->screenWidth/gConfig->totalWidth))/ 256 | (2*gConfig->screenWidth/gConfig->totalWidth) 257 | + displayNumber * (2 * gConfig->totalWidth/(gConfig->screenWidth * 5)); 258 | //} 259 | glLoadMatrixf(mSaved); 260 | free(mSaved); 261 | } 262 | else { 263 | glLoadMatrixf(m); 264 | } 265 | 266 | LOG("handleLoadMatrix\n"); 267 | } 268 | 269 | -------------------------------------------------------------------------------- /src/include/lru_cache.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2004-2011 by Patrick Audley * 3 | * paudley@blackcat.ca * 4 | * http://patrickaudley.com * 5 | * * 6 | ***************************************************************************/ 7 | /** 8 | * @file lru_cache.h Template cache with an LRU removal policy 9 | * @author Patrick Audley 10 | * @version 1.3 11 | * @date May 2011 12 | * @par 13 | * This cache is thread safe if compiled with _REENTRANT defined. It 14 | * uses the BOOST scientific computing library to provide the thread safety 15 | * mutexes. 16 | * 17 | * @par 18 | * Thanks to graydon@pobox.com for the size counting functor. 19 | * 20 | */ 21 | /** 22 | * @mainpage LRU Cache 23 | * 24 | * @section intro_section Introduction 25 | * 26 | * Fast, thread safe C++ template with Least Recently Used (LRU) 27 | * removal semantics. Complete with a comprehensive unit test 28 | * suite. Threading features require the BOOST scientific library to be 29 | * installed. 30 | * 31 | * @section usage_section Usage 32 | * 33 | * An LRU cache is a fixed size cache that discards the oldest (least 34 | * recently accessed) elements after it fills up. It's ideally 35 | * suited to be used in situations where you need to speed up access to 36 | * slower data sources (databases, synthetic structures, etc.). Below is 37 | * a simple example of using it to cache strings using integer keys. 38 | * 39 | * @section also_section See Also 40 | * 41 | * See: LRU Cache 42 | * 43 | * @example lru_example.cpp 44 | */ 45 | #include 46 | 47 | #include 48 | #include 49 | #include 50 | #ifdef _REENTRANT 51 | #include 52 | /// If we are reentrant then use a BOOST scoped mutex where neccessary. 53 | #define SCOPED_MUTEX boost::mutex::scoped_lock lock(this->_mutex); 54 | #else 55 | /// If we aren't reentrant then don't do anything. 56 | #define SCOPED_MUTEX 57 | #endif 58 | 59 | template < class T > 60 | struct Countfn { 61 | unsigned long operator()( const T &x ) { return 1; } 62 | }; 63 | 64 | 65 | /** 66 | * @brief Template cache with an LRU removal policy. 67 | * @class LRUCache 68 | * 69 | * @par 70 | * This template creats a simple collection of key-value pairs that grows 71 | * until the size specified at construction is reached and then begins 72 | * discard the Least Recently Used element on each insertion. 73 | * 74 | */ 75 | template< class Key, class Data, class Sizefn = Countfn< Data > > class LRUCache { 76 | public: 77 | typedef std::list< std::pair< Key, Data > > List; ///< Main cache storage typedef 78 | typedef typename List::iterator List_Iter; ///< Main cache iterator 79 | typedef typename List::const_iterator List_cIter; ///< Main cache iterator (const) 80 | typedef std::vector< Key > Key_List; ///< List of keys 81 | typedef typename Key_List::iterator Key_List_Iter; ///< Main cache iterator 82 | typedef typename Key_List::const_iterator Key_List_cIter; ///< Main cache iterator (const) 83 | typedef std::map< Key, List_Iter > Map; ///< Index typedef 84 | typedef std::pair< Key, List_Iter > Pair; ///< Pair of Map elements 85 | typedef typename Map::iterator Map_Iter; ///< Index iterator 86 | typedef typename Map::const_iterator Map_cIter; ///< Index iterator (const) 87 | 88 | private: 89 | List _list; ///< Main cache storage 90 | Map _index; ///< Cache storage index 91 | unsigned long _max_size; ///< Maximum abstract size of the cache 92 | unsigned long _curr_size; ///< Current abstract size of the cache 93 | 94 | #ifdef _REENTRANT 95 | boost::mutex _mutex; 96 | #endif 97 | 98 | public: 99 | 100 | /** @brief Creates a cache that holds at most Size worth of elements. 101 | * @param Size maximum size of cache 102 | */ 103 | LRUCache( const unsigned long Size ) : 104 | _max_size( Size ), 105 | _curr_size( 0 ) 106 | {} 107 | 108 | /// Destructor - cleans up both index and storage 109 | ~LRUCache() { clear(); } 110 | 111 | /** @brief Gets the current abstract size of the cache. 112 | * @return current size 113 | */ 114 | inline unsigned long size( void ) const { return _curr_size; } 115 | 116 | /** @brief Gets the maximum sbstract size of the cache. 117 | * @return maximum size 118 | */ 119 | inline unsigned long max_size( void ) const { return _max_size; } 120 | 121 | /// Clears all storage and indices. 122 | void clear( void ) { 123 | SCOPED_MUTEX; 124 | _list.clear(); 125 | _index.clear(); 126 | }; 127 | 128 | /** @brief Checks for the existance of a key in the cache. 129 | * @param key to check for 130 | * @return bool indicating whether or not the key was found. 131 | */ 132 | #ifdef _REENTRANT 133 | inline bool exists( const Key &key ) { 134 | SCOPED_MUTEX; 135 | #else 136 | inline bool exists( const Key &key ) const { 137 | #endif 138 | return _index.find( key ) != _index.end(); 139 | } 140 | 141 | /** @brief Removes a key-data pair from the cache. 142 | * @param key to be removed 143 | */ 144 | inline void remove( const Key &key ) { 145 | #ifdef _REENTRANT 146 | SCOPED_MUTEX; 147 | #endif 148 | Map_Iter miter = _index.find( key ); 149 | if( miter == _index.end() ) return; 150 | _remove( miter ); 151 | } 152 | 153 | /** @brief Touches a key in the Cache and makes it the most recently used. 154 | * @param key to be touched 155 | */ 156 | inline void touch( const Key &key ) { 157 | SCOPED_MUTEX; 158 | _touch( key ); 159 | } 160 | 161 | /** @brief Fetches a pointer to cache data. 162 | * @param key to fetch data for 163 | * @param touch whether or not to touch the data 164 | * @return pointer to data or NULL on error 165 | */ 166 | inline Data *fetch_ptr( const Key &key, bool touch = true ) { 167 | SCOPED_MUTEX; 168 | Map_Iter miter = _index.find( key ); 169 | if( miter == _index.end() ) return NULL; 170 | _touch( key ); 171 | return &(miter->second->second); 172 | } 173 | 174 | /** @brief Fetches a copy of cached data. 175 | * @param key to fetch data for 176 | * @param touch_data whether or not to touch the data 177 | * @return copy of the data or an empty Data object if not found 178 | */ 179 | inline Data fetch( const Key &key, bool touch_data = true ) { 180 | SCOPED_MUTEX; 181 | Map_Iter miter = _index.find( key ); 182 | if( miter == _index.end() ) 183 | return Data(); 184 | Data tmp = miter->second->second; 185 | if( touch_data ) 186 | _touch( key ); 187 | return tmp; 188 | } 189 | 190 | /** @brief Fetches a pointer to cache data. 191 | * @param key to fetch data for 192 | * @param data to fetch data into 193 | * @param touch_data whether or not to touch the data 194 | * @return whether or not data was filled in 195 | */ 196 | inline bool fetch( const Key &key, Data &data, bool touch_data = true ) { 197 | SCOPED_MUTEX; 198 | Map_Iter miter = _index.find( key ); 199 | if( miter == _index.end() ) return false; 200 | if( touch_data ) 201 | _touch( key ); 202 | data = miter->second->second; 203 | return true; 204 | } 205 | 206 | /** @brief Inserts a key-data pair into the cache and removes entries if neccessary. 207 | * @param key object key for insertion 208 | * @param data object data for insertion 209 | * @note This function checks key existance and touches the key if it already exists. 210 | */ 211 | inline void insert( const Key &key, const Data &data ) { 212 | SCOPED_MUTEX; 213 | // Touch the key, if it exists, then replace the content. 214 | Map_Iter miter = _touch( key ); 215 | if( miter != _index.end() ) 216 | _remove( miter ); 217 | 218 | // Ok, do the actual insert at the head of the list 219 | _list.push_front( std::make_pair( key, data ) ); 220 | List_Iter liter = _list.begin(); 221 | 222 | // Store the index 223 | _index.insert( std::make_pair( key, liter ) ); 224 | _curr_size += Sizefn()( data ); 225 | 226 | // Check to see if we need to remove an element due to exceeding max_size 227 | while( _curr_size > _max_size ) { 228 | // Remove the last element. 229 | liter = _list.end(); 230 | --liter; 231 | 232 | //LOG("Removed %d\n", liter->first); 233 | 234 | free(liter->second); 235 | 236 | _remove( liter->first ); 237 | 238 | } 239 | } 240 | 241 | /** @brief Get a list of keys. 242 | @return list of the current keys. 243 | */ 244 | inline const Key_List get_all_keys( void ) { 245 | SCOPED_MUTEX; 246 | Key_List ret; 247 | for( List_cIter liter = _list.begin(); liter != _list.end(); liter++ ) 248 | ret.push_back( liter->first ); 249 | return ret; 250 | } 251 | 252 | private: 253 | /** @brief Internal touch function. 254 | * @param key to be touched 255 | * @return a Map_Iter pointing to the key that was touched. 256 | */ 257 | inline Map_Iter _touch( const Key &key ) { 258 | Map_Iter miter = _index.find( key ); 259 | if( miter == _index.end() ) return miter; 260 | // Move the found node to the head of the list. 261 | _list.splice( _list.begin(), _list, miter->second ); 262 | return miter; 263 | } 264 | 265 | /** @brief Interal remove function 266 | * @param miter Map_Iter that points to the key to remove 267 | * @warning miter is now longer usable after being passed to this function. 268 | */ 269 | inline void _remove( const Map_Iter &miter ) { 270 | _curr_size -= Sizefn()( miter->second->second ); 271 | _list.erase( miter->second ); 272 | _index.erase( miter ); 273 | } 274 | 275 | /** @brief Interal remove function 276 | * @param key to remove 277 | */ 278 | inline void _remove( const Key &key ) { 279 | Map_Iter miter = _index.find( key ); 280 | _remove( miter ); 281 | } 282 | }; 283 | -------------------------------------------------------------------------------- /libcglinput/web/css/bootstrap-responsive.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Responsive v2.0.4 3 | * 4 | * Copyright 2012 Twitter, Inc 5 | * Licensed under the Apache License v2.0 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Designed and built with all the love in the world @twitter by @mdo and @fat. 9 | */.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:28px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}.hidden{display:none;visibility:hidden}.visible-phone{display:none!important}.visible-tablet{display:none!important}.hidden-desktop{display:none!important}@media(max-width:767px){.visible-phone{display:inherit!important}.hidden-phone{display:none!important}.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}}@media(min-width:768px) and (max-width:979px){.visible-tablet{display:inherit!important}.hidden-tablet{display:none!important}.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}}@media(max-width:480px){.nav-collapse{-webkit-transform:translate3d(0,0,0)}.page-header h1 small{display:block;line-height:18px}input[type="checkbox"],input[type="radio"]{border:1px solid #ccc}.form-horizontal .control-group>label{float:none;width:auto;padding-top:0;text-align:left}.form-horizontal .controls{margin-left:0}.form-horizontal .control-list{padding-top:0}.form-horizontal .form-actions{padding-right:10px;padding-left:10px}.modal{position:absolute;top:10px;right:10px;left:10px;width:auto;margin:0}.modal.fade.in{top:auto}.modal-header .close{padding:10px;margin:-10px}.carousel-caption{position:static}}@media(max-width:767px){body{padding-right:20px;padding-left:20px}.navbar-fixed-top,.navbar-fixed-bottom{margin-right:-20px;margin-left:-20px}.container-fluid{padding:0}.dl-horizontal dt{float:none;width:auto;clear:none;text-align:left}.dl-horizontal dd{margin-left:0}.container{width:auto}.row-fluid{width:100%}.row,.thumbnails{margin-left:0}[class*="span"],.row-fluid [class*="span"]{display:block;float:none;width:auto;margin-left:0}.input-large,.input-xlarge,.input-xxlarge,input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{display:block;width:100%;min-height:28px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}.input-prepend input,.input-append input,.input-prepend input[class*="span"],.input-append input[class*="span"]{display:inline-block;width:auto}}@media(min-width:768px) and (max-width:979px){.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;content:""}.row:after{clear:both}[class*="span"]{float:left;margin-left:20px}.container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:724px}.span12{width:724px}.span11{width:662px}.span10{width:600px}.span9{width:538px}.span8{width:476px}.span7{width:414px}.span6{width:352px}.span5{width:290px}.span4{width:228px}.span3{width:166px}.span2{width:104px}.span1{width:42px}.offset12{margin-left:764px}.offset11{margin-left:702px}.offset10{margin-left:640px}.offset9{margin-left:578px}.offset8{margin-left:516px}.offset7{margin-left:454px}.offset6{margin-left:392px}.offset5{margin-left:330px}.offset4{margin-left:268px}.offset3{margin-left:206px}.offset2{margin-left:144px}.offset1{margin-left:82px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:28px;margin-left:2.762430939%;*margin-left:2.709239449638298%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .span12{width:99.999999993%;*width:99.9468085036383%}.row-fluid .span11{width:91.436464082%;*width:91.38327259263829%}.row-fluid .span10{width:82.87292817100001%;*width:82.8197366816383%}.row-fluid .span9{width:74.30939226%;*width:74.25620077063829%}.row-fluid .span8{width:65.74585634900001%;*width:65.6926648596383%}.row-fluid .span7{width:57.182320438000005%;*width:57.129128948638304%}.row-fluid .span6{width:48.618784527%;*width:48.5655930376383%}.row-fluid .span5{width:40.055248616%;*width:40.0020571266383%}.row-fluid .span4{width:31.491712705%;*width:31.4385212156383%}.row-fluid .span3{width:22.928176794%;*width:22.874985304638297%}.row-fluid .span2{width:14.364640883%;*width:14.311449393638298%}.row-fluid .span1{width:5.801104972%;*width:5.747913482638298%}input,textarea,.uneditable-input{margin-left:0}input.span12,textarea.span12,.uneditable-input.span12{width:714px}input.span11,textarea.span11,.uneditable-input.span11{width:652px}input.span10,textarea.span10,.uneditable-input.span10{width:590px}input.span9,textarea.span9,.uneditable-input.span9{width:528px}input.span8,textarea.span8,.uneditable-input.span8{width:466px}input.span7,textarea.span7,.uneditable-input.span7{width:404px}input.span6,textarea.span6,.uneditable-input.span6{width:342px}input.span5,textarea.span5,.uneditable-input.span5{width:280px}input.span4,textarea.span4,.uneditable-input.span4{width:218px}input.span3,textarea.span3,.uneditable-input.span3{width:156px}input.span2,textarea.span2,.uneditable-input.span2{width:94px}input.span1,textarea.span1,.uneditable-input.span1{width:32px}}@media(min-width:1200px){.row{margin-left:-30px;*zoom:1}.row:before,.row:after{display:table;content:""}.row:after{clear:both}[class*="span"]{float:left;margin-left:30px}.container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:1170px}.span12{width:1170px}.span11{width:1070px}.span10{width:970px}.span9{width:870px}.span8{width:770px}.span7{width:670px}.span6{width:570px}.span5{width:470px}.span4{width:370px}.span3{width:270px}.span2{width:170px}.span1{width:70px}.offset12{margin-left:1230px}.offset11{margin-left:1130px}.offset10{margin-left:1030px}.offset9{margin-left:930px}.offset8{margin-left:830px}.offset7{margin-left:730px}.offset6{margin-left:630px}.offset5{margin-left:530px}.offset4{margin-left:430px}.offset3{margin-left:330px}.offset2{margin-left:230px}.offset1{margin-left:130px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:28px;margin-left:2.564102564%;*margin-left:2.510911074638298%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.45299145300001%;*width:91.3997999636383%}.row-fluid .span10{width:82.905982906%;*width:82.8527914166383%}.row-fluid .span9{width:74.358974359%;*width:74.30578286963829%}.row-fluid .span8{width:65.81196581200001%;*width:65.7587743226383%}.row-fluid .span7{width:57.264957265%;*width:57.2117657756383%}.row-fluid .span6{width:48.717948718%;*width:48.6647572286383%}.row-fluid .span5{width:40.170940171000005%;*width:40.117748681638304%}.row-fluid .span4{width:31.623931624%;*width:31.5707401346383%}.row-fluid .span3{width:23.076923077%;*width:23.0237315876383%}.row-fluid .span2{width:14.529914530000001%;*width:14.4767230406383%}.row-fluid .span1{width:5.982905983%;*width:5.929714493638298%}input,textarea,.uneditable-input{margin-left:0}input.span12,textarea.span12,.uneditable-input.span12{width:1160px}input.span11,textarea.span11,.uneditable-input.span11{width:1060px}input.span10,textarea.span10,.uneditable-input.span10{width:960px}input.span9,textarea.span9,.uneditable-input.span9{width:860px}input.span8,textarea.span8,.uneditable-input.span8{width:760px}input.span7,textarea.span7,.uneditable-input.span7{width:660px}input.span6,textarea.span6,.uneditable-input.span6{width:560px}input.span5,textarea.span5,.uneditable-input.span5{width:460px}input.span4,textarea.span4,.uneditable-input.span4{width:360px}input.span3,textarea.span3,.uneditable-input.span3{width:260px}input.span2,textarea.span2,.uneditable-input.span2{width:160px}input.span1,textarea.span1,.uneditable-input.span1{width:60px}.thumbnails{margin-left:-30px}.thumbnails>li{margin-left:30px}.row-fluid .thumbnails{margin-left:0}}@media(max-width:979px){body{padding-top:0}.navbar-fixed-top,.navbar-fixed-bottom{position:static}.navbar-fixed-top{margin-bottom:18px}.navbar-fixed-bottom{margin-top:18px}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding:5px}.navbar .container{width:auto;padding:0}.navbar .brand{padding-right:10px;padding-left:10px;margin:0 0 0 -5px}.nav-collapse{clear:both}.nav-collapse .nav{float:none;margin:0 0 9px}.nav-collapse .nav>li{float:none}.nav-collapse .nav>li>a{margin-bottom:2px}.nav-collapse .nav>.divider-vertical{display:none}.nav-collapse .nav .nav-header{color:#999;text-shadow:none}.nav-collapse .nav>li>a,.nav-collapse .dropdown-menu a{padding:6px 15px;font-weight:bold;color:#999;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.nav-collapse .btn{padding:4px 10px 4px;font-weight:normal;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.nav-collapse .dropdown-menu li+li a{margin-bottom:2px}.nav-collapse .nav>li>a:hover,.nav-collapse .dropdown-menu a:hover{background-color:#222}.nav-collapse.in .btn-group{padding:0;margin-top:5px}.nav-collapse .dropdown-menu{position:static;top:auto;left:auto;display:block;float:none;max-width:none;padding:0;margin:0 15px;background-color:transparent;border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.nav-collapse .dropdown-menu:before,.nav-collapse .dropdown-menu:after{display:none}.nav-collapse .dropdown-menu .divider{display:none}.nav-collapse .navbar-form,.nav-collapse .navbar-search{float:none;padding:9px 15px;margin:9px 0;border-top:1px solid #222;border-bottom:1px solid #222;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1)}.navbar .nav-collapse .nav.pull-right{float:none;margin-left:0}.nav-collapse,.nav-collapse.collapse{height:0;overflow:hidden}.navbar .btn-navbar{display:block}.navbar-static .navbar-inner{padding-right:10px;padding-left:10px}}@media(min-width:980px){.nav-collapse.collapse{height:auto!important;overflow:visible!important}} 10 | --------------------------------------------------------------------------------