• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2013 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 SkImageGenerator_DEFINED
9 #define SkImageGenerator_DEFINED
10 
11 #include "SkBitmap.h"
12 #include "SkColor.h"
13 #include "SkImageInfo.h"
14 
15 class GrContext;
16 class GrTexture;
17 class GrTextureParams;
18 class SkBitmap;
19 class SkData;
20 class SkImageGenerator;
21 class SkMatrix;
22 class SkPaint;
23 class SkPicture;
24 
25 #ifdef SK_SUPPORT_LEGACY_REFENCODEDDATA_NOCTX
26     #define SK_REFENCODEDDATA_CTXPARAM
27 #else
28     #define SK_REFENCODEDDATA_CTXPARAM  GrContext* ctx
29 #endif
30 
31 /**
32  *  Takes ownership of SkImageGenerator.  If this method fails for
33  *  whatever reason, it will return false and immediatetely delete
34  *  the generator.  If it succeeds, it will modify destination
35  *  bitmap.
36  *
37  *  If generator is NULL, will safely return false.
38  *
39  *  If this fails or when the SkDiscardablePixelRef that is
40  *  installed into destination is destroyed, it will
41  *  delete the generator.  Therefore, generator should be
42  *  allocated with new.
43  *
44  *  @param destination Upon success, this bitmap will be
45  *  configured and have a pixelref installed.
46  *
47  *  @return true iff successful.
48  */
49 SK_API bool SkDEPRECATED_InstallDiscardablePixelRef(SkImageGenerator*, SkBitmap* destination);
50 
51 /**
52  *  On success, installs a discardable pixelref into destination, based on encoded data.
53  *  Regardless of success or failure, the caller must still balance their ownership of encoded.
54  */
55 SK_API bool SkDEPRECATED_InstallDiscardablePixelRef(SkData* encoded, SkBitmap* destination);
56 
57 /**
58  *  An interface that allows a purgeable PixelRef (such as a
59  *  SkDiscardablePixelRef) to decode and re-decode an image as needed.
60  */
61 class SK_API SkImageGenerator : public SkNoncopyable {
62 public:
63     /**
64      *  The PixelRef which takes ownership of this SkImageGenerator
65      *  will call the image generator's destructor.
66      */
~SkImageGenerator()67     virtual ~SkImageGenerator() { }
68 
uniqueID()69     uint32_t uniqueID() const { return fUniqueID; }
70 
71     /**
72      *  Return a ref to the encoded (i.e. compressed) representation,
73      *  of this data. If the GrContext is non-null, then the caller is only interested in
74      *  gpu-specific formats, so the impl may return null even if they have encoded data,
75      *  assuming they know it is not suitable for the gpu.
76      *
77      *  If non-NULL is returned, the caller is responsible for calling
78      *  unref() on the data when it is finished.
79      */
80     SkData* refEncodedData(GrContext* ctx = nullptr) {
81 #ifdef SK_SUPPORT_LEGACY_REFENCODEDDATA_NOCTX
82         return this->onRefEncodedData();
83 #else
84         return this->onRefEncodedData(ctx);
85 #endif
86     }
87 
88     /**
89      *  Return the ImageInfo associated with this generator.
90      */
getInfo()91     const SkImageInfo& getInfo() const { return fInfo; }
92 
93     /**
94      *  Decode into the given pixels, a block of memory of size at
95      *  least (info.fHeight - 1) * rowBytes + (info.fWidth *
96      *  bytesPerPixel)
97      *
98      *  Repeated calls to this function should give the same results,
99      *  allowing the PixelRef to be immutable.
100      *
101      *  @param info A description of the format (config, size)
102      *         expected by the caller.  This can simply be identical
103      *         to the info returned by getInfo().
104      *
105      *         This contract also allows the caller to specify
106      *         different output-configs, which the implementation can
107      *         decide to support or not.
108      *
109      *         A size that does not match getInfo() implies a request
110      *         to scale. If the generator cannot perform this scale,
111      *         it will return kInvalidScale.
112      *
113      *  If info is kIndex8_SkColorType, then the caller must provide storage for up to 256
114      *  SkPMColor values in ctable. On success the generator must copy N colors into that storage,
115      *  (where N is the logical number of table entries) and set ctableCount to N.
116      *
117      *  If info is not kIndex8_SkColorType, then the last two parameters may be NULL. If ctableCount
118      *  is not null, it will be set to 0.
119      *
120      *  @return true on success.
121      */
122     bool getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
123                    SkPMColor ctable[], int* ctableCount);
124 
125     /**
126      *  Simplified version of getPixels() that asserts that info is NOT kIndex8_SkColorType and
127      *  uses the default Options.
128      */
129     bool getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes);
130 
131     /**
132      *  If planes or rowBytes is NULL or if any entry in planes is NULL or if any entry in rowBytes
133      *  is 0, this imagegenerator should output the sizes and return true if it can efficiently
134      *  return YUV planar data. If it cannot, it should return false. Note that either planes and
135      *  rowBytes are both fully defined and non NULL/non 0 or they are both NULL or have NULL or 0
136      *  entries only. Having only partial planes/rowBytes information is not supported.
137      *
138      *  If all planes and rowBytes entries are non NULL or non 0, then it should copy the
139      *  associated YUV data into those planes of memory supplied by the caller. It should validate
140      *  that the sizes match what it expected. If the sizes do not match, it should return false.
141      */
142     bool getYUV8Planes(SkISize sizes[3], void* planes[3], size_t rowBytes[3],
143                        SkYUVColorSpace* colorSpace);
144 
145     /**
146      *  If the generator can natively/efficiently return its pixels as a GPU image (backed by a
147      *  texture) this will return that image. If not, this will return NULL.
148      *
149      *  Regarding the GrContext parameter:
150      *
151      *  The caller may pass NULL for the context. In that case the generator may assume that its
152      *  internal context is current. If it has no internal context, then it should just return
153      *  null.
154      *
155      *  If the caller passes a non-null context, then the generator should only succeed if:
156      *  - it has no intrinsic context, and will use the caller's
157      *  - its internal context is the same
158      *  - it can somehow convert its texture into one that is valid for the provided context.
159      *
160      *  Regarding the GrTextureParams parameter:
161      *
162      *  If the context (the provided one or the generator's intrinsic one) determines that to
163      *  support the specified usage, it must return a different sized texture it may,
164      *  so the caller must inspect the texture's width/height and compare them to the generator's
165      *  getInfo() width/height. For readback usage use GrTextureParams::ClampNoFilter()
166      */
167     GrTexture* generateTexture(GrContext*, const SkIRect* subset = nullptr);
168 
169     struct SupportedSizes {
170         SkISize fSizes[2];
171     };
172 
173     /**
174      *  Some generators can efficiently scale their contents. If this is supported, the generator
175      *  may only support certain scaled dimensions. Call this with the desired scale factor,
176      *  and it will return true if scaling is supported, and in supportedSizes[] it will return
177      *  the nearest supported dimensions.
178      *
179      *  If no native scaling is supported, or scale is invalid (e.g. scale <= 0 || scale > 1)
180      *  this will return false, and the supportedsizes will be undefined.
181      */
182     bool computeScaledDimensions(SkScalar scale, SupportedSizes*);
183 
184     /**
185      *  Scale the generator's pixels to fit into scaledSize.
186      *  This routine also support retrieving only a subset of the pixels. That subset is specified
187      *  by the following rectangle (in the scaled space):
188      *
189      *      subset = SkIRect::MakeXYWH(subsetOrigin.x(), subsetOrigin.y(),
190      *                                 subsetPixels.width(), subsetPixels.height())
191      *
192      *  If subset is not contained inside the scaledSize, this returns false.
193      *
194      *      whole = SkIRect::MakeWH(scaledSize.width(), scaledSize.height())
195      *      if (!whole.contains(subset)) {
196      *          return false;
197      *      }
198      *
199      *  If the requested colortype/alphatype in pixels is not supported,
200      *  or the requested scaledSize is not supported, or the generator encounters an error,
201      *  this returns false.
202      */
203     bool generateScaledPixels(const SkISize& scaledSize, const SkIPoint& subsetOrigin,
204                               const SkPixmap& subsetPixels);
205 
generateScaledPixels(const SkPixmap & scaledPixels)206     bool generateScaledPixels(const SkPixmap& scaledPixels) {
207         return this->generateScaledPixels(SkISize::Make(scaledPixels.width(),
208                                                         scaledPixels.height()),
209                                           SkIPoint::Make(0, 0), scaledPixels);
210     }
211 
212     /**
213      *  If the default image decoder system can interpret the specified (encoded) data, then
214      *  this returns a new ImageGenerator for it. Otherwise this returns NULL. Either way
215      *  the caller is still responsible for managing their ownership of the data.
216      */
217     static SkImageGenerator* NewFromEncoded(SkData*);
218 
219     /** Return a new image generator backed by the specified picture.  If the size is empty or
220      *  the picture is NULL, this returns NULL.
221      *  The optional matrix and paint arguments are passed to drawPicture() at rasterization
222      *  time.
223      */
224     static SkImageGenerator* NewFromPicture(const SkISize&, const SkPicture*, const SkMatrix*,
225                                             const SkPaint*);
226 
tryGenerateBitmap(SkBitmap * bm)227     bool tryGenerateBitmap(SkBitmap* bm) {
228         return this->tryGenerateBitmap(bm, nullptr, nullptr);
229     }
tryGenerateBitmap(SkBitmap * bm,const SkImageInfo & info,SkBitmap::Allocator * allocator)230     bool tryGenerateBitmap(SkBitmap* bm, const SkImageInfo& info, SkBitmap::Allocator* allocator) {
231         return this->tryGenerateBitmap(bm, &info, allocator);
232     }
generateBitmap(SkBitmap * bm)233     void generateBitmap(SkBitmap* bm) {
234         if (!this->tryGenerateBitmap(bm, nullptr, nullptr)) {
235             sk_throw();
236         }
237     }
generateBitmap(SkBitmap * bm,const SkImageInfo & info)238     void generateBitmap(SkBitmap* bm, const SkImageInfo& info) {
239         if (!this->tryGenerateBitmap(bm, &info, nullptr)) {
240             sk_throw();
241         }
242     }
243 
244 protected:
245     SkImageGenerator(const SkImageInfo& info);
246 
247     virtual SkData* onRefEncodedData(SK_REFENCODEDDATA_CTXPARAM);
248 
249     virtual bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
250                              SkPMColor ctable[], int* ctableCount);
251     virtual bool onGetYUV8Planes(SkISize sizes[3], void* planes[3], size_t rowBytes[3]);
252     virtual bool onGetYUV8Planes(SkISize sizes[3], void* planes[3], size_t rowBytes[3],
253                                  SkYUVColorSpace* colorSpace);
254 
onGenerateTexture(GrContext *,const SkIRect *)255     virtual GrTexture* onGenerateTexture(GrContext*, const SkIRect*) {
256         return nullptr;
257     }
258 
onComputeScaledDimensions(SkScalar,SupportedSizes *)259     virtual bool onComputeScaledDimensions(SkScalar, SupportedSizes*) {
260         return false;
261     }
onGenerateScaledPixels(const SkISize &,const SkIPoint &,const SkPixmap &)262     virtual bool onGenerateScaledPixels(const SkISize&, const SkIPoint&, const SkPixmap&) {
263         return false;
264     }
265 
266     bool tryGenerateBitmap(SkBitmap* bm, const SkImageInfo* optionalInfo, SkBitmap::Allocator*);
267 
268 private:
269     const SkImageInfo fInfo;
270     const uint32_t fUniqueID;
271 
272     // This is our default impl, which may be different on different platforms.
273     // It is called from NewFromEncoded() after it has checked for any runtime factory.
274     // The SkData will never be NULL, as that will have been checked by NewFromEncoded.
275     static SkImageGenerator* NewFromEncodedImpl(SkData*);
276 };
277 
278 #endif  // SkImageGenerator_DEFINED
279