• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 "src/gpu/GrTextureMaker.h"
9 
10 #include "include/private/GrRecordingContext.h"
11 #include "src/gpu/GrColorSpaceXform.h"
12 #include "src/gpu/GrGpu.h"
13 #include "src/gpu/GrProxyProvider.h"
14 #include "src/gpu/GrRecordingContextPriv.h"
15 
onRefTextureProxyForParams(const GrSamplerState & params,bool willBeMipped,SkScalar scaleAdjust[2])16 sk_sp<GrTextureProxy> GrTextureMaker::onRefTextureProxyForParams(const GrSamplerState& params,
17                                                                  bool willBeMipped,
18                                                                  SkScalar scaleAdjust[2]) {
19     if (this->width() > this->context()->priv().caps()->maxTextureSize() ||
20         this->height() > this->context()->priv().caps()->maxTextureSize()) {
21         return nullptr;
22     }
23 
24     CopyParams copyParams;
25 
26     sk_sp<GrTextureProxy> original(this->refOriginalTextureProxy(willBeMipped,
27                                                                  AllowedTexGenType::kCheap));
28     bool needsCopyForMipsOnly = false;
29     if (original) {
30         if (!params.isRepeated() ||
31             !GrGpu::IsACopyNeededForRepeatWrapMode(this->context()->priv().caps(), original.get(),
32                                                    original->width(), original->height(),
33                                                    params.filter(), &copyParams, scaleAdjust)) {
34             needsCopyForMipsOnly = GrGpu::IsACopyNeededForMips(this->context()->priv().caps(),
35                                                                original.get(), params.filter(),
36                                                                &copyParams);
37             if (!needsCopyForMipsOnly) {
38                 return original;
39             }
40         }
41     } else {
42         if (!params.isRepeated() ||
43             !GrGpu::IsACopyNeededForRepeatWrapMode(this->context()->priv().caps(), nullptr,
44                                                    this->width(), this->height(),
45                                                    params.filter(), &copyParams, scaleAdjust)) {
46             return this->refOriginalTextureProxy(willBeMipped, AllowedTexGenType::kAny);
47         }
48     }
49 
50     GrProxyProvider* proxyProvider = this->context()->priv().proxyProvider();
51 
52     GrSurfaceOrigin origOrigin = original ? original->origin() : kTopLeft_GrSurfaceOrigin;
53     GrUniqueKey copyKey;
54     this->makeCopyKey(copyParams, &copyKey);
55     sk_sp<GrTextureProxy> cachedProxy;
56     if (copyKey.isValid()) {
57         cachedProxy =
58                 proxyProvider->findOrCreateProxyByUniqueKey(copyKey, this->colorType(), origOrigin);
59         if (cachedProxy && (!willBeMipped || GrMipMapped::kYes == cachedProxy->mipMapped())) {
60             return cachedProxy;
61         }
62     }
63 
64     sk_sp<GrTextureProxy> source;
65     if (original) {
66         source = std::move(original);
67     } else if (cachedProxy) {
68         source = cachedProxy;
69     } else {
70         // Since we will be copying this texture there is no reason to make it mipped
71         source = this->refOriginalTextureProxy(false, AllowedTexGenType::kAny);
72     }
73 
74     if (!source) {
75         return nullptr;
76     }
77 
78     sk_sp<GrTextureProxy> result =
79             CopyOnGpu(this->context(), source, this->colorType(), copyParams, willBeMipped);
80 
81     if (!result) {
82         // If we were unable to make a copy and we only needed a copy for mips, then we will return
83         // the source texture here and require that the GPU backend is able to fall back to using
84         // bilerp if mips are required.
85         if (needsCopyForMipsOnly) {
86             return source;
87         }
88         return nullptr;
89     }
90 
91     if (copyKey.isValid()) {
92         SkASSERT(result->origin() == origOrigin);
93         if (cachedProxy) {
94             SkASSERT(GrMipMapped::kYes == result->mipMapped() &&
95                      GrMipMapped::kNo == cachedProxy->mipMapped());
96             // If we had a cachedProxy, that means there already is a proxy in the cache which
97             // matches the key, but it does not have mip levels and we require them. Thus we must
98             // remove the unique key from that proxy.
99             SkASSERT(cachedProxy->getUniqueKey() == copyKey);
100             proxyProvider->removeUniqueKeyFromProxy(cachedProxy.get());
101         }
102         proxyProvider->assignUniqueKeyToProxy(copyKey, result.get());
103         this->didCacheCopy(copyKey, proxyProvider->contextID());
104     }
105     return result;
106 }
107 
createFragmentProcessor(const SkMatrix & textureMatrix,const SkRect & constraintRect,FilterConstraint filterConstraint,bool coordsLimitedToConstraintRect,const GrSamplerState::Filter * filterOrNullForBicubic)108 std::unique_ptr<GrFragmentProcessor> GrTextureMaker::createFragmentProcessor(
109         const SkMatrix& textureMatrix,
110         const SkRect& constraintRect,
111         FilterConstraint filterConstraint,
112         bool coordsLimitedToConstraintRect,
113         const GrSamplerState::Filter* filterOrNullForBicubic) {
114     const GrSamplerState::Filter* fmForDetermineDomain = filterOrNullForBicubic;
115     if (filterOrNullForBicubic && GrSamplerState::Filter::kMipMap == *filterOrNullForBicubic &&
116         kYes_FilterConstraint == filterConstraint) {
117         // TODO: Here we should force a copy restricted to the constraintRect since MIP maps will
118         // read outside the constraint rect. However, as in the adjuster case, we aren't currently
119         // doing that.
120         // We instead we compute the domain as though were bilerping which is only correct if we
121         // only sample level 0.
122         static const GrSamplerState::Filter kBilerp = GrSamplerState::Filter::kBilerp;
123         fmForDetermineDomain = &kBilerp;
124     }
125 
126     SkScalar scaleAdjust[2] = { 1.0f, 1.0f };
127     sk_sp<GrTextureProxy> proxy(this->refTextureProxyForParams(filterOrNullForBicubic,
128                                                                scaleAdjust));
129     if (!proxy) {
130         return nullptr;
131     }
132     SkMatrix adjustedMatrix = textureMatrix;
133     adjustedMatrix.postScale(scaleAdjust[0], scaleAdjust[1]);
134 
135     SkRect domain;
136     DomainMode domainMode =
137         DetermineDomainMode(constraintRect, filterConstraint, coordsLimitedToConstraintRect,
138                             proxy.get(), fmForDetermineDomain, &domain);
139     SkASSERT(kTightCopy_DomainMode != domainMode);
140     return this->createFragmentProcessorForDomainAndFilter(
141             std::move(proxy), adjustedMatrix, domainMode, domain, filterOrNullForBicubic);
142 }
143