Index: src/gpu/effects/GrDashingEffect.cpp |
diff --git a/src/gpu/effects/GrDashingEffect.cpp b/src/gpu/effects/GrDashingEffect.cpp |
index 34e03011b2aced46670e3747f87f909164a61fa9..a33d604668912cf6b5588671400a336e800006c9 100644 |
--- a/src/gpu/effects/GrDashingEffect.cpp |
+++ b/src/gpu/effects/GrDashingEffect.cpp |
@@ -67,6 +67,15 @@ namespace { |
struct DashLineVertex { |
SkPoint fPos; |
SkPoint fDashPos; |
+ SkScalar fIntervalLength; |
+ SkRect fRect; |
+}; |
+struct DashCircleVertex { |
+ SkPoint fPos; |
+ SkPoint fDashPos; |
+ SkScalar fIntervalLength; |
+ SkScalar fRadius; |
+ SkScalar fCenterX; |
}; |
}; |
@@ -138,21 +147,73 @@ static SkScalar calc_end_adjustment(const SkPathEffect::DashInfo& info, const Sk |
return 0; |
} |
-static void setup_dashed_rect(const SkRect& rect, DashLineVertex* verts, int idx, const SkMatrix& matrix, |
- SkScalar offset, SkScalar bloat, SkScalar len, SkScalar stroke) { |
- SkScalar startDashX = offset - bloat; |
- SkScalar endDashX = offset + len + bloat; |
- SkScalar startDashY = -stroke - bloat; |
- SkScalar endDashY = stroke + bloat; |
- verts[idx].fDashPos = SkPoint::Make(startDashX , startDashY); |
- verts[idx + 1].fDashPos = SkPoint::Make(startDashX, endDashY); |
- verts[idx + 2].fDashPos = SkPoint::Make(endDashX, endDashY); |
- verts[idx + 3].fDashPos = SkPoint::Make(endDashX, startDashY); |
- verts[idx].fPos = SkPoint::Make(rect.fLeft, rect.fTop); |
- verts[idx + 1].fPos = SkPoint::Make(rect.fLeft, rect.fBottom); |
- verts[idx + 2].fPos = SkPoint::Make(rect.fRight, rect.fBottom); |
- verts[idx + 3].fPos = SkPoint::Make(rect.fRight, rect.fTop); |
- matrix.mapPointsWithStride(&verts[idx].fPos, sizeof(DashLineVertex), 4); |
+enum DashCap { |
+ kRound_DashCap, |
+ kNonRound_DashCap, |
+}; |
+ |
+static int kDashVertices = 4; |
+ |
+template <typename T> |
+void setup_dashed_rect_common(const SkRect& rect, const SkMatrix& matrix, T* vertices, int idx, |
+ SkScalar offset, SkScalar bloat, SkScalar len, SkScalar stroke) { |
+ SkScalar startDashX = offset - bloat; |
+ SkScalar endDashX = offset + len + bloat; |
+ SkScalar startDashY = -stroke - bloat; |
+ SkScalar endDashY = stroke + bloat; |
+ vertices[idx].fDashPos = SkPoint::Make(startDashX , startDashY); |
+ vertices[idx + 1].fDashPos = SkPoint::Make(startDashX, endDashY); |
+ vertices[idx + 2].fDashPos = SkPoint::Make(endDashX, endDashY); |
+ vertices[idx + 3].fDashPos = SkPoint::Make(endDashX, startDashY); |
+ |
+ vertices[idx].fPos = SkPoint::Make(rect.fLeft, rect.fTop); |
+ vertices[idx + 1].fPos = SkPoint::Make(rect.fLeft, rect.fBottom); |
+ vertices[idx + 2].fPos = SkPoint::Make(rect.fRight, rect.fBottom); |
+ vertices[idx + 3].fPos = SkPoint::Make(rect.fRight, rect.fTop); |
+ |
+ matrix.mapPointsWithStride(&vertices[idx].fPos, sizeof(T), 4); |
+} |
+ |
+static void setup_dashed_rect(const SkRect& rect, void* vertices, int idx, |
+ const SkMatrix& matrix, SkScalar offset, SkScalar bloat, |
+ SkScalar len, SkScalar stroke, SkScalar startInterval, |
+ SkScalar endInterval, SkScalar strokeWidth, DashCap cap, |
+ const size_t vertexStride) { |
+ SkScalar intervalLength = startInterval + endInterval; |
+ |
+ if (kRound_DashCap == cap) { |
+ SkASSERT(vertexStride == sizeof(DashCircleVertex)); |
+ DashCircleVertex* verts = reinterpret_cast<DashCircleVertex*>(vertices); |
+ |
+ setup_dashed_rect_common<DashCircleVertex>(rect, matrix, verts, idx, offset, bloat, len, |
+ stroke); |
+ |
+ SkScalar radius = SkScalarHalf(strokeWidth) - 0.5f; |
+ SkScalar centerX = SkScalarHalf(endInterval); |
+ |
+ for (int i = 0; i < kDashVertices; i++) { |
+ verts[idx + i].fIntervalLength = intervalLength; |
+ verts[idx + i].fRadius = radius; |
+ verts[idx + i].fCenterX = centerX; |
+ } |
+ |
+ } else { |
+ SkASSERT(kNonRound_DashCap == cap && vertexStride == sizeof(DashLineVertex)); |
+ DashLineVertex* verts = reinterpret_cast<DashLineVertex*>(vertices); |
+ |
+ setup_dashed_rect_common<DashLineVertex>(rect, matrix, verts, idx, offset, bloat, len, |
+ stroke); |
+ |
+ SkScalar halfOffLen = SkScalarHalf(endInterval); |
+ SkScalar halfStroke = SkScalarHalf(strokeWidth); |
+ SkRect rectParam; |
+ rectParam.set(halfOffLen + 0.5f, -halfStroke + 0.5f, |
+ halfOffLen + startInterval - 0.5f, halfStroke - 0.5f); |
+ for (int i = 0; i < kDashVertices; i++) { |
+ verts[idx + i].fIntervalLength = intervalLength; |
+ verts[idx + i].fRect = rectParam; |
+ } |
+ } |
} |
static void setup_dashed_rect_pos(const SkRect& rect, int idx, const SkMatrix& matrix, |
@@ -164,6 +225,18 @@ static void setup_dashed_rect_pos(const SkRect& rect, int idx, const SkMatrix& m |
matrix.mapPoints(&verts[idx], 4); |
} |
+ |
+/** |
+ * An GrGeometryProcessor that renders a dashed line. |
+ * This GrGeometryProcessor is meant for dashed lines that only have a single on/off interval pair. |
+ * Bounding geometry is rendered and the effect computes coverage based on the fragment's |
+ * position relative to the dashed line. |
+ */ |
+static GrGeometryProcessor* create_dash_gp(GrColor, |
+ GrPrimitiveEdgeType edgeType, |
+ DashCap cap, |
+ const SkMatrix& localMatrix); |
+ |
bool GrDashingEffect::DrawDashLine(GrGpu* gpu, GrDrawTarget* target, |
GrPipelineBuilder* pipelineBuilder, GrColor color, |
const SkMatrix& viewMatrix, const SkPoint pts[2], |
@@ -342,6 +415,9 @@ bool GrDashingEffect::DrawDashLine(GrGpu* gpu, GrDrawTarget* target, |
return false; |
} |
+ bool isRoundCap = SkPaint::kRound_Cap == cap; |
+ DashCap capType = isRoundCap ? kRound_DashCap : kNonRound_DashCap; |
+ |
SkAutoTUnref<const GrGeometryProcessor> gp; |
bool fullDash = devIntervals[1] > 0.f || useAA; |
if (fullDash) { |
@@ -349,12 +425,9 @@ bool GrDashingEffect::DrawDashLine(GrGpu* gpu, GrDrawTarget* target, |
devInfo.fPhase = devPhase; |
devInfo.fCount = 2; |
devInfo.fIntervals = devIntervals; |
- GrPrimitiveEdgeType edgeType= useAA ? kFillAA_GrProcessorEdgeType : |
+ GrPrimitiveEdgeType edgeType = useAA ? kFillAA_GrProcessorEdgeType : |
kFillBW_GrProcessorEdgeType; |
- bool isRoundCap = SkPaint::kRound_Cap == cap; |
- GrDashingEffect::DashCap capType = isRoundCap ? GrDashingEffect::kRound_DashCap : |
- GrDashingEffect::kNonRound_DashCap; |
- gp.reset(GrDashingEffect::Create(color, edgeType, devInfo, strokeWidth, capType, invert)); |
+ gp.reset(create_dash_gp(color, edgeType, capType, invert)); |
} else { |
// Set up the vertex data for the line and start/end dashes |
gp.reset(GrDefaultGeoProcFactory::Create(GrDefaultGeoProcFactory::kPosition_GPType, |
@@ -397,10 +470,9 @@ bool GrDashingEffect::DrawDashLine(GrGpu* gpu, GrDrawTarget* target, |
bounds.set(ptsRot[0].fX, ptsRot[0].fY, ptsRot[1].fX, ptsRot[1].fY); |
bounds.outset(bloatX + strokeAdj, bloatY + halfSrcStroke); |
if (fullDash) { |
- DashLineVertex* verts = reinterpret_cast<DashLineVertex*>(geo.vertices()); |
- SkASSERT(gp->getVertexStride() == sizeof(DashLineVertex)); |
- setup_dashed_rect(bounds, verts, curVIdx, combinedMatrix, startOffset, devBloat, |
- lineLength, halfDevStroke); |
+ setup_dashed_rect(bounds, geo.vertices(), curVIdx, combinedMatrix, startOffset, |
+ devBloat, lineLength, halfDevStroke, devIntervals[0], devIntervals[1], |
+ strokeWidth, capType, gp->getVertexStride()); |
} else { |
SkPoint* verts = reinterpret_cast<SkPoint*>(geo.vertices()); |
SkASSERT(gp->getVertexStride() == sizeof(SkPoint)); |
@@ -413,10 +485,9 @@ bool GrDashingEffect::DrawDashLine(GrGpu* gpu, GrDrawTarget* target, |
SkASSERT(useAA); // so that we know bloatX and bloatY have been set |
startRect.outset(bloatX, bloatY); |
if (fullDash) { |
- DashLineVertex* verts = reinterpret_cast<DashLineVertex*>(geo.vertices()); |
- SkASSERT(gp->getVertexStride() == sizeof(DashLineVertex)); |
- setup_dashed_rect(startRect, verts, curVIdx, combinedMatrix, startOffset, devBloat, |
- devIntervals[0], halfDevStroke); |
+ setup_dashed_rect(startRect, geo.vertices(), curVIdx, combinedMatrix, startOffset, |
+ devBloat, devIntervals[0], halfDevStroke, devIntervals[0], |
+ devIntervals[1], strokeWidth, capType, gp->getVertexStride()); |
} else { |
SkPoint* verts = reinterpret_cast<SkPoint*>(geo.vertices()); |
SkASSERT(gp->getVertexStride() == sizeof(SkPoint)); |
@@ -430,10 +501,9 @@ bool GrDashingEffect::DrawDashLine(GrGpu* gpu, GrDrawTarget* target, |
SkASSERT(useAA); // so that we know bloatX and bloatY have been set |
endRect.outset(bloatX, bloatY); |
if (fullDash) { |
- DashLineVertex* verts = reinterpret_cast<DashLineVertex*>(geo.vertices()); |
- SkASSERT(gp->getVertexStride() == sizeof(DashLineVertex)); |
- setup_dashed_rect(endRect, verts, curVIdx, combinedMatrix, startOffset, devBloat, |
- devIntervals[0], halfDevStroke); |
+ setup_dashed_rect(endRect, geo.vertices(), curVIdx, combinedMatrix, startOffset, |
+ devBloat, devIntervals[0], halfDevStroke, devIntervals[0], |
+ devIntervals[1], strokeWidth, capType, gp->getVertexStride()); |
} else { |
SkPoint* verts = reinterpret_cast<SkPoint*>(geo.vertices()); |
SkASSERT(gp->getVertexStride() == sizeof(SkPoint)); |
@@ -474,8 +544,6 @@ public: |
static GrGeometryProcessor* Create(GrColor, |
GrPrimitiveEdgeType edgeType, |
- const DashInfo& info, |
- SkScalar radius, |
const SkMatrix& localMatrix); |
virtual ~DashingCircleEffect(); |
@@ -484,15 +552,11 @@ public: |
const Attribute* inPosition() const { return fInPosition; } |
- const Attribute* inCoord() const { return fInCoord; } |
- |
- GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; } |
- |
- SkScalar getRadius() const { return fRadius; } |
+ const Attribute* inDashParams() const { return fInDashParams; } |
- SkScalar getCenterX() const { return fCenterX; } |
+ const Attribute* inCircleParams() const { return fInCircleParams; } |
- SkScalar getIntervalLength() const { return fIntervalLength; } |
+ GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; } |
virtual void getGLProcessorKey(const GrBatchTracker&, |
const GrGLCaps&, |
@@ -508,19 +572,16 @@ public: |
const GrBatchTracker&) const SK_OVERRIDE; |
private: |
- DashingCircleEffect(GrColor, GrPrimitiveEdgeType edgeType, const DashInfo& info, |
- SkScalar radius, const SkMatrix& localMatrix); |
+ DashingCircleEffect(GrColor, GrPrimitiveEdgeType edgeType, const SkMatrix& localMatrix); |
bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE; |
void onGetInvariantOutputCoverage(GrInitInvariantOutput*) const SK_OVERRIDE; |
GrPrimitiveEdgeType fEdgeType; |
- const Attribute* fInPosition; |
- const Attribute* fInCoord; |
- SkScalar fIntervalLength; |
- SkScalar fRadius; |
- SkScalar fCenterX; |
+ const Attribute* fInPosition; |
+ const Attribute* fInDashParams; |
+ const Attribute* fInCircleParams; |
GR_DECLARE_GEOMETRY_PROCESSOR_TEST; |
@@ -566,21 +627,20 @@ void GLDashingCircleEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { |
const DashingCircleEffect& dce = args.fGP.cast<DashingCircleEffect>(); |
const DashingCircleBatchTracker local = args.fBT.cast<DashingCircleBatchTracker>(); |
GrGLGPBuilder* pb = args.fPB; |
- const char *paramName; |
- // The param uniforms, xyz, refer to circle radius - 0.5, cicles center x coord, and |
- // the total interval length of the dash. |
- fParamUniform = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility, |
- kVec3f_GrSLType, kDefault_GrSLPrecision, |
- "params", ¶mName); |
- |
GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); |
// emit attributes |
vsBuilder->emitAttributes(dce); |
- GrGLVertToFrag v(kVec2f_GrSLType); |
- args.fPB->addVarying("Coord", &v); |
- vsBuilder->codeAppendf("%s = %s;", v.vsOut(), dce.inCoord()->fName); |
+ // XY are dashPos, Z is dashInterval |
+ GrGLVertToFrag dashParams(kVec3f_GrSLType); |
+ args.fPB->addVarying("DashParam", &dashParams); |
+ vsBuilder->codeAppendf("%s = %s;", dashParams.vsOut(), dce.inDashParams()->fName); |
+ |
+ // xy, refer to circle radius - 0.5, z refers to cicles center x coord |
+ GrGLVertToFrag circleParams(kVec2f_GrSLType); |
+ args.fPB->addVarying("CircleParams", &circleParams); |
+ vsBuilder->codeAppendf("%s = %s;", circleParams.vsOut(), dce.inCircleParams()->fName); |
// Setup pass through color |
this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor, NULL, &fColorUniform); |
@@ -597,18 +657,19 @@ void GLDashingCircleEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { |
// transforms all points so that we can compare them to our test circle |
GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); |
- fsBuilder->codeAppendf("\t\tfloat xShifted = %s.x - floor(%s.x / %s.z) * %s.z;\n", |
- v.fsIn(), v.fsIn(), paramName, paramName); |
- fsBuilder->codeAppendf("\t\tvec2 fragPosShifted = vec2(xShifted, %s.y);\n", v.fsIn()); |
- fsBuilder->codeAppendf("\t\tvec2 center = vec2(%s.y, 0.0);\n", paramName); |
- fsBuilder->codeAppend("\t\tfloat dist = length(center - fragPosShifted);\n"); |
+ fsBuilder->codeAppendf("float xShifted = %s.x - floor(%s.x / %s.z) * %s.z;", |
+ dashParams.fsIn(), dashParams.fsIn(), dashParams.fsIn(), |
+ dashParams.fsIn()); |
+ fsBuilder->codeAppendf("vec2 fragPosShifted = vec2(xShifted, %s.y);", dashParams.fsIn()); |
+ fsBuilder->codeAppendf("vec2 center = vec2(%s.y, 0.0);", circleParams.fsIn()); |
+ fsBuilder->codeAppend("float dist = length(center - fragPosShifted);"); |
if (GrProcessorEdgeTypeIsAA(dce.getEdgeType())) { |
- fsBuilder->codeAppendf("\t\tfloat diff = dist - %s.x;\n", paramName); |
- fsBuilder->codeAppend("\t\tdiff = 1.0 - diff;\n"); |
- fsBuilder->codeAppend("\t\tfloat alpha = clamp(diff, 0.0, 1.0);\n"); |
+ fsBuilder->codeAppendf("float diff = dist - %s.x;", circleParams.fsIn()); |
+ fsBuilder->codeAppend("diff = 1.0 - diff;"); |
+ fsBuilder->codeAppend("float alpha = clamp(diff, 0.0, 1.0);"); |
} else { |
- fsBuilder->codeAppendf("\t\tfloat alpha = 1.0;\n"); |
- fsBuilder->codeAppendf("\t\talpha *= dist < %s.x + 0.5 ? 1.0 : 0.0;\n", paramName); |
+ fsBuilder->codeAppendf("float alpha = 1.0;"); |
+ fsBuilder->codeAppendf("alpha *= dist < %s.x + 0.5 ? 1.0 : 0.0;", circleParams.fsIn()); |
} |
fsBuilder->codeAppendf("%s = vec4(alpha);", args.fOutputCoverage); |
} |
@@ -618,17 +679,6 @@ void GLDashingCircleEffect::setData(const GrGLProgramDataManager& pdman, |
const GrBatchTracker& bt) { |
this->setUniformViewMatrix(pdman, processor.viewMatrix()); |
- const DashingCircleEffect& dce = processor.cast<DashingCircleEffect>(); |
- SkScalar radius = dce.getRadius(); |
- SkScalar centerX = dce.getCenterX(); |
- SkScalar intervalLength = dce.getIntervalLength(); |
- if (radius != fPrevRadius || centerX != fPrevCenterX || intervalLength != fPrevIntervalLength) { |
- pdman.set3f(fParamUniform, radius - 0.5f, centerX, intervalLength); |
- fPrevRadius = radius; |
- fPrevCenterX = centerX; |
- fPrevIntervalLength = intervalLength; |
- } |
- |
const DashingCircleBatchTracker& local = bt.cast<DashingCircleBatchTracker>(); |
if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) { |
GrGLfloat c[4]; |
@@ -655,14 +705,8 @@ void GLDashingCircleEffect::GenKey(const GrGeometryProcessor& gp, |
GrGeometryProcessor* DashingCircleEffect::Create(GrColor color, |
GrPrimitiveEdgeType edgeType, |
- const DashInfo& info, |
- SkScalar radius, |
const SkMatrix& localMatrix) { |
- if (info.fCount != 2 || info.fIntervals[0] != 0) { |
- return NULL; |
- } |
- |
- return SkNEW_ARGS(DashingCircleEffect, (color, edgeType, info, radius, localMatrix)); |
+ return SkNEW_ARGS(DashingCircleEffect, (color, edgeType, localMatrix)); |
} |
DashingCircleEffect::~DashingCircleEffect() {} |
@@ -684,26 +728,18 @@ GrGLPrimitiveProcessor* DashingCircleEffect::createGLInstance(const GrBatchTrack |
DashingCircleEffect::DashingCircleEffect(GrColor color, |
GrPrimitiveEdgeType edgeType, |
- const DashInfo& info, |
- SkScalar radius, |
const SkMatrix& localMatrix) |
: INHERITED(color, SkMatrix::I(), localMatrix), fEdgeType(edgeType) { |
this->initClassID<DashingCircleEffect>(); |
fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType)); |
- fInCoord = &this->addVertexAttrib(Attribute("inCoord", kVec2f_GrVertexAttribType)); |
- SkScalar onLen = info.fIntervals[0]; |
- SkScalar offLen = info.fIntervals[1]; |
- fIntervalLength = onLen + offLen; |
- fRadius = radius; |
- fCenterX = SkScalarHalf(offLen); |
+ fInDashParams = &this->addVertexAttrib(Attribute("inDashParams", kVec3f_GrVertexAttribType)); |
+ fInCircleParams = &this->addVertexAttrib(Attribute("inCircleParams", |
+ kVec2f_GrVertexAttribType)); |
} |
bool DashingCircleEffect::onIsEqual(const GrGeometryProcessor& other) const { |
const DashingCircleEffect& dce = other.cast<DashingCircleEffect>(); |
- return (fEdgeType == dce.fEdgeType && |
- fIntervalLength == dce.fIntervalLength && |
- fRadius == dce.fRadius && |
- fCenterX == dce.fCenterX); |
+ return fEdgeType == dce.fEdgeType; |
} |
void DashingCircleEffect::initBatchTracker(GrBatchTracker* bt, const GrPipelineInfo& init) const { |
@@ -731,18 +767,8 @@ GrGeometryProcessor* DashingCircleEffect::TestCreate(SkRandom* random, |
GrTexture*[]) { |
GrPrimitiveEdgeType edgeType = static_cast<GrPrimitiveEdgeType>(random->nextULessThan( |
kGrProcessorEdgeTypeCnt)); |
- SkScalar strokeWidth = random->nextRangeScalar(0, 100.f); |
- DashInfo info; |
- info.fCount = 2; |
- SkAutoTArray<SkScalar> intervals(info.fCount); |
- info.fIntervals = intervals.get(); |
- info.fIntervals[0] = 0; |
- info.fIntervals[1] = random->nextRangeScalar(0, 10.f); |
- info.fPhase = random->nextRangeScalar(0, info.fIntervals[1]); |
- |
return DashingCircleEffect::Create(GrRandomColor(random), |
- edgeType, info, strokeWidth, |
- GrProcessorUnitTest::TestMatrix(random)); |
+ edgeType, GrProcessorUnitTest::TestMatrix(random)); |
} |
////////////////////////////////////////////////////////////////////////////// |
@@ -770,8 +796,6 @@ public: |
static GrGeometryProcessor* Create(GrColor, |
GrPrimitiveEdgeType edgeType, |
- const DashInfo& info, |
- SkScalar strokeWidth, |
const SkMatrix& localMatrix); |
virtual ~DashingLineEffect(); |
@@ -780,13 +804,11 @@ public: |
const Attribute* inPosition() const { return fInPosition; } |
- const Attribute* inCoord() const { return fInCoord; } |
- |
- GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; } |
+ const Attribute* inDashParams() const { return fInDashParams; } |
- const SkRect& getRect() const { return fRect; } |
+ const Attribute* inRectParams() const { return fInRectParams; } |
- SkScalar getIntervalLength() const { return fIntervalLength; } |
+ GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; } |
virtual void getGLProcessorKey(const GrBatchTracker& bt, |
const GrGLCaps& caps, |
@@ -802,18 +824,16 @@ public: |
const GrBatchTracker&) const SK_OVERRIDE; |
private: |
- DashingLineEffect(GrColor, GrPrimitiveEdgeType edgeType, const DashInfo& info, |
- SkScalar strokeWidth, const SkMatrix& localMatrix); |
+ DashingLineEffect(GrColor, GrPrimitiveEdgeType edgeType, const SkMatrix& localMatrix); |
bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE; |
void onGetInvariantOutputCoverage(GrInitInvariantOutput*) const SK_OVERRIDE; |
GrPrimitiveEdgeType fEdgeType; |
- const Attribute* fInPosition; |
- const Attribute* fInCoord; |
- SkRect fRect; |
- SkScalar fIntervalLength; |
+ const Attribute* fInPosition; |
+ const Attribute* fInDashParams; |
+ const Attribute* fInRectParams; |
GR_DECLARE_GEOMETRY_PROCESSOR_TEST; |
@@ -839,48 +859,35 @@ public: |
private: |
GrColor fColor; |
- UniformHandle fRectUniform; |
- UniformHandle fIntervalUniform; |
UniformHandle fColorUniform; |
- SkRect fPrevRect; |
- SkScalar fPrevIntervalLength; |
typedef GrGLGeometryProcessor INHERITED; |
}; |
GLDashingLineEffect::GLDashingLineEffect(const GrGeometryProcessor&, |
const GrBatchTracker&) { |
fColor = GrColor_ILLEGAL; |
- fPrevRect.fLeft = SK_ScalarNaN; |
- fPrevIntervalLength = SK_ScalarMax; |
} |
void GLDashingLineEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { |
const DashingLineEffect& de = args.fGP.cast<DashingLineEffect>(); |
const DashingLineBatchTracker& local = args.fBT.cast<DashingLineBatchTracker>(); |
GrGLGPBuilder* pb = args.fPB; |
- const char *rectName; |
- // The rect uniform's xyzw refer to (left + 0.5, top + 0.5, right - 0.5, bottom - 0.5), |
- // respectively. |
- fRectUniform = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility, |
- kVec4f_GrSLType, kDefault_GrSLPrecision, |
- "rect", |
- &rectName); |
- const char *intervalName; |
- // The interval uniform's refers to the total length of the interval (on + off) |
- fIntervalUniform = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility, |
- kFloat_GrSLType, kDefault_GrSLPrecision, |
- "interval", |
- &intervalName); |
- |
GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); |
// emit attributes |
vsBuilder->emitAttributes(de); |
- GrGLVertToFrag v(kVec2f_GrSLType); |
- args.fPB->addVarying("Coord", &v); |
- vsBuilder->codeAppendf("%s = %s;", v.vsOut(), de.inCoord()->fName); |
+ // XY refers to dashPos, Z is the dash interval length |
+ GrGLVertToFrag inDashParams(kVec3f_GrSLType); |
+ args.fPB->addVarying("DashParams", &inDashParams); |
+ vsBuilder->codeAppendf("%s = %s;", inDashParams.vsOut(), de.inDashParams()->fName); |
+ |
+ // The rect uniform's xyzw refer to (left + 0.5, top + 0.5, right - 0.5, bottom - 0.5), |
+ // respectively. |
+ GrGLVertToFrag inRectParams(kVec4f_GrSLType); |
+ args.fPB->addVarying("RectParams", &inRectParams); |
+ vsBuilder->codeAppendf("%s = %s;", inRectParams.vsOut(), de.inRectParams()->fName); |
// Setup pass through color |
this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor, NULL, &fColorUniform); |
@@ -897,25 +904,28 @@ void GLDashingLineEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { |
// transforms all points so that we can compare them to our test rect |
GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); |
- fsBuilder->codeAppendf("\t\tfloat xShifted = %s.x - floor(%s.x / %s) * %s;\n", |
- v.fsIn(), v.fsIn(), intervalName, intervalName); |
- fsBuilder->codeAppendf("\t\tvec2 fragPosShifted = vec2(xShifted, %s.y);\n", v.fsIn()); |
+ fsBuilder->codeAppendf("float xShifted = %s.x - floor(%s.x / %s.z) * %s.z;", |
+ inDashParams.fsIn(), inDashParams.fsIn(), inDashParams.fsIn(), |
+ inDashParams.fsIn()); |
+ fsBuilder->codeAppendf("vec2 fragPosShifted = vec2(xShifted, %s.y);", inDashParams.fsIn()); |
if (GrProcessorEdgeTypeIsAA(de.getEdgeType())) { |
// The amount of coverage removed in x and y by the edges is computed as a pair of negative |
// numbers, xSub and ySub. |
- fsBuilder->codeAppend("\t\tfloat xSub, ySub;\n"); |
- fsBuilder->codeAppendf("\t\txSub = min(fragPosShifted.x - %s.x, 0.0);\n", rectName); |
- fsBuilder->codeAppendf("\t\txSub += min(%s.z - fragPosShifted.x, 0.0);\n", rectName); |
- fsBuilder->codeAppendf("\t\tySub = min(fragPosShifted.y - %s.y, 0.0);\n", rectName); |
- fsBuilder->codeAppendf("\t\tySub += min(%s.w - fragPosShifted.y, 0.0);\n", rectName); |
+ fsBuilder->codeAppend("float xSub, ySub;"); |
+ fsBuilder->codeAppendf("xSub = min(fragPosShifted.x - %s.x, 0.0);", inRectParams.fsIn()); |
+ fsBuilder->codeAppendf("xSub += min(%s.z - fragPosShifted.x, 0.0);", inRectParams.fsIn()); |
+ fsBuilder->codeAppendf("ySub = min(fragPosShifted.y - %s.y, 0.0);", inRectParams.fsIn()); |
+ fsBuilder->codeAppendf("ySub += min(%s.w - fragPosShifted.y, 0.0);", inRectParams.fsIn()); |
// Now compute coverage in x and y and multiply them to get the fraction of the pixel |
// covered. |
- fsBuilder->codeAppendf("\t\tfloat alpha = (1.0 + max(xSub, -1.0)) * (1.0 + max(ySub, -1.0));\n"); |
+ fsBuilder->codeAppendf("float alpha = (1.0 + max(xSub, -1.0)) * (1.0 + max(ySub, -1.0));"); |
} else { |
// Assuming the bounding geometry is tight so no need to check y values |
- fsBuilder->codeAppendf("\t\tfloat alpha = 1.0;\n"); |
- fsBuilder->codeAppendf("\t\talpha *= (fragPosShifted.x - %s.x) > -0.5 ? 1.0 : 0.0;\n", rectName); |
- fsBuilder->codeAppendf("\t\talpha *= (%s.z - fragPosShifted.x) >= -0.5 ? 1.0 : 0.0;\n", rectName); |
+ fsBuilder->codeAppendf("float alpha = 1.0;"); |
+ fsBuilder->codeAppendf("alpha *= (fragPosShifted.x - %s.x) > -0.5 ? 1.0 : 0.0;", |
+ inRectParams.fsIn()); |
+ fsBuilder->codeAppendf("alpha *= (%s.z - fragPosShifted.x) >= -0.5 ? 1.0 : 0.0;", |
+ inRectParams.fsIn()); |
} |
fsBuilder->codeAppendf("%s = vec4(alpha);", args.fOutputCoverage); |
} |
@@ -925,17 +935,6 @@ void GLDashingLineEffect::setData(const GrGLProgramDataManager& pdman, |
const GrBatchTracker& bt) { |
this->setUniformViewMatrix(pdman, processor.viewMatrix()); |
- const DashingLineEffect& de = processor.cast<DashingLineEffect>(); |
- const SkRect& rect = de.getRect(); |
- SkScalar intervalLength = de.getIntervalLength(); |
- if (rect != fPrevRect || intervalLength != fPrevIntervalLength) { |
- pdman.set4f(fRectUniform, rect.fLeft + 0.5f, rect.fTop + 0.5f, |
- rect.fRight - 0.5f, rect.fBottom - 0.5f); |
- pdman.set1f(fIntervalUniform, intervalLength); |
- fPrevRect = rect; |
- fPrevIntervalLength = intervalLength; |
- } |
- |
const DashingLineBatchTracker& local = bt.cast<DashingLineBatchTracker>(); |
if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) { |
GrGLfloat c[4]; |
@@ -962,14 +961,8 @@ void GLDashingLineEffect::GenKey(const GrGeometryProcessor& gp, |
GrGeometryProcessor* DashingLineEffect::Create(GrColor color, |
GrPrimitiveEdgeType edgeType, |
- const DashInfo& info, |
- SkScalar strokeWidth, |
const SkMatrix& localMatrix) { |
- if (info.fCount != 2) { |
- return NULL; |
- } |
- |
- return SkNEW_ARGS(DashingLineEffect, (color, edgeType, info, strokeWidth, localMatrix)); |
+ return SkNEW_ARGS(DashingLineEffect, (color, edgeType, localMatrix)); |
} |
DashingLineEffect::~DashingLineEffect() {} |
@@ -991,26 +984,17 @@ GrGLPrimitiveProcessor* DashingLineEffect::createGLInstance(const GrBatchTracker |
DashingLineEffect::DashingLineEffect(GrColor color, |
GrPrimitiveEdgeType edgeType, |
- const DashInfo& info, |
- SkScalar strokeWidth, |
const SkMatrix& localMatrix) |
: INHERITED(color, SkMatrix::I(), localMatrix), fEdgeType(edgeType) { |
this->initClassID<DashingLineEffect>(); |
fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType)); |
- fInCoord = &this->addVertexAttrib(Attribute("inCoord", kVec2f_GrVertexAttribType)); |
- SkScalar onLen = info.fIntervals[0]; |
- SkScalar offLen = info.fIntervals[1]; |
- SkScalar halfOffLen = SkScalarHalf(offLen); |
- SkScalar halfStroke = SkScalarHalf(strokeWidth); |
- fIntervalLength = onLen + offLen; |
- fRect.set(halfOffLen, -halfStroke, halfOffLen + onLen, halfStroke); |
+ fInDashParams = &this->addVertexAttrib(Attribute("inDashParams", kVec3f_GrVertexAttribType)); |
+ fInRectParams = &this->addVertexAttrib(Attribute("inRect", kVec4f_GrVertexAttribType)); |
} |
bool DashingLineEffect::onIsEqual(const GrGeometryProcessor& other) const { |
const DashingLineEffect& de = other.cast<DashingLineEffect>(); |
- return (fEdgeType == de.fEdgeType && |
- fRect == de.fRect && |
- fIntervalLength == de.fIntervalLength); |
+ return fEdgeType == de.fEdgeType; |
} |
void DashingLineEffect::initBatchTracker(GrBatchTracker* bt, const GrPipelineInfo& init) const { |
@@ -1038,35 +1022,22 @@ GrGeometryProcessor* DashingLineEffect::TestCreate(SkRandom* random, |
GrTexture*[]) { |
GrPrimitiveEdgeType edgeType = static_cast<GrPrimitiveEdgeType>(random->nextULessThan( |
kGrProcessorEdgeTypeCnt)); |
- SkScalar strokeWidth = random->nextRangeScalar(0, 100.f); |
- DashInfo info; |
- info.fCount = 2; |
- SkAutoTArray<SkScalar> intervals(info.fCount); |
- info.fIntervals = intervals.get(); |
- info.fIntervals[0] = random->nextRangeScalar(0, 10.f); |
- info.fIntervals[1] = random->nextRangeScalar(0, 10.f); |
- info.fPhase = random->nextRangeScalar(0, info.fIntervals[0] + info.fIntervals[1]); |
return DashingLineEffect::Create(GrRandomColor(random), |
- edgeType, info, strokeWidth, |
- GrProcessorUnitTest::TestMatrix(random)); |
+ edgeType, GrProcessorUnitTest::TestMatrix(random)); |
} |
////////////////////////////////////////////////////////////////////////////// |
-GrGeometryProcessor* GrDashingEffect::Create(GrColor color, |
- GrPrimitiveEdgeType edgeType, |
- const SkPathEffect::DashInfo& info, |
- SkScalar strokeWidth, |
- GrDashingEffect::DashCap cap, |
- const SkMatrix& localMatrix) { |
+static GrGeometryProcessor* create_dash_gp(GrColor color, |
+ GrPrimitiveEdgeType edgeType, |
+ DashCap cap, |
+ const SkMatrix& localMatrix) { |
switch (cap) { |
- case GrDashingEffect::kRound_DashCap: |
- return DashingCircleEffect::Create(color, edgeType, info, |
- SkScalarHalf(strokeWidth), |
- localMatrix); |
- case GrDashingEffect::kNonRound_DashCap: |
- return DashingLineEffect::Create(color, edgeType, info, strokeWidth, localMatrix); |
+ case kRound_DashCap: |
+ return DashingCircleEffect::Create(color, edgeType, localMatrix); |
+ case kNonRound_DashCap: |
+ return DashingLineEffect::Create(color, edgeType, localMatrix); |
default: |
SkFAIL("Unexpected dashed cap."); |
} |