blob: cb383d4d2eb01927b353e645a41aca8c2ba3ca86 [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 "GrTextureMaker.h"
9
Brian Osman1cb41712017-10-19 12:54:52 -040010#include "GrColorSpaceXform.h"
Brian Osmane8e54582016-11-28 10:06:27 -050011#include "GrContext.h"
Robert Phillips1afd4cd2018-01-08 13:40:32 -050012#include "GrContextPriv.h"
Brian Osmane8e54582016-11-28 10:06:27 -050013#include "GrGpu.h"
Robert Phillips1afd4cd2018-01-08 13:40:32 -050014#include "GrProxyProvider.h"
Brian Osmane8e54582016-11-28 10:06:27 -050015
Brian Salomon2a943df2018-05-04 13:43:19 -040016sk_sp<GrTextureProxy> GrTextureMaker::onRefTextureProxyForParams(const GrSamplerState& params,
17 SkColorSpace* dstColorSpace,
18 sk_sp<SkColorSpace>* texColorSpace,
Greg Daniel8e9b4c42018-07-20 10:30:48 -040019 bool willBeMipped,
Brian Salomon2a943df2018-05-04 13:43:19 -040020 SkScalar scaleAdjust[2]) {
Brian Salomonc7fe0f72018-05-11 10:14:21 -040021 if (this->width() > fContext->contextPriv().caps()->maxTextureSize() ||
22 this->height() > fContext->contextPriv().caps()->maxTextureSize()) {
Brian Osman875f7852018-04-12 13:29:08 -040023 return nullptr;
24 }
25
Brian Osmane8e54582016-11-28 10:06:27 -050026 CopyParams copyParams;
Brian Osmane8e54582016-11-28 10:06:27 -050027
28 if (texColorSpace) {
Brian Osman61624f02016-12-09 14:51:59 -050029 *texColorSpace = this->getColorSpace(dstColorSpace);
Brian Osmane8e54582016-11-28 10:06:27 -050030 }
31
Stan Ilievba81af22017-06-08 15:16:53 -040032 sk_sp<GrTextureProxy> original(this->refOriginalTextureProxy(willBeMipped, dstColorSpace,
33 AllowedTexGenType::kCheap));
Greg Daniel8f5bbda2018-06-08 17:22:23 -040034 bool needsCopyForMipsOnly = false;
Stan Ilievba81af22017-06-08 15:16:53 -040035 if (original) {
Greg Daniel8f5bbda2018-06-08 17:22:23 -040036 if (!params.isRepeated() ||
37 !GrGpu::IsACopyNeededForRepeatWrapMode(fContext->contextPriv().caps(), original.get(),
38 original->width(), original->height(),
39 params.filter(), &copyParams, scaleAdjust)) {
40 needsCopyForMipsOnly = GrGpu::IsACopyNeededForMips(fContext->contextPriv().caps(),
41 original.get(), params.filter(),
42 &copyParams);
43 if (!needsCopyForMipsOnly) {
44 return original;
45 }
Stan Ilievba81af22017-06-08 15:16:53 -040046 }
47 } else {
Greg Daniel8f5bbda2018-06-08 17:22:23 -040048 if (!params.isRepeated() ||
49 !GrGpu::IsACopyNeededForRepeatWrapMode(fContext->contextPriv().caps(), nullptr,
50 this->width(), this->height(),
51 params.filter(), &copyParams, scaleAdjust)) {
Stan Ilievba81af22017-06-08 15:16:53 -040052 return this->refOriginalTextureProxy(willBeMipped, dstColorSpace,
53 AllowedTexGenType::kAny);
54 }
Brian Osmane8e54582016-11-28 10:06:27 -050055 }
Stan Ilievba81af22017-06-08 15:16:53 -040056
Robert Phillips1afd4cd2018-01-08 13:40:32 -050057 GrProxyProvider* proxyProvider = fContext->contextPriv().proxyProvider();
58
59 GrSurfaceOrigin origOrigin = original ? original->origin() : kTopLeft_GrSurfaceOrigin;
Brian Osmane8e54582016-11-28 10:06:27 -050060 GrUniqueKey copyKey;
Brian Osmanb3f38302018-09-07 15:24:44 -040061 this->makeCopyKey(copyParams, &copyKey);
Greg Daniel2d59d2f2017-10-31 15:25:14 -040062 sk_sp<GrTextureProxy> cachedProxy;
Brian Osmane8e54582016-11-28 10:06:27 -050063 if (copyKey.isValid()) {
Robert Phillips1afd4cd2018-01-08 13:40:32 -050064 cachedProxy = proxyProvider->findOrCreateProxyByUniqueKey(copyKey, origOrigin);
Greg Daniel2d59d2f2017-10-31 15:25:14 -040065 if (cachedProxy && (!willBeMipped || GrMipMapped::kYes == cachedProxy->mipMapped())) {
66 return cachedProxy;
Brian Osmane8e54582016-11-28 10:06:27 -050067 }
68 }
69
Greg Daniel8f5bbda2018-06-08 17:22:23 -040070 sk_sp<GrTextureProxy> source;
Stan Ilievba81af22017-06-08 15:16:53 -040071 if (original) {
Greg Daniel8f5bbda2018-06-08 17:22:23 -040072 source = std::move(original);
Greg Daniel2d59d2f2017-10-31 15:25:14 -040073 } else if (cachedProxy) {
Greg Daniel8f5bbda2018-06-08 17:22:23 -040074 source = cachedProxy;
Stan Ilievba81af22017-06-08 15:16:53 -040075 } else {
Greg Daniel2d59d2f2017-10-31 15:25:14 -040076 // Since we will be copying this texture there is no reason to make it mipped
Greg Daniel8f5bbda2018-06-08 17:22:23 -040077 source = this->refOriginalTextureProxy(false, dstColorSpace,
Greg Daniel2d59d2f2017-10-31 15:25:14 -040078 AllowedTexGenType::kAny);
Stan Ilievba81af22017-06-08 15:16:53 -040079 }
Greg Daniel8f5bbda2018-06-08 17:22:23 -040080
81 if (!source) {
Greg Daniel2d59d2f2017-10-31 15:25:14 -040082 return nullptr;
83 }
84
Greg Daniel8f5bbda2018-06-08 17:22:23 -040085 sk_sp<GrTextureProxy> result = CopyOnGpu(fContext, source, copyParams, willBeMipped);
Stan Ilievba81af22017-06-08 15:16:53 -040086
Brian Osmane8e54582016-11-28 10:06:27 -050087 if (!result) {
Greg Daniel8f5bbda2018-06-08 17:22:23 -040088 // If we were unable to make a copy and we only needed a copy for mips, then we will return
89 // the source texture here and require that the GPU backend is able to fall back to using
90 // bilerp if mips are required.
91 if (needsCopyForMipsOnly) {
92 return source;
93 }
Brian Osmane8e54582016-11-28 10:06:27 -050094 return nullptr;
95 }
96
97 if (copyKey.isValid()) {
Robert Phillipsd3e247f2017-07-25 08:00:17 -040098 SkASSERT(result->origin() == origOrigin);
Greg Daniel2d59d2f2017-10-31 15:25:14 -040099 if (cachedProxy) {
100 SkASSERT(GrMipMapped::kYes == result->mipMapped() &&
101 GrMipMapped::kNo == cachedProxy->mipMapped());
102 // If we had a cachedProxy, that means there already is a proxy in the cache which
103 // matches the key, but it does not have mip levels and we require them. Thus we must
104 // remove the unique key from that proxy.
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500105 proxyProvider->removeUniqueKeyFromProxy(copyKey, cachedProxy.get());
Greg Daniel2d59d2f2017-10-31 15:25:14 -0400106 }
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500107 proxyProvider->assignUniqueKeyToProxy(copyKey, result.get());
Brian Salomon238069b2018-07-11 15:58:57 -0400108 this->didCacheCopy(copyKey, proxyProvider->contextUniqueID());
Brian Osmane8e54582016-11-28 10:06:27 -0500109 }
110 return result;
111}
112
Brian Salomonaff329b2017-08-11 09:40:37 -0400113std::unique_ptr<GrFragmentProcessor> GrTextureMaker::createFragmentProcessor(
114 const SkMatrix& textureMatrix,
115 const SkRect& constraintRect,
116 FilterConstraint filterConstraint,
117 bool coordsLimitedToConstraintRect,
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400118 const GrSamplerState::Filter* filterOrNullForBicubic,
Brian Salomonaff329b2017-08-11 09:40:37 -0400119 SkColorSpace* dstColorSpace) {
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400120 const GrSamplerState::Filter* fmForDetermineDomain = filterOrNullForBicubic;
121 if (filterOrNullForBicubic && GrSamplerState::Filter::kMipMap == *filterOrNullForBicubic &&
Brian Osmane8e54582016-11-28 10:06:27 -0500122 kYes_FilterConstraint == filterConstraint) {
123 // TODo: Here we should force a copy restricted to the constraintRect since MIP maps will
124 // read outside the constraint rect. However, as in the adjuster case, we aren't currently
125 // doing that.
126 // We instead we compute the domain as though were bilerping which is only correct if we
127 // only sample level 0.
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400128 static const GrSamplerState::Filter kBilerp = GrSamplerState::Filter::kBilerp;
Brian Osmane8e54582016-11-28 10:06:27 -0500129 fmForDetermineDomain = &kBilerp;
130 }
131
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400132 GrSamplerState samplerState;
Brian Osmane8e54582016-11-28 10:06:27 -0500133 if (filterOrNullForBicubic) {
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400134 samplerState = GrSamplerState(GrSamplerState::WrapMode::kClamp, *filterOrNullForBicubic);
Brian Osmane8e54582016-11-28 10:06:27 -0500135 } else {
136 // Bicubic doesn't use filtering for it's texture accesses.
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400137 samplerState = GrSamplerState::ClampNearest();
Brian Osmane8e54582016-11-28 10:06:27 -0500138 }
139 sk_sp<SkColorSpace> texColorSpace;
Robert Phillips67c18d62017-01-20 12:44:06 -0500140 SkScalar scaleAdjust[2] = { 1.0f, 1.0f };
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400141 sk_sp<GrTextureProxy> proxy(this->refTextureProxyForParams(samplerState, dstColorSpace,
142 &texColorSpace, scaleAdjust));
Robert Phillips3798c862017-03-27 11:08:16 -0400143 if (!proxy) {
Brian Osmane8e54582016-11-28 10:06:27 -0500144 return nullptr;
145 }
Robert Phillips67c18d62017-01-20 12:44:06 -0500146 SkMatrix adjustedMatrix = textureMatrix;
147 adjustedMatrix.postScale(scaleAdjust[0], scaleAdjust[1]);
Brian Osmane8e54582016-11-28 10:06:27 -0500148 SkRect domain;
149 DomainMode domainMode =
Brian Salomon4df00922017-09-07 16:34:11 +0000150 DetermineDomainMode(constraintRect, filterConstraint, coordsLimitedToConstraintRect,
Greg Danielc77085d2017-11-01 16:38:48 -0400151 proxy.get(), fmForDetermineDomain, &domain);
Brian Osmane8e54582016-11-28 10:06:27 -0500152 SkASSERT(kTightCopy_DomainMode != domainMode);
Brian Osman5e341672017-10-18 10:23:18 -0400153 auto fp = CreateFragmentProcessorForDomainAndFilter(std::move(proxy), adjustedMatrix,
154 domainMode, domain, filterOrNullForBicubic);
Brian Osman21fc5ce2018-08-27 20:36:19 +0000155 return GrColorSpaceXformEffect::Make(std::move(fp), texColorSpace.get(), this->alphaType(),
156 dstColorSpace);
Brian Osmane8e54582016-11-28 10:06:27 -0500157}