blob: 9b6ce36311e8bad964f84200416df24b74e6e51f [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/private/GrRecordingContext.h"
9#include "src/gpu/GrColorSpaceXform.h"
10#include "src/gpu/GrGpu.h"
11#include "src/gpu/GrProxyProvider.h"
12#include "src/gpu/GrRecordingContextPriv.h"
13#include "src/gpu/GrTextureAdjuster.h"
14#include "src/gpu/SkGr.h"
Brian Osmane8e54582016-11-28 10:06:27 -050015
Brian Salomone7499c72019-06-24 12:12:36 -040016GrTextureAdjuster::GrTextureAdjuster(GrRecordingContext* context,
17 sk_sp<GrTextureProxy> original,
Brian Salomond6287472019-06-24 15:50:07 -040018 GrColorType colorType,
Brian Salomon4df00922017-09-07 16:34:11 +000019 SkAlphaType alphaType,
Greg Danielc77085d2017-11-01 16:38:48 -040020 uint32_t uniqueID,
Michael Ludwigddeed372019-02-20 16:50:10 -050021 SkColorSpace* cs,
22 bool useDecal)
Brian Salomone7499c72019-06-24 12:12:36 -040023 : INHERITED(context, original->width(), original->height(),
Brian Salomon4bc0c1f2019-09-30 15:12:27 -040024 GrColorInfo(colorType, alphaType, sk_ref_sp(cs)), useDecal)
Brian Salomone7499c72019-06-24 12:12:36 -040025 , fOriginal(std::move(original))
26 , fUniqueID(uniqueID) {}
Brian Osmane8e54582016-11-28 10:06:27 -050027
Greg Daniela4828a12019-10-11 13:51:02 -040028GrTextureAdjuster::GrTextureAdjuster(GrRecordingContext* context,
29 sk_sp<GrTextureProxy> original,
30 const GrColorInfo& colorInfo,
31 uint32_t uniqueID,
32 bool useDecal)
33 : INHERITED(context, original->width(), original->height(), colorInfo, useDecal)
34 , fOriginal(std::move(original))
35 , fUniqueID(uniqueID) {}
36
Brian Osmanb3f38302018-09-07 15:24:44 -040037void GrTextureAdjuster::makeCopyKey(const CopyParams& params, GrUniqueKey* copyKey) {
Brian Osman61624f02016-12-09 14:51:59 -050038 // Destination color space is irrelevant - we already have a texture so we're just sub-setting
Brian Osmane8e54582016-11-28 10:06:27 -050039 GrUniqueKey baseKey;
40 GrMakeKeyFromImageID(&baseKey, fUniqueID, SkIRect::MakeWH(this->width(), this->height()));
41 MakeCopyKeyFromOrigKey(baseKey, params, copyKey);
42}
43
Brian Salomon238069b2018-07-11 15:58:57 -040044void GrTextureAdjuster::didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) {
Brian Osmane8e54582016-11-28 10:06:27 -050045 // We don't currently have a mechanism for notifications on Images!
46}
47
Greg Daniele1da1d92017-10-06 15:59:27 -040048sk_sp<GrTextureProxy> GrTextureAdjuster::refTextureProxyCopy(const CopyParams& copyParams,
49 bool willBeMipped) {
Robert Phillips9338c602019-02-19 12:52:29 -050050 GrProxyProvider* proxyProvider = this->context()->priv().proxyProvider();
Robert Phillips1afd4cd2018-01-08 13:40:32 -050051
Robert Phillips0c984a02017-03-16 07:51:56 -040052 GrUniqueKey key;
Brian Osmanb3f38302018-09-07 15:24:44 -040053 this->makeCopyKey(copyParams, &key);
Greg Daniel09c94002018-06-08 22:11:51 +000054 sk_sp<GrTextureProxy> cachedCopy;
Robert Phillips0c984a02017-03-16 07:51:56 -040055 if (key.isValid()) {
Brian Salomon2af3e702019-08-11 19:10:31 -040056 cachedCopy = proxyProvider->findOrCreateProxyByUniqueKey(key, this->colorType(),
Greg Daniel09c94002018-06-08 22:11:51 +000057 this->originalProxy()->origin());
58 if (cachedCopy && (!willBeMipped || GrMipMapped::kYes == cachedCopy->mipMapped())) {
Robert Phillips0c984a02017-03-16 07:51:56 -040059 return cachedCopy;
60 }
61 }
62
63 sk_sp<GrTextureProxy> proxy = this->originalProxyRef();
Robert Phillips0c984a02017-03-16 07:51:56 -040064
Brian Salomond6287472019-06-24 15:50:07 -040065 sk_sp<GrTextureProxy> copy = CopyOnGpu(this->context(), std::move(proxy), this->colorType(),
Robert Phillips9338c602019-02-19 12:52:29 -050066 copyParams, willBeMipped);
Robert Phillips0c984a02017-03-16 07:51:56 -040067 if (copy) {
68 if (key.isValid()) {
Robert Phillips78814092017-07-24 15:26:17 -040069 SkASSERT(copy->origin() == this->originalProxy()->origin());
Greg Daniel09c94002018-06-08 22:11:51 +000070 if (cachedCopy) {
71 SkASSERT(GrMipMapped::kYes == copy->mipMapped() &&
72 GrMipMapped::kNo == cachedCopy->mipMapped());
73 // If we had a cachedProxy, that means there already is a proxy in the cache which
74 // matches the key, but it does not have mip levels and we require them. Thus we
75 // must remove the unique key from that proxy.
Chris Dalton2de13dd2019-01-03 15:11:59 -070076 SkASSERT(cachedCopy->getUniqueKey() == key);
77 proxyProvider->removeUniqueKeyFromProxy(cachedCopy.get());
Greg Daniel09c94002018-06-08 22:11:51 +000078 }
Robert Phillips1afd4cd2018-01-08 13:40:32 -050079 proxyProvider->assignUniqueKeyToProxy(key, copy.get());
Robert Phillipsa41c6852019-02-07 10:44:10 -050080 this->didCacheCopy(key, proxyProvider->contextID());
Brian Osmane8e54582016-11-28 10:06:27 -050081 }
82 }
83 return copy;
84}
85
Brian Salomon2a943df2018-05-04 13:43:19 -040086sk_sp<GrTextureProxy> GrTextureAdjuster::onRefTextureProxyForParams(
87 const GrSamplerState& params,
Greg Daniel8e9b4c42018-07-20 10:30:48 -040088 bool willBeMipped,
Brian Salomon2a943df2018-05-04 13:43:19 -040089 SkScalar scaleAdjust[2]) {
Robert Phillips3798c862017-03-27 11:08:16 -040090 sk_sp<GrTextureProxy> proxy = this->originalProxyRef();
Brian Osmane8e54582016-11-28 10:06:27 -050091 CopyParams copyParams;
Brian Osmane8e54582016-11-28 10:06:27 -050092
Robert Phillips9338c602019-02-19 12:52:29 -050093 if (this->context()->priv().abandoned()) {
Brian Osmane8e54582016-11-28 10:06:27 -050094 // The texture was abandoned.
95 return nullptr;
96 }
Brian Salomon4df00922017-09-07 16:34:11 +000097
Robert Phillips9338c602019-02-19 12:52:29 -050098 SkASSERT(this->width() <= this->context()->priv().caps()->maxTextureSize() &&
99 this->height() <= this->context()->priv().caps()->maxTextureSize());
Brian Osman875f7852018-04-12 13:29:08 -0400100
Greg Daniel8f5bbda2018-06-08 17:22:23 -0400101 bool needsCopyForMipsOnly = false;
102 if (!params.isRepeated() ||
Robert Phillips9338c602019-02-19 12:52:29 -0500103 !GrGpu::IsACopyNeededForRepeatWrapMode(this->context()->priv().caps(), proxy.get(),
Greg Daniel8f5bbda2018-06-08 17:22:23 -0400104 proxy->width(), proxy->height(), params.filter(),
105 &copyParams, scaleAdjust)) {
Robert Phillips9338c602019-02-19 12:52:29 -0500106 needsCopyForMipsOnly = GrGpu::IsACopyNeededForMips(this->context()->priv().caps(),
Greg Daniel8f5bbda2018-06-08 17:22:23 -0400107 proxy.get(), params.filter(),
108 &copyParams);
109 if (!needsCopyForMipsOnly) {
110 return proxy;
111 }
Brian Osmane8e54582016-11-28 10:06:27 -0500112 }
113
Greg Daniel8f5bbda2018-06-08 17:22:23 -0400114 sk_sp<GrTextureProxy> result = this->refTextureProxyCopy(copyParams, willBeMipped);
115 if (!result && needsCopyForMipsOnly) {
116 // If we were unable to make a copy and we only needed a copy for mips, then we will return
117 // the source texture here and require that the GPU backend is able to fall back to using
118 // bilerp if mips are required.
119 return this->originalProxyRef();
120 }
121 return result;
Brian Osmane8e54582016-11-28 10:06:27 -0500122}
123
Brian Salomonaff329b2017-08-11 09:40:37 -0400124std::unique_ptr<GrFragmentProcessor> GrTextureAdjuster::createFragmentProcessor(
125 const SkMatrix& origTextureMatrix,
Greg Danielc77085d2017-11-01 16:38:48 -0400126 const SkRect& constraintRect,
Brian Salomonaff329b2017-08-11 09:40:37 -0400127 FilterConstraint filterConstraint,
128 bool coordsLimitedToConstraintRect,
Brian Osman05c8f462018-10-22 17:13:36 -0400129 const GrSamplerState::Filter* filterOrNullForBicubic) {
Brian Osmane8e54582016-11-28 10:06:27 -0500130 SkMatrix textureMatrix = origTextureMatrix;
Brian Osmane8e54582016-11-28 10:06:27 -0500131
Robert Phillips67c18d62017-01-20 12:44:06 -0500132 SkScalar scaleAdjust[2] = { 1.0f, 1.0f };
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400133 sk_sp<GrTextureProxy> proxy(
Michael Ludwigddeed372019-02-20 16:50:10 -0500134 this->refTextureProxyForParams(filterOrNullForBicubic, scaleAdjust));
Robert Phillips3798c862017-03-27 11:08:16 -0400135 if (!proxy) {
Brian Osmane8e54582016-11-28 10:06:27 -0500136 return nullptr;
137 }
138 // If we made a copy then we only copied the contentArea, in which case the new texture is all
139 // content.
Robert Phillips3798c862017-03-27 11:08:16 -0400140 if (proxy.get() != this->originalProxy()) {
Robert Phillips67c18d62017-01-20 12:44:06 -0500141 textureMatrix.postScale(scaleAdjust[0], scaleAdjust[1]);
Brian Osmane8e54582016-11-28 10:06:27 -0500142 }
143
Michael Ludwigddeed372019-02-20 16:50:10 -0500144 SkRect domain;
Brian Osmane8e54582016-11-28 10:06:27 -0500145 DomainMode domainMode =
Greg Danielc77085d2017-11-01 16:38:48 -0400146 DetermineDomainMode(constraintRect, filterConstraint, coordsLimitedToConstraintRect,
147 proxy.get(), filterOrNullForBicubic, &domain);
Brian Osmane8e54582016-11-28 10:06:27 -0500148 if (kTightCopy_DomainMode == domainMode) {
149 // TODO: Copy the texture and adjust the texture matrix (both parts need to consider
150 // non-int constraint rect)
151 // For now: treat as bilerp and ignore what goes on above level 0.
152
153 // We only expect MIP maps to require a tight copy.
154 SkASSERT(filterOrNullForBicubic &&
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400155 GrSamplerState::Filter::kMipMap == *filterOrNullForBicubic);
156 static const GrSamplerState::Filter kBilerp = GrSamplerState::Filter::kBilerp;
Brian Osmane8e54582016-11-28 10:06:27 -0500157 domainMode =
Greg Danielc77085d2017-11-01 16:38:48 -0400158 DetermineDomainMode(constraintRect, filterConstraint, coordsLimitedToConstraintRect,
159 proxy.get(), &kBilerp, &domain);
Brian Osmane8e54582016-11-28 10:06:27 -0500160 SkASSERT(kTightCopy_DomainMode != domainMode);
161 }
162 SkASSERT(kNoDomain_DomainMode == domainMode ||
163 (domain.fLeft <= domain.fRight && domain.fTop <= domain.fBottom));
Michael Ludwigddeed372019-02-20 16:50:10 -0500164 return this->createFragmentProcessorForDomainAndFilter(
165 std::move(proxy), textureMatrix, domainMode, domain, filterOrNullForBicubic);
Brian Osmane8e54582016-11-28 10:06:27 -0500166}