blob: 74e1dd485d43f48499bf074e095e3d8cad8ef6fa [file] [log] [blame]
commit-bot@chromium.org855e88e2014-04-21 19:33:12 +00001/*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/core/SkCanvas.h"
9#include "include/core/SkPicture.h"
10#include "include/core/SkPictureRecorder.h"
11#include "include/core/SkShader.h"
12#include "include/core/SkSurface.h"
Mike Reed07ee5482021-03-07 12:53:44 -050013#include "src/core/SkPicturePriv.h"
14#include "src/core/SkResourceCache.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050015#include "src/shaders/SkPictureShader.h"
16#include "tests/Test.h"
commit-bot@chromium.org855e88e2014-04-21 19:33:12 +000017
Florin Malitab00a3602017-07-13 22:34:04 -040018// Test that the SkPictureShader cache is purged on shader deletion.
19DEF_TEST(PictureShader_caching, reporter) {
20 auto makePicture = [] () {
21 SkPictureRecorder recorder;
22 recorder.beginRecording(100, 100)->drawColor(SK_ColorGREEN);
23 return recorder.finishRecordingAsPicture();
24 };
25
26 sk_sp<SkPicture> picture = makePicture();
27 REPORTER_ASSERT(reporter, picture->unique());
28
29 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(100, 100);
30
31 {
32 SkPaint paint;
Mike Reed10a5ff22021-03-18 17:18:58 -040033 paint.setShader(picture->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat,
34 SkFilterMode::kNearest));
Florin Malitab00a3602017-07-13 22:34:04 -040035 surface->getCanvas()->drawPaint(paint);
36
37 // We should have about 3 refs by now: local + shader + shader cache.
38 REPORTER_ASSERT(reporter, !picture->unique());
39 }
40
41 // Draw another picture shader to have a chance to purge.
42 {
43 SkPaint paint;
Mike Reed10a5ff22021-03-18 17:18:58 -040044 paint.setShader(makePicture()->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat,
45 SkFilterMode::kNearest));
Florin Malitab00a3602017-07-13 22:34:04 -040046 surface->getCanvas()->drawPaint(paint);
47
48 }
49
50 // All but the local ref should be gone now.
51 REPORTER_ASSERT(reporter, picture->unique());
52}
Mike Reedff83dda2021-03-04 13:40:44 -050053
Mike Reedff83dda2021-03-04 13:40:44 -050054/*
55 * Check caching of picture-shaders
56 * - we do cache the underlying image (i.e. there is a cache entry)
57 * - there is only 1 entry, even with differing tile modes
58 * - after deleting the picture, the cache entry is purged
59 */
60DEF_TEST(PictureShader_caching2, reporter) {
61 auto picture = []() {
62 SkPictureRecorder recorder;
63 recorder.beginRecording(100, 100)->drawColor(SK_ColorGREEN);
64 return recorder.finishRecordingAsPicture();
65 }();
66 REPORTER_ASSERT(reporter, picture->unique());
67
68 struct Data {
69 uint64_t sharedID;
70 int counter;
71 } data = {
72 SkPicturePriv::MakeSharedID(picture->uniqueID()),
73 0,
74 };
75
76 auto counter = [](const SkResourceCache::Rec& rec, void* dataPtr) {
77 if (rec.getKey().getSharedID() == ((Data*)dataPtr)->sharedID) {
78 ((Data*)dataPtr)->counter += 1;
79 }
80 };
81
82 SkResourceCache::VisitAll(counter, &data);
83 REPORTER_ASSERT(reporter, data.counter == 0);
84
85 // Draw with a view variants of picture-shaders that all use the same picture.
86 // Only expect 1 cache entry for all (since same CTM for all).
87 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(100, 100);
88 for (SkTileMode m : {
89 SkTileMode::kClamp, SkTileMode::kRepeat, SkTileMode::kRepeat, SkTileMode::kDecal
90 }) {
91 SkPaint paint;
Mike Reed10a5ff22021-03-18 17:18:58 -040092 paint.setShader(picture->makeShader(m, m, SkFilterMode::kNearest));
Mike Reedff83dda2021-03-04 13:40:44 -050093 surface->getCanvas()->drawPaint(paint);
94 }
95
96 // Don't expect any additional refs on the picture
97 REPORTER_ASSERT(reporter, picture->unique());
98
99 // Check that we did cache something, but only 1 thing
100 data.counter = 0;
101 SkResourceCache::VisitAll(counter, &data);
102 REPORTER_ASSERT(reporter, data.counter == 1);
103
104 // Now delete the picture, and check the we purge the cache entry
105
106 picture.reset();
107 SkResourceCache::CheckMessages();
108
109 data.counter = 0;
110 SkResourceCache::VisitAll(counter, &data);
111 REPORTER_ASSERT(reporter, data.counter == 0);
112}