00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <GL/gl.h>
00021
00022 #include <archon/util/thread.H>
00023
00024 #include <archon/render/context.H>
00025
00026 #include <archon/render/conductor.H>
00027
00028 namespace Archon
00029 {
00030 namespace Render
00031 {
00032 Conductor::Conductor():
00033 unfinishedSlaves(0), proceed(syncMutex), slaveFinished(syncMutex)
00034 {
00035 }
00036
00037 Ref<Pipe> Conductor::addPipe(Ref<Display::Visual> visual,
00038 bool direct)
00039 {
00040 Ref<Pipe> pipe;
00041 Ref<Thread> thread;
00042 {
00043 Mutex::Lock l(syncMutex);
00044 pipe = new Pipe(visual, direct, masterPipe);
00045 if(masterPipe)
00046 {
00047 thread =
00048 Thread::run<Conductor, unsigned>(this, &Conductor::slaveThread,
00049 slaves.size(), false);
00050 slaves.push_back(Slave(pipe, thread));
00051 }
00052 else masterPipe = pipe;
00053 }
00054 if(thread) Thread::start(thread);
00055 return pipe;
00056 }
00057
00058 void Conductor::addWindow(Ref<Display::Window> d, Ref<Pipe> p)
00059 {
00060 Mutex::Lock l(syncMutex);
00061 for(unsigned i=0; i<windows.size(); ++i)
00062 if(windows[i].first == d) return;
00063 windows.push_back(make_pair(d, p));
00064 }
00065
00066 void Conductor::render()
00067 {
00068
00069 for(unsigned i=0; i<windows.size(); ++i)
00070 {
00071 pair<Ref<Display::Window>, Ref<Pipe> > &p = windows[i];
00072 Display::Bind b(p.second->context, p.first);
00073 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00074 }
00075
00076
00077 {
00078 Mutex::Lock l(syncMutex);
00079 for(unsigned i=0; i<slaves.size(); ++i)
00080 slaves[i].hold = false;
00081 unfinishedSlaves = slaves.size();
00082 }
00083 proceed.notifyAll();
00084
00085
00086 masterPipe->render();
00087
00088
00089 {
00090 Mutex::Lock l(syncMutex);
00091 while(unfinishedSlaves) slaveFinished.wait();
00092 }
00093
00094
00095 for(unsigned i=0; i<windows.size(); ++i)
00096 windows[i].first->swapBuffers();
00097 }
00098
00099 void Conductor::slaveThread(unsigned index)
00100 {
00101 Ref<Pipe> pipe;
00102 {
00103 Mutex::Lock l(syncMutex);
00104 pipe = slaves[index].pipe;
00105 }
00106
00107 for(;;)
00108 {
00109 {
00110 Mutex::Lock l(syncMutex);
00111 while(slaves[index].hold) proceed.wait();
00112 slaves[index].hold = true;
00113 }
00114
00115 pipe->render();
00116
00117 {
00118 Mutex::Lock l(syncMutex);
00119 --unfinishedSlaves;
00120 }
00121 slaveFinished.notifyAll();
00122 }
00123 }
00124
00125 Conductor::Slave::Slave(Ref<Pipe> pipe, Ref<Thread> thread):
00126 pipe(pipe), thread(thread), hold(true)
00127 {
00128 }
00129
00130 void Conductor::terminate()
00131 {
00132 Mutex::Lock l(syncMutex);
00133 for(unsigned i=0; i<slaves.size(); ++i)
00134 slaves[i].thread->terminate();
00135 }
00136 }
00137 }