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;
|
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) {
|
if (useCache) {
|
||||||
SkASSERT(proxy->origin() == kTopLeft_GrSurfaceOrigin);
|
SkASSERT(proxy->origin() == kTopLeft_GrSurfaceOrigin);
|
||||||
fResourceProvider->assignUniqueKeyToProxy(maskKey, proxy.get());
|
fResourceProvider->assignUniqueKeyToProxy(maskKey, proxy.get());
|
||||||
|
args.fShape->addGenIDChangeListener(new PathInvalidator(maskKey));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (inverseFilled) {
|
if (inverseFilled) {
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "GrContext.h"
|
#include "GrContext.h"
|
||||||
#include "GrContextPriv.h"
|
#include "GrContextPriv.h"
|
||||||
#include "GrResourceCache.h"
|
#include "GrResourceCache.h"
|
||||||
|
#include "GrSoftwarePathRenderer.h"
|
||||||
#include "effects/GrPorterDuffXferProcessor.h"
|
#include "effects/GrPorterDuffXferProcessor.h"
|
||||||
#include "ops/GrTessellatingPathRenderer.h"
|
#include "ops/GrTessellatingPathRenderer.h"
|
||||||
|
|
||||||
@ -31,8 +32,8 @@ static void draw_path(GrContext* ctx,
|
|||||||
GrRenderTargetContext* renderTargetContext,
|
GrRenderTargetContext* renderTargetContext,
|
||||||
const SkPath& path,
|
const SkPath& path,
|
||||||
GrPathRenderer* pr,
|
GrPathRenderer* pr,
|
||||||
GrAAType aaType = GrAAType::kNone,
|
GrAAType aaType,
|
||||||
GrStyle style = GrStyle(SkStrokeRec::kFill_InitStyle)) {
|
const GrStyle& style) {
|
||||||
GrPaint paint;
|
GrPaint paint;
|
||||||
paint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
|
paint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
|
||||||
|
|
||||||
@ -57,14 +58,23 @@ static void draw_path(GrContext* ctx,
|
|||||||
pr->drawPath(args);
|
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,
|
static void test_path(skiatest::Reporter* reporter,
|
||||||
std::function<SkPath(void)> createPath,
|
std::function<SkPath(void)> createPath,
|
||||||
GrPathRenderer* pathRenderer,
|
std::function<GrPathRenderer*(GrContext*)> createPathRenderer,
|
||||||
int expectedResources = 1,
|
|
||||||
GrAAType aaType = GrAAType::kNone,
|
GrAAType aaType = GrAAType::kNone,
|
||||||
GrStyle style = GrStyle(SkStrokeRec::kFill_InitStyle)) {
|
GrStyle style = GrStyle(SkStrokeRec::kFill_InitStyle)) {
|
||||||
sk_sp<GrContext> ctx = GrContext::MakeMock(nullptr);
|
sk_sp<GrContext> ctx = GrContext::MakeMock(nullptr);
|
||||||
ctx->setResourceCacheLimits(100, 10000);
|
ctx->setResourceCacheLimits(100, 100000);
|
||||||
GrResourceCache* cache = ctx->getResourceCache();
|
GrResourceCache* cache = ctx->getResourceCache();
|
||||||
|
|
||||||
sk_sp<GrRenderTargetContext> rtc(ctx->makeDeferredRenderTargetContext(
|
sk_sp<GrRenderTargetContext> rtc(ctx->makeDeferredRenderTargetContext(
|
||||||
@ -74,40 +84,61 @@ static void test_path(skiatest::Reporter* reporter,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sk_sp<GrPathRenderer> pathRenderer(createPathRenderer(ctx.get()));
|
||||||
SkPath path = createPath();
|
SkPath path = createPath();
|
||||||
|
|
||||||
// Initially, cache only has the render target context
|
// 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 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();
|
ctx->flush();
|
||||||
REPORTER_ASSERT(reporter, (1 + expectedResources) == cache->getResourceCount());
|
REPORTER_ASSERT(reporter, cache_non_scratch_resources_equals(cache, 1));
|
||||||
|
|
||||||
// Nothing should be purgeable yet
|
// Nothing should be purgeable yet
|
||||||
cache->purgeAsNeeded();
|
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
|
// Reset the path to change the GenID, which should invalidate any resources in the cache
|
||||||
path.reset();
|
path.reset();
|
||||||
cache->purgeAsNeeded();
|
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
|
// Test that deleting the original path invalidates the VBs cached by the tessellating path renderer
|
||||||
DEF_GPUTEST(TessellatingPathRendererCacheTest, reporter, factory) {
|
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)
|
// 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
|
// Test with a style that alters the path geometry. This needs to attach the invalidation logic
|
||||||
// path, not the modified path produced by the style.
|
// to the original path, not the modified path produced by the style.
|
||||||
SkPaint paint;
|
SkPaint paint;
|
||||||
paint.setStyle(SkPaint::kStroke_Style);
|
paint.setStyle(SkPaint::kStroke_Style);
|
||||||
paint.setStrokeWidth(1);
|
paint.setStrokeWidth(1);
|
||||||
GrStyle style(paint);
|
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
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user