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