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 "GrTextureAdjuster.h" 9 10 #include "GrColorSpaceXform.h" 11 #include "GrContext.h" 12 #include "GrContextPriv.h" 13 #include "GrGpu.h" 14 #include "GrProxyProvider.h" 15 #include "SkGr.h" 16 17 GrTextureAdjuster::GrTextureAdjuster(GrContext* context, sk_sp<GrTextureProxy> original, 18 SkAlphaType alphaType, 19 uint32_t uniqueID, 20 SkColorSpace* cs) 21 : INHERITED(original->width(), original->height(), 22 GrPixelConfigIsAlphaOnly(original->config())) 23 , fContext(context) 24 , fOriginal(std::move(original)) 25 , fAlphaType(alphaType) 26 , fColorSpace(cs) 27 , fUniqueID(uniqueID) {} 28 29 void GrTextureAdjuster::makeCopyKey(const CopyParams& params, GrUniqueKey* copyKey, 30 SkColorSpace* dstColorSpace) { 31 // Destination color space is irrelevant - we already have a texture so we're just sub-setting 32 GrUniqueKey baseKey; 33 GrMakeKeyFromImageID(&baseKey, fUniqueID, SkIRect::MakeWH(this->width(), this->height())); 34 MakeCopyKeyFromOrigKey(baseKey, params, copyKey); 35 } 36 37 void GrTextureAdjuster::didCacheCopy(const GrUniqueKey& copyKey) { 38 // We don't currently have a mechanism for notifications on Images! 39 } 40 41 sk_sp<GrTextureProxy> GrTextureAdjuster::refTextureProxyCopy(const CopyParams& copyParams, 42 bool willBeMipped) { 43 GrProxyProvider* proxyProvider = fContext->contextPriv().proxyProvider(); 44 45 GrUniqueKey key; 46 this->makeCopyKey(copyParams, &key, nullptr); 47 if (key.isValid()) { 48 sk_sp<GrTextureProxy> cachedCopy = 49 proxyProvider->findOrCreateProxyByUniqueKey(key, this->originalProxy()->origin()); 50 if (cachedCopy) { 51 return cachedCopy; 52 } 53 } 54 55 sk_sp<GrTextureProxy> proxy = this->originalProxyRef(); 56 57 sk_sp<GrTextureProxy> copy = CopyOnGpu(fContext, std::move(proxy), copyParams, willBeMipped); 58 if (copy) { 59 if (key.isValid()) { 60 SkASSERT(copy->origin() == this->originalProxy()->origin()); 61 proxyProvider->assignUniqueKeyToProxy(key, copy.get()); 62 this->didCacheCopy(key); 63 } 64 } 65 return copy; 66 } 67 68 sk_sp<GrTextureProxy> GrTextureAdjuster::onRefTextureProxyForParams( 69 const GrSamplerState& params, 70 SkColorSpace* dstColorSpace, 71 sk_sp<SkColorSpace>* texColorSpace, 72 SkScalar scaleAdjust[2]) { 73 sk_sp<GrTextureProxy> proxy = this->originalProxyRef(); 74 CopyParams copyParams; 75 76 if (!fContext) { 77 // The texture was abandoned. 78 return nullptr; 79 } 80 81 if (texColorSpace) { 82 *texColorSpace = sk_ref_sp(fColorSpace); 83 } 84 85 GrGpu* gpu = fContext->contextPriv().getGpu(); 86 if (!gpu) { 87 return proxy; 88 } 89 90 if (!gpu->isACopyNeededForTextureParams(proxy.get(), params, ©Params, scaleAdjust)) { 91 return proxy; 92 } 93 94 bool willBeMipped = GrSamplerState::Filter::kMipMap == params.filter(); 95 return this->refTextureProxyCopy(copyParams, willBeMipped); 96 } 97 98 std::unique_ptr<GrFragmentProcessor> GrTextureAdjuster::createFragmentProcessor( 99 const SkMatrix& origTextureMatrix, 100 const SkRect& constraintRect, 101 FilterConstraint filterConstraint, 102 bool coordsLimitedToConstraintRect, 103 const GrSamplerState::Filter* filterOrNullForBicubic, 104 SkColorSpace* dstColorSpace) { 105 SkMatrix textureMatrix = origTextureMatrix; 106 107 SkRect domain; 108 GrSamplerState samplerState; 109 if (filterOrNullForBicubic) { 110 samplerState.setFilterMode(*filterOrNullForBicubic); 111 } 112 SkScalar scaleAdjust[2] = { 1.0f, 1.0f }; 113 sk_sp<GrTextureProxy> proxy( 114 this->refTextureProxyForParams(samplerState, nullptr, nullptr, scaleAdjust)); 115 if (!proxy) { 116 return nullptr; 117 } 118 // If we made a copy then we only copied the contentArea, in which case the new texture is all 119 // content. 120 if (proxy.get() != this->originalProxy()) { 121 textureMatrix.postScale(scaleAdjust[0], scaleAdjust[1]); 122 } 123 124 DomainMode domainMode = 125 DetermineDomainMode(constraintRect, filterConstraint, coordsLimitedToConstraintRect, 126 proxy.get(), filterOrNullForBicubic, &domain); 127 if (kTightCopy_DomainMode == domainMode) { 128 // TODO: Copy the texture and adjust the texture matrix (both parts need to consider 129 // non-int constraint rect) 130 // For now: treat as bilerp and ignore what goes on above level 0. 131 132 // We only expect MIP maps to require a tight copy. 133 SkASSERT(filterOrNullForBicubic && 134 GrSamplerState::Filter::kMipMap == *filterOrNullForBicubic); 135 static const GrSamplerState::Filter kBilerp = GrSamplerState::Filter::kBilerp; 136 domainMode = 137 DetermineDomainMode(constraintRect, filterConstraint, coordsLimitedToConstraintRect, 138 proxy.get(), &kBilerp, &domain); 139 SkASSERT(kTightCopy_DomainMode != domainMode); 140 } 141 SkASSERT(kNoDomain_DomainMode == domainMode || 142 (domain.fLeft <= domain.fRight && domain.fTop <= domain.fBottom)); 143 GrPixelConfig config = proxy->config(); 144 auto fp = CreateFragmentProcessorForDomainAndFilter(std::move(proxy), textureMatrix, 145 domainMode, domain, filterOrNullForBicubic); 146 return GrColorSpaceXformEffect::Make(std::move(fp), fColorSpace, config, dstColorSpace); 147 } 148