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 #include "GrTextureMaker.h" 9 10 #include "GrColorSpaceXform.h" 11 #include "GrContext.h" 12 #include "GrContextPriv.h" 13 #include "GrGpu.h" 14 #include "GrProxyProvider.h" 15 16 sk_sp<GrTextureProxy> GrTextureMaker::onRefTextureProxyForParams(const GrSamplerState& params, 17 bool willBeMipped, 18 SkScalar scaleAdjust[2]) { 19 if (this->width() > fContext->contextPriv().caps()->maxTextureSize() || 20 this->height() > fContext->contextPriv().caps()->maxTextureSize()) { 21 return nullptr; 22 } 23 24 CopyParams copyParams; 25 26 sk_sp<GrTextureProxy> original(this->refOriginalTextureProxy(willBeMipped, 27 AllowedTexGenType::kCheap)); 28 bool needsCopyForMipsOnly = false; 29 if (original) { 30 if (!params.isRepeated() || 31 !GrGpu::IsACopyNeededForRepeatWrapMode(fContext->contextPriv().caps(), original.get(), 32 original->width(), original->height(), 33 params.filter(), ©Params, scaleAdjust)) { 34 needsCopyForMipsOnly = GrGpu::IsACopyNeededForMips(fContext->contextPriv().caps(), 35 original.get(), params.filter(), 36 ©Params); 37 if (!needsCopyForMipsOnly) { 38 return original; 39 } 40 } 41 } else { 42 if (!params.isRepeated() || 43 !GrGpu::IsACopyNeededForRepeatWrapMode(fContext->contextPriv().caps(), nullptr, 44 this->width(), this->height(), 45 params.filter(), ©Params, scaleAdjust)) { 46 return this->refOriginalTextureProxy(willBeMipped, AllowedTexGenType::kAny); 47 } 48 } 49 50 GrProxyProvider* proxyProvider = fContext->contextPriv().proxyProvider(); 51 52 GrSurfaceOrigin origOrigin = original ? original->origin() : kTopLeft_GrSurfaceOrigin; 53 GrUniqueKey copyKey; 54 this->makeCopyKey(copyParams, ©Key); 55 sk_sp<GrTextureProxy> cachedProxy; 56 if (copyKey.isValid()) { 57 cachedProxy = proxyProvider->findOrCreateProxyByUniqueKey(copyKey, origOrigin); 58 if (cachedProxy && (!willBeMipped || GrMipMapped::kYes == cachedProxy->mipMapped())) { 59 return cachedProxy; 60 } 61 } 62 63 sk_sp<GrTextureProxy> source; 64 if (original) { 65 source = std::move(original); 66 } else if (cachedProxy) { 67 source = cachedProxy; 68 } else { 69 // Since we will be copying this texture there is no reason to make it mipped 70 source = this->refOriginalTextureProxy(false, AllowedTexGenType::kAny); 71 } 72 73 if (!source) { 74 return nullptr; 75 } 76 77 sk_sp<GrTextureProxy> result = CopyOnGpu(fContext, source, copyParams, willBeMipped); 78 79 if (!result) { 80 // If we were unable to make a copy and we only needed a copy for mips, then we will return 81 // the source texture here and require that the GPU backend is able to fall back to using 82 // bilerp if mips are required. 83 if (needsCopyForMipsOnly) { 84 return source; 85 } 86 return nullptr; 87 } 88 89 if (copyKey.isValid()) { 90 SkASSERT(result->origin() == origOrigin); 91 if (cachedProxy) { 92 SkASSERT(GrMipMapped::kYes == result->mipMapped() && 93 GrMipMapped::kNo == cachedProxy->mipMapped()); 94 // If we had a cachedProxy, that means there already is a proxy in the cache which 95 // matches the key, but it does not have mip levels and we require them. Thus we must 96 // remove the unique key from that proxy. 97 SkASSERT(cachedProxy->getUniqueKey() == copyKey); 98 proxyProvider->removeUniqueKeyFromProxy(cachedProxy.get()); 99 } 100 proxyProvider->assignUniqueKeyToProxy(copyKey, result.get()); 101 this->didCacheCopy(copyKey, proxyProvider->contextUniqueID()); 102 } 103 return result; 104 } 105 106 std::unique_ptr<GrFragmentProcessor> GrTextureMaker::createFragmentProcessor( 107 const SkMatrix& textureMatrix, 108 const SkRect& constraintRect, 109 FilterConstraint filterConstraint, 110 bool coordsLimitedToConstraintRect, 111 const GrSamplerState::Filter* filterOrNullForBicubic) { 112 const GrSamplerState::Filter* fmForDetermineDomain = filterOrNullForBicubic; 113 if (filterOrNullForBicubic && GrSamplerState::Filter::kMipMap == *filterOrNullForBicubic && 114 kYes_FilterConstraint == filterConstraint) { 115 // TODo: Here we should force a copy restricted to the constraintRect since MIP maps will 116 // read outside the constraint rect. However, as in the adjuster case, we aren't currently 117 // doing that. 118 // We instead we compute the domain as though were bilerping which is only correct if we 119 // only sample level 0. 120 static const GrSamplerState::Filter kBilerp = GrSamplerState::Filter::kBilerp; 121 fmForDetermineDomain = &kBilerp; 122 } 123 124 GrSamplerState samplerState; 125 if (filterOrNullForBicubic) { 126 samplerState = GrSamplerState(GrSamplerState::WrapMode::kClamp, *filterOrNullForBicubic); 127 } else { 128 // Bicubic doesn't use filtering for it's texture accesses. 129 samplerState = GrSamplerState::ClampNearest(); 130 } 131 SkScalar scaleAdjust[2] = { 1.0f, 1.0f }; 132 sk_sp<GrTextureProxy> proxy(this->refTextureProxyForParams(samplerState, scaleAdjust)); 133 if (!proxy) { 134 return nullptr; 135 } 136 SkMatrix adjustedMatrix = textureMatrix; 137 adjustedMatrix.postScale(scaleAdjust[0], scaleAdjust[1]); 138 SkRect domain; 139 DomainMode domainMode = 140 DetermineDomainMode(constraintRect, filterConstraint, coordsLimitedToConstraintRect, 141 proxy.get(), fmForDetermineDomain, &domain); 142 SkASSERT(kTightCopy_DomainMode != domainMode); 143 return CreateFragmentProcessorForDomainAndFilter(std::move(proxy), adjustedMatrix, domainMode, 144 domain, filterOrNullForBicubic); 145 } 146