• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/SkRefCnt.h"
13 #include "include/core/SkSamplingOptions.h"
14 #include "include/core/SkSurfaceProps.h"
15 #include "src/core/SkNextID.h"
16 
17 #if SK_SUPPORT_GPU
18 #include "include/private/GrTypesPriv.h"
19 #include "src/gpu/GrSurfaceProxyView.h"
20 #endif
21 
22 class GrRecordingContext;
23 class GrTextureProxy;
24 class SkBitmap;
25 class SkCanvas;
26 class SkImage;
27 struct SkImageInfo;
28 class SkMatrix;
29 class SkPaint;
30 class SkPixmap;
31 class SkShader;
32 class SkSpecialSurface;
33 class SkSurface;
34 enum class SkTileMode;
35 
36 enum {
37     kNeedNewImageUniqueID_SpecialImage = 0
38 };
39 
40 /**
41  * This is a restricted form of SkImage solely intended for internal use. It
42  * differs from SkImage in that:
43  *      - it can only be backed by raster or gpu (no generators)
44  *      - it can be backed by a GrTextureProxy larger than its nominal bounds
45  *      - it can't be drawn tiled
46  *      - it can't be drawn with MIPMAPs
47  * It is similar to SkImage in that it abstracts how the pixels are stored/represented.
48  *
49  * Note: the contents of the backing storage outside of the subset rect are undefined.
50  */
51 class SkSpecialImage : public SkRefCnt {
52 public:
53     typedef void* ReleaseContext;
54     typedef void(*RasterReleaseProc)(void* pixels, ReleaseContext);
55 
props()56     const SkSurfaceProps& props() const { return fProps; }
57 
width()58     int width() const { return fSubset.width(); }
height()59     int height() const { return fSubset.height(); }
subset()60     const SkIRect& subset() const { return fSubset; }
61     SkColorSpace* getColorSpace() const;
62 
uniqueID()63     uint32_t uniqueID() const { return fUniqueID; }
64     virtual SkAlphaType alphaType() const = 0;
65     virtual SkColorType colorType() const = 0;
66     virtual size_t getSize() const = 0;
67 
68     /**
69      *  Draw this SpecialImage into the canvas, automatically taking into account the image's subset
70      */
71     void draw(SkCanvas*, SkScalar x, SkScalar y, const SkSamplingOptions&, const SkPaint*) const;
draw(SkCanvas * canvas,SkScalar x,SkScalar y)72     void draw(SkCanvas* canvas, SkScalar x, SkScalar y) const {
73         this->draw(canvas, x, y, SkSamplingOptions(), nullptr);
74     }
75 
76     static sk_sp<SkSpecialImage> MakeFromImage(GrRecordingContext*,
77                                                const SkIRect& subset,
78                                                sk_sp<SkImage>,
79                                                const SkSurfaceProps&);
80     static sk_sp<SkSpecialImage> MakeFromRaster(const SkIRect& subset,
81                                                 const SkBitmap&,
82                                                 const SkSurfaceProps&);
83     static sk_sp<SkSpecialImage> CopyFromRaster(const SkIRect& subset,
84                                                 const SkBitmap&,
85                                                 const SkSurfaceProps&);
86 #if SK_SUPPORT_GPU
87     static sk_sp<SkSpecialImage> MakeDeferredFromGpu(GrRecordingContext*,
88                                                      const SkIRect& subset,
89                                                      uint32_t uniqueID,
90                                                      GrSurfaceProxyView,
91                                                      GrColorType,
92                                                      sk_sp<SkColorSpace>,
93                                                      const SkSurfaceProps&,
94                                                      SkAlphaType at = kPremul_SkAlphaType);
95 #endif
96 
97     /**
98      *  Create a new special surface with a backend that is compatible with this special image.
99      */
100     sk_sp<SkSpecialSurface> makeSurface(SkColorType colorType,
101                                         const SkColorSpace* colorSpace,
102                                         const SkISize& size,
103                                         SkAlphaType,
104                                         const SkSurfaceProps&) const;
105 
106     /**
107      * Create a new surface with a backend that is compatible with this special image.
108      * TODO: switch this to makeSurface once we resolved the naming issue
109      * TODO (michaelludwig) - This is only used by SkTileImageFilter, which appears should be
110      * updated to work correctly with subsets and then makeTightSurface() can go away entirely.
111      */
112     sk_sp<SkSurface> makeTightSurface(SkColorType colorType,
113                                       const SkColorSpace* colorSpace,
114                                       const SkISize& size,
115                                       SkAlphaType at = kPremul_SkAlphaType) const;
116 
117     /**
118      * Extract a subset of this special image and return it as a special image.
119      * It may or may not point to the same backing memory. The input 'subset' is relative to the
120      * special image's content rect.
121      */
122     sk_sp<SkSpecialImage> makeSubset(const SkIRect& subset) const;
123 
124     /**
125      * Create an SkImage from the contents of this special image optionally extracting a subset.
126      * It may or may not point to the same backing memory.
127      * Note: when no 'subset' parameter is specified the the entire SkSpecialImage will be
128      * returned - including whatever extra padding may have resulted from a loose fit!
129      * When the 'subset' parameter is specified the returned image will be tight even if that
130      * entails a copy! The 'subset' is relative to this special image's content rect.
131      */
132     // TODO: The only version that uses the subset is the tile image filter, and that doesn't need
133     // to if it can be rewritten to use asShader() and SkTileModes. Similarly, the only use case of
134     // asImage() w/o a subset is SkImage::makeFiltered() and that could/should return an SkShader so
135     // that users don't need to worry about correctly applying the subset, etc.
136     sk_sp<SkImage> asImage(const SkIRect* subset = nullptr) const;
137 
138     /**
139      * Create an SkShader that samples the contents of this special image, applying tile mode for
140      * any sample that falls outside its internal subset.
141      */
142     sk_sp<SkShader> asShader(SkTileMode, const SkSamplingOptions&, const SkMatrix&) const;
143     sk_sp<SkShader> asShader(const SkSamplingOptions& sampling) const;
144     sk_sp<SkShader> asShader(const SkSamplingOptions& sampling, const SkMatrix& lm) const;
145 
146     /**
147      *  If the SpecialImage is backed by a gpu texture, return true.
148      */
149     bool isTextureBacked() const;
150 
151     /**
152      * Return the GrRecordingContext if the SkSpecialImage is GrTexture-backed
153      */
154     GrRecordingContext* getContext() const;
155 
156 #if SK_SUPPORT_GPU
157     /**
158      * Regardless of how the underlying backing data is stored, returns the contents as a
159      * GrSurfaceProxyView. The returned view's proxy represents the entire backing image, so texture
160      * coordinates must be mapped from the content rect (e.g. relative to 'subset()') to the proxy's
161      * space (offset by subset().topLeft()).
162      */
163     GrSurfaceProxyView view(GrRecordingContext*) const;
164 #endif
165 
166     /**
167      *  Regardless of the underlying backing store, return the contents as an SkBitmap.
168      *  The returned bitmap represents the subset accessed by this image, thus (0,0) refers to the
169      *  top-left corner of 'subset'.
170      */
171     bool getROPixels(SkBitmap*) const;
172 
173 protected:
174     SkSpecialImage(const SkIRect& subset, uint32_t uniqueID, const SkSurfaceProps&);
175 
176 private:
177     const SkSurfaceProps fProps;
178     const SkIRect        fSubset;
179     const uint32_t       fUniqueID;
180 
181     using INHERITED = SkRefCnt;
182 };
183 
184 #endif
185