/* -*- C++ -*- * Copyright ©2004 Hugo Mills * * This software is distributed under the terms of the GNU GPL v3 * For more information on the GPL, see the file COPYING or * visit http://www.gnu.org/ * * This software is distributed without warranty */ #include "magellan/configuration.h" #include "magellan/options.h" #include "rendercontext.h" #ifdef HAVE_BOOST_THREAD #include "renderer.h" #endif class DeleterMap { public: DeleterMap() { } template void operator()(T ob) { ob.second->destroy(); } }; class DeleterList { public: DeleterList() { } template void operator()(T ob) { ob->destroy(); } }; class DeleterListNormal { public: DeleterListNormal() { } template void operator()(T ob) { delete ob; } }; Configuration::~Configuration() { _output->destroy(); for_each(orbits.begin(), orbits.end(), DeleterMap()); for_each(content.begin(), content.end(), DeleterMap()); for_each(maps.begin(), maps.end(), DeleterMap()); for_each(viewports.begin(), viewports.end(), DeleterMap()); for_each(displays.begin(), displays.end(), DeleterList()); #ifdef HAVE_BOOST_THREAD for_each(contexts.begin(), contexts.end(), DeleterListNormal()); #endif } void Configuration::update(void) { for(std::map::iterator it = orbits.begin(); it != orbits.end(); ++it) { it->second->reset(); } } void Configuration::render(void) { if(opts->debug_render() >= 1) std::cerr << "Rendering started" << std::endl; #ifdef HAVE_BOOST_THREAD std::set renderers; std::set threads; currentcontext = contexts.begin(); // Barrier to wait for all threads to complete jobcompletion = new boost::barrier(max_threads+1); // Create the threads for(int i = 0; i < max_threads; i++) { Renderer* t = new Renderer(this, _output, jobcompletion); renderers.insert(t); boost::thread* thr = new boost::thread(*t); threads.insert(thr); if(opts->debug_render() >= 1) { std::cerr << "Rendering thread " << i << " created at " << t << std::endl; } } // Wait for thread termination jobcompletion->wait(); for(std::set::iterator it = renderers.begin(); it != renderers.end(); it++) { delete *it; } for(std::set::iterator it = threads.begin(); it != threads.end(); it++) { delete *it; } delete jobcompletion; #else for(std::list::iterator disp = displays.begin(); disp != displays.end(); disp++) { if(opts->debug_render() >= 2) std::cerr << " Rendering from " << *disp << std::endl; (*disp)->plot(_output, (*disp)->getviewport()); } #endif if(opts->debug_render() >= 1) std::cerr << "Rendering finished" << std::endl; } void Configuration::output(void) { _output->commit(); } RenderContext* Configuration::nextcontext(void) { #ifdef HAVE_BOOST_THREAD boost::mutex::scoped_lock _lock(contextlock); if(currentcontext == contexts.end()) return NULL; return *(currentcontext++); #endif } /* Methods to get the different types of plugin */ XfView* Configuration::getviewport(const std::string& name) const { std::map::const_iterator rv = viewports.find(name); if(rv == viewports.end()) return NULL; return rv->second; } XfMap* Configuration::getprojection(const std::string& name) const { std::map::const_iterator rv = maps.find(name); if(rv == maps.end()) return NULL; return rv->second; } XfOrbit* Configuration::getorbit(const std::string& name) const { std::map::const_iterator rv = orbits.find(name); if(rv == orbits.end()) return NULL; return rv->second; } Content* Configuration::getcontent(const std::string& name) const { std::map::const_iterator rv = content.find(name); if(rv == content.end()) { std::cerr << "Content object " << name << " not found" << std::endl; return NULL; } return rv->second; } /* Template specialisations for the different types of plugin */ template <> XfOrbit* Configuration::getplugin(const std::string& s) const { return getorbit(s); } template <> XfMap* Configuration::getplugin(const std::string& s) const { return getprojection(s); } template <> XfView* Configuration::getplugin(const std::string& s) const { return getviewport(s); } template <> Content* Configuration::getplugin(const std::string& s) const { return getcontent(s); }