blob: 11cb5b3c903aa8c4a27c966359ac2cd5c5420545 [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"
Robert Phillips009e9af2017-06-15 14:01:04 -040011#include "GrGpu.h"
Brian Osman32342f02017-03-04 08:12:46 -050012#include "GrResourceProvider.h"
Brian Osman3b655982017-03-07 16:58:08 -050013#include "SkGr.h"
Brian Osmane8e54582016-11-28 10:06:27 -050014
Robert Phillips3798c862017-03-27 11:08:16 -040015GrTextureAdjuster::GrTextureAdjuster(GrContext* context, sk_sp<GrTextureProxy> original,
Robert Phillips0c984a02017-03-16 07:51:56 -040016 SkAlphaType alphaType,
Brian Osmane8e54582016-11-28 10:06:27 -050017 const SkIRect& contentArea, uint32_t uniqueID,
18 SkColorSpace* cs)
19 : INHERITED(contentArea.width(), contentArea.height(),
20 GrPixelConfigIsAlphaOnly(original->config()))
Robert Phillips0c984a02017-03-16 07:51:56 -040021 , fContext(context)
Robert Phillips3798c862017-03-27 11:08:16 -040022 , fOriginal(std::move(original))
Brian Osmane8e54582016-11-28 10:06:27 -050023 , fAlphaType(alphaType)
24 , fColorSpace(cs)
25 , fUniqueID(uniqueID) {
Robert Phillips3798c862017-03-27 11:08:16 -040026 SkASSERT(SkIRect::MakeWH(fOriginal->width(), fOriginal->height()).contains(contentArea));
Brian Osmane8e54582016-11-28 10:06:27 -050027 if (contentArea.fLeft > 0 || contentArea.fTop > 0 ||
Robert Phillips3798c862017-03-27 11:08:16 -040028 contentArea.fRight < fOriginal->width() || contentArea.fBottom < fOriginal->height()) {
Brian Osmane8e54582016-11-28 10:06:27 -050029 fContentArea.set(contentArea);
30 }
31}
32
33void GrTextureAdjuster::makeCopyKey(const CopyParams& params, GrUniqueKey* copyKey,
Brian Osman61624f02016-12-09 14:51:59 -050034 SkColorSpace* dstColorSpace) {
35 // Destination color space is irrelevant - we already have a texture so we're just sub-setting
Brian Osmane8e54582016-11-28 10:06:27 -050036 GrUniqueKey baseKey;
37 GrMakeKeyFromImageID(&baseKey, fUniqueID, SkIRect::MakeWH(this->width(), this->height()));
38 MakeCopyKeyFromOrigKey(baseKey, params, copyKey);
39}
40
41void GrTextureAdjuster::didCacheCopy(const GrUniqueKey& copyKey) {
42 // We don't currently have a mechanism for notifications on Images!
43}
44
Robert Phillips0c984a02017-03-16 07:51:56 -040045sk_sp<GrTextureProxy> GrTextureAdjuster::refTextureProxyCopy(const CopyParams& copyParams) {
46 GrUniqueKey key;
47 this->makeCopyKey(copyParams, &key, nullptr);
48 if (key.isValid()) {
Robert Phillips96be9df2017-07-21 14:17:45 +000049 sk_sp<GrTextureProxy> cachedCopy = fContext->resourceProvider()->findProxyByUniqueKey(key);
Robert Phillips0c984a02017-03-16 07:51:56 -040050 if (cachedCopy) {
51 return cachedCopy;
52 }
53 }
54
55 sk_sp<GrTextureProxy> proxy = this->originalProxyRef();
56 const SkIRect* contentArea = this->contentAreaOrNull();
57
58 sk_sp<GrTextureProxy> copy = CopyOnGpu(fContext, std::move(proxy), contentArea, copyParams);
59 if (copy) {
60 if (key.isValid()) {
Robert Phillips78814092017-07-24 15:26:17 -040061 SkASSERT(copy->origin() == this->originalProxy()->origin());
Robert Phillips0c984a02017-03-16 07:51:56 -040062 fContext->resourceProvider()->assignUniqueKeyToProxy(key, copy.get());
Brian Osmane8e54582016-11-28 10:06:27 -050063 this->didCacheCopy(key);
64 }
65 }
66 return copy;
67}
68
Robert Phillips3798c862017-03-27 11:08:16 -040069sk_sp<GrTextureProxy> GrTextureAdjuster::refTextureProxySafeForParams(
70 const GrSamplerParams& params,
71 SkIPoint* outOffset,
72 SkScalar scaleAdjust[2]) {
73 sk_sp<GrTextureProxy> proxy = this->originalProxyRef();
Brian Osmane8e54582016-11-28 10:06:27 -050074 CopyParams copyParams;
75 const SkIRect* contentArea = this->contentAreaOrNull();
76
Robert Phillips0c984a02017-03-16 07:51:56 -040077 if (!fContext) {
Brian Osmane8e54582016-11-28 10:06:27 -050078 // The texture was abandoned.
79 return nullptr;
80 }
81
82 if (contentArea && GrSamplerParams::kMipMap_FilterMode == params.filterMode()) {
83 // If we generate a MIP chain for texture it will read pixel values from outside the content
84 // area.
85 copyParams.fWidth = contentArea->width();
86 copyParams.fHeight = contentArea->height();
87 copyParams.fFilter = GrSamplerParams::kBilerp_FilterMode;
Robert Phillips3798c862017-03-27 11:08:16 -040088 } else if (!fContext->getGpu()->isACopyNeededForTextureParams(proxy.get(), params, &copyParams,
Robert Phillips81444fb2017-03-21 09:14:35 -040089 scaleAdjust)) {
Brian Osmane8e54582016-11-28 10:06:27 -050090 if (outOffset) {
91 if (contentArea) {
92 outOffset->set(contentArea->fLeft, contentArea->fRight);
93 } else {
94 outOffset->set(0, 0);
95 }
96 }
Robert Phillips3798c862017-03-27 11:08:16 -040097 return proxy;
Brian Osmane8e54582016-11-28 10:06:27 -050098 }
99
Robert Phillips3798c862017-03-27 11:08:16 -0400100 sk_sp<GrTextureProxy> copy = this->refTextureProxyCopy(copyParams);
Brian Osmane8e54582016-11-28 10:06:27 -0500101 if (copy && outOffset) {
102 outOffset->set(0, 0);
103 }
104 return copy;
105}
106
107sk_sp<GrFragmentProcessor> GrTextureAdjuster::createFragmentProcessor(
108 const SkMatrix& origTextureMatrix,
109 const SkRect& origConstraintRect,
110 FilterConstraint filterConstraint,
111 bool coordsLimitedToConstraintRect,
112 const GrSamplerParams::FilterMode* filterOrNullForBicubic,
Brian Osman61624f02016-12-09 14:51:59 -0500113 SkColorSpace* dstColorSpace) {
Brian Osmane8e54582016-11-28 10:06:27 -0500114
115 SkMatrix textureMatrix = origTextureMatrix;
116 const SkIRect* contentArea = this->contentAreaOrNull();
117 // Convert the constraintRect to be relative to the texture rather than the content area so
118 // that both rects are in the same coordinate system.
119 SkTCopyOnFirstWrite<SkRect> constraintRect(origConstraintRect);
120 if (contentArea) {
121 SkScalar l = SkIntToScalar(contentArea->fLeft);
122 SkScalar t = SkIntToScalar(contentArea->fTop);
123 constraintRect.writable()->offset(l, t);
124 textureMatrix.postTranslate(l, t);
125 }
126
127 SkRect domain;
128 GrSamplerParams params;
129 if (filterOrNullForBicubic) {
130 params.setFilterMode(*filterOrNullForBicubic);
131 }
Robert Phillips67c18d62017-01-20 12:44:06 -0500132 SkScalar scaleAdjust[2] = { 1.0f, 1.0f };
Robert Phillips3798c862017-03-27 11:08:16 -0400133 sk_sp<GrTextureProxy> proxy(this->refTextureProxySafeForParams(params, nullptr, scaleAdjust));
134 if (!proxy) {
Brian Osmane8e54582016-11-28 10:06:27 -0500135 return nullptr;
136 }
137 // If we made a copy then we only copied the contentArea, in which case the new texture is all
138 // content.
Robert Phillips3798c862017-03-27 11:08:16 -0400139 if (proxy.get() != this->originalProxy()) {
Brian Osmane8e54582016-11-28 10:06:27 -0500140 contentArea = nullptr;
Robert Phillips67c18d62017-01-20 12:44:06 -0500141 textureMatrix.postScale(scaleAdjust[0], scaleAdjust[1]);
Brian Osmane8e54582016-11-28 10:06:27 -0500142 }
143
144 DomainMode domainMode =
145 DetermineDomainMode(*constraintRect, filterConstraint, coordsLimitedToConstraintRect,
Robert Phillips3798c862017-03-27 11:08:16 -0400146 proxy.get(),
Brian Osmane8e54582016-11-28 10:06:27 -0500147 contentArea, filterOrNullForBicubic,
148 &domain);
149 if (kTightCopy_DomainMode == domainMode) {
150 // TODO: Copy the texture and adjust the texture matrix (both parts need to consider
151 // non-int constraint rect)
152 // For now: treat as bilerp and ignore what goes on above level 0.
153
154 // We only expect MIP maps to require a tight copy.
155 SkASSERT(filterOrNullForBicubic &&
156 GrSamplerParams::kMipMap_FilterMode == *filterOrNullForBicubic);
157 static const GrSamplerParams::FilterMode kBilerp = GrSamplerParams::kBilerp_FilterMode;
158 domainMode =
159 DetermineDomainMode(*constraintRect, filterConstraint, coordsLimitedToConstraintRect,
Robert Phillips3798c862017-03-27 11:08:16 -0400160 proxy.get(),
Brian Osmane8e54582016-11-28 10:06:27 -0500161 contentArea, &kBilerp, &domain);
162 SkASSERT(kTightCopy_DomainMode != domainMode);
163 }
164 SkASSERT(kNoDomain_DomainMode == domainMode ||
165 (domain.fLeft <= domain.fRight && domain.fTop <= domain.fBottom));
Brian Osmane8e54582016-11-28 10:06:27 -0500166 sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(fColorSpace,
167 dstColorSpace);
Robert Phillipsfbcef6e2017-06-15 12:07:18 -0400168 return CreateFragmentProcessorForDomainAndFilter(std::move(proxy),
Robert Phillips3798c862017-03-27 11:08:16 -0400169 std::move(colorSpaceXform),
Brian Osmane8e54582016-11-28 10:06:27 -0500170 textureMatrix, domainMode, domain,
171 filterOrNullForBicubic);
172}