#pragma once
#include "FractoriumSettings.h"
#include "FractoriumEmberController.h"
///
/// FinalRenderEmberControllerBase and FinalRenderEmberController classes.
///
///
/// FractoriumEmberController and Fractorium need each other, but each can't include the other.
/// So Fractorium includes this file, and Fractorium is declared as a forward declaration here.
///
class Fractorium;
class FractoriumFinalRenderDialog;
template class FinalRenderPreviewRenderer;
///
/// Used to hold the options specified in the current state of the Gui for performing the final render.
///
struct FinalRenderGuiState
{
bool m_EarlyClip;
bool m_YAxisUp;
bool m_AlphaChannel;
bool m_Transparency;
bool m_OpenCL;
bool m_Double;
bool m_SaveXml;
bool m_DoAll;
bool m_Png16Bit;
bool m_DoSequence;
bool m_KeepAspect;
eScaleType m_Scale;
QString m_Path;
QString m_Ext;
QString m_Prefix;
QString m_Suffix;
QList m_Devices;
uint m_ThreadCount;
int m_ThreadPriority;
double m_SubBatchPct;
double m_WidthScale;
double m_HeightScale;
double m_Quality;
uint m_TemporalSamples;
uint m_Supersample;
size_t m_Strips;
};
///
/// FinalRenderEmberControllerBase serves as a non-templated base class with virtual
/// functions which will be overridden in a derived class that takes a template parameter.
/// Although not meant to be used as an interactive renderer, it derives from FractoriumEmberControllerBase
/// to access a few of its members to avoid having to redefine them here.
///
class FinalRenderEmberControllerBase : public FractoriumEmberControllerBase
{
friend FractoriumFinalRenderDialog;
public:
FinalRenderEmberControllerBase(FractoriumFinalRenderDialog* finalRenderDialog);
virtual ~FinalRenderEmberControllerBase() { }
virtual void SyncCurrentToGui() { }
virtual void SyncGuiToEmbers(size_t widthOverride = 0, size_t heightOverride = 0, bool dowidth = true, bool doheight = true) { }
virtual void SyncCurrentToSizeSpinners(bool scale, bool size, bool doWidth = true, bool doHeight = true) { }
virtual void ResetProgress(bool total = true) { }
virtual tuple SyncAndComputeMemory() { return tuple(0, 0, 0); }
virtual double OriginalAspect() { return 1; }
virtual QString ComposePath(const QString& name, bool unique = true) { return ""; }
virtual bool BumpQualityRender(double d) { return false; }
virtual QString SaveCurrentAgain() { return ""; }
virtual void CancelRender() { }
virtual QString CheckMemory(const tuple& p) { return ""; }
bool Running() { return m_Result.isRunning(); }
bool CreateRendererFromGUI();
void Output(const QString& s);
protected:
bool m_Run = false;
bool m_IsQualityBump = false;
size_t m_ImageCount = 0;
std::atomic m_FinishedImageCount;
QFuture m_Result;
std::function m_FinalRenderFunc;
shared_ptr m_Settings;
FractoriumFinalRenderDialog* m_FinalRenderDialog;
FinalRenderGuiState m_GuiState;
std::recursive_mutex m_ProgressCs;
Timing m_RenderTimer;
Timing m_TotalTimer;
};
///
/// Templated derived class which implements all interaction functionality between the embers
/// of a specific template type and the final render dialog.
///
template
class FinalRenderEmberController : public FinalRenderEmberControllerBase
{
friend FinalRenderPreviewRenderer;
public:
FinalRenderEmberController(FractoriumFinalRenderDialog* finalRender);
virtual ~FinalRenderEmberController() { }
//Virtual functions overridden from FractoriumEmberControllerBase.
void SetEmberFile(const EmberFile& emberFile, bool move) override;
void CopyEmberFile(EmberFile& emberFile, bool sequence, std::function& ember)> perEmberOperation/* = [&](Ember& ember) { }*/) override;
#ifdef DO_DOUBLE
void SetEmberFile(const EmberFile& emberFile, bool move) override;
void CopyEmberFile(EmberFile& emberFile, bool sequence, std::function& ember)> perEmberOperation/* = [&](Ember& ember) { }*/) override;
#endif
void SetEmber(size_t index, bool verbatim) override;
void SaveCurrentAsXml(QString filename = "") override;
bool Render() override;
bool BumpQualityRender(double d) override;
bool CreateRenderer(eRendererType renderType, const vector>& devices, bool updatePreviews, bool shared = true) override;
int ProgressFunc(Ember& ember, void* foo, double fraction, int stage, double etaMs) override;
size_t Index() const noexcept override { return m_Ember->m_Index; }
uint SizeOfT() const noexcept override { return sizeof(T); }
//Virtual functions overridden from FinalRenderEmberControllerBase.
void SyncCurrentToGui() override;
void SyncGuiToEmbers(size_t widthOverride = 0, size_t heightOverride = 0, bool dowidth = true, bool doheight = true) override;
void SyncCurrentToSizeSpinners(bool scale, bool size, bool doWidth = true, bool doHeight = true) override;
void ResetProgress(bool total = true) override;
tuple SyncAndComputeMemory() override;
double OriginalAspect() override { return double(m_Ember->m_OrigFinalRasW) / m_Ember->m_OrigFinalRasH; }
QString Name() const override { return QString::fromStdString(m_Ember->m_Name); }
QString ComposePath(const QString& name, bool unique = true) override;
QString SaveCurrentAgain() override;
void CancelRender() override;
QString CheckMemory(const tuple& p) override;
//Non Virtual functions.
EmberNs::Renderer* FirstOrDefaultRenderer();
protected:
void Pause(bool pause) override;
bool Paused() override;
void HandleFinishedProgress();
QString SaveCurrentRender(Ember& ember);
QString SaveCurrentRender(Ember& ember, const EmberImageComments& comments, vector& pixels, size_t width, size_t height, bool png16Bit, bool transparency);
void RenderComplete(Ember& ember);
void RenderComplete(Ember& ember, const EmberStats& stats, Timing& renderTimer);
void SyncGuiToEmber(Ember& ember, size_t widthOverride = 0, size_t heightOverride = 0, bool dowidth = true, bool doheight = true);
bool SyncGuiToRenderer();
void SetProgressComplete(int val);
bool RenderSingleEmber(Ember& ember, bool fullRender, size_t& stripForProgress);
bool RenderSingleEmberFromSeries(std::atomic* atomfTime, size_t index);
Ember* m_Ember;
EmberFile m_EmberFile;
EmberToXml m_XmlWriter;
unique_ptr> m_FinalPreviewRenderer;
vector>> m_Renderers;
};
///
/// Thin derivation to handle preview rendering that is specific to the final render dialog.
/// This differs from the preview renderers on the main window because they render multiple embers
/// to a tree, whereas this renders a single preview.
///
template
class FinalRenderPreviewRenderer : public PreviewRenderer
{
public:
using PreviewRenderer::m_PreviewRun;
using PreviewRenderer::m_PreviewVec;
using PreviewRenderer::m_PreviewEmber;
using PreviewRenderer::m_PreviewRenderer;
using PreviewRenderer::m_PreviewFinalImage;
FinalRenderPreviewRenderer(FinalRenderEmberController* controller) : m_Controller(controller)
{
}
void PreviewRenderFunc(uint start, uint end) override;
private:
FinalRenderEmberController* m_Controller;
};