1 /* 2 * Copyright 2016 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 GrTextureProducer_DEFINED 9 #define GrTextureProducer_DEFINED 10 11 #include "GrResourceKey.h" 12 #include "GrSamplerState.h" 13 #include "SkImageInfo.h" 14 #include "SkNoncopyable.h" 15 16 class GrFragmentProcessor; 17 class GrRecordingContext; 18 class GrTexture; 19 class GrTextureProxy; 20 class SkColorSpace; 21 class SkMatrix; 22 struct SkRect; 23 24 /** 25 * Different GPUs and API extensions have different requirements with respect to what texture 26 * sampling parameters may be used with textures of various types. This class facilitates making 27 * texture compatible with a given GrSamplerState. There are two immediate subclasses defined 28 * below. One is a base class for sources that are inherently texture-backed (e.g. a texture-backed 29 * SkImage). It supports subsetting the original texture. The other is for use cases where the 30 * source can generate a texture that represents some content (e.g. cpu pixels, SkPicture, ...). 31 */ 32 class GrTextureProducer : public SkNoncopyable { 33 public: 34 struct CopyParams { 35 GrSamplerState::Filter fFilter; 36 int fWidth; 37 int fHeight; 38 }; 39 40 enum FilterConstraint { 41 kYes_FilterConstraint, 42 kNo_FilterConstraint, 43 }; 44 45 /** 46 * Helper for creating a fragment processor to sample the texture with a given filtering mode. 47 * It attempts to avoid making texture copies or using domains whenever possible. 48 * 49 * @param textureMatrix Matrix used to access the texture. It is applied to 50 * the local coords. The post-transformed coords should 51 * be in texel units (rather than normalized) with 52 * respect to this Producer's bounds (width()/height()). 53 * @param constraintRect A rect that represents the area of the texture to be 54 * sampled. It must be contained in the Producer's 55 * bounds as defined by width()/height(). 56 * @param filterConstriant Indicates whether filtering is limited to 57 * constraintRect. 58 * @param coordsLimitedToConstraintRect Is it known that textureMatrix*localCoords is bound 59 * by the portion of the texture indicated by 60 * constraintRect (without consideration of filter 61 * width, just the raw coords). 62 * @param filterOrNullForBicubic If non-null indicates the filter mode. If null means 63 * use bicubic filtering. 64 **/ 65 virtual std::unique_ptr<GrFragmentProcessor> createFragmentProcessor( 66 const SkMatrix& textureMatrix, 67 const SkRect& constraintRect, 68 FilterConstraint filterConstraint, 69 bool coordsLimitedToConstraintRect, 70 const GrSamplerState::Filter* filterOrNullForBicubic) = 0; 71 72 /** 73 * Returns a texture that is safe for use with the params. 74 * 75 * If the size of the returned texture does not match width()/height() then the contents of the 76 * original may have been scaled to fit the texture or the original may have been copied into 77 * a subrect of the copy. 'scaleAdjust' must be applied to the normalized texture coordinates 78 * in order to correct for the latter case. 79 * 80 * If the GrSamplerState is known to clamp and use kNearest or kBilerp filter mode then the 81 * proxy will always be unscaled and nullptr can be passed for scaleAdjust. There is a weird 82 * contract that if scaleAdjust is not null it must be initialized to {1, 1} before calling 83 * this method. (TODO: Fix this and make this function always initialize scaleAdjust). 84 */ 85 sk_sp<GrTextureProxy> refTextureProxyForParams(const GrSamplerState&, 86 SkScalar scaleAdjust[2]); 87 88 sk_sp<GrTextureProxy> refTextureProxyForParams( 89 const GrSamplerState::Filter* filterOrNullForBicubic, SkScalar scaleAdjust[2]); 90 91 /** 92 * Returns a texture. If willNeedMips is true then the returned texture is guaranteed to have 93 * allocated mip map levels. This can be a performance win if future draws with the texture 94 * require mip maps. 95 */ 96 // TODO: Once we remove support for npot textures, we should add a flag for must support repeat 97 // wrap mode. To support that flag now would require us to support scaleAdjust array like in 98 // refTextureProxyForParams, however the current public API that uses this call does not expose 99 // that array. 100 sk_sp<GrTextureProxy> refTextureProxy(GrMipMapped willNeedMips); 101 ~GrTextureProducer()102 virtual ~GrTextureProducer() {} 103 width()104 int width() const { return fWidth; } height()105 int height() const { return fHeight; } isAlphaOnly()106 bool isAlphaOnly() const { return fIsAlphaOnly; } domainNeedsDecal()107 bool domainNeedsDecal() const { return fDomainNeedsDecal; } 108 virtual SkAlphaType alphaType() const = 0; 109 virtual SkColorSpace* colorSpace() const = 0; 110 111 protected: 112 friend class GrTextureProducer_TestAccess; 113 GrTextureProducer(GrRecordingContext * context,int width,int height,bool isAlphaOnly,bool domainNeedsDecal)114 GrTextureProducer(GrRecordingContext* context, int width, int height, bool isAlphaOnly, 115 bool domainNeedsDecal) 116 : fContext(context) 117 , fWidth(width) 118 , fHeight(height) 119 , fIsAlphaOnly(isAlphaOnly) 120 , fDomainNeedsDecal(domainNeedsDecal) {} 121 122 /** Helper for creating a key for a copy from an original key. */ MakeCopyKeyFromOrigKey(const GrUniqueKey & origKey,const CopyParams & copyParams,GrUniqueKey * copyKey)123 static void MakeCopyKeyFromOrigKey(const GrUniqueKey& origKey, 124 const CopyParams& copyParams, 125 GrUniqueKey* copyKey) { 126 SkASSERT(!copyKey->isValid()); 127 if (origKey.isValid()) { 128 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); 129 GrUniqueKey::Builder builder(copyKey, origKey, kDomain, 3); 130 builder[0] = static_cast<uint32_t>(copyParams.fFilter); 131 builder[1] = copyParams.fWidth; 132 builder[2] = copyParams.fHeight; 133 } 134 } 135 136 /** 137 * If we need to make a copy in order to be compatible with GrTextureParams producer is asked to 138 * return a key that identifies its original content + the CopyParms parameter. If the producer 139 * does not want to cache the stretched version (e.g. the producer is volatile), this should 140 * simply return without initializing the copyKey. If the texture generated by this producer 141 * depends on the destination color space, then that information should also be incorporated 142 * in the key. 143 */ 144 virtual void makeCopyKey(const CopyParams&, GrUniqueKey* copyKey) = 0; 145 146 /** 147 * If a stretched version of the texture is generated, it may be cached (assuming that 148 * makeCopyKey() returns true). In that case, the maker is notified in case it 149 * wants to note that for when the maker is destroyed. 150 */ 151 virtual void didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) = 0; 152 153 enum DomainMode { 154 kNoDomain_DomainMode, 155 kDomain_DomainMode, 156 kTightCopy_DomainMode 157 }; 158 159 // This can draw to accomplish the copy, thus the recording context is needed 160 static sk_sp<GrTextureProxy> CopyOnGpu(GrRecordingContext*, sk_sp<GrTextureProxy> inputProxy, 161 const CopyParams& copyParams, 162 bool dstWillRequireMipMaps); 163 164 static DomainMode DetermineDomainMode(const SkRect& constraintRect, 165 FilterConstraint filterConstraint, 166 bool coordsLimitedToConstraintRect, 167 GrTextureProxy*, 168 const GrSamplerState::Filter* filterModeOrNullForBicubic, 169 SkRect* domainRect); 170 171 std::unique_ptr<GrFragmentProcessor> createFragmentProcessorForDomainAndFilter( 172 sk_sp<GrTextureProxy> proxy, 173 const SkMatrix& textureMatrix, 174 DomainMode, 175 const SkRect& domain, 176 const GrSamplerState::Filter* filterOrNullForBicubic); 177 context()178 GrRecordingContext* context() const { return fContext; } 179 180 private: 181 virtual sk_sp<GrTextureProxy> onRefTextureProxyForParams(const GrSamplerState&, 182 bool willBeMipped, 183 SkScalar scaleAdjust[2]) = 0; 184 185 GrRecordingContext* fContext; 186 const int fWidth; 187 const int fHeight; 188 const bool fIsAlphaOnly; 189 // If true, any domain effect uses kDecal instead of kClamp, and sampler filter uses 190 // kClampToBorder instead of kClamp. 191 const bool fDomainNeedsDecal; 192 193 typedef SkNoncopyable INHERITED; 194 }; 195 196 #endif 197