blob: c682e0b96a482487967d44e7121e83b7534a7ed3 [file] [log] [blame]
Brian Osmane8e54582016-11-28 10:06:27 -05001/*
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"
Brian Osman1cb41712017-10-19 12:54:52 -04009#include "GrColorSpaceXform.h"
Brian Osmane8e54582016-11-28 10:06:27 -050010#include "GrContext.h"
Robert Phillips1afd4cd2018-01-08 13:40:32 -050011#include "GrContextPriv.h"
Robert Phillips009e9af2017-06-15 14:01:04 -040012#include "GrGpu.h"
Robert Phillips1afd4cd2018-01-08 13:40:32 -050013#include "GrProxyProvider.h"
Brian Osman3b655982017-03-07 16:58:08 -050014#include "SkGr.h"
Brian Osmane8e54582016-11-28 10:06:27 -050015
Robert Phillips3798c862017-03-27 11:08:16 -040016GrTextureAdjuster::GrTextureAdjuster(GrContext* context, sk_sp<GrTextureProxy> original,
Brian Salomon4df00922017-09-07 16:34:11 +000017 SkAlphaType alphaType,
Greg Danielc77085d2017-11-01 16:38:48 -040018 uint32_t uniqueID,
Brian Salomon4df00922017-09-07 16:34:11 +000019 SkColorSpace* cs)
Greg Daniel8e9b4c42018-07-20 10:30:48 -040020 : INHERITED(context, original->width(), original->height(),
Brian Salomon4df00922017-09-07 16:34:11 +000021 GrPixelConfigIsAlphaOnly(original->config()))
Brian Salomon4df00922017-09-07 16:34:11 +000022 , fOriginal(std::move(original))
23 , fAlphaType(alphaType)
24 , fColorSpace(cs)
Greg Danielc77085d2017-11-01 16:38:48 -040025 , fUniqueID(uniqueID) {}
Brian Osmane8e54582016-11-28 10:06:27 -050026
Brian Osmanb3f38302018-09-07 15:24:44 -040027void GrTextureAdjuster::makeCopyKey(const CopyParams& params, GrUniqueKey* copyKey) {
Brian Osman61624f02016-12-09 14:51:59 -050028 // Destination color space is irrelevant - we already have a texture so we're just sub-setting
Brian Osmane8e54582016-11-28 10:06:27 -050029 GrUniqueKey baseKey;
30 GrMakeKeyFromImageID(&baseKey, fUniqueID, SkIRect::MakeWH(this->width(), this->height()));
31 MakeCopyKeyFromOrigKey(baseKey, params, copyKey);
32}
33
Brian Salomon238069b2018-07-11 15:58:57 -040034void GrTextureAdjuster::didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) {
Brian Osmane8e54582016-11-28 10:06:27 -050035 // We don't currently have a mechanism for notifications on Images!
36}
37
Greg Daniele1da1d92017-10-06 15:59:27 -040038sk_sp<GrTextureProxy> GrTextureAdjuster::refTextureProxyCopy(const CopyParams& copyParams,
39 bool willBeMipped) {
Robert Phillips1afd4cd2018-01-08 13:40:32 -050040 GrProxyProvider* proxyProvider = fContext->contextPriv().proxyProvider();
41
Robert Phillips0c984a02017-03-16 07:51:56 -040042 GrUniqueKey key;
Brian Osmanb3f38302018-09-07 15:24:44 -040043 this->makeCopyKey(copyParams, &key);
Greg Daniel09c94002018-06-08 22:11:51 +000044 sk_sp<GrTextureProxy> cachedCopy;
Robert Phillips0c984a02017-03-16 07:51:56 -040045 if (key.isValid()) {
Greg Daniel09c94002018-06-08 22:11:51 +000046 cachedCopy = proxyProvider->findOrCreateProxyByUniqueKey(key,
47 this->originalProxy()->origin());
48 if (cachedCopy && (!willBeMipped || GrMipMapped::kYes == cachedCopy->mipMapped())) {
Robert Phillips0c984a02017-03-16 07:51:56 -040049 return cachedCopy;
50 }
51 }
52
53 sk_sp<GrTextureProxy> proxy = this->originalProxyRef();
Robert Phillips0c984a02017-03-16 07:51:56 -040054
Greg Danielc77085d2017-11-01 16:38:48 -040055 sk_sp<GrTextureProxy> copy = CopyOnGpu(fContext, std::move(proxy), copyParams, willBeMipped);
Robert Phillips0c984a02017-03-16 07:51:56 -040056 if (copy) {
57 if (key.isValid()) {
Robert Phillips78814092017-07-24 15:26:17 -040058 SkASSERT(copy->origin() == this->originalProxy()->origin());
Greg Daniel09c94002018-06-08 22:11:51 +000059 if (cachedCopy) {
60 SkASSERT(GrMipMapped::kYes == copy->mipMapped() &&
61 GrMipMapped::kNo == cachedCopy->mipMapped());
62 // If we had a cachedProxy, that means there already is a proxy in the cache which
63 // matches the key, but it does not have mip levels and we require them. Thus we
64 // must remove the unique key from that proxy.
65 proxyProvider->removeUniqueKeyFromProxy(key, cachedCopy.get());
66 }
Robert Phillips1afd4cd2018-01-08 13:40:32 -050067 proxyProvider->assignUniqueKeyToProxy(key, copy.get());
Robert Phillipsdf65b832018-08-30 09:11:37 -040068 if (!proxyProvider->recordingDDL()) {
69 // If we're recording a DDL we cannot add genID change listeners because
70 // that process isn't thread safe
71 this->didCacheCopy(key, proxyProvider->contextUniqueID());
72 }
Brian Osmane8e54582016-11-28 10:06:27 -050073 }
74 }
75 return copy;
76}
77
Brian Salomon2a943df2018-05-04 13:43:19 -040078sk_sp<GrTextureProxy> GrTextureAdjuster::onRefTextureProxyForParams(
79 const GrSamplerState& params,
80 SkColorSpace* dstColorSpace,
81 sk_sp<SkColorSpace>* texColorSpace,
Greg Daniel8e9b4c42018-07-20 10:30:48 -040082 bool willBeMipped,
Brian Salomon2a943df2018-05-04 13:43:19 -040083 SkScalar scaleAdjust[2]) {
Robert Phillips3798c862017-03-27 11:08:16 -040084 sk_sp<GrTextureProxy> proxy = this->originalProxyRef();
Brian Osmane8e54582016-11-28 10:06:27 -050085 CopyParams copyParams;
Brian Osmane8e54582016-11-28 10:06:27 -050086
Robert Phillips0c984a02017-03-16 07:51:56 -040087 if (!fContext) {
Brian Osmane8e54582016-11-28 10:06:27 -050088 // The texture was abandoned.
89 return nullptr;
90 }
Brian Salomon4df00922017-09-07 16:34:11 +000091
Brian Salomon2a943df2018-05-04 13:43:19 -040092 if (texColorSpace) {
93 *texColorSpace = sk_ref_sp(fColorSpace);
94 }
Brian Salomonc7fe0f72018-05-11 10:14:21 -040095 SkASSERT(this->width() <= fContext->contextPriv().caps()->maxTextureSize() &&
96 this->height() <= fContext->contextPriv().caps()->maxTextureSize());
Brian Osman875f7852018-04-12 13:29:08 -040097
Greg Daniel8f5bbda2018-06-08 17:22:23 -040098 bool needsCopyForMipsOnly = false;
99 if (!params.isRepeated() ||
100 !GrGpu::IsACopyNeededForRepeatWrapMode(fContext->contextPriv().caps(), proxy.get(),
101 proxy->width(), proxy->height(), params.filter(),
102 &copyParams, scaleAdjust)) {
103 needsCopyForMipsOnly = GrGpu::IsACopyNeededForMips(fContext->contextPriv().caps(),
104 proxy.get(), params.filter(),
105 &copyParams);
106 if (!needsCopyForMipsOnly) {
107 return proxy;
108 }
Brian Osmane8e54582016-11-28 10:06:27 -0500109 }
110
Greg Daniel8f5bbda2018-06-08 17:22:23 -0400111 sk_sp<GrTextureProxy> result = this->refTextureProxyCopy(copyParams, willBeMipped);
112 if (!result && needsCopyForMipsOnly) {
113 // If we were unable to make a copy and we only needed a copy for mips, then we will return
114 // the source texture here and require that the GPU backend is able to fall back to using
115 // bilerp if mips are required.
116 return this->originalProxyRef();
117 }
118 return result;
Brian Osmane8e54582016-11-28 10:06:27 -0500119}
120
Brian Salomonaff329b2017-08-11 09:40:37 -0400121std::unique_ptr<GrFragmentProcessor> GrTextureAdjuster::createFragmentProcessor(
122 const SkMatrix& origTextureMatrix,
Greg Danielc77085d2017-11-01 16:38:48 -0400123 const SkRect& constraintRect,
Brian Salomonaff329b2017-08-11 09:40:37 -0400124 FilterConstraint filterConstraint,
125 bool coordsLimitedToConstraintRect,
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400126 const GrSamplerState::Filter* filterOrNullForBicubic,
Brian Salomonaff329b2017-08-11 09:40:37 -0400127 SkColorSpace* dstColorSpace) {
Brian Osmane8e54582016-11-28 10:06:27 -0500128 SkMatrix textureMatrix = origTextureMatrix;
Brian Osmane8e54582016-11-28 10:06:27 -0500129
130 SkRect domain;
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400131 GrSamplerState samplerState;
Brian Osmane8e54582016-11-28 10:06:27 -0500132 if (filterOrNullForBicubic) {
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400133 samplerState.setFilterMode(*filterOrNullForBicubic);
Brian Osmane8e54582016-11-28 10:06:27 -0500134 }
Robert Phillips67c18d62017-01-20 12:44:06 -0500135 SkScalar scaleAdjust[2] = { 1.0f, 1.0f };
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400136 sk_sp<GrTextureProxy> proxy(
Brian Salomon2a943df2018-05-04 13:43:19 -0400137 this->refTextureProxyForParams(samplerState, nullptr, nullptr, scaleAdjust));
Robert Phillips3798c862017-03-27 11:08:16 -0400138 if (!proxy) {
Brian Osmane8e54582016-11-28 10:06:27 -0500139 return nullptr;
140 }
141 // If we made a copy then we only copied the contentArea, in which case the new texture is all
142 // content.
Robert Phillips3798c862017-03-27 11:08:16 -0400143 if (proxy.get() != this->originalProxy()) {
Robert Phillips67c18d62017-01-20 12:44:06 -0500144 textureMatrix.postScale(scaleAdjust[0], scaleAdjust[1]);
Brian Osmane8e54582016-11-28 10:06:27 -0500145 }
146
147 DomainMode domainMode =
Greg Danielc77085d2017-11-01 16:38:48 -0400148 DetermineDomainMode(constraintRect, filterConstraint, coordsLimitedToConstraintRect,
149 proxy.get(), filterOrNullForBicubic, &domain);
Brian Osmane8e54582016-11-28 10:06:27 -0500150 if (kTightCopy_DomainMode == domainMode) {
151 // TODO: Copy the texture and adjust the texture matrix (both parts need to consider
152 // non-int constraint rect)
153 // For now: treat as bilerp and ignore what goes on above level 0.
154
155 // We only expect MIP maps to require a tight copy.
156 SkASSERT(filterOrNullForBicubic &&
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400157 GrSamplerState::Filter::kMipMap == *filterOrNullForBicubic);
158 static const GrSamplerState::Filter kBilerp = GrSamplerState::Filter::kBilerp;
Brian Osmane8e54582016-11-28 10:06:27 -0500159 domainMode =
Greg Danielc77085d2017-11-01 16:38:48 -0400160 DetermineDomainMode(constraintRect, filterConstraint, coordsLimitedToConstraintRect,
161 proxy.get(), &kBilerp, &domain);
Brian Osmane8e54582016-11-28 10:06:27 -0500162 SkASSERT(kTightCopy_DomainMode != domainMode);
163 }
164 SkASSERT(kNoDomain_DomainMode == domainMode ||
165 (domain.fLeft <= domain.fRight && domain.fTop <= domain.fBottom));
Brian Osman5e341672017-10-18 10:23:18 -0400166 auto fp = CreateFragmentProcessorForDomainAndFilter(std::move(proxy), textureMatrix,
167 domainMode, domain, filterOrNullForBicubic);
Brian Osman21fc5ce2018-08-27 20:36:19 +0000168 return GrColorSpaceXformEffect::Make(std::move(fp), fColorSpace, fAlphaType, dstColorSpace);
Brian Osmane8e54582016-11-28 10:06:27 -0500169}