1 /*
2  * Copyright 2012 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 SkImage_Base_DEFINED
9 #define SkImage_Base_DEFINED
10 
11 #include "include/core/SkImage.h"
12 #include "include/core/SkSurface.h"
13 #include "src/core/SkMipmap.h"
14 #include <atomic>
15 
16 #if SK_SUPPORT_GPU
17 #include "include/private/SkTDArray.h"
18 #include "src/gpu/GrSurfaceProxyView.h"
19 #include "src/gpu/GrTextureProxy.h"
20 #include "src/gpu/SkGr.h"
21 
22 class GrTexture;
23 #endif
24 
25 #include <new>
26 
27 class GrDirectContext;
28 class GrImageContext;
29 class GrSamplerState;
30 class SkCachedData;
31 
32 enum {
33     kNeedNewImageUniqueID = 0
34 };
35 
36 class SkImage_Base : public SkImage {
37 public:
38     ~SkImage_Base() override;
39 
onPeekPixels(SkPixmap *)40     virtual bool onPeekPixels(SkPixmap*) const { return false; }
41 
onPeekBitmap()42     virtual const SkBitmap* onPeekBitmap() const { return nullptr; }
43 
44     virtual bool onReadPixels(GrDirectContext*,
45                               const SkImageInfo& dstInfo,
46                               void* dstPixels,
47                               size_t dstRowBytes,
48                               int srcX,
49                               int srcY,
50                               CachingHint) const = 0;
51 
52     virtual bool onHasMipmaps() const = 0;
53 
onPeekMips()54     virtual SkMipmap* onPeekMips() const { return nullptr; }
55 
refMips()56     sk_sp<SkMipmap> refMips() const {
57         return sk_ref_sp(this->onPeekMips());
58     }
59 
60     /**
61      * Default implementation does a rescale/read and then calls the callback.
62      */
63     virtual void onAsyncRescaleAndReadPixels(const SkImageInfo&,
64                                              const SkIRect& srcRect,
65                                              RescaleGamma,
66                                              RescaleMode,
67                                              ReadPixelsCallback,
68                                              ReadPixelsContext);
69     /**
70      * Default implementation does a rescale/read/yuv conversion and then calls the callback.
71      */
72     virtual void onAsyncRescaleAndReadPixelsYUV420(SkYUVColorSpace,
73                                                    sk_sp<SkColorSpace> dstColorSpace,
74                                                    const SkIRect& srcRect,
75                                                    const SkISize& dstSize,
76                                                    RescaleGamma,
77                                                    RescaleMode,
78                                                    ReadPixelsCallback,
79                                                    ReadPixelsContext);
80 
context()81     virtual GrImageContext* context() const { return nullptr; }
82 
83     /** this->context() try-casted to GrDirectContext. Useful for migrations – avoid otherwise! */
84     GrDirectContext* directContext() const;
85 
86 #if SK_SUPPORT_GPU
onFlush(GrDirectContext *,const GrFlushInfo &)87     virtual GrSemaphoresSubmitted onFlush(GrDirectContext*, const GrFlushInfo&) {
88         return GrSemaphoresSubmitted::kNo;
89     }
90 
91     // Returns a GrSurfaceProxyView representation of the image, if possible. This also returns
92     // a color type. This may be different than the image's color type when the image is not
93     // texture-backed and the capabilities of the GPU require a data type conversion to put
94     // the data in a texture.
95     std::tuple<GrSurfaceProxyView, GrColorType> asView(
96             GrRecordingContext* context,
97             GrMipmapped mipmapped,
98             GrImageTexGenPolicy policy = GrImageTexGenPolicy::kDraw) const;
99 
100     /**
101      * Returns a GrFragmentProcessor that can be used with the passed GrRecordingContext to
102      * draw the image. SkSamplingOptions indicates the filter and SkTileMode[] indicates the x and
103      * y tile modes. The passed matrix is applied to the coordinates before sampling the image.
104      * Optional 'subset' indicates whether the tile modes should be applied to a subset of the image
105      * Optional 'domain' is a bound on the coordinates of the image that will be required and can be
106      * used to optimize the shader if 'subset' is also specified.
107      */
108     std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(GrRecordingContext*,
109                                                              SkSamplingOptions,
110                                                              const SkTileMode[2],
111                                                              const SkMatrix&,
112                                                              const SkRect* subset = nullptr,
113                                                              const SkRect* domain = nullptr) const;
114 
isYUVA()115     virtual bool isYUVA() const { return false; }
116 
117     // If this image is the current cached image snapshot of a surface then this is called when the
118     // surface is destroyed to indicate no further writes may happen to surface backing store.
generatingSurfaceIsDeleted()119     virtual void generatingSurfaceIsDeleted() {}
120 #endif
121 
onPinAsTexture(GrRecordingContext *)122     virtual bool onPinAsTexture(GrRecordingContext*) const { return false; }
onUnpinAsTexture(GrRecordingContext *)123     virtual void onUnpinAsTexture(GrRecordingContext*) const {}
isPinnedOnContext(GrRecordingContext *)124     virtual bool isPinnedOnContext(GrRecordingContext*) const { return false; }
125 
126     virtual GrBackendTexture onGetBackendTexture(bool flushPendingGrContextIO,
127                                                  GrSurfaceOrigin* origin) const;
128 
129     // return a read-only copy of the pixels. We promise to not modify them,
130     // but only inspect them (or encode them).
131     virtual bool getROPixels(GrDirectContext*, SkBitmap*,
132                              CachingHint = kAllow_CachingHint) const = 0;
133 
134     virtual sk_sp<SkImage> onMakeSubset(const SkIRect&, GrDirectContext*) const = 0;
135 
onRefEncoded()136     virtual sk_sp<SkData> onRefEncoded() const { return nullptr; }
137 
138     virtual bool onAsLegacyBitmap(GrDirectContext*, SkBitmap*) const;
139 
140     // True for picture-backed and codec-backed
onIsLazyGenerated()141     virtual bool onIsLazyGenerated() const { return false; }
142 
143     // True for images instantiated in GPU memory
onIsTextureBacked()144     virtual bool onIsTextureBacked() const { return false; }
145 
146     // Amount of texture memory used by texture-backed images.
onTextureSize()147     virtual size_t onTextureSize() const { return 0; }
148 
149     // Call when this image is part of the key to a resourcecache entry. This allows the cache
150     // to know automatically those entries can be purged when this SkImage deleted.
notifyAddedToRasterCache()151     virtual void notifyAddedToRasterCache() const {
152         fAddedToRasterCache.store(true);
153     }
154 
155     virtual bool onIsValid(GrRecordingContext*) const = 0;
156 
157     virtual sk_sp<SkImage> onMakeColorTypeAndColorSpace(SkColorType, sk_sp<SkColorSpace>,
158                                                         GrDirectContext*) const = 0;
159 
160     virtual sk_sp<SkImage> onReinterpretColorSpace(sk_sp<SkColorSpace>) const = 0;
161 
162     // on failure, returns nullptr
onMakeWithMipmaps(sk_sp<SkMipmap>)163     virtual sk_sp<SkImage> onMakeWithMipmaps(sk_sp<SkMipmap>) const {
164         return nullptr;
165     }
166 
167 protected:
168     SkImage_Base(const SkImageInfo& info, uint32_t uniqueID);
169 
170 #if SK_SUPPORT_GPU
171     // Utility for making a copy of an existing view when the GrImageTexGenPolicy is not kDraw.
172     static GrSurfaceProxyView CopyView(GrRecordingContext*,
173                                        GrSurfaceProxyView src,
174                                        GrMipmapped,
175                                        GrImageTexGenPolicy);
176 
177     static std::unique_ptr<GrFragmentProcessor> MakeFragmentProcessorFromView(GrRecordingContext*,
178                                                                               GrSurfaceProxyView,
179                                                                               SkAlphaType,
180                                                                               SkSamplingOptions,
181                                                                               const SkTileMode[2],
182                                                                               const SkMatrix&,
183                                                                               const SkRect* subset,
184                                                                               const SkRect* domain);
185 
186     /**
187      * Returns input view if it is already mipmapped. Otherwise, attempts to make a mipmapped view
188      * with the same contents. If the mipmapped copy is successfully created it will be cached
189      * using the image unique ID. A subsequent call with the same unique ID will return the cached
190      * view if it has not been purged. The view is cached with a key domain specific to this
191      * function.
192      */
193     static GrSurfaceProxyView FindOrMakeCachedMipmappedView(GrRecordingContext*,
194                                                             GrSurfaceProxyView,
195                                                             uint32_t imageUniqueID);
196 #endif
197 
198 private:
199 #if SK_SUPPORT_GPU
200     virtual std::tuple<GrSurfaceProxyView, GrColorType> onAsView(
201             GrRecordingContext*,
202             GrMipmapped,
203             GrImageTexGenPolicy policy) const = 0;
204 
205     virtual std::unique_ptr<GrFragmentProcessor> onAsFragmentProcessor(
206             GrRecordingContext*,
207             SkSamplingOptions,
208             const SkTileMode[2],
209             const SkMatrix&,
210             const SkRect* subset,
211             const SkRect* domain) const = 0;
212 #endif
213     // Set true by caches when they cache content that's derived from the current pixels.
214     mutable std::atomic<bool> fAddedToRasterCache;
215 
216     using INHERITED = SkImage;
217 };
218 
as_IB(SkImage * image)219 static inline SkImage_Base* as_IB(SkImage* image) {
220     return static_cast<SkImage_Base*>(image);
221 }
222 
as_IB(const sk_sp<SkImage> & image)223 static inline SkImage_Base* as_IB(const sk_sp<SkImage>& image) {
224     return static_cast<SkImage_Base*>(image.get());
225 }
226 
as_IB(const SkImage * image)227 static inline const SkImage_Base* as_IB(const SkImage* image) {
228     return static_cast<const SkImage_Base*>(image);
229 }
230 
231 #if SK_SUPPORT_GPU
CopyView(GrRecordingContext * context,GrSurfaceProxyView src,GrMipmapped mipmapped,GrImageTexGenPolicy policy)232 inline GrSurfaceProxyView SkImage_Base::CopyView(GrRecordingContext* context,
233                                                  GrSurfaceProxyView src,
234                                                  GrMipmapped mipmapped,
235                                                  GrImageTexGenPolicy policy) {
236     SkBudgeted budgeted = policy == GrImageTexGenPolicy::kNew_Uncached_Budgeted
237                           ? SkBudgeted::kYes
238                           : SkBudgeted::kNo;
239     return GrSurfaceProxyView::Copy(context,
240                                     std::move(src),
241                                     mipmapped,
242                                     SkBackingFit::kExact,
243                                     budgeted);
244 }
245 #endif
246 
247 #endif
248