Line data Source code
1 : /*
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"
13 : #include "GrResourceProvider.h"
14 : #include "GrTexture.h"
15 : #include "SkGr.h"
16 :
17 0 : GrTextureAdjuster::GrTextureAdjuster(GrContext* context, sk_sp<GrTextureProxy> original,
18 : SkAlphaType alphaType,
19 : const SkIRect& contentArea, uint32_t uniqueID,
20 0 : SkColorSpace* cs)
21 : : INHERITED(contentArea.width(), contentArea.height(),
22 0 : GrPixelConfigIsAlphaOnly(original->config()))
23 : , fContext(context)
24 0 : , fOriginal(std::move(original))
25 : , fAlphaType(alphaType)
26 : , fColorSpace(cs)
27 0 : , fUniqueID(uniqueID) {
28 0 : SkASSERT(SkIRect::MakeWH(fOriginal->width(), fOriginal->height()).contains(contentArea));
29 0 : if (contentArea.fLeft > 0 || contentArea.fTop > 0 ||
30 0 : contentArea.fRight < fOriginal->width() || contentArea.fBottom < fOriginal->height()) {
31 0 : fContentArea.set(contentArea);
32 : }
33 0 : }
34 :
35 0 : void GrTextureAdjuster::makeCopyKey(const CopyParams& params, GrUniqueKey* copyKey,
36 : SkColorSpace* dstColorSpace) {
37 : // Destination color space is irrelevant - we already have a texture so we're just sub-setting
38 0 : GrUniqueKey baseKey;
39 0 : GrMakeKeyFromImageID(&baseKey, fUniqueID, SkIRect::MakeWH(this->width(), this->height()));
40 0 : MakeCopyKeyFromOrigKey(baseKey, params, copyKey);
41 0 : }
42 :
43 0 : void GrTextureAdjuster::didCacheCopy(const GrUniqueKey& copyKey) {
44 : // We don't currently have a mechanism for notifications on Images!
45 0 : }
46 :
47 0 : sk_sp<GrTextureProxy> GrTextureAdjuster::refTextureProxyCopy(const CopyParams& copyParams) {
48 0 : GrUniqueKey key;
49 0 : this->makeCopyKey(copyParams, &key, nullptr);
50 0 : if (key.isValid()) {
51 0 : sk_sp<GrTextureProxy> cachedCopy = fContext->resourceProvider()->findProxyByUniqueKey(key);
52 0 : if (cachedCopy) {
53 0 : return cachedCopy;
54 : }
55 : }
56 :
57 0 : sk_sp<GrTextureProxy> proxy = this->originalProxyRef();
58 0 : const SkIRect* contentArea = this->contentAreaOrNull();
59 :
60 0 : sk_sp<GrTextureProxy> copy = CopyOnGpu(fContext, std::move(proxy), contentArea, copyParams);
61 0 : if (copy) {
62 0 : if (key.isValid()) {
63 0 : fContext->resourceProvider()->assignUniqueKeyToProxy(key, copy.get());
64 0 : this->didCacheCopy(key);
65 : }
66 : }
67 0 : return copy;
68 : }
69 :
70 0 : sk_sp<GrTextureProxy> GrTextureAdjuster::refTextureProxySafeForParams(
71 : const GrSamplerParams& params,
72 : SkIPoint* outOffset,
73 : SkScalar scaleAdjust[2]) {
74 0 : sk_sp<GrTextureProxy> proxy = this->originalProxyRef();
75 : CopyParams copyParams;
76 0 : const SkIRect* contentArea = this->contentAreaOrNull();
77 :
78 0 : if (!fContext) {
79 : // The texture was abandoned.
80 0 : return nullptr;
81 : }
82 :
83 0 : 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 0 : copyParams.fWidth = contentArea->width();
87 0 : copyParams.fHeight = contentArea->height();
88 0 : copyParams.fFilter = GrSamplerParams::kBilerp_FilterMode;
89 0 : } else if (!fContext->getGpu()->isACopyNeededForTextureParams(proxy.get(), params, ©Params,
90 : scaleAdjust)) {
91 0 : if (outOffset) {
92 0 : if (contentArea) {
93 0 : outOffset->set(contentArea->fLeft, contentArea->fRight);
94 : } else {
95 0 : outOffset->set(0, 0);
96 : }
97 : }
98 0 : return proxy;
99 : }
100 :
101 0 : sk_sp<GrTextureProxy> copy = this->refTextureProxyCopy(copyParams);
102 0 : if (copy && outOffset) {
103 0 : outOffset->set(0, 0);
104 : }
105 0 : return copy;
106 : }
107 :
108 0 : sk_sp<GrFragmentProcessor> GrTextureAdjuster::createFragmentProcessor(
109 : const SkMatrix& origTextureMatrix,
110 : const SkRect& origConstraintRect,
111 : FilterConstraint filterConstraint,
112 : bool coordsLimitedToConstraintRect,
113 : const GrSamplerParams::FilterMode* filterOrNullForBicubic,
114 : SkColorSpace* dstColorSpace) {
115 :
116 0 : SkMatrix textureMatrix = origTextureMatrix;
117 0 : 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 0 : SkTCopyOnFirstWrite<SkRect> constraintRect(origConstraintRect);
121 0 : if (contentArea) {
122 0 : SkScalar l = SkIntToScalar(contentArea->fLeft);
123 0 : SkScalar t = SkIntToScalar(contentArea->fTop);
124 0 : constraintRect.writable()->offset(l, t);
125 0 : textureMatrix.postTranslate(l, t);
126 : }
127 :
128 : SkRect domain;
129 0 : GrSamplerParams params;
130 0 : if (filterOrNullForBicubic) {
131 0 : params.setFilterMode(*filterOrNullForBicubic);
132 : }
133 0 : SkScalar scaleAdjust[2] = { 1.0f, 1.0f };
134 0 : sk_sp<GrTextureProxy> proxy(this->refTextureProxySafeForParams(params, nullptr, scaleAdjust));
135 0 : if (!proxy) {
136 0 : 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.
140 0 : if (proxy.get() != this->originalProxy()) {
141 0 : contentArea = nullptr;
142 0 : textureMatrix.postScale(scaleAdjust[0], scaleAdjust[1]);
143 : }
144 :
145 : DomainMode domainMode =
146 0 : DetermineDomainMode(*constraintRect, filterConstraint, coordsLimitedToConstraintRect,
147 : proxy.get(),
148 : contentArea, filterOrNullForBicubic,
149 0 : &domain);
150 0 : 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 0 : SkASSERT(filterOrNullForBicubic &&
157 : GrSamplerParams::kMipMap_FilterMode == *filterOrNullForBicubic);
158 : static const GrSamplerParams::FilterMode kBilerp = GrSamplerParams::kBilerp_FilterMode;
159 : domainMode =
160 0 : DetermineDomainMode(*constraintRect, filterConstraint, coordsLimitedToConstraintRect,
161 : proxy.get(),
162 0 : contentArea, &kBilerp, &domain);
163 0 : SkASSERT(kTightCopy_DomainMode != domainMode);
164 : }
165 0 : SkASSERT(kNoDomain_DomainMode == domainMode ||
166 : (domain.fLeft <= domain.fRight && domain.fTop <= domain.fBottom));
167 0 : sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(fColorSpace,
168 0 : dstColorSpace);
169 0 : return CreateFragmentProcessorForDomainAndFilter(fContext->resourceProvider(), std::move(proxy),
170 0 : std::move(colorSpaceXform),
171 : textureMatrix, domainMode, domain,
172 0 : filterOrNullForBicubic);
173 : }
|