blob: be29857e3b7c9cd2507d5f4d52832656337fd614 [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()) {
49 sk_sp<GrTextureProxy> cachedCopy = fContext->resourceProvider()->findProxyByUniqueKey(key);
50 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()) {
61 fContext->resourceProvider()->assignUniqueKeyToProxy(key, copy.get());
Brian Osmane8e54582016-11-28 10:06:27 -050062 this->didCacheCopy(key);
63 }
64 }
65 return copy;
66}
67
Robert Phillips3798c862017-03-27 11:08:16 -040068sk_sp<GrTextureProxy> GrTextureAdjuster::refTextureProxySafeForParams(
69 const GrSamplerParams& params,
70 SkIPoint* outOffset,
71 SkScalar scaleAdjust[2]) {
72 sk_sp<GrTextureProxy> proxy = this->originalProxyRef();
Brian Osmane8e54582016-11-28 10:06:27 -050073 CopyParams copyParams;
74 const SkIRect* contentArea = this->contentAreaOrNull();
75
Robert Phillips0c984a02017-03-16 07:51:56 -040076 if (!fContext) {
Brian Osmane8e54582016-11-28 10:06:27 -050077 // The texture was abandoned.
78 return nullptr;
79 }
80
81 if (contentArea && GrSamplerParams::kMipMap_FilterMode == params.filterMode()) {
82 // If we generate a MIP chain for texture it will read pixel values from outside the content
83 // area.
84 copyParams.fWidth = contentArea->width();
85 copyParams.fHeight = contentArea->height();
86 copyParams.fFilter = GrSamplerParams::kBilerp_FilterMode;
Robert Phillips3798c862017-03-27 11:08:16 -040087 } else if (!fContext->getGpu()->isACopyNeededForTextureParams(proxy.get(), params, &copyParams,
Robert Phillips81444fb2017-03-21 09:14:35 -040088 scaleAdjust)) {
Brian Osmane8e54582016-11-28 10:06:27 -050089 if (outOffset) {
90 if (contentArea) {
91 outOffset->set(contentArea->fLeft, contentArea->fRight);
92 } else {
93 outOffset->set(0, 0);
94 }
95 }
Robert Phillips3798c862017-03-27 11:08:16 -040096 return proxy;
Brian Osmane8e54582016-11-28 10:06:27 -050097 }
98
Robert Phillips3798c862017-03-27 11:08:16 -040099 sk_sp<GrTextureProxy> copy = this->refTextureProxyCopy(copyParams);
Brian Osmane8e54582016-11-28 10:06:27 -0500100 if (copy && outOffset) {
101 outOffset->set(0, 0);
102 }
103 return copy;
104}
105
106sk_sp<GrFragmentProcessor> GrTextureAdjuster::createFragmentProcessor(
107 const SkMatrix& origTextureMatrix,
108 const SkRect& origConstraintRect,
109 FilterConstraint filterConstraint,
110 bool coordsLimitedToConstraintRect,
111 const GrSamplerParams::FilterMode* filterOrNullForBicubic,
Brian Osman61624f02016-12-09 14:51:59 -0500112 SkColorSpace* dstColorSpace) {
Brian Osmane8e54582016-11-28 10:06:27 -0500113
114 SkMatrix textureMatrix = origTextureMatrix;
115 const SkIRect* contentArea = this->contentAreaOrNull();
116 // Convert the constraintRect to be relative to the texture rather than the content area so
117 // that both rects are in the same coordinate system.
118 SkTCopyOnFirstWrite<SkRect> constraintRect(origConstraintRect);
119 if (contentArea) {
120 SkScalar l = SkIntToScalar(contentArea->fLeft);
121 SkScalar t = SkIntToScalar(contentArea->fTop);
122 constraintRect.writable()->offset(l, t);
123 textureMatrix.postTranslate(l, t);
124 }
125
126 SkRect domain;
127 GrSamplerParams params;
128 if (filterOrNullForBicubic) {
129 params.setFilterMode(*filterOrNullForBicubic);
130 }
Robert Phillips67c18d62017-01-20 12:44:06 -0500131 SkScalar scaleAdjust[2] = { 1.0f, 1.0f };
Robert Phillips3798c862017-03-27 11:08:16 -0400132 sk_sp<GrTextureProxy> proxy(this->refTextureProxySafeForParams(params, nullptr, scaleAdjust));
133 if (!proxy) {
Brian Osmane8e54582016-11-28 10:06:27 -0500134 return nullptr;
135 }
136 // If we made a copy then we only copied the contentArea, in which case the new texture is all
137 // content.
Robert Phillips3798c862017-03-27 11:08:16 -0400138 if (proxy.get() != this->originalProxy()) {
Brian Osmane8e54582016-11-28 10:06:27 -0500139 contentArea = nullptr;
Robert Phillips67c18d62017-01-20 12:44:06 -0500140 textureMatrix.postScale(scaleAdjust[0], scaleAdjust[1]);
Brian Osmane8e54582016-11-28 10:06:27 -0500141 }
142
143 DomainMode domainMode =
144 DetermineDomainMode(*constraintRect, filterConstraint, coordsLimitedToConstraintRect,
Robert Phillips3798c862017-03-27 11:08:16 -0400145 proxy.get(),
Brian Osmane8e54582016-11-28 10:06:27 -0500146 contentArea, filterOrNullForBicubic,
147 &domain);
148 if (kTightCopy_DomainMode == domainMode) {
149 // TODO: Copy the texture and adjust the texture matrix (both parts need to consider
150 // non-int constraint rect)
151 // For now: treat as bilerp and ignore what goes on above level 0.
152
153 // We only expect MIP maps to require a tight copy.
154 SkASSERT(filterOrNullForBicubic &&
155 GrSamplerParams::kMipMap_FilterMode == *filterOrNullForBicubic);
156 static const GrSamplerParams::FilterMode kBilerp = GrSamplerParams::kBilerp_FilterMode;
157 domainMode =
158 DetermineDomainMode(*constraintRect, filterConstraint, coordsLimitedToConstraintRect,
Robert Phillips3798c862017-03-27 11:08:16 -0400159 proxy.get(),
Brian Osmane8e54582016-11-28 10:06:27 -0500160 contentArea, &kBilerp, &domain);
161 SkASSERT(kTightCopy_DomainMode != domainMode);
162 }
163 SkASSERT(kNoDomain_DomainMode == domainMode ||
164 (domain.fLeft <= domain.fRight && domain.fTop <= domain.fBottom));
Brian Osmane8e54582016-11-28 10:06:27 -0500165 sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(fColorSpace,
166 dstColorSpace);
Robert Phillipsfbcef6e2017-06-15 12:07:18 -0400167 return CreateFragmentProcessorForDomainAndFilter(std::move(proxy),
Robert Phillips3798c862017-03-27 11:08:16 -0400168 std::move(colorSpaceXform),
Brian Osmane8e54582016-11-28 10:06:27 -0500169 textureMatrix, domainMode, domain,
170 filterOrNullForBicubic);
171}