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