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 "SkNextID.h"
12 #include "SkRefCnt.h"
13 #include "SkSurfaceProps.h"
14 
15 #include "SkImageFilter.h" // for OutputProperties
16 #include "SkImageInfo.h"   // for SkAlphaType
17 
18 class GrContext;
19 class GrSurfaceProxy;
20 class GrTexture;
21 class GrTextureProxy;
22 class SkBitmap;
23 class SkCanvas;
24 class SkImage;
25 struct SkImageInfo;
26 class SkPaint;
27 class SkPixmap;
28 class SkSpecialSurface;
29 class SkSurface;
30 
31 enum {
32     kNeedNewImageUniqueID_SpecialImage = 0
33 };
34 
35 /**
36  * This is a restricted form of SkImage solely intended for internal use. It
37  * differs from SkImage in that:
38  *      - it can only be backed by raster or gpu (no generators)
39  *      - it can be backed by a GrTextureProxy larger than its nominal bounds
40  *      - it can't be drawn tiled
41  *      - it can't be drawn with MIPMAPs
42  * It is similar to SkImage in that it abstracts how the pixels are stored/represented.
43  *
44  * Note: the contents of the backing storage outside of the subset rect are undefined.
45  */
46 class SkSpecialImage : public SkRefCnt {
47 public:
48     typedef void* ReleaseContext;
49     typedef void(*RasterReleaseProc)(void* pixels, ReleaseContext);
50 
props()51     const SkSurfaceProps& props() const { return fProps; }
52 
width()53     int width() const { return fSubset.width(); }
height()54     int height() const { return fSubset.height(); }
subset()55     const SkIRect& subset() const { return fSubset; }
56     SkColorSpace* getColorSpace() const;
57 
uniqueID()58     uint32_t uniqueID() const { return fUniqueID; }
59     virtual SkAlphaType alphaType() const = 0;
60     virtual size_t getSize() const = 0;
61 
62     /**
63      *  Ensures that a special image is backed by a texture (when GrContext is non-null). If no
64      *  transformation is required, the returned image may be the same as this special image.
65      *  If this special image is from a different GrContext, this will fail.
66      */
67     sk_sp<SkSpecialImage> makeTextureImage(GrContext*);
68 
69     /**
70      *  Draw this SpecialImage into the canvas.
71      */
72     void draw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) const;
73 
74     static sk_sp<SkSpecialImage> MakeFromImage(const SkIRect& subset,
75                                                sk_sp<SkImage>,
76                                                SkColorSpace* dstColorSpace,
77                                                const SkSurfaceProps* = nullptr);
78     static sk_sp<SkSpecialImage> MakeFromRaster(const SkIRect& subset,
79                                                 const SkBitmap&,
80                                                 const SkSurfaceProps* = nullptr);
81 #if SK_SUPPORT_GPU
82     static sk_sp<SkSpecialImage> MakeDeferredFromGpu(GrContext*,
83                                                      const SkIRect& subset,
84                                                      uint32_t uniqueID,
85                                                      sk_sp<GrTextureProxy>,
86                                                      sk_sp<SkColorSpace>,
87                                                      const SkSurfaceProps* = nullptr,
88                                                      SkAlphaType at = kPremul_SkAlphaType);
89 #endif
90 
91     /**
92      *  Create a new special surface with a backend that is compatible with this special image.
93      */
94     sk_sp<SkSpecialSurface> makeSurface(const SkImageFilter::OutputProperties& outProps,
95                                         const SkISize& size,
96                                         SkAlphaType at = kPremul_SkAlphaType) const;
97 
98     /**
99      * Create a new surface with a backend that is compatible with this special image.
100      * TODO: switch this to makeSurface once we resolved the naming issue
101      */
102     sk_sp<SkSurface> makeTightSurface(const SkImageFilter::OutputProperties& outProps,
103                                       const SkISize& size,
104                                       SkAlphaType at = kPremul_SkAlphaType) const;
105 
106     /**
107      * Extract a subset of this special image and return it as a special image.
108      * It may or may not point to the same backing memory.
109      */
110     sk_sp<SkSpecialImage> makeSubset(const SkIRect& subset) const;
111 
112     /**
113      * Create an SkImage from the contents of this special image optionally extracting a subset.
114      * It may or may not point to the same backing memory.
115      * Note: when no 'subset' parameter is specified the the entire SkSpecialImage will be
116      * returned - including whatever extra padding may have resulted from a loose fit!
117      * When the 'subset' parameter is specified the returned image will be tight even if that
118      * entails a copy!
119      */
120     sk_sp<SkImage> asImage(const SkIRect* subset = nullptr) const;
121 
122     // TODO: hide this when GrLayerHoister uses SkSpecialImages more fully (see skbug.com/5063)
123     /**
124      *  If the SpecialImage is backed by a gpu texture, return true.
125      */
126     bool isTextureBacked() const;
127 
128     /**
129      * Return the GrContext if the SkSpecialImage is GrTexture-backed
130      */
131     GrContext* getContext() const;
132 
133 #if SK_SUPPORT_GPU
134     /**
135      *  Regardless of the underlying backing store, return the contents as a GrTextureProxy.
136      *  The active portion of the texture can be retrieved via 'subset'.
137      */
138     sk_sp<GrTextureProxy> asTextureProxyRef(GrContext*) const;
139 #endif
140 
141     // TODO: hide this whe the imagefilter all have a consistent draw path (see skbug.com/5063)
142     /**
143      *  Regardless of the underlying backing store, return the contents as an SkBitmap
144      *
145      *  The returned ImageInfo represents the backing memory. Use 'subset'
146      *  to get the active portion's dimensions.
147      */
148     bool getROPixels(SkBitmap*) const;
149 
150 protected:
151     SkSpecialImage(const SkIRect& subset, uint32_t uniqueID, const SkSurfaceProps*);
152 
153 private:
154     const SkSurfaceProps fProps;
155     const SkIRect        fSubset;
156     const uint32_t       fUniqueID;
157 
158     typedef SkRefCnt INHERITED;
159 };
160 
161 #endif
162