AADistanceFieldPathRenderer unit tests

TBR=bsalomon@google.com
BUG=skia:

Review URL: https://codereview.chromium.org/1129083005
This commit is contained in:
joshualitt 2015-05-11 07:21:37 -07:00 committed by Commit bot
parent 624637cc8e
commit 21279c7ada
5 changed files with 120 additions and 31 deletions

View File

@ -14,6 +14,7 @@
#include "GrColor.h"
#include "SkRandom.h"
#include "SkStrokeRec.h"
class SkMatrix;
class SkPath;
@ -31,6 +32,7 @@ const SkMatrix& TestMatrixInvertible(SkRandom*);
const SkRect& TestRect(SkRandom*);
const SkRRect& TestRRectSimple(SkRandom*);
const SkPath& TestPath(SkRandom*);
SkStrokeRec TestStrokeRec(SkRandom*);
}

View File

@ -10,6 +10,7 @@
#include "GrBatch.h"
#include "GrBatchTarget.h"
#include "GrBatchTest.h"
#include "GrContext.h"
#include "GrPipelineBuilder.h"
#include "GrResourceProvider.h"
@ -553,6 +554,28 @@ private:
PathDataList* fPathList;
};
static GrBatchAtlas* create_atlas(GrContext* context, GrBatchAtlas::EvictionFunc func, void* data) {
GrBatchAtlas* atlas;
// Create a new atlas
GrSurfaceDesc desc;
desc.fFlags = kNone_GrSurfaceFlags;
desc.fWidth = ATLAS_TEXTURE_WIDTH;
desc.fHeight = ATLAS_TEXTURE_HEIGHT;
desc.fConfig = kAlpha_8_GrPixelConfig;
// We don't want to flush the context so we claim we're in the middle of flushing so as to
// guarantee we do not recieve a texture with pending IO
GrTexture* texture = context->textureProvider()->refScratchTexture(
desc, GrTextureProvider::kApprox_ScratchTexMatch, true);
if (texture) {
atlas = SkNEW_ARGS(GrBatchAtlas, (texture, NUM_PLOTS_X, NUM_PLOTS_Y));
} else {
return NULL;
}
atlas->registerEvictionCallback(func, data);
return atlas;
}
bool GrAADistanceFieldPathRenderer::onDrawPath(GrDrawTarget* target,
GrPipelineBuilder* pipelineBuilder,
GrColor color,
@ -568,24 +591,11 @@ bool GrAADistanceFieldPathRenderer::onDrawPath(GrDrawTarget* target,
SkASSERT(fContext);
if (!fAtlas) {
// Create a new atlas
GrSurfaceDesc desc;
desc.fFlags = kNone_GrSurfaceFlags;
desc.fWidth = ATLAS_TEXTURE_WIDTH;
desc.fHeight = ATLAS_TEXTURE_HEIGHT;
desc.fConfig = kAlpha_8_GrPixelConfig;
// We don't want to flush the context so we claim we're in the middle of flushing so as to
// guarantee we do not recieve a texture with pending IO
GrTexture* texture = fContext->textureProvider()->refScratchTexture(
desc, GrTextureProvider::kApprox_ScratchTexMatch, true);
if (texture) {
fAtlas = SkNEW_ARGS(GrBatchAtlas, (texture, NUM_PLOTS_X, NUM_PLOTS_Y));
} else {
fAtlas = create_atlas(fContext, &GrAADistanceFieldPathRenderer::HandleEviction,
(void*)this);
if (!fAtlas) {
return false;
}
fAtlas->registerEvictionCallback(&GrAADistanceFieldPathRenderer::HandleEviction,
(void*)this);
}
AADistanceFieldPathBatch::Geometry geometry(stroke.getStrokeRec());
@ -599,3 +609,72 @@ bool GrAADistanceFieldPathRenderer::onDrawPath(GrDrawTarget* target,
return true;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef GR_TEST_UTILS
struct PathTestStruct {
typedef GrAADistanceFieldPathRenderer::PathCache PathCache;
typedef GrAADistanceFieldPathRenderer::PathData PathData;
typedef GrAADistanceFieldPathRenderer::PathDataList PathDataList;
PathTestStruct() : fContextID(SK_InvalidGenID), fAtlas(NULL) {}
~PathTestStruct() { this->reset(); }
void reset() {
PathDataList::Iter iter;
iter.init(fPathList, PathDataList::Iter::kHead_IterStart);
PathData* pathData;
while ((pathData = iter.get())) {
iter.next();
fPathList.remove(pathData);
SkDELETE(pathData);
}
SkDELETE(fAtlas);
}
static void HandleEviction(GrBatchAtlas::AtlasID id, void* pr) {
PathTestStruct* dfpr = (PathTestStruct*)pr;
// remove any paths that use this plot
PathDataList::Iter iter;
iter.init(dfpr->fPathList, PathDataList::Iter::kHead_IterStart);
PathData* pathData;
while ((pathData = iter.get())) {
iter.next();
if (id == pathData->fID) {
dfpr->fPathCache.remove(pathData->fKey);
dfpr->fPathList.remove(pathData);
SkDELETE(pathData);
}
}
}
uint32_t fContextID;
GrBatchAtlas* fAtlas;
PathCache fPathCache;
PathDataList fPathList;
};
BATCH_TEST_DEFINE(AADistanceFieldPathRenderer) {
static PathTestStruct gTestStruct;
if (context->uniqueID() != gTestStruct.fContextID) {
gTestStruct.fContextID = context->uniqueID();
gTestStruct.reset();
gTestStruct.fAtlas = create_atlas(context, &PathTestStruct::HandleEviction,
(void*)&gTestStruct);
}
SkMatrix viewMatrix = GrTest::TestMatrix(random);
GrColor color = GrRandomColor(random);
AADistanceFieldPathBatch::Geometry geometry(GrTest::TestStrokeRec(random));
geometry.fPath = GrTest::TestPath(random);
geometry.fAntiAlias = random->nextBool();
return AADistanceFieldPathBatch::Create(geometry, color, viewMatrix,
gTestStruct.fAtlas,
&gTestStruct.fPathCache,
&gTestStruct.fPathList);
}
#endif

View File

@ -72,16 +72,18 @@ private:
static void HandleEviction(GrBatchAtlas::AtlasID, void*);
typedef SkTDynamicHash<PathData, PathData::Key> PathCache;
typedef SkTInternalLList<PathData> PathDataList;
GrContext* fContext;
GrBatchAtlas* fAtlas;
SkTDynamicHash<PathData, PathData::Key> fPathCache;
PathCache fPathCache;
PathDataList fPathList;
typedef GrPathRenderer INHERITED;
friend class AADistanceFieldPathBatch;
friend struct PathTestStruct;
};
#endif

View File

@ -2090,22 +2090,13 @@ bool GrOvalRenderer::drawRRect(GrDrawTarget* target,
#ifdef GR_TEST_UTILS
static SkStrokeRec random_strokerec(SkRandom* random) {
SkStrokeRec::InitStyle style =
SkStrokeRec::InitStyle(random->nextULessThan(SkStrokeRec::kFill_InitStyle + 1));
SkStrokeRec rec(style);
bool strokeAndFill = random->nextBool();
SkScalar strokeWidth = random->nextBool() ? 0.f : 1.f;
rec.setStrokeStyle(strokeWidth, strokeAndFill);
return rec;
}
BATCH_TEST_DEFINE(CircleBatch) {
SkMatrix viewMatrix = GrTest::TestMatrix(random);
GrColor color = GrRandomColor(random);
bool useCoverageAA = random->nextBool();
SkRect circle = GrTest::TestRect(random);
return create_circle_batch(color, viewMatrix, useCoverageAA, circle, random_strokerec(random));
return create_circle_batch(color, viewMatrix, useCoverageAA, circle,
GrTest::TestStrokeRec(random));
}
BATCH_TEST_DEFINE(EllipseBatch) {
@ -2114,7 +2105,7 @@ BATCH_TEST_DEFINE(EllipseBatch) {
bool useCoverageAA = random->nextBool();
SkRect ellipse = GrTest::TestRect(random);
return create_ellipse_batch(color, viewMatrix, useCoverageAA, ellipse,
random_strokerec(random));
GrTest::TestStrokeRec(random));
}
BATCH_TEST_DEFINE(DIEllipseBatch) {
@ -2123,14 +2114,14 @@ BATCH_TEST_DEFINE(DIEllipseBatch) {
bool useCoverageAA = random->nextBool();
SkRect ellipse = GrTest::TestRect(random);
return create_diellipse_batch(color, viewMatrix, useCoverageAA, ellipse,
random_strokerec(random));
GrTest::TestStrokeRec(random));
}
BATCH_TEST_DEFINE(RRectBatch) {
SkMatrix viewMatrix = GrTest::TestMatrixRectStaysRect(random);
GrColor color = GrRandomColor(random);
const SkRRect& rrect = GrTest::TestRRectSimple(random);
return create_rrect_batch(color, viewMatrix, rrect, random_strokerec(random));
return create_rrect_batch(color, viewMatrix, rrect, GrTest::TestStrokeRec(random));
}
#endif

View File

@ -175,6 +175,21 @@ const SkPath& TestPath(SkRandom* random) {
return gPath[random->nextULessThan(static_cast<uint32_t>(SK_ARRAY_COUNT(gPath)))];
}
SkStrokeRec TestStrokeRec(SkRandom* random) {
SkStrokeRec::InitStyle style =
SkStrokeRec::InitStyle(random->nextULessThan(SkStrokeRec::kFill_InitStyle + 1));
SkStrokeRec rec(style);
bool strokeAndFill = random->nextBool();
SkScalar strokeWidth = random->nextBool() ? 0.f : 1.f;
rec.setStrokeStyle(strokeWidth, strokeAndFill);
SkPaint::Cap cap = SkPaint::Cap(random->nextULessThan(SkPaint::kCapCount));
SkPaint::Join join = SkPaint::Join(random->nextULessThan(SkPaint::kJoinCount));
SkScalar miterLimit = random->nextRangeScalar(1.f, 5.f);
rec.setStrokeParams(cap, join, miterLimit);
return rec;
}
};
#endif