blob: fd17d2adb47c6b2c8f6f79ed7563951da649eb68 [file] [log] [blame]
bsalomon045802d2015-10-20 07:58:01 -07001/*
2 * Copyright 2015 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 "GrTextureParamsAdjuster.h"
9
10#include "GrCaps.h"
11#include "GrContext.h"
12#include "GrDrawContext.h"
13#include "GrGpu.h"
bsalomon89fe56b2015-10-29 10:49:28 -070014#include "GrGpuResourcePriv.h"
15#include "GrResourceKey.h"
bsalomon045802d2015-10-20 07:58:01 -070016#include "GrTexture.h"
17#include "GrTextureParams.h"
18#include "GrTextureProvider.h"
19#include "SkCanvas.h"
20#include "SkGr.h"
21#include "SkGrPriv.h"
bsalomonc55271f2015-11-09 11:55:57 -080022#include "effects/GrBicubicEffect.h"
bsalomon89fe56b2015-10-29 10:49:28 -070023#include "effects/GrTextureDomain.h"
bsalomon045802d2015-10-20 07:58:01 -070024
bsalomon89fe56b2015-10-29 10:49:28 -070025typedef GrTextureProducer::CopyParams CopyParams;
bsalomon045802d2015-10-20 07:58:01 -070026
bsalomon89fe56b2015-10-29 10:49:28 -070027//////////////////////////////////////////////////////////////////////////////
28
29static GrTexture* copy_on_gpu(GrTexture* inputTexture, const SkIRect* subset,
30 const CopyParams& copyParams) {
31 SkASSERT(!subset || !subset->isEmpty());
bsalomon045802d2015-10-20 07:58:01 -070032 GrContext* context = inputTexture->getContext();
33 SkASSERT(context);
34 const GrCaps* caps = context->caps();
35
36 // Either it's a cache miss or the original wasn't cached to begin with.
37 GrSurfaceDesc rtDesc = inputTexture->desc();
bsalomon89fe56b2015-10-29 10:49:28 -070038 rtDesc.fFlags = rtDesc.fFlags | kRenderTarget_GrSurfaceFlag;
39 rtDesc.fWidth = copyParams.fWidth;
bsalomon045802d2015-10-20 07:58:01 -070040 rtDesc.fHeight = copyParams.fHeight;
41 rtDesc.fConfig = GrMakePixelConfigUncompressed(rtDesc.fConfig);
42
43 // If the config isn't renderable try converting to either A8 or an 32 bit config. Otherwise,
44 // fail.
45 if (!caps->isConfigRenderable(rtDesc.fConfig, false)) {
46 if (GrPixelConfigIsAlphaOnly(rtDesc.fConfig)) {
47 if (caps->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
48 rtDesc.fConfig = kAlpha_8_GrPixelConfig;
49 } else if (caps->isConfigRenderable(kSkia8888_GrPixelConfig, false)) {
50 rtDesc.fConfig = kSkia8888_GrPixelConfig;
51 } else {
52 return nullptr;
53 }
54 } else if (kRGB_GrColorComponentFlags ==
55 (kRGB_GrColorComponentFlags & GrPixelConfigComponentMask(rtDesc.fConfig))) {
56 if (caps->isConfigRenderable(kSkia8888_GrPixelConfig, false)) {
57 rtDesc.fConfig = kSkia8888_GrPixelConfig;
58 } else {
59 return nullptr;
60 }
61 } else {
62 return nullptr;
63 }
64 }
65
66 SkAutoTUnref<GrTexture> copy(context->textureProvider()->createTexture(rtDesc, true));
67 if (!copy) {
68 return nullptr;
69 }
70
bsalomon89fe56b2015-10-29 10:49:28 -070071 // TODO: If no scaling is being performed then use copySurface.
72
bsalomon045802d2015-10-20 07:58:01 -070073 GrPaint paint;
74
egdaniel0a0605d2015-11-23 15:29:36 -080075 // TODO: Initializing these values for no reason cause the compiler is complaining
76 SkScalar sx = 0.f;
77 SkScalar sy = 0.f;
bsalomon89fe56b2015-10-29 10:49:28 -070078 if (subset) {
79 sx = 1.f / inputTexture->width();
80 sy = 1.f / inputTexture->height();
81 }
bsalomon045802d2015-10-20 07:58:01 -070082
bsalomon89fe56b2015-10-29 10:49:28 -070083 if (copyParams.fFilter != GrTextureParams::kNone_FilterMode && subset &&
84 (subset->width() != copyParams.fWidth || subset->height() != copyParams.fHeight)) {
85 SkRect domain;
86 domain.fLeft = (subset->fLeft + 0.5f) * sx;
87 domain.fTop = (subset->fTop + 0.5f)* sy;
88 domain.fRight = (subset->fRight - 0.5f) * sx;
89 domain.fBottom = (subset->fBottom - 0.5f) * sy;
90 // This would cause us to read values from outside the subset. Surely, the caller knows
91 // better!
92 SkASSERT(copyParams.fFilter != GrTextureParams::kMipMap_FilterMode);
93 paint.addColorFragmentProcessor(
94 GrTextureDomainEffect::Create(inputTexture, SkMatrix::I(), domain,
95 GrTextureDomain::kClamp_Mode,
96 copyParams.fFilter))->unref();
97 } else {
98 GrTextureParams params(SkShader::kClamp_TileMode, copyParams.fFilter);
99 paint.addColorTextureProcessor(inputTexture, SkMatrix::I(), params);
100 }
egdaniel813351f2015-11-23 15:12:23 -0800101 paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
bsalomon89fe56b2015-10-29 10:49:28 -0700102
103 SkRect localRect;
104 if (subset) {
105 localRect = SkRect::Make(*subset);
106 localRect.fLeft *= sx;
107 localRect.fTop *= sy;
108 localRect.fRight *= sx;
109 localRect.fBottom *= sy;
110 } else {
111 localRect = SkRect::MakeWH(1.f, 1.f);
112 }
bsalomon045802d2015-10-20 07:58:01 -0700113
114 SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(copy->asRenderTarget()));
115 if (!drawContext) {
116 return nullptr;
117 }
118
bsalomon89fe56b2015-10-29 10:49:28 -0700119 SkRect dstRect = SkRect::MakeWH(SkIntToScalar(rtDesc.fWidth), SkIntToScalar(rtDesc.fHeight));
bsalomona2e69fc2015-11-05 10:41:43 -0800120 drawContext->fillRectToRect(GrClip::WideOpen(), paint, SkMatrix::I(), dstRect, localRect);
bsalomon045802d2015-10-20 07:58:01 -0700121 return copy.detach();
122}
123
bsalomonf1ecd212015-12-09 17:06:02 -0800124GrTextureAdjuster::GrTextureAdjuster(GrTexture* original,
125 const SkIRect& contentArea,
126 bool isAlphaOnly)
127 : INHERITED(contentArea.width(), contentArea.height(), isAlphaOnly)
bsalomon3aa5fce2015-11-12 09:59:44 -0800128 , fOriginal(original) {
129 SkASSERT(SkIRect::MakeWH(original->width(), original->height()).contains(contentArea));
bsalomonc75be342015-10-29 12:34:31 -0700130 if (contentArea.fLeft > 0 || contentArea.fTop > 0 ||
131 contentArea.fRight < original->width() || contentArea.fBottom < original->height()) {
132 fContentArea.set(contentArea);
bsalomon89fe56b2015-10-29 10:49:28 -0700133 }
134}
135
bsalomone179a912016-01-20 06:18:10 -0800136GrTexture* GrTextureAdjuster::refCopy(const CopyParams& copyParams) {
137 GrTexture* texture = this->originalTexture();
138 GrContext* context = texture->getContext();
139 const SkIRect* contentArea = this->contentAreaOrNull();
140 GrUniqueKey key;
141 this->makeCopyKey(copyParams, &key);
142 if (key.isValid()) {
143 GrTexture* cachedCopy = context->textureProvider()->findAndRefTextureByUniqueKey(key);
144 if (cachedCopy) {
145 return cachedCopy;
146 }
147 }
148 GrTexture* copy = copy_on_gpu(texture, contentArea, copyParams);
149 if (copy) {
150 if (key.isValid()) {
151 copy->resourcePriv().setUniqueKey(key);
152 this->didCacheCopy(key);
153 }
154 }
155 return copy;
156}
157
bsalomon89fe56b2015-10-29 10:49:28 -0700158GrTexture* GrTextureAdjuster::refTextureSafeForParams(const GrTextureParams& params,
159 SkIPoint* outOffset) {
160 GrTexture* texture = this->originalTexture();
161 GrContext* context = texture->getContext();
162 CopyParams copyParams;
bsalomonc55271f2015-11-09 11:55:57 -0800163 const SkIRect* contentArea = this->contentAreaOrNull();
bsalomon89fe56b2015-10-29 10:49:28 -0700164
bsalomonc75be342015-10-29 12:34:31 -0700165 if (contentArea && GrTextureParams::kMipMap_FilterMode == params.filterMode()) {
166 // If we generate a MIP chain for texture it will read pixel values from outside the content
167 // area.
168 copyParams.fWidth = contentArea->width();
169 copyParams.fHeight = contentArea->height();
170 copyParams.fFilter = GrTextureParams::kBilerp_FilterMode;
bsalomone179a912016-01-20 06:18:10 -0800171 } else if (!context->getGpu()->makeCopyForTextureParams(texture, params, &copyParams)) {
bsalomon89fe56b2015-10-29 10:49:28 -0700172 if (outOffset) {
bsalomonc75be342015-10-29 12:34:31 -0700173 if (contentArea) {
174 outOffset->set(contentArea->fLeft, contentArea->fRight);
bsalomon89fe56b2015-10-29 10:49:28 -0700175 } else {
176 outOffset->set(0, 0);
177 }
178 }
179 return SkRef(texture);
180 }
bsalomone179a912016-01-20 06:18:10 -0800181
182 GrTexture* copy = this->refCopy(copyParams);
183 if (copy && outOffset) {
184 outOffset->set(0, 0);
bsalomon89fe56b2015-10-29 10:49:28 -0700185 }
bsalomone179a912016-01-20 06:18:10 -0800186 return copy;
bsalomon89fe56b2015-10-29 10:49:28 -0700187}
188
bsalomonc55271f2015-11-09 11:55:57 -0800189enum DomainMode {
190 kNoDomain_DomainMode,
191 kDomain_DomainMode,
192 kTightCopy_DomainMode
193};
194
195/** Determines whether a texture domain is necessary and if so what domain to use. There are two
196 * rectangles to consider:
197 * - The first is the content area specified by the texture adjuster. We can *never* allow
198 * filtering to cause bleed of pixels outside this rectangle.
199 * - The second rectangle is the constraint rectangle, which is known to be contained by the
200 * content area. The filterConstraint specifies whether we are allowed to bleed across this
201 * rect.
202 *
203 * We want to avoid using a domain if possible. We consider the above rectangles, the filter type,
204 * and whether the coords generated by the draw would all fall within the constraint rect. If the
205 * latter is true we only need to consider whether the filter would extend beyond the rects.
206 */
207static DomainMode determine_domain_mode(
208 const SkRect& constraintRect,
209 GrTextureAdjuster::FilterConstraint filterConstraint,
210 bool coordsLimitedToConstraintRect,
211 int texW, int texH,
212 const SkIRect* textureContentArea,
213 const GrTextureParams::FilterMode* filterModeOrNullForBicubic,
214 SkRect* domainRect) {
215
216 SkASSERT(SkRect::MakeIWH(texW, texH).contains(constraintRect));
217 // We only expect a content area rect if there is some non-content area.
218 SkASSERT(!textureContentArea ||
219 (!textureContentArea->contains(SkIRect::MakeWH(texW, texH)) &&
220 SkRect::Make(*textureContentArea).contains(constraintRect)));
221
222 SkRect textureBounds = SkRect::MakeIWH(texW, texH);
223 // If the src rectangle contains the whole texture then no need for a domain.
224 if (constraintRect.contains(textureBounds)) {
225 return kNoDomain_DomainMode;
226 }
227
bsalomonb1b01992015-11-18 10:56:08 -0800228 bool restrictFilterToRect = (filterConstraint == GrTextureProducer::kYes_FilterConstraint);
bsalomonc55271f2015-11-09 11:55:57 -0800229
230 // If we can filter outside the constraint rect, and there is no non-content area of the
231 // texture, and we aren't going to generate sample coords outside the constraint rect then we
232 // don't need a domain.
233 if (!restrictFilterToRect && !textureContentArea && coordsLimitedToConstraintRect) {
234 return kNoDomain_DomainMode;
235 }
236
237 // Get the domain inset based on sampling mode (or bail if mipped)
238 SkScalar filterHalfWidth = 0.f;
239 if (filterModeOrNullForBicubic) {
240 switch (*filterModeOrNullForBicubic) {
241 case GrTextureParams::kNone_FilterMode:
242 if (coordsLimitedToConstraintRect) {
243 return kNoDomain_DomainMode;
244 } else {
245 filterHalfWidth = 0.f;
246 }
247 break;
248 case GrTextureParams::kBilerp_FilterMode:
249 filterHalfWidth = .5f;
250 break;
251 case GrTextureParams::kMipMap_FilterMode:
bsalomonb1b01992015-11-18 10:56:08 -0800252 if (restrictFilterToRect || textureContentArea) {
253 // No domain can save us here.
254 return kTightCopy_DomainMode;
255 }
256 return kNoDomain_DomainMode;
bsalomonc55271f2015-11-09 11:55:57 -0800257 }
258 } else {
259 // bicubic does nearest filtering internally.
260 filterHalfWidth = 1.5f;
261 }
262
263 // Both bilerp and bicubic use bilinear filtering and so need to be clamped to the center
264 // of the edge texel. Pinning to the texel center has no impact on nearest mode and MIP-maps
265
266 static const SkScalar kDomainInset = 0.5f;
267 // Figure out the limits of pixels we're allowed to sample from.
268 // Unless we know the amount of outset and the texture matrix we have to conservatively enforce
269 // the domain.
270 if (restrictFilterToRect) {
271 domainRect->fLeft = constraintRect.fLeft + kDomainInset;
272 domainRect->fTop = constraintRect.fTop + kDomainInset;
273 domainRect->fRight = constraintRect.fRight - kDomainInset;
274 domainRect->fBottom = constraintRect.fBottom - kDomainInset;
275 } else if (textureContentArea) {
276 // If we got here then: there is a textureContentArea, the coords are limited to the
277 // constraint rect, and we're allowed to filter across the constraint rect boundary. So
278 // we check whether the filter would reach across the edge of the content area.
279 // We will only set the sides that are required.
280
281 domainRect->setLargest();
282 if (coordsLimitedToConstraintRect) {
283 // We may be able to use the fact that the texture coords are limited to the constraint
284 // rect in order to avoid having to add a domain.
285 bool needContentAreaConstraint = false;
286 if (textureContentArea->fLeft > 0 &&
287 textureContentArea->fLeft + filterHalfWidth > constraintRect.fLeft) {
288 domainRect->fLeft = textureContentArea->fLeft + kDomainInset;
289 needContentAreaConstraint = true;
290 }
291 if (textureContentArea->fTop > 0 &&
292 textureContentArea->fTop + filterHalfWidth > constraintRect.fTop) {
293 domainRect->fTop = textureContentArea->fTop + kDomainInset;
294 needContentAreaConstraint = true;
295 }
296 if (textureContentArea->fRight < texW &&
297 textureContentArea->fRight - filterHalfWidth < constraintRect.fRight) {
298 domainRect->fRight = textureContentArea->fRight - kDomainInset;
299 needContentAreaConstraint = true;
300 }
301 if (textureContentArea->fBottom < texH &&
302 textureContentArea->fBottom - filterHalfWidth < constraintRect.fBottom) {
303 domainRect->fBottom = textureContentArea->fBottom - kDomainInset;
304 needContentAreaConstraint = true;
305 }
306 if (!needContentAreaConstraint) {
307 return kNoDomain_DomainMode;
308 }
309 } else {
310 // Our sample coords for the texture are allowed to be outside the constraintRect so we
311 // don't consider it when computing the domain.
312 if (textureContentArea->fLeft != 0) {
313 domainRect->fLeft = textureContentArea->fLeft + kDomainInset;
314 }
315 if (textureContentArea->fTop != 0) {
316 domainRect->fTop = textureContentArea->fTop + kDomainInset;
317 }
318 if (textureContentArea->fRight != texW) {
319 domainRect->fRight = textureContentArea->fRight - kDomainInset;
320 }
321 if (textureContentArea->fBottom != texH) {
322 domainRect->fBottom = textureContentArea->fBottom - kDomainInset;
323 }
324 }
325 } else {
326 return kNoDomain_DomainMode;
327 }
328
329 if (domainRect->fLeft > domainRect->fRight) {
330 domainRect->fLeft = domainRect->fRight = SkScalarAve(domainRect->fLeft, domainRect->fRight);
331 }
332 if (domainRect->fTop > domainRect->fBottom) {
333 domainRect->fTop = domainRect->fBottom = SkScalarAve(domainRect->fTop, domainRect->fBottom);
334 }
335 domainRect->fLeft /= texW;
336 domainRect->fTop /= texH;
337 domainRect->fRight /= texW;
338 domainRect->fBottom /= texH;
339 return kDomain_DomainMode;
340}
341
bsalomonb1b01992015-11-18 10:56:08 -0800342static const GrFragmentProcessor* create_fp_for_domain_and_filter(
343 GrTexture* texture,
344 const SkMatrix& textureMatrix,
345 DomainMode domainMode,
346 const SkRect& domain,
347 const GrTextureParams::FilterMode* filterOrNullForBicubic) {
348 SkASSERT(kTightCopy_DomainMode != domainMode);
349 if (filterOrNullForBicubic) {
350 if (kDomain_DomainMode == domainMode) {
351 return GrTextureDomainEffect::Create(texture, textureMatrix, domain,
352 GrTextureDomain::kClamp_Mode,
353 *filterOrNullForBicubic);
354 } else {
355 GrTextureParams params(SkShader::kClamp_TileMode, *filterOrNullForBicubic);
356 return GrSimpleTextureEffect::Create(texture, textureMatrix, params);
357 }
358 } else {
359 if (kDomain_DomainMode == domainMode) {
360 return GrBicubicEffect::Create(texture, textureMatrix, domain);
361 } else {
362 static const SkShader::TileMode kClampClamp[] =
bsalomone179a912016-01-20 06:18:10 -0800363 { SkShader::kClamp_TileMode, SkShader::kClamp_TileMode };
bsalomonb1b01992015-11-18 10:56:08 -0800364 return GrBicubicEffect::Create(texture, textureMatrix, kClampClamp);
365 }
366 }
367}
368
bsalomonc55271f2015-11-09 11:55:57 -0800369const GrFragmentProcessor* GrTextureAdjuster::createFragmentProcessor(
bsalomon3aa5fce2015-11-12 09:59:44 -0800370 const SkMatrix& origTextureMatrix,
371 const SkRect& origConstraintRect,
bsalomonc55271f2015-11-09 11:55:57 -0800372 FilterConstraint filterConstraint,
373 bool coordsLimitedToConstraintRect,
374 const GrTextureParams::FilterMode* filterOrNullForBicubic) {
375
bsalomon3aa5fce2015-11-12 09:59:44 -0800376 SkMatrix textureMatrix = origTextureMatrix;
bsalomonc55271f2015-11-09 11:55:57 -0800377 const SkIRect* contentArea = this->contentAreaOrNull();
bsalomon3aa5fce2015-11-12 09:59:44 -0800378 // Convert the constraintRect to be relative to the texture rather than the content area so
379 // that both rects are in the same coordinate system.
380 SkTCopyOnFirstWrite<SkRect> constraintRect(origConstraintRect);
381 if (contentArea) {
382 SkScalar l = SkIntToScalar(contentArea->fLeft);
383 SkScalar t = SkIntToScalar(contentArea->fTop);
384 constraintRect.writable()->offset(l, t);
385 textureMatrix.postTranslate(l, t);
386 }
bsalomonc55271f2015-11-09 11:55:57 -0800387
388 SkRect domain;
bsalomone179a912016-01-20 06:18:10 -0800389 GrTextureParams params;
390 if (filterOrNullForBicubic) {
391 params.setFilterMode(*filterOrNullForBicubic);
392 }
393 SkAutoTUnref<GrTexture> texture(this->refTextureSafeForParams(params, nullptr));
394 if (!texture) {
395 return nullptr;
396 }
397 // If we made a copy then we only copied the contentArea, in which case the new texture is all
398 // content.
399 if (texture != this->originalTexture()) {
400 contentArea = nullptr;
401 }
402
bsalomonc55271f2015-11-09 11:55:57 -0800403 DomainMode domainMode =
bsalomon3aa5fce2015-11-12 09:59:44 -0800404 determine_domain_mode(*constraintRect, filterConstraint, coordsLimitedToConstraintRect,
bsalomonc55271f2015-11-09 11:55:57 -0800405 texture->width(), texture->height(),
406 contentArea, filterOrNullForBicubic,
407 &domain);
408 if (kTightCopy_DomainMode == domainMode) {
409 // TODO: Copy the texture and adjust the texture matrix (both parts need to consider
410 // non-int constraint rect)
411 // For now: treat as bilerp and ignore what goes on above level 0.
412
413 // We only expect MIP maps to require a tight copy.
414 SkASSERT(filterOrNullForBicubic &&
415 GrTextureParams::kMipMap_FilterMode == *filterOrNullForBicubic);
416 static const GrTextureParams::FilterMode kBilerp = GrTextureParams::kBilerp_FilterMode;
417 domainMode =
bsalomon3aa5fce2015-11-12 09:59:44 -0800418 determine_domain_mode(*constraintRect, filterConstraint, coordsLimitedToConstraintRect,
bsalomonc55271f2015-11-09 11:55:57 -0800419 texture->width(), texture->height(),
420 contentArea, &kBilerp, &domain);
421 SkASSERT(kTightCopy_DomainMode != domainMode);
bsalomonc55271f2015-11-09 11:55:57 -0800422 }
423 SkASSERT(kNoDomain_DomainMode == domainMode ||
424 (domain.fLeft <= domain.fRight && domain.fTop <= domain.fBottom));
bsalomon3aa5fce2015-11-12 09:59:44 -0800425 textureMatrix.postIDiv(texture->width(), texture->height());
bsalomonb1b01992015-11-18 10:56:08 -0800426 return create_fp_for_domain_and_filter(texture, textureMatrix, domainMode, domain,
427 filterOrNullForBicubic);
bsalomonc55271f2015-11-09 11:55:57 -0800428}
429
bsalomon89fe56b2015-10-29 10:49:28 -0700430//////////////////////////////////////////////////////////////////////////////
431
bsalomonb1b01992015-11-18 10:56:08 -0800432GrTexture* GrTextureMaker::refTextureForParams(const GrTextureParams& params) {
bsalomon045802d2015-10-20 07:58:01 -0700433 CopyParams copyParams;
bsalomonb1b01992015-11-18 10:56:08 -0800434 if (!fContext->getGpu()->makeCopyForTextureParams(this->width(), this->height(), params,
435 &copyParams)) {
436 return this->refOriginalTexture();
bsalomon045802d2015-10-20 07:58:01 -0700437 }
438 GrUniqueKey copyKey;
439 this->makeCopyKey(copyParams, &copyKey);
440 if (copyKey.isValid()) {
bsalomonb1b01992015-11-18 10:56:08 -0800441 GrTexture* result = fContext->textureProvider()->findAndRefTextureByUniqueKey(copyKey);
bsalomon045802d2015-10-20 07:58:01 -0700442 if (result) {
443 return result;
444 }
445 }
446
bsalomonb1b01992015-11-18 10:56:08 -0800447 GrTexture* result = this->generateTextureForParams(copyParams);
bsalomon045802d2015-10-20 07:58:01 -0700448 if (!result) {
449 return nullptr;
450 }
451
452 if (copyKey.isValid()) {
bsalomonb1b01992015-11-18 10:56:08 -0800453 fContext->textureProvider()->assignUniqueKeyToTexture(copyKey, result);
bsalomon045802d2015-10-20 07:58:01 -0700454 this->didCacheCopy(copyKey);
455 }
456 return result;
457}
458
bsalomonb1b01992015-11-18 10:56:08 -0800459const GrFragmentProcessor* GrTextureMaker::createFragmentProcessor(
460 const SkMatrix& textureMatrix,
461 const SkRect& constraintRect,
462 FilterConstraint filterConstraint,
463 bool coordsLimitedToConstraintRect,
464 const GrTextureParams::FilterMode* filterOrNullForBicubic) {
465
466 const GrTextureParams::FilterMode* fmForDetermineDomain = filterOrNullForBicubic;
467 if (filterOrNullForBicubic && GrTextureParams::kMipMap_FilterMode == *filterOrNullForBicubic &&
468 kYes_FilterConstraint == filterConstraint) {
469 // TODo: Here we should force a copy restricted to the constraintRect since MIP maps will
470 // read outside the constraint rect. However, as in the adjuster case, we aren't currently
471 // doing that.
472 // We instead we compute the domain as though were bilerping which is only correct if we
473 // only sample level 0.
474 static const GrTextureParams::FilterMode kBilerp = GrTextureParams::kBilerp_FilterMode;
475 fmForDetermineDomain = &kBilerp;
476 }
477
478 GrTextureParams params;
479 if (filterOrNullForBicubic) {
480 params.reset(SkShader::kClamp_TileMode, *filterOrNullForBicubic);
481 } else {
482 // Bicubic doesn't use filtering for it's texture accesses.
483 params.reset(SkShader::kClamp_TileMode, GrTextureParams::kNone_FilterMode);
484 }
485 SkAutoTUnref<GrTexture> texture(this->refTextureForParams(params));
486 if (!texture) {
487 return nullptr;
488 }
489 SkRect domain;
490 DomainMode domainMode =
491 determine_domain_mode(constraintRect, filterConstraint, coordsLimitedToConstraintRect,
492 texture->width(), texture->height(), nullptr, fmForDetermineDomain,
493 &domain);
494 SkASSERT(kTightCopy_DomainMode != domainMode);
495 SkMatrix normalizedTextureMatrix = textureMatrix;
496 normalizedTextureMatrix.postIDiv(texture->width(), texture->height());
497 return create_fp_for_domain_and_filter(texture, normalizedTextureMatrix, domainMode, domain,
498 filterOrNullForBicubic);
499}
500
501GrTexture* GrTextureMaker::generateTextureForParams(const CopyParams& copyParams) {
502 SkAutoTUnref<GrTexture> original(this->refOriginalTexture());
bsalomon100b8f82015-10-28 08:37:44 -0700503 if (!original) {
504 return nullptr;
bsalomon045802d2015-10-20 07:58:01 -0700505 }
bsalomon89fe56b2015-10-29 10:49:28 -0700506 return copy_on_gpu(original, nullptr, copyParams);
bsalomon045802d2015-10-20 07:58:01 -0700507}