conductor.C

00001 /*
00002  * This file is part of the "Archon" framework.
00003  * (http://files3d.sourceforge.net)
00004  *
00005  * Copyright © 2002 by Kristian Spangsege and Brian Kristiansen.
00006  *
00007  * Permission to use, copy, modify, and distribute this software and
00008  * its documentation under the terms of the GNU General Public License is
00009  * hereby granted. No representations are made about the suitability of
00010  * this software for any purpose. It is provided "as is" without express
00011  * or implied warranty. See the GNU General Public License
00012  * (http://www.gnu.org/copyleft/gpl.html) for more details.
00013  *
00014  * The characters in this file are ISO8859-1 encoded.
00015  *
00016  * The documentation in this file is in "Doxygen" style
00017  * (http://www.doxygen.org).
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       // Clear all windows
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       // Proceed slave threads
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       // Render
00086       masterPipe->render();
00087 
00088       // Sync with slave threads
00089       {
00090         Mutex::Lock l(syncMutex);
00091         while(unfinishedSlaves) slaveFinished.wait();
00092       }
00093 
00094       // Swap all buffers
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 }

Generated on Sun Jul 30 22:55:43 2006 for Archon by  doxygen 1.4.4