sk_sp<GrTextureProxy> GrTextureProducer::refTextureProxyForParams( const GrSamplerState& sampler, SkColorSpace* dstColorSpace, sk_sp<SkColorSpace>* proxyColorSpace, SkScalar scaleAdjust[2]) { // Check that the caller pre-initialized scaleAdjust SkASSERT(!scaleAdjust || (scaleAdjust[0] == 1 && scaleAdjust[1] == 1)); // Check that if the caller passed nullptr for scaleAdjust that we're in the case where there // can be no scaling. SkDEBUGCODE(bool expectNoScale = (sampler.filter() != GrSamplerState::Filter::kMipMap && !sampler.isRepeated())); SkASSERT(scaleAdjust || expectNoScale); int mipCount = SkMipMap::ComputeLevelCount(this->width(), this->height()); bool willBeMipped = GrSamplerState::Filter::kMipMap == sampler.filter() && mipCount && fContext->contextPriv().caps()->mipMapSupport(); auto result = this->onRefTextureProxyForParams(sampler, dstColorSpace, proxyColorSpace, willBeMipped, scaleAdjust); // Check to make sure that if we say the texture willBeMipped that the returned texture has mip // maps, unless the config is not copyable. SkASSERT(!result || !willBeMipped || result->mipMapped() == GrMipMapped::kYes || !fContext->contextPriv().caps()->isConfigCopyable(result->config())); // Check that the "no scaling expected" case always returns a proxy of the same size as the // producer. SkASSERT(!result || !expectNoScale || (result->width() == this->width() && result->height() == this->height())); return result; }
std::unique_ptr<GrFragmentProcessor> GrTextureAdjuster::createFragmentProcessor( const SkMatrix& origTextureMatrix, const SkRect& constraintRect, FilterConstraint filterConstraint, bool coordsLimitedToConstraintRect, const GrSamplerState::Filter* filterOrNullForBicubic, SkColorSpace* dstColorSpace) { SkMatrix textureMatrix = origTextureMatrix; SkRect domain; GrSamplerState samplerState; if (filterOrNullForBicubic) { samplerState.setFilterMode(*filterOrNullForBicubic); } SkScalar scaleAdjust[2] = { 1.0f, 1.0f }; sk_sp<GrTextureProxy> proxy( this->refTextureProxySafeForParams(samplerState, scaleAdjust)); if (!proxy) { return nullptr; } // If we made a copy then we only copied the contentArea, in which case the new texture is all // content. if (proxy.get() != this->originalProxy()) { textureMatrix.postScale(scaleAdjust[0], scaleAdjust[1]); } DomainMode domainMode = DetermineDomainMode(constraintRect, filterConstraint, coordsLimitedToConstraintRect, proxy.get(), filterOrNullForBicubic, &domain); if (kTightCopy_DomainMode == domainMode) { // TODO: Copy the texture and adjust the texture matrix (both parts need to consider // non-int constraint rect) // For now: treat as bilerp and ignore what goes on above level 0. // We only expect MIP maps to require a tight copy. SkASSERT(filterOrNullForBicubic && GrSamplerState::Filter::kMipMap == *filterOrNullForBicubic); static const GrSamplerState::Filter kBilerp = GrSamplerState::Filter::kBilerp; domainMode = DetermineDomainMode(constraintRect, filterConstraint, coordsLimitedToConstraintRect, proxy.get(), &kBilerp, &domain); SkASSERT(kTightCopy_DomainMode != domainMode); } SkASSERT(kNoDomain_DomainMode == domainMode || (domain.fLeft <= domain.fRight && domain.fTop <= domain.fBottom)); GrPixelConfig config = proxy->config(); auto fp = CreateFragmentProcessorForDomainAndFilter(std::move(proxy), textureMatrix, domainMode, domain, filterOrNullForBicubic); return GrColorSpaceXformEffect::Make(std::move(fp), fColorSpace, config, dstColorSpace); }
bool GrGpu::IsACopyNeededForTextureParams(const GrCaps* caps, GrTextureProxy* texProxy, int width, int height, const GrSamplerState& textureParams, GrTextureProducer::CopyParams* copyParams, SkScalar scaleAdjust[2]) { if (texProxy) { // If the texture format itself doesn't support repeat wrap mode or mipmapping (and // those capabilities are required) force a copy. if ((textureParams.isRepeated() && texProxy->texPriv().isClampOnly()) || (GrSamplerState::Filter::kMipMap == textureParams.filter() && texProxy->texPriv().doesNotSupportMipMaps())) { copyParams->fFilter = GrSamplerState::Filter::kNearest; copyParams->fWidth = texProxy->width(); copyParams->fHeight = texProxy->height(); return true; } } if (textureParams.isRepeated() && !caps->npotTextureTileSupport() && (!SkIsPow2(width) || !SkIsPow2(height))) { SkASSERT(scaleAdjust); copyParams->fWidth = GrNextPow2(width); copyParams->fHeight = GrNextPow2(height); SkASSERT(scaleAdjust); scaleAdjust[0] = ((SkScalar) copyParams->fWidth) / width; scaleAdjust[1] = ((SkScalar) copyParams->fHeight) / height; switch (textureParams.filter()) { case GrSamplerState::Filter::kNearest: copyParams->fFilter = GrSamplerState::Filter::kNearest; break; case GrSamplerState::Filter::kBilerp: case GrSamplerState::Filter::kMipMap: // We are only ever scaling up so no reason to ever indicate kMipMap. copyParams->fFilter = GrSamplerState::Filter::kBilerp; break; } return true; } return false; }
sk_sp<GrTextureProxy> GrTextureAdjuster::refTextureProxySafeForParams(const GrSamplerState& params, SkScalar scaleAdjust[2]) { sk_sp<GrTextureProxy> proxy = this->originalProxyRef(); CopyParams copyParams; if (!fContext) { // The texture was abandoned. return nullptr; } if (!GrGpu::IsACopyNeededForTextureParams(fContext->caps(), proxy.get(), proxy->width(), proxy->height(), params, ©Params, scaleAdjust)) { return proxy; } bool willBeMipped = GrSamplerState::Filter::kMipMap == params.filter(); return this->refTextureProxyCopy(copyParams, willBeMipped); }
GrVkSampler::Key GrVkSampler::GenerateKey(const GrSamplerState& samplerState, const GrVkYcbcrConversionInfo& ycbcrInfo) { const int kTileModeXShift = 2; const int kTileModeYShift = 4; SkASSERT(static_cast<int>(samplerState.filter()) <= 3); uint8_t samplerKey = static_cast<uint16_t>(samplerState.filter()); SkASSERT(static_cast<int>(samplerState.wrapModeX()) <= 3); samplerKey |= (static_cast<uint8_t>(samplerState.wrapModeX()) << kTileModeXShift); SkASSERT(static_cast<int>(samplerState.wrapModeY()) <= 3); samplerKey |= (static_cast<uint8_t>(samplerState.wrapModeY()) << kTileModeYShift); return {samplerKey, GrVkSamplerYcbcrConversion::GenerateKey(ycbcrInfo)}; }