xref: /aosp_15_r20/external/skia/tools/graphite/GraphiteToolUtils.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2024 Google LLC
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 "tools/graphite/GraphiteToolUtils.h"
9 
10 #include "include/core/SkCanvas.h"
11 #include "include/core/SkImage.h"
12 #include "include/core/SkTiledImageUtils.h"
13 #include "include/gpu/graphite/Image.h"
14 #include "include/gpu/graphite/ImageProvider.h"
15 #include "include/gpu/graphite/Recorder.h"
16 #include "src/core/SkLRUCache.h"
17 
18 namespace {
19 // Currently, we give each new Recorder its own ImageProvider. This means we don't have to deal
20 // w/ any threading issues.
21 // TODO: We should probably have this class generate and report some cache stats
22 // TODO: Hook up to listener system?
23 // TODO: add testing of a single ImageProvider passed to multiple recorders
24 class TestingImageProvider : public skgpu::graphite::ImageProvider {
25 public:
TestingImageProvider()26     TestingImageProvider() : fCache(kDefaultNumCachedImages) {}
~TestingImageProvider()27     ~TestingImageProvider() override {}
28 
findOrCreate(skgpu::graphite::Recorder * recorder,const SkImage * image,SkImage::RequiredProperties requiredProps)29     sk_sp<SkImage> findOrCreate(skgpu::graphite::Recorder* recorder,
30                                 const SkImage* image,
31                                 SkImage::RequiredProperties requiredProps) override {
32         if (!requiredProps.fMipmapped) {
33             // If no mipmaps are required, check to see if we have a mipmapped version anyway -
34             // since it can be used in that case.
35             // TODO: we could get fancy and, if ever a mipmapped key eclipsed a non-mipmapped
36             // key, we could remove the hidden non-mipmapped key/image from the cache.
37             ImageKey mipMappedKey(image, /* mipmapped= */ true);
38             auto result = fCache.find(mipMappedKey);
39             if (result) {
40                 return *result;
41             }
42         }
43 
44         ImageKey key(image, requiredProps.fMipmapped);
45 
46         auto result = fCache.find(key);
47         if (result) {
48             return *result;
49         }
50 
51         sk_sp<SkImage> newImage = SkImages::TextureFromImage(recorder, image, requiredProps);
52         if (!newImage) {
53             return nullptr;
54         }
55 
56         result = fCache.insert(key, std::move(newImage));
57         SkASSERT(result);
58 
59         return *result;
60     }
61 
62 private:
63     static constexpr int kDefaultNumCachedImages = 256;
64 
65     class ImageKey {
66     public:
ImageKey(const SkImage * image,bool mipmapped)67         ImageKey(const SkImage* image, bool mipmapped) {
68             uint32_t flags = mipmapped ? 0x1 : 0x0;
69             SkTiledImageUtils::GetImageKeyValues(image, &fValues[1]);
70             fValues[kNumValues - 1] = flags;
71             fValues[0] = SkChecksum::Hash32(&fValues[1], (kNumValues - 1) * sizeof(uint32_t));
72         }
73 
hash() const74         uint32_t hash() const { return fValues[0]; }
75 
operator ==(const ImageKey & other) const76         bool operator==(const ImageKey& other) const {
77             for (int i = 0; i < kNumValues; ++i) {
78                 if (fValues[i] != other.fValues[i]) {
79                     return false;
80                 }
81             }
82 
83             return true;
84         }
operator !=(const ImageKey & other) const85         bool operator!=(const ImageKey& other) const { return !(*this == other); }
86 
87     private:
88         static const int kNumValues = SkTiledImageUtils::kNumImageKeyValues + 2;
89 
90         uint32_t fValues[kNumValues];
91     };
92 
93     struct ImageHash {
operator ()__anon2a4697350111::TestingImageProvider::ImageHash94         size_t operator()(const ImageKey& key) const { return key.hash(); }
95     };
96 
97     SkLRUCache<ImageKey, sk_sp<SkImage>, ImageHash> fCache;
98 };
99 
100 }  // anonymous namespace
101 
102 namespace ToolUtils {
103 
CreateTestingRecorderOptions()104 skgpu::graphite::RecorderOptions CreateTestingRecorderOptions() {
105     skgpu::graphite::RecorderOptions options;
106 
107     options.fImageProvider.reset(new TestingImageProvider);
108 
109     return options;
110 }
111 
112 }  // namespace ToolUtils
113