blob: 183ec70fcf39c588511ad8eb10d233a92ff91269 [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"
Brian Osman32342f02017-03-04 08:12:46 -050011#include "GrResourceProvider.h"
Brian Osman3b655982017-03-07 16:58:08 -050012#include "SkGr.h"
Brian Osmane8e54582016-11-28 10:06:27 -050013
Robert Phillips3798c862017-03-27 11:08:16 -040014GrTextureAdjuster::GrTextureAdjuster(GrContext* context, sk_sp<GrTextureProxy> original,
Robert Phillips0c984a02017-03-16 07:51:56 -040015 SkAlphaType alphaType,
Brian Osmane8e54582016-11-28 10:06:27 -050016 const SkIRect& contentArea, uint32_t uniqueID,
17 SkColorSpace* cs)
18 : INHERITED(contentArea.width(), contentArea.height(),
19 GrPixelConfigIsAlphaOnly(original->config()))
Robert Phillips0c984a02017-03-16 07:51:56 -040020 , fContext(context)
Robert Phillips3798c862017-03-27 11:08:16 -040021 , fOriginal(std::move(original))
Brian Osmane8e54582016-11-28 10:06:27 -050022 , fAlphaType(alphaType)
23 , fColorSpace(cs)
24 , fUniqueID(uniqueID) {
Robert Phillips3798c862017-03-27 11:08:16 -040025 SkASSERT(SkIRect::MakeWH(fOriginal->width(), fOriginal->height()).contains(contentArea));
Brian Osmane8e54582016-11-28 10:06:27 -050026 if (contentArea.fLeft > 0 || contentArea.fTop > 0 ||
Robert Phillips3798c862017-03-27 11:08:16 -040027 contentArea.fRight < fOriginal->width() || contentArea.fBottom < fOriginal->height()) {
Brian Osmane8e54582016-11-28 10:06:27 -050028 fContentArea.set(contentArea);
29 }
30}
31
32void GrTextureAdjuster::makeCopyKey(const CopyParams& params, GrUniqueKey* copyKey,
Brian Osman61624f02016-12-09 14:51:59 -050033 SkColorSpace* dstColorSpace) {
34 // Destination color space is irrelevant - we already have a texture so we're just sub-setting
Brian Osmane8e54582016-11-28 10:06:27 -050035 GrUniqueKey baseKey;
36 GrMakeKeyFromImageID(&baseKey, fUniqueID, SkIRect::MakeWH(this->width(), this->height()));
37 MakeCopyKeyFromOrigKey(baseKey, params, copyKey);
38}
39
40void GrTextureAdjuster::didCacheCopy(const GrUniqueKey& copyKey) {
41 // We don't currently have a mechanism for notifications on Images!
42}
43
Robert Phillips0c984a02017-03-16 07:51:56 -040044sk_sp<GrTextureProxy> GrTextureAdjuster::refTextureProxyCopy(const CopyParams& copyParams) {
45 GrUniqueKey key;
46 this->makeCopyKey(copyParams, &key, nullptr);
47 if (key.isValid()) {
48 sk_sp<GrTextureProxy> cachedCopy = fContext->resourceProvider()->findProxyByUniqueKey(key);
49 if (cachedCopy) {
50 return cachedCopy;
51 }
52 }
53
54 sk_sp<GrTextureProxy> proxy = this->originalProxyRef();
55 const SkIRect* contentArea = this->contentAreaOrNull();
56
57 sk_sp<GrTextureProxy> copy = CopyOnGpu(fContext, std::move(proxy), contentArea, copyParams);
58 if (copy) {
59 if (key.isValid()) {
60 fContext->resourceProvider()->assignUniqueKeyToProxy(key, copy.get());
Brian Osmane8e54582016-11-28 10:06:27 -050061 this->didCacheCopy(key);
62 }
63 }
64 return copy;
65}
66
Robert Phillips3798c862017-03-27 11:08:16 -040067sk_sp<GrTextureProxy> GrTextureAdjuster::refTextureProxySafeForParams(
68 const GrSamplerParams& params,
69 SkIPoint* outOffset,
70 SkScalar scaleAdjust[2]) {
71 sk_sp<GrTextureProxy> proxy = this->originalProxyRef();
Brian Osmane8e54582016-11-28 10:06:27 -050072 CopyParams copyParams;
73 const SkIRect* contentArea = this->contentAreaOrNull();
74
Robert Phillips0c984a02017-03-16 07:51:56 -040075 if (!fContext) {
Brian Osmane8e54582016-11-28 10:06:27 -050076 // The texture was abandoned.
77 return nullptr;
78 }
79
80 if (contentArea && GrSamplerParams::kMipMap_FilterMode == params.filterMode()) {
81 // If we generate a MIP chain for texture it will read pixel values from outside the content
82 // area.
83 copyParams.fWidth = contentArea->width();
84 copyParams.fHeight = contentArea->height();
85 copyParams.fFilter = GrSamplerParams::kBilerp_FilterMode;
Robert Phillips3798c862017-03-27 11:08:16 -040086 } else if (!fContext->getGpu()->isACopyNeededForTextureParams(proxy.get(), params, &copyParams,
Robert Phillips81444fb2017-03-21 09:14:35 -040087 scaleAdjust)) {
Brian Osmane8e54582016-11-28 10:06:27 -050088 if (outOffset) {
89 if (contentArea) {
90 outOffset->set(contentArea->fLeft, contentArea->fRight);
91 } else {
92 outOffset->set(0, 0);
93 }
94 }
Robert Phillips3798c862017-03-27 11:08:16 -040095 return proxy;
Brian Osmane8e54582016-11-28 10:06:27 -050096 }
97
Robert Phillips3798c862017-03-27 11:08:16 -040098 sk_sp<GrTextureProxy> copy = this->refTextureProxyCopy(copyParams);
Brian Osmane8e54582016-11-28 10:06:27 -050099 if (copy && outOffset) {
100 outOffset->set(0, 0);
101 }
102 return copy;
103}
104
105sk_sp<GrFragmentProcessor> GrTextureAdjuster::createFragmentProcessor(
106 const SkMatrix& origTextureMatrix,
107 const SkRect& origConstraintRect,
108 FilterConstraint filterConstraint,
109 bool coordsLimitedToConstraintRect,
110 const GrSamplerParams::FilterMode* filterOrNullForBicubic,
Brian Osman61624f02016-12-09 14:51:59 -0500111 SkColorSpace* dstColorSpace) {
Brian Osmane8e54582016-11-28 10:06:27 -0500112
113 SkMatrix textureMatrix = origTextureMatrix;
114 const SkIRect* contentArea = this->contentAreaOrNull();
115 // Convert the constraintRect to be relative to the texture rather than the content area so
116 // that both rects are in the same coordinate system.
117 SkTCopyOnFirstWrite<SkRect> constraintRect(origConstraintRect);
118 if (contentArea) {
119 SkScalar l = SkIntToScalar(contentArea->fLeft);
120 SkScalar t = SkIntToScalar(contentArea->fTop);
121 constraintRect.writable()->offset(l, t);
122 textureMatrix.postTranslate(l, t);
123 }
124
125 SkRect domain;
126 GrSamplerParams params;
127 if (filterOrNullForBicubic) {
128 params.setFilterMode(*filterOrNullForBicubic);
129 }
Robert Phillips67c18d62017-01-20 12:44:06 -0500130 SkScalar scaleAdjust[2] = { 1.0f, 1.0f };
Robert Phillips3798c862017-03-27 11:08:16 -0400131 sk_sp<GrTextureProxy> proxy(this->refTextureProxySafeForParams(params, nullptr, scaleAdjust));
132 if (!proxy) {
Brian Osmane8e54582016-11-28 10:06:27 -0500133 return nullptr;
134 }
135 // If we made a copy then we only copied the contentArea, in which case the new texture is all
136 // content.
Robert Phillips3798c862017-03-27 11:08:16 -0400137 if (proxy.get() != this->originalProxy()) {
Brian Osmane8e54582016-11-28 10:06:27 -0500138 contentArea = nullptr;
Robert Phillips67c18d62017-01-20 12:44:06 -0500139 textureMatrix.postScale(scaleAdjust[0], scaleAdjust[1]);
Brian Osmane8e54582016-11-28 10:06:27 -0500140 }
141
142 DomainMode domainMode =
143 DetermineDomainMode(*constraintRect, filterConstraint, coordsLimitedToConstraintRect,
Robert Phillips3798c862017-03-27 11:08:16 -0400144 proxy.get(),
Brian Osmane8e54582016-11-28 10:06:27 -0500145 contentArea, filterOrNullForBicubic,
146 &domain);
147 if (kTightCopy_DomainMode == domainMode) {
148 // TODO: Copy the texture and adjust the texture matrix (both parts need to consider
149 // non-int constraint rect)
150 // For now: treat as bilerp and ignore what goes on above level 0.
151
152 // We only expect MIP maps to require a tight copy.
153 SkASSERT(filterOrNullForBicubic &&
154 GrSamplerParams::kMipMap_FilterMode == *filterOrNullForBicubic);
155 static const GrSamplerParams::FilterMode kBilerp = GrSamplerParams::kBilerp_FilterMode;
156 domainMode =
157 DetermineDomainMode(*constraintRect, filterConstraint, coordsLimitedToConstraintRect,
Robert Phillips3798c862017-03-27 11:08:16 -0400158 proxy.get(),
Brian Osmane8e54582016-11-28 10:06:27 -0500159 contentArea, &kBilerp, &domain);
160 SkASSERT(kTightCopy_DomainMode != domainMode);
161 }
162 SkASSERT(kNoDomain_DomainMode == domainMode ||
163 (domain.fLeft <= domain.fRight && domain.fTop <= domain.fBottom));
Brian Osmane8e54582016-11-28 10:06:27 -0500164 sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(fColorSpace,
165 dstColorSpace);
Robert Phillips3798c862017-03-27 11:08:16 -0400166 return CreateFragmentProcessorForDomainAndFilter(fContext->resourceProvider(), std::move(proxy),
167 std::move(colorSpaceXform),
Brian Osmane8e54582016-11-28 10:06:27 -0500168 textureMatrix, domainMode, domain,
169 filterOrNullForBicubic);
170}