xref: /aosp_15_r20/external/skia/src/core/SkSpecialImage.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2016 Google Inc.
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 #ifndef SkSpecialImage_DEFINED
9 #define SkSpecialImage_DEFINED
10 
11 #include "include/core/SkImageInfo.h"
12 #include "include/core/SkRect.h"
13 #include "include/core/SkRefCnt.h"
14 #include "include/core/SkSamplingOptions.h"
15 #include "include/core/SkScalar.h"
16 #include "include/core/SkSize.h"
17 #include "include/core/SkSurfaceProps.h"
18 
19 #include <cstddef>
20 #include <cstdint>
21 
22 class GrRecordingContext;
23 class SkBitmap;
24 class SkCanvas;
25 class SkColorSpace;
26 class SkImage;
27 class SkMatrix;
28 class SkPaint;
29 class SkShader;
30 enum SkAlphaType : int;
31 enum SkColorType : int;
32 enum class SkTileMode;
33 
34 enum {
35     kNeedNewImageUniqueID_SpecialImage = 0
36 };
37 
38 /**
39  * This is a restricted form of SkImage solely intended for internal use. It
40  * differs from SkImage in that:
41  *      - it can only be backed by raster or gpu (no generators)
42  *      - it can be backed by a GrTextureProxy larger than its nominal bounds
43  *      - it can't be drawn tiled
44  *      - it can't be drawn with MIPMAPs
45  * It is similar to SkImage in that it abstracts how the pixels are stored/represented.
46  *
47  * Note: the contents of the backing storage outside of the subset rect are undefined.
48  */
49 class SkSpecialImage : public SkRefCnt {
50 public:
51     typedef void* ReleaseContext;
52     typedef void(*RasterReleaseProc)(void* pixels, ReleaseContext);
53 
props()54     const SkSurfaceProps& props() const { return fProps; }
55 
width()56     int width() const { return fSubset.width(); }
height()57     int height() const { return fSubset.height(); }
dimensions()58     SkISize dimensions() const { return { this->width(), this->height() }; }
subset()59     const SkIRect& subset() const { return fSubset; }
60 
uniqueID()61     uint32_t uniqueID() const { return fUniqueID; }
62 
63     virtual SkISize backingStoreDimensions() const = 0;
64 
65     virtual size_t getSize() const = 0;
66 
isExactFit()67     bool isExactFit() const { return fSubset == SkIRect::MakeSize(this->backingStoreDimensions()); }
68 
colorInfo()69     const SkColorInfo& colorInfo() const { return fColorInfo; }
alphaType()70     SkAlphaType alphaType() const { return fColorInfo.alphaType(); }
colorType()71     SkColorType colorType() const { return fColorInfo.colorType(); }
getColorSpace()72     SkColorSpace* getColorSpace() const { return fColorInfo.colorSpace(); }
73 
74     /**
75      *  Draw this SpecialImage into the canvas, automatically taking into account the image's subset
76      */
77     void draw(SkCanvas* canvas,
78               SkScalar x, SkScalar y,
79               const SkSamplingOptions& sampling,
80               const SkPaint* paint,
81               bool strict = true) const;
draw(SkCanvas * canvas,SkScalar x,SkScalar y)82     void draw(SkCanvas* canvas, SkScalar x, SkScalar y) const {
83         this->draw(canvas, x, y, SkSamplingOptions(), nullptr);
84     }
85 
86     /**
87      * Extract a subset of this special image and return it as a special image.
88      * It may or may not point to the same backing memory. The input 'subset' is relative to the
89      * special image's content rect.
90      */
makeSubset(const SkIRect & subset)91     sk_sp<SkSpecialImage> makeSubset(const SkIRect& subset) const {
92         SkIRect absolute = subset.makeOffset(this->subset().topLeft());
93         return this->onMakeBackingStoreSubset(absolute);
94     }
95 
96     /**
97      * Return a special image with a 1px larger subset in the backing store compared to this image.
98      * This should only be used when it's externally known that those outer pixels are valid.
99      */
makePixelOutset()100     sk_sp<SkSpecialImage> makePixelOutset() const {
101         return this->onMakeBackingStoreSubset(this->subset().makeOutset(1, 1));
102     }
103 
104     /**
105      * Create an SkImage view of the contents of this special image, pointing to the same
106      * underlying memory.
107      *
108      * TODO: If SkImages::MakeFiltered were to return an SkShader that accounted for the subset
109      * constraint and offset, then this could move to a private virtual for use in draw() and
110      * asShader().
111      */
112     virtual sk_sp<SkImage> asImage() const = 0;
113 
114     /**
115      * Create an SkShader that samples the contents of this special image, applying tile mode for
116      * any sample that falls outside its internal subset.
117      *
118      * 'strict' defaults to true and applies shader-based tiling to the subset. If the subset is
119      * the same as the backing store dimensions, it is automatically degraded to non-strict
120      * (HW tiling and sampling). 'strict' can be set to false if it's known that the subset
121      * boundaries aren't visible AND the texel data in adjacent rows/cols is valid to be included
122      * by the given sampling options.
123      */
124     virtual sk_sp<SkShader> asShader(SkTileMode,
125                                      const SkSamplingOptions&,
126                                      const SkMatrix& lm,
127                                      bool strict=true) const;
128 
129     /**
130      *  If the SpecialImage is backed by a gpu texture, return true.
131      */
isGaneshBacked()132     virtual bool isGaneshBacked() const { return false; }
isGraphiteBacked()133     virtual bool isGraphiteBacked() const { return false; }
134 
135     /**
136      * Return the GrRecordingContext if the SkSpecialImage is GrTexture-backed
137      */
getContext()138     virtual GrRecordingContext* getContext() const { return nullptr; }
139 
140 protected:
141     SkSpecialImage(const SkIRect& subset,
142                    uint32_t uniqueID,
143                    const SkColorInfo&,
144                    const SkSurfaceProps&);
145 
146     // This subset is relative to the backing store's coordinate frame, it has already been mapped
147     // from the content rect by the non-virtual makeSubset(). The provided 'subset' is not
148     // necessarily contained within this special image's subset.
149     virtual sk_sp<SkSpecialImage> onMakeBackingStoreSubset(const SkIRect& subset) const = 0;
150 
151 private:
152     const SkIRect        fSubset;
153     const uint32_t       fUniqueID;
154     const SkColorInfo    fColorInfo;
155     const SkSurfaceProps fProps;
156 };
157 
158 namespace SkSpecialImages {
159 
160 sk_sp<SkSpecialImage> MakeFromRaster(const SkIRect& subset, sk_sp<SkImage>, const SkSurfaceProps&);
161 sk_sp<SkSpecialImage> MakeFromRaster(const SkIRect& subset, const SkBitmap&, const SkSurfaceProps&);
162 sk_sp<SkSpecialImage> CopyFromRaster(const SkIRect& subset, const SkBitmap&, const SkSurfaceProps&);
163 
164 bool AsBitmap(const SkSpecialImage* img, SkBitmap*);
165 
166 }  // namespace SkSpecialImages
167 
168 #endif // SkSpecialImage_DEFINED
169