xref: /aosp_15_r20/external/skia/src/gpu/ganesh/image/SkSpecialImage_Ganesh.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2023 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/ganesh/image/SkSpecialImage_Ganesh.h"
9 
10 #include "include/core/SkColorSpace.h"  // IWYU pragma: keep
11 #include "include/core/SkImage.h"
12 #include "include/core/SkImageInfo.h"
13 #include "include/core/SkRect.h"
14 #include "include/core/SkSize.h"
15 #include "include/gpu/GpuTypes.h"
16 #include "include/gpu/ganesh/GrRecordingContext.h"
17 #include "include/private/base/SkAssert.h"
18 #include "include/private/gpu/ganesh/GrTypesPriv.h"
19 #include "src/core/SkSpecialImage.h"
20 #include "src/gpu/ganesh/GrSurfaceProxy.h"
21 #include "src/gpu/ganesh/GrSurfaceProxyPriv.h"
22 #include "src/gpu/ganesh/GrSurfaceProxyView.h"
23 #include "src/gpu/ganesh/image/GrImageUtils.h"
24 #include "src/gpu/ganesh/image/SkImage_Ganesh.h"
25 
26 #include <cstddef>
27 #include <utility>
28 
29 enum SkColorType : int;
30 
31 class SkSpecialImage_Gpu final : public SkSpecialImage {
32 public:
SkSpecialImage_Gpu(GrRecordingContext * context,const SkIRect & subset,uint32_t uniqueID,GrSurfaceProxyView view,const SkColorInfo & colorInfo,const SkSurfaceProps & props)33     SkSpecialImage_Gpu(GrRecordingContext* context,
34                        const SkIRect& subset,
35                        uint32_t uniqueID,
36                        GrSurfaceProxyView view,
37                        const SkColorInfo& colorInfo,
38                        const SkSurfaceProps& props)
39             : SkSpecialImage(subset, uniqueID, colorInfo, props)
40             , fContext(context)
41             , fView(std::move(view)) {}
42 
getSize() const43     size_t getSize() const override { return fView.proxy()->gpuMemorySize(); }
44 
isGaneshBacked() const45     bool isGaneshBacked() const override { return true; }
46 
getContext() const47     GrRecordingContext* getContext() const override { return fContext; }
48 
view(GrRecordingContext *) const49     GrSurfaceProxyView view(GrRecordingContext*) const { return fView; }
50 
backingStoreDimensions() const51     SkISize backingStoreDimensions() const override {
52         return fView.proxy()->backingStoreDimensions();
53     }
54 
onMakeBackingStoreSubset(const SkIRect & subset) const55     sk_sp<SkSpecialImage> onMakeBackingStoreSubset(const SkIRect& subset) const override {
56         return SkSpecialImages::MakeDeferredFromGpu(
57                 fContext, subset, this->uniqueID(), fView, this->colorInfo(), this->props());
58     }
59 
asImage() const60     sk_sp<SkImage> asImage() const override {
61         fView.proxy()->priv().exactify();
62         return sk_make_sp<SkImage_Ganesh>(
63                 sk_ref_sp(fContext), this->uniqueID(), fView, this->colorInfo());
64     }
65 
66 private:
67     GrRecordingContext* fContext;
68     GrSurfaceProxyView fView;
69 };
70 
71 namespace SkSpecialImages {
72 
MakeFromTextureImage(GrRecordingContext * rContext,const SkIRect & subset,sk_sp<SkImage> image,const SkSurfaceProps & props)73 sk_sp<SkSpecialImage> MakeFromTextureImage(GrRecordingContext* rContext,
74                                            const SkIRect& subset,
75                                            sk_sp<SkImage> image,
76                                            const SkSurfaceProps& props) {
77     if (!rContext || !image || subset.isEmpty()) {
78         return nullptr;
79     }
80 
81     SkASSERT(image->bounds().contains(subset));
82 
83     // This will work even if the image is a raster-backed image.
84     auto [view, ct] = skgpu::ganesh::AsView(rContext, image, skgpu::Mipmapped::kNo);
85     return MakeDeferredFromGpu(rContext,
86                                subset,
87                                image->uniqueID(),
88                                std::move(view),
89                                {ct, image->alphaType(), image->refColorSpace()},
90                                props);
91 }
92 
MakeDeferredFromGpu(GrRecordingContext * context,const SkIRect & subset,uint32_t uniqueID,GrSurfaceProxyView view,const GrColorInfo & colorInfo,const SkSurfaceProps & props)93 sk_sp<SkSpecialImage> MakeDeferredFromGpu(GrRecordingContext* context,
94                                           const SkIRect& subset,
95                                           uint32_t uniqueID,
96                                           GrSurfaceProxyView view,
97                                           const GrColorInfo& colorInfo,
98                                           const SkSurfaceProps& props) {
99     if (!context || context->abandoned() || !view.asTextureProxy()) {
100         return nullptr;
101     }
102 
103     SkASSERT(view.proxy()->backingStoreBoundsIRect().contains(subset));
104 
105     SkColorType ct = GrColorTypeToSkColorType(colorInfo.colorType());
106     return sk_make_sp<SkSpecialImage_Gpu>(
107             context,
108             subset,
109             uniqueID,
110             std::move(view),
111             SkColorInfo(ct, colorInfo.alphaType(), colorInfo.refColorSpace()),
112             props);
113 }
114 
AsView(GrRecordingContext * context,const SkSpecialImage * img)115 GrSurfaceProxyView AsView(GrRecordingContext* context, const SkSpecialImage* img) {
116     if (!context || !img || !img->isGaneshBacked()) {
117         return {};
118     }
119     auto grImg = static_cast<const SkSpecialImage_Gpu*>(img);
120     return grImg->view(context);
121 }
122 
123 }  // namespace SkSpecialImages
124