diff options
author | Brian Osman <brianosman@google.com> | 2017-09-26 14:05:19 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-09-26 19:07:46 +0000 |
commit | e9242ca695a390445690cb32f67eedef85f54099 (patch) | |
tree | 6d828ae00ec453214755f581ae751e35809d8586 | |
parent | 832b222efbc3f42cf74633a19c5a4a74bc929719 (diff) |
Invalidate textures cached by SW path renderer when paths go away
Bug: skia:
Change-Id: Icfc2f1bd57c0cf7be54469b6d86cbd436b59155d
Reviewed-on: https://skia-review.googlesource.com/51201
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
-rw-r--r-- | src/gpu/GrSoftwarePathRenderer.cpp | 13 | ||||
-rw-r--r-- | tests/PathRendererCacheTests.cpp | 61 |
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 |