예제 #1
0
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;
}
예제 #2
0
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;
			}