b00a36050a
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 <reed@google.com> Commit-Queue: Florin Malita <fmalita@chromium.org>
81 lines
2.7 KiB
C++
81 lines
2.7 KiB
C++
/*
|
|
* Copyright 2014 Google Inc.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
#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
|
|
// empty picture returns a shader that draws nothing.
|
|
DEF_TEST(PictureShader_empty, reporter) {
|
|
SkPaint paint;
|
|
|
|
SkBitmap bitmap;
|
|
bitmap.allocN32Pixels(1,1);
|
|
|
|
SkCanvas canvas(bitmap);
|
|
canvas.clear(SK_ColorGREEN);
|
|
|
|
paint.setShader(SkShader::MakePictureShader(
|
|
nullptr, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, nullptr, nullptr));
|
|
|
|
canvas.drawRect(SkRect::MakeWH(1,1), paint);
|
|
REPORTER_ASSERT(reporter, *bitmap.getAddr32(0,0) == SK_ColorGREEN);
|
|
|
|
|
|
SkPictureRecorder factory;
|
|
factory.beginRecording(0, 0, nullptr, 0);
|
|
paint.setShader(SkShader::MakePictureShader(factory.finishRecordingAsPicture(),
|
|
SkShader::kClamp_TileMode,
|
|
SkShader::kClamp_TileMode, nullptr, nullptr));
|
|
|
|
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<SkPicture> picture = makePicture();
|
|
REPORTER_ASSERT(reporter, picture->unique());
|
|
|
|
sk_sp<SkSurface> 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());
|
|
}
|