Chromium Code Reviews| Index: src/gpu/effects/GrDashingEffect.cpp |
| diff --git a/src/gpu/effects/GrDashingEffect.cpp b/src/gpu/effects/GrDashingEffect.cpp |
| index 3b06c3a52312fa77982324c03483260d9a872b73..e0745d26e7123eb5bae8203be2b85a42e1acd29d 100644 |
| --- a/src/gpu/effects/GrDashingEffect.cpp |
| +++ b/src/gpu/effects/GrDashingEffect.cpp |
| @@ -7,17 +7,68 @@ |
| #include "GrDashingEffect.h" |
| +#include "../GrAARectRenderer.h" |
| + |
| +#include "effects/GrVertexEffect.h" |
| #include "gl/GrGLEffect.h" |
| +#include "gl/GrGLVertexEffect.h" |
| #include "gl/GrGLSL.h" |
| #include "GrContext.h" |
| #include "GrCoordTransform.h" |
| +#include "GrDrawTarget.h" |
| #include "GrDrawTargetCaps.h" |
| #include "GrEffect.h" |
| +#include "GrGpu.h" |
| +#include "GrStrokeInfo.h" |
| #include "GrTBackendEffectFactory.h" |
| #include "SkGr.h" |
| /////////////////////////////////////////////////////////////////////////////// |
| +// Returns whether or not the gpu can fast path the dash line effect. |
| +static bool can_fast_path_dash(const SkPoint pts[2], const GrStrokeInfo& strokeInfo, |
| + const GrDrawTarget& target, const SkMatrix& viewMatrix) { |
| + if (target.getDrawState().getRenderTarget()->isMultisampled()) { |
| + return false; |
| + } |
| + |
| + // Pts must be either horizontal or vertical in src space |
| + if (pts[0].fX != pts[1].fX && pts[0].fY != pts[1].fY) { |
| + return false; |
| + } |
| + |
| + // May be able to relax this to include skew. As of not cannot do perspective |
|
bsalomon
2014/06/11 13:24:44
not->now?
|
| + // because of the non uniform scaling of bloating a rect |
| + if (!viewMatrix.preservesRightAngles()) { |
| + return false; |
| + } |
| + |
| + if (!strokeInfo.isDashed() || 2 != strokeInfo.dashCount()) { |
| + return false; |
| + } |
| + |
| + SkPaint::Cap cap = strokeInfo.getStrokeRec().getCap(); |
| + // Current we do don't handle Round or Square cap dashes |
| + if (SkPaint::kRound_Cap == cap) { |
| + return false; |
| + } |
| + |
| + return true; |
| +} |
| + |
| +namespace { |
| + |
| +struct DashLineVertex { |
| + SkPoint fPos; |
| + SkPoint fDashPos; |
| +}; |
| + |
| +extern const GrVertexAttrib gDashLineVertexAttribs[] = { |
| + { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding }, |
| + { kVec2f_GrVertexAttribType, sizeof(SkPoint), kEffect_GrVertexAttribBinding }, |
| +}; |
| + |
| +}; |
| static void calc_dash_scaling(SkScalar* parallelScale, SkScalar* perpScale, |
| const SkMatrix& viewMatrix, const SkPoint pts[2]) { |
| SkVector vecSrc = pts[1] - pts[0]; |
| @@ -62,7 +113,8 @@ static SkScalar calc_start_adjustment(const SkPathEffect::DashInfo& info) { |
| return 0; |
| } |
| -static SkScalar calc_end_adjustment(const SkPathEffect::DashInfo& info, const SkPoint pts[2], SkScalar* endingInt) { |
| +static SkScalar calc_end_adjustment(const SkPathEffect::DashInfo& info, const SkPoint pts[2], |
| + SkScalar phase, SkScalar* endingInt) { |
| if (pts[1].fX <= pts[0].fX) { |
| return 0; |
| } |
| @@ -70,7 +122,7 @@ static SkScalar calc_end_adjustment(const SkPathEffect::DashInfo& info, const Sk |
| SkScalar totalLen = pts[1].fX - pts[0].fX; |
| SkScalar temp = SkScalarDiv(totalLen, srcIntervalLen); |
| SkScalar numFullIntervals = SkScalarFloorToScalar(temp); |
| - *endingInt = totalLen - numFullIntervals * srcIntervalLen + info.fPhase; |
| + *endingInt = totalLen - numFullIntervals * srcIntervalLen + phase; |
| temp = SkScalarDiv(*endingInt, srcIntervalLen); |
| *endingInt = *endingInt - SkScalarFloorToScalar(temp) * srcIntervalLen; |
| if (0 == *endingInt) { |
| @@ -85,188 +137,260 @@ 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.mapPoints(&verts[idx].fPos, 1); |
|
bsalomon
2014/06/11 13:24:44
Not sure if it's clearer, but there is a mapPoints
|
| + matrix.mapPoints(&verts[idx + 1].fPos, 1); |
| + matrix.mapPoints(&verts[idx + 2].fPos, 1); |
| + matrix.mapPoints(&verts[idx + 3].fPos, 1); |
| +} |
| -bool GrDashingEffect::DrawDashLine(const SkPoint pts[2], const SkPaint& paint, GrContext* context) { |
| - if (context->getRenderTarget()->isMultisampled()) { |
| - return false; |
| - } |
| - const SkMatrix& viewMatrix = context->getMatrix(); |
| - if (!viewMatrix.preservesRightAngles()) { |
| - return false; |
| - } |
| +bool GrDashingEffect::DrawDashLine(const SkPoint pts[2], const GrPaint& paint, |
| + const GrStrokeInfo& strokeInfo, GrGpu* gpu, |
| + GrDrawTarget* target, const SkMatrix& vm) { |
| - const SkPathEffect* pe = paint.getPathEffect(); |
| - SkPathEffect::DashInfo info; |
| - SkPathEffect::DashType dashType = pe->asADash(&info); |
| - // Must be a dash effect with 2 intervals (1 on and 1 off) |
| - if (SkPathEffect::kDash_DashType != dashType || 2 != info.fCount) { |
| + if (!can_fast_path_dash(pts, strokeInfo, *target, vm)) { |
| return false; |
| } |
| - SkPaint::Cap cap = paint.getStrokeCap(); |
| - // Current we do don't handle Round or Square cap dashes |
| - if (SkPaint::kRound_Cap == cap) { |
| - return false; |
| - } |
| + const SkPathEffect::DashInfo& info = strokeInfo.getDashInfo(); |
| - SkScalar srcStrokeWidth = paint.getStrokeWidth(); |
| + SkPaint::Cap cap = strokeInfo.getStrokeRec().getCap(); |
| - // Get all info about the dash effect |
| - SkAutoTArray<SkScalar> intervals(info.fCount); |
| - info.fIntervals = intervals.get(); |
| - pe->asADash(&info); |
| + SkScalar srcStrokeWidth = strokeInfo.getStrokeRec().getWidth(); |
| // the phase should be normalized to be [0, sum of all intervals) |
| SkASSERT(info.fPhase >= 0 && info.fPhase < info.fIntervals[0] + info.fIntervals[1]); |
| - SkMatrix coordTrans; |
| + SkScalar srcPhase = info.fPhase; |
| // Rotate the src pts so they are aligned horizontally with pts[0].fX < pts[1].fX |
| SkMatrix srcRotInv; |
| SkPoint ptsRot[2]; |
| if (pts[0].fY != pts[1].fY || pts[0].fX > pts[1].fX) { |
| - align_to_x_axis(pts, &coordTrans, ptsRot); |
| - if(!coordTrans.invert(&srcRotInv)) { |
| + SkMatrix rotMatrix; |
| + align_to_x_axis(pts, &rotMatrix, ptsRot); |
| + if(!rotMatrix.invert(&srcRotInv)) { |
| + GrPrintf("Failed to create invertible rotation matrix!\n"); |
| return false; |
| } |
| } else { |
| - coordTrans.reset(); |
| srcRotInv.reset(); |
| memcpy(ptsRot, pts, 2 * sizeof(SkPoint)); |
| } |
| - GrPaint grPaint; |
| - SkPaint2GrPaintShader(context, paint, true, &grPaint); |
| - |
| bool useAA = paint.isAntiAlias(); |
| // Scale corrections of intervals and stroke from view matrix |
| SkScalar parallelScale; |
| SkScalar perpScale; |
| - calc_dash_scaling(¶llelScale, &perpScale, viewMatrix, ptsRot); |
| + calc_dash_scaling(¶llelScale, &perpScale, vm, ptsRot); |
| bool hasCap = SkPaint::kSquare_Cap == cap && 0 != srcStrokeWidth; |
| // We always want to at least stroke out half a pixel on each side in device space |
| // so 0.5f / perpScale gives us this min in src space |
| - SkScalar halfStroke = SkMaxScalar(srcStrokeWidth * 0.5f, 0.5f / perpScale); |
| + SkScalar halfSrcStroke = SkMaxScalar(srcStrokeWidth * 0.5f, 0.5f / perpScale); |
| - SkScalar xStroke; |
| + SkScalar strokeAdj; |
| if (!hasCap) { |
| - xStroke = 0.f; |
| + strokeAdj = 0.f; |
| } else { |
| - xStroke = halfStroke; |
| + strokeAdj = halfSrcStroke; |
| } |
| + SkScalar startAdj = 0; |
| + |
| + SkMatrix combinedMatrix = srcRotInv; |
| + combinedMatrix.postConcat(vm); |
| + |
| + bool lineDone = false; |
| + SkRect startRect; |
| + bool hasStartRect = false; |
| // If we are using AA, check to see if we are drawing a partial dash at the start. If so |
| // draw it separately here and adjust our start point accordingly |
| if (useAA) { |
| - if (info.fPhase > 0 && info.fPhase < info.fIntervals[0]) { |
| + if (srcPhase > 0 && srcPhase < info.fIntervals[0]) { |
| SkPoint startPts[2]; |
| startPts[0] = ptsRot[0]; |
| startPts[1].fY = startPts[0].fY; |
| - startPts[1].fX = SkMinScalar(startPts[0].fX + info.fIntervals[0] - info.fPhase, |
| + startPts[1].fX = SkMinScalar(startPts[0].fX + info.fIntervals[0] - srcPhase, |
| ptsRot[1].fX); |
| - SkRect startRect; |
| startRect.set(startPts, 2); |
| - startRect.outset(xStroke, halfStroke); |
| - context->drawRect(grPaint, startRect, NULL, &srcRotInv); |
| + startRect.outset(strokeAdj, halfSrcStroke); |
| - ptsRot[0].fX += info.fIntervals[0] + info.fIntervals[1] - info.fPhase; |
| - info.fPhase = 0; |
| + hasStartRect = true; |
| + startAdj = info.fIntervals[0] + info.fIntervals[1] - srcPhase; |
| } |
| } |
| // adjustments for start and end of bounding rect so we only draw dash intervals |
| // contained in the original line segment. |
| - SkScalar startAdj = calc_start_adjustment(info); |
| + startAdj += calc_start_adjustment(info); |
| + if (startAdj != 0) { |
| + ptsRot[0].fX += startAdj; |
| + srcPhase = 0; |
| + } |
| SkScalar endingInterval = 0; |
| - SkScalar endAdj = calc_end_adjustment(info, ptsRot, &endingInterval); |
| - if (ptsRot[0].fX + startAdj >= ptsRot[1].fX - endAdj) { |
| - // Nothing left to draw so just return |
| - return true; |
| + SkScalar endAdj = calc_end_adjustment(info, ptsRot, srcPhase, &endingInterval); |
| + ptsRot[1].fX -= endAdj; |
| + if (ptsRot[0].fX >= ptsRot[1].fX) { |
| + lineDone = true; |
| } |
| + SkRect endRect; |
| + bool hasEndRect = false; |
| // If we are using AA, check to see if we are drawing a partial dash at then end. If so |
| // draw it separately here and adjust our end point accordingly |
| - if (useAA) { |
| + if (useAA && !lineDone) { |
| // If we adjusted the end then we will not be drawing a partial dash at the end. |
| // If we didn't adjust the end point then we just need to make sure the ending |
| // dash isn't a full dash |
| if (0 == endAdj && endingInterval != info.fIntervals[0]) { |
| - |
| SkPoint endPts[2]; |
| endPts[1] = ptsRot[1]; |
| endPts[0].fY = endPts[1].fY; |
| endPts[0].fX = endPts[1].fX - endingInterval; |
| - SkRect endRect; |
| endRect.set(endPts, 2); |
| - endRect.outset(xStroke, halfStroke); |
| - context->drawRect(grPaint, endRect, NULL, &srcRotInv); |
| + endRect.outset(strokeAdj, halfSrcStroke); |
| + |
| + hasEndRect = true; |
| + endAdj = endingInterval + info.fIntervals[1]; |
| - ptsRot[1].fX -= endingInterval + info.fIntervals[1]; |
| + ptsRot[1].fX -= endAdj; |
| if (ptsRot[0].fX >= ptsRot[1].fX) { |
| - // Nothing left to draw so just return |
| - return true; |
| + lineDone = true; |
| } |
| } |
| } |
| - coordTrans.postConcat(viewMatrix); |
| - SkPoint devicePts[2]; |
| - viewMatrix.mapPoints(devicePts, ptsRot, 2); |
| + if (startAdj != 0) { |
| + srcPhase = 0; |
| + } |
| - info.fIntervals[0] *= parallelScale; |
| - info.fIntervals[1] *= parallelScale; |
| - info.fPhase *= parallelScale; |
| + // Change the dashing info from src space into device space |
| + SkScalar devIntervals[2]; |
| + devIntervals[0] = info.fIntervals[0] * parallelScale; |
| + devIntervals[1] = info.fIntervals[1] * parallelScale; |
| + SkScalar devPhase = srcPhase * parallelScale; |
| SkScalar strokeWidth = srcStrokeWidth * perpScale; |
| if ((strokeWidth < 1.f && !useAA) || 0.f == strokeWidth) { |
| strokeWidth = 1.f; |
| } |
| - // Set up coordTransform for device space transforms |
| - // We rotate the dashed line such that it is horizontal with the start point at smaller x |
| - // then we translate the start point to the origin |
| - if (devicePts[0].fY != devicePts[1].fY || devicePts[0].fX > devicePts[1].fX) { |
| - SkMatrix rot; |
| - align_to_x_axis(devicePts, &rot); |
| - coordTrans.postConcat(rot); |
| - } |
| - coordTrans.postTranslate(-devicePts[0].fX, -devicePts[0].fY); |
| - coordTrans.postTranslate(info.fIntervals[1] * 0.5f + info.fPhase, 0); |
| + SkScalar halfDevStroke = strokeWidth * 0.5f; |
| if (SkPaint::kSquare_Cap == cap && 0 != srcStrokeWidth) { |
| // add cap to on interveal and remove from off interval |
| - info.fIntervals[0] += strokeWidth; |
| - info.fIntervals[1] -= strokeWidth; |
| + devIntervals[0] += strokeWidth; |
| + devIntervals[1] -= strokeWidth; |
| } |
| - |
| - if (info.fIntervals[1] > 0.f) { |
| + SkScalar startOffset = devIntervals[1] * 0.5 + devPhase; |
| + |
| + SkScalar bloatX = useAA ? 0.5f / parallelScale : 0.f; |
| + SkScalar bloatY = useAA ? 0.5f / perpScale : 0.f; |
| + |
| + SkScalar devBloat = useAA ? 0.5f : 0.f; |
| + |
| + GrDrawState* drawState = target->drawState(); |
| + if (devIntervals[1] <= 0.f) { |
| + if (useAA) { |
| + // Case when we end up drawing a solid AA rect |
| + GrAARectRenderer* aaRectRenderer = SkNEW(GrAARectRenderer); |
|
bsalomon
2014/06/11 13:24:44
Hmm... it seems a bit expensive to cons up an obje
|
| + ptsRot[0].fX -= hasStartRect ? startAdj : 0; |
| + ptsRot[1].fX += hasEndRect ? endAdj : 0; |
| + SkRect rect; |
| + rect.set(ptsRot, 2); |
| + rect.outset(strokeAdj, halfSrcStroke); |
| + SkRect devRect; |
| + combinedMatrix.mapRect(&devRect, rect); |
| + aaRectRenderer->fillAARect(gpu, target, rect, combinedMatrix, devRect, false); |
| + aaRectRenderer->unref(); |
| + return true; |
| + } |
| + } else { |
| + SkPathEffect::DashInfo devInfo; |
| + devInfo.fPhase = devPhase; |
| + devInfo.fCount = 2; |
| + devInfo.fIntervals = devIntervals; |
| GrEffectEdgeType edgeType= useAA ? kFillAA_GrEffectEdgeType : |
| kFillBW_GrEffectEdgeType; |
| - grPaint.addCoverageEffect( |
| - GrDashingEffect::Create(edgeType, info, coordTrans, strokeWidth))->unref(); |
| - grPaint.setAntiAlias(false); |
| + drawState->addCoverageEffect( |
| + GrDashingEffect::Create(edgeType, devInfo, strokeWidth), 1)->unref(); |
| } |
| - SkRect rect; |
| - bool bloat = useAA && info.fIntervals[1] > 0.f; |
| - SkScalar bloatX = bloat ? 0.5f / parallelScale : 0.f; |
| - SkScalar bloatY = bloat ? 0.5f / perpScale : 0.f; |
| - ptsRot[0].fX += startAdj; |
| - ptsRot[1].fX -= endAdj; |
| - if (!hasCap) { |
| - xStroke = 0.f; |
| - } else { |
| - xStroke = halfStroke; |
| + // Set up the vertex data for the line and start/end dashes |
| + drawState->setVertexAttribs<gDashLineVertexAttribs>(SK_ARRAY_COUNT(gDashLineVertexAttribs)); |
| + |
| + int totalRectCnt = 0; |
| + |
| + totalRectCnt += !lineDone ? 1 : 0; |
| + totalRectCnt += hasStartRect ? 1 : 0; |
| + totalRectCnt += hasEndRect ? 1 : 0; |
| + |
| + GrDrawTarget::AutoReleaseGeometry geo(target, totalRectCnt * 4, 0); |
| + if (!geo.succeeded()) { |
| + GrPrintf("Failed to get space for vertices!\n"); |
| + return false; |
| + } |
| + |
| + DashLineVertex* verts = reinterpret_cast<DashLineVertex*>(geo.vertices()); |
| + |
| + int curVIdx = 0; |
| + |
| + // Draw interior part of dashed line |
| + if (!lineDone) { |
| + SkPoint devicePts[2]; |
| + vm.mapPoints(devicePts, ptsRot, 2); |
| + SkScalar lineLength = SkPoint::Distance(devicePts[0], devicePts[1]); |
| + if (hasCap) { |
| + lineLength += 2.f * halfDevStroke; |
| + } |
| + |
| + SkRect bounds; |
| + bounds.set(ptsRot[0].fX, ptsRot[0].fY, ptsRot[1].fX, ptsRot[1].fY); |
| + bounds.outset(bloatX + strokeAdj, bloatY + halfSrcStroke); |
| + setup_dashed_rect(bounds, verts, curVIdx, combinedMatrix, startOffset, devBloat, |
| + lineLength, halfDevStroke); |
| + curVIdx += 4; |
| + } |
| + |
| + if (hasStartRect) { |
| + SkASSERT(useAA); // so that we know bloatX and bloatY have been set |
| + startRect.outset(bloatX, bloatY); |
| + setup_dashed_rect(startRect, verts, curVIdx, combinedMatrix, startOffset, devBloat, |
| + devIntervals[0], halfDevStroke); |
| + curVIdx += 4; |
| } |
| - rect.set(ptsRot, 2); |
| - rect.outset(bloatX + xStroke, bloatY + halfStroke); |
| - context->drawRect(grPaint, rect, NULL, &srcRotInv); |
| + if (hasEndRect) { |
| + SkASSERT(useAA); // so that we know bloatX and bloatY have been set |
| + endRect.outset(bloatX, bloatY); |
| + setup_dashed_rect(endRect, verts, curVIdx, combinedMatrix, startOffset, devBloat, |
| + devIntervals[0], halfDevStroke); |
| + } |
| + |
| + target->setIndexSourceToBuffer(gpu->getContext()->getQuadIndexBuffer()); |
| + target->drawIndexedInstances(kTriangles_GrPrimitiveType, totalRectCnt, 4, 6); |
| + target->resetIndexSource(); |
| return true; |
| } |
| @@ -274,7 +398,7 @@ bool GrDashingEffect::DrawDashLine(const SkPoint pts[2], const SkPaint& paint, G |
| class GLDashingLineEffect; |
| -class DashingLineEffect : public GrEffect { |
| +class DashingLineEffect : public GrVertexEffect { |
| public: |
| typedef SkPathEffect::DashInfo DashInfo; |
| @@ -286,7 +410,7 @@ public: |
| * and half the off interval. |
| */ |
| static GrEffectRef* Create(GrEffectEdgeType edgeType, const DashInfo& info, |
| - const SkMatrix& matrix, SkScalar strokeWidth); |
| + SkScalar strokeWidth); |
| virtual ~DashingLineEffect(); |
| @@ -305,13 +429,11 @@ public: |
| virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; |
| private: |
| - DashingLineEffect(GrEffectEdgeType edgeType, const DashInfo& info, const SkMatrix& matrix, |
| - SkScalar strokeWidth); |
| + DashingLineEffect(GrEffectEdgeType edgeType, const DashInfo& info, SkScalar strokeWidth); |
| virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE; |
| GrEffectEdgeType fEdgeType; |
| - GrCoordTransform fCoordTransform; |
| SkRect fRect; |
| SkScalar fIntervalLength; |
| @@ -322,11 +444,11 @@ private: |
| ////////////////////////////////////////////////////////////////////////////// |
| -class GLDashingLineEffect : public GrGLEffect { |
| +class GLDashingLineEffect : public GrGLVertexEffect { |
| public: |
| GLDashingLineEffect(const GrBackendEffectFactory&, const GrDrawEffect&); |
| - virtual void emitCode(GrGLShaderBuilder* builder, |
| + virtual void emitCode(GrGLFullShaderBuilder* builder, |
| const GrDrawEffect& drawEffect, |
| EffectKey key, |
| const char* outputColor, |
| @@ -343,7 +465,7 @@ private: |
| GrGLUniformManager::UniformHandle fIntervalUniform; |
| SkRect fPrevRect; |
| SkScalar fPrevIntervalLength; |
| - typedef GrGLEffect INHERITED; |
| + typedef GrGLVertexEffect INHERITED; |
| }; |
| GLDashingLineEffect::GLDashingLineEffect(const GrBackendEffectFactory& factory, |
| @@ -354,12 +476,12 @@ GLDashingLineEffect::GLDashingLineEffect(const GrBackendEffectFactory& factory, |
| } |
| -void GLDashingLineEffect::emitCode(GrGLShaderBuilder* builder, |
| +void GLDashingLineEffect::emitCode(GrGLFullShaderBuilder* builder, |
| const GrDrawEffect& drawEffect, |
| EffectKey key, |
| const char* outputColor, |
| const char* inputColor, |
| - const TransformedCoordsArray& coords, |
| + const TransformedCoordsArray&, |
| const TextureSamplerArray& samplers) { |
| const DashingLineEffect& de = drawEffect.castEffect<DashingLineEffect>(); |
| const char *rectName; |
| @@ -375,10 +497,17 @@ void GLDashingLineEffect::emitCode(GrGLShaderBuilder* builder, |
| kFloat_GrSLType, |
| "interval", |
| &intervalName); |
| + |
| + const char *vsCoordName, *fsCoordName; |
| + builder->addVarying(kVec2f_GrSLType, "Coord", &vsCoordName, &fsCoordName); |
| + const SkString* attr0Name = |
| + builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); |
| + builder->vsCodeAppendf("\t%s = %s;\n", vsCoordName, attr0Name->c_str()); |
| + |
| // transforms all points so that we can compare them to our test rect |
| builder->fsCodeAppendf("\t\tfloat xShifted = %s.x - floor(%s.x / %s) * %s;\n", |
| - coords[0].c_str(), coords[0].c_str(), intervalName, intervalName); |
| - builder->fsCodeAppendf("\t\tvec2 fragPosShifted = vec2(xShifted, %s.y);\n", coords[0].c_str()); |
| + fsCoordName, fsCoordName, intervalName, intervalName); |
| + builder->fsCodeAppendf("\t\tvec2 fragPosShifted = vec2(xShifted, %s.y);\n", fsCoordName); |
| if (GrEffectEdgeTypeIsAA(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. |
| @@ -422,13 +551,13 @@ GrGLEffect::EffectKey GLDashingLineEffect::GenKey(const GrDrawEffect& drawEffect |
| ////////////////////////////////////////////////////////////////////////////// |
| GrEffectRef* DashingLineEffect::Create(GrEffectEdgeType edgeType, const DashInfo& info, |
| - const SkMatrix& matrix, SkScalar strokeWidth) { |
| + SkScalar strokeWidth) { |
| if (info.fCount != 2) { |
| return NULL; |
| } |
| return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(DashingLineEffect, |
| - (edgeType, info, matrix, strokeWidth)))); |
| + (edgeType, info, strokeWidth)))); |
| } |
| DashingLineEffect::~DashingLineEffect() {} |
| @@ -442,9 +571,8 @@ const GrBackendEffectFactory& DashingLineEffect::getFactory() const { |
| } |
| DashingLineEffect::DashingLineEffect(GrEffectEdgeType edgeType, const DashInfo& info, |
| - const SkMatrix& matrix, SkScalar strokeWidth) |
| - : fEdgeType(edgeType) |
| - , fCoordTransform(kLocal_GrCoordSet, matrix) { |
| + SkScalar strokeWidth) |
| + : fEdgeType(edgeType) { |
| SkScalar onLen = info.fIntervals[0]; |
| SkScalar offLen = info.fIntervals[1]; |
| SkScalar halfOffLen = SkScalarHalf(offLen); |
| @@ -452,13 +580,12 @@ DashingLineEffect::DashingLineEffect(GrEffectEdgeType edgeType, const DashInfo& |
| fIntervalLength = onLen + offLen; |
| fRect.set(halfOffLen, -halfStroke, halfOffLen + onLen, halfStroke); |
| - addCoordTransform(&fCoordTransform); |
| + this->addVertexAttrib(kVec2f_GrSLType); |
| } |
| bool DashingLineEffect::onIsEqual(const GrEffect& other) const { |
| const DashingLineEffect& de = CastEffect<DashingLineEffect>(other); |
| return (fEdgeType == de.fEdgeType && |
| - fCoordTransform == de.fCoordTransform && |
| fRect == de.fRect && |
| fIntervalLength == de.fIntervalLength); |
| } |
| @@ -470,8 +597,6 @@ GrEffectRef* DashingLineEffect::TestCreate(SkRandom* random, |
| const GrDrawTargetCaps& caps, |
| GrTexture*[]) { |
| GrEffectRef* effect; |
| - SkMatrix m; |
| - m.reset(); |
| GrEffectEdgeType edgeType = static_cast<GrEffectEdgeType>(random->nextULessThan( |
| kGrEffectEdgeTypeCnt)); |
| SkScalar strokeWidth = random->nextRangeScalar(0, 100.f); |
| @@ -483,13 +608,13 @@ GrEffectRef* DashingLineEffect::TestCreate(SkRandom* random, |
| info.fIntervals[1] = random->nextRangeScalar(0, 10.f); |
| info.fPhase = random->nextRangeScalar(0, info.fIntervals[0] + info.fIntervals[1]); |
| - effect = DashingLineEffect::Create(edgeType, info, m, strokeWidth); |
| + effect = DashingLineEffect::Create(edgeType, info, strokeWidth); |
| return effect; |
| } |
| ////////////////////////////////////////////////////////////////////////////// |
| GrEffectRef* GrDashingEffect::Create(GrEffectEdgeType edgeType, const SkPathEffect::DashInfo& info, |
| - const SkMatrix& matrix, SkScalar strokeWidth) { |
| - return DashingLineEffect::Create(edgeType, info, matrix, strokeWidth); |
| + SkScalar strokeWidth) { |
| + return DashingLineEffect::Create(edgeType, info, strokeWidth); |
| } |