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