| 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.");
|
| }
|
|
|