blob: 96b0b6430f53f37addbaf629d09ccceeae214564 [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,
Greg Danielcc104db2020-02-03 14:17:08 -050017 GrSurfaceProxyView original,
Greg Daniela4828a12019-10-11 13:51:02 -040018 const GrColorInfo& colorInfo,
19 uint32_t uniqueID,
20 bool useDecal)
Greg Danielcc104db2020-02-03 14:17:08 -050021 : INHERITED(context, {colorInfo, original.proxy()->dimensions()}, useDecal)
Greg Daniela4828a12019-10-11 13:51:02 -040022 , fOriginal(std::move(original))
23 , fUniqueID(uniqueID) {}
24
Brian Osmanb3f38302018-09-07 15:24:44 -040025void GrTextureAdjuster::makeCopyKey(const CopyParams& params, GrUniqueKey* copyKey) {
Brian Osman61624f02016-12-09 14:51:59 -050026 // Destination color space is irrelevant - we already have a texture so we're just sub-setting
Brian Osmane8e54582016-11-28 10:06:27 -050027 GrUniqueKey baseKey;
Brian Salomon1a217eb2019-10-24 10:50:36 -040028 GrMakeKeyFromImageID(&baseKey, fUniqueID, SkIRect::MakeSize(this->dimensions()));
Brian Osmane8e54582016-11-28 10:06:27 -050029 MakeCopyKeyFromOrigKey(baseKey, params, copyKey);
30}
31
Brian Salomon238069b2018-07-11 15:58:57 -040032void GrTextureAdjuster::didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) {
Brian Osmane8e54582016-11-28 10:06:27 -050033 // We don't currently have a mechanism for notifications on Images!
34}
35
Greg Danielc61d7e32020-02-04 14:27:45 -050036GrSurfaceProxyView GrTextureAdjuster::copy(const CopyParams& copyParams, bool willBeMipped,
37 bool copyForMipsOnly) {
Robert Phillips9338c602019-02-19 12:52:29 -050038 GrProxyProvider* proxyProvider = this->context()->priv().proxyProvider();
Robert Phillips1afd4cd2018-01-08 13:40:32 -050039
Robert Phillips0c984a02017-03-16 07:51:56 -040040 GrUniqueKey key;
Brian Osmanb3f38302018-09-07 15:24:44 -040041 this->makeCopyKey(copyParams, &key);
Greg Daniel09c94002018-06-08 22:11:51 +000042 sk_sp<GrTextureProxy> cachedCopy;
Greg Danielcc104db2020-02-03 14:17:08 -050043 const GrSurfaceProxyView& originalView = this->originalProxyView();
Robert Phillips0c984a02017-03-16 07:51:56 -040044 if (key.isValid()) {
Greg Daniel3a365112020-02-14 10:47:18 -050045 cachedCopy = proxyProvider->findOrCreateProxyByUniqueKey(key, this->colorType());
Greg Daniel09c94002018-06-08 22:11:51 +000046 if (cachedCopy && (!willBeMipped || GrMipMapped::kYes == cachedCopy->mipMapped())) {
Greg Danielcc104db2020-02-03 14:17:08 -050047 // TODO: Once we no longer use CopyOnGpu which can fallback to arbitrary formats and
48 // colorTypes, we can use the swizzle of the originalView.
Greg Daniel87506ab2020-02-12 13:05:42 -050049 GrSwizzle swizzle = cachedCopy->textureSwizzleDoNotUse();
Greg Danielcc104db2020-02-03 14:17:08 -050050 return GrSurfaceProxyView(std::move(cachedCopy), originalView.origin(), swizzle);
Robert Phillips0c984a02017-03-16 07:51:56 -040051 }
52 }
53
Greg Danielcc104db2020-02-03 14:17:08 -050054 GrSurfaceProxyView copyView;
Greg Danielcce65002020-01-23 11:16:49 -050055 if (copyForMipsOnly) {
Greg Danielcc104db2020-02-03 14:17:08 -050056 copyView = GrCopyBaseMipMapToTextureProxy(this->context(), originalView.proxy(),
57 originalView.origin(), this->colorType());
Greg Danielcce65002020-01-23 11:16:49 -050058 } else {
Greg Danielcc104db2020-02-03 14:17:08 -050059 copyView = CopyOnGpu(this->context(), this->originalProxyViewRef(), this->colorType(),
60 copyParams, willBeMipped);
Greg Danielcce65002020-01-23 11:16:49 -050061 }
Greg Danielcc104db2020-02-03 14:17:08 -050062 if (copyView.proxy()) {
Robert Phillips0c984a02017-03-16 07:51:56 -040063 if (key.isValid()) {
Greg Danielcc104db2020-02-03 14:17:08 -050064 SkASSERT(copyView.origin() == originalView.origin());
Greg Daniel09c94002018-06-08 22:11:51 +000065 if (cachedCopy) {
Greg Danielcc104db2020-02-03 14:17:08 -050066 SkASSERT(GrMipMapped::kYes == copyView.asTextureProxy()->mipMapped() &&
Greg Daniel09c94002018-06-08 22:11:51 +000067 GrMipMapped::kNo == cachedCopy->mipMapped());
68 // If we had a cachedProxy, that means there already is a proxy in the cache which
69 // matches the key, but it does not have mip levels and we require them. Thus we
70 // must remove the unique key from that proxy.
Chris Dalton2de13dd2019-01-03 15:11:59 -070071 SkASSERT(cachedCopy->getUniqueKey() == key);
72 proxyProvider->removeUniqueKeyFromProxy(cachedCopy.get());
Greg Daniel09c94002018-06-08 22:11:51 +000073 }
Greg Danielcc104db2020-02-03 14:17:08 -050074 proxyProvider->assignUniqueKeyToProxy(key, copyView.asTextureProxy());
Robert Phillipsa41c6852019-02-07 10:44:10 -050075 this->didCacheCopy(key, proxyProvider->contextID());
Brian Osmane8e54582016-11-28 10:06:27 -050076 }
77 }
Greg Danielcc104db2020-02-03 14:17:08 -050078 return copyView;
Brian Osmane8e54582016-11-28 10:06:27 -050079}
80
Greg Danielcc104db2020-02-03 14:17:08 -050081GrSurfaceProxyView GrTextureAdjuster::onRefTextureProxyViewForParams(GrSamplerState params,
82 bool willBeMipped,
83 SkScalar scaleAdjust[2]) {
Robert Phillips9338c602019-02-19 12:52:29 -050084 if (this->context()->priv().abandoned()) {
Brian Osmane8e54582016-11-28 10:06:27 -050085 // The texture was abandoned.
Greg Danielcc104db2020-02-03 14:17:08 -050086 return {};
Brian Osmane8e54582016-11-28 10:06:27 -050087 }
Brian Salomon4df00922017-09-07 16:34:11 +000088
Robert Phillips9338c602019-02-19 12:52:29 -050089 SkASSERT(this->width() <= this->context()->priv().caps()->maxTextureSize() &&
90 this->height() <= this->context()->priv().caps()->maxTextureSize());
Brian Osman875f7852018-04-12 13:29:08 -040091
Greg Danielcc104db2020-02-03 14:17:08 -050092 GrSurfaceProxyView view = this->originalProxyViewRef();
93 GrTextureProxy* texProxy = view.asTextureProxy();
94 SkASSERT(texProxy);
95 CopyParams copyParams;
96
Greg Daniel8f5bbda2018-06-08 17:22:23 -040097 bool needsCopyForMipsOnly = false;
98 if (!params.isRepeated() ||
Greg Danielcc104db2020-02-03 14:17:08 -050099 !GrGpu::IsACopyNeededForRepeatWrapMode(this->context()->priv().caps(), texProxy,
100 texProxy->dimensions(), params.filter(), &copyParams,
Brian Salomon1a217eb2019-10-24 10:50:36 -0400101 scaleAdjust)) {
Robert Phillips9338c602019-02-19 12:52:29 -0500102 needsCopyForMipsOnly = GrGpu::IsACopyNeededForMips(this->context()->priv().caps(),
Greg Danielcc104db2020-02-03 14:17:08 -0500103 texProxy, params.filter(),
Greg Daniel8f5bbda2018-06-08 17:22:23 -0400104 &copyParams);
105 if (!needsCopyForMipsOnly) {
Greg Danielcc104db2020-02-03 14:17:08 -0500106 return view;
Greg Daniel8f5bbda2018-06-08 17:22:23 -0400107 }
Brian Osmane8e54582016-11-28 10:06:27 -0500108 }
109
Greg Danielc61d7e32020-02-04 14:27:45 -0500110 GrSurfaceProxyView result = this->copy(copyParams, willBeMipped, needsCopyForMipsOnly);
Greg Danielcc104db2020-02-03 14:17:08 -0500111 if (!result.proxy() && needsCopyForMipsOnly) {
Greg Daniel8f5bbda2018-06-08 17:22:23 -0400112 // If we were unable to make a copy and we only needed a copy for mips, then we will return
113 // the source texture here and require that the GPU backend is able to fall back to using
114 // bilerp if mips are required.
Greg Danielcc104db2020-02-03 14:17:08 -0500115 return view;
Greg Daniel8f5bbda2018-06-08 17:22:23 -0400116 }
Greg Danielcc104db2020-02-03 14:17:08 -0500117 SkASSERT(result.asTextureProxy());
Greg Daniel8f5bbda2018-06-08 17:22:23 -0400118 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 Osman05c8f462018-10-22 17:13:36 -0400126 const GrSamplerState::Filter* filterOrNullForBicubic) {
Brian Osmane8e54582016-11-28 10:06:27 -0500127 SkMatrix textureMatrix = origTextureMatrix;
Brian Osmane8e54582016-11-28 10:06:27 -0500128
Robert Phillips67c18d62017-01-20 12:44:06 -0500129 SkScalar scaleAdjust[2] = { 1.0f, 1.0f };
Greg Danielc61d7e32020-02-04 14:27:45 -0500130 GrSurfaceProxyView view = this->viewForParams(filterOrNullForBicubic, scaleAdjust);
Greg Danielcc104db2020-02-03 14:17:08 -0500131 if (!view.proxy()) {
Brian Osmane8e54582016-11-28 10:06:27 -0500132 return nullptr;
133 }
Greg Danielcc104db2020-02-03 14:17:08 -0500134 SkASSERT(view.asTextureProxy());
Brian Osmane8e54582016-11-28 10:06:27 -0500135 // If we made a copy then we only copied the contentArea, in which case the new texture is all
136 // content.
Greg Danielcc104db2020-02-03 14:17:08 -0500137 if (view.proxy() != this->originalProxyView().proxy()) {
Robert Phillips67c18d62017-01-20 12:44:06 -0500138 textureMatrix.postScale(scaleAdjust[0], scaleAdjust[1]);
Brian Osmane8e54582016-11-28 10:06:27 -0500139 }
140
Michael Ludwigddeed372019-02-20 16:50:10 -0500141 SkRect domain;
Brian Osmane8e54582016-11-28 10:06:27 -0500142 DomainMode domainMode =
Greg Danielc77085d2017-11-01 16:38:48 -0400143 DetermineDomainMode(constraintRect, filterConstraint, coordsLimitedToConstraintRect,
Greg Danielcc104db2020-02-03 14:17:08 -0500144 view.proxy(), filterOrNullForBicubic, &domain);
Brian Osmane8e54582016-11-28 10:06:27 -0500145 if (kTightCopy_DomainMode == domainMode) {
146 // TODO: Copy the texture and adjust the texture matrix (both parts need to consider
147 // non-int constraint rect)
148 // For now: treat as bilerp and ignore what goes on above level 0.
149
150 // We only expect MIP maps to require a tight copy.
151 SkASSERT(filterOrNullForBicubic &&
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400152 GrSamplerState::Filter::kMipMap == *filterOrNullForBicubic);
153 static const GrSamplerState::Filter kBilerp = GrSamplerState::Filter::kBilerp;
Brian Osmane8e54582016-11-28 10:06:27 -0500154 domainMode =
Greg Danielc77085d2017-11-01 16:38:48 -0400155 DetermineDomainMode(constraintRect, filterConstraint, coordsLimitedToConstraintRect,
Greg Danielcc104db2020-02-03 14:17:08 -0500156 view.proxy(), &kBilerp, &domain);
Brian Osmane8e54582016-11-28 10:06:27 -0500157 SkASSERT(kTightCopy_DomainMode != domainMode);
158 }
159 SkASSERT(kNoDomain_DomainMode == domainMode ||
160 (domain.fLeft <= domain.fRight && domain.fTop <= domain.fBottom));
Michael Ludwigddeed372019-02-20 16:50:10 -0500161 return this->createFragmentProcessorForDomainAndFilter(
Greg Danielcc104db2020-02-03 14:17:08 -0500162 std::move(view), textureMatrix, domainMode, domain, filterOrNullForBicubic);
Brian Osmane8e54582016-11-28 10:06:27 -0500163}