aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpu')
-rw-r--r--src/gpu/GrDrawTarget.h2
-rw-r--r--src/gpu/GrGeometryProcessor.cpp542
-rw-r--r--src/gpu/GrGeometryProcessor.h264
-rw-r--r--src/gpu/GrPathProcessor.cpp73
-rw-r--r--src/gpu/GrPathProcessor.h65
-rw-r--r--src/gpu/GrPipelineBuilder.h1
-rw-r--r--src/gpu/GrPrimitiveProcessor.cpp67
-rw-r--r--src/gpu/GrPrimitiveProcessor.h230
-rw-r--r--src/gpu/gl/GrGLGeometryProcessor.cpp129
-rw-r--r--src/gpu/gl/GrGLGeometryProcessor.h156
-rw-r--r--src/gpu/gl/GrGLPathProcessor.cpp183
-rw-r--r--src/gpu/gl/GrGLPathProcessor.h113
-rw-r--r--src/gpu/gl/GrGLPrimitiveProcessor.cpp75
-rw-r--r--src/gpu/gl/GrGLPrimitiveProcessor.h130
-rw-r--r--src/gpu/gl/GrGLProgram.cpp4
-rw-r--r--src/gpu/gl/builders/GrGLProgramBuilder.cpp7
-rw-r--r--src/gpu/gl/builders/GrGLProgramBuilder.h2
17 files changed, 1078 insertions, 965 deletions
diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h
index 1b6651716c..65407e653b 100644
--- a/src/gpu/GrDrawTarget.h
+++ b/src/gpu/GrDrawTarget.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"
diff --git a/src/gpu/GrGeometryProcessor.cpp b/src/gpu/GrGeometryProcessor.cpp
index c707efc6a2..23989cfe92 100644
--- a/src/gpu/GrGeometryProcessor.cpp
+++ b/src/gpu/GrGeometryProcessor.cpp
@@ -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));
- }
-}
diff --git a/src/gpu/GrGeometryProcessor.h b/src/gpu/GrGeometryProcessor.h
index a7fea765ab..7f8d041af8 100644
--- a/src/gpu/GrGeometryProcessor.h
+++ b/src/gpu/GrGeometryProcessor.h
@@ -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
diff --git a/src/gpu/GrPathProcessor.cpp b/src/gpu/GrPathProcessor.cpp
new file mode 100644
index 0000000000..f6c164016e
--- /dev/null
+++ b/src/gpu/GrPathProcessor.cpp
@@ -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));
+ }
+}
diff --git a/src/gpu/GrPathProcessor.h b/src/gpu/GrPathProcessor.h
new file mode 100644
index 0000000000..03d3907459
--- /dev/null
+++ b/src/gpu/GrPathProcessor.h
@@ -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
diff --git a/src/gpu/GrPipelineBuilder.h b/src/gpu/GrPipelineBuilder.h
index 5743c39dc5..c6adf870b3 100644
--- a/src/gpu/GrPipelineBuilder.h
+++ b/src/gpu/GrPipelineBuilder.h
@@ -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"
diff --git a/src/gpu/GrPrimitiveProcessor.cpp b/src/gpu/GrPrimitiveProcessor.cpp
new file mode 100644
index 0000000000..673656821b
--- /dev/null
+++ b/src/gpu/GrPrimitiveProcessor.cpp
@@ -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;
+}
diff --git a/src/gpu/GrPrimitiveProcessor.h b/src/gpu/GrPrimitiveProcessor.h
new file mode 100644
index 0000000000..a088d38b61
--- /dev/null
+++ b/src/gpu/GrPrimitiveProcessor.h
@@ -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
diff --git a/src/gpu/gl/GrGLGeometryProcessor.cpp b/src/gpu/gl/GrGLGeometryProcessor.cpp
new file mode 100644
index 0000000000..a8d020a166
--- /dev/null
+++ b/src/gpu/gl/GrGLGeometryProcessor.cpp
@@ -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);
+ }
+}
diff --git a/src/gpu/gl/GrGLGeometryProcessor.h b/src/gpu/gl/GrGLGeometryProcessor.h
index da6c347314..e8b16afe33 100644
--- a/src/gpu/gl/GrGLGeometryProcessor.h
+++ b/src/gpu/gl/GrGLGeometryProcessor.h
@@ -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
diff --git a/src/gpu/gl/GrGLPathProcessor.cpp b/src/gpu/gl/GrGLPathProcessor.cpp
new file mode 100644
index 0000000000..3f3e5d9be7
--- /dev/null
+++ b/src/gpu/gl/GrGLPathProcessor.cpp
@@ -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);
+ }
+}
diff --git a/src/gpu/gl/GrGLPathProcessor.h b/src/gpu/gl/GrGLPathProcessor.h
new file mode 100644
index 0000000000..368f1f9fcd
--- /dev/null
+++ b/src/gpu/gl/GrGLPathProcessor.h
@@ -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
diff --git a/src/gpu/gl/GrGLPrimitiveProcessor.cpp b/src/gpu/gl/GrGLPrimitiveProcessor.cpp
new file mode 100644
index 0000000000..335dc4fe5f
--- /dev/null
+++ b/src/gpu/gl/GrGLPrimitiveProcessor.cpp
@@ -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);
+ }
+}
diff --git a/src/gpu/gl/GrGLPrimitiveProcessor.h b/src/gpu/gl/GrGLPrimitiveProcessor.h
new file mode 100644
index 0000000000..30b1c178cd
--- /dev/null
+++ b/src/gpu/gl/GrGLPrimitiveProcessor.h
@@ -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
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index eebcf6b2f3..2f6b784b40 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -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"
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
index bb278be395..5a623033fb 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
@@ -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"
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.h b/src/gpu/gl/builders/GrGLProgramBuilder.h
index a9288cc9b0..37908f9971 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.h
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.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"