Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "stdfx/shaderfx.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzStdfx includes
Toshihiro Shimizu 890ddd
#include "stdfx.h"
Toshihiro Shimizu 890ddd
#include "stdfx/shaderinterface.h"
Toshihiro Shimizu 890ddd
#include "stdfx/shadingcontext.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzBase includes
Toshihiro Shimizu 890ddd
#include "tfxparam.h"
Toshihiro Shimizu 890ddd
#include "tparamset.h"
Toshihiro Shimizu 890ddd
#include "trenderresourcemanager.h"
Toshihiro Shimizu 890ddd
#include "trenderer.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzCore includes
Toshihiro Shimizu 890ddd
#include "tthread.h"
Toshihiro Shimizu 890ddd
#include "tfilepath.h"
Toshihiro Shimizu 890ddd
#include "tstream.h"
Toshihiro Shimizu 890ddd
#include "tfunctorinvoker.h"
Toshihiro Shimizu 890ddd
#include "tmsgcore.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Qt includes
Toshihiro Shimizu 890ddd
#include <qdir></qdir>
Toshihiro Shimizu 890ddd
#include <qglshaderprogram></qglshaderprogram>
Toshihiro Shimizu 890ddd
#include <qcoreapplication></qcoreapplication>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Glew include
Toshihiro Shimizu 890ddd
#include <gl glew.h=""></gl>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// tcg includes
Toshihiro Shimizu 890ddd
#include "tcg/tcg_function_types.h"
Toshihiro Shimizu 890ddd
#include "tcg/tcg_unique_ptr.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Boost includes
Toshihiro Shimizu 890ddd
#include <boost any.hpp=""></boost>
Toshihiro Shimizu 890ddd
#include <boost iterator="" transform_iterator.hpp=""></boost>
Toshihiro Shimizu 890ddd
#include <boost ptr_container="" ptr_vector.hpp=""></boost>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Diagnostics include
Toshihiro Shimizu 890ddd
//#define DIAGNOSTICS
Toshihiro Shimizu 890ddd
#ifdef DIAGNOSTICS
Toshihiro Shimizu 890ddd
#include "diagnostics.h"
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//===================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//    Forward Declarations
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class ShaderFxDeclaration;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//===================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************
Toshihiro Shimizu 890ddd
//    Local Namespace  stuff
Toshihiro Shimizu 890ddd
//****************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Classes
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct ContextLocker {
Toshihiro Shimizu 890ddd
	ShadingContext &m_ctx;
Toshihiro Shimizu 890ddd
	bool m_locked;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	ContextLocker(ShadingContext &ctx)
Toshihiro Shimizu 890ddd
		: m_ctx(ctx), m_locked(false) { relock(); }
Toshihiro Shimizu 890ddd
	~ContextLocker()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		if (m_locked)
Toshihiro Shimizu 890ddd
			unlock();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void relock()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		assert(!m_locked), m_locked = true;
Toshihiro Shimizu 890ddd
		m_ctx.makeCurrent();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void unlock()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		assert(m_locked), m_locked = false;
Toshihiro Shimizu 890ddd
		m_ctx.doneCurrent();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct ProgramBinder {
Toshihiro Shimizu 890ddd
	QGLShaderProgram *m_prog;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	ProgramBinder(QGLShaderProgram *prog) : m_prog(prog) { m_prog->bind(); }
Toshihiro Shimizu 890ddd
	~ProgramBinder() { m_prog->release(); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct RectF {
Toshihiro Shimizu 890ddd
	GLfloat m_val[4];
Toshihiro Shimizu 890ddd
	RectF(GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1) { m_val[0] = x0, m_val[1] = y0, m_val[2] = x1, m_val[3] = y1; }
Toshihiro Shimizu 890ddd
	RectF(const TRectD &rect) { m_val[0] = rect.x0, m_val[1] = rect.y0, m_val[2] = rect.x1, m_val[3] = rect.y1; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	operator TRectD() const { return TRectD(m_val[0], m_val[1], m_val[2], m_val[3]); }
Toshihiro Shimizu 890ddd
	bool operator==(const RectF &rect) const { return (memcmp(m_val, rect.m_val, sizeof(this)) == 0); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct AffineF {
Toshihiro Shimizu 890ddd
	GLfloat m_val[9];
Toshihiro Shimizu 890ddd
	operator TAffine() const { return TAffine(m_val[0], m_val[3], m_val[6], m_val[1], m_val[4], m_val[7]); }
Toshihiro Shimizu 890ddd
	// Observe that mat3 from GLSL stores elements column-wise; this explains the weird indexing
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Global Variables
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef std::map<qstring, *="" shaderfxdeclaration=""> FxDeclarationsMap;</qstring,>
Toshihiro Shimizu 890ddd
FxDeclarationsMap l_shaderFxDeclarations;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
enum Measures { NONE,
Toshihiro Shimizu 890ddd
				PERCENT,
Toshihiro Shimizu 890ddd
				LENGTH,
Toshihiro Shimizu 890ddd
				ANGLE,
Toshihiro Shimizu 890ddd
				MEASURESCOUNT };
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static const std::string l_measureNames[MEASURESCOUNT] = {
Toshihiro Shimizu 890ddd
	"", "percentage", "fxLength", "angle"};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static const TParamUIConcept::Type l_conceptTypes[ShaderInterface::CONCEPTSCOUNT - ShaderInterface::UI_CONCEPTS] = {
Toshihiro Shimizu 890ddd
	TParamUIConcept::RADIUS, TParamUIConcept::WIDTH, TParamUIConcept::ANGLE, TParamUIConcept::POINT,
Toshihiro Shimizu 890ddd
	TParamUIConcept::POINT_2, TParamUIConcept::VECTOR, TParamUIConcept::POLAR, TParamUIConcept::SIZE,
Toshihiro Shimizu 890ddd
	TParamUIConcept::QUAD, TParamUIConcept::RECT};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Functions
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
inline bool isObsolete(const TFilePath &fp, const QDateTime &lastModified)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QFileInfo fInfo(QString::fromStdWString(fp.getWideString()));
Toshihiro Shimizu 890ddd
	return (lastModified != fInfo.lastModified());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
inline TRectD tileRect(const TTile &tile)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	const TDimension &dim = tile.getRaster()->getSize();
Toshihiro Shimizu 890ddd
	return TRectD(tile.m_pos, TDimensionD(dim.lx, dim.ly));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
inline void ceilRect(TRectD &rect)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	rect.x0 = tfloor(rect.x0), rect.y0 = tfloor(rect.y0);
Toshihiro Shimizu 890ddd
	rect.x1 = tceil(rect.x1), rect.y1 = tceil(rect.y1);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************
Toshihiro Shimizu 890ddd
//    Shader Fx  declaration
Toshihiro Shimizu 890ddd
//****************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class ShaderFx : public TStandardZeraryFx
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	FX_PLUGIN_DECLARATION(ShaderFx)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const ShaderInterface *m_shaderInterface;	  //!< Shader fx 'description'.
Toshihiro Shimizu 890ddd
	std::vector<boost::any> m_params;			   //!< Parameters for the shader fx. The actual parameter</boost::any>
Toshihiro Shimizu 890ddd
												   //!< type depends on the shader interface declaration.
Toshihiro Shimizu 890ddd
	std::vector<tparamuiconcept> m_uiConcepts;	 //!< UI concepts related to m_params.</tparamuiconcept>
Toshihiro Shimizu 890ddd
	boost::ptr_vector<trasterfxport> m_inputPorts; //!< Input ports for the shader fx.</trasterfxport>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	ShaderFx() : m_shaderInterface() { assert(false); } // Necessary due to TPersist inheritance, but must NOT be used
Toshihiro Shimizu 890ddd
	ShaderFx(const ShaderInterface *shaderInterface)
Toshihiro Shimizu 890ddd
		: m_shaderInterface(shaderInterface) { initialize(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//void setShaderInterface(const ShaderInterface& shaderInterface);
Toshihiro Shimizu 890ddd
	void initialize();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void getParamUIs(TParamUIConcept *¶ms, int &length);
Toshihiro Shimizu 890ddd
	bool doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info);
Toshihiro Shimizu 890ddd
	bool canHandle(const TRenderSettings &info, double frame);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void doDryCompute(TRectD &rect, double frame, const TRenderSettings &ri);
Toshihiro Shimizu 890ddd
	void doCompute(TTile &tile, double frame, const TRenderSettings &ri);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Toshihiro Shimizu 890ddd
	QGLShaderProgram *touchShaderProgram(
Toshihiro Shimizu 890ddd
		const ShaderInterface::ShaderData &sd,
Toshihiro Shimizu 890ddd
		ShadingContext &context,
Toshihiro Shimizu 890ddd
		int varyingsCount = 0, const GLchar **varyings = 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void bindParameters(QGLShaderProgram *shaderProgram, double frame);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void bindWorldTransform(QGLShaderProgram *shaderProgram, const TAffine &worldToDst);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void getInputData(const TRectD &rect, double frame, const TRenderSettings &ri,
Toshihiro Shimizu 890ddd
					  std::vector<trectd> &inputRects, std::vector<taffine> &inputAffines,</taffine></trectd>
Toshihiro Shimizu 890ddd
					  ShadingContext &context);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************
Toshihiro Shimizu 890ddd
//    ShaderFxDeclaration  definition
Toshihiro Shimizu 890ddd
//****************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class ShaderFxDeclaration : public TFxDeclaration
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	ShaderInterface m_shaderInterface;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	ShaderFxDeclaration(const ShaderInterface &shaderInterface)
Toshihiro Shimizu 890ddd
		: TFxDeclaration(TFxInfo(
Toshihiro Shimizu 890ddd
			  shaderInterface.mainShader().m_name.toStdString(), false)),
Toshihiro Shimizu 890ddd
		  m_shaderInterface(shaderInterface) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPersist *create() const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return new ShaderFx(&m_shaderInterface);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************
Toshihiro Shimizu 890ddd
//    ShadingContextManager  definition
Toshihiro Shimizu 890ddd
//****************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class ShadingContextManager : public QObject
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	mutable QMutex m_mutex;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ShadingContext m_shadingContext;
Toshihiro Shimizu 890ddd
	TAtomicVar m_activeRenderInstances;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	ShadingContextManager()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		/*
Toshihiro Shimizu 890ddd
      The ShadingContext's QGLPixelBuffer must be destroyed *before* the global QApplication
Toshihiro Shimizu 890ddd
      is. So, we will attach to a suitable parent object whose lifespan is shorter.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
      FYI - yes, this approach was adopted after a long and PAINFUL wrestling session with Qt.
Toshihiro Shimizu 890ddd
      Suggestions are welcome as this is a tad beyond ridiculous...
Toshihiro Shimizu 890ddd
    */
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		QObject *mainScopeBoundObject = QCoreApplication::instance()->findChild<qobject *="">("mainScope");</qobject>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		assert(thread() == mainScopeBoundObject->thread()); // Parent object must be in the same thread,
Toshihiro Shimizu 890ddd
		setParent(mainScopeBoundObject);					// otherwise reparenting fails
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	static ShadingContextManager *instance()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		static ShadingContextManager *theManager = new ShadingContextManager;
Toshihiro Shimizu 890ddd
		return theManager;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QMutex *mutex() const { return &m_mutex; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const ShadingContext &shadingContext() const { return m_shadingContext; }
Toshihiro Shimizu 890ddd
	ShadingContext &shadingContext() { return m_shadingContext; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void onRenderInstanceStart()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		++m_activeRenderInstances;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void onRenderInstanceEnd()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		if (--m_activeRenderInstances == 0) {
Toshihiro Shimizu 890ddd
			QMutexLocker mLocker(&m_mutex);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// Release the shading context's output buffer
Toshihiro Shimizu 890ddd
			::ContextLocker cLocker(m_shadingContext);
Toshihiro Shimizu 890ddd
			m_shadingContext.resize(0, 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef DIAGNOSTICS
Toshihiro Shimizu 890ddd
			DIAGNOSTICS_DUMP("ShaderLogs");
Toshihiro Shimizu 890ddd
			DIAGNOSTICS_CLEAR;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ShadingContext::Support touchSupport()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		struct {
Toshihiro Shimizu 890ddd
			ShadingContextManager *m_this;
Toshihiro Shimizu 890ddd
			ShadingContext::Support support()
Toshihiro Shimizu 890ddd
			{
Toshihiro Shimizu 890ddd
				QMutexLocker mLocker(&m_this->m_mutex);
Toshihiro Shimizu 890ddd
				::ContextLocker cLocker(m_this->m_shadingContext);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				return ShadingContext::support();
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		} locals = {this};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		static ShadingContext::Support sup = locals.support();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		static bool sentMsg = false;
Toshihiro Shimizu 890ddd
		if (!sentMsg) {
Toshihiro Shimizu 890ddd
			switch (sup) {
Toshihiro Shimizu 890ddd
			case ShadingContext::NO_PIXEL_BUFFER:
Toshihiro Shimizu 890ddd
				DVGui::warning(QGLShaderProgram::tr(
Toshihiro Shimizu 890ddd
					"This system configuration does not support OpenGL Pixel Buffers. Shader Fxs will not be able to render."));
Shinya Kitaoka d4642c
				break;
Toshihiro Shimizu 890ddd
Shinya Kitaoka d4642c
			case ShadingContext::NO_SHADERS:
Shinya Kitaoka d4642c
				DVGui::warning(QGLShaderProgram::tr(
Shinya Kitaoka d4642c
					"This system configuration does not support OpenGL Shader Programs. Shader Fxs will not be able to render."));
Shinya Kitaoka d4642c
				break;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			sentMsg = true;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		return sup;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template class DV_EXPORT_API TFxDeclarationT<shaderfx>;</shaderfx>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************
Toshihiro Shimizu 890ddd
//    ShadingContextManagerDelegate  definition
Toshihiro Shimizu 890ddd
//****************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class MessageCreateContext : public TThread::Message
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	ShadingContextManager *man;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	MessageCreateContext(ShadingContextManager *ctx)
Toshihiro Shimizu 890ddd
		: man(ctx) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void onDeliver()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		man->onRenderInstanceEnd();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TThread::Message *clone() const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return new MessageCreateContext(*this);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class SCMDelegate : public TRenderResourceManager
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	T_RENDER_RESOURCE_MANAGER
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void onRenderInstanceStart(unsigned long id)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		ShadingContextManager::instance()->onRenderInstanceStart();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void onRenderInstanceEnd(unsigned long id)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		if (!TThread::isMainThread()) {
Toshihiro Shimizu 890ddd
			/* tofflinegl のときとは逆で main thread に dispatch する */
Toshihiro Shimizu 890ddd
			MessageCreateContext(ShadingContextManager::instance()).sendBlocking();
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			ShadingContextManager::instance()->onRenderInstanceEnd();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class SCMDelegateGenerator : public TRenderResourceManagerGenerator
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	SCMDelegateGenerator() : TRenderResourceManagerGenerator(false)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		/*
Toshihiro Shimizu 890ddd
      Again, this has to do with the manager's lifetime issue.
Toshihiro Shimizu 890ddd
      The SCM must be created in the MAIN THREAD, but NOT BEFORE the
Toshihiro Shimizu 890ddd
      QCoreApplication itself has been created. The easiest way to do so
Toshihiro Shimizu 890ddd
      is scheduling a slot to be executed as soon as event processing starts.
Toshihiro Shimizu 890ddd
    */
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		struct InstanceSCM : public TFunctorInvoker::BaseFunctor {
Toshihiro Shimizu 890ddd
			void operator()() { ShadingContextManager::instance(); }
Toshihiro Shimizu 890ddd
		};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TFunctorInvoker::instance()->invokeQueued(new InstanceSCM);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRenderResourceManager *operator()() { return new SCMDelegate; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
MANAGER_FILESCOPE_DECLARATION(SCMDelegate, SCMDelegateGenerator)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************
Toshihiro Shimizu 890ddd
//    Shader Fx  implementation
Toshihiro Shimizu 890ddd
//****************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ShaderFx::initialize()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	struct {
Toshihiro Shimizu 890ddd
		ShaderFx *m_this;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		inline void addUiConcept(const ShaderInterface::Parameter &siParam, const TParamP ¶m)
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			if (siParam.m_concept.m_type >= ShaderInterface::UI_CONCEPTS &&
Toshihiro Shimizu 890ddd
				siParam.m_concept.m_type < ShaderInterface::CONCEPTSCOUNT) {
Toshihiro Shimizu 890ddd
				m_this->m_uiConcepts.push_back(TParamUIConcept());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				TParamUIConcept &uiConcept = m_this->m_uiConcepts.back();
Toshihiro Shimizu 890ddd
				uiConcept.m_type = ::l_conceptTypes[siParam.m_concept.m_type - ShaderInterface::UI_CONCEPTS];
Toshihiro Shimizu 890ddd
				uiConcept.m_label = siParam.m_concept.m_label.toStdString();
Toshihiro Shimizu 890ddd
				uiConcept.m_params.push_back(param);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		inline void addUiConcept(const ShaderInterface::ParameterConcept &concept)
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			if (!concept.isUI() || concept.m_parameterNames.empty())
Toshihiro Shimizu 890ddd
				return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			TParamUIConcept uiConcept = {
Toshihiro Shimizu 890ddd
				::l_conceptTypes[concept.m_type - ShaderInterface::UI_CONCEPTS],
Toshihiro Shimizu 890ddd
				concept.m_label.toStdString()};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			int n, nCount = int(concept.m_parameterNames.size());
Toshihiro Shimizu 890ddd
			for (n = 0; n != nCount; ++n) {
Toshihiro Shimizu 890ddd
				TParam *param = m_this->getParams()->getParam(concept.m_parameterNames[n].toStdString());
Toshihiro Shimizu 890ddd
				if (!param)
Toshihiro Shimizu 890ddd
					break;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				uiConcept.m_params.push_back(param);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (uiConcept.m_params.size() == concept.m_parameterNames.size())
Toshihiro Shimizu 890ddd
				m_this->m_uiConcepts.push_back(uiConcept);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	} locals = {this};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(m_params.empty()); // Interfaces should not be re-set
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Allocate parameters following the specified interface
Toshihiro Shimizu 890ddd
	const std::vector<shaderinterface::parameter> &siParams =</shaderinterface::parameter>
Toshihiro Shimizu 890ddd
		m_shaderInterface->parameters();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int p, pCount = int(siParams.size());
Toshihiro Shimizu 890ddd
	m_params.reserve(pCount);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (p = 0; p != pCount; ++p) {
Toshihiro Shimizu 890ddd
		const ShaderInterface::Parameter &siParam = siParams[p];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		switch (siParam.m_type) {
Toshihiro Shimizu 890ddd
		case ShaderInterface::BOOL: {
Toshihiro Shimizu 890ddd
			TBoolParamP param(siParam.m_default.m_bool);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			m_params.push_back(param);
Toshihiro Shimizu 890ddd
			bindParam(this, siParam.m_name.toStdString(),
Shinya Kitaoka d4642c
				*boost::unsafe_any_cast<tboolparamp>(&m_params.back()));</tboolparamp>
Toshihiro Shimizu 890ddd
Shinya Kitaoka d4642c
			break;
Shinya Kitaoka d4642c
		}
Toshihiro Shimizu 890ddd
Shinya Kitaoka d4642c
		case ShaderInterface::FLOAT: {
Shinya Kitaoka d4642c
			TDoubleParamP param(siParam.m_default.m_float);
Shinya Kitaoka d4642c
			param->setValueRange(siParam.m_range[0].m_float, siParam.m_range[1].m_float);
Toshihiro Shimizu 890ddd
Shinya Kitaoka d4642c
			locals.addUiConcept(siParam, param);
Toshihiro Shimizu 890ddd
Shinya Kitaoka d4642c
			switch (siParam.m_concept.m_type) {
Shinya Kitaoka d4642c
			case ShaderInterface::PERCENT:
Shinya Kitaoka d4642c
				param->setMeasureName(l_measureNames[PERCENT]);
Shinya Kitaoka d4642c
				break;
Toshihiro Shimizu 890ddd
Shinya Kitaoka d4642c
			case ShaderInterface::LENGTH:
Shinya Kitaoka d4642c
			case ShaderInterface::RADIUS_UI:
Shinya Kitaoka d4642c
			case ShaderInterface::WIDTH_UI:
Shinya Kitaoka d4642c
			case ShaderInterface::SIZE_UI:
Shinya Kitaoka d4642c
				param->setMeasureName(l_measureNames[LENGTH]);
Shinya Kitaoka d4642c
				break;
Toshihiro Shimizu 890ddd
Shinya Kitaoka d4642c
			case ShaderInterface::ANGLE:
Shinya Kitaoka d4642c
			case ShaderInterface::ANGLE_UI:
Shinya Kitaoka d4642c
				param->setMeasureName(l_measureNames[ANGLE]);
Shinya Kitaoka d4642c
				break;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Shinya Kitaoka d4642c
			m_params.push_back(param);
Shinya Kitaoka d4642c
			bindParam(this, siParam.m_name.toStdString(),
Shinya Kitaoka d4642c
				*boost::unsafe_any_cast<tdoubleparamp>(&m_params.back()));</tdoubleparamp>
Shinya Kitaoka d4642c
			break;
Shinya Kitaoka d4642c
		}
Toshihiro Shimizu 890ddd
Shinya Kitaoka d4642c
		case ShaderInterface::VEC2: {
Shinya Kitaoka d4642c
			TPointParamP param(TPointD(
Shinya Kitaoka d4642c
				siParam.m_default.m_vec2[0], siParam.m_default.m_vec2[1]));
Shinya Kitaoka d4642c
Shinya Kitaoka d4642c
			param->getX()->setValueRange(siParam.m_range[0].m_vec2[0], siParam.m_range[1].m_vec2[0]);
Shinya Kitaoka d4642c
			param->getY()->setValueRange(siParam.m_range[0].m_vec2[1], siParam.m_range[1].m_vec2[1]);
Shinya Kitaoka d4642c
Shinya Kitaoka d4642c
			locals.addUiConcept(siParam, param);
Shinya Kitaoka d4642c
Shinya Kitaoka d4642c
			switch (siParam.m_concept.m_type) {
Shinya Kitaoka d4642c
			case ShaderInterface::PERCENT:
Shinya Kitaoka d4642c
				param->getX()->setMeasureName(l_measureNames[PERCENT]);
Shinya Kitaoka d4642c
				param->getY()->setMeasureName(l_measureNames[PERCENT]);
Shinya Kitaoka d4642c
				break;
Shinya Kitaoka d4642c
Shinya Kitaoka d4642c
			case ShaderInterface::LENGTH:
Shinya Kitaoka d4642c
			case ShaderInterface::POINT:
Shinya Kitaoka d4642c
			case ShaderInterface::POINT_UI:
Shinya Kitaoka d4642c
			case ShaderInterface::VECTOR_UI:
Shinya Kitaoka d4642c
			case ShaderInterface::WIDTH_UI:
Shinya Kitaoka d4642c
			case ShaderInterface::SIZE_UI:
Shinya Kitaoka d4642c
				param->getX()->setMeasureName(l_measureNames[LENGTH]);
Shinya Kitaoka d4642c
				param->getY()->setMeasureName(l_measureNames[LENGTH]);
Shinya Kitaoka d4642c
				break;
Shinya Kitaoka d4642c
Shinya Kitaoka d4642c
			case ShaderInterface::ANGLE:
Shinya Kitaoka d4642c
			case ShaderInterface::ANGLE_UI:
Shinya Kitaoka d4642c
				param->getX()->setMeasureName(l_measureNames[ANGLE]);
Shinya Kitaoka d4642c
				param->getY()->setMeasureName(l_measureNames[ANGLE]);
Shinya Kitaoka d4642c
				break;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Shinya Kitaoka d4642c
			m_params.push_back(param);
Shinya Kitaoka d4642c
			bindParam(this, siParam.m_name.toStdString(),
Shinya Kitaoka d4642c
				*boost::unsafe_any_cast<tpointparamp>(&m_params.back()));</tpointparamp>
Shinya Kitaoka d4642c
			break;
Shinya Kitaoka d4642c
		}
Toshihiro Shimizu 890ddd
Shinya Kitaoka d4642c
		case ShaderInterface::INT: {
Shinya Kitaoka d4642c
			TIntParamP param(siParam.m_default.m_int);
Shinya Kitaoka d4642c
			param->setValueRange(siParam.m_range[0].m_int, siParam.m_range[1].m_int);
Toshihiro Shimizu 890ddd
Shinya Kitaoka d4642c
			m_params.push_back(param);
Shinya Kitaoka d4642c
			bindParam(this, siParam.m_name.toStdString(),
Shinya Kitaoka d4642c
				*boost::unsafe_any_cast<tintparamp>(&m_params.back()));</tintparamp>
Shinya Kitaoka d4642c
			break;
Shinya Kitaoka d4642c
		}
Toshihiro Shimizu 890ddd
Shinya Kitaoka d4642c
		case ShaderInterface::RGBA: {
Shinya Kitaoka d4642c
			TPixelParamP param(TPixel32(
Shinya Kitaoka d4642c
				siParam.m_default.m_rgba[0], siParam.m_default.m_rgba[1],
Shinya Kitaoka d4642c
				siParam.m_default.m_rgba[2], siParam.m_default.m_rgba[3]));
Toshihiro Shimizu 890ddd
Shinya Kitaoka d4642c
			m_params.push_back(param);
Shinya Kitaoka d4642c
			bindParam(this, siParam.m_name.toStdString(),
Shinya Kitaoka d4642c
				*boost::unsafe_any_cast<tpixelparamp>(&m_params.back()));</tpixelparamp>
Shinya Kitaoka d4642c
			break;
Shinya Kitaoka d4642c
		}
Toshihiro Shimizu 890ddd
Shinya Kitaoka d4642c
		case ShaderInterface::RGB: {
Shinya Kitaoka d4642c
			TPixelParamP param(TPixel32(
Shinya Kitaoka d4642c
				siParam.m_default.m_rgb[0], siParam.m_default.m_rgb[1],
Shinya Kitaoka d4642c
				siParam.m_default.m_rgb[2]));
Toshihiro Shimizu 890ddd
Shinya Kitaoka d4642c
			param->enableMatte(false);
Toshihiro Shimizu 890ddd
Shinya Kitaoka d4642c
			m_params.push_back(param);
Shinya Kitaoka d4642c
			bindParam(this, siParam.m_name.toStdString(),
Shinya Kitaoka d4642c
				*boost::unsafe_any_cast<tpixelparamp>(&m_params.back()));</tpixelparamp>
Shinya Kitaoka d4642c
			break;
Shinya Kitaoka d4642c
		}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Add composite UI concepts
Toshihiro Shimizu 890ddd
	const std::vector<shaderinterface::parameterconcept> &parConcepts = m_shaderInterface->m_parConcepts;</shaderinterface::parameterconcept>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int c, cCount = int(parConcepts.size());
Toshihiro Shimizu 890ddd
	for (c = 0; c != cCount; ++c)
Toshihiro Shimizu 890ddd
		locals.addUiConcept(parConcepts[c]);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Add input ports
Toshihiro Shimizu 890ddd
	const std::vector<qstring> &inputPorts = m_shaderInterface->inputPorts();</qstring>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int i, iCount = int(inputPorts.size());
Toshihiro Shimizu 890ddd
	m_inputPorts.reserve(iCount);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (i = 0; i != iCount; ++i) {
Toshihiro Shimizu 890ddd
		m_inputPorts.push_back(new TRasterFxPort);
Toshihiro Shimizu 890ddd
		addInputPort(inputPorts[i].toStdString(), m_inputPorts[i]);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ShaderFx::getParamUIs(TParamUIConcept *¶ms, int &length)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	length = int(m_uiConcepts.size());
Toshihiro Shimizu 890ddd
	params = new TParamUIConcept[length];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::copy(m_uiConcepts.begin(), m_uiConcepts.end(), params);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool ShaderFx::doGetBBox(double frame, TRectD &bbox, const TRenderSettings &info)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	static const ::RectF infiniteRectF(
Toshihiro Shimizu 890ddd
		-(std::numeric_limits<glfloat>::max)(), -(std::numeric_limits<glfloat>::max)(),</glfloat></glfloat>
Toshihiro Shimizu 890ddd
		(std::numeric_limits<glfloat>::max)(), (std::numeric_limits<glfloat>::max)());</glfloat></glfloat>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bbox = TConsts::infiniteRectD;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const ShaderInterface::ShaderData &sd = m_shaderInterface->bboxShader();
Toshihiro Shimizu 890ddd
	if (!sd.isValid())
Toshihiro Shimizu 890ddd
		return true;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ShadingContextManager *manager = ShadingContextManager::instance();
Toshihiro Shimizu 890ddd
	if (manager->touchSupport() != ShadingContext::OK)
Toshihiro Shimizu 890ddd
		return true;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Remember: info.m_affine MUST NOT BE CONSIDERED in doGetBBox's implementation
Toshihiro Shimizu 890ddd
	::RectF bboxF(infiniteRectF);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QMutexLocker mLocker(manager->mutex());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//ShadingContext& context = manager->shadingContext();
Toshihiro Shimizu 890ddd
	std::shared_ptr<shadingcontext> shadingContextPtr(new ShadingContext);</shadingcontext>
Toshihiro Shimizu 890ddd
	ShadingContext &context = *shadingContextPtr.get();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	::ContextLocker cLocker(context);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Build the varyings data
Toshihiro Shimizu 890ddd
	QGLShaderProgram *prog = 0;
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		const GLchar *varyingNames[] = {"outputBBox"};
Toshihiro Shimizu 890ddd
		prog = touchShaderProgram(sd, context, 1, &varyingNames[0]);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int pCount = getInputPortCount();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::vector<rectf> inputBBoxes(pCount, ::RectF(TRectD()));</rectf>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (int p = 0; p != pCount; ++p) {
Toshihiro Shimizu 890ddd
		TRasterFxPort &port = m_inputPorts[p];
Toshihiro Shimizu 890ddd
		if (port.isConnected()) {
Toshihiro Shimizu 890ddd
			TRectD inputBBox;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			cLocker.unlock();
Toshihiro Shimizu 890ddd
			mLocker.unlock();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (port->doGetBBox(frame, inputBBox, info))
Toshihiro Shimizu 890ddd
				inputBBoxes[p] = (inputBBox == TConsts::infiniteRectD) ? infiniteRectF : ::RectF(inputBBox);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			mLocker.relock();
Toshihiro Shimizu 890ddd
			cLocker.relock();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		ProgramBinder progBinder(prog);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Bind uniform parameters
Toshihiro Shimizu 890ddd
		bindParameters(prog, frame);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		prog->setUniformValue("infiniteRect",
Toshihiro Shimizu 890ddd
							  infiniteRectF.m_val[0], infiniteRectF.m_val[1], infiniteRectF.m_val[2], infiniteRectF.m_val[3]);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		prog->setUniformValueArray("inputBBox", inputBBoxes[0].m_val,
Toshihiro Shimizu 890ddd
								   int(inputBBoxes.size()), 4);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Perform transform feedback
Toshihiro Shimizu 890ddd
		const GLsizeiptr varyingSizes[] = {sizeof(::RectF)};
Toshihiro Shimizu 890ddd
		GLvoid *bufs[] = {bboxF.m_val};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		context.transformFeedback(1, varyingSizes, bufs);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Finalize output
Toshihiro Shimizu 890ddd
	bbox = (bboxF == infiniteRectF) ? TConsts::infiniteRectD : TRectD(bboxF);
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool ShaderFx::canHandle(const TRenderSettings &info, double frame)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return (m_shaderInterface->hwtType() == ShaderInterface::ANY) ? true : isAlmostIsotropic(info.m_affine);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
QGLShaderProgram *ShaderFx::touchShaderProgram(
Toshihiro Shimizu 890ddd
	const ShaderInterface::ShaderData &sd,
Toshihiro Shimizu 890ddd
	ShadingContext &context,
Toshihiro Shimizu 890ddd
	int varyingsCount, const GLchar **varyings)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	typedef std::pair<qglshaderprogram *,="" qdatetime=""> CompiledShader;</qglshaderprogram>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	struct locals {
Toshihiro Shimizu 890ddd
		inline static void logCompilation(QGLShaderProgram *program)
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			// Log shaders - observe that we'll look into the program's *children*, not its
Toshihiro Shimizu 890ddd
			// shaders. This is necessary as uncompiled shaders are not added to the program.
Toshihiro Shimizu 890ddd
			const QObjectList &children = program->children();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			int c, cCount = children.size();
Toshihiro Shimizu 890ddd
			for (c = 0; c != cCount; ++c) {
Toshihiro Shimizu 890ddd
				if (QGLShader *shader = dynamic_cast<qglshader *="">(children[c])) {</qglshader>
Toshihiro Shimizu 890ddd
					const QString &log = shader->log();
Toshihiro Shimizu 890ddd
					if (!log.isEmpty())
Toshihiro Shimizu 890ddd
						DVGui::info(log);
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// ShaderProgram linking logs
Toshihiro Shimizu 890ddd
			const QString &log = program->log();
Toshihiro Shimizu 890ddd
			if (!log.isEmpty())
Toshihiro Shimizu 890ddd
				DVGui::info(log);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}; // locals
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//ShadingContext& context = ShadingContextManager::instance()->shadingContext();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	CompiledShader cs = context.shaderData(sd.m_name);
Toshihiro Shimizu 890ddd
	if (!cs.first || ::isObsolete(sd.m_path, cs.second)) {
Toshihiro Shimizu 890ddd
		cs = m_shaderInterface->makeProgram(sd, varyingsCount, varyings);
Toshihiro Shimizu 890ddd
		context.addShaderProgram(sd.m_name, cs.first, cs.second);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		locals::logCompilation(cs.first);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(cs.first);
Toshihiro Shimizu 890ddd
	return cs.first;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ShaderFx::bindParameters(
Toshihiro Shimizu 890ddd
	QGLShaderProgram *program, double frame)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// Bind fx parameters
Toshihiro Shimizu 890ddd
	const std::vector<shaderinterface::parameter> &siParams =</shaderinterface::parameter>
Toshihiro Shimizu 890ddd
		m_shaderInterface->parameters();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(siParams.size() == m_params.size());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int p, pCount = int(siParams.size());
Toshihiro Shimizu 890ddd
	for (p = 0; p != pCount; ++p) {
Toshihiro Shimizu 890ddd
		const ShaderInterface::Parameter &siParam = siParams[p];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		switch (siParam.m_type) {
Toshihiro Shimizu 890ddd
		case ShaderInterface::BOOL: {
Toshihiro Shimizu 890ddd
			const TBoolParamP ¶m = *boost::unsafe_any_cast<tboolparamp>(&m_params[p]);</tboolparamp>
Toshihiro Shimizu 890ddd
			program->setUniformValue(siParam.m_name.toUtf8().data(), (GLboolean)param->getValue());
Shinya Kitaoka d4642c
			break;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Shinya Kitaoka d4642c
		case ShaderInterface::FLOAT: {
Shinya Kitaoka d4642c
			const TDoubleParamP ¶m = *boost::unsafe_any_cast<tdoubleparamp>(&m_params[p]);</tdoubleparamp>
Shinya Kitaoka d4642c
			program->setUniformValue(siParam.m_name.toUtf8().data(),
Shinya Kitaoka d4642c
				(GLfloat)param->getValue(frame));
Shinya Kitaoka d4642c
			break;
Shinya Kitaoka d4642c
		}
Toshihiro Shimizu 890ddd
Shinya Kitaoka d4642c
		case ShaderInterface::VEC2: {
Shinya Kitaoka d4642c
			const TPointParamP ¶m = *boost::unsafe_any_cast<tpointparamp>(&m_params[p]);</tpointparamp>
Toshihiro Shimizu 890ddd
Shinya Kitaoka d4642c
			const TPointD &value = param->getValue(frame);
Shinya Kitaoka d4642c
			program->setUniformValue(siParam.m_name.toUtf8().data(),
Shinya Kitaoka d4642c
				(GLfloat)value.x, (GLfloat)value.y);
Shinya Kitaoka d4642c
			break;
Shinya Kitaoka d4642c
		}
Toshihiro Shimizu 890ddd
Shinya Kitaoka d4642c
		case ShaderInterface::INT: {
Shinya Kitaoka d4642c
			const TIntParamP ¶m = *boost::unsafe_any_cast<tintparamp>(&m_params[p]);</tintparamp>
Shinya Kitaoka d4642c
			program->setUniformValue(siParam.m_name.toUtf8().data(), (GLint)param->getValue());
Shinya Kitaoka d4642c
			break;
Shinya Kitaoka d4642c
		}
Toshihiro Shimizu 890ddd
Shinya Kitaoka d4642c
		case ShaderInterface::RGBA:
Shinya Kitaoka d4642c
		case ShaderInterface::RGB: {
Shinya Kitaoka d4642c
			const TPixelParamP ¶m = *boost::unsafe_any_cast<tpixelparamp>(&m_params[p]);</tpixelparamp>
Toshihiro Shimizu 890ddd
Shinya Kitaoka d4642c
			const TPixel32 &value = param->getValue(frame);
Shinya Kitaoka d4642c
			program->setUniformValue(siParam.m_name.toUtf8().data(),
Shinya Kitaoka d4642c
				(GLfloat)value.r / 255.0f, (GLfloat)value.g / 255.0f,
Shinya Kitaoka d4642c
				(GLfloat)value.b / 255.0f, (GLfloat)value.m / 255.0f);
Shinya Kitaoka d4642c
			break;
Shinya Kitaoka d4642c
		}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ShaderFx::bindWorldTransform(QGLShaderProgram *program, const TAffine &worldToDst)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
// Bind transformation affine
Toshihiro Shimizu 890ddd
#if QT_VERSION >= 0x050500
Toshihiro Shimizu 890ddd
	float qwToD[9] = {static_cast<float>(worldToDst.a11), static_cast<float>(worldToDst.a12), static_cast<float>(worldToDst.a13),</float></float></float>
Toshihiro Shimizu 890ddd
					  static_cast<float>(worldToDst.a21), static_cast<float>(worldToDst.a22), static_cast<float>(worldToDst.a23),</float></float></float>
Toshihiro Shimizu 890ddd
					  0.0f, 0.0f, 1.0f};
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
	qreal qwToD[9] = {worldToDst.a11, worldToDst.a12, worldToDst.a13,
Toshihiro Shimizu 890ddd
					  worldToDst.a21, worldToDst.a22, worldToDst.a23,
Toshihiro Shimizu 890ddd
					  0.0, 0.0, 1.0};
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
	program->setUniformValue("worldToOutput", QMatrix3x3(qwToD));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const TAffine &dToW = worldToDst.inv();
Toshihiro Shimizu 890ddd
#if QT_VERSION >= 0x050500
Toshihiro Shimizu 890ddd
	float qdToW[9] = {static_cast<float>(dToW.a11), static_cast<float>(dToW.a12), static_cast<float>(dToW.a13),</float></float></float>
Toshihiro Shimizu 890ddd
					  static_cast<float>(dToW.a21), static_cast<float>(dToW.a22), static_cast<float>(dToW.a23),</float></float></float>
Toshihiro Shimizu 890ddd
					  0.0f, 0.0f, 1.0f};
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
	qreal qdToW[9] = {dToW.a11, dToW.a12, dToW.a13,
Toshihiro Shimizu 890ddd
					  dToW.a21, dToW.a22, dToW.a23,
Toshihiro Shimizu 890ddd
					  0.0, 0.0, 1.0};
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
	program->setUniformValue("outputToWorld", QMatrix3x3(qdToW));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ShaderFx::getInputData(const TRectD &rect, double frame, const TRenderSettings &ri,
Toshihiro Shimizu 890ddd
							std::vector<trectd> &inputRects, std::vector<taffine> &inputAffines,</taffine></trectd>
Toshihiro Shimizu 890ddd
							ShadingContext &context)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	struct locals {
Toshihiro Shimizu 890ddd
		static inline void addNames(std::vector<std::string> &names, const char *prefix, int pCount)</std::string>
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			for (int p = 0; p != pCount; ++p)
Toshihiro Shimizu 890ddd
				names.push_back((prefix + QString("[%1]").arg(p)).toStdString());
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const ShaderInterface::ShaderData &sd = m_shaderInterface->inputPortsShader();
Toshihiro Shimizu 890ddd
	if (!sd.isValid()) {
Toshihiro Shimizu 890ddd
		inputRects.resize(getInputPortCount());
Toshihiro Shimizu 890ddd
		std::fill(inputRects.begin(), inputRects.end(), rect);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		inputAffines.resize(getInputPortCount());
Toshihiro Shimizu 890ddd
		std::fill(inputAffines.begin(), inputAffines.end(), ri.m_affine);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//ShadingContext& context = ShadingContextManager::instance()->shadingContext();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::vector<glfloat> buf;</glfloat>
Toshihiro Shimizu 890ddd
	int pCount = getInputPortCount();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Build the varyings data
Toshihiro Shimizu 890ddd
	QGLShaderProgram *prog = 0;
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		// Unsubscripted varying arrays on transform feedback seems to be unsupported
Toshihiro Shimizu 890ddd
		// on ATI cards. We have to declare EACH array name - e.g. inputRect[0], intputRect[1], etc..
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		const GLchar *varyingPrefixes[] = {"inputRect", "worldToInput"};
Toshihiro Shimizu 890ddd
		const int varyingsCount = sizeof(varyingPrefixes) / sizeof(GLchar *);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		std::vector<std::string> varyingStrings;</std::string>
Toshihiro Shimizu 890ddd
		varyingStrings.reserve(varyingsCount);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (int v = 0; v != varyingsCount; ++v)
Toshihiro Shimizu 890ddd
			locals::addNames(varyingStrings, varyingPrefixes[v], pCount);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#if defined(__APPLE_CC__)
Toshihiro Shimizu 890ddd
		/* OSX10.8 の clang -stdlib=libc++ だと link 時 &std::string::c_str が undefined になってしまう */
Toshihiro Shimizu 890ddd
		std::vector<const *="" glchar=""> varyingNames(varyingStrings.size());</const>
Toshihiro Shimizu 890ddd
		auto conv = [](const std::string &i) { return i.c_str(); };
Toshihiro Shimizu 890ddd
		std::transform(varyingStrings.begin(), varyingStrings.end(), varyingNames.begin(), conv);
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
		std::vector<const *="" glchar=""> varyingNames(</const>
Toshihiro Shimizu 890ddd
			boost::make_transform_iterator(varyingStrings.begin(), std::mem_fun_ref(&std::string::c_str)),
Toshihiro Shimizu 890ddd
			boost::make_transform_iterator(varyingStrings.end(), std::mem_fun_ref(&std::string::c_str)));
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
		prog = touchShaderProgram(sd, context, int(varyingNames.size()), &varyingNames[0]);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		ProgramBinder progBinder(prog);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Build varying buffers
Toshihiro Shimizu 890ddd
		int bufFloatsCount = pCount * (sizeof(RectF) + sizeof(AffineF)) / sizeof(GLfloat);
Toshihiro Shimizu 890ddd
		buf.resize(bufFloatsCount);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Bind uniform parameters
Toshihiro Shimizu 890ddd
		bindParameters(prog, frame);
Toshihiro Shimizu 890ddd
		bindWorldTransform(prog, ri.m_affine);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		prog->setUniformValue("outputRect",
Toshihiro Shimizu 890ddd
							  (GLfloat)rect.x0, (GLfloat)rect.y0, (GLfloat)rect.x1, (GLfloat)rect.y1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Perform transform feedback
Toshihiro Shimizu 890ddd
		const GLsizeiptr varyingSizes[] = {static_cast<glsizeiptr>(bufFloatsCount * sizeof(GLfloat))};</glsizeiptr>
Toshihiro Shimizu 890ddd
		GLvoid *bufs[] = {&buf[0]};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		context.transformFeedback(1, varyingSizes, bufs);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef TRANSFORM_FEEDBACK_COUT
Toshihiro Shimizu 890ddd
		std::cout << "trFeedback: ";
Toshihiro Shimizu 890ddd
		for (int f = 0; f != bufFloatsCount; ++f)
Toshihiro Shimizu 890ddd
			std::cout << buf[f] << " ";
Toshihiro Shimizu 890ddd
		std::cout << "\n" << std::endl;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Finalize output
Toshihiro Shimizu 890ddd
	const RectF *rBufBegin(reinterpret_cast<const *="" rectf="">(&buf[0])), *rBufEnd(rBufBegin + pCount);</const>
Toshihiro Shimizu 890ddd
	std::copy(rBufBegin, rBufEnd, &inputRects[0]);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const AffineF *aBufBegin(reinterpret_cast<const *="" affinef="">(rBufEnd)), *aBufEnd(aBufBegin + pCount);</const>
Toshihiro Shimizu 890ddd
	std::copy(aBufBegin, aBufEnd, &inputAffines[0]);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ShaderFx::doCompute(TTile &tile, double frame, const TRenderSettings &info)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	struct locals {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		struct TexturesStorage {
Toshihiro Shimizu 890ddd
			ShadingContext &m_ctx;
Toshihiro Shimizu 890ddd
			std::vector<gluint> m_texIds;</gluint>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			TexturesStorage(ShadingContext &ctx, int pCount)
Toshihiro Shimizu 890ddd
				: m_ctx(ctx)
Toshihiro Shimizu 890ddd
			{
Toshihiro Shimizu 890ddd
				m_texIds.reserve(pCount);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			~TexturesStorage()
Toshihiro Shimizu 890ddd
			{
Toshihiro Shimizu 890ddd
				typedef tcg::function
Toshihiro Shimizu 890ddd
									  &ShadingContext::unloadTexture> UnloadFunc;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				std::for_each(m_texIds.begin(), m_texIds.end(),
Toshihiro Shimizu 890ddd
							  tcg::bind1st(UnloadFunc(), m_ctx));
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			void load(const TRasterP &ras, GLuint texUnit)
Toshihiro Shimizu 890ddd
			{
Toshihiro Shimizu 890ddd
				if (ras)
Toshihiro Shimizu 890ddd
					m_texIds.push_back(m_ctx.loadTexture(ras, texUnit));
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		inline static QGLFramebufferObjectFormat makeFormat(int bpp)
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			QGLFramebufferObjectFormat fmt;
Toshihiro Shimizu 890ddd
			if (bpp == 64)
Toshihiro Shimizu 890ddd
				fmt.setInternalTextureFormat(GL_RGBA16);
Toshihiro Shimizu 890ddd
			return fmt;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		inline static void touchOutputSize(ShadingContext &context, const TDimension &size, int bpp)
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			const QGLFramebufferObjectFormat &fmt = makeFormat(bpp);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			const TDimension ¤tSize = context.size();
Toshihiro Shimizu 890ddd
			const QGLFramebufferObjectFormat ¤tFmt = context.format();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (currentSize.lx < size.lx || currentSize.ly < size.ly ||
Toshihiro Shimizu 890ddd
				currentFmt != fmt)
Toshihiro Shimizu 890ddd
				context.resize(tmax(size.lx, currentSize.lx), tmax(size.ly, currentSize.ly), fmt);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}; // locals
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ShadingContextManager *manager = ShadingContextManager::instance();
Toshihiro Shimizu 890ddd
	if (manager->touchSupport() != ShadingContext::OK)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QMutexLocker mLocker(manager->mutex()); // As GPU access can be considered sequential anyway,
Toshihiro Shimizu 890ddd
											// lock the full-scale mutex
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::shared_ptr<shadingcontext> shadingContextPtr(new ShadingContext);</shadingcontext>
Toshihiro Shimizu 890ddd
	ShadingContext &context = *shadingContextPtr.get();
Toshihiro Shimizu 890ddd
	// ShadingContext& context = manager->shadingContext();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int pCount = getInputPortCount();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const TRectD &tileRect = ::tileRect(tile);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::vector<trectd> inputRects(pCount);</trectd>
Toshihiro Shimizu 890ddd
	std::vector<taffine> inputAffines(pCount);</taffine>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Calculate input tiles
Toshihiro Shimizu 890ddd
	::ContextLocker cLocker(context);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	tcg::unique_ptr<ttile[]> inTiles(new TTile[pCount]); // NOTE: Input tiles must be STORED - they cannot</ttile[]>
Toshihiro Shimizu 890ddd
														 // be passed immediately to OpenGL, since *other shader
Toshihiro Shimizu 890ddd
	if (pCount > 0)										 // fxs*, with the very same host context, could lie
Toshihiro Shimizu 890ddd
	{													 // inside this fx's input branches...
Toshihiro Shimizu 890ddd
		getInputData(tileRect, frame, info, inputRects, inputAffines, context);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Release context and mutex
Toshihiro Shimizu 890ddd
		cLocker.unlock();
Toshihiro Shimizu 890ddd
		mLocker.unlock();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (int p = 0; p != pCount; ++p) {
Toshihiro Shimizu 890ddd
			TRasterFxPort &port = m_inputPorts[p];
Toshihiro Shimizu 890ddd
			if (port.isConnected()) {
Toshihiro Shimizu 890ddd
				// Compute input tile
Toshihiro Shimizu 890ddd
				TRectD &inRect = inputRects[p];
Toshihiro Shimizu 890ddd
				if (inRect.getLx() > 0.0 && inRect.getLy() > 0.0) {
Toshihiro Shimizu 890ddd
					::ceilRect(inRect);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					TRenderSettings inputInfo(info);
Toshihiro Shimizu 890ddd
					inputInfo.m_affine = inputAffines[p];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef TRANSFORM_FEEDBACK_COUT
Toshihiro Shimizu 890ddd
					const TAffine &inAff = inputAffines[p];
Toshihiro Shimizu 890ddd
					std::cout << "inRect " << p << ": " << inRect.x0 << " " << inRect.y0 << " " << inRect.x1 << " " << inRect.y1 << "\n";
Toshihiro Shimizu 890ddd
					std::cout << "inAff  " << p << ": " << inAff.a11 << " " << inAff.a12 << " " << inAff.a13 << "\n";
Toshihiro Shimizu 890ddd
					std::cout << "          " << inAff.a21 << " " << inAff.a22 << " " << inAff.a23 << "\n" << std::endl;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					port->allocateAndCompute(inTiles[p], inRect.getP00(),
Toshihiro Shimizu 890ddd
											 TDimension(tround(inRect.getLx()), tround(inRect.getLy())), tile.getRaster(), frame, inputInfo);
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Load input tiles on the GPU as textures
Toshihiro Shimizu 890ddd
		mLocker.relock();
Toshihiro Shimizu 890ddd
		cLocker.relock();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Input tiles are NOT supplied to OpenGL here - but rather just before drawing.
Toshihiro Shimizu 890ddd
		// It's probably beacuse a uniform integer variable must have already been bound
Toshihiro Shimizu 890ddd
		// to prepare the associated sampler variable in the linkes program...
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Perform the actual fragment shading
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		locals::touchOutputSize(context, tile.getRaster()->getSize(), info.m_bpp);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		QGLShaderProgram *program = touchShaderProgram(m_shaderInterface->mainShader(), context);
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			ProgramBinder binder(program);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// Bind parameters and textures
Toshihiro Shimizu 890ddd
			bindParameters(program, frame);
Toshihiro Shimizu 890ddd
			bindWorldTransform(program, TTranslation(-tile.m_pos) * info.m_affine);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// Setup input data, if any
Toshihiro Shimizu 890ddd
			locals::TexturesStorage texStorage(context, pCount);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (pCount > 0) {
Toshihiro Shimizu 890ddd
				std::vector<glint> inputs(pCount);</glint>
Toshihiro Shimizu 890ddd
				std::vector<qmatrix3x3> screenToInput(pCount);</qmatrix3x3>
Toshihiro Shimizu 890ddd
				std::vector<qmatrix3x3> inputToScreen(pCount);</qmatrix3x3>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				for (int p = 0; p != pCount; ++p) {
Toshihiro Shimizu 890ddd
					TAffine iToS(
Toshihiro Shimizu 890ddd
						TTranslation(-tile.m_pos) *							   // Output to Screen
Toshihiro Shimizu 890ddd
						info.m_affine *										   // World to Output
Toshihiro Shimizu 890ddd
						inputAffines[p].inv() *								   // Input to World
Toshihiro Shimizu 890ddd
						TTranslation(inputRects[p].getP00()) *				   // Texture to Input
Toshihiro Shimizu 890ddd
						TScale(inputRects[p].getLx(), inputRects[p].getLy())); //
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					TAffine sToI(iToS.inv());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#if QT_VERSION >= 0x050500
Toshihiro Shimizu 890ddd
					float qiToS[9] = {static_cast<float>(iToS.a11), static_cast<float>(iToS.a12), static_cast<float>(iToS.a13),</float></float></float>
Toshihiro Shimizu 890ddd
									  static_cast<float>(iToS.a21), static_cast<float>(iToS.a22), static_cast<float>(iToS.a23),</float></float></float>
Toshihiro Shimizu 890ddd
									  0.0f, 0.0f, 1.0f};
Toshihiro Shimizu 890ddd
					float qsToI[9] = {static_cast<float>(sToI.a11), static_cast<float>(sToI.a12), static_cast<float>(sToI.a13),</float></float></float>
Toshihiro Shimizu 890ddd
									  static_cast<float>(sToI.a21), static_cast<float>(sToI.a22), static_cast<float>(sToI.a23),</float></float></float>
Toshihiro Shimizu 890ddd
									  0.0f, 0.0f, 1.0f};
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
					qreal qiToS[9] = {iToS.a11, iToS.a12, iToS.a13,
Toshihiro Shimizu 890ddd
									  iToS.a21, iToS.a22, iToS.a23,
Toshihiro Shimizu 890ddd
									  0.0, 0.0, 1.0};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					qreal qsToI[9] = {sToI.a11, sToI.a12, sToI.a13,
Toshihiro Shimizu 890ddd
									  sToI.a21, sToI.a22, sToI.a23,
Toshihiro Shimizu 890ddd
									  0.0, 0.0, 1.0};
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
					inputs[p] = p, screenToInput[p] = QMatrix3x3(qsToI), inputToScreen[p] = QMatrix3x3(qiToS);
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				program->setUniformValueArray("inputImage", &inputs[0], pCount);
Toshihiro Shimizu 890ddd
				program->setUniformValueArray("outputToInput", &screenToInput[0], pCount);
Toshihiro Shimizu 890ddd
				program->setUniformValueArray("inputToOutput", &inputToScreen[0], pCount);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				// Load textures
Toshihiro Shimizu 890ddd
				for (int p = 0; p != pCount; ++p)
Toshihiro Shimizu 890ddd
					texStorage.load(inTiles[p].getRaster(), p);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef DIAGNOSTICS
Toshihiro Shimizu 890ddd
			DIAGNOSTICS_TIMER("Shader Overall Times | " + m_shaderInterface->m_mainShader.m_name);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			context.draw(tile.getRaster());
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ShaderFx::doDryCompute(TRectD &rect, double frame, const TRenderSettings &info)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	ShadingContextManager *manager = ShadingContextManager::instance();
Toshihiro Shimizu 890ddd
	if (manager->touchSupport() != ShadingContext::OK)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QMutexLocker mLocker(manager->mutex());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//ShadingContext& context = manager->shadingContext();
Toshihiro Shimizu 890ddd
	std::shared_ptr<shadingcontext> shadingContextPtr(new ShadingContext);</shadingcontext>
Toshihiro Shimizu 890ddd
	ShadingContext &context = *shadingContextPtr.get();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int pCount = getInputPortCount();
Toshihiro Shimizu 890ddd
	if (pCount > 0) {
Toshihiro Shimizu 890ddd
		::ContextLocker cLocker(context);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		std::vector<trectd> inputRects(pCount);</trectd>
Toshihiro Shimizu 890ddd
		std::vector<taffine> inputAffines(pCount);</taffine>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		getInputData(rect, frame, info, inputRects, inputAffines, context);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (int p = 0; p != pCount; ++p) {
Toshihiro Shimizu 890ddd
			TRasterFxPort &port = m_inputPorts[p];
Toshihiro Shimizu 890ddd
			if (port.isConnected()) {
Toshihiro Shimizu 890ddd
				TRectD &inRect = inputRects[p];
Toshihiro Shimizu 890ddd
				if (inRect.getLx() > 0.0 && inRect.getLy() > 0.0) {
Toshihiro Shimizu 890ddd
					::ceilRect(inRect);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					TRenderSettings inputInfo(info);
Toshihiro Shimizu 890ddd
					inputInfo.m_affine = inputAffines[p];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					cLocker.unlock();
Toshihiro Shimizu 890ddd
					mLocker.unlock();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					port->dryCompute(inRect, frame, inputInfo);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					mLocker.relock();
Toshihiro Shimizu 890ddd
					cLocker.relock();
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
const TPersistDeclaration *ShaderFx::getDeclaration() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	FxDeclarationsMap::iterator it = ::l_shaderFxDeclarations.find(
Toshihiro Shimizu 890ddd
		m_shaderInterface->mainShader().m_name);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return (it == ::l_shaderFxDeclarations.end()) ? 0 : it->second;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************
Toshihiro Shimizu 890ddd
//    Shader Interfaces  loading function
Toshihiro Shimizu 890ddd
//****************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void loadShaderInterfaces(const TFilePath &shadersFolder)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// Scan the shaders folder for xml (shader interface) files
Toshihiro Shimizu 890ddd
	QDir shadersDir(QString::fromStdWString(shadersFolder.getWideString()));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QStringList namesFilter("*.xml");
Toshihiro Shimizu 890ddd
	QStringList files = shadersDir.entryList(namesFilter, QDir::Files, QDir::Name | QDir::LocaleAware);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int f, fCount = files.size();
Toshihiro Shimizu 890ddd
	for (f = 0; f != fCount; ++f) {
Toshihiro Shimizu 890ddd
		TIStream is(shadersFolder + TFilePath(files[f].toStdWString()));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Try to load a ShaderInterface instance for the file
Toshihiro Shimizu 890ddd
		ShaderInterface shaderInterface;
Toshihiro Shimizu 890ddd
		is >> shaderInterface;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (shaderInterface.isValid()) {
Toshihiro Shimizu 890ddd
			// Store a ShaderFx factory for the interface
Toshihiro Shimizu 890ddd
			::l_shaderFxDeclarations.insert(std::make_pair(
Toshihiro Shimizu 890ddd
				shaderInterface.mainShader().m_name, new ShaderFxDeclaration(shaderInterface)));
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}