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