xref: /aosp_15_r20/external/skia/src/gpu/graphite/SpecialImage_Graphite.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2022 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 "src/gpu/graphite/SpecialImage_Graphite.h"
9 
10 #include "include/core/SkCanvas.h"
11 #include "include/core/SkColorSpace.h"
12 #include "src/core/SkSpecialImage.h"
13 #include "src/gpu/graphite/Device.h"
14 #include "src/gpu/graphite/Image_Graphite.h"
15 #include "src/gpu/graphite/Surface_Graphite.h"
16 #include "src/gpu/graphite/TextureUtils.h"
17 
18 namespace skgpu::graphite {
19 
20 class SpecialImage final : public SkSpecialImage {
21 public:
SpecialImage(const SkIRect & subset,sk_sp<SkImage> image,const SkSurfaceProps & props)22     SpecialImage(const SkIRect& subset, sk_sp<SkImage> image, const SkSurfaceProps& props)
23             : SkSpecialImage(subset, image->uniqueID(), image->imageInfo().colorInfo(), props)
24             , fImage(std::move(image)) {
25         SkASSERT(as_IB(fImage)->isGraphiteBacked());
26     }
27 
getSize() const28     size_t getSize() const override {
29         return fImage->textureSize();
30     }
31 
isGraphiteBacked() const32     bool isGraphiteBacked() const override { return true; }
33 
backingStoreDimensions() const34     SkISize backingStoreDimensions() const override {
35         return fImage->dimensions();
36     }
37 
onMakeBackingStoreSubset(const SkIRect & subset) const38     sk_sp<SkSpecialImage> onMakeBackingStoreSubset(const SkIRect& subset) const override {
39         SkASSERT(fImage->bounds().contains(subset));
40         return sk_make_sp<skgpu::graphite::SpecialImage>(subset, fImage, this->props());
41     }
42 
asImage() const43     sk_sp<SkImage> asImage() const override { return fImage; }
44 
45 private:
46     // TODO(b/299474380): SkSpecialImage is intended to go away in favor of just using SkImages
47     // and tracking the intended srcRect explicitly in skif::FilterResult. Since Graphite tracks
48     // device-linked textures via Images, the graphite special image just wraps an image.
49     sk_sp<SkImage> fImage;
50 };
51 
52 } // namespace skgpu::graphite
53 
54 namespace SkSpecialImages {
55 
MakeGraphite(skgpu::graphite::Recorder * recorder,const SkIRect & subset,sk_sp<SkImage> image,const SkSurfaceProps & props)56 sk_sp<SkSpecialImage> MakeGraphite(skgpu::graphite::Recorder* recorder,
57                                    const SkIRect& subset,
58                                    sk_sp<SkImage> image,
59                                    const SkSurfaceProps& props) {
60     // 'recorder' can be null if we're wrapping a graphite-backed image since there's no work that
61     // needs to be added. This can happen when snapping a special image from a Device that's been
62     // marked as immutable and abandoned its recorder.
63     if (!image || subset.isEmpty()) {
64         return nullptr;
65     }
66 
67     SkASSERT(image->bounds().contains(subset));
68 
69     // Use the Recorder's client ImageProvider to convert to a graphite-backed image when
70     // possible, but this does not necessarily mean the provider will produce a valid image.
71     if (!as_IB(image)->isGraphiteBacked()) {
72         if (!recorder) {
73             return nullptr;
74         }
75         auto [graphiteImage, _] =
76                 skgpu::graphite::GetGraphiteBacked(recorder, image.get(), {});
77         if (!graphiteImage) {
78             return nullptr;
79         }
80 
81         image = graphiteImage;
82     }
83 
84     return sk_make_sp<skgpu::graphite::SpecialImage>(subset, std::move(image), props);
85 }
86 
87 }  // namespace SkSpecialImages
88