aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/gpu/GrSoftwarePathRenderer.cpp13
-rw-r--r--tests/PathRendererCacheTests.cpp61
2 files changed, 59 insertions, 15 deletions
diff --git a/src/gpu/GrSoftwarePathRenderer.cpp b/src/gpu/GrSoftwarePathRenderer.cpp
index 8b509082c8..9f876f1213 100644
--- a/src/gpu/GrSoftwarePathRenderer.cpp
+++ b/src/gpu/GrSoftwarePathRenderer.cpp
@@ -200,6 +200,18 @@ private:
GrAA fAA;
};
+// When the SkPathRef genID changes, invalidate a corresponding GrResource described by key.
+class PathInvalidator : public SkPathRef::GenIDChangeListener {
+public:
+ explicit PathInvalidator(const GrUniqueKey& key) : fMsg(key) {}
+private:
+ GrUniqueKeyInvalidatedMessage fMsg;
+
+ void onChange() override {
+ SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(fMsg);
+ }
+};
+
}
////////////////////////////////////////////////////////////////////////////////
@@ -344,6 +356,7 @@ bool GrSoftwarePathRenderer::onDrawPath(const DrawPathArgs& args) {
if (useCache) {
SkASSERT(proxy->origin() == kTopLeft_GrSurfaceOrigin);
fResourceProvider->assignUniqueKeyToProxy(maskKey, proxy.get());
+ args.fShape->addGenIDChangeListener(new PathInvalidator(maskKey));
}
}
if (inverseFilled) {
diff --git a/tests/PathRendererCacheTests.cpp b/tests/PathRendererCacheTests.cpp
index da58fa4d7d..d21289055b 100644
--- a/tests/PathRendererCacheTests.cpp
+++ b/tests/PathRendererCacheTests.cpp
@@ -14,6 +14,7 @@
#include "GrContext.h"
#include "GrContextPriv.h"
#include "GrResourceCache.h"
+#include "GrSoftwarePathRenderer.h"
#include "effects/GrPorterDuffXferProcessor.h"
#include "ops/GrTessellatingPathRenderer.h"
@@ -31,8 +32,8 @@ static void draw_path(GrContext* ctx,
GrRenderTargetContext* renderTargetContext,
const SkPath& path,
GrPathRenderer* pr,
- GrAAType aaType = GrAAType::kNone,
- GrStyle style = GrStyle(SkStrokeRec::kFill_InitStyle)) {
+ GrAAType aaType,
+ const GrStyle& style) {
GrPaint paint;
paint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
@@ -57,14 +58,23 @@ static void draw_path(GrContext* ctx,
pr->drawPath(args);
}
+static bool cache_non_scratch_resources_equals(GrResourceCache* cache, int expected) {
+#if GR_CACHE_STATS
+ GrResourceCache::Stats stats;
+ cache->getStats(&stats);
+ return (stats.fTotal - stats.fScratch) == expected;
+#else
+ return true;
+#endif
+}
+
static void test_path(skiatest::Reporter* reporter,
std::function<SkPath(void)> createPath,
- GrPathRenderer* pathRenderer,
- int expectedResources = 1,
+ std::function<GrPathRenderer*(GrContext*)> createPathRenderer,
GrAAType aaType = GrAAType::kNone,
GrStyle style = GrStyle(SkStrokeRec::kFill_InitStyle)) {
sk_sp<GrContext> ctx = GrContext::MakeMock(nullptr);
- ctx->setResourceCacheLimits(100, 10000);
+ ctx->setResourceCacheLimits(100, 100000);
GrResourceCache* cache = ctx->getResourceCache();
sk_sp<GrRenderTargetContext> rtc(ctx->makeDeferredRenderTargetContext(
@@ -74,40 +84,61 @@ static void test_path(skiatest::Reporter* reporter,
return;
}
+ sk_sp<GrPathRenderer> pathRenderer(createPathRenderer(ctx.get()));
SkPath path = createPath();
// Initially, cache only has the render target context
- REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
+ REPORTER_ASSERT(reporter, cache_non_scratch_resources_equals(cache, 0));
// Draw the path, check that new resource count matches expectations
- draw_path(ctx.get(), rtc.get(), path, pathRenderer);
+ draw_path(ctx.get(), rtc.get(), path, pathRenderer.get(), aaType, style);
ctx->flush();
- REPORTER_ASSERT(reporter, (1 + expectedResources) == cache->getResourceCount());
+ REPORTER_ASSERT(reporter, cache_non_scratch_resources_equals(cache, 1));
// Nothing should be purgeable yet
cache->purgeAsNeeded();
- REPORTER_ASSERT(reporter, (1 + expectedResources) == cache->getResourceCount());
+ REPORTER_ASSERT(reporter, cache_non_scratch_resources_equals(cache, 1));
// 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());
+ REPORTER_ASSERT(reporter, cache_non_scratch_resources_equals(cache, 0));
}
// Test that deleting the original path invalidates the VBs cached by the tessellating path renderer
DEF_GPUTEST(TessellatingPathRendererCacheTest, reporter, factory) {
- GrTessellatingPathRenderer tess;
+ auto createPR = [](GrContext*) {
+ return new GrTessellatingPathRenderer();
+ };
+
+ // Tessellating path renderer stores vertex buffers in the cache (for non-AA paths)
+ test_path(reporter, create_concave_path, createPR);
+
+ // Test with a style that alters the path geometry. 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, createPR, GrAAType::kNone, style);
+}
+
+// Test that deleting the original path invalidates the textures cached by the SW path renderer
+DEF_GPUTEST(SoftwarePathRendererCacheTest, reporter, factory) {
+ auto createPR = [](GrContext* ctx) {
+ return new GrSoftwarePathRenderer(ctx->resourceProvider(), true);
+ };
// Tessellating path renderer stores vertex buffers in the cache (for non-AA paths)
- test_path(reporter, create_concave_path, &tess);
+ test_path(reporter, create_concave_path, createPR, GrAAType::kCoverage);
- // 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.
+ // Test with a style that alters the path geometry. 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);
+ test_path(reporter, create_concave_path, createPR, GrAAType::kCoverage, style);
}
#endif