PointSampleRenderer.cpp

Go to the documentation of this file.
00001 /**<!-------------------------------------------------------------------->
00002    @file   PointSampleRenderer.cpp
00003    @author Travis Fischer (fisch0920@gmail.com)
00004    @author Matthew Jacobs (jacobs.mh@gmail.com)
00005    @date   Fall 2008
00006    
00007    @brief
00008       Abstraction of renderers which construct their output by point sampling 
00009    a 2D domain (the film plane). The steps of generating point 
00010    samples across this domain (SampleGenerator), evaluating the samples 
00011    (PointSampleRenderer/SampleConsumer), and storing/using the evaluated 
00012    samples (RenderOutput) have been abstracted from each other.
00013    <!-------------------------------------------------------------------->**/
00014 
00015 #include "PointSampleRenderer.h"
00016 #include "RenderOutput.h"
00017 
00018 #include <generators.h>
00019 #include <QtCore>
00020 using namespace std;
00021 
00022 void PointSampleRenderer::render() {
00023    if (!m_initted)
00024       init();
00025    
00026    QMutexLocker lock(&m_renderMutex);
00027    m_output->init();
00028    
00029    // parse parameters
00030    unsigned noConsumers = getValue<unsigned>("noRenderThreads", 1);
00031    ASSERT(noConsumers > 0);
00032    
00033    // initialize timer to begin counting
00034    m_timer.reset();
00035    
00036    cout << endl;
00037    cout << "rendering with " << noConsumers << 
00038       (noConsumers == 1 ? " thread" : " threads") << endl;
00039    
00040    // create and start sample generator
00041    SampleGeneratorThread *generator = _getGenerator();
00042    generator->init();
00043    generator->start();
00044    
00045    // create and start sample consumers (render threads)
00046    SampleConsumerList consumers;
00047    
00048    for(unsigned i = noConsumers; i--;) {
00049       SampleConsumer *consumer = _getConsumer();
00050       consumers.push_back(consumer);
00051       
00052       consumer->init();
00053       consumer->start();
00054    }
00055    
00056    //cout << "waiting on generator" << endl;
00057    
00058    // join with generator thread (wait until it has completed execution)
00059    while(!generator->wait());
00060    safeDelete(generator);
00061    
00062    // join with consumer threads (wait until they have all completed execution)
00063    for(unsigned i = noConsumers; i--;) {
00064       SampleConsumer *consumer = consumers[i];
00065       
00066       //cout << "waiting on consumer " << (noConsumers - i) << " / " << noConsumers << endl;
00067       while(!consumer->wait());
00068       
00069       safeDelete(consumer);
00070    }
00071    
00072    m_output->finalize();
00073    finalize();
00074    
00075    cout << endl << "done rendering in " << getElapsedTime() << endl << endl;
00076 }
00077 
00078 void PointSampleRenderer::finalize()
00079 { }
00080 
00081 void PointSampleRenderer::addSharedSample(const PointSample &s) {
00082    QMutexLocker lock(&m_mutex);
00083    ASSERT(m_noProducers > 0);
00084    
00085    while(m_sharedShamples.size() > MAX_SHARED_SAMPLES_SIZE)
00086       m_producer.wait(&m_mutex);
00087    
00088    m_sharedShamples.push_back(s);
00089    
00090    m_consumer.wakeOne();
00091 }
00092 
00093 void PointSampleRenderer::addSharedSamples(const PointSampleList &s) {
00094    QMutexLocker lock(&m_mutex);
00095    ASSERT(m_noProducers > 0);
00096    
00097    while(m_sharedShamples.size() >= MAX_SHARED_SAMPLES_SIZE)
00098       m_producer.wait(&m_mutex);
00099    
00100    FOREACH(PointSampleListConstIter, s, iter) {
00101       m_sharedShamples.push_back(*iter);
00102    }
00103    
00104    m_consumer.wakeAll();
00105 }
00106 
00107 bool PointSampleRenderer::getSharedSample(PointSample &outSample) {
00108    QMutexLocker lock(&m_mutex);
00109    
00110    while(m_sharedShamples.size() == 0) {
00111       if (m_sharedShamples.empty() && !m_noProducers)
00112          return false;
00113       
00114       m_consumer.wait(&m_mutex);
00115    }
00116    
00117    outSample = m_sharedShamples.front();
00118    m_sharedShamples.pop_front();
00119    
00120    m_producer.wakeAll();
00121    
00122    return true;
00123 }
00124 
00125 void PointSampleRenderer::addProducer() {
00126    QMutexLocker lock(&m_mutex);
00127    
00128    ++m_noProducers;
00129 }
00130 
00131 void PointSampleRenderer::removeProducer() {
00132    QMutexLocker lock(&m_mutex);
00133    
00134    ASSERT(0 < m_noProducers);
00135    
00136    if (0 == --m_noProducers) // completely done with sample generation
00137       m_consumer.wakeAll();
00138 }
00139 
00140 SampleGeneratorThread *PointSampleRenderer::_getGenerator() {
00141    const std::string &generator = getValue<std::string>("generator", 
00142                                                         std::string("default"));
00143    SampleGeneratorThread *sampleGenerator = 
00144       SampleGeneratorThread::create(generator);
00145    
00146    sampleGenerator->inherit(*this);
00147    sampleGenerator->setRenderer(this);
00148    sampleGenerator->setViewport(m_output->getViewport());
00149    
00150    return sampleGenerator;
00151 }
00152 
00153 SampleConsumer  *PointSampleRenderer::_getConsumer() {
00154    // TODO: consider making this customizable via parameters?
00155    
00156    return new SampleConsumer(this);
00157 }
00158 

Generated on 28 Feb 2009 for Milton by doxygen 1.5.6