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 GrTextureMaker_DEFINED 9 #define GrTextureMaker_DEFINED 10 11 #include "GrTextureParams.h" 12 #include "GrResourceKey.h" 13 #include "GrTexture.h" 14 #include "SkTLazy.h" 15 16 class GrContext; 17 class GrTextureParams; 18 class GrUniqueKey; 19 class SkBitmap; 20 21 /** 22 * Different GPUs and API extensions have different requirements with respect to what texture 23 * sampling parameters may be used with textures of various types. This class facilitates making 24 * texture compatible with a given GrTextureParams. There are two immediate subclasses defined 25 * below. One is a base class for sources that are inherently texture-backed (e.g. a texture-backed 26 * SkImage). It supports subsetting the original texture. The other is for use cases where the 27 * source can generate a texture that represents some content (e.g. cpu pixels, SkPicture, ...). 28 */ 29 class GrTextureProducer : public SkNoncopyable { 30 public: 31 struct CopyParams { 32 GrTextureParams::FilterMode fFilter; 33 int fWidth; 34 int fHeight; 35 }; 36 37 enum FilterConstraint { 38 kYes_FilterConstraint, 39 kNo_FilterConstraint, 40 }; 41 42 /** 43 * Helper for creating a fragment processor to sample the texture with a given filtering mode. 44 * It attempts to avoid making texture copies or using domains whenever possible. 45 * 46 * @param textureMatrix Matrix used to access the texture. It is applied to 47 * the local coords. The post-transformed coords should 48 * be in texel units (rather than normalized) with 49 * respect to this Producer's bounds (width()/height()). 50 * @param constraintRect A rect that represents the area of the texture to be 51 * sampled. It must be contained in the Producer's bounds 52 * as defined by width()/height(). 53 * @param filterConstriant Indicates whether filtering is limited to 54 * constraintRect. 55 * @param coordsLimitedToConstraintRect Is it known that textureMatrix*localCoords is bound 56 * by the portion of the texture indicated by 57 * constraintRect (without consideration of filter 58 * width, just the raw coords). 59 * @param filterOrNullForBicubic If non-null indicates the filter mode. If null means 60 * use bicubic filtering. 61 **/ 62 virtual sk_sp<GrFragmentProcessor> createFragmentProcessor( 63 const SkMatrix& textureMatrix, 64 const SkRect& constraintRect, 65 FilterConstraint filterConstraint, 66 bool coordsLimitedToConstraintRect, 67 const GrTextureParams::FilterMode* filterOrNullForBicubic, 68 SkColorSpace* dstColorSpace, 69 SkSourceGammaTreatment) = 0; 70 ~GrTextureProducer()71 virtual ~GrTextureProducer() {} 72 width()73 int width() const { return fWidth; } height()74 int height() const { return fHeight; } isAlphaOnly()75 bool isAlphaOnly() const { return fIsAlphaOnly; } 76 virtual SkAlphaType alphaType() const = 0; 77 virtual SkColorSpace* getColorSpace() = 0; 78 79 protected: GrTextureProducer(int width,int height,bool isAlphaOnly)80 GrTextureProducer(int width, int height, bool isAlphaOnly) 81 : fWidth(width) 82 , fHeight(height) 83 , fIsAlphaOnly(isAlphaOnly) {} 84 85 /** Helper for creating a key for a copy from an original key. */ MakeCopyKeyFromOrigKey(const GrUniqueKey & origKey,const CopyParams & copyParams,GrUniqueKey * copyKey)86 static void MakeCopyKeyFromOrigKey(const GrUniqueKey& origKey, 87 const CopyParams& copyParams, 88 GrUniqueKey* copyKey) { 89 SkASSERT(!copyKey->isValid()); 90 if (origKey.isValid()) { 91 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); 92 GrUniqueKey::Builder builder(copyKey, origKey, kDomain, 3); 93 builder[0] = copyParams.fFilter; 94 builder[1] = copyParams.fWidth; 95 builder[2] = copyParams.fHeight; 96 } 97 } 98 99 /** 100 * If we need to make a copy in order to be compatible with GrTextureParams producer is asked to 101 * return a key that identifies its original content + the CopyParms parameter. If the producer 102 * does not want to cache the stretched version (e.g. the producer is volatile), this should 103 * simply return without initializing the copyKey. 104 */ 105 virtual void makeCopyKey(const CopyParams&, GrUniqueKey* copyKey) = 0; 106 107 /** 108 * If a stretched version of the texture is generated, it may be cached (assuming that 109 * makeCopyKey() returns true). In that case, the maker is notified in case it 110 * wants to note that for when the maker is destroyed. 111 */ 112 virtual void didCacheCopy(const GrUniqueKey& copyKey) = 0; 113 114 private: 115 const int fWidth; 116 const int fHeight; 117 const bool fIsAlphaOnly; 118 119 typedef SkNoncopyable INHERITED; 120 }; 121 122 /** 123 * Base class for sources that start out as textures. Optionally allows for a content area subrect. 124 * The intent is not to use content area for subrect rendering. Rather, the pixels outside the 125 * content area have undefined values and shouldn't be read *regardless* of filtering mode or 126 * the SkCanvas::SrcRectConstraint used for subrect draws. 127 */ 128 class GrTextureAdjuster : public GrTextureProducer { 129 public: 130 /** Makes the subset of the texture safe to use with the given texture parameters. 131 outOffset will be the top-left corner of the subset if a copy is not made. Otherwise, 132 the copy will be tight to the contents and outOffset will be (0, 0). If the copy's size 133 does not match subset's dimensions then the contents are scaled to fit the copy.*/ 134 GrTexture* refTextureSafeForParams(const GrTextureParams&, SkSourceGammaTreatment, 135 SkIPoint* outOffset); 136 137 sk_sp<GrFragmentProcessor> createFragmentProcessor( 138 const SkMatrix& textureMatrix, 139 const SkRect& constraintRect, 140 FilterConstraint, 141 bool coordsLimitedToConstraintRect, 142 const GrTextureParams::FilterMode* filterOrNullForBicubic, 143 SkColorSpace* dstColorSpace, 144 SkSourceGammaTreatment) override; 145 146 // We do not ref the texture nor the colorspace, so the caller must keep them in scope while 147 // this Adjuster is alive. 148 GrTextureAdjuster(GrTexture*, SkAlphaType, const SkIRect& area, uint32_t uniqueID, 149 SkColorSpace*); 150 151 protected: alphaType()152 SkAlphaType alphaType() const override { return fAlphaType; } 153 SkColorSpace* getColorSpace() override; 154 void makeCopyKey(const CopyParams& params, GrUniqueKey* copyKey) override; 155 void didCacheCopy(const GrUniqueKey& copyKey) override; 156 originalTexture()157 GrTexture* originalTexture() const { return fOriginal; } 158 159 /** Returns the content area or null for the whole original texture */ contentAreaOrNull()160 const SkIRect* contentAreaOrNull() { return fContentArea.getMaybeNull(); } 161 162 private: 163 SkTLazy<SkIRect> fContentArea; 164 GrTexture* fOriginal; 165 SkAlphaType fAlphaType; 166 SkColorSpace* fColorSpace; 167 uint32_t fUniqueID; 168 169 GrTexture* refCopy(const CopyParams ©Params); 170 171 typedef GrTextureProducer INHERITED; 172 }; 173 174 /** 175 * Base class for sources that start out as something other than a texture (encoded image, 176 * picture, ...). 177 */ 178 class GrTextureMaker : public GrTextureProducer { 179 public: 180 /** Returns a texture that is safe for use with the params. If the size of the returned texture 181 does not match width()/height() then the contents of the original must be scaled to fit 182 the texture. */ 183 GrTexture* refTextureForParams(const GrTextureParams&, SkSourceGammaTreatment); 184 185 sk_sp<GrFragmentProcessor> createFragmentProcessor( 186 const SkMatrix& textureMatrix, 187 const SkRect& constraintRect, 188 FilterConstraint filterConstraint, 189 bool coordsLimitedToConstraintRect, 190 const GrTextureParams::FilterMode* filterOrNullForBicubic, 191 SkColorSpace* dstColorSpace, 192 SkSourceGammaTreatment) override; 193 194 protected: GrTextureMaker(GrContext * context,int width,int height,bool isAlphaOnly)195 GrTextureMaker(GrContext* context, int width, int height, bool isAlphaOnly) 196 : INHERITED(width, height, isAlphaOnly) 197 , fContext(context) {} 198 199 /** 200 * Return the maker's "original" texture. It is the responsibility of the maker to handle any 201 * caching of the original if desired. 202 */ 203 virtual GrTexture* refOriginalTexture(bool willBeMipped, SkSourceGammaTreatment) = 0; 204 205 /** 206 * Return a new (uncached) texture that is the stretch of the maker's original. 207 * 208 * The base-class handles general logic for this, and only needs access to the following 209 * method: 210 * - refOriginalTexture() 211 * 212 * Subclass may override this if they can handle creating the texture more directly than 213 * by copying. 214 */ 215 virtual GrTexture* generateTextureForParams(const CopyParams&, bool willBeMipped, 216 SkSourceGammaTreatment); 217 context()218 GrContext* context() const { return fContext; } 219 220 private: 221 GrContext* fContext; 222 223 typedef GrTextureProducer INHERITED; 224 }; 225 226 #endif 227