blob: 22870cc7c85b0d368a828873adf0ee42348d4753 [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,
19 SkScalar scaleAdjust[2]) {
Brian Salomonc7fe0f72018-05-11 10:14:21 -040020 if (this->width() > fContext->contextPriv().caps()->maxTextureSize() ||
21 this->height() > fContext->contextPriv().caps()->maxTextureSize()) {
Brian Osman875f7852018-04-12 13:29:08 -040022 return nullptr;
23 }
24
Brian Osmane8e54582016-11-28 10:06:27 -050025 CopyParams copyParams;
Brian Salomon2bbdcc42017-09-07 12:36:34 -040026 bool willBeMipped = params.filter() == GrSamplerState::Filter::kMipMap;
Brian Osmane8e54582016-11-28 10:06:27 -050027
Brian Salomonc7fe0f72018-05-11 10:14:21 -040028 if (!fContext->contextPriv().caps()->mipMapSupport()) {
Brian Osmane8e54582016-11-28 10:06:27 -050029 willBeMipped = false;
30 }
31
32 if (texColorSpace) {
Brian Osman61624f02016-12-09 14:51:59 -050033 *texColorSpace = this->getColorSpace(dstColorSpace);
Brian Osmane8e54582016-11-28 10:06:27 -050034 }
35
Stan Ilievba81af22017-06-08 15:16:53 -040036 sk_sp<GrTextureProxy> original(this->refOriginalTextureProxy(willBeMipped, dstColorSpace,
37 AllowedTexGenType::kCheap));
Greg Daniel8f5bbda2018-06-08 17:22:23 -040038 bool needsCopyForMipsOnly = false;
Stan Ilievba81af22017-06-08 15:16:53 -040039 if (original) {
Greg Daniel8f5bbda2018-06-08 17:22:23 -040040 if (!params.isRepeated() ||
41 !GrGpu::IsACopyNeededForRepeatWrapMode(fContext->contextPriv().caps(), original.get(),
42 original->width(), original->height(),
43 params.filter(), &copyParams, scaleAdjust)) {
44 needsCopyForMipsOnly = GrGpu::IsACopyNeededForMips(fContext->contextPriv().caps(),
45 original.get(), params.filter(),
46 &copyParams);
47 if (!needsCopyForMipsOnly) {
48 return original;
49 }
Stan Ilievba81af22017-06-08 15:16:53 -040050 }
51 } else {
Greg Daniel8f5bbda2018-06-08 17:22:23 -040052 if (!params.isRepeated() ||
53 !GrGpu::IsACopyNeededForRepeatWrapMode(fContext->contextPriv().caps(), nullptr,
54 this->width(), this->height(),
55 params.filter(), &copyParams, scaleAdjust)) {
Stan Ilievba81af22017-06-08 15:16:53 -040056 return this->refOriginalTextureProxy(willBeMipped, dstColorSpace,
57 AllowedTexGenType::kAny);
58 }
Brian Osmane8e54582016-11-28 10:06:27 -050059 }
Stan Ilievba81af22017-06-08 15:16:53 -040060
Robert Phillips1afd4cd2018-01-08 13:40:32 -050061 GrProxyProvider* proxyProvider = fContext->contextPriv().proxyProvider();
62
63 GrSurfaceOrigin origOrigin = original ? original->origin() : kTopLeft_GrSurfaceOrigin;
Brian Osmane8e54582016-11-28 10:06:27 -050064 GrUniqueKey copyKey;
Brian Osman61624f02016-12-09 14:51:59 -050065 this->makeCopyKey(copyParams, &copyKey, dstColorSpace);
Greg Daniel2d59d2f2017-10-31 15:25:14 -040066 sk_sp<GrTextureProxy> cachedProxy;
Brian Osmane8e54582016-11-28 10:06:27 -050067 if (copyKey.isValid()) {
Robert Phillips1afd4cd2018-01-08 13:40:32 -050068 cachedProxy = proxyProvider->findOrCreateProxyByUniqueKey(copyKey, origOrigin);
Greg Daniel2d59d2f2017-10-31 15:25:14 -040069 if (cachedProxy && (!willBeMipped || GrMipMapped::kYes == cachedProxy->mipMapped())) {
70 return cachedProxy;
Brian Osmane8e54582016-11-28 10:06:27 -050071 }
72 }
73
Greg Daniel8f5bbda2018-06-08 17:22:23 -040074 sk_sp<GrTextureProxy> source;
Stan Ilievba81af22017-06-08 15:16:53 -040075 if (original) {
Greg Daniel8f5bbda2018-06-08 17:22:23 -040076 source = std::move(original);
Greg Daniel2d59d2f2017-10-31 15:25:14 -040077 } else if (cachedProxy) {
Greg Daniel8f5bbda2018-06-08 17:22:23 -040078 source = cachedProxy;
Stan Ilievba81af22017-06-08 15:16:53 -040079 } else {
Greg Daniel2d59d2f2017-10-31 15:25:14 -040080 // Since we will be copying this texture there is no reason to make it mipped
Greg Daniel8f5bbda2018-06-08 17:22:23 -040081 source = this->refOriginalTextureProxy(false, dstColorSpace,
Greg Daniel2d59d2f2017-10-31 15:25:14 -040082 AllowedTexGenType::kAny);
Stan Ilievba81af22017-06-08 15:16:53 -040083 }
Greg Daniel8f5bbda2018-06-08 17:22:23 -040084
85 if (!source) {
Greg Daniel2d59d2f2017-10-31 15:25:14 -040086 return nullptr;
87 }
88
Greg Daniel8f5bbda2018-06-08 17:22:23 -040089 sk_sp<GrTextureProxy> result = CopyOnGpu(fContext, source, copyParams, willBeMipped);
Stan Ilievba81af22017-06-08 15:16:53 -040090
Brian Osmane8e54582016-11-28 10:06:27 -050091 if (!result) {
Greg Daniel8f5bbda2018-06-08 17:22:23 -040092 // If we were unable to make a copy and we only needed a copy for mips, then we will return
93 // the source texture here and require that the GPU backend is able to fall back to using
94 // bilerp if mips are required.
95 if (needsCopyForMipsOnly) {
96 return source;
97 }
Brian Osmane8e54582016-11-28 10:06:27 -050098 return nullptr;
99 }
100
101 if (copyKey.isValid()) {
Robert Phillipsd3e247f2017-07-25 08:00:17 -0400102 SkASSERT(result->origin() == origOrigin);
Greg Daniel2d59d2f2017-10-31 15:25:14 -0400103 if (cachedProxy) {
104 SkASSERT(GrMipMapped::kYes == result->mipMapped() &&
105 GrMipMapped::kNo == cachedProxy->mipMapped());
106 // If we had a cachedProxy, that means there already is a proxy in the cache which
107 // matches the key, but it does not have mip levels and we require them. Thus we must
108 // remove the unique key from that proxy.
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500109 proxyProvider->removeUniqueKeyFromProxy(copyKey, cachedProxy.get());
Greg Daniel2d59d2f2017-10-31 15:25:14 -0400110 }
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500111 proxyProvider->assignUniqueKeyToProxy(copyKey, result.get());
Brian Salomon238069b2018-07-11 15:58:57 -0400112 this->didCacheCopy(copyKey, proxyProvider->contextUniqueID());
Brian Osmane8e54582016-11-28 10:06:27 -0500113 }
114 return result;
115}
116
Brian Salomonaff329b2017-08-11 09:40:37 -0400117std::unique_ptr<GrFragmentProcessor> GrTextureMaker::createFragmentProcessor(
118 const SkMatrix& textureMatrix,
119 const SkRect& constraintRect,
120 FilterConstraint filterConstraint,
121 bool coordsLimitedToConstraintRect,
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400122 const GrSamplerState::Filter* filterOrNullForBicubic,
Brian Salomonaff329b2017-08-11 09:40:37 -0400123 SkColorSpace* dstColorSpace) {
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400124 const GrSamplerState::Filter* fmForDetermineDomain = filterOrNullForBicubic;
125 if (filterOrNullForBicubic && GrSamplerState::Filter::kMipMap == *filterOrNullForBicubic &&
Brian Osmane8e54582016-11-28 10:06:27 -0500126 kYes_FilterConstraint == filterConstraint) {
127 // TODo: Here we should force a copy restricted to the constraintRect since MIP maps will
128 // read outside the constraint rect. However, as in the adjuster case, we aren't currently
129 // doing that.
130 // We instead we compute the domain as though were bilerping which is only correct if we
131 // only sample level 0.
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400132 static const GrSamplerState::Filter kBilerp = GrSamplerState::Filter::kBilerp;
Brian Osmane8e54582016-11-28 10:06:27 -0500133 fmForDetermineDomain = &kBilerp;
134 }
135
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400136 GrSamplerState samplerState;
Brian Osmane8e54582016-11-28 10:06:27 -0500137 if (filterOrNullForBicubic) {
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400138 samplerState = GrSamplerState(GrSamplerState::WrapMode::kClamp, *filterOrNullForBicubic);
Brian Osmane8e54582016-11-28 10:06:27 -0500139 } else {
140 // Bicubic doesn't use filtering for it's texture accesses.
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400141 samplerState = GrSamplerState::ClampNearest();
Brian Osmane8e54582016-11-28 10:06:27 -0500142 }
143 sk_sp<SkColorSpace> texColorSpace;
Robert Phillips67c18d62017-01-20 12:44:06 -0500144 SkScalar scaleAdjust[2] = { 1.0f, 1.0f };
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400145 sk_sp<GrTextureProxy> proxy(this->refTextureProxyForParams(samplerState, dstColorSpace,
146 &texColorSpace, scaleAdjust));
Robert Phillips3798c862017-03-27 11:08:16 -0400147 if (!proxy) {
Brian Osmane8e54582016-11-28 10:06:27 -0500148 return nullptr;
149 }
Robert Phillips67c18d62017-01-20 12:44:06 -0500150 SkMatrix adjustedMatrix = textureMatrix;
151 adjustedMatrix.postScale(scaleAdjust[0], scaleAdjust[1]);
Brian Osmane8e54582016-11-28 10:06:27 -0500152 SkRect domain;
153 DomainMode domainMode =
Brian Salomon4df00922017-09-07 16:34:11 +0000154 DetermineDomainMode(constraintRect, filterConstraint, coordsLimitedToConstraintRect,
Greg Danielc77085d2017-11-01 16:38:48 -0400155 proxy.get(), fmForDetermineDomain, &domain);
Brian Osmane8e54582016-11-28 10:06:27 -0500156 SkASSERT(kTightCopy_DomainMode != domainMode);
Brian Osman5e341672017-10-18 10:23:18 -0400157 auto fp = CreateFragmentProcessorForDomainAndFilter(std::move(proxy), adjustedMatrix,
158 domainMode, domain, filterOrNullForBicubic);
Brian Osman653f34d2018-06-14 11:44:02 -0400159 return GrColorSpaceXformEffect::Make(std::move(fp), texColorSpace.get(), dstColorSpace);
Brian Osmane8e54582016-11-28 10:06:27 -0500160}