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