bool InitSystem(void) { setlocale(LC_ALL, ""); systemData.locale = QLocale::system(); systemData.locale.setNumberOptions(QLocale::OmitGroupSeparator); QLocale::setDefault(systemData.locale); QTextStream out(stdout); systemData.homedir = QDir::homePath() + QDir::separator(); #ifdef WIN32 /* WINDOWS */ systemData.sharedDir = (QDir::currentPath() + QDir::separator()); #else systemData.sharedDir = QString(SHARED_DIR) + QDir::separator(); #endif /* WINDOWS */ //logfile #ifdef WIN32 /* WINDOWS */ systemData.logfileName = systemData.homedir + "mandelbulber_log.txt"; #else systemData.logfileName = systemData.homedir + ".mandelbulber_log.txt"; #endif FILE *logfile = fopen(systemData.logfileName.toUtf8().constData(), "w"); fclose(logfile); out << "Mandelbulber " << MANDELBULBER_VERSION_STRING << ", build date: " << QString(__DATE__) << "\n"; out << "Log file name: " << systemData.logfileName << endl; WriteLogString("Mandelbulber version", QString(MANDELBULBER_VERSION_STRING)); WriteLogString("Mandelbulber compilation date", QString(__DATE__) + " " + QString(__TIME__)); //detecting number of CPU cores systemData.numberOfThreads = get_cpu_count(); //NR_THREADS = 1; printf("Detected %d CPUs\n", systemData.numberOfThreads); WriteLogDouble("CPUs detected", systemData.numberOfThreads); #ifdef ONETHREAD //for debugging NR_THREADS = 1; #endif //data directory location #ifdef WIN32 /* WINDOWS */ systemData.dataDirectory = systemData.homedir + "mandelbulber" + QDir::separator(); #else systemData.dataDirectory = systemData.homedir + ".mandelbulber" + QDir::separator(); #endif out << "Default data directory: " << systemData.dataDirectory << endl; WriteLogString("Default data directory", systemData.dataDirectory); systemData.thumbnailDir = systemData.dataDirectory + "thumbnails" + QDir::separator(); systemData.autosaveFile = systemData.dataDirectory + ".autosave.fract"; //*********** temporary set to false ************ systemData.noGui = false; systemData.lastSettingsFile = systemData.dataDirectory + "settings" + QDir::separator() + QString("settings.fract"); systemData.lastImageFile = systemData.dataDirectory + "images" + QDir::separator() + QString("image.jpg"); systemData.lastImagePaletteFile = systemData.sharedDir + "textures" + QDir::separator() + QString("colour palette.jpg"); QLocale systemLocale = QLocale::system(); systemData.decimalPoint = systemLocale.decimalPoint(); WriteLogString("Decimal point", QString(systemData.decimalPoint)); systemData.supportedLanguages.insert("en_EN", "English"); systemData.supportedLanguages.insert("pl_PL", "Polski"); systemData.supportedLanguages.insert("de_DE", "Deutsch"); systemData.supportedLanguages.insert("it_IT", "Italiano"); //get number of columns of console #ifdef WIN32 systemData.terminalWidth = 80; #else handle_winch(-1); #endif return true; }
bool cRenderer::RenderImage() { WriteLog("cRenderer::RenderImage()", 2); if (image->IsAllocated()) { image->SetImageParameters(params->imageAdjustments); int progressiveSteps; if (data->configuration.UseProgressive()) progressiveSteps = (int)(log((double)max(image->GetWidth(), image->GetHeight())) / log(2.0)) - 3; else progressiveSteps = 0; if (progressiveSteps < 0) progressiveSteps = 0; int progressive = pow(2.0, (double)progressiveSteps - 1); if (progressive == 0) progressive = 1; // prepare multiple threads QThread **thread = new QThread *[data->configuration.GetNumberOfThreads()]; cRenderWorker::sThreadData *threadData = new cRenderWorker::sThreadData[data->configuration.GetNumberOfThreads()]; cRenderWorker **worker = new cRenderWorker *[data->configuration.GetNumberOfThreads()]; if (scheduler) delete scheduler; scheduler = new cScheduler(image->GetHeight(), progressive); cProgressText progressText; progressText.ResetTimer(); for (int i = 0; i < data->configuration.GetNumberOfThreads(); i++) { threadData[i].id = i + 1; if (data->configuration.UseNetRender()) { if (i < data->netRenderStartingPositions.size()) { threadData[i].startLine = data->netRenderStartingPositions.at(i); } else { threadData[i].startLine = 0; qCritical() << "NetRender - Mising starting positions data"; } } else { threadData[i].startLine = (image->GetHeight() / data->configuration.GetNumberOfThreads()) * i / scheduler->GetProgressiveStep() * scheduler->GetProgressiveStep(); } threadData[i].scheduler = scheduler; } QString statusText; QString progressTxt; QElapsedTimer timerRefresh; timerRefresh.start(); qint64 lastRefreshTime = 0; QList<int> listToRefresh; QList<int> listToSend; QElapsedTimer timerProgressRefresh; timerProgressRefresh.start(); WriteLog("Start rendering", 2); do { WriteLogDouble("Progressive loop", scheduler->GetProgressiveStep(), 2); for (int i = 0; i < data->configuration.GetNumberOfThreads(); i++) { WriteLog(QString("Thread ") + QString::number(i) + " create", 3); thread[i] = new QThread; worker[i] = new cRenderWorker( params, fractal, &threadData[i], data, image); // Warning! not needed to delete object worker[i]->moveToThread(thread[i]); QObject::connect(thread[i], SIGNAL(started()), worker[i], SLOT(doWork())); QObject::connect(worker[i], SIGNAL(finished()), thread[i], SLOT(quit())); QObject::connect(worker[i], SIGNAL(finished()), worker[i], SLOT(deleteLater())); thread[i]->setObjectName("RenderWorker #" + QString::number(i)); thread[i]->start(); WriteLog(QString("Thread ") + QString::number(i) + " started", 3); } while (!scheduler->AllLinesDone()) { gApplication->processEvents(); if (*data->stopRequest || progressText.getTime() > data->configuration.GetMaxRenderTime() || systemData.globalStopRequest) { scheduler->Stop(); } Wait(10); // wait 10ms if (data->configuration.UseRefreshRenderedList()) { // get list of last rendered lines QList<int> list = scheduler->GetLastRenderedLines(); // create list of lines for image refresh listToRefresh += list; } // status bar and progress bar double percentDone = scheduler->PercentDone(); data->lastPercentage = percentDone; statusText = QObject::tr("Rendering image"); progressTxt = progressText.getText(percentDone); data->statistics.time = progressText.getTime(); if (timerProgressRefresh.elapsed() > 1000) { emit updateProgressAndStatus(statusText, progressTxt, percentDone); emit updateStatistics(data->statistics); timerProgressRefresh.restart(); } // refresh image if (listToRefresh.size() > 0) { if (timerRefresh.elapsed() > lastRefreshTime && (scheduler->GetProgressivePass() > 1 || !data->configuration.UseProgressive())) { timerRefresh.restart(); emit updateProgressAndStatus(statusText, progressTxt, percentDone); emit updateStatistics(data->statistics); QSet<int> set_listToRefresh = listToRefresh.toSet(); // removing duplicates listToRefresh = set_listToRefresh.toList(); qSort(listToRefresh); listToSend += listToRefresh; image->CompileImage(&listToRefresh); if (data->configuration.UseRenderTimeEffects()) { if (params->ambientOcclusionEnabled && params->ambientOcclusionMode == params::AOmodeScreenSpace) { cRenderSSAO rendererSSAO(params, data, image); rendererSSAO.setProgressive(scheduler->GetProgressiveStep()); rendererSSAO.RenderSSAO(&listToRefresh); } } image->ConvertTo8bit(); if (data->configuration.UseImageRefresh()) { image->UpdatePreview(&listToRefresh); image->GetImageWidget()->update(); } // sending rendered lines to NetRender server if (data->configuration.UseNetRender() && gNetRender->IsClient() && gNetRender->GetStatus() == CNetRender::netRender_WORKING) { // If ACK was already received, then server is ready to take new data. if (netRenderAckReceived) { QList<QByteArray> renderedLinesData; for (int i = 0; i < listToSend.size(); i++) { // avoid sending already rendered lines if (scheduler->IsLineDoneByServer(listToSend.at(i))) { listToSend.removeAt(i); i--; continue; } // creating data set to send QByteArray lineData; CreateLineData(listToSend.at(i), &lineData); renderedLinesData.append(lineData); } // sending data if (listToSend.size() > 0) { emit sendRenderedLines(listToSend, renderedLinesData); emit NotifyClientStatus(); netRenderAckReceived = false; listToSend.clear(); } } } if (data->configuration.UseNetRender() && gNetRender->IsServer()) { QList<int> toDoList = scheduler->CreateDoneList(); if (toDoList.size() > data->configuration.GetNumberOfThreads()) { for (int c = 0; c < gNetRender->GetClientCount(); c++) { emit SendToDoList(c, toDoList); } } } lastRefreshTime = timerRefresh.elapsed() * data->configuration.GetRefreshRate() / (listToRefresh.size()); if (lastRefreshTime < 100) lastRefreshTime = 100; // the shortest refresh time can be 100ms // do not refresh and send data too often if (data->configuration.UseNetRender()) { if (lastRefreshTime < 500) lastRefreshTime = 500; } timerRefresh.restart(); listToRefresh.clear(); } // timerRefresh } // isPreview } // while scheduler for (int i = 0; i < data->configuration.GetNumberOfThreads(); i++) { while (thread[i]->isRunning()) { gApplication->processEvents(); }; WriteLog(QString("Thread ") + QString::number(i) + " finished", 2); delete thread[i]; } } while (scheduler->ProgressiveNextStep()); // send last rendered lines if (data->configuration.UseNetRender() && gNetRender->IsClient() && gNetRender->GetStatus() == CNetRender::netRender_WORKING) { if (netRenderAckReceived) { QList<QByteArray> renderedLinesData; for (int i = 0; i < listToSend.size(); i++) { // avoid sending already rendered lines if (scheduler->IsLineDoneByServer(listToSend.at(i))) { listToSend.removeAt(i); i--; continue; } QByteArray lineData; CreateLineData(listToSend.at(i), &lineData); renderedLinesData.append(lineData); } if (listToSend.size() > 0) { emit sendRenderedLines(listToSend, renderedLinesData); emit NotifyClientStatus(); netRenderAckReceived = false; listToSend.clear(); } } } if (data->configuration.UseNetRender()) { if (gNetRender->IsClient()) { gNetRender->SetStatus(CNetRender::netRender_READY); emit NotifyClientStatus(); } if (gNetRender->IsServer()) { emit StopAllClients(); } } // refresh image at end WriteLog("image->CompileImage()", 2); image->CompileImage(); if (!(gNetRender->IsClient() && data->configuration.UseNetRender())) { bool ssaoUsed = false; if (params->ambientOcclusionEnabled && params->ambientOcclusionMode == params::AOmodeScreenSpace) { cRenderSSAO rendererSSAO(params, data, image); connect(&rendererSSAO, SIGNAL(updateProgressAndStatus(const QString &, const QString &, double)), this, SIGNAL(updateProgressAndStatus(const QString &, const QString &, double))); rendererSSAO.RenderSSAO(); ssaoUsed = true; }