blob: bb4d92aa549f0ccc421c4ff94ddde6a8218a80d6 [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 "GrTextureAdjuster.h"
9
10#include "GrContext.h"
11#include "GrGpu.h"
12#include "GrGpuResourcePriv.h"
Brian Osman32342f02017-03-04 08:12:46 -050013#include "GrResourceProvider.h"
Brian Osmane8e54582016-11-28 10:06:27 -050014#include "GrTexture.h"
Brian Osman3b655982017-03-07 16:58:08 -050015#include "SkGr.h"
Brian Osmane8e54582016-11-28 10:06:27 -050016
Robert Phillips3798c862017-03-27 11:08:16 -040017GrTextureAdjuster::GrTextureAdjuster(GrContext* context, sk_sp<GrTextureProxy> original,
Robert Phillips0c984a02017-03-16 07:51:56 -040018 SkAlphaType alphaType,
Brian Osmane8e54582016-11-28 10:06:27 -050019 const SkIRect& contentArea, uint32_t uniqueID,
20 SkColorSpace* cs)
21 : INHERITED(contentArea.width(), contentArea.height(),
22 GrPixelConfigIsAlphaOnly(original->config()))
Robert Phillips0c984a02017-03-16 07:51:56 -040023 , fContext(context)
Robert Phillips3798c862017-03-27 11:08:16 -040024 , fOriginal(std::move(original))
Brian Osmane8e54582016-11-28 10:06:27 -050025 , fAlphaType(alphaType)
26 , fColorSpace(cs)
27 , fUniqueID(uniqueID) {
Robert Phillips3798c862017-03-27 11:08:16 -040028 SkASSERT(SkIRect::MakeWH(fOriginal->width(), fOriginal->height()).contains(contentArea));
Brian Osmane8e54582016-11-28 10:06:27 -050029 if (contentArea.fLeft > 0 || contentArea.fTop > 0 ||
Robert Phillips3798c862017-03-27 11:08:16 -040030 contentArea.fRight < fOriginal->width() || contentArea.fBottom < fOriginal->height()) {
Brian Osmane8e54582016-11-28 10:06:27 -050031 fContentArea.set(contentArea);
32 }
33}
34
35void GrTextureAdjuster::makeCopyKey(const CopyParams& params, GrUniqueKey* copyKey,
Brian Osman61624f02016-12-09 14:51:59 -050036 SkColorSpace* dstColorSpace) {
37 // Destination color space is irrelevant - we already have a texture so we're just sub-setting
Brian Osmane8e54582016-11-28 10:06:27 -050038 GrUniqueKey baseKey;
39 GrMakeKeyFromImageID(&baseKey, fUniqueID, SkIRect::MakeWH(this->width(), this->height()));
40 MakeCopyKeyFromOrigKey(baseKey, params, copyKey);
41}
42
43void GrTextureAdjuster::didCacheCopy(const GrUniqueKey& copyKey) {
44 // We don't currently have a mechanism for notifications on Images!
45}
46
Robert Phillips0c984a02017-03-16 07:51:56 -040047sk_sp<GrTextureProxy> GrTextureAdjuster::refTextureProxyCopy(const CopyParams& copyParams) {
48 GrUniqueKey key;
49 this->makeCopyKey(copyParams, &key, nullptr);
50 if (key.isValid()) {
51 sk_sp<GrTextureProxy> cachedCopy = fContext->resourceProvider()->findProxyByUniqueKey(key);
52 if (cachedCopy) {
53 return cachedCopy;
54 }
55 }
56
57 sk_sp<GrTextureProxy> proxy = this->originalProxyRef();
58 const SkIRect* contentArea = this->contentAreaOrNull();
59
60 sk_sp<GrTextureProxy> copy = CopyOnGpu(fContext, std::move(proxy), contentArea, copyParams);
61 if (copy) {
62 if (key.isValid()) {
63 fContext->resourceProvider()->assignUniqueKeyToProxy(key, copy.get());
Brian Osmane8e54582016-11-28 10:06:27 -050064 this->didCacheCopy(key);
65 }
66 }
67 return copy;
68}
69
Robert Phillips3798c862017-03-27 11:08:16 -040070sk_sp<GrTextureProxy> GrTextureAdjuster::refTextureProxySafeForParams(
71 const GrSamplerParams& params,
72 SkIPoint* outOffset,
73 SkScalar scaleAdjust[2]) {
74 sk_sp<GrTextureProxy> proxy = this->originalProxyRef();
Brian Osmane8e54582016-11-28 10:06:27 -050075 CopyParams copyParams;
76 const SkIRect* contentArea = this->contentAreaOrNull();
77
Robert Phillips0c984a02017-03-16 07:51:56 -040078 if (!fContext) {
Brian Osmane8e54582016-11-28 10:06:27 -050079 // The texture was abandoned.
80 return nullptr;
81 }
82
83 if (contentArea && GrSamplerParams::kMipMap_FilterMode == params.filterMode()) {
84 // If we generate a MIP chain for texture it will read pixel values from outside the content
85 // area.
86 copyParams.fWidth = contentArea->width();
87 copyParams.fHeight = contentArea->height();
88 copyParams.fFilter = GrSamplerParams::kBilerp_FilterMode;
Robert Phillips3798c862017-03-27 11:08:16 -040089 } else if (!fContext->getGpu()->isACopyNeededForTextureParams(proxy.get(), params, &copyParams,
Robert Phillips81444fb2017-03-21 09:14:35 -040090 scaleAdjust)) {
Brian Osmane8e54582016-11-28 10:06:27 -050091 if (outOffset) {
92 if (contentArea) {
93 outOffset->set(contentArea->fLeft, contentArea->fRight);
94 } else {
95 outOffset->set(0, 0);
96 }
97 }
Robert Phillips3798c862017-03-27 11:08:16 -040098 return proxy;
Brian Osmane8e54582016-11-28 10:06:27 -050099 }
100
Robert Phillips3798c862017-03-27 11:08:16 -0400101 sk_sp<GrTextureProxy> copy = this->refTextureProxyCopy(copyParams);
Brian Osmane8e54582016-11-28 10:06:27 -0500102 if (copy && outOffset) {
103 outOffset->set(0, 0);
104 }
105 return copy;
106}
107
108sk_sp<GrFragmentProcessor> GrTextureAdjuster::createFragmentProcessor(
109 const SkMatrix& origTextureMatrix,
110 const SkRect& origConstraintRect,
111 FilterConstraint filterConstraint,
112 bool coordsLimitedToConstraintRect,
113 const GrSamplerParams::FilterMode* filterOrNullForBicubic,
Brian Osman61624f02016-12-09 14:51:59 -0500114 SkColorSpace* dstColorSpace) {
Brian Osmane8e54582016-11-28 10:06:27 -0500115
116 SkMatrix textureMatrix = origTextureMatrix;
117 const SkIRect* contentArea = this->contentAreaOrNull();
118 // Convert the constraintRect to be relative to the texture rather than the content area so
119 // that both rects are in the same coordinate system.
120 SkTCopyOnFirstWrite<SkRect> constraintRect(origConstraintRect);
121 if (contentArea) {
122 SkScalar l = SkIntToScalar(contentArea->fLeft);
123 SkScalar t = SkIntToScalar(contentArea->fTop);
124 constraintRect.writable()->offset(l, t);
125 textureMatrix.postTranslate(l, t);
126 }
127
128 SkRect domain;
129 GrSamplerParams params;
130 if (filterOrNullForBicubic) {
131 params.setFilterMode(*filterOrNullForBicubic);
132 }
Robert Phillips67c18d62017-01-20 12:44:06 -0500133 SkScalar scaleAdjust[2] = { 1.0f, 1.0f };
Robert Phillips3798c862017-03-27 11:08:16 -0400134 sk_sp<GrTextureProxy> proxy(this->refTextureProxySafeForParams(params, nullptr, scaleAdjust));
135 if (!proxy) {
Brian Osmane8e54582016-11-28 10:06:27 -0500136 return nullptr;
137 }
138 // If we made a copy then we only copied the contentArea, in which case the new texture is all
139 // content.
Robert Phillips3798c862017-03-27 11:08:16 -0400140 if (proxy.get() != this->originalProxy()) {
Brian Osmane8e54582016-11-28 10:06:27 -0500141 contentArea = nullptr;
Robert Phillips67c18d62017-01-20 12:44:06 -0500142 textureMatrix.postScale(scaleAdjust[0], scaleAdjust[1]);
Brian Osmane8e54582016-11-28 10:06:27 -0500143 }
144
145 DomainMode domainMode =
146 DetermineDomainMode(*constraintRect, filterConstraint, coordsLimitedToConstraintRect,
Robert Phillips3798c862017-03-27 11:08:16 -0400147 proxy.get(),
Brian Osmane8e54582016-11-28 10:06:27 -0500148 contentArea, filterOrNullForBicubic,
149 &domain);
150 if (kTightCopy_DomainMode == domainMode) {
151 // TODO: Copy the texture and adjust the texture matrix (both parts need to consider
152 // non-int constraint rect)
153 // For now: treat as bilerp and ignore what goes on above level 0.
154
155 // We only expect MIP maps to require a tight copy.
156 SkASSERT(filterOrNullForBicubic &&
157 GrSamplerParams::kMipMap_FilterMode == *filterOrNullForBicubic);
158 static const GrSamplerParams::FilterMode kBilerp = GrSamplerParams::kBilerp_FilterMode;
159 domainMode =
160 DetermineDomainMode(*constraintRect, filterConstraint, coordsLimitedToConstraintRect,
Robert Phillips3798c862017-03-27 11:08:16 -0400161 proxy.get(),
Brian Osmane8e54582016-11-28 10:06:27 -0500162 contentArea, &kBilerp, &domain);
163 SkASSERT(kTightCopy_DomainMode != domainMode);
164 }
165 SkASSERT(kNoDomain_DomainMode == domainMode ||
166 (domain.fLeft <= domain.fRight && domain.fTop <= domain.fBottom));
Brian Osmane8e54582016-11-28 10:06:27 -0500167 sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(fColorSpace,
168 dstColorSpace);
Robert Phillips3798c862017-03-27 11:08:16 -0400169 return CreateFragmentProcessorForDomainAndFilter(fContext->resourceProvider(), std::move(proxy),
170 std::move(colorSpaceXform),
Brian Osmane8e54582016-11-28 10:06:27 -0500171 textureMatrix, domainMode, domain,
172 filterOrNullForBicubic);
173}