/*
* Copyright 2013 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrGLSLPrimitiveProcessor_DEFINED
#define GrGLSLPrimitiveProcessor_DEFINED
#include "GrFragmentProcessor.h"
#include "GrPrimitiveProcessor.h"
#include "glsl/GrGLSLProgramDataManager.h"
#include "glsl/GrGLSLUniformHandler.h"
class GrPrimitiveProcessor;
class GrGLSLPPFragmentBuilder;
class GrGLSLGeometryBuilder;
class GrGLSLGPBuilder;
class GrGLSLVaryingHandler;
class GrGLSLVertexBuilder;
class GrShaderCaps;
class GrGLSLPrimitiveProcessor {
public:
using FPCoordTransformIter = GrFragmentProcessor::CoordTransformIter;
virtual ~GrGLSLPrimitiveProcessor() {}
using UniformHandle = GrGLSLProgramDataManager::UniformHandle;
using SamplerHandle = GrGLSLUniformHandler::SamplerHandle;
using TexelBufferHandle = GrGLSLUniformHandler::TexelBufferHandle;
/**
* This class provides access to the GrCoordTransforms across all GrFragmentProcessors in a
* GrPipeline. It is also used by the primitive processor to specify the fragment shader
* variable that will hold the transformed coords for each GrCoordTransform. It is required that
* the primitive processor iterate over each coord transform and insert a shader var result for
* each. The GrGLSLFragmentProcessors will reference these variables in their fragment code.
*/
class FPCoordTransformHandler : public SkNoncopyable {
public:
FPCoordTransformHandler(const GrPipeline& pipeline,
SkTArray<GrShaderVar>* transformedCoordVars)
: fIter(pipeline)
, fTransformedCoordVars(transformedCoordVars) {}
~FPCoordTransformHandler() { SkASSERT(!this->nextCoordTransform());}
const GrCoordTransform* nextCoordTransform();
// 'args' are constructor params to GrShaderVar.
template<typename... Args>
void specifyCoordsForCurrCoordTransform(Args&&... args) {
SkASSERT(!fAddedCoord);
fTransformedCoordVars->emplace_back(std::forward<Args>(args)...);
SkDEBUGCODE(fAddedCoord = true;)
}
private:
GrFragmentProcessor::CoordTransformIter fIter;
SkDEBUGCODE(bool fAddedCoord = false;)
SkDEBUGCODE(const GrCoordTransform* fCurr = nullptr;)
SkTArray<GrShaderVar>* fTransformedCoordVars;
};
struct EmitArgs {
EmitArgs(GrGLSLVertexBuilder* vertBuilder,
GrGLSLGeometryBuilder* geomBuilder,
GrGLSLPPFragmentBuilder* fragBuilder,
GrGLSLVaryingHandler* varyingHandler,
GrGLSLUniformHandler* uniformHandler,
const GrShaderCaps* caps,
const GrPrimitiveProcessor& gp,
const char* outputColor,
const char* outputCoverage,
const char* rtAdjustName,
const SamplerHandle* texSamplers,
const TexelBufferHandle* texelBuffers,
FPCoordTransformHandler* transformHandler)
: fVertBuilder(vertBuilder)
, fGeomBuilder(geomBuilder)
, fFragBuilder(fragBuilder)
, fVaryingHandler(varyingHandler)
, fUniformHandler(uniformHandler)
, fShaderCaps(caps)
, fGP(gp)
, fOutputColor(outputColor)
, fOutputCoverage(outputCoverage)
, fRTAdjustName(rtAdjustName)
, fTexSamplers(texSamplers)
, fTexelBuffers(texelBuffers)
, fFPCoordTransformHandler(transformHandler) {}
GrGLSLVertexBuilder* fVertBuilder;
GrGLSLGeometryBuilder* fGeomBuilder;
GrGLSLPPFragmentBuilder* fFragBuilder;
GrGLSLVaryingHandler* fVaryingHandler;
GrGLSLUniformHandler* fUniformHandler;
const GrShaderCaps* fShaderCaps;
const GrPrimitiveProcessor& fGP;
const char* fOutputColor;
const char* fOutputCoverage;
const char* fRTAdjustName;
const SamplerHandle* fTexSamplers;
const TexelBufferHandle* fTexelBuffers;
FPCoordTransformHandler* fFPCoordTransformHandler;
};
/**
* This is similar to emitCode() in the base class, except it takes a full shader builder.
* This allows the effect subclass to emit vertex code.
*/
virtual void emitCode(EmitArgs&) = 0;
/**
* A GrGLSLPrimitiveProcessor instance can be reused with any GrGLSLPrimitiveProcessor that
* produces the same stage key; this function reads data from a GrGLSLPrimitiveProcessor and
* uploads any uniform variables required by the shaders created in emitCode(). The
* GrPrimitiveProcessor parameter is guaranteed to be of the same type and to have an
* identical processor key as the GrPrimitiveProcessor that created this
* GrGLSLPrimitiveProcessor.
* The subclass may use the transform iterator to perform any setup required for the particular
* set of fp transform matrices, such as uploading via uniforms. The iterator will iterate over
* the transforms in the same order as the TransformHandler passed to emitCode.
*/
virtual void setData(const GrGLSLProgramDataManager&, const GrPrimitiveProcessor&,
FPCoordTransformIter&&) = 0;
static SkMatrix GetTransformMatrix(const SkMatrix& localMatrix, const GrCoordTransform&);
protected:
void setupUniformColor(GrGLSLPPFragmentBuilder* fragBuilder,
GrGLSLUniformHandler* uniformHandler,
const char* outputName,
UniformHandle* colorUniform);
};
#endif