From b00a36050a7144903b4bc0ad37108cb5c8fc6934 Mon Sep 17 00:00:00 2001 From: Florin Malita Date: Thu, 13 Jul 2017 22:34:04 -0400 Subject: Purge cached SkPictureShader entries on shader deletion We're currently adding picture shader cache entries to the resource cache, but we don't ever purge. To avoid exhausting the budget, add logic to associate cached entries with their owning picture shader, and purge when the shader is deleted. -- Side note -- The current cache key is K(pictureID, ...) so technically the cache entries are associated with the picture, not the shader. One could resonably argue we should only purge when the *picture* is deleted. Unfortunately, this doesn't work: the cache entries contain indirect refs to the picture (SkImageShader -> SkImage_Generated -> SkPictureImageGenerator -> SkPicture), so the picture is always kept alive. Associating the cache entries with the shader itself seems like a reasonable alternative, even if we give up some cache persistence in the process. Change-Id: Ia115dbb5ae627e5ee171da7c4430fecfd42f4292 Reviewed-on: https://skia-review.googlesource.com/23380 Reviewed-by: Mike Reed Commit-Queue: Florin Malita --- tests/PictureShaderTest.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'tests/PictureShaderTest.cpp') diff --git a/tests/PictureShaderTest.cpp b/tests/PictureShaderTest.cpp index 78d59afd41..742b72db16 100644 --- a/tests/PictureShaderTest.cpp +++ b/tests/PictureShaderTest.cpp @@ -8,7 +8,9 @@ #include "SkCanvas.h" #include "SkPicture.h" #include "SkPictureRecorder.h" +#include "SkPictureShader.h" #include "SkShader.h" +#include "SkSurface.h" #include "Test.h" // Test that attempting to create a picture shader with a nullptr picture or @@ -38,3 +40,41 @@ DEF_TEST(PictureShader_empty, reporter) { canvas.drawRect(SkRect::MakeWH(1,1), paint); REPORTER_ASSERT(reporter, *bitmap.getAddr32(0,0) == SK_ColorGREEN); } + +// Test that the SkPictureShader cache is purged on shader deletion. +DEF_TEST(PictureShader_caching, reporter) { + auto makePicture = [] () { + SkPictureRecorder recorder; + recorder.beginRecording(100, 100)->drawColor(SK_ColorGREEN); + return recorder.finishRecordingAsPicture(); + }; + + sk_sp picture = makePicture(); + REPORTER_ASSERT(reporter, picture->unique()); + + sk_sp surface = SkSurface::MakeRasterN32Premul(100, 100); + + { + SkPaint paint; + paint.setShader(SkPictureShader::Make(picture, + SkShader::kRepeat_TileMode, + SkShader::kRepeat_TileMode, nullptr, nullptr)); + surface->getCanvas()->drawPaint(paint); + + // We should have about 3 refs by now: local + shader + shader cache. + REPORTER_ASSERT(reporter, !picture->unique()); + } + + // Draw another picture shader to have a chance to purge. + { + SkPaint paint; + paint.setShader(SkPictureShader::Make(makePicture(), + SkShader::kRepeat_TileMode, + SkShader::kRepeat_TileMode, nullptr, nullptr)); + surface->getCanvas()->drawPaint(paint); + + } + + // All but the local ref should be gone now. + REPORTER_ASSERT(reporter, picture->unique()); +} -- cgit v1.2.3