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 info()33 const SkImageInfo& info() const { return fInfo; } uniqueID()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: Make(std::unique_ptr<SkImageGenerator> gen)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: SharedGenerator(std::unique_ptr<SkImageGenerator> gen)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