GrTextureMaker.cpp revision f35fd8d2f26ef7217368d1a09d231ee68ed0cb2f
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 "GrTextureMaker.h"
9
10#include "GrColorSpaceXform.h"
11#include "GrContext.h"
12#include "GrContextPriv.h"
13#include "GrGpu.h"
14#include "GrProxyProvider.h"
15
16sk_sp<GrTextureProxy> GrTextureMaker::refTextureProxyForParams(const GrSamplerState& params,
17                                                               SkColorSpace* dstColorSpace,
18                                                               sk_sp<SkColorSpace>* texColorSpace,
19                                                               SkScalar scaleAdjust[2]) {
20    CopyParams copyParams;
21    bool willBeMipped = params.filter() == GrSamplerState::Filter::kMipMap;
22
23    if (!fContext->caps()->mipMapSupport()) {
24        willBeMipped = false;
25    }
26
27    if (texColorSpace) {
28        *texColorSpace = this->getColorSpace(dstColorSpace);
29    }
30
31    GrGpu* gpu = fContext->contextPriv().getGpu();
32    sk_sp<GrTextureProxy> original(this->refOriginalTextureProxy(willBeMipped, dstColorSpace,
33                                                                 AllowedTexGenType::kCheap));
34    if (original) {
35        if (!gpu->isACopyNeededForTextureParams(original.get(), params, &copyParams, scaleAdjust)) {
36            return original;
37        }
38    } else {
39        if (!gpu->isACopyNeededForTextureParams(this->width(), this->height(),
40                                                params, &copyParams, scaleAdjust)) {
41            return this->refOriginalTextureProxy(willBeMipped, dstColorSpace,
42                                                 AllowedTexGenType::kAny);
43        }
44    }
45
46    GrProxyProvider* proxyProvider = fContext->contextPriv().proxyProvider();
47
48    GrSurfaceOrigin origOrigin = original ? original->origin() : kTopLeft_GrSurfaceOrigin;
49    GrUniqueKey copyKey;
50    this->makeCopyKey(copyParams, &copyKey, dstColorSpace);
51    sk_sp<GrTextureProxy> cachedProxy;
52    if (copyKey.isValid()) {
53        cachedProxy = proxyProvider->findOrCreateProxyByUniqueKey(copyKey, origOrigin);
54        if (cachedProxy && (!willBeMipped || GrMipMapped::kYes == cachedProxy->mipMapped())) {
55            return cachedProxy;
56        }
57    }
58
59    sk_sp<GrTextureProxy> result;
60    if (original) {
61        result = std::move(original);
62    } else if (cachedProxy) {
63        result = cachedProxy;
64    } else {
65        // Since we will be copying this texture there is no reason to make it mipped
66        result = this->refOriginalTextureProxy(false, dstColorSpace,
67                                               AllowedTexGenType::kAny);
68    }
69    if (!result) {
70        return nullptr;
71    }
72
73    result = CopyOnGpu(fContext, std::move(result), copyParams, willBeMipped);
74
75    if (!result) {
76        return nullptr;
77    }
78
79    if (copyKey.isValid()) {
80        SkASSERT(result->origin() == origOrigin);
81        if (cachedProxy) {
82            SkASSERT(GrMipMapped::kYes == result->mipMapped() &&
83                     GrMipMapped::kNo == cachedProxy->mipMapped());
84            // If we had a cachedProxy, that means there already is a proxy in the cache which
85            // matches the key, but it does not have mip levels and we require them. Thus we must
86            // remove the unique key from that proxy.
87            proxyProvider->removeUniqueKeyFromProxy(copyKey, cachedProxy.get());
88        }
89        proxyProvider->assignUniqueKeyToProxy(copyKey, result.get());
90        this->didCacheCopy(copyKey);
91    }
92    return result;
93}
94
95std::unique_ptr<GrFragmentProcessor> GrTextureMaker::createFragmentProcessor(
96        const SkMatrix& textureMatrix,
97        const SkRect& constraintRect,
98        FilterConstraint filterConstraint,
99        bool coordsLimitedToConstraintRect,
100        const GrSamplerState::Filter* filterOrNullForBicubic,
101        SkColorSpace* dstColorSpace) {
102    const GrSamplerState::Filter* fmForDetermineDomain = filterOrNullForBicubic;
103    if (filterOrNullForBicubic && GrSamplerState::Filter::kMipMap == *filterOrNullForBicubic &&
104        kYes_FilterConstraint == filterConstraint) {
105        // TODo: Here we should force a copy restricted to the constraintRect since MIP maps will
106        // read outside the constraint rect. However, as in the adjuster case, we aren't currently
107        // doing that.
108        // We instead we compute the domain as though were bilerping which is only correct if we
109        // only sample level 0.
110        static const GrSamplerState::Filter kBilerp = GrSamplerState::Filter::kBilerp;
111        fmForDetermineDomain = &kBilerp;
112    }
113
114    GrSamplerState samplerState;
115    if (filterOrNullForBicubic) {
116        samplerState = GrSamplerState(GrSamplerState::WrapMode::kClamp, *filterOrNullForBicubic);
117    } else {
118        // Bicubic doesn't use filtering for it's texture accesses.
119        samplerState = GrSamplerState::ClampNearest();
120    }
121    sk_sp<SkColorSpace> texColorSpace;
122    SkScalar scaleAdjust[2] = { 1.0f, 1.0f };
123    sk_sp<GrTextureProxy> proxy(this->refTextureProxyForParams(samplerState, dstColorSpace,
124                                                               &texColorSpace, scaleAdjust));
125    if (!proxy) {
126        return nullptr;
127    }
128    SkMatrix adjustedMatrix = textureMatrix;
129    adjustedMatrix.postScale(scaleAdjust[0], scaleAdjust[1]);
130    SkRect domain;
131    DomainMode domainMode =
132        DetermineDomainMode(constraintRect, filterConstraint, coordsLimitedToConstraintRect,
133                            proxy.get(), fmForDetermineDomain, &domain);
134    SkASSERT(kTightCopy_DomainMode != domainMode);
135    GrPixelConfig config = proxy->config();
136    auto fp = CreateFragmentProcessorForDomainAndFilter(std::move(proxy), adjustedMatrix,
137                                                        domainMode, domain, filterOrNullForBicubic);
138    return GrColorSpaceXformEffect::Make(std::move(fp), texColorSpace.get(), config, dstColorSpace);
139}
140
141sk_sp<GrTextureProxy> GrTextureMaker::generateTextureProxyForParams(const CopyParams& copyParams,
142                                                                    bool willBeMipped,
143                                                                    SkColorSpace* dstColorSpace) {
144    sk_sp<GrTextureProxy> original(this->refOriginalTextureProxy(willBeMipped, dstColorSpace,
145                                                                 AllowedTexGenType::kAny));
146    if (!original) {
147        return nullptr;
148    }
149
150    return CopyOnGpu(fContext, std::move(original), copyParams, willBeMipped);
151}
152