aboutsummaryrefslogtreecommitdiffhomepage
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/GrShapeTest.cpp11
-rw-r--r--tests/PathRendererCacheTests.cpp113
2 files changed, 124 insertions, 0 deletions
diff --git a/tests/GrShapeTest.cpp b/tests/GrShapeTest.cpp
index 087ac525c8..2b2a169477 100644
--- a/tests/GrShapeTest.cpp
+++ b/tests/GrShapeTest.cpp
@@ -17,6 +17,10 @@
#include "SkSurface.h"
#include "SkClipOpPriv.h"
+uint32_t GrShape::testingOnly_getOriginalGenerationID() const {
+ return fOriginalPath.getGenerationID();
+}
+
using Key = SkTArray<uint32_t>;
static bool make_key(Key* key, const GrShape& shape) {
@@ -493,6 +497,13 @@ private:
make_key(&fAppliedPEThenStrokeKey, fAppliedPEThenStroke);
make_key(&fAppliedFullKey, fAppliedFull);
+ // All shapes should report the same "original" path, so that path renderers can get to it
+ // if necessary.
+ uint32_t baseGenID = fBase.testingOnly_getOriginalGenerationID();
+ REPORTER_ASSERT(r, baseGenID == fAppliedPE.testingOnly_getOriginalGenerationID());
+ REPORTER_ASSERT(r, baseGenID == fAppliedPEThenStroke.testingOnly_getOriginalGenerationID());
+ REPORTER_ASSERT(r, baseGenID == fAppliedFull.testingOnly_getOriginalGenerationID());
+
// Applying the path effect and then the stroke should always be the same as applying
// both in one go.
REPORTER_ASSERT(r, fAppliedPEThenStrokeKey == fAppliedFullKey);
diff --git a/tests/PathRendererCacheTests.cpp b/tests/PathRendererCacheTests.cpp
new file mode 100644
index 0000000000..da58fa4d7d
--- /dev/null
+++ b/tests/PathRendererCacheTests.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Test.h"
+
+#include "SkPath.h"
+
+#if SK_SUPPORT_GPU
+#include "GrClip.h"
+#include "GrContext.h"
+#include "GrContextPriv.h"
+#include "GrResourceCache.h"
+#include "effects/GrPorterDuffXferProcessor.h"
+#include "ops/GrTessellatingPathRenderer.h"
+
+static SkPath create_concave_path() {
+ SkPath path;
+ path.moveTo(100, 0);
+ path.lineTo(200, 200);
+ path.lineTo(100, 150);
+ path.lineTo(0, 200);
+ path.close();
+ return path;
+}
+
+static void draw_path(GrContext* ctx,
+ GrRenderTargetContext* renderTargetContext,
+ const SkPath& path,
+ GrPathRenderer* pr,
+ GrAAType aaType = GrAAType::kNone,
+ GrStyle style = GrStyle(SkStrokeRec::kFill_InitStyle)) {
+ GrPaint paint;
+ paint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
+
+ GrNoClip noClip;
+ SkIRect clipConservativeBounds = SkIRect::MakeWH(renderTargetContext->width(),
+ renderTargetContext->height());
+ GrShape shape(path, style);
+ if (shape.style().applies()) {
+ shape = shape.applyStyle(GrStyle::Apply::kPathEffectAndStrokeRec, 1.0f);
+ }
+ SkMatrix matrix = SkMatrix::I();
+ GrPathRenderer::DrawPathArgs args{ctx,
+ std::move(paint),
+ &GrUserStencilSettings::kUnused,
+ renderTargetContext,
+ &noClip,
+ &clipConservativeBounds,
+ &matrix,
+ &shape,
+ aaType,
+ false};
+ pr->drawPath(args);
+}
+
+static void test_path(skiatest::Reporter* reporter,
+ std::function<SkPath(void)> createPath,
+ GrPathRenderer* pathRenderer,
+ int expectedResources = 1,
+ GrAAType aaType = GrAAType::kNone,
+ GrStyle style = GrStyle(SkStrokeRec::kFill_InitStyle)) {
+ sk_sp<GrContext> ctx = GrContext::MakeMock(nullptr);
+ ctx->setResourceCacheLimits(100, 10000);
+ GrResourceCache* cache = ctx->getResourceCache();
+
+ sk_sp<GrRenderTargetContext> rtc(ctx->makeDeferredRenderTargetContext(
+ SkBackingFit::kApprox, 800, 800, kRGBA_8888_GrPixelConfig, nullptr, 0,
+ kTopLeft_GrSurfaceOrigin));
+ if (!rtc) {
+ return;
+ }
+
+ SkPath path = createPath();
+
+ // Initially, cache only has the render target context
+ REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
+
+ // Draw the path, check that new resource count matches expectations
+ draw_path(ctx.get(), rtc.get(), path, pathRenderer);
+ ctx->flush();
+ REPORTER_ASSERT(reporter, (1 + expectedResources) == cache->getResourceCount());
+
+ // Nothing should be purgeable yet
+ cache->purgeAsNeeded();
+ REPORTER_ASSERT(reporter, (1 + expectedResources) == cache->getResourceCount());
+
+ // Reset the path to change the GenID, which should invalidate any resources in the cache
+ path.reset();
+ cache->purgeAsNeeded();
+ REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
+}
+
+// Test that deleting the original path invalidates the VBs cached by the tessellating path renderer
+DEF_GPUTEST(TessellatingPathRendererCacheTest, reporter, factory) {
+ GrTessellatingPathRenderer tess;
+
+ // Tessellating path renderer stores vertex buffers in the cache (for non-AA paths)
+ test_path(reporter, create_concave_path, &tess);
+
+ // Test with a shape that applies. This needs to attach the invalidation logic to the original
+ // path, not the modified path produced by the style.
+ SkPaint paint;
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(1);
+ GrStyle style(paint);
+ test_path(reporter, create_concave_path, &tess, 1, GrAAType::kNone, style);
+}
+
+#endif