aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu
diff options
context:
space:
mode:
authorGravatar joshualitt <joshualitt@chromium.org>2015-04-29 11:32:05 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-04-29 11:32:06 -0700
commitfa2008ff6ee5963fc2566b20c1af39367b77bdf7 (patch)
treed56fb9c34aeb92fe8d62fe3acbbeeea07bc29742 /src/gpu
parente9c0fc616d2a1632c285885b9b656b68ca8d4f24 (diff)
Add dash lines batch unit test
Diffstat (limited to 'src/gpu')
-rw-r--r--src/gpu/GrStrokeInfo.h19
-rw-r--r--src/gpu/GrTestUtils.cpp26
-rw-r--r--src/gpu/effects/GrDashingEffect.cpp113
3 files changed, 146 insertions, 12 deletions
diff --git a/src/gpu/GrStrokeInfo.h b/src/gpu/GrStrokeInfo.h
index dd942c52e9..f008dc6a5d 100644
--- a/src/gpu/GrStrokeInfo.h
+++ b/src/gpu/GrStrokeInfo.h
@@ -38,7 +38,6 @@ public:
this->init(paint);
}
-
explicit GrStrokeInfo(const SkPaint& paint) :
fStroke(paint), fDashType(SkPathEffect::kNone_DashType) {
this->init(paint);
@@ -78,6 +77,24 @@ public:
return false;
}
+ /*
+ * Like the above, but sets with an explicit SkPathEffect::DashInfo
+ */
+ bool setDashInfo(const SkPathEffect::DashInfo& info) {
+ if (!fStroke.isFillStyle()) {
+ SkASSERT(!fStroke.isFillStyle());
+ fDashInfo.fCount = info.fCount;
+ fDashInfo.fPhase = info.fPhase;
+ fIntervals.reset(info.fCount);
+ for (int i = 0; i < info.fCount; i++) {
+ fIntervals[i] = info.fIntervals[i];
+ }
+ fDashInfo.fIntervals = fIntervals.get();
+ return true;
+ }
+ return false;
+ }
+
bool isDashed() const {
return (!fStroke.isFillStyle() && SkPathEffect::kDash_DashType == fDashType);
}
diff --git a/src/gpu/GrTestUtils.cpp b/src/gpu/GrTestUtils.cpp
index afd9fd80b6..d0cea5565c 100644
--- a/src/gpu/GrTestUtils.cpp
+++ b/src/gpu/GrTestUtils.cpp
@@ -29,6 +29,32 @@ const SkMatrix& TestMatrix(SkRandom* random) {
return gMatrices[random->nextULessThan(static_cast<uint32_t>(SK_ARRAY_COUNT(gMatrices)))];
}
+const SkMatrix& TestMatrixPreservesRightAngles(SkRandom* random) {
+ static SkMatrix gMatrices[4];
+ static bool gOnce;
+ if (!gOnce) {
+ // identity
+ gMatrices[0].reset();
+ // translation
+ gMatrices[1].setTranslate(SkIntToScalar(-100), SkIntToScalar(100));
+ // scale
+ gMatrices[2].setScale(SkIntToScalar(17), SkIntToScalar(17));
+ // scale + translation
+ gMatrices[3].setScale(SkIntToScalar(-17), SkIntToScalar(-17));
+ gMatrices[3].postTranslate(SkIntToScalar(66), SkIntToScalar(-33));
+ // orthogonal basis vectors
+ gMatrices[4].reset();
+ gMatrices[4].setScale(SkIntToScalar(-1), SkIntToScalar(-1));
+ gMatrices[4].setRotate(47);
+ gOnce = true;
+
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gMatrices); i++) {
+ SkASSERT(gMatrices[i].preservesRightAngles());
+ }
+ }
+ return gMatrices[random->nextULessThan(static_cast<uint32_t>(SK_ARRAY_COUNT(gMatrices)))];
+}
+
const SkRect& TestRect(SkRandom* random) {
static SkRect gRects[1];
static bool gOnce;
diff --git a/src/gpu/effects/GrDashingEffect.cpp b/src/gpu/effects/GrDashingEffect.cpp
index b729d0a698..40d52f3096 100644
--- a/src/gpu/effects/GrDashingEffect.cpp
+++ b/src/gpu/effects/GrDashingEffect.cpp
@@ -9,6 +9,7 @@
#include "GrBatch.h"
#include "GrBatchTarget.h"
+#include "GrBatchTest.h"
#include "GrBufferAllocPool.h"
#include "GrGeometryProcessor.h"
#include "GrContext.h"
@@ -258,7 +259,8 @@ public:
SkDEBUGCODE(SkRect fDevBounds;)
};
- static GrBatch* Create(const Geometry& geometry, SkPaint::Cap cap, DashAAMode aaMode, bool fullDash) {
+ static GrBatch* Create(const Geometry& geometry, SkPaint::Cap cap, DashAAMode aaMode,
+ bool fullDash) {
return SkNEW_ARGS(DashBatch, (geometry, cap, aaMode, fullDash));
}
@@ -699,11 +701,8 @@ private:
SkSTArray<1, Geometry, true> fGeoData;
};
-
-bool GrDashingEffect::DrawDashLine(GrGpu* gpu, GrDrawTarget* target,
- GrPipelineBuilder* pipelineBuilder, GrColor color,
- const SkMatrix& viewMatrix, const SkPoint pts[2],
- bool useAA, const GrStrokeInfo& strokeInfo) {
+static GrBatch* create_batch(GrColor color, const SkMatrix& viewMatrix, const SkPoint pts[2],
+ bool useAA, const GrStrokeInfo& strokeInfo, bool msaaRT) {
const SkPathEffect::DashInfo& info = strokeInfo.getDashInfo();
SkPaint::Cap cap = strokeInfo.getStrokeRec().getCap();
@@ -720,7 +719,7 @@ bool GrDashingEffect::DrawDashLine(GrGpu* gpu, GrDrawTarget* target,
align_to_x_axis(pts, &rotMatrix, geometry.fPtsRot);
if(!rotMatrix.invert(&geometry.fSrcRotInv)) {
SkDebugf("Failed to create invertible rotation matrix!\n");
- return false;
+ return NULL;
}
} else {
geometry.fSrcRotInv.reset();
@@ -739,8 +738,8 @@ bool GrDashingEffect::DrawDashLine(GrGpu* gpu, GrDrawTarget* target,
offInterval -= strokeWidth;
}
- DashAAMode aaMode = pipelineBuilder->getRenderTarget()->isMultisampled() ? kMSAA_DashAAMode :
- useAA ? kEdgeAA_DashAAMode : kBW_DashAAMode;
+ DashAAMode aaMode = msaaRT ? kMSAA_DashAAMode :
+ useAA ? kEdgeAA_DashAAMode : kBW_DashAAMode;
// TODO we can do a real rect call if not using fulldash(ie no off interval, not using AA)
bool fullDash = offInterval > 0.f || aaMode != kBW_DashAAMode;
@@ -751,9 +750,20 @@ bool GrDashingEffect::DrawDashLine(GrGpu* gpu, GrDrawTarget* target,
geometry.fIntervals[0] = info.fIntervals[0];
geometry.fIntervals[1] = info.fIntervals[1];
- SkAutoTUnref<GrBatch> batch(DashBatch::Create(geometry, cap, aaMode, fullDash));
- target->drawBatch(pipelineBuilder, batch);
+ return DashBatch::Create(geometry, cap, aaMode, fullDash);
+}
+
+bool GrDashingEffect::DrawDashLine(GrGpu* gpu, GrDrawTarget* target,
+ GrPipelineBuilder* pipelineBuilder, GrColor color,
+ const SkMatrix& viewMatrix, const SkPoint pts[2],
+ bool useAA, const GrStrokeInfo& strokeInfo) {
+ SkAutoTUnref<GrBatch> batch(create_batch(color, viewMatrix, pts, useAA, strokeInfo,
+ pipelineBuilder->getRenderTarget()->isMultisampled()));
+ if (!batch) {
+ return false;
+ }
+ target->drawBatch(pipelineBuilder, batch);
return true;
}
@@ -1280,3 +1290,84 @@ static GrGeometryProcessor* create_dash_gp(GrColor color,
}
return NULL;
}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef GR_TEST_UTILS
+
+BATCH_TEST_DEFINE(DashBatch) {
+ GrColor color = GrRandomColor(random);
+ SkMatrix viewMatrix = GrTest::TestMatrixPreservesRightAngles(random);
+ bool useAA = random->nextBool();
+ bool msaaRT = random->nextBool();
+
+ // We can only dash either horizontal or vertical lines
+ SkPoint pts[2];
+ if (random->nextBool()) {
+ // vertical
+ pts[0].fX = 1.f;
+ pts[0].fY = random->nextF() * 10.f;
+ pts[1].fX = 1.f;
+ pts[1].fY = random->nextF() * 10.f;
+ } else {
+ // horizontal
+ pts[0].fX = random->nextF() * 10.f;
+ pts[0].fY = 1.f;
+ pts[1].fX = random->nextF() * 10.f;
+ pts[1].fY = 1.f;
+ }
+
+ // pick random cap
+ SkPaint::Cap cap = SkPaint::Cap(random->nextULessThan(SkPaint::Cap::kCapCount));
+
+ SkScalar intervals[2];
+
+ // We can only dash with the following intervals
+ enum Intervals {
+ kOpenOpen_Intervals ,
+ kOpenClose_Intervals,
+ kCloseOpen_Intervals,
+ };
+
+ Intervals intervalType = SkPaint::kRound_Cap ?
+ kOpenClose_Intervals :
+ Intervals(random->nextULessThan(kCloseOpen_Intervals + 1));
+ static const SkScalar kIntervalMin = 0.1f;
+ static const SkScalar kIntervalMax = 10.f;
+ switch (intervalType) {
+ case kOpenOpen_Intervals:
+ intervals[0] = random->nextRangeScalar(kIntervalMin, kIntervalMax);
+ intervals[1] = random->nextRangeScalar(kIntervalMin, kIntervalMax);
+ break;
+ case kOpenClose_Intervals:
+ intervals[0] = 0.f;
+ intervals[1] = random->nextRangeScalar(kIntervalMin, kIntervalMax);
+ break;
+ case kCloseOpen_Intervals:
+ intervals[0] = random->nextRangeScalar(kIntervalMin, kIntervalMax);
+ intervals[1] = 0.f;
+ break;
+
+ }
+
+ // phase is 0 < sum (i0, i1)
+ SkScalar phase = random->nextRangeScalar(0, intervals[0] + intervals[1]);
+
+ SkPaint p;
+ p.setStyle(SkPaint::kStroke_Style);
+ p.setStrokeWidth(SkIntToScalar(1));
+ p.setStrokeCap(cap);
+
+ GrStrokeInfo strokeInfo(p);
+
+ SkPathEffect::DashInfo info;
+ info.fIntervals = intervals;
+ info.fCount = 2;
+ info.fPhase = phase;
+ SkDEBUGCODE(bool success = ) strokeInfo.setDashInfo(info);
+ SkASSERT(success);
+
+ return create_batch(color, viewMatrix, pts, useAA, strokeInfo, msaaRT);
+}
+
+#endif