Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2015 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 SkImageCacherator_DEFINED
      9 #define SkImageCacherator_DEFINED
     10 
     11 #include "SkImageGenerator.h"
     12 #include "SkMutex.h"
     13 #include "SkTemplates.h"
     14 
     15 class GrCaps;
     16 class GrContext;
     17 class GrSamplerParams;
     18 class GrTextureProxy;
     19 class GrUniqueKey;
     20 class SkBitmap;
     21 class SkImage;
     22 
     23 /*
     24  *  Internal class to manage caching the output of an ImageGenerator.
     25  */
     26 class SkImageCacherator {
     27 public:
     28     static SkImageCacherator* NewFromGenerator(std::unique_ptr<SkImageGenerator>,
     29                                                const SkIRect* subset = nullptr);
     30 
     31     ~SkImageCacherator();
     32 
     33     const SkImageInfo& info() const { return fInfo; }
     34     uint32_t uniqueID() const { return fUniqueIDs[kLegacy_CachedFormat]; }
     35 
     36     enum CachedFormat {
     37         kLegacy_CachedFormat,    // The format from the generator, with any color space stripped out
     38         kAsIs_CachedFormat,      // The format from the generator, with no modification
     39         kLinearF16_CachedFormat, // Half float RGBA with linear gamma
     40         kSRGB8888_CachedFormat,  // sRGB bytes
     41 
     42         kNumCachedFormats,
     43     };
     44 
     45     /**
     46      *  On success (true), bitmap will point to the pixels for this generator. If this returns
     47      *  false, the bitmap will be reset to empty.
     48      *
     49      *  If not NULL, the client will be notified (->notifyAddedToCache()) when resources are
     50      *  added to the cache on its behalf.
     51      */
     52     bool lockAsBitmap(GrContext*, SkBitmap*, const SkImage* client, SkColorSpace* dstColorSpace,
     53                       SkImage::CachingHint = SkImage::kAllow_CachingHint);
     54 
     55 #if SK_SUPPORT_GPU
     56     /**
     57      *  Returns a ref() on the texture produced by this generator. The caller must call unref()
     58      *  when it is done. Will return nullptr on failure.
     59      *
     60      *  If not NULL, the client will be notified (->notifyAddedToCache()) when resources are
     61      *  added to the cache on its behalf.
     62      *
     63      *  The caller is responsible for calling proxy->unref() when they are done.
     64      *
     65      *  The scaleAdjust in/out parameter will return any scale adjustment that needs
     66      *  to be applied to the absolute texture coordinates in the case where the image
     67      *  was resized to meet the sampling requirements (e.g., resized out to the next power of 2).
     68      *  It can be null if the caller knows resizing will not be required.
     69      */
     70     sk_sp<GrTextureProxy> lockAsTextureProxy(GrContext*, const GrSamplerParams&,
     71                                              SkColorSpace* dstColorSpace,
     72                                              sk_sp<SkColorSpace>* texColorSpace,
     73                                              const SkImage* client,
     74                                              SkScalar scaleAdjust[2],
     75                                              SkImage::CachingHint = SkImage::kAllow_CachingHint);
     76 #endif
     77 
     78     /**
     79      *  If the underlying src naturally is represented by an encoded blob (in SkData), this returns
     80      *  a ref to that data. If not, it returns null.
     81      *
     82      *  If a GrContext is specified, then the caller is only interested in gpu-specific encoded
     83      *  formats, so others (e.g. PNG) can just return nullptr.
     84      */
     85     SkData* refEncoded(GrContext*);
     86 
     87     // Only return true if the generate has already been cached.
     88     bool lockAsBitmapOnlyIfAlreadyCached(SkBitmap*, CachedFormat);
     89     // Call the underlying generator directly
     90     bool directGeneratePixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
     91                               int srcX, int srcY);
     92 
     93 private:
     94     // Ref-counted tuple(SkImageGenerator, SkMutex) which allows sharing of one generator
     95     // among several cacherators.
     96     class SharedGenerator final : public SkNVRefCnt<SharedGenerator> {
     97     public:
     98         static sk_sp<SharedGenerator> Make(std::unique_ptr<SkImageGenerator> gen) {
     99             return gen ? sk_sp<SharedGenerator>(new SharedGenerator(std::move(gen))) : nullptr;
    100         }
    101 
    102     private:
    103         explicit SharedGenerator(std::unique_ptr<SkImageGenerator> gen)
    104             : fGenerator(std::move(gen))
    105         {
    106             SkASSERT(fGenerator);
    107         }
    108 
    109         friend class ScopedGenerator;
    110         friend class SkImageCacherator;
    111 
    112         std::unique_ptr<SkImageGenerator> fGenerator;
    113         SkMutex                           fMutex;
    114     };
    115     class ScopedGenerator;
    116 
    117     struct Validator {
    118         Validator(sk_sp<SharedGenerator>, const SkIRect* subset);
    119 
    120         operator bool() const { return fSharedGenerator.get(); }
    121 
    122         sk_sp<SharedGenerator> fSharedGenerator;
    123         SkImageInfo            fInfo;
    124         SkIPoint               fOrigin;
    125         uint32_t               fUniqueID;
    126     };
    127 
    128     SkImageCacherator(Validator*);
    129 
    130     CachedFormat chooseCacheFormat(SkColorSpace* dstColorSpace, const GrCaps* = nullptr);
    131     SkImageInfo buildCacheInfo(CachedFormat);
    132 
    133     bool generateBitmap(SkBitmap*, const SkImageInfo&);
    134     bool tryLockAsBitmap(SkBitmap*, const SkImage*, SkImage::CachingHint, CachedFormat,
    135                          const SkImageInfo&);
    136 #if SK_SUPPORT_GPU
    137     // Returns the texture proxy. If the cacherator is generating the texture and wants to cache it,
    138     // it should use the passed in key (if the key is valid).
    139     sk_sp<GrTextureProxy> lockTextureProxy(GrContext*,
    140                                            const GrUniqueKey& key,
    141                                            const SkImage* client,
    142                                            SkImage::CachingHint,
    143                                            bool willBeMipped,
    144                                            SkColorSpace* dstColorSpace);
    145     // Returns the color space of the texture that would be returned if you called lockTexture.
    146     // Separate code path to allow querying of the color space for textures that cached (even
    147     // externally).
    148     sk_sp<SkColorSpace> getColorSpace(GrContext*, SkColorSpace* dstColorSpace);
    149     void makeCacheKeyFromOrigKey(const GrUniqueKey& origKey, CachedFormat, GrUniqueKey* cacheKey);
    150 #endif
    151 
    152     sk_sp<SharedGenerator> fSharedGenerator;
    153     const SkImageInfo      fInfo;
    154     const SkIPoint         fOrigin;
    155     uint32_t               fUniqueIDs[kNumCachedFormats];
    156 
    157     friend class GrImageTextureMaker;
    158     friend class SkImage;
    159     friend class SkImage_Generator;
    160 };
    161 
    162 #endif
    163