This CL wires up the backend portion necessary for sending transformed coords via vertex attributes.
BUG=skia:
Review URL: https://codereview.chromium.org/1243583002
diff --git a/src/gpu/GrDefaultGeoProcFactory.cpp b/src/gpu/GrDefaultGeoProcFactory.cpp
index 639a593..f8d30f8 100644
--- a/src/gpu/GrDefaultGeoProcFactory.cpp
+++ b/src/gpu/GrDefaultGeoProcFactory.cpp
@@ -16,6 +16,14 @@
* matrix. It also leaves coverage untouched. Behind the scenes, we may add per vertex color or
* local coords.
*/
+
+enum GPFlag {
+ kColor_GPFlag = 0x1,
+ kLocalCoord_GPFlag = 0x2,
+ kCoverage_GPFlag= 0x4,
+ kTransformedLocalCoord_GPFlag = 0x8,
+};
+
class DefaultGeoProc : public GrGeometryProcessor {
public:
static GrGeometryProcessor* Create(uint32_t gpTypeFlags,
@@ -77,10 +85,14 @@
this->setupPosition(pb, gpArgs, gp.inPosition()->fName, gp.viewMatrix(),
&fViewMatrixUniform);
- if (gp.inLocalCoords()) {
+ if (gp.hasExplicitLocalCoords()) {
// emit transforms with explicit local coords
this->emitTransforms(pb, gpArgs->fPositionVar, gp.inLocalCoords()->fName,
gp.localMatrix(), args.fTransformsIn, args.fTransformsOut);
+ } else if(gp.hasTransformedLocalCoords()) {
+ // transforms have already been applied to vertex attributes on the cpu
+ this->emitTransforms(pb, gp.inLocalCoords()->fName,
+ args.fTransformsIn, args.fTransformsOut);
} else {
// emit transforms with position
this->emitTransforms(pb, gpArgs->fPositionVar, gp.inPosition()->fName,
@@ -199,9 +211,11 @@
, fLocalCoordsWillBeRead(localCoordsWillBeRead)
, fCoverageWillBeIgnored(coverageWillBeIgnored) {
this->initClassID<DefaultGeoProc>();
- bool hasColor = SkToBool(gpTypeFlags & GrDefaultGeoProcFactory::kColor_GPType);
- bool hasLocalCoord = SkToBool(gpTypeFlags & GrDefaultGeoProcFactory::kLocalCoord_GPType);
- bool hasCoverage = SkToBool(gpTypeFlags & GrDefaultGeoProcFactory::kCoverage_GPType);
+ bool hasColor = SkToBool(gpTypeFlags & kColor_GPFlag);
+ bool hasExplicitLocalCoords = SkToBool(gpTypeFlags & kLocalCoord_GPFlag);
+ bool hasTransformedLocalCoords = SkToBool(gpTypeFlags & kTransformedLocalCoord_GPFlag);
+ bool hasLocalCoord = hasExplicitLocalCoords || hasTransformedLocalCoords;
+ bool hasCoverage = SkToBool(gpTypeFlags & kCoverage_GPFlag);
fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType,
kHigh_GrSLPrecision));
if (hasColor) {
@@ -210,7 +224,12 @@
if (hasLocalCoord) {
fInLocalCoords = &this->addVertexAttrib(Attribute("inLocalCoord",
kVec2f_GrVertexAttribType));
- this->setHasLocalCoords();
+ if (hasExplicitLocalCoords) {
+ this->setHasExplicitLocalCoords();
+ } else {
+ SkASSERT(hasTransformedLocalCoords);
+ this->setHasTransformedLocalCoords();
+ }
}
if (hasCoverage) {
fInCoverage = &this->addVertexAttrib(Attribute("inCoverage",
@@ -240,13 +259,16 @@
GrGeometryProcessor* DefaultGeoProc::TestCreate(GrProcessorTestData* d) {
uint32_t flags = 0;
if (d->fRandom->nextBool()) {
- flags |= GrDefaultGeoProcFactory::kColor_GPType;
+ flags |= kColor_GPFlag;
}
if (d->fRandom->nextBool()) {
- flags |= GrDefaultGeoProcFactory::kCoverage_GPType;
+ flags |= kCoverage_GPFlag;
}
if (d->fRandom->nextBool()) {
- flags |= GrDefaultGeoProcFactory::kLocalCoord_GPType;
+ flags |= kLocalCoord_GPFlag;
+ }
+ if (d->fRandom->nextBool()) {
+ flags |= kTransformedLocalCoord_GPFlag;
}
return DefaultGeoProc::Create(flags,
@@ -263,9 +285,11 @@
const LocalCoords& localCoords,
const SkMatrix& viewMatrix) {
uint32_t flags = 0;
- flags |= color.fType == Color::kAttribute_Type ? kColor_GPType : 0;
- flags |= coverage.fType == Coverage::kAttribute_Type ? kCoverage_GPType : 0;
- flags |= localCoords.fType == LocalCoords::kHasExplicit_Type ? kLocalCoord_GPType : 0;
+ flags |= color.fType == Color::kAttribute_Type ? kColor_GPFlag : 0;
+ flags |= coverage.fType == Coverage::kAttribute_Type ? kCoverage_GPFlag : 0;
+ flags |= localCoords.fType == LocalCoords::kHasExplicit_Type ? kLocalCoord_GPFlag : 0;
+ flags |= localCoords.fType == LocalCoords::kHasTransformed_Type ?
+ kTransformedLocalCoord_GPFlag : 0;
uint8_t inCoverage = coverage.fCoverage;
bool coverageWillBeIgnored = coverage.fType == Coverage::kNone_Type;
diff --git a/src/gpu/GrDefaultGeoProcFactory.h b/src/gpu/GrDefaultGeoProcFactory.h
index cd886a2..2d80558 100644
--- a/src/gpu/GrDefaultGeoProcFactory.h
+++ b/src/gpu/GrDefaultGeoProcFactory.h
@@ -64,14 +64,6 @@
GrColor fCoverage;
};
- enum GPType {
- kPosition_GPType = 0x0, // we ALWAYS have position
- kColor_GPType = 0x01,
- kLocalCoord_GPType = 0x02,
- kCoverage_GPType= 0x04,
- kLastGPType = kCoverage_GPType
- };
-
struct Color {
enum Type {
kNone_Type,
@@ -113,6 +105,7 @@
kUnused_Type,
kUsePosition_Type,
kHasExplicit_Type,
+ kHasTransformed_Type,
};
LocalCoords(Type type) : fType(type), fMatrix(NULL) {}
LocalCoords(Type type, const SkMatrix* matrix) : fType(type), fMatrix(matrix) {
diff --git a/src/gpu/GrGeometryProcessor.h b/src/gpu/GrGeometryProcessor.h
index ea4e890..96c1cb6 100644
--- a/src/gpu/GrGeometryProcessor.h
+++ b/src/gpu/GrGeometryProcessor.h
@@ -22,7 +22,7 @@
GrGeometryProcessor()
: INHERITED(false)
, fWillUseGeoShader(false)
- , fHasLocalCoords(false) {}
+ , fLocalCoordsType(kUnused_LocalCoordsType) {}
bool willUseGeoShader() const override { return fWillUseGeoShader; }
@@ -45,6 +45,14 @@
SkFAIL("Unsupported\n");
}
+ bool hasTransformedLocalCoords() const override {
+ return kHasTransformed_LocalCoordsType == fLocalCoordsType;
+ }
+
+ bool hasExplicitLocalCoords() const override {
+ return kHasExplicit_LocalCoordsType == fLocalCoordsType;
+ }
+
protected:
/**
* Subclasses call this from their constructor to register vertex attributes. Attributes
@@ -64,14 +72,32 @@
void setWillUseGeoShader() { fWillUseGeoShader = true; }
- // TODO hack see above
- void setHasLocalCoords() { fHasLocalCoords = true; }
+ /**
+ * If a GrFragmentProcessor in the GrPipeline needs localCoods, we will provide them in one of
+ * three ways
+ * 1) LocalCoordTransform * Position - in Shader
+ * 2) LocalCoordTransform * ExplicitLocalCoords- in Shader
+ * 3) A transformation on the CPU uploaded via vertex attribute
+ * TODO make this GrBatches responsibility
+ */
+ enum LocalCoordsType {
+ kUnused_LocalCoordsType,
+ kHasExplicit_LocalCoordsType,
+ kHasTransformed_LocalCoordsType
+ };
+
+ void setHasExplicitLocalCoords() {
+ SkASSERT(kUnused_LocalCoordsType == fLocalCoordsType);
+ fLocalCoordsType = kHasExplicit_LocalCoordsType;
+ }
+ void setHasTransformedLocalCoords() {
+ SkASSERT(kUnused_LocalCoordsType == fLocalCoordsType);
+ fLocalCoordsType = kHasTransformed_LocalCoordsType;
+ }
private:
- bool hasExplicitLocalCoords() const override { return fHasLocalCoords; }
-
bool fWillUseGeoShader;
- bool fHasLocalCoords;
+ LocalCoordsType fLocalCoordsType;
typedef GrPrimitiveProcessor INHERITED;
};
diff --git a/src/gpu/GrPathProcessor.h b/src/gpu/GrPathProcessor.h
index 7c1ab2b..1959795 100644
--- a/src/gpu/GrPathProcessor.h
+++ b/src/gpu/GrPathProcessor.h
@@ -54,6 +54,8 @@
virtual GrGLPrimitiveProcessor* createGLInstance(const GrBatchTracker& bt,
const GrGLSLCaps& caps) const override;
+ bool hasTransformedLocalCoords() const override { return false; }
+
private:
GrPathProcessor(GrColor color, const SkMatrix& viewMatrix, const SkMatrix& localMatrix);
diff --git a/src/gpu/GrPrimitiveProcessor.h b/src/gpu/GrPrimitiveProcessor.h
index e5635a8..54d7d8d 100644
--- a/src/gpu/GrPrimitiveProcessor.h
+++ b/src/gpu/GrPrimitiveProcessor.h
@@ -220,6 +220,12 @@
bool isPathRendering() const { return fIsPathRendering; }
+ /**
+ * No Local Coord Transformation is needed in the shader, instead transformed local coords will
+ * be provided via vertex attribute.
+ */
+ virtual bool hasTransformedLocalCoords() const = 0;
+
protected:
GrPrimitiveProcessor(bool isPathRendering)
: fNumAttribs(0)
diff --git a/src/gpu/gl/GrGLGeometryProcessor.cpp b/src/gpu/gl/GrGLGeometryProcessor.cpp
index dc4518f..4026c72 100644
--- a/src/gpu/gl/GrGLGeometryProcessor.cpp
+++ b/src/gpu/gl/GrGLGeometryProcessor.cpp
@@ -89,6 +89,35 @@
}
}
+void GrGLGeometryProcessor::emitTransforms(GrGLGPBuilder* pb,
+ const char* localCoords,
+ const TransformsIn& tin,
+ TransformsOut* tout) {
+ GrGLVertexBuilder* vb = pb->getVertexShaderBuilder();
+ tout->push_back_n(tin.count());
+ for (int i = 0; i < tin.count(); i++) {
+ const ProcCoords& coordTransforms = tin[i];
+ for (int t = 0; t < coordTransforms.count(); t++) {
+ GrSLType varyingType = kVec2f_GrSLType;
+
+ // Device coords aren't supported
+ SkASSERT(kDevice_GrCoordSet != coordTransforms[t]->sourceCoords());
+ GrSLPrecision precision = coordTransforms[t]->precision();
+
+ SkString strVaryingName("MatrixCoord");
+ strVaryingName.appendf("_%i_%i", i, t);
+
+ GrGLVertToFrag v(varyingType);
+ pb->addVarying(strVaryingName.c_str(), &v, precision);
+ vb->codeAppendf("%s = %s;", v.vsOut(), localCoords);
+
+ SkNEW_APPEND_TO_TARRAY(&(*tout)[i],
+ GrGLProcessor::TransformedCoords,
+ (SkString(v.fsIn()), varyingType));
+ }
+ }
+}
+
void GrGLGeometryProcessor::setupPosition(GrGLGPBuilder* pb,
GrGPArgs* gpArgs,
const char* posName) {
diff --git a/src/gpu/gl/GrGLGeometryProcessor.h b/src/gpu/gl/GrGLGeometryProcessor.h
index 747d82a..88baecf 100644
--- a/src/gpu/gl/GrGLGeometryProcessor.h
+++ b/src/gpu/gl/GrGLGeometryProcessor.h
@@ -41,7 +41,7 @@
}
protected:
- // A helper for subclasses which don't have an explicit local matrix
+ // Emit a uniform matrix for each coord transform.
void emitTransforms(GrGLGPBuilder* gp,
const GrShaderVar& posVar,
const char* localCoords,
@@ -50,6 +50,7 @@
this->emitTransforms(gp, posVar, localCoords, SkMatrix::I(), tin, tout);
}
+ // Emit pre-transformed coords as a vertex attribute per coord-transform.
void emitTransforms(GrGLGPBuilder*,
const GrShaderVar& posVar,
const char* localCoords,
@@ -57,6 +58,12 @@
const TransformsIn&,
TransformsOut*);
+ // caller has emitted transforms via attributes
+ void emitTransforms(GrGLGPBuilder*,
+ const char* localCoords,
+ const TransformsIn& tin,
+ TransformsOut* tout);
+
struct GrGPArgs {
// The variable used by a GP to store its position. It can be
// either a vec2 or a vec3 depending on the presence of perspective.
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
index daa2480..c7528f0 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
@@ -197,12 +197,15 @@
const GrPrimitiveProcessor& primProc = this->primitiveProcessor();
int totalTextures = primProc.numTextures();
const int maxTextureUnits = fGpu->glCaps().maxFragmentTextureUnits();
- SkSTArray<8, GrGLProcessor::TransformedCoordsArray> outCoords;
+
for (int i = 0; i < this->pipeline().numFragmentStages(); i++) {
const GrFragmentProcessor* processor = this->pipeline().getFragmentStage(i).processor();
- SkSTArray<2, const GrCoordTransform*, true>& procCoords = fCoordTransforms.push_back();
- append_gr_fp_coord_transforms(processor, &procCoords);
+ if (!primProc.hasTransformedLocalCoords()) {
+ SkSTArray<2, const GrCoordTransform*, true>& procCoords = fCoordTransforms.push_back();
+
+ append_gr_fp_coord_transforms(processor, &procCoords);
+ }
totalTextures += processor->numTexturesIncludeChildProcs();
if (totalTextures >= maxTextureUnits) {