Add dash lines batch unit test

BUG=skia:

Review URL: https://codereview.chromium.org/1108053004
This commit is contained in:
joshualitt 2015-04-29 11:32:05 -07:00 committed by Commit bot
parent e9c0fc616d
commit fa2008ff6e
4 changed files with 147 additions and 12 deletions

View File

@ -23,6 +23,7 @@ namespace GrTest {
* A helper for use in Test functions.
*/
const SkMatrix& TestMatrix(SkRandom*);
const SkMatrix& TestMatrixPreservesRightAngles(SkRandom*);
const SkRect& TestRect(SkRandom*);
}

View File

@ -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);
}

View File

@ -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;

View File

@ -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