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