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