1e8e54580c3c91fd485187af040af118aa5153261Brian Osman/*
2e8e54580c3c91fd485187af040af118aa5153261Brian Osman * Copyright 2016 Google Inc.
3e8e54580c3c91fd485187af040af118aa5153261Brian Osman *
4e8e54580c3c91fd485187af040af118aa5153261Brian Osman * Use of this source code is governed by a BSD-style license that can be
5e8e54580c3c91fd485187af040af118aa5153261Brian Osman * found in the LICENSE file.
6e8e54580c3c91fd485187af040af118aa5153261Brian Osman */
7e8e54580c3c91fd485187af040af118aa5153261Brian Osman
8e8e54580c3c91fd485187af040af118aa5153261Brian Osman#include "GrTextureMaker.h"
9e8e54580c3c91fd485187af040af118aa5153261Brian Osman
10e8e54580c3c91fd485187af040af118aa5153261Brian Osman#include "GrContext.h"
11e8e54580c3c91fd485187af040af118aa5153261Brian Osman#include "GrGpu.h"
1232342f032e1dfd133040324f851f0365f9d4cb51Brian Osman#include "GrResourceProvider.h"
13e8e54580c3c91fd485187af040af118aa5153261Brian Osman
143798c86f6885f0b47fb2e659a43b48a4468a97efRobert Phillipssk_sp<GrTextureProxy> GrTextureMaker::refTextureProxyForParams(const GrSamplerParams& params,
153798c86f6885f0b47fb2e659a43b48a4468a97efRobert Phillips                                                               SkColorSpace* dstColorSpace,
163798c86f6885f0b47fb2e659a43b48a4468a97efRobert Phillips                                                               sk_sp<SkColorSpace>* texColorSpace,
173798c86f6885f0b47fb2e659a43b48a4468a97efRobert Phillips                                                               SkScalar scaleAdjust[2]) {
18e8e54580c3c91fd485187af040af118aa5153261Brian Osman    CopyParams copyParams;
19e8e54580c3c91fd485187af040af118aa5153261Brian Osman    bool willBeMipped = params.filterMode() == GrSamplerParams::kMipMap_FilterMode;
20e8e54580c3c91fd485187af040af118aa5153261Brian Osman
21e8e54580c3c91fd485187af040af118aa5153261Brian Osman    if (!fContext->caps()->mipMapSupport()) {
22e8e54580c3c91fd485187af040af118aa5153261Brian Osman        willBeMipped = false;
23e8e54580c3c91fd485187af040af118aa5153261Brian Osman    }
24e8e54580c3c91fd485187af040af118aa5153261Brian Osman
25e8e54580c3c91fd485187af040af118aa5153261Brian Osman    if (texColorSpace) {
2661624f0c716b576706659750d87b6956f4c15722Brian Osman        *texColorSpace = this->getColorSpace(dstColorSpace);
27e8e54580c3c91fd485187af040af118aa5153261Brian Osman    }
28e8e54580c3c91fd485187af040af118aa5153261Brian Osman
2981444fbc22d09c92f6c577254c6c82dfa9967391Robert Phillips    if (!fContext->getGpu()->isACopyNeededForTextureParams(this->width(), this->height(), params,
3081444fbc22d09c92f6c577254c6c82dfa9967391Robert Phillips                                                           &copyParams, scaleAdjust)) {
313798c86f6885f0b47fb2e659a43b48a4468a97efRobert Phillips        return this->refOriginalTextureProxy(willBeMipped, dstColorSpace);
32e8e54580c3c91fd485187af040af118aa5153261Brian Osman    }
33e8e54580c3c91fd485187af040af118aa5153261Brian Osman    GrUniqueKey copyKey;
3461624f0c716b576706659750d87b6956f4c15722Brian Osman    this->makeCopyKey(copyParams, &copyKey, dstColorSpace);
35e8e54580c3c91fd485187af040af118aa5153261Brian Osman    if (copyKey.isValid()) {
363798c86f6885f0b47fb2e659a43b48a4468a97efRobert Phillips        sk_sp<GrTextureProxy> result(fContext->resourceProvider()->findProxyByUniqueKey(copyKey));
37e8e54580c3c91fd485187af040af118aa5153261Brian Osman        if (result) {
38e8e54580c3c91fd485187af040af118aa5153261Brian Osman            return result;
39e8e54580c3c91fd485187af040af118aa5153261Brian Osman        }
40e8e54580c3c91fd485187af040af118aa5153261Brian Osman    }
41e8e54580c3c91fd485187af040af118aa5153261Brian Osman
423798c86f6885f0b47fb2e659a43b48a4468a97efRobert Phillips    sk_sp<GrTextureProxy> result(this->generateTextureProxyForParams(copyParams, willBeMipped,
433798c86f6885f0b47fb2e659a43b48a4468a97efRobert Phillips                                                                     dstColorSpace));
44e8e54580c3c91fd485187af040af118aa5153261Brian Osman    if (!result) {
45e8e54580c3c91fd485187af040af118aa5153261Brian Osman        return nullptr;
46e8e54580c3c91fd485187af040af118aa5153261Brian Osman    }
47e8e54580c3c91fd485187af040af118aa5153261Brian Osman
48e8e54580c3c91fd485187af040af118aa5153261Brian Osman    if (copyKey.isValid()) {
493798c86f6885f0b47fb2e659a43b48a4468a97efRobert Phillips        fContext->resourceProvider()->assignUniqueKeyToProxy(copyKey, result.get());
50e8e54580c3c91fd485187af040af118aa5153261Brian Osman        this->didCacheCopy(copyKey);
51e8e54580c3c91fd485187af040af118aa5153261Brian Osman    }
52e8e54580c3c91fd485187af040af118aa5153261Brian Osman    return result;
53e8e54580c3c91fd485187af040af118aa5153261Brian Osman}
54e8e54580c3c91fd485187af040af118aa5153261Brian Osman
55e8e54580c3c91fd485187af040af118aa5153261Brian Osmansk_sp<GrFragmentProcessor> GrTextureMaker::createFragmentProcessor(
56e8e54580c3c91fd485187af040af118aa5153261Brian Osman                                        const SkMatrix& textureMatrix,
57e8e54580c3c91fd485187af040af118aa5153261Brian Osman                                        const SkRect& constraintRect,
58e8e54580c3c91fd485187af040af118aa5153261Brian Osman                                        FilterConstraint filterConstraint,
59e8e54580c3c91fd485187af040af118aa5153261Brian Osman                                        bool coordsLimitedToConstraintRect,
60e8e54580c3c91fd485187af040af118aa5153261Brian Osman                                        const GrSamplerParams::FilterMode* filterOrNullForBicubic,
6161624f0c716b576706659750d87b6956f4c15722Brian Osman                                        SkColorSpace* dstColorSpace) {
62e8e54580c3c91fd485187af040af118aa5153261Brian Osman
63e8e54580c3c91fd485187af040af118aa5153261Brian Osman    const GrSamplerParams::FilterMode* fmForDetermineDomain = filterOrNullForBicubic;
64e8e54580c3c91fd485187af040af118aa5153261Brian Osman    if (filterOrNullForBicubic && GrSamplerParams::kMipMap_FilterMode == *filterOrNullForBicubic &&
65e8e54580c3c91fd485187af040af118aa5153261Brian Osman        kYes_FilterConstraint == filterConstraint) {
66e8e54580c3c91fd485187af040af118aa5153261Brian Osman        // TODo: Here we should force a copy restricted to the constraintRect since MIP maps will
67e8e54580c3c91fd485187af040af118aa5153261Brian Osman        // read outside the constraint rect. However, as in the adjuster case, we aren't currently
68e8e54580c3c91fd485187af040af118aa5153261Brian Osman        // doing that.
69e8e54580c3c91fd485187af040af118aa5153261Brian Osman        // We instead we compute the domain as though were bilerping which is only correct if we
70e8e54580c3c91fd485187af040af118aa5153261Brian Osman        // only sample level 0.
71e8e54580c3c91fd485187af040af118aa5153261Brian Osman        static const GrSamplerParams::FilterMode kBilerp = GrSamplerParams::kBilerp_FilterMode;
72e8e54580c3c91fd485187af040af118aa5153261Brian Osman        fmForDetermineDomain = &kBilerp;
73e8e54580c3c91fd485187af040af118aa5153261Brian Osman    }
74e8e54580c3c91fd485187af040af118aa5153261Brian Osman
75e8e54580c3c91fd485187af040af118aa5153261Brian Osman    GrSamplerParams params;
76e8e54580c3c91fd485187af040af118aa5153261Brian Osman    if (filterOrNullForBicubic) {
77e8e54580c3c91fd485187af040af118aa5153261Brian Osman        params.reset(SkShader::kClamp_TileMode, *filterOrNullForBicubic);
78e8e54580c3c91fd485187af040af118aa5153261Brian Osman    } else {
79e8e54580c3c91fd485187af040af118aa5153261Brian Osman        // Bicubic doesn't use filtering for it's texture accesses.
80e8e54580c3c91fd485187af040af118aa5153261Brian Osman        params.reset(SkShader::kClamp_TileMode, GrSamplerParams::kNone_FilterMode);
81e8e54580c3c91fd485187af040af118aa5153261Brian Osman    }
82e8e54580c3c91fd485187af040af118aa5153261Brian Osman    sk_sp<SkColorSpace> texColorSpace;
8367c18d6b5188a0497f6912a73d964c763d2f8f84Robert Phillips    SkScalar scaleAdjust[2] = { 1.0f, 1.0f };
843798c86f6885f0b47fb2e659a43b48a4468a97efRobert Phillips    sk_sp<GrTextureProxy> proxy(this->refTextureProxyForParams(params, dstColorSpace,
853798c86f6885f0b47fb2e659a43b48a4468a97efRobert Phillips                                                               &texColorSpace,
863798c86f6885f0b47fb2e659a43b48a4468a97efRobert Phillips                                                               scaleAdjust));
873798c86f6885f0b47fb2e659a43b48a4468a97efRobert Phillips    if (!proxy) {
88e8e54580c3c91fd485187af040af118aa5153261Brian Osman        return nullptr;
89e8e54580c3c91fd485187af040af118aa5153261Brian Osman    }
9067c18d6b5188a0497f6912a73d964c763d2f8f84Robert Phillips    SkMatrix adjustedMatrix = textureMatrix;
9167c18d6b5188a0497f6912a73d964c763d2f8f84Robert Phillips    adjustedMatrix.postScale(scaleAdjust[0], scaleAdjust[1]);
92e8e54580c3c91fd485187af040af118aa5153261Brian Osman    SkRect domain;
93e8e54580c3c91fd485187af040af118aa5153261Brian Osman    DomainMode domainMode =
94e8e54580c3c91fd485187af040af118aa5153261Brian Osman        DetermineDomainMode(constraintRect, filterConstraint, coordsLimitedToConstraintRect,
953798c86f6885f0b47fb2e659a43b48a4468a97efRobert Phillips                            proxy.get(),
96e98234f231d66848e149db683c11b6388e10b233Robert Phillips                            nullptr, fmForDetermineDomain, &domain);
97e8e54580c3c91fd485187af040af118aa5153261Brian Osman    SkASSERT(kTightCopy_DomainMode != domainMode);
98e8e54580c3c91fd485187af040af118aa5153261Brian Osman    sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(texColorSpace.get(),
99e8e54580c3c91fd485187af040af118aa5153261Brian Osman                                                                       dstColorSpace);
1003798c86f6885f0b47fb2e659a43b48a4468a97efRobert Phillips    return CreateFragmentProcessorForDomainAndFilter(fContext->resourceProvider(), std::move(proxy),
1013798c86f6885f0b47fb2e659a43b48a4468a97efRobert Phillips                                                     std::move(colorSpaceXform),
10267c18d6b5188a0497f6912a73d964c763d2f8f84Robert Phillips                                                     adjustedMatrix, domainMode, domain,
103e8e54580c3c91fd485187af040af118aa5153261Brian Osman                                                     filterOrNullForBicubic);
104e8e54580c3c91fd485187af040af118aa5153261Brian Osman}
105e8e54580c3c91fd485187af040af118aa5153261Brian Osman
1063798c86f6885f0b47fb2e659a43b48a4468a97efRobert Phillipssk_sp<GrTextureProxy> GrTextureMaker::generateTextureProxyForParams(const CopyParams& copyParams,
1073798c86f6885f0b47fb2e659a43b48a4468a97efRobert Phillips                                                                    bool willBeMipped,
1083798c86f6885f0b47fb2e659a43b48a4468a97efRobert Phillips                                                                    SkColorSpace* dstColorSpace) {
1094f358be6b72cca97856b3f59d83448650d359d93Robert Phillips    sk_sp<GrTextureProxy> original(this->refOriginalTextureProxy(willBeMipped, dstColorSpace));
110e8e54580c3c91fd485187af040af118aa5153261Brian Osman    if (!original) {
111e8e54580c3c91fd485187af040af118aa5153261Brian Osman        return nullptr;
112e8e54580c3c91fd485187af040af118aa5153261Brian Osman    }
1134f358be6b72cca97856b3f59d83448650d359d93Robert Phillips
1143798c86f6885f0b47fb2e659a43b48a4468a97efRobert Phillips    return CopyOnGpu(fContext, std::move(original), nullptr, copyParams);
115e8e54580c3c91fd485187af040af118aa5153261Brian Osman}
116