xref: /aosp_15_r20/external/skia/tests/PictureShaderTest.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
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 
8 #include "include/core/SkCanvas.h"
9 #include "include/core/SkColor.h"
10 #include "include/core/SkImageInfo.h"
11 #include "include/core/SkPaint.h"
12 #include "include/core/SkPicture.h"
13 #include "include/core/SkPictureRecorder.h"
14 #include "include/core/SkRefCnt.h"
15 #include "include/core/SkSamplingOptions.h"
16 #include "include/core/SkSurface.h"
17 #include "include/core/SkTileMode.h"
18 #include "src/core/SkPicturePriv.h"
19 #include "src/core/SkResourceCache.h"
20 #include "tests/Test.h"
21 
22 #include <cstdint>
23 #include <initializer_list>
24 
25 // Test that the SkPictureShader cache is purged on shader deletion.
DEF_TEST(PictureShader_caching,reporter)26 DEF_TEST(PictureShader_caching, reporter) {
27     auto makePicture = [] () {
28         SkPictureRecorder recorder;
29         recorder.beginRecording(100, 100)->drawColor(SK_ColorGREEN);
30         return recorder.finishRecordingAsPicture();
31     };
32 
33     sk_sp<SkPicture> picture = makePicture();
34     REPORTER_ASSERT(reporter, picture->unique());
35 
36     sk_sp<SkSurface> surface = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(100, 100));
37 
38     {
39         SkPaint paint;
40         paint.setShader(picture->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat,
41                                             SkFilterMode::kNearest));
42         surface->getCanvas()->drawPaint(paint);
43 
44         // We should have about 3 refs by now: local + shader + shader cache.
45         REPORTER_ASSERT(reporter, !picture->unique());
46     }
47 
48     // Draw another picture shader to have a chance to purge.
49     {
50         SkPaint paint;
51         paint.setShader(makePicture()->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat,
52                                                   SkFilterMode::kNearest));
53         surface->getCanvas()->drawPaint(paint);
54 
55     }
56 
57     // All but the local ref should be gone now.
58     REPORTER_ASSERT(reporter, picture->unique());
59 }
60 
61 /*
62  *  Check caching of picture-shaders
63  *  - we do cache the underlying image (i.e. there is a cache entry)
64  *  - there is only 1 entry, even with differing tile modes
65  *  - after deleting the picture, the cache entry is purged
66  */
DEF_TEST(PictureShader_caching2,reporter)67 DEF_TEST(PictureShader_caching2, reporter) {
68     auto picture = []() {
69         SkPictureRecorder recorder;
70         recorder.beginRecording(100, 100)->drawColor(SK_ColorGREEN);
71         return recorder.finishRecordingAsPicture();
72     }();
73     REPORTER_ASSERT(reporter, picture->unique());
74 
75     struct Data {
76         uint64_t sharedID;
77         int counter;
78     } data = {
79         SkPicturePriv::MakeSharedID(picture->uniqueID()),
80         0,
81     };
82 
83     auto counter = [](const SkResourceCache::Rec& rec, void* dataPtr) {
84         if (rec.getKey().getSharedID() == ((Data*)dataPtr)->sharedID) {
85             ((Data*)dataPtr)->counter += 1;
86         }
87     };
88 
89     SkResourceCache::VisitAll(counter, &data);
90     REPORTER_ASSERT(reporter, data.counter == 0);
91 
92     // Draw with a view variants of picture-shaders that all use the same picture.
93     // Only expect 1 cache entry for all (since same CTM for all).
94     sk_sp<SkSurface> surface = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(100, 100));
95     for (SkTileMode m : {
96         SkTileMode::kClamp, SkTileMode::kRepeat, SkTileMode::kRepeat, SkTileMode::kDecal
97     }) {
98         SkPaint paint;
99         paint.setShader(picture->makeShader(m, m, SkFilterMode::kNearest));
100         surface->getCanvas()->drawPaint(paint);
101     }
102 
103     // Don't expect any additional refs on the picture
104     REPORTER_ASSERT(reporter, picture->unique());
105 
106     // Check that we did cache something, but only 1 thing
107     data.counter = 0;
108     SkResourceCache::VisitAll(counter, &data);
109     REPORTER_ASSERT(reporter, data.counter == 1);
110 
111     // Now delete the picture, and check the we purge the cache entry
112 
113     picture.reset();
114     SkResourceCache::CheckMessages();
115 
116     data.counter = 0;
117     SkResourceCache::VisitAll(counter, &data);
118     REPORTER_ASSERT(reporter, data.counter == 0);
119 }
120