A simple change to move a bunch of stuff out of Gr*Geometry.h
BUG=skia: Review URL: https://codereview.chromium.org/920863002
This commit is contained in:
parent
b0fb935bd5
commit
8072caa803
@ -111,6 +111,8 @@
|
||||
'<(skia_src_path)/gpu/GrPaint.cpp',
|
||||
'<(skia_src_path)/gpu/GrPath.cpp',
|
||||
'<(skia_src_path)/gpu/GrPath.h',
|
||||
'<(skia_src_path)/gpu/GrPathProcessor.cpp',
|
||||
'<(skia_src_path)/gpu/GrPathProcessor.h',
|
||||
'<(skia_src_path)/gpu/GrPathRange.cpp',
|
||||
'<(skia_src_path)/gpu/GrPathRange.h',
|
||||
'<(skia_src_path)/gpu/GrPathRendererChain.cpp',
|
||||
@ -126,6 +128,8 @@
|
||||
'<(skia_src_path)/gpu/GrPipeline.h',
|
||||
'<(skia_src_path)/gpu/GrPipelineBuilder.cpp',
|
||||
'<(skia_src_path)/gpu/GrPipelineBuilder.h',
|
||||
'<(skia_src_path)/gpu/GrPrimitiveProcessor.cpp',
|
||||
'<(skia_src_path)/gpu/GrPrimitiveProcessor.h',
|
||||
'<(skia_src_path)/gpu/GrProgramDesc.h',
|
||||
'<(skia_src_path)/gpu/GrProgramElement.cpp',
|
||||
'<(skia_src_path)/gpu/GrProcessor.cpp',
|
||||
@ -231,6 +235,7 @@
|
||||
'<(skia_src_path)/gpu/gl/GrGLCreateNativeInterface_none.cpp',
|
||||
'<(skia_src_path)/gpu/gl/GrGLDefaultInterface_none.cpp',
|
||||
'<(skia_src_path)/gpu/gl/GrGLDefines.h',
|
||||
'<(skia_src_path)/gpu/gl/GrGLGeometryProcessor.cpp',
|
||||
'<(skia_src_path)/gpu/gl/GrGLGeometryProcessor.h',
|
||||
'<(skia_src_path)/gpu/gl/GrGLGpu.cpp',
|
||||
'<(skia_src_path)/gpu/gl/GrGLGpu.h',
|
||||
@ -246,10 +251,14 @@
|
||||
'<(skia_src_path)/gpu/gl/GrGLNoOpInterface.h',
|
||||
'<(skia_src_path)/gpu/gl/GrGLPath.cpp',
|
||||
'<(skia_src_path)/gpu/gl/GrGLPath.h',
|
||||
'<(skia_src_path)/gpu/gl/GrGLPathProcessor.cpp',
|
||||
'<(skia_src_path)/gpu/gl/GrGLPathProcessor.h',
|
||||
'<(skia_src_path)/gpu/gl/GrGLPathRange.cpp',
|
||||
'<(skia_src_path)/gpu/gl/GrGLPathRange.h',
|
||||
'<(skia_src_path)/gpu/gl/GrGLPathRendering.cpp',
|
||||
'<(skia_src_path)/gpu/gl/GrGLPathRendering.h',
|
||||
'<(skia_src_path)/gpu/gl/GrGLPrimitiveProcessor.cpp',
|
||||
'<(skia_src_path)/gpu/gl/GrGLPrimitiveProcessor.h',
|
||||
'<(skia_src_path)/gpu/gl/GrGLProcessor.h',
|
||||
'<(skia_src_path)/gpu/gl/GrGLProgram.cpp',
|
||||
'<(skia_src_path)/gpu/gl/GrGLProgram.h',
|
||||
|
@ -11,6 +11,8 @@
|
||||
#include "GrClipData.h"
|
||||
#include "GrClipMaskManager.h"
|
||||
#include "GrContext.h"
|
||||
#include "GrPathProcessor.h"
|
||||
#include "GrPrimitiveProcessor.h"
|
||||
#include "GrIndexBuffer.h"
|
||||
#include "GrPathRendering.h"
|
||||
#include "GrPipelineBuilder.h"
|
||||
|
@ -7,70 +7,7 @@
|
||||
|
||||
#include "GrGeometryProcessor.h"
|
||||
|
||||
#include "GrCoordTransform.h"
|
||||
#include "GrInvariantOutput.h"
|
||||
#include "gl/GrGLGeometryProcessor.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* The key for an individual coord transform is made up of a matrix type, a precision, and a bit
|
||||
* that indicates the source of the input coords.
|
||||
*/
|
||||
enum {
|
||||
kMatrixTypeKeyBits = 1,
|
||||
kMatrixTypeKeyMask = (1 << kMatrixTypeKeyBits) - 1,
|
||||
|
||||
kPrecisionBits = 2,
|
||||
kPrecisionShift = kMatrixTypeKeyBits,
|
||||
|
||||
kPositionCoords_Flag = (1 << (kPrecisionShift + kPrecisionBits)),
|
||||
kDeviceCoords_Flag = kPositionCoords_Flag + kPositionCoords_Flag,
|
||||
|
||||
kTransformKeyBits = kMatrixTypeKeyBits + kPrecisionBits + 2,
|
||||
};
|
||||
|
||||
GR_STATIC_ASSERT(kHigh_GrSLPrecision < (1 << kPrecisionBits));
|
||||
|
||||
/**
|
||||
* We specialize the vertex code for each of these matrix types.
|
||||
*/
|
||||
enum MatrixType {
|
||||
kNoPersp_MatrixType = 0,
|
||||
kGeneral_MatrixType = 1,
|
||||
};
|
||||
|
||||
uint32_t
|
||||
GrPrimitiveProcessor::getTransformKey(const SkTArray<const GrCoordTransform*, true>& coords) const {
|
||||
uint32_t totalKey = 0;
|
||||
for (int t = 0; t < coords.count(); ++t) {
|
||||
uint32_t key = 0;
|
||||
const GrCoordTransform* coordTransform = coords[t];
|
||||
if (coordTransform->getMatrix().hasPerspective()) {
|
||||
key |= kGeneral_MatrixType;
|
||||
} else {
|
||||
key |= kNoPersp_MatrixType;
|
||||
}
|
||||
|
||||
if (kLocal_GrCoordSet == coordTransform->sourceCoords() &&
|
||||
!this->hasExplicitLocalCoords()) {
|
||||
key |= kPositionCoords_Flag;
|
||||
} else if (kDevice_GrCoordSet == coordTransform->sourceCoords()) {
|
||||
key |= kDeviceCoords_Flag;
|
||||
}
|
||||
|
||||
GR_STATIC_ASSERT(kGrSLPrecisionCount <= (1 << kPrecisionBits));
|
||||
key |= (coordTransform->precision() << kPrecisionShift);
|
||||
|
||||
key <<= kTransformKeyBits * t;
|
||||
|
||||
SkASSERT(0 == (totalKey & key)); // keys for each transform ought not to overlap
|
||||
totalKey |= key;
|
||||
}
|
||||
return totalKey;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void GrGeometryProcessor::getInvariantOutputColor(GrInitInvariantOutput* out) const {
|
||||
if (fHasVertexColor) {
|
||||
@ -89,483 +26,4 @@ void GrGeometryProcessor::getInvariantOutputCoverage(GrInitInvariantOutput* out)
|
||||
this->onGetInvariantOutputCoverage(out);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "gl/builders/GrGLProgramBuilder.h"
|
||||
|
||||
SkMatrix GrGLPrimitiveProcessor::GetTransformMatrix(const SkMatrix& localMatrix,
|
||||
const GrCoordTransform& coordTransform) {
|
||||
SkMatrix combined;
|
||||
// We only apply the localmatrix to localcoords
|
||||
if (kLocal_GrCoordSet == coordTransform.sourceCoords()) {
|
||||
combined.setConcat(coordTransform.getMatrix(), localMatrix);
|
||||
} else {
|
||||
combined = coordTransform.getMatrix();
|
||||
}
|
||||
if (coordTransform.reverseY()) {
|
||||
// combined.postScale(1,-1);
|
||||
// combined.postTranslate(0,1);
|
||||
combined.set(SkMatrix::kMSkewY,
|
||||
combined[SkMatrix::kMPersp0] - combined[SkMatrix::kMSkewY]);
|
||||
combined.set(SkMatrix::kMScaleY,
|
||||
combined[SkMatrix::kMPersp1] - combined[SkMatrix::kMScaleY]);
|
||||
combined.set(SkMatrix::kMTransY,
|
||||
combined[SkMatrix::kMPersp2] - combined[SkMatrix::kMTransY]);
|
||||
}
|
||||
return combined;
|
||||
}
|
||||
|
||||
void
|
||||
GrGLPrimitiveProcessor::setupColorPassThrough(GrGLGPBuilder* pb,
|
||||
GrGPInput inputType,
|
||||
const char* outputName,
|
||||
const GrGeometryProcessor::Attribute* colorAttr,
|
||||
UniformHandle* colorUniform) {
|
||||
GrGLGPFragmentBuilder* fs = pb->getFragmentShaderBuilder();
|
||||
if (kUniform_GrGPInput == inputType) {
|
||||
SkASSERT(colorUniform);
|
||||
const char* stagedLocalVarName;
|
||||
*colorUniform = pb->addUniform(GrGLProgramBuilder::kFragment_Visibility,
|
||||
kVec4f_GrSLType,
|
||||
kDefault_GrSLPrecision,
|
||||
"Color",
|
||||
&stagedLocalVarName);
|
||||
fs->codeAppendf("%s = %s;", outputName, stagedLocalVarName);
|
||||
} else if (kAttribute_GrGPInput == inputType) {
|
||||
SkASSERT(colorAttr);
|
||||
pb->addPassThroughAttribute(colorAttr, outputName);
|
||||
} else if (kAllOnes_GrGPInput == inputType) {
|
||||
fs->codeAppendf("%s = vec4(1);", outputName);
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLPrimitiveProcessor::addUniformViewMatrix(GrGLGPBuilder* pb) {
|
||||
fViewMatrixUniform = pb->addUniform(GrGLProgramBuilder::kVertex_Visibility,
|
||||
kMat33f_GrSLType, kDefault_GrSLPrecision,
|
||||
"uViewM",
|
||||
&fViewMatrixName);
|
||||
}
|
||||
|
||||
void GrGLPrimitiveProcessor::setUniformViewMatrix(const GrGLProgramDataManager& pdman,
|
||||
const SkMatrix& viewMatrix) {
|
||||
if (!fViewMatrix.cheapEqualTo(viewMatrix)) {
|
||||
SkASSERT(fViewMatrixUniform.isValid());
|
||||
fViewMatrix = viewMatrix;
|
||||
|
||||
GrGLfloat viewMatrix[3 * 3];
|
||||
GrGLGetMatrix<3>(viewMatrix, fViewMatrix);
|
||||
pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
void GrGLGeometryProcessor::emitCode(EmitArgs& args) {
|
||||
GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
|
||||
GrGPArgs gpArgs;
|
||||
this->onEmitCode(args, &gpArgs);
|
||||
vsBuilder->transformToNormalizedDeviceSpace(gpArgs.fPositionVar);
|
||||
}
|
||||
|
||||
void GrGLGeometryProcessor::emitTransforms(GrGLGPBuilder* pb,
|
||||
const GrShaderVar& posVar,
|
||||
const char* localCoords,
|
||||
const SkMatrix& localMatrix,
|
||||
const TransformsIn& tin,
|
||||
TransformsOut* tout) {
|
||||
GrGLVertexBuilder* vb = pb->getVertexShaderBuilder();
|
||||
tout->push_back_n(tin.count());
|
||||
fInstalledTransforms.push_back_n(tin.count());
|
||||
for (int i = 0; i < tin.count(); i++) {
|
||||
const ProcCoords& coordTransforms = tin[i];
|
||||
fInstalledTransforms[i].push_back_n(coordTransforms.count());
|
||||
for (int t = 0; t < coordTransforms.count(); t++) {
|
||||
SkString strUniName("StageMatrix");
|
||||
strUniName.appendf("_%i_%i", i, t);
|
||||
GrSLType varyingType;
|
||||
|
||||
GrCoordSet coordType = coordTransforms[t]->sourceCoords();
|
||||
uint32_t type = coordTransforms[t]->getMatrix().getType();
|
||||
if (kLocal_GrCoordSet == coordType) {
|
||||
type |= localMatrix.getType();
|
||||
}
|
||||
varyingType = SkToBool(SkMatrix::kPerspective_Mask & type) ? kVec3f_GrSLType :
|
||||
kVec2f_GrSLType;
|
||||
GrSLPrecision precision = coordTransforms[t]->precision();
|
||||
|
||||
const char* uniName;
|
||||
fInstalledTransforms[i][t].fHandle =
|
||||
pb->addUniform(GrGLProgramBuilder::kVertex_Visibility,
|
||||
kMat33f_GrSLType, precision,
|
||||
strUniName.c_str(),
|
||||
&uniName).toShaderBuilderIndex();
|
||||
|
||||
SkString strVaryingName("MatrixCoord");
|
||||
strVaryingName.appendf("_%i_%i", i, t);
|
||||
|
||||
GrGLVertToFrag v(varyingType);
|
||||
pb->addVarying(strVaryingName.c_str(), &v, precision);
|
||||
|
||||
SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
|
||||
SkNEW_APPEND_TO_TARRAY(&(*tout)[i], GrGLProcessor::TransformedCoords,
|
||||
(SkString(v.fsIn()), varyingType));
|
||||
|
||||
// varying = matrix * coords (logically)
|
||||
if (kDevice_GrCoordSet == coordType) {
|
||||
if (kVec2f_GrSLType == varyingType) {
|
||||
if (kVec2f_GrSLType == posVar.getType()) {
|
||||
vb->codeAppendf("%s = (%s * vec3(%s, 1)).xy;",
|
||||
v.vsOut(), uniName, posVar.c_str());
|
||||
} else {
|
||||
// The brackets here are just to scope the temp variable
|
||||
vb->codeAppendf("{ vec3 temp = %s * %s;", uniName, posVar.c_str());
|
||||
vb->codeAppendf("%s = vec2(temp.x/temp.z, temp.y/temp.z); }", v.vsOut());
|
||||
}
|
||||
} else {
|
||||
if (kVec2f_GrSLType == posVar.getType()) {
|
||||
vb->codeAppendf("%s = %s * vec3(%s, 1);",
|
||||
v.vsOut(), uniName, posVar.c_str());
|
||||
} else {
|
||||
vb->codeAppendf("%s = %s * %s;", v.vsOut(), uniName, posVar.c_str());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (kVec2f_GrSLType == varyingType) {
|
||||
vb->codeAppendf("%s = (%s * vec3(%s, 1)).xy;", v.vsOut(), uniName, localCoords);
|
||||
} else {
|
||||
vb->codeAppendf("%s = %s * vec3(%s, 1);", v.vsOut(), uniName, localCoords);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
GrGLGeometryProcessor::setTransformData(const GrPrimitiveProcessor& primProc,
|
||||
const GrGLProgramDataManager& pdman,
|
||||
int index,
|
||||
const SkTArray<const GrCoordTransform*, true>& transforms) {
|
||||
SkSTArray<2, Transform, true>& procTransforms = fInstalledTransforms[index];
|
||||
int numTransforms = transforms.count();
|
||||
for (int t = 0; t < numTransforms; ++t) {
|
||||
SkASSERT(procTransforms[t].fHandle.isValid());
|
||||
const SkMatrix& transform = GetTransformMatrix(primProc.localMatrix(), *transforms[t]);
|
||||
if (!procTransforms[t].fCurrentValue.cheapEqualTo(transform)) {
|
||||
pdman.setSkMatrix(procTransforms[t].fHandle.convertToUniformHandle(), transform);
|
||||
procTransforms[t].fCurrentValue = transform;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLGeometryProcessor::SetupPosition(GrGLVertexBuilder* vsBuilder,
|
||||
GrGPArgs* gpArgs,
|
||||
const char* posName,
|
||||
const SkMatrix& mat,
|
||||
const char* matName) {
|
||||
if (mat.isIdentity()) {
|
||||
gpArgs->fPositionVar.set(kVec2f_GrSLType, "pos2");
|
||||
|
||||
vsBuilder->codeAppendf("vec2 %s = %s;", gpArgs->fPositionVar.c_str(), posName);
|
||||
} else if (!mat.hasPerspective()) {
|
||||
gpArgs->fPositionVar.set(kVec2f_GrSLType, "pos2");
|
||||
|
||||
vsBuilder->codeAppendf("vec2 %s = vec2(%s * vec3(%s, 1));",
|
||||
gpArgs->fPositionVar.c_str(), matName, posName);
|
||||
} else {
|
||||
gpArgs->fPositionVar.set(kVec3f_GrSLType, "pos3");
|
||||
|
||||
vsBuilder->codeAppendf("vec3 %s = %s * vec3(%s, 1);",
|
||||
gpArgs->fPositionVar.c_str(), matName, posName);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "gl/GrGLGpu.h"
|
||||
#include "gl/GrGLPathRendering.h"
|
||||
|
||||
struct PathBatchTracker {
|
||||
GrGPInput fInputColorType;
|
||||
GrGPInput fInputCoverageType;
|
||||
GrColor fColor;
|
||||
bool fUsesLocalCoords;
|
||||
};
|
||||
|
||||
GrGLPathProcessor::GrGLPathProcessor(const GrPathProcessor&, const GrBatchTracker&)
|
||||
: fColor(GrColor_ILLEGAL) {}
|
||||
|
||||
void GrGLPathProcessor::emitCode(EmitArgs& args) {
|
||||
GrGLGPBuilder* pb = args.fPB;
|
||||
GrGLGPFragmentBuilder* fs = args.fPB->getFragmentShaderBuilder();
|
||||
const PathBatchTracker& local = args.fBT.cast<PathBatchTracker>();
|
||||
|
||||
// emit transforms
|
||||
this->emitTransforms(args.fPB, args.fTransformsIn, args.fTransformsOut);
|
||||
|
||||
// Setup uniform color
|
||||
if (kUniform_GrGPInput == local.fInputColorType) {
|
||||
const char* stagedLocalVarName;
|
||||
fColorUniform = pb->addUniform(GrGLProgramBuilder::kFragment_Visibility,
|
||||
kVec4f_GrSLType,
|
||||
kDefault_GrSLPrecision,
|
||||
"Color",
|
||||
&stagedLocalVarName);
|
||||
fs->codeAppendf("%s = %s;", args.fOutputColor, stagedLocalVarName);
|
||||
}
|
||||
|
||||
// setup constant solid coverage
|
||||
if (kAllOnes_GrGPInput == local.fInputCoverageType) {
|
||||
fs->codeAppendf("%s = vec4(1);", args.fOutputCoverage);
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLPathProcessor::GenKey(const GrPathProcessor&,
|
||||
const GrBatchTracker& bt,
|
||||
const GrGLCaps&,
|
||||
GrProcessorKeyBuilder* b) {
|
||||
const PathBatchTracker& local = bt.cast<PathBatchTracker>();
|
||||
b->add32(local.fInputColorType | local.fInputCoverageType << 16);
|
||||
}
|
||||
|
||||
void GrGLPathProcessor::setData(const GrGLProgramDataManager& pdman,
|
||||
const GrPrimitiveProcessor& primProc,
|
||||
const GrBatchTracker& bt) {
|
||||
const PathBatchTracker& local = bt.cast<PathBatchTracker>();
|
||||
if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
|
||||
GrGLfloat c[4];
|
||||
GrColorToRGBAFloat(local.fColor, c);
|
||||
pdman.set4fv(fColorUniform, 1, c);
|
||||
fColor = local.fColor;
|
||||
}
|
||||
}
|
||||
|
||||
class GrGLLegacyPathProcessor : public GrGLPathProcessor {
|
||||
public:
|
||||
GrGLLegacyPathProcessor(const GrPathProcessor& pathProc, const GrBatchTracker& bt,
|
||||
int maxTexCoords)
|
||||
: INHERITED(pathProc, bt)
|
||||
, fTexCoordSetCnt(0) {
|
||||
SkDEBUGCODE(fMaxTexCoords = maxTexCoords;)
|
||||
}
|
||||
|
||||
int addTexCoordSets(int count) {
|
||||
int firstFreeCoordSet = fTexCoordSetCnt;
|
||||
fTexCoordSetCnt += count;
|
||||
SkASSERT(fMaxTexCoords >= fTexCoordSetCnt);
|
||||
return firstFreeCoordSet;
|
||||
}
|
||||
|
||||
void emitTransforms(GrGLGPBuilder*, const TransformsIn& tin, TransformsOut* tout) SK_OVERRIDE {
|
||||
tout->push_back_n(tin.count());
|
||||
fInstalledTransforms.push_back_n(tin.count());
|
||||
for (int i = 0; i < tin.count(); i++) {
|
||||
const ProcCoords& coordTransforms = tin[i];
|
||||
int texCoordIndex = this->addTexCoordSets(coordTransforms.count());
|
||||
|
||||
// Use the first uniform location as the texcoord index.
|
||||
fInstalledTransforms[i].push_back_n(1);
|
||||
fInstalledTransforms[i][0].fHandle = ShaderVarHandle(texCoordIndex);
|
||||
|
||||
SkString name;
|
||||
for (int t = 0; t < coordTransforms.count(); ++t) {
|
||||
GrSLType type = coordTransforms[t]->getMatrix().hasPerspective() ? kVec3f_GrSLType :
|
||||
kVec2f_GrSLType;
|
||||
|
||||
name.printf("%s(gl_TexCoord[%i])", GrGLSLTypeString(type), texCoordIndex++);
|
||||
SkNEW_APPEND_TO_TARRAY(&(*tout)[i], GrGLProcessor::TransformedCoords, (name, type));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setTransformData(const GrPrimitiveProcessor& primProc,
|
||||
int index,
|
||||
const SkTArray<const GrCoordTransform*, true>& transforms,
|
||||
GrGLPathRendering* glpr,
|
||||
GrGLuint) SK_OVERRIDE {
|
||||
// We've hidden the texcoord index in the first entry of the transforms array for each
|
||||
// effect
|
||||
int texCoordIndex = fInstalledTransforms[index][0].fHandle.handle();
|
||||
for (int t = 0; t < transforms.count(); ++t) {
|
||||
const SkMatrix& transform = GetTransformMatrix(primProc.localMatrix(), *transforms[t]);
|
||||
GrGLPathRendering::PathTexGenComponents components =
|
||||
GrGLPathRendering::kST_PathTexGenComponents;
|
||||
if (transform.hasPerspective()) {
|
||||
components = GrGLPathRendering::kSTR_PathTexGenComponents;
|
||||
}
|
||||
glpr->enablePathTexGen(texCoordIndex++, components, transform);
|
||||
}
|
||||
}
|
||||
|
||||
void didSetData(GrGLPathRendering* glpr) SK_OVERRIDE {
|
||||
glpr->flushPathTexGenSettings(fTexCoordSetCnt);
|
||||
}
|
||||
|
||||
private:
|
||||
SkDEBUGCODE(int fMaxTexCoords;)
|
||||
int fTexCoordSetCnt;
|
||||
|
||||
typedef GrGLPathProcessor INHERITED;
|
||||
};
|
||||
|
||||
class GrGLNormalPathProcessor : public GrGLPathProcessor {
|
||||
public:
|
||||
GrGLNormalPathProcessor(const GrPathProcessor& pathProc, const GrBatchTracker& bt)
|
||||
: INHERITED(pathProc, bt) {}
|
||||
|
||||
void emitTransforms(GrGLGPBuilder* pb, const TransformsIn& tin,
|
||||
TransformsOut* tout) SK_OVERRIDE {
|
||||
tout->push_back_n(tin.count());
|
||||
fInstalledTransforms.push_back_n(tin.count());
|
||||
for (int i = 0; i < tin.count(); i++) {
|
||||
const ProcCoords& coordTransforms = tin[i];
|
||||
fInstalledTransforms[i].push_back_n(coordTransforms.count());
|
||||
for (int t = 0; t < coordTransforms.count(); t++) {
|
||||
GrSLType varyingType =
|
||||
coordTransforms[t]->getMatrix().hasPerspective() ? kVec3f_GrSLType :
|
||||
kVec2f_GrSLType;
|
||||
|
||||
|
||||
SkString strVaryingName("MatrixCoord");
|
||||
strVaryingName.appendf("_%i_%i", i, t);
|
||||
GrGLVertToFrag v(varyingType);
|
||||
pb->addVarying(strVaryingName.c_str(), &v);
|
||||
SeparableVaryingInfo& varyingInfo = fSeparableVaryingInfos.push_back();
|
||||
varyingInfo.fVariable = pb->getFragmentShaderBuilder()->fInputs.back();
|
||||
varyingInfo.fLocation = fSeparableVaryingInfos.count() - 1;
|
||||
varyingInfo.fType = varyingType;
|
||||
fInstalledTransforms[i][t].fHandle = ShaderVarHandle(varyingInfo.fLocation);
|
||||
fInstalledTransforms[i][t].fType = varyingType;
|
||||
|
||||
SkNEW_APPEND_TO_TARRAY(&(*tout)[i], GrGLProcessor::TransformedCoords,
|
||||
(SkString(v.fsIn()), varyingType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void resolveSeparableVaryings(GrGLGpu* gpu, GrGLuint programId) {
|
||||
int count = fSeparableVaryingInfos.count();
|
||||
for (int i = 0; i < count; ++i) {
|
||||
GrGLint location;
|
||||
GR_GL_CALL_RET(gpu->glInterface(),
|
||||
location,
|
||||
GetProgramResourceLocation(programId,
|
||||
GR_GL_FRAGMENT_INPUT,
|
||||
fSeparableVaryingInfos[i].fVariable.c_str()));
|
||||
fSeparableVaryingInfos[i].fLocation = location;
|
||||
}
|
||||
}
|
||||
|
||||
void setTransformData(const GrPrimitiveProcessor& primProc,
|
||||
int index,
|
||||
const SkTArray<const GrCoordTransform*, true>& coordTransforms,
|
||||
GrGLPathRendering* glpr,
|
||||
GrGLuint programID) SK_OVERRIDE {
|
||||
SkSTArray<2, Transform, true>& transforms = fInstalledTransforms[index];
|
||||
int numTransforms = transforms.count();
|
||||
for (int t = 0; t < numTransforms; ++t) {
|
||||
SkASSERT(transforms[t].fHandle.isValid());
|
||||
const SkMatrix& transform = GetTransformMatrix(primProc.localMatrix(),
|
||||
*coordTransforms[t]);
|
||||
if (transforms[t].fCurrentValue.cheapEqualTo(transform)) {
|
||||
continue;
|
||||
}
|
||||
transforms[t].fCurrentValue = transform;
|
||||
const SeparableVaryingInfo& fragmentInput =
|
||||
fSeparableVaryingInfos[transforms[t].fHandle.handle()];
|
||||
SkASSERT(transforms[t].fType == kVec2f_GrSLType ||
|
||||
transforms[t].fType == kVec3f_GrSLType);
|
||||
unsigned components = transforms[t].fType == kVec2f_GrSLType ? 2 : 3;
|
||||
glpr->setProgramPathFragmentInputTransform(programID,
|
||||
fragmentInput.fLocation,
|
||||
GR_GL_OBJECT_LINEAR,
|
||||
components,
|
||||
transform);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
struct SeparableVaryingInfo {
|
||||
GrSLType fType;
|
||||
GrGLShaderVar fVariable;
|
||||
GrGLint fLocation;
|
||||
};
|
||||
|
||||
|
||||
typedef SkSTArray<8, SeparableVaryingInfo, true> SeparableVaryingInfoArray;
|
||||
|
||||
SeparableVaryingInfoArray fSeparableVaryingInfos;
|
||||
|
||||
typedef GrGLPathProcessor INHERITED;
|
||||
};
|
||||
|
||||
GrPathProcessor::GrPathProcessor(GrColor color,
|
||||
const SkMatrix& viewMatrix,
|
||||
const SkMatrix& localMatrix)
|
||||
: INHERITED(viewMatrix, localMatrix, true)
|
||||
, fColor(color) {
|
||||
this->initClassID<GrPathProcessor>();
|
||||
}
|
||||
|
||||
void GrPathProcessor::getInvariantOutputColor(GrInitInvariantOutput* out) const {
|
||||
out->setKnownFourComponents(fColor);
|
||||
}
|
||||
|
||||
void GrPathProcessor::getInvariantOutputCoverage(GrInitInvariantOutput* out) const {
|
||||
out->setKnownSingleComponent(0xff);
|
||||
}
|
||||
|
||||
void GrPathProcessor::initBatchTracker(GrBatchTracker* bt, const GrPipelineInfo& init) const {
|
||||
PathBatchTracker* local = bt->cast<PathBatchTracker>();
|
||||
if (init.fColorIgnored) {
|
||||
local->fInputColorType = kIgnored_GrGPInput;
|
||||
local->fColor = GrColor_ILLEGAL;
|
||||
} else {
|
||||
local->fInputColorType = kUniform_GrGPInput;
|
||||
local->fColor = GrColor_ILLEGAL == init.fOverrideColor ? this->color() :
|
||||
init.fOverrideColor;
|
||||
}
|
||||
|
||||
local->fInputCoverageType = init.fCoverageIgnored ? kIgnored_GrGPInput : kAllOnes_GrGPInput;
|
||||
local->fUsesLocalCoords = init.fUsesLocalCoords;
|
||||
}
|
||||
|
||||
bool GrPathProcessor::canMakeEqual(const GrBatchTracker& m,
|
||||
const GrPrimitiveProcessor& that,
|
||||
const GrBatchTracker& t) const {
|
||||
if (this->classID() != that.classID() || !this->hasSameTextureAccesses(that)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this->viewMatrix().cheapEqualTo(that.viewMatrix())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const PathBatchTracker& mine = m.cast<PathBatchTracker>();
|
||||
const PathBatchTracker& theirs = t.cast<PathBatchTracker>();
|
||||
return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
|
||||
that, theirs.fUsesLocalCoords) &&
|
||||
CanCombineOutput(mine.fInputColorType, mine.fColor,
|
||||
theirs.fInputColorType, theirs.fColor) &&
|
||||
CanCombineOutput(mine.fInputCoverageType, 0xff,
|
||||
theirs.fInputCoverageType, 0xff);
|
||||
}
|
||||
|
||||
void GrPathProcessor::getGLProcessorKey(const GrBatchTracker& bt,
|
||||
const GrGLCaps& caps,
|
||||
GrProcessorKeyBuilder* b) const {
|
||||
GrGLPathProcessor::GenKey(*this, bt, caps, b);
|
||||
}
|
||||
|
||||
GrGLPrimitiveProcessor* GrPathProcessor::createGLInstance(const GrBatchTracker& bt,
|
||||
const GrGLCaps& caps) const {
|
||||
SkASSERT(caps.nvprSupport() != GrGLCaps::kNone_NvprSupport);
|
||||
if (caps.nvprSupport() == GrGLCaps::kLegacy_NvprSupport) {
|
||||
return SkNEW_ARGS(GrGLLegacyPathProcessor, (*this, bt,
|
||||
caps.maxFixedFunctionTextureCoords()));
|
||||
} else {
|
||||
return SkNEW_ARGS(GrGLNormalPathProcessor, (*this, bt));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,224 +8,7 @@
|
||||
#ifndef GrGeometryProcessor_DEFINED
|
||||
#define GrGeometryProcessor_DEFINED
|
||||
|
||||
#include "GrColor.h"
|
||||
#include "GrProcessor.h"
|
||||
#include "GrShaderVar.h"
|
||||
|
||||
/*
|
||||
* The GrPrimitiveProcessor represents some kind of geometric primitive. This includes the shape
|
||||
* of the primitive and the inherent color of the primitive. The GrPrimitiveProcessor is
|
||||
* responsible for providing a color and coverage input into the Ganesh rendering pipeline. Through
|
||||
* optimization, Ganesh may decide a different color, no color, and / or no coverage are required
|
||||
* from the GrPrimitiveProcessor, so the GrPrimitiveProcessor must be able to support this
|
||||
* functionality. We also use the GrPrimitiveProcessor to make batching decisions.
|
||||
*
|
||||
* There are two feedback loops between the GrFragmentProcessors, the GrXferProcessor, and the
|
||||
* GrPrimitiveProcessor. These loops run on the CPU and compute any invariant components which
|
||||
* might be useful for correctness / optimization decisions. The GrPrimitiveProcessor seeds these
|
||||
* loops, one with initial color and one with initial coverage, in its
|
||||
* onComputeInvariantColor / Coverage calls. These seed values are processed by the subsequent
|
||||
* stages of the rendering pipeline and the output is then fed back into the GrPrimitiveProcessor in
|
||||
* the initBatchTracker call, where the GrPrimitiveProcessor can then initialize the GrBatchTracker
|
||||
* struct with the appropriate values.
|
||||
*
|
||||
* We are evolving this system to move towards generating geometric meshes and their associated
|
||||
* vertex data after we have batched and reordered draws. This system, known as 'deferred geometry'
|
||||
* will allow the GrPrimitiveProcessor much greater control over how data is transmitted to shaders.
|
||||
*
|
||||
* In a deferred geometry world, the GrPrimitiveProcessor can always 'batch' To do this, each
|
||||
* primitive type is associated with one GrPrimitiveProcessor, who has complete control of how
|
||||
* it draws. Each primitive draw will bundle all required data to perform the draw, and these
|
||||
* bundles of data will be owned by an instance of the associated GrPrimitiveProcessor. Bundles
|
||||
* can be updated alongside the GrBatchTracker struct itself, ultimately allowing the
|
||||
* GrPrimitiveProcessor complete control of how it gets data into the fragment shader as long as
|
||||
* it emits the appropriate color, or none at all, as directed.
|
||||
*/
|
||||
|
||||
/*
|
||||
* A struct for tracking batching decisions. While this lives on GrOptState, it is managed
|
||||
* entirely by the derived classes of the GP.
|
||||
* // TODO this was an early attempt at handling out of order batching. It should be
|
||||
* used carefully as it is being replaced by GrBatch
|
||||
*/
|
||||
class GrBatchTracker {
|
||||
public:
|
||||
template <typename T> const T& cast() const {
|
||||
SkASSERT(sizeof(T) <= kMaxSize);
|
||||
return *reinterpret_cast<const T*>(fData.get());
|
||||
}
|
||||
|
||||
template <typename T> T* cast() {
|
||||
SkASSERT(sizeof(T) <= kMaxSize);
|
||||
return reinterpret_cast<T*>(fData.get());
|
||||
}
|
||||
|
||||
static const size_t kMaxSize = 32;
|
||||
|
||||
private:
|
||||
SkAlignedSStorage<kMaxSize> fData;
|
||||
};
|
||||
|
||||
class GrIndexBufferAllocPool;
|
||||
class GrGLCaps;
|
||||
class GrGLPrimitiveProcessor;
|
||||
class GrVertexBufferAllocPool;
|
||||
|
||||
struct GrInitInvariantOutput;
|
||||
|
||||
/*
|
||||
* This struct allows the GrPipeline to communicate information about the pipeline. Most of this
|
||||
* is overrides, but some of it is general information. Logically it should live in GrPipeline.h,
|
||||
* but this is problematic due to circular dependencies.
|
||||
*/
|
||||
struct GrPipelineInfo {
|
||||
bool fColorIgnored;
|
||||
bool fCoverageIgnored;
|
||||
GrColor fOverrideColor;
|
||||
bool fUsesLocalCoords;
|
||||
};
|
||||
|
||||
/*
|
||||
* This enum is shared by GrPrimitiveProcessors and GrGLPrimitiveProcessors to coordinate shaders
|
||||
* with vertex attributes / uniforms.
|
||||
*/
|
||||
enum GrGPInput {
|
||||
kAllOnes_GrGPInput,
|
||||
kAttribute_GrGPInput,
|
||||
kUniform_GrGPInput,
|
||||
kIgnored_GrGPInput,
|
||||
};
|
||||
|
||||
/*
|
||||
* GrPrimitiveProcessor defines an interface which all subclasses must implement. All
|
||||
* GrPrimitiveProcessors must proivide seed color and coverage for the Ganesh color / coverage
|
||||
* pipelines, and they must provide some notion of equality
|
||||
*/
|
||||
class GrPrimitiveProcessor : public GrProcessor {
|
||||
public:
|
||||
// TODO let the PrimProc itself set this in its setData call, this should really live on the
|
||||
// bundle of primitive data
|
||||
const SkMatrix& viewMatrix() const { return fViewMatrix; }
|
||||
const SkMatrix& localMatrix() const { return fLocalMatrix; }
|
||||
|
||||
virtual void initBatchTracker(GrBatchTracker*, const GrPipelineInfo&) const = 0;
|
||||
|
||||
virtual bool canMakeEqual(const GrBatchTracker& mine,
|
||||
const GrPrimitiveProcessor& that,
|
||||
const GrBatchTracker& theirs) const = 0;
|
||||
|
||||
virtual void getInvariantOutputColor(GrInitInvariantOutput* out) const = 0;
|
||||
virtual void getInvariantOutputCoverage(GrInitInvariantOutput* out) const = 0;
|
||||
|
||||
// Only the GrGeometryProcessor subclass actually has a geo shader or vertex attributes, but
|
||||
// we put these calls on the base class to prevent having to cast
|
||||
virtual bool willUseGeoShader() const = 0;
|
||||
|
||||
/*
|
||||
* This is a safeguard to prevent GrPrimitiveProcessor's from going beyond platform specific
|
||||
* attribute limits. This number can almost certainly be raised if required.
|
||||
*/
|
||||
static const int kMaxVertexAttribs = 6;
|
||||
|
||||
struct Attribute {
|
||||
Attribute()
|
||||
: fName(NULL)
|
||||
, fType(kFloat_GrVertexAttribType)
|
||||
, fOffset(0) {}
|
||||
Attribute(const char* name, GrVertexAttribType type)
|
||||
: fName(name)
|
||||
, fType(type)
|
||||
, fOffset(SkAlign4(GrVertexAttribTypeSize(type))) {}
|
||||
const char* fName;
|
||||
GrVertexAttribType fType;
|
||||
size_t fOffset;
|
||||
};
|
||||
|
||||
int numAttribs() const { return fNumAttribs; }
|
||||
const Attribute& getAttrib(int index) const {
|
||||
SkASSERT(index < fNumAttribs);
|
||||
return fAttribs[index];
|
||||
}
|
||||
|
||||
// Returns the vertex stride of the GP. A common use case is to request geometry from a
|
||||
// drawtarget based off of the stride, and to populate this memory using an implicit array of
|
||||
// structs. In this case, it is best to assert the vertexstride == sizeof(VertexStruct).
|
||||
size_t getVertexStride() const { return fVertexStride; }
|
||||
|
||||
/**
|
||||
* Gets a transformKey from an array of coord transforms
|
||||
*/
|
||||
uint32_t getTransformKey(const SkTArray<const GrCoordTransform*, true>&) const;
|
||||
|
||||
/**
|
||||
* Sets a unique key on the GrProcessorKeyBuilder that is directly associated with this geometry
|
||||
* processor's GL backend implementation.
|
||||
*/
|
||||
virtual void getGLProcessorKey(const GrBatchTracker& bt,
|
||||
const GrGLCaps& caps,
|
||||
GrProcessorKeyBuilder* b) const = 0;
|
||||
|
||||
|
||||
/** Returns a new instance of the appropriate *GL* implementation class
|
||||
for the given GrProcessor; caller is responsible for deleting
|
||||
the object. */
|
||||
virtual GrGLPrimitiveProcessor* createGLInstance(const GrBatchTracker& bt,
|
||||
const GrGLCaps& caps) const = 0;
|
||||
|
||||
bool isPathRendering() const { return fIsPathRendering; }
|
||||
|
||||
protected:
|
||||
GrPrimitiveProcessor(const SkMatrix& viewMatrix, const SkMatrix& localMatrix,
|
||||
bool isPathRendering)
|
||||
: fNumAttribs(0)
|
||||
, fVertexStride(0)
|
||||
, fViewMatrix(viewMatrix)
|
||||
, fLocalMatrix(localMatrix)
|
||||
, fIsPathRendering(isPathRendering) {}
|
||||
|
||||
/*
|
||||
* CanCombineOutput will return true if two draws are 'batchable' from a color perspective.
|
||||
* TODO remove this when GPs can upgrade to attribute color
|
||||
*/
|
||||
static bool CanCombineOutput(GrGPInput left, GrColor lColor, GrGPInput right, GrColor rColor) {
|
||||
if (left != right) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (kUniform_GrGPInput == left && lColor != rColor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool CanCombineLocalMatrices(const GrPrimitiveProcessor& left,
|
||||
bool leftUsesLocalCoords,
|
||||
const GrPrimitiveProcessor& right,
|
||||
bool rightUsesLocalCoords) {
|
||||
if (leftUsesLocalCoords != rightUsesLocalCoords) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (leftUsesLocalCoords && !left.localMatrix().cheapEqualTo(right.localMatrix())) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Attribute fAttribs[kMaxVertexAttribs];
|
||||
int fNumAttribs;
|
||||
size_t fVertexStride;
|
||||
|
||||
private:
|
||||
virtual bool hasExplicitLocalCoords() const = 0;
|
||||
|
||||
const SkMatrix fViewMatrix;
|
||||
SkMatrix fLocalMatrix;
|
||||
bool fIsPathRendering;
|
||||
|
||||
typedef GrProcessor INHERITED;
|
||||
};
|
||||
#include "GrPrimitiveProcessor.h"
|
||||
|
||||
/**
|
||||
* A GrGeometryProcessor is a flexible method for rendering a primitive. The GrGeometryProcessor
|
||||
@ -370,49 +153,4 @@ private:
|
||||
typedef GrPrimitiveProcessor INHERITED;
|
||||
};
|
||||
|
||||
/*
|
||||
* The path equivalent of the GP. For now this just manages color. In the long term we plan on
|
||||
* extending this class to handle all nvpr uniform / varying / program work.
|
||||
*/
|
||||
class GrPathProcessor : public GrPrimitiveProcessor {
|
||||
public:
|
||||
static GrPathProcessor* Create(GrColor color,
|
||||
const SkMatrix& viewMatrix = SkMatrix::I(),
|
||||
const SkMatrix& localMatrix = SkMatrix::I()) {
|
||||
return SkNEW_ARGS(GrPathProcessor, (color, viewMatrix, localMatrix));
|
||||
}
|
||||
|
||||
void initBatchTracker(GrBatchTracker*, const GrPipelineInfo&) const SK_OVERRIDE;
|
||||
|
||||
bool canMakeEqual(const GrBatchTracker& mine,
|
||||
const GrPrimitiveProcessor& that,
|
||||
const GrBatchTracker& theirs) const SK_OVERRIDE;
|
||||
|
||||
const char* name() const SK_OVERRIDE { return "PathProcessor"; }
|
||||
|
||||
GrColor color() const { return fColor; }
|
||||
|
||||
void getInvariantOutputColor(GrInitInvariantOutput* out) const SK_OVERRIDE;
|
||||
void getInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRIDE;
|
||||
|
||||
bool willUseGeoShader() const SK_OVERRIDE { return false; }
|
||||
|
||||
virtual void getGLProcessorKey(const GrBatchTracker& bt,
|
||||
const GrGLCaps& caps,
|
||||
GrProcessorKeyBuilder* b) const SK_OVERRIDE;
|
||||
|
||||
virtual GrGLPrimitiveProcessor* createGLInstance(const GrBatchTracker& bt,
|
||||
const GrGLCaps& caps) const SK_OVERRIDE;
|
||||
|
||||
protected:
|
||||
GrPathProcessor(GrColor color, const SkMatrix& viewMatrix, const SkMatrix& localMatrix);
|
||||
|
||||
private:
|
||||
bool hasExplicitLocalCoords() const SK_OVERRIDE { return false; }
|
||||
|
||||
GrColor fColor;
|
||||
|
||||
typedef GrPrimitiveProcessor INHERITED;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
73
src/gpu/GrPathProcessor.cpp
Normal file
73
src/gpu/GrPathProcessor.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
#include "GrPathProcessor.h"
|
||||
|
||||
#include "gl/GrGLPathProcessor.h"
|
||||
#include "gl/GrGLGpu.h"
|
||||
|
||||
GrPathProcessor::GrPathProcessor(GrColor color,
|
||||
const SkMatrix& viewMatrix,
|
||||
const SkMatrix& localMatrix)
|
||||
: INHERITED(viewMatrix, localMatrix, true)
|
||||
, fColor(color) {
|
||||
this->initClassID<GrPathProcessor>();
|
||||
}
|
||||
|
||||
void GrPathProcessor::getInvariantOutputColor(GrInitInvariantOutput* out) const {
|
||||
out->setKnownFourComponents(fColor);
|
||||
}
|
||||
|
||||
void GrPathProcessor::getInvariantOutputCoverage(GrInitInvariantOutput* out) const {
|
||||
out->setKnownSingleComponent(0xff);
|
||||
}
|
||||
|
||||
void GrPathProcessor::initBatchTracker(GrBatchTracker* bt, const GrPipelineInfo& init) const {
|
||||
PathBatchTracker* local = bt->cast<PathBatchTracker>();
|
||||
if (init.fColorIgnored) {
|
||||
local->fInputColorType = kIgnored_GrGPInput;
|
||||
local->fColor = GrColor_ILLEGAL;
|
||||
} else {
|
||||
local->fInputColorType = kUniform_GrGPInput;
|
||||
local->fColor = GrColor_ILLEGAL == init.fOverrideColor ? this->color() :
|
||||
init.fOverrideColor;
|
||||
}
|
||||
|
||||
local->fInputCoverageType = init.fCoverageIgnored ? kIgnored_GrGPInput : kAllOnes_GrGPInput;
|
||||
local->fUsesLocalCoords = init.fUsesLocalCoords;
|
||||
}
|
||||
|
||||
bool GrPathProcessor::canMakeEqual(const GrBatchTracker& m,
|
||||
const GrPrimitiveProcessor& that,
|
||||
const GrBatchTracker& t) const {
|
||||
if (this->classID() != that.classID() || !this->hasSameTextureAccesses(that)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this->viewMatrix().cheapEqualTo(that.viewMatrix())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const PathBatchTracker& mine = m.cast<PathBatchTracker>();
|
||||
const PathBatchTracker& theirs = t.cast<PathBatchTracker>();
|
||||
return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
|
||||
that, theirs.fUsesLocalCoords) &&
|
||||
CanCombineOutput(mine.fInputColorType, mine.fColor,
|
||||
theirs.fInputColorType, theirs.fColor) &&
|
||||
CanCombineOutput(mine.fInputCoverageType, 0xff,
|
||||
theirs.fInputCoverageType, 0xff);
|
||||
}
|
||||
|
||||
void GrPathProcessor::getGLProcessorKey(const GrBatchTracker& bt,
|
||||
const GrGLCaps& caps,
|
||||
GrProcessorKeyBuilder* b) const {
|
||||
GrGLPathProcessor::GenKey(*this, bt, caps, b);
|
||||
}
|
||||
|
||||
GrGLPrimitiveProcessor* GrPathProcessor::createGLInstance(const GrBatchTracker& bt,
|
||||
const GrGLCaps& caps) const {
|
||||
SkASSERT(caps.nvprSupport() != GrGLCaps::kNone_NvprSupport);
|
||||
if (caps.nvprSupport() == GrGLCaps::kLegacy_NvprSupport) {
|
||||
return SkNEW_ARGS(GrGLLegacyPathProcessor, (*this, bt,
|
||||
caps.maxFixedFunctionTextureCoords()));
|
||||
} else {
|
||||
return SkNEW_ARGS(GrGLNormalPathProcessor, (*this, bt));
|
||||
}
|
||||
}
|
65
src/gpu/GrPathProcessor.h
Normal file
65
src/gpu/GrPathProcessor.h
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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 GrPathProcessor_DEFINED
|
||||
#define GrPathProcessor_DEFINED
|
||||
|
||||
#include "GrPrimitiveProcessor.h"
|
||||
|
||||
struct PathBatchTracker {
|
||||
GrGPInput fInputColorType;
|
||||
GrGPInput fInputCoverageType;
|
||||
GrColor fColor;
|
||||
bool fUsesLocalCoords;
|
||||
};
|
||||
|
||||
/*
|
||||
* The path equivalent of the GP. For now this just manages color. In the long term we plan on
|
||||
* extending this class to handle all nvpr uniform / varying / program work.
|
||||
*/
|
||||
class GrPathProcessor : public GrPrimitiveProcessor {
|
||||
public:
|
||||
static GrPathProcessor* Create(GrColor color,
|
||||
const SkMatrix& viewMatrix = SkMatrix::I(),
|
||||
const SkMatrix& localMatrix = SkMatrix::I()) {
|
||||
return SkNEW_ARGS(GrPathProcessor, (color, viewMatrix, localMatrix));
|
||||
}
|
||||
|
||||
void initBatchTracker(GrBatchTracker*, const GrPipelineInfo&) const SK_OVERRIDE;
|
||||
|
||||
bool canMakeEqual(const GrBatchTracker& mine,
|
||||
const GrPrimitiveProcessor& that,
|
||||
const GrBatchTracker& theirs) const SK_OVERRIDE;
|
||||
|
||||
const char* name() const SK_OVERRIDE { return "PathProcessor"; }
|
||||
|
||||
GrColor color() const { return fColor; }
|
||||
|
||||
void getInvariantOutputColor(GrInitInvariantOutput* out) const SK_OVERRIDE;
|
||||
void getInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRIDE;
|
||||
|
||||
bool willUseGeoShader() const SK_OVERRIDE { return false; }
|
||||
|
||||
virtual void getGLProcessorKey(const GrBatchTracker& bt,
|
||||
const GrGLCaps& caps,
|
||||
GrProcessorKeyBuilder* b) const SK_OVERRIDE;
|
||||
|
||||
virtual GrGLPrimitiveProcessor* createGLInstance(const GrBatchTracker& bt,
|
||||
const GrGLCaps& caps) const SK_OVERRIDE;
|
||||
|
||||
protected:
|
||||
GrPathProcessor(GrColor color, const SkMatrix& viewMatrix, const SkMatrix& localMatrix);
|
||||
|
||||
private:
|
||||
bool hasExplicitLocalCoords() const SK_OVERRIDE { return false; }
|
||||
|
||||
GrColor fColor;
|
||||
|
||||
typedef GrPrimitiveProcessor INHERITED;
|
||||
};
|
||||
|
||||
#endif
|
@ -11,7 +11,6 @@
|
||||
#include "GrBatch.h"
|
||||
#include "GrBlend.h"
|
||||
#include "GrDrawTargetCaps.h"
|
||||
#include "GrGeometryProcessor.h"
|
||||
#include "GrGpuResourceRef.h"
|
||||
#include "GrFragmentStage.h"
|
||||
#include "GrProcOptInfo.h"
|
||||
|
67
src/gpu/GrPrimitiveProcessor.cpp
Normal file
67
src/gpu/GrPrimitiveProcessor.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2014 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "GrPrimitiveProcessor.h"
|
||||
|
||||
#include "GrCoordTransform.h"
|
||||
|
||||
/**
|
||||
* The key for an individual coord transform is made up of a matrix type, a precision, and a bit
|
||||
* that indicates the source of the input coords.
|
||||
*/
|
||||
enum {
|
||||
kMatrixTypeKeyBits = 1,
|
||||
kMatrixTypeKeyMask = (1 << kMatrixTypeKeyBits) - 1,
|
||||
|
||||
kPrecisionBits = 2,
|
||||
kPrecisionShift = kMatrixTypeKeyBits,
|
||||
|
||||
kPositionCoords_Flag = (1 << (kPrecisionShift + kPrecisionBits)),
|
||||
kDeviceCoords_Flag = kPositionCoords_Flag + kPositionCoords_Flag,
|
||||
|
||||
kTransformKeyBits = kMatrixTypeKeyBits + kPrecisionBits + 2,
|
||||
};
|
||||
|
||||
GR_STATIC_ASSERT(kHigh_GrSLPrecision < (1 << kPrecisionBits));
|
||||
|
||||
/**
|
||||
* We specialize the vertex code for each of these matrix types.
|
||||
*/
|
||||
enum MatrixType {
|
||||
kNoPersp_MatrixType = 0,
|
||||
kGeneral_MatrixType = 1,
|
||||
};
|
||||
|
||||
uint32_t
|
||||
GrPrimitiveProcessor::getTransformKey(const SkTArray<const GrCoordTransform*, true>& coords) const {
|
||||
uint32_t totalKey = 0;
|
||||
for (int t = 0; t < coords.count(); ++t) {
|
||||
uint32_t key = 0;
|
||||
const GrCoordTransform* coordTransform = coords[t];
|
||||
if (coordTransform->getMatrix().hasPerspective()) {
|
||||
key |= kGeneral_MatrixType;
|
||||
} else {
|
||||
key |= kNoPersp_MatrixType;
|
||||
}
|
||||
|
||||
if (kLocal_GrCoordSet == coordTransform->sourceCoords() &&
|
||||
!this->hasExplicitLocalCoords()) {
|
||||
key |= kPositionCoords_Flag;
|
||||
} else if (kDevice_GrCoordSet == coordTransform->sourceCoords()) {
|
||||
key |= kDeviceCoords_Flag;
|
||||
}
|
||||
|
||||
GR_STATIC_ASSERT(kGrSLPrecisionCount <= (1 << kPrecisionBits));
|
||||
key |= (coordTransform->precision() << kPrecisionShift);
|
||||
|
||||
key <<= kTransformKeyBits * t;
|
||||
|
||||
SkASSERT(0 == (totalKey & key)); // keys for each transform ought not to overlap
|
||||
totalKey |= key;
|
||||
}
|
||||
return totalKey;
|
||||
}
|
230
src/gpu/GrPrimitiveProcessor.h
Normal file
230
src/gpu/GrPrimitiveProcessor.h
Normal file
@ -0,0 +1,230 @@
|
||||
/*
|
||||
* 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 GrPrimitiveProcessor_DEFINED
|
||||
#define GrPrimitiveProcessor_DEFINED
|
||||
|
||||
#include "GrColor.h"
|
||||
#include "GrProcessor.h"
|
||||
#include "GrShaderVar.h"
|
||||
|
||||
/*
|
||||
* The GrPrimitiveProcessor represents some kind of geometric primitive. This includes the shape
|
||||
* of the primitive and the inherent color of the primitive. The GrPrimitiveProcessor is
|
||||
* responsible for providing a color and coverage input into the Ganesh rendering pipeline. Through
|
||||
* optimization, Ganesh may decide a different color, no color, and / or no coverage are required
|
||||
* from the GrPrimitiveProcessor, so the GrPrimitiveProcessor must be able to support this
|
||||
* functionality. We also use the GrPrimitiveProcessor to make batching decisions.
|
||||
*
|
||||
* There are two feedback loops between the GrFragmentProcessors, the GrXferProcessor, and the
|
||||
* GrPrimitiveProcessor. These loops run on the CPU and compute any invariant components which
|
||||
* might be useful for correctness / optimization decisions. The GrPrimitiveProcessor seeds these
|
||||
* loops, one with initial color and one with initial coverage, in its
|
||||
* onComputeInvariantColor / Coverage calls. These seed values are processed by the subsequent
|
||||
* stages of the rendering pipeline and the output is then fed back into the GrPrimitiveProcessor in
|
||||
* the initBatchTracker call, where the GrPrimitiveProcessor can then initialize the GrBatchTracker
|
||||
* struct with the appropriate values.
|
||||
*
|
||||
* We are evolving this system to move towards generating geometric meshes and their associated
|
||||
* vertex data after we have batched and reordered draws. This system, known as 'deferred geometry'
|
||||
* will allow the GrPrimitiveProcessor much greater control over how data is transmitted to shaders.
|
||||
*
|
||||
* In a deferred geometry world, the GrPrimitiveProcessor can always 'batch' To do this, each
|
||||
* primitive type is associated with one GrPrimitiveProcessor, who has complete control of how
|
||||
* it draws. Each primitive draw will bundle all required data to perform the draw, and these
|
||||
* bundles of data will be owned by an instance of the associated GrPrimitiveProcessor. Bundles
|
||||
* can be updated alongside the GrBatchTracker struct itself, ultimately allowing the
|
||||
* GrPrimitiveProcessor complete control of how it gets data into the fragment shader as long as
|
||||
* it emits the appropriate color, or none at all, as directed.
|
||||
*/
|
||||
|
||||
/*
|
||||
* A struct for tracking batching decisions. While this lives on GrOptState, it is managed
|
||||
* entirely by the derived classes of the GP.
|
||||
* // TODO this was an early attempt at handling out of order batching. It should be
|
||||
* used carefully as it is being replaced by GrBatch
|
||||
*/
|
||||
class GrBatchTracker {
|
||||
public:
|
||||
template <typename T> const T& cast() const {
|
||||
SkASSERT(sizeof(T) <= kMaxSize);
|
||||
return *reinterpret_cast<const T*>(fData.get());
|
||||
}
|
||||
|
||||
template <typename T> T* cast() {
|
||||
SkASSERT(sizeof(T) <= kMaxSize);
|
||||
return reinterpret_cast<T*>(fData.get());
|
||||
}
|
||||
|
||||
static const size_t kMaxSize = 32;
|
||||
|
||||
private:
|
||||
SkAlignedSStorage<kMaxSize> fData;
|
||||
};
|
||||
|
||||
class GrIndexBufferAllocPool;
|
||||
class GrGLCaps;
|
||||
class GrGLPrimitiveProcessor;
|
||||
class GrVertexBufferAllocPool;
|
||||
|
||||
struct GrInitInvariantOutput;
|
||||
|
||||
/*
|
||||
* This struct allows the GrPipeline to communicate information about the pipeline. Most of this
|
||||
* is overrides, but some of it is general information. Logically it should live in GrPipeline.h,
|
||||
* but this is problematic due to circular dependencies.
|
||||
*/
|
||||
struct GrPipelineInfo {
|
||||
bool fColorIgnored;
|
||||
bool fCoverageIgnored;
|
||||
GrColor fOverrideColor;
|
||||
bool fUsesLocalCoords;
|
||||
};
|
||||
|
||||
/*
|
||||
* This enum is shared by GrPrimitiveProcessors and GrGLPrimitiveProcessors to coordinate shaders
|
||||
* with vertex attributes / uniforms.
|
||||
*/
|
||||
enum GrGPInput {
|
||||
kAllOnes_GrGPInput,
|
||||
kAttribute_GrGPInput,
|
||||
kUniform_GrGPInput,
|
||||
kIgnored_GrGPInput,
|
||||
};
|
||||
|
||||
/*
|
||||
* GrPrimitiveProcessor defines an interface which all subclasses must implement. All
|
||||
* GrPrimitiveProcessors must proivide seed color and coverage for the Ganesh color / coverage
|
||||
* pipelines, and they must provide some notion of equality
|
||||
*/
|
||||
class GrPrimitiveProcessor : public GrProcessor {
|
||||
public:
|
||||
// TODO let the PrimProc itself set this in its setData call, this should really live on the
|
||||
// bundle of primitive data
|
||||
const SkMatrix& viewMatrix() const { return fViewMatrix; }
|
||||
const SkMatrix& localMatrix() const { return fLocalMatrix; }
|
||||
|
||||
virtual void initBatchTracker(GrBatchTracker*, const GrPipelineInfo&) const = 0;
|
||||
|
||||
virtual bool canMakeEqual(const GrBatchTracker& mine,
|
||||
const GrPrimitiveProcessor& that,
|
||||
const GrBatchTracker& theirs) const = 0;
|
||||
|
||||
virtual void getInvariantOutputColor(GrInitInvariantOutput* out) const = 0;
|
||||
virtual void getInvariantOutputCoverage(GrInitInvariantOutput* out) const = 0;
|
||||
|
||||
// Only the GrGeometryProcessor subclass actually has a geo shader or vertex attributes, but
|
||||
// we put these calls on the base class to prevent having to cast
|
||||
virtual bool willUseGeoShader() const = 0;
|
||||
|
||||
/*
|
||||
* This is a safeguard to prevent GrPrimitiveProcessor's from going beyond platform specific
|
||||
* attribute limits. This number can almost certainly be raised if required.
|
||||
*/
|
||||
static const int kMaxVertexAttribs = 6;
|
||||
|
||||
struct Attribute {
|
||||
Attribute()
|
||||
: fName(NULL)
|
||||
, fType(kFloat_GrVertexAttribType)
|
||||
, fOffset(0) {}
|
||||
Attribute(const char* name, GrVertexAttribType type)
|
||||
: fName(name)
|
||||
, fType(type)
|
||||
, fOffset(SkAlign4(GrVertexAttribTypeSize(type))) {}
|
||||
const char* fName;
|
||||
GrVertexAttribType fType;
|
||||
size_t fOffset;
|
||||
};
|
||||
|
||||
int numAttribs() const { return fNumAttribs; }
|
||||
const Attribute& getAttrib(int index) const {
|
||||
SkASSERT(index < fNumAttribs);
|
||||
return fAttribs[index];
|
||||
}
|
||||
|
||||
// Returns the vertex stride of the GP. A common use case is to request geometry from a
|
||||
// drawtarget based off of the stride, and to populate this memory using an implicit array of
|
||||
// structs. In this case, it is best to assert the vertexstride == sizeof(VertexStruct).
|
||||
size_t getVertexStride() const { return fVertexStride; }
|
||||
|
||||
/**
|
||||
* Gets a transformKey from an array of coord transforms
|
||||
*/
|
||||
uint32_t getTransformKey(const SkTArray<const GrCoordTransform*, true>&) const;
|
||||
|
||||
/**
|
||||
* Sets a unique key on the GrProcessorKeyBuilder that is directly associated with this geometry
|
||||
* processor's GL backend implementation.
|
||||
*/
|
||||
virtual void getGLProcessorKey(const GrBatchTracker& bt,
|
||||
const GrGLCaps& caps,
|
||||
GrProcessorKeyBuilder* b) const = 0;
|
||||
|
||||
|
||||
/** Returns a new instance of the appropriate *GL* implementation class
|
||||
for the given GrProcessor; caller is responsible for deleting
|
||||
the object. */
|
||||
virtual GrGLPrimitiveProcessor* createGLInstance(const GrBatchTracker& bt,
|
||||
const GrGLCaps& caps) const = 0;
|
||||
|
||||
bool isPathRendering() const { return fIsPathRendering; }
|
||||
|
||||
protected:
|
||||
GrPrimitiveProcessor(const SkMatrix& viewMatrix, const SkMatrix& localMatrix,
|
||||
bool isPathRendering)
|
||||
: fNumAttribs(0)
|
||||
, fVertexStride(0)
|
||||
, fViewMatrix(viewMatrix)
|
||||
, fLocalMatrix(localMatrix)
|
||||
, fIsPathRendering(isPathRendering) {}
|
||||
|
||||
/*
|
||||
* CanCombineOutput will return true if two draws are 'batchable' from a color perspective.
|
||||
* TODO remove this when GPs can upgrade to attribute color
|
||||
*/
|
||||
static bool CanCombineOutput(GrGPInput left, GrColor lColor, GrGPInput right, GrColor rColor) {
|
||||
if (left != right) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (kUniform_GrGPInput == left && lColor != rColor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool CanCombineLocalMatrices(const GrPrimitiveProcessor& left,
|
||||
bool leftUsesLocalCoords,
|
||||
const GrPrimitiveProcessor& right,
|
||||
bool rightUsesLocalCoords) {
|
||||
if (leftUsesLocalCoords != rightUsesLocalCoords) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (leftUsesLocalCoords && !left.localMatrix().cheapEqualTo(right.localMatrix())) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Attribute fAttribs[kMaxVertexAttribs];
|
||||
int fNumAttribs;
|
||||
size_t fVertexStride;
|
||||
|
||||
private:
|
||||
virtual bool hasExplicitLocalCoords() const = 0;
|
||||
|
||||
const SkMatrix fViewMatrix;
|
||||
SkMatrix fLocalMatrix;
|
||||
bool fIsPathRendering;
|
||||
|
||||
typedef GrProcessor INHERITED;
|
||||
};
|
||||
|
||||
#endif
|
129
src/gpu/gl/GrGLGeometryProcessor.cpp
Normal file
129
src/gpu/gl/GrGLGeometryProcessor.cpp
Normal file
@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright 2014 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "GrGLGeometryProcessor.h"
|
||||
|
||||
#include "builders/GrGLProgramBuilder.h"
|
||||
|
||||
void GrGLGeometryProcessor::emitCode(EmitArgs& args) {
|
||||
GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
|
||||
GrGPArgs gpArgs;
|
||||
this->onEmitCode(args, &gpArgs);
|
||||
vsBuilder->transformToNormalizedDeviceSpace(gpArgs.fPositionVar);
|
||||
}
|
||||
|
||||
void GrGLGeometryProcessor::emitTransforms(GrGLGPBuilder* pb,
|
||||
const GrShaderVar& posVar,
|
||||
const char* localCoords,
|
||||
const SkMatrix& localMatrix,
|
||||
const TransformsIn& tin,
|
||||
TransformsOut* tout) {
|
||||
GrGLVertexBuilder* vb = pb->getVertexShaderBuilder();
|
||||
tout->push_back_n(tin.count());
|
||||
fInstalledTransforms.push_back_n(tin.count());
|
||||
for (int i = 0; i < tin.count(); i++) {
|
||||
const ProcCoords& coordTransforms = tin[i];
|
||||
fInstalledTransforms[i].push_back_n(coordTransforms.count());
|
||||
for (int t = 0; t < coordTransforms.count(); t++) {
|
||||
SkString strUniName("StageMatrix");
|
||||
strUniName.appendf("_%i_%i", i, t);
|
||||
GrSLType varyingType;
|
||||
|
||||
GrCoordSet coordType = coordTransforms[t]->sourceCoords();
|
||||
uint32_t type = coordTransforms[t]->getMatrix().getType();
|
||||
if (kLocal_GrCoordSet == coordType) {
|
||||
type |= localMatrix.getType();
|
||||
}
|
||||
varyingType = SkToBool(SkMatrix::kPerspective_Mask & type) ? kVec3f_GrSLType :
|
||||
kVec2f_GrSLType;
|
||||
GrSLPrecision precision = coordTransforms[t]->precision();
|
||||
|
||||
const char* uniName;
|
||||
fInstalledTransforms[i][t].fHandle =
|
||||
pb->addUniform(GrGLProgramBuilder::kVertex_Visibility,
|
||||
kMat33f_GrSLType, precision,
|
||||
strUniName.c_str(),
|
||||
&uniName).toShaderBuilderIndex();
|
||||
|
||||
SkString strVaryingName("MatrixCoord");
|
||||
strVaryingName.appendf("_%i_%i", i, t);
|
||||
|
||||
GrGLVertToFrag v(varyingType);
|
||||
pb->addVarying(strVaryingName.c_str(), &v, precision);
|
||||
|
||||
SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
|
||||
SkNEW_APPEND_TO_TARRAY(&(*tout)[i], GrGLProcessor::TransformedCoords,
|
||||
(SkString(v.fsIn()), varyingType));
|
||||
|
||||
// varying = matrix * coords (logically)
|
||||
if (kDevice_GrCoordSet == coordType) {
|
||||
if (kVec2f_GrSLType == varyingType) {
|
||||
if (kVec2f_GrSLType == posVar.getType()) {
|
||||
vb->codeAppendf("%s = (%s * vec3(%s, 1)).xy;",
|
||||
v.vsOut(), uniName, posVar.c_str());
|
||||
} else {
|
||||
// The brackets here are just to scope the temp variable
|
||||
vb->codeAppendf("{ vec3 temp = %s * %s;", uniName, posVar.c_str());
|
||||
vb->codeAppendf("%s = vec2(temp.x/temp.z, temp.y/temp.z); }", v.vsOut());
|
||||
}
|
||||
} else {
|
||||
if (kVec2f_GrSLType == posVar.getType()) {
|
||||
vb->codeAppendf("%s = %s * vec3(%s, 1);",
|
||||
v.vsOut(), uniName, posVar.c_str());
|
||||
} else {
|
||||
vb->codeAppendf("%s = %s * %s;", v.vsOut(), uniName, posVar.c_str());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (kVec2f_GrSLType == varyingType) {
|
||||
vb->codeAppendf("%s = (%s * vec3(%s, 1)).xy;", v.vsOut(), uniName, localCoords);
|
||||
} else {
|
||||
vb->codeAppendf("%s = %s * vec3(%s, 1);", v.vsOut(), uniName, localCoords);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GrGLGeometryProcessor::setTransformData(const GrPrimitiveProcessor& primProc,
|
||||
const GrGLProgramDataManager& pdman,
|
||||
int index,
|
||||
const SkTArray<const GrCoordTransform*, true>& transforms) {
|
||||
SkSTArray<2, Transform, true>& procTransforms = fInstalledTransforms[index];
|
||||
int numTransforms = transforms.count();
|
||||
for (int t = 0; t < numTransforms; ++t) {
|
||||
SkASSERT(procTransforms[t].fHandle.isValid());
|
||||
const SkMatrix& transform = GetTransformMatrix(primProc.localMatrix(), *transforms[t]);
|
||||
if (!procTransforms[t].fCurrentValue.cheapEqualTo(transform)) {
|
||||
pdman.setSkMatrix(procTransforms[t].fHandle.convertToUniformHandle(), transform);
|
||||
procTransforms[t].fCurrentValue = transform;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLGeometryProcessor::SetupPosition(GrGLVertexBuilder* vsBuilder,
|
||||
GrGPArgs* gpArgs,
|
||||
const char* posName,
|
||||
const SkMatrix& mat,
|
||||
const char* matName) {
|
||||
if (mat.isIdentity()) {
|
||||
gpArgs->fPositionVar.set(kVec2f_GrSLType, "pos2");
|
||||
|
||||
vsBuilder->codeAppendf("vec2 %s = %s;", gpArgs->fPositionVar.c_str(), posName);
|
||||
} else if (!mat.hasPerspective()) {
|
||||
gpArgs->fPositionVar.set(kVec2f_GrSLType, "pos2");
|
||||
|
||||
vsBuilder->codeAppendf("vec2 %s = vec2(%s * vec3(%s, 1));",
|
||||
gpArgs->fPositionVar.c_str(), matName, posName);
|
||||
} else {
|
||||
gpArgs->fPositionVar.set(kVec3f_GrSLType, "pos3");
|
||||
|
||||
vsBuilder->codeAppendf("vec3 %s = %s * vec3(%s, 1);",
|
||||
gpArgs->fPositionVar.c_str(), matName, posName);
|
||||
}
|
||||
}
|
@ -8,126 +8,10 @@
|
||||
#ifndef GrGLGeometryProcessor_DEFINED
|
||||
#define GrGLGeometryProcessor_DEFINED
|
||||
|
||||
#include "GrGLProcessor.h"
|
||||
#include "GrGLPrimitiveProcessor.h"
|
||||
|
||||
class GrBatchTracker;
|
||||
class GrFragmentProcessor;
|
||||
class GrGLGPBuilder;
|
||||
|
||||
class GrGLPrimitiveProcessor {
|
||||
public:
|
||||
GrGLPrimitiveProcessor() : fViewMatrixName(NULL) { fViewMatrix = SkMatrix::InvalidMatrix(); }
|
||||
virtual ~GrGLPrimitiveProcessor() {}
|
||||
|
||||
typedef GrGLProgramDataManager::UniformHandle UniformHandle;
|
||||
typedef GrGLProcessor::TextureSamplerArray TextureSamplerArray;
|
||||
|
||||
typedef SkSTArray<2, const GrCoordTransform*, true> ProcCoords;
|
||||
typedef SkSTArray<8, ProcCoords> TransformsIn;
|
||||
typedef SkSTArray<8, GrGLProcessor::TransformedCoordsArray> TransformsOut;
|
||||
|
||||
struct EmitArgs {
|
||||
EmitArgs(GrGLGPBuilder* pb,
|
||||
const GrPrimitiveProcessor& gp,
|
||||
const GrBatchTracker& bt,
|
||||
const char* outputColor,
|
||||
const char* outputCoverage,
|
||||
const TextureSamplerArray& samplers,
|
||||
const TransformsIn& transformsIn,
|
||||
TransformsOut* transformsOut)
|
||||
: fPB(pb)
|
||||
, fGP(gp)
|
||||
, fBT(bt)
|
||||
, fOutputColor(outputColor)
|
||||
, fOutputCoverage(outputCoverage)
|
||||
, fSamplers(samplers)
|
||||
, fTransformsIn(transformsIn)
|
||||
, fTransformsOut(transformsOut) {}
|
||||
GrGLGPBuilder* fPB;
|
||||
const GrPrimitiveProcessor& fGP;
|
||||
const GrBatchTracker& fBT;
|
||||
const char* fOutputColor;
|
||||
const char* fOutputCoverage;
|
||||
const TextureSamplerArray& fSamplers;
|
||||
const TransformsIn& fTransformsIn;
|
||||
TransformsOut* fTransformsOut;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 GrGLPrimitiveProcessor instance can be reused with any GrGLPrimitiveProcessor that
|
||||
produces the same stage key; this function reads data from a GrGLPrimitiveProcessor and
|
||||
uploads any uniform variables required by the shaders created in emitCode(). The
|
||||
GrPrimitiveProcessor parameter is guaranteed to be of the same type that created this
|
||||
GrGLPrimitiveProcessor and to have an identical processor key as the one that created this
|
||||
GrGLPrimitiveProcessor. */
|
||||
virtual void setData(const GrGLProgramDataManager&,
|
||||
const GrPrimitiveProcessor&,
|
||||
const GrBatchTracker&) = 0;
|
||||
|
||||
static SkMatrix GetTransformMatrix(const SkMatrix& localMatrix, const GrCoordTransform&);
|
||||
|
||||
protected:
|
||||
/** a helper which can setup vertex, constant, or uniform color depending on inputType.
|
||||
* This function will only do the minimum required to emit the correct shader code. If
|
||||
* inputType == attribute, then colorAttr must not be NULL. Likewise, if inputType == Uniform
|
||||
* then colorUniform must not be NULL.
|
||||
*/
|
||||
void setupColorPassThrough(GrGLGPBuilder* pb,
|
||||
GrGPInput inputType,
|
||||
const char* inputName,
|
||||
const GrGeometryProcessor::Attribute* colorAttr,
|
||||
UniformHandle* colorUniform);
|
||||
|
||||
const char* uViewM() const { return fViewMatrixName; }
|
||||
|
||||
/** a helper function to setup the uniform handle for the uniform view matrix */
|
||||
void addUniformViewMatrix(GrGLGPBuilder*);
|
||||
|
||||
|
||||
/** a helper function to upload a uniform viewmatrix.
|
||||
* TODO we can remove this function when we have deferred geometry in place
|
||||
*/
|
||||
void setUniformViewMatrix(const GrGLProgramDataManager&,
|
||||
const SkMatrix& viewMatrix);
|
||||
|
||||
class ShaderVarHandle {
|
||||
public:
|
||||
bool isValid() const { return fHandle > -1; }
|
||||
ShaderVarHandle() : fHandle(-1) {}
|
||||
ShaderVarHandle(int value) : fHandle(value) { SkASSERT(this->isValid()); }
|
||||
int handle() const { SkASSERT(this->isValid()); return fHandle; }
|
||||
UniformHandle convertToUniformHandle() {
|
||||
SkASSERT(this->isValid());
|
||||
return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fHandle);
|
||||
}
|
||||
|
||||
private:
|
||||
int fHandle;
|
||||
};
|
||||
|
||||
struct Transform {
|
||||
Transform() : fType(kVoid_GrSLType) { fCurrentValue = SkMatrix::InvalidMatrix(); }
|
||||
ShaderVarHandle fHandle;
|
||||
SkMatrix fCurrentValue;
|
||||
GrSLType fType;
|
||||
};
|
||||
|
||||
SkSTArray<8, SkSTArray<2, Transform, true> > fInstalledTransforms;
|
||||
|
||||
private:
|
||||
UniformHandle fViewMatrixUniform;
|
||||
SkMatrix fViewMatrix;
|
||||
const char* fViewMatrixName;
|
||||
};
|
||||
|
||||
class GrGLPathRendering;
|
||||
class GrGLVertexBuilder;
|
||||
|
||||
/**
|
||||
* If a GL effect needs a GrGLFullShaderBuilder* object to emit vertex code, then it must inherit
|
||||
* from this class. Since paths don't have vertices, this class is only meant to be used internally
|
||||
@ -189,40 +73,4 @@ private:
|
||||
typedef GrGLPrimitiveProcessor INHERITED;
|
||||
};
|
||||
|
||||
class GrGLGpu;
|
||||
|
||||
class GrGLPathProcessor : public GrGLPrimitiveProcessor {
|
||||
public:
|
||||
GrGLPathProcessor(const GrPathProcessor&, const GrBatchTracker&);
|
||||
|
||||
static void GenKey(const GrPathProcessor&,
|
||||
const GrBatchTracker& bt,
|
||||
const GrGLCaps&,
|
||||
GrProcessorKeyBuilder* b);
|
||||
|
||||
void emitCode(EmitArgs&) SK_OVERRIDE;
|
||||
|
||||
virtual void emitTransforms(GrGLGPBuilder*, const TransformsIn&, TransformsOut*) = 0;
|
||||
|
||||
virtual void resolveSeparableVaryings(GrGLGpu* gpu, GrGLuint programId) {}
|
||||
|
||||
void setData(const GrGLProgramDataManager&,
|
||||
const GrPrimitiveProcessor&,
|
||||
const GrBatchTracker&) SK_OVERRIDE;
|
||||
|
||||
virtual void setTransformData(const GrPrimitiveProcessor&,
|
||||
int index,
|
||||
const SkTArray<const GrCoordTransform*, true>& transforms,
|
||||
GrGLPathRendering*,
|
||||
GrGLuint programID) = 0;
|
||||
|
||||
virtual void didSetData(GrGLPathRendering*) {}
|
||||
|
||||
private:
|
||||
UniformHandle fColorUniform;
|
||||
GrColor fColor;
|
||||
|
||||
typedef GrGLPrimitiveProcessor INHERITED;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
183
src/gpu/gl/GrGLPathProcessor.cpp
Normal file
183
src/gpu/gl/GrGLPathProcessor.cpp
Normal file
@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright 2013 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "GrGLPathProcessor.h"
|
||||
|
||||
#include "GrPathProcessor.h"
|
||||
#include "GrGLGpu.h"
|
||||
#include "GrGLPathRendering.h"
|
||||
|
||||
GrGLPathProcessor::GrGLPathProcessor(const GrPathProcessor&, const GrBatchTracker&)
|
||||
: fColor(GrColor_ILLEGAL) {}
|
||||
|
||||
void GrGLPathProcessor::emitCode(EmitArgs& args) {
|
||||
GrGLGPBuilder* pb = args.fPB;
|
||||
GrGLGPFragmentBuilder* fs = args.fPB->getFragmentShaderBuilder();
|
||||
const PathBatchTracker& local = args.fBT.cast<PathBatchTracker>();
|
||||
|
||||
// emit transforms
|
||||
this->emitTransforms(args.fPB, args.fTransformsIn, args.fTransformsOut);
|
||||
|
||||
// Setup uniform color
|
||||
if (kUniform_GrGPInput == local.fInputColorType) {
|
||||
const char* stagedLocalVarName;
|
||||
fColorUniform = pb->addUniform(GrGLProgramBuilder::kFragment_Visibility,
|
||||
kVec4f_GrSLType,
|
||||
kDefault_GrSLPrecision,
|
||||
"Color",
|
||||
&stagedLocalVarName);
|
||||
fs->codeAppendf("%s = %s;", args.fOutputColor, stagedLocalVarName);
|
||||
}
|
||||
|
||||
// setup constant solid coverage
|
||||
if (kAllOnes_GrGPInput == local.fInputCoverageType) {
|
||||
fs->codeAppendf("%s = vec4(1);", args.fOutputCoverage);
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLPathProcessor::GenKey(const GrPathProcessor&,
|
||||
const GrBatchTracker& bt,
|
||||
const GrGLCaps&,
|
||||
GrProcessorKeyBuilder* b) {
|
||||
const PathBatchTracker& local = bt.cast<PathBatchTracker>();
|
||||
b->add32(local.fInputColorType | local.fInputCoverageType << 16);
|
||||
}
|
||||
|
||||
void GrGLPathProcessor::setData(const GrGLProgramDataManager& pdman,
|
||||
const GrPrimitiveProcessor& primProc,
|
||||
const GrBatchTracker& bt) {
|
||||
const PathBatchTracker& local = bt.cast<PathBatchTracker>();
|
||||
if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
|
||||
GrGLfloat c[4];
|
||||
GrColorToRGBAFloat(local.fColor, c);
|
||||
pdman.set4fv(fColorUniform, 1, c);
|
||||
fColor = local.fColor;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void GrGLLegacyPathProcessor::emitTransforms(GrGLGPBuilder*, const TransformsIn& tin,
|
||||
TransformsOut* tout) {
|
||||
tout->push_back_n(tin.count());
|
||||
fInstalledTransforms.push_back_n(tin.count());
|
||||
for (int i = 0; i < tin.count(); i++) {
|
||||
const ProcCoords& coordTransforms = tin[i];
|
||||
int texCoordIndex = this->addTexCoordSets(coordTransforms.count());
|
||||
|
||||
// Use the first uniform location as the texcoord index.
|
||||
fInstalledTransforms[i].push_back_n(1);
|
||||
fInstalledTransforms[i][0].fHandle = ShaderVarHandle(texCoordIndex);
|
||||
|
||||
SkString name;
|
||||
for (int t = 0; t < coordTransforms.count(); ++t) {
|
||||
GrSLType type = coordTransforms[t]->getMatrix().hasPerspective() ? kVec3f_GrSLType :
|
||||
kVec2f_GrSLType;
|
||||
|
||||
name.printf("%s(gl_TexCoord[%i])", GrGLSLTypeString(type), texCoordIndex++);
|
||||
SkNEW_APPEND_TO_TARRAY(&(*tout)[i], GrGLProcessor::TransformedCoords, (name, type));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLLegacyPathProcessor::setTransformData(
|
||||
const GrPrimitiveProcessor& primProc,
|
||||
int index,
|
||||
const SkTArray<const GrCoordTransform*, true>& transforms,
|
||||
GrGLPathRendering* glpr,
|
||||
GrGLuint) {
|
||||
// We've hidden the texcoord index in the first entry of the transforms array for each
|
||||
// effect
|
||||
int texCoordIndex = fInstalledTransforms[index][0].fHandle.handle();
|
||||
for (int t = 0; t < transforms.count(); ++t) {
|
||||
const SkMatrix& transform = GetTransformMatrix(primProc.localMatrix(), *transforms[t]);
|
||||
GrGLPathRendering::PathTexGenComponents components =
|
||||
GrGLPathRendering::kST_PathTexGenComponents;
|
||||
if (transform.hasPerspective()) {
|
||||
components = GrGLPathRendering::kSTR_PathTexGenComponents;
|
||||
}
|
||||
glpr->enablePathTexGen(texCoordIndex++, components, transform);
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLLegacyPathProcessor::didSetData(GrGLPathRendering* glpr) {
|
||||
glpr->flushPathTexGenSettings(fTexCoordSetCnt);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void GrGLNormalPathProcessor::emitTransforms(GrGLGPBuilder* pb, const TransformsIn& tin,
|
||||
TransformsOut* tout) {
|
||||
tout->push_back_n(tin.count());
|
||||
fInstalledTransforms.push_back_n(tin.count());
|
||||
for (int i = 0; i < tin.count(); i++) {
|
||||
const ProcCoords& coordTransforms = tin[i];
|
||||
fInstalledTransforms[i].push_back_n(coordTransforms.count());
|
||||
for (int t = 0; t < coordTransforms.count(); t++) {
|
||||
GrSLType varyingType =
|
||||
coordTransforms[t]->getMatrix().hasPerspective() ? kVec3f_GrSLType :
|
||||
kVec2f_GrSLType;
|
||||
|
||||
|
||||
SkString strVaryingName("MatrixCoord");
|
||||
strVaryingName.appendf("_%i_%i", i, t);
|
||||
GrGLVertToFrag v(varyingType);
|
||||
pb->addVarying(strVaryingName.c_str(), &v);
|
||||
SeparableVaryingInfo& varyingInfo = fSeparableVaryingInfos.push_back();
|
||||
varyingInfo.fVariable = pb->getFragmentShaderBuilder()->fInputs.back();
|
||||
varyingInfo.fLocation = fSeparableVaryingInfos.count() - 1;
|
||||
varyingInfo.fType = varyingType;
|
||||
fInstalledTransforms[i][t].fHandle = ShaderVarHandle(varyingInfo.fLocation);
|
||||
fInstalledTransforms[i][t].fType = varyingType;
|
||||
|
||||
SkNEW_APPEND_TO_TARRAY(&(*tout)[i], GrGLProcessor::TransformedCoords,
|
||||
(SkString(v.fsIn()), varyingType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLNormalPathProcessor::resolveSeparableVaryings(GrGLGpu* gpu, GrGLuint programId) {
|
||||
int count = fSeparableVaryingInfos.count();
|
||||
for (int i = 0; i < count; ++i) {
|
||||
GrGLint location;
|
||||
GR_GL_CALL_RET(gpu->glInterface(),
|
||||
location,
|
||||
GetProgramResourceLocation(programId,
|
||||
GR_GL_FRAGMENT_INPUT,
|
||||
fSeparableVaryingInfos[i].fVariable.c_str()));
|
||||
fSeparableVaryingInfos[i].fLocation = location;
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLNormalPathProcessor::setTransformData(
|
||||
const GrPrimitiveProcessor& primProc,
|
||||
int index,
|
||||
const SkTArray<const GrCoordTransform*, true>& coordTransforms,
|
||||
GrGLPathRendering* glpr,
|
||||
GrGLuint programID) {
|
||||
SkSTArray<2, Transform, true>& transforms = fInstalledTransforms[index];
|
||||
int numTransforms = transforms.count();
|
||||
for (int t = 0; t < numTransforms; ++t) {
|
||||
SkASSERT(transforms[t].fHandle.isValid());
|
||||
const SkMatrix& transform = GetTransformMatrix(primProc.localMatrix(),
|
||||
*coordTransforms[t]);
|
||||
if (transforms[t].fCurrentValue.cheapEqualTo(transform)) {
|
||||
continue;
|
||||
}
|
||||
transforms[t].fCurrentValue = transform;
|
||||
const SeparableVaryingInfo& fragmentInput =
|
||||
fSeparableVaryingInfos[transforms[t].fHandle.handle()];
|
||||
SkASSERT(transforms[t].fType == kVec2f_GrSLType ||
|
||||
transforms[t].fType == kVec3f_GrSLType);
|
||||
unsigned components = transforms[t].fType == kVec2f_GrSLType ? 2 : 3;
|
||||
glpr->setProgramPathFragmentInputTransform(programID,
|
||||
fragmentInput.fLocation,
|
||||
GR_GL_OBJECT_LINEAR,
|
||||
components,
|
||||
transform);
|
||||
}
|
||||
}
|
113
src/gpu/gl/GrGLPathProcessor.h
Normal file
113
src/gpu/gl/GrGLPathProcessor.h
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* 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 GrGLPathProcessor_DEFINED
|
||||
#define GrGLPathProcessor_DEFINED
|
||||
|
||||
#include "GrGLPrimitiveProcessor.h"
|
||||
|
||||
class GrPathProcessor;
|
||||
class GrGLPathRendering;
|
||||
class GrGLGpu;
|
||||
|
||||
class GrGLPathProcessor : public GrGLPrimitiveProcessor {
|
||||
public:
|
||||
GrGLPathProcessor(const GrPathProcessor&, const GrBatchTracker&);
|
||||
|
||||
static void GenKey(const GrPathProcessor&,
|
||||
const GrBatchTracker& bt,
|
||||
const GrGLCaps&,
|
||||
GrProcessorKeyBuilder* b);
|
||||
|
||||
void emitCode(EmitArgs&) SK_OVERRIDE;
|
||||
|
||||
virtual void emitTransforms(GrGLGPBuilder*, const TransformsIn&, TransformsOut*) = 0;
|
||||
|
||||
virtual void resolveSeparableVaryings(GrGLGpu* gpu, GrGLuint programId) {}
|
||||
|
||||
void setData(const GrGLProgramDataManager&,
|
||||
const GrPrimitiveProcessor&,
|
||||
const GrBatchTracker&) SK_OVERRIDE;
|
||||
|
||||
virtual void setTransformData(const GrPrimitiveProcessor&,
|
||||
int index,
|
||||
const SkTArray<const GrCoordTransform*, true>& transforms,
|
||||
GrGLPathRendering*,
|
||||
GrGLuint programID) = 0;
|
||||
|
||||
virtual void didSetData(GrGLPathRendering*) {}
|
||||
|
||||
private:
|
||||
UniformHandle fColorUniform;
|
||||
GrColor fColor;
|
||||
|
||||
typedef GrGLPrimitiveProcessor INHERITED;
|
||||
};
|
||||
|
||||
class GrGLLegacyPathProcessor : public GrGLPathProcessor {
|
||||
public:
|
||||
GrGLLegacyPathProcessor(const GrPathProcessor& pathProc, const GrBatchTracker& bt,
|
||||
int maxTexCoords)
|
||||
: INHERITED(pathProc, bt)
|
||||
, fTexCoordSetCnt(0) {
|
||||
SkDEBUGCODE(fMaxTexCoords = maxTexCoords;)
|
||||
}
|
||||
|
||||
int addTexCoordSets(int count) {
|
||||
int firstFreeCoordSet = fTexCoordSetCnt;
|
||||
fTexCoordSetCnt += count;
|
||||
SkASSERT(fMaxTexCoords >= fTexCoordSetCnt);
|
||||
return firstFreeCoordSet;
|
||||
}
|
||||
|
||||
void emitTransforms(GrGLGPBuilder*, const TransformsIn& tin, TransformsOut* tout) SK_OVERRIDE;
|
||||
|
||||
void setTransformData(const GrPrimitiveProcessor& primProc,
|
||||
int index,
|
||||
const SkTArray<const GrCoordTransform*, true>& transforms,
|
||||
GrGLPathRendering* glpr,
|
||||
GrGLuint) SK_OVERRIDE;
|
||||
|
||||
void didSetData(GrGLPathRendering* glpr) SK_OVERRIDE;
|
||||
|
||||
private:
|
||||
SkDEBUGCODE(int fMaxTexCoords;)
|
||||
int fTexCoordSetCnt;
|
||||
|
||||
typedef GrGLPathProcessor INHERITED;
|
||||
};
|
||||
|
||||
class GrGLNormalPathProcessor : public GrGLPathProcessor {
|
||||
public:
|
||||
GrGLNormalPathProcessor(const GrPathProcessor& pathProc, const GrBatchTracker& bt)
|
||||
: INHERITED(pathProc, bt) {}
|
||||
|
||||
void emitTransforms(GrGLGPBuilder* pb, const TransformsIn& tin,TransformsOut* tout) SK_OVERRIDE;
|
||||
|
||||
void resolveSeparableVaryings(GrGLGpu* gpu, GrGLuint programId);
|
||||
|
||||
void setTransformData(const GrPrimitiveProcessor& primProc,
|
||||
int index,
|
||||
const SkTArray<const GrCoordTransform*, true>& coordTransforms,
|
||||
GrGLPathRendering* glpr,
|
||||
GrGLuint programID) SK_OVERRIDE;
|
||||
|
||||
private:
|
||||
struct SeparableVaryingInfo {
|
||||
GrSLType fType;
|
||||
GrGLShaderVar fVariable;
|
||||
GrGLint fLocation;
|
||||
};
|
||||
|
||||
typedef SkSTArray<8, SeparableVaryingInfo, true> SeparableVaryingInfoArray;
|
||||
|
||||
SeparableVaryingInfoArray fSeparableVaryingInfos;
|
||||
|
||||
typedef GrGLPathProcessor INHERITED;
|
||||
};
|
||||
|
||||
#endif
|
75
src/gpu/gl/GrGLPrimitiveProcessor.cpp
Normal file
75
src/gpu/gl/GrGLPrimitiveProcessor.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2014 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "GrGLPrimitiveProcessor.h"
|
||||
|
||||
#include "builders/GrGLProgramBuilder.h"
|
||||
|
||||
SkMatrix GrGLPrimitiveProcessor::GetTransformMatrix(const SkMatrix& localMatrix,
|
||||
const GrCoordTransform& coordTransform) {
|
||||
SkMatrix combined;
|
||||
// We only apply the localmatrix to localcoords
|
||||
if (kLocal_GrCoordSet == coordTransform.sourceCoords()) {
|
||||
combined.setConcat(coordTransform.getMatrix(), localMatrix);
|
||||
} else {
|
||||
combined = coordTransform.getMatrix();
|
||||
}
|
||||
if (coordTransform.reverseY()) {
|
||||
// combined.postScale(1,-1);
|
||||
// combined.postTranslate(0,1);
|
||||
combined.set(SkMatrix::kMSkewY,
|
||||
combined[SkMatrix::kMPersp0] - combined[SkMatrix::kMSkewY]);
|
||||
combined.set(SkMatrix::kMScaleY,
|
||||
combined[SkMatrix::kMPersp1] - combined[SkMatrix::kMScaleY]);
|
||||
combined.set(SkMatrix::kMTransY,
|
||||
combined[SkMatrix::kMPersp2] - combined[SkMatrix::kMTransY]);
|
||||
}
|
||||
return combined;
|
||||
}
|
||||
|
||||
void
|
||||
GrGLPrimitiveProcessor::setupColorPassThrough(GrGLGPBuilder* pb,
|
||||
GrGPInput inputType,
|
||||
const char* outputName,
|
||||
const GrGeometryProcessor::Attribute* colorAttr,
|
||||
UniformHandle* colorUniform) {
|
||||
GrGLGPFragmentBuilder* fs = pb->getFragmentShaderBuilder();
|
||||
if (kUniform_GrGPInput == inputType) {
|
||||
SkASSERT(colorUniform);
|
||||
const char* stagedLocalVarName;
|
||||
*colorUniform = pb->addUniform(GrGLProgramBuilder::kFragment_Visibility,
|
||||
kVec4f_GrSLType,
|
||||
kDefault_GrSLPrecision,
|
||||
"Color",
|
||||
&stagedLocalVarName);
|
||||
fs->codeAppendf("%s = %s;", outputName, stagedLocalVarName);
|
||||
} else if (kAttribute_GrGPInput == inputType) {
|
||||
SkASSERT(colorAttr);
|
||||
pb->addPassThroughAttribute(colorAttr, outputName);
|
||||
} else if (kAllOnes_GrGPInput == inputType) {
|
||||
fs->codeAppendf("%s = vec4(1);", outputName);
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLPrimitiveProcessor::addUniformViewMatrix(GrGLGPBuilder* pb) {
|
||||
fViewMatrixUniform = pb->addUniform(GrGLProgramBuilder::kVertex_Visibility,
|
||||
kMat33f_GrSLType, kDefault_GrSLPrecision,
|
||||
"uViewM",
|
||||
&fViewMatrixName);
|
||||
}
|
||||
|
||||
void GrGLPrimitiveProcessor::setUniformViewMatrix(const GrGLProgramDataManager& pdman,
|
||||
const SkMatrix& viewMatrix) {
|
||||
if (!fViewMatrix.cheapEqualTo(viewMatrix)) {
|
||||
SkASSERT(fViewMatrixUniform.isValid());
|
||||
fViewMatrix = viewMatrix;
|
||||
|
||||
GrGLfloat viewMatrix[3 * 3];
|
||||
GrGLGetMatrix<3>(viewMatrix, fViewMatrix);
|
||||
pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
|
||||
}
|
||||
}
|
130
src/gpu/gl/GrGLPrimitiveProcessor.h
Normal file
130
src/gpu/gl/GrGLPrimitiveProcessor.h
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* 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 GrGLPrimitiveProcessor_DEFINED
|
||||
#define GrGLPrimitiveProcessor_DEFINED
|
||||
|
||||
#include "GrPrimitiveProcessor.h"
|
||||
#include "GrGLProcessor.h"
|
||||
|
||||
class GrBatchTracker;
|
||||
class GrPrimitiveProcessor;
|
||||
class GrGLGPBuilder;
|
||||
|
||||
class GrGLPrimitiveProcessor {
|
||||
public:
|
||||
GrGLPrimitiveProcessor() : fViewMatrixName(NULL) { fViewMatrix = SkMatrix::InvalidMatrix(); }
|
||||
virtual ~GrGLPrimitiveProcessor() {}
|
||||
|
||||
typedef GrGLProgramDataManager::UniformHandle UniformHandle;
|
||||
typedef GrGLProcessor::TextureSamplerArray TextureSamplerArray;
|
||||
|
||||
typedef SkSTArray<2, const GrCoordTransform*, true> ProcCoords;
|
||||
typedef SkSTArray<8, ProcCoords> TransformsIn;
|
||||
typedef SkSTArray<8, GrGLProcessor::TransformedCoordsArray> TransformsOut;
|
||||
|
||||
struct EmitArgs {
|
||||
EmitArgs(GrGLGPBuilder* pb,
|
||||
const GrPrimitiveProcessor& gp,
|
||||
const GrBatchTracker& bt,
|
||||
const char* outputColor,
|
||||
const char* outputCoverage,
|
||||
const TextureSamplerArray& samplers,
|
||||
const TransformsIn& transformsIn,
|
||||
TransformsOut* transformsOut)
|
||||
: fPB(pb)
|
||||
, fGP(gp)
|
||||
, fBT(bt)
|
||||
, fOutputColor(outputColor)
|
||||
, fOutputCoverage(outputCoverage)
|
||||
, fSamplers(samplers)
|
||||
, fTransformsIn(transformsIn)
|
||||
, fTransformsOut(transformsOut) {}
|
||||
GrGLGPBuilder* fPB;
|
||||
const GrPrimitiveProcessor& fGP;
|
||||
const GrBatchTracker& fBT;
|
||||
const char* fOutputColor;
|
||||
const char* fOutputCoverage;
|
||||
const TextureSamplerArray& fSamplers;
|
||||
const TransformsIn& fTransformsIn;
|
||||
TransformsOut* fTransformsOut;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 GrGLPrimitiveProcessor instance can be reused with any GrGLPrimitiveProcessor that
|
||||
produces the same stage key; this function reads data from a GrGLPrimitiveProcessor and
|
||||
uploads any uniform variables required by the shaders created in emitCode(). The
|
||||
GrPrimitiveProcessor parameter is guaranteed to be of the same type that created this
|
||||
GrGLPrimitiveProcessor and to have an identical processor key as the one that created this
|
||||
GrGLPrimitiveProcessor. */
|
||||
virtual void setData(const GrGLProgramDataManager&,
|
||||
const GrPrimitiveProcessor&,
|
||||
const GrBatchTracker&) = 0;
|
||||
|
||||
static SkMatrix GetTransformMatrix(const SkMatrix& localMatrix, const GrCoordTransform&);
|
||||
|
||||
protected:
|
||||
/** a helper which can setup vertex, constant, or uniform color depending on inputType.
|
||||
* This function will only do the minimum required to emit the correct shader code. If
|
||||
* inputType == attribute, then colorAttr must not be NULL. Likewise, if inputType == Uniform
|
||||
* then colorUniform must not be NULL.
|
||||
*/
|
||||
void setupColorPassThrough(GrGLGPBuilder* pb,
|
||||
GrGPInput inputType,
|
||||
const char* inputName,
|
||||
const GrPrimitiveProcessor::Attribute* colorAttr,
|
||||
UniformHandle* colorUniform);
|
||||
|
||||
const char* uViewM() const { return fViewMatrixName; }
|
||||
|
||||
/** a helper function to setup the uniform handle for the uniform view matrix */
|
||||
void addUniformViewMatrix(GrGLGPBuilder*);
|
||||
|
||||
|
||||
/** a helper function to upload a uniform viewmatrix.
|
||||
* TODO we can remove this function when we have deferred geometry in place
|
||||
*/
|
||||
void setUniformViewMatrix(const GrGLProgramDataManager&,
|
||||
const SkMatrix& viewMatrix);
|
||||
|
||||
class ShaderVarHandle {
|
||||
public:
|
||||
bool isValid() const { return fHandle > -1; }
|
||||
ShaderVarHandle() : fHandle(-1) {}
|
||||
ShaderVarHandle(int value) : fHandle(value) { SkASSERT(this->isValid()); }
|
||||
int handle() const { SkASSERT(this->isValid()); return fHandle; }
|
||||
UniformHandle convertToUniformHandle() {
|
||||
SkASSERT(this->isValid());
|
||||
return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fHandle);
|
||||
}
|
||||
|
||||
private:
|
||||
int fHandle;
|
||||
};
|
||||
|
||||
struct Transform {
|
||||
Transform() : fType(kVoid_GrSLType) { fCurrentValue = SkMatrix::InvalidMatrix(); }
|
||||
ShaderVarHandle fHandle;
|
||||
SkMatrix fCurrentValue;
|
||||
GrSLType fType;
|
||||
};
|
||||
|
||||
SkSTArray<8, SkSTArray<2, Transform, true> > fInstalledTransforms;
|
||||
|
||||
private:
|
||||
UniformHandle fViewMatrixUniform;
|
||||
SkMatrix fViewMatrix;
|
||||
const char* fViewMatrixName;
|
||||
};
|
||||
|
||||
#endif
|
@ -11,12 +11,12 @@
|
||||
#include "GrProcessor.h"
|
||||
#include "GrCoordTransform.h"
|
||||
#include "GrGLGeometryProcessor.h"
|
||||
#include "GrGLProcessor.h"
|
||||
#include "GrGLXferProcessor.h"
|
||||
#include "GrGLGpu.h"
|
||||
#include "GrGLPathProcessor.h"
|
||||
#include "GrGLPathRendering.h"
|
||||
#include "GrGLShaderVar.h"
|
||||
#include "GrGLSL.h"
|
||||
#include "GrGLXferProcessor.h"
|
||||
#include "GrPipeline.h"
|
||||
#include "GrXferProcessor.h"
|
||||
#include "SkXfermode.h"
|
||||
|
@ -6,11 +6,14 @@
|
||||
*/
|
||||
|
||||
#include "GrGLProgramBuilder.h"
|
||||
|
||||
#include "gl/GrGLGeometryProcessor.h"
|
||||
#include "gl/GrGLGpu.h"
|
||||
#include "gl/GrGLPathProcessor.h"
|
||||
#include "gl/GrGLProgram.h"
|
||||
#include "gl/GrGLSLPrettyPrint.h"
|
||||
#include "gl/GrGLUniformHandle.h"
|
||||
#include "../GrGLXferProcessor.h"
|
||||
#include "../GrGLGpu.h"
|
||||
#include "gl/GrGLXferProcessor.h"
|
||||
#include "GrCoordTransform.h"
|
||||
#include "GrGLProgramBuilder.h"
|
||||
#include "GrTexture.h"
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include "GrGLVertexShaderBuilder.h"
|
||||
#include "../GrGLProgramDataManager.h"
|
||||
#include "../GrGLUniformHandle.h"
|
||||
#include "../GrGLGeometryProcessor.h"
|
||||
#include "../GrGLPrimitiveProcessor.h"
|
||||
#include "../GrGLXferProcessor.h"
|
||||
#include "../../GrPendingFragmentStage.h"
|
||||
#include "../../GrPipeline.h"
|
||||
|
Loading…
Reference in New Issue
Block a user