Chromium Code Reviews| Index: src/gpu/effects/GrDashingEffect.cpp |
| diff --git a/src/gpu/effects/GrDashingEffect.cpp b/src/gpu/effects/GrDashingEffect.cpp |
| index 34e03011b2aced46670e3747f87f909164a61fa9..060e7f608dfbcbf62957d9a18be601a8f4c71347 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 fRadius; |
| + SkScalar fCenterX; |
| + SkScalar fIntervalLength; |
|
egdaniel
2015/02/03 14:45:59
move fIntervalLength before radius and center to m
|
| }; |
| }; |
| @@ -138,21 +147,82 @@ 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, |
| +}; |
| + |
| +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); |
| + verts[idx].fIntervalLength = intervalLength; |
| + verts[idx].fRadius = radius; |
| + verts[idx].fCenterX = centerX; |
| + verts[idx + 1].fRadius = radius; |
|
bsalomon
2015/02/03 01:02:01
nit, optional.. prolly fewer lines to write this a
|
| + verts[idx + 1].fCenterX = centerX; |
| + verts[idx + 1].fIntervalLength = intervalLength; |
| + verts[idx + 2].fRadius = radius; |
| + verts[idx + 2].fCenterX = centerX; |
| + verts[idx + 2].fIntervalLength = intervalLength; |
| + verts[idx + 3].fRadius = radius; |
| + verts[idx + 3].fCenterX = centerX; |
| + verts[idx + 3].fIntervalLength = intervalLength; |
| + |
| + } else { |
| + SkASSERT(kNonRound_DashCap == cap && vertexStride == sizeof(DashLineVertex)); |
|
egdaniel
2015/02/03 14:45:59
is the NonRound assert really needed since we alre
|
| + 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); |
| + verts[idx].fIntervalLength = intervalLength; |
| + verts[idx].fRect.set(halfOffLen + 0.5f, -halfStroke + 0.5f, |
|
egdaniel
2015/02/03 14:45:59
as with Brians comment, probably can loop this. Al
|
| + halfOffLen + startInterval - 0.5f, halfStroke - 0.5f); |
| + verts[idx + 1].fIntervalLength = intervalLength; |
| + verts[idx + 1].fRect.set(halfOffLen + 0.5f, -halfStroke + 0.5f, |
| + halfOffLen + startInterval - 0.5f, halfStroke - 0.5f); |
| + verts[idx + 2].fIntervalLength = intervalLength; |
| + verts[idx + 2].fRect.set(halfOffLen + 0.5f, -halfStroke + 0.5f, |
| + halfOffLen + startInterval - 0.5f, halfStroke - 0.5f); |
| + verts[idx + 3].fIntervalLength = intervalLength; |
| + verts[idx + 3].fRect.set(halfOffLen + 0.5f, -halfStroke + 0.5f, |
| + halfOffLen + startInterval - 0.5f, halfStroke - 0.5f); |
| + } |
| } |
| static void setup_dashed_rect_pos(const SkRect& rect, int idx, const SkMatrix& matrix, |
| @@ -164,6 +234,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 +424,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 +434,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 +479,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 +494,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 +510,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 +553,6 @@ public: |
| static GrGeometryProcessor* Create(GrColor, |
| GrPrimitiveEdgeType edgeType, |
| - const DashInfo& info, |
| - SkScalar radius, |
| const SkMatrix& localMatrix); |
| virtual ~DashingCircleEffect(); |
| @@ -486,13 +563,9 @@ public: |
| const Attribute* inCoord() const { return fInCoord; } |
| - GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; } |
| - |
| - SkScalar getRadius() const { return fRadius; } |
| - |
| - SkScalar getCenterX() const { return fCenterX; } |
| + const Attribute* inParams() const { return fInParams; } |
| - SkScalar getIntervalLength() const { return fIntervalLength; } |
| + GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; } |
| virtual void getGLProcessorKey(const GrBatchTracker&, |
| const GrGLCaps&, |
| @@ -508,19 +581,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* fInCoord; |
| + const Attribute* fInParams; |
| GR_DECLARE_GEOMETRY_PROCESSOR_TEST; |
| @@ -566,21 +636,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); |
| + GrGLVertToFrag coord(kVec2f_GrSLType); |
| + args.fPB->addVarying("Coord", &coord); |
| + vsBuilder->codeAppendf("%s = %s;", coord.vsOut(), dce.inCoord()->fName); |
| + |
| + // The param attribute, xyz, refer to circle radius - 0.5, cicles center x coord, and |
|
egdaniel
2015/02/03 14:45:59
Lets move the interval length to the second parame
|
| + // the total interval length of the dash. |
| + GrGLVertToFrag params(kVec3f_GrSLType); |
| + args.fPB->addVarying("Params", ¶ms); |
| + vsBuilder->codeAppendf("%s = %s;", params.vsOut(), dce.inParams()->fName); |
| // Setup pass through color |
| this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor, NULL, &fColorUniform); |
| @@ -597,18 +666,18 @@ 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;", |
| + coord.fsIn(), coord.fsIn(), params.fsIn(), params.fsIn()); |
| + fsBuilder->codeAppendf("vec2 fragPosShifted = vec2(xShifted, %s.y);", coord.fsIn()); |
| + fsBuilder->codeAppendf("vec2 center = vec2(%s.y, 0.0);", params.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;", params.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;", params.fsIn()); |
| } |
| fsBuilder->codeAppendf("%s = vec4(alpha);", args.fOutputCoverage); |
| } |
| @@ -618,17 +687,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 +713,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 +736,17 @@ 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); |
| + fInParams = &this->addVertexAttrib(Attribute("inParams", kVec3f_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 +774,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 +803,6 @@ public: |
| static GrGeometryProcessor* Create(GrColor, |
| GrPrimitiveEdgeType edgeType, |
| - const DashInfo& info, |
| - SkScalar strokeWidth, |
| const SkMatrix& localMatrix); |
| virtual ~DashingLineEffect(); |
| @@ -782,11 +813,9 @@ public: |
| const Attribute* inCoord() const { return fInCoord; } |
| - GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; } |
| + const Attribute* inRect() const { return fInRect; } |
| - const SkRect& getRect() const { return fRect; } |
| - |
| - SkScalar getIntervalLength() const { return fIntervalLength; } |
| + GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; } |
| virtual void getGLProcessorKey(const GrBatchTracker& bt, |
| const GrGLCaps& caps, |
| @@ -802,18 +831,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* fInCoord; |
| + const Attribute* fInRect; |
| GR_DECLARE_GEOMETRY_PROCESSOR_TEST; |
| @@ -839,48 +866,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, and Z is interval length |
|
egdaniel
2015/02/03 14:45:59
"XY refer to the transformed dash position, and Z.
|
| + GrGLVertToFrag inCoord(kVec3f_GrSLType); |
| + args.fPB->addVarying("Coord", &inCoord); |
| + vsBuilder->codeAppendf("%s = %s;", inCoord.vsOut(), de.inCoord()->fName); |
| + |
| + // The rect uniform's xyzw refer to (left + 0.5, top + 0.5, right - 0.5, bottom - 0.5), |
| + // respectively. |
| + GrGLVertToFrag inRect(kVec4f_GrSLType); |
| + args.fPB->addVarying("Rect", &inRect); |
| + vsBuilder->codeAppendf("%s = %s;", inRect.vsOut(), de.inRect()->fName); |
| // Setup pass through color |
| this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor, NULL, &fColorUniform); |
| @@ -897,25 +911,27 @@ 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;", |
| + inCoord.fsIn(), inCoord.fsIn(), inCoord.fsIn(), inCoord.fsIn()); |
| + fsBuilder->codeAppendf("vec2 fragPosShifted = vec2(xShifted, %s.y);", inCoord.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);", inRect.fsIn()); |
| + fsBuilder->codeAppendf("xSub += min(%s.z - fragPosShifted.x, 0.0);", inRect.fsIn()); |
| + fsBuilder->codeAppendf("ySub = min(fragPosShifted.y - %s.y, 0.0);", inRect.fsIn()); |
| + fsBuilder->codeAppendf("ySub += min(%s.w - fragPosShifted.y, 0.0);", inRect.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;", |
| + inRect.fsIn()); |
| + fsBuilder->codeAppendf("alpha *= (%s.z - fragPosShifted.x) >= -0.5 ? 1.0 : 0.0;", |
| + inRect.fsIn()); |
| } |
| fsBuilder->codeAppendf("%s = vec4(alpha);", args.fOutputCoverage); |
| } |
| @@ -925,17 +941,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 +967,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 +990,19 @@ 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); |
| + fInCoord = &this->addVertexAttrib(Attribute("inCoord", kVec3f_GrVertexAttribType)); |
| + fInRect = &this->addVertexAttrib(Attribute("inRect", kVec4f_GrVertexAttribType)); |
| } |
| bool DashingLineEffect::onIsEqual(const GrGeometryProcessor& other) const { |
| const DashingLineEffect& de = other.cast<DashingLineEffect>(); |
| - return (fEdgeType == de.fEdgeType && |
| + return (fEdgeType == de.fEdgeType/* && |
| fRect == de.fRect && |
| - fIntervalLength == de.fIntervalLength); |
| + fIntervalLength == de.fIntervalLength*/); |
| } |
| void DashingLineEffect::initBatchTracker(GrBatchTracker* bt, const GrPipelineInfo& init) const { |
| @@ -1038,35 +1030,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."); |
| } |