#ifndef _MT_RENDERER_H_ #define _MT_RENDERER_H_ #include #include #include #include #include #include "GLOutput.h" #include "Renderer.h" #include "options.h" /* multithreaded renderer by Hannes Volk, with corrections and comments by Sven Zühlsdorf */ /*v1.1*/ class MTRenderer : public Renderer { public: int threadNo; #if !SILENT int *finished; #endif MTRenderer(const Scene *scene, Image *image) : Renderer(scene, image) {} static void *RenderThreaded(void *arguments) { MTRenderer *a = (MTRenderer *) arguments; int thread = a->threadNo++; pthread_t pth; if(thread < THREADS - 1) { pthread_create(&pth, NULL, &MTRenderer::RenderThreaded, arguments); } for(int j = thread; j < a->image->GetHeight(); j += THREADS) { for(int i = 0; i < a->image->GetWidth(); i++) { a->image->SetPixel(i, j, a->RenderPixel((float) i, (float) j)); #if !SILENT && PROGRESS_PER_PIXEL a->update_progress(thread); #endif } #if !SILENT && !PROGRESS_PER_PIXEL a->update_progress(thread); #endif } if(thread < THREADS - 1) {pthread_join(pth, NULL);} return NULL; } void Render() { MTRenderer *args = this; args->threadNo = 0; //args->renderer = this; #if !SILENT args->finished = (int *) malloc(THREADS * sizeof(int)); for(int n = 0; n < THREADS; n++) {args->finished[n] = 0;} std::cout << std::endl; /* we would overwrite the line above our finished line without this */ #endif MTRenderer::RenderThreaded((void *) args); OutputCostImage(); } private: #if !SILENT inline void update_progress(int thread) const { this->finished[thread]++; GLOutput::getInstance()->setUpdated(); if(!thread) /* only the first thread does output */ { float progress = 0; for(int n = 0; n < THREADS; n++) {progress += this->finished[n];} progress /= (float) image->GetHeight(); #if PROGRESS_PER_PIXEL progress /= (float) image->GetWidth(); #endif /* info about the escape codes: http://en.wikipedia.org/wiki/ANSI_escape_sequence#CSI_Codes */ //std::cout << "\e[A\e[1G\e[2Kfinished " << progress * 100.f << "%" << std::endl; } } #endif }; #endif