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 "GrContext.h"
11#include "GrGpu.h"
12#include "GrResourceProvider.h"
13
14sk_sp<GrTextureProxy> GrTextureMaker::refTextureProxyForParams(const GrSamplerParams& params,
15                                                               SkColorSpace* dstColorSpace,
16                                                               sk_sp<SkColorSpace>* texColorSpace,
17                                                               SkScalar scaleAdjust[2]) {
18    CopyParams copyParams;
19    bool willBeMipped = params.filterMode() == GrSamplerParams::kMipMap_FilterMode;
20
21    if (!fContext->caps()->mipMapSupport()) {
22        willBeMipped = false;
23    }
24
25    if (texColorSpace) {
26        *texColorSpace = this->getColorSpace(dstColorSpace);
27    }
28
29    if (!fContext->getGpu()->isACopyNeededForTextureParams(this->width(), this->height(), params,
30                                                           &copyParams, scaleAdjust)) {
31        return this->refOriginalTextureProxy(willBeMipped, dstColorSpace);
32    }
33    GrUniqueKey copyKey;
34    this->makeCopyKey(copyParams, &copyKey, dstColorSpace);
35    if (copyKey.isValid()) {
36        sk_sp<GrTextureProxy> result(fContext->resourceProvider()->findProxyByUniqueKey(copyKey));
37        if (result) {
38            return result;
39        }
40    }
41
42    sk_sp<GrTextureProxy> result(this->generateTextureProxyForParams(copyParams, willBeMipped,
43                                                                     dstColorSpace));
44    if (!result) {
45        return nullptr;
46    }
47
48    if (copyKey.isValid()) {
49        fContext->resourceProvider()->assignUniqueKeyToProxy(copyKey, result.get());
50        this->didCacheCopy(copyKey);
51    }
52    return result;
53}
54
55sk_sp<GrFragmentProcessor> GrTextureMaker::createFragmentProcessor(
56                                        const SkMatrix& textureMatrix,
57                                        const SkRect& constraintRect,
58                                        FilterConstraint filterConstraint,
59                                        bool coordsLimitedToConstraintRect,
60                                        const GrSamplerParams::FilterMode* filterOrNullForBicubic,
61                                        SkColorSpace* dstColorSpace) {
62
63    const GrSamplerParams::FilterMode* fmForDetermineDomain = filterOrNullForBicubic;
64    if (filterOrNullForBicubic && GrSamplerParams::kMipMap_FilterMode == *filterOrNullForBicubic &&
65        kYes_FilterConstraint == filterConstraint) {
66        // TODo: Here we should force a copy restricted to the constraintRect since MIP maps will
67        // read outside the constraint rect. However, as in the adjuster case, we aren't currently
68        // doing that.
69        // We instead we compute the domain as though were bilerping which is only correct if we
70        // only sample level 0.
71        static const GrSamplerParams::FilterMode kBilerp = GrSamplerParams::kBilerp_FilterMode;
72        fmForDetermineDomain = &kBilerp;
73    }
74
75    GrSamplerParams params;
76    if (filterOrNullForBicubic) {
77        params.reset(SkShader::kClamp_TileMode, *filterOrNullForBicubic);
78    } else {
79        // Bicubic doesn't use filtering for it's texture accesses.
80        params.reset(SkShader::kClamp_TileMode, GrSamplerParams::kNone_FilterMode);
81    }
82    sk_sp<SkColorSpace> texColorSpace;
83    SkScalar scaleAdjust[2] = { 1.0f, 1.0f };
84    sk_sp<GrTextureProxy> proxy(this->refTextureProxyForParams(params, dstColorSpace,
85                                                               &texColorSpace,
86                                                               scaleAdjust));
87    if (!proxy) {
88        return nullptr;
89    }
90    SkMatrix adjustedMatrix = textureMatrix;
91    adjustedMatrix.postScale(scaleAdjust[0], scaleAdjust[1]);
92    SkRect domain;
93    DomainMode domainMode =
94        DetermineDomainMode(constraintRect, filterConstraint, coordsLimitedToConstraintRect,
95                            proxy.get(),
96                            nullptr, fmForDetermineDomain, &domain);
97    SkASSERT(kTightCopy_DomainMode != domainMode);
98    sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(texColorSpace.get(),
99                                                                       dstColorSpace);
100    return CreateFragmentProcessorForDomainAndFilter(fContext->resourceProvider(), std::move(proxy),
101                                                     std::move(colorSpaceXform),
102                                                     adjustedMatrix, domainMode, domain,
103                                                     filterOrNullForBicubic);
104}
105
106sk_sp<GrTextureProxy> GrTextureMaker::generateTextureProxyForParams(const CopyParams& copyParams,
107                                                                    bool willBeMipped,
108                                                                    SkColorSpace* dstColorSpace) {
109    sk_sp<GrTextureProxy> original(this->refOriginalTextureProxy(willBeMipped, dstColorSpace));
110    if (!original) {
111        return nullptr;
112    }
113
114    return CopyOnGpu(fContext, std::move(original), nullptr, copyParams);
115}
116