Home | History | Annotate | Download | only in core
      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      */
     67     virtual ~SkImageGenerator() { }
     68 
     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      */
     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 
    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 
    227     bool tryGenerateBitmap(SkBitmap* bm) {
    228         return this->tryGenerateBitmap(bm, nullptr, nullptr);
    229     }
    230     bool tryGenerateBitmap(SkBitmap* bm, const SkImageInfo& info, SkBitmap::Allocator* allocator) {
    231         return this->tryGenerateBitmap(bm, &info, allocator);
    232     }
    233     void generateBitmap(SkBitmap* bm) {
    234         if (!this->tryGenerateBitmap(bm, nullptr, nullptr)) {
    235             sk_throw();
    236         }
    237     }
    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 
    255     virtual GrTexture* onGenerateTexture(GrContext*, const SkIRect*) {
    256         return nullptr;
    257     }
    258 
    259     virtual bool onComputeScaledDimensions(SkScalar, SupportedSizes*) {
    260         return false;
    261     }
    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