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>
This commit is contained in:
parent
832b222efb
commit
e9242ca695
@ -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) {
|
||||
|
@ -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, &tess);
|
||||
test_path(reporter, create_concave_path, createPR);
|
||||
|
||||
// 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::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, createPR, GrAAType::kCoverage);
|
||||
|
||||
// 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::kCoverage, style);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user