aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu
diff options
context:
space:
mode:
authorGravatar Brian Osman <brianosman@google.com>2016-11-28 10:06:27 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2016-11-28 15:44:40 +0000
commite8e54580c3c91fd485187af040af118aa5153261 (patch)
tree27d67ccb3500d300ba40e52bef56c05b095999df /src/gpu
parente9f78b41c65a78400c22a1b79007b1b9e187a745 (diff)
GrTextureProducer cleanup, phase two: Producer, Adjuster, Maker
Previously: GrTextureProducer, GrTextureAdjuster, and GrTextureMaker were all in GrTextureParamsAdjuster.h. Now they're each in their own header. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=5202 Change-Id: I17fa9057b11511aa4d3e15569ea1c378cfec4c80 Reviewed-on: https://skia-review.googlesource.com/5202 Reviewed-by: Robert Phillips <robertphillips@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Brian Osman <brianosman@google.com>
Diffstat (limited to 'src/gpu')
-rw-r--r--src/gpu/GrBitmapTextureMaker.h2
-rw-r--r--src/gpu/GrGpu.h2
-rw-r--r--src/gpu/GrImageTextureMaker.h2
-rw-r--r--src/gpu/GrTextureAdjuster.cpp167
-rw-r--r--src/gpu/GrTextureAdjuster.h66
-rw-r--r--src/gpu/GrTextureMaker.cpp107
-rw-r--r--src/gpu/GrTextureMaker.h74
-rw-r--r--src/gpu/GrTextureParamsAdjuster.cpp524
-rw-r--r--src/gpu/GrTextureParamsAdjuster.h236
-rw-r--r--src/gpu/GrTextureProducer.cpp252
-rw-r--r--src/gpu/GrTextureProducer.h146
-rw-r--r--src/gpu/GrTextureProvider.cpp1
-rw-r--r--src/gpu/SkGpuDevice.cpp1
-rw-r--r--src/gpu/SkGpuDevice_drawTexture.cpp4
-rw-r--r--src/gpu/SkGr.cpp1
15 files changed, 819 insertions, 766 deletions
diff --git a/src/gpu/GrBitmapTextureMaker.h b/src/gpu/GrBitmapTextureMaker.h
index f66f20ce56..33145439c4 100644
--- a/src/gpu/GrBitmapTextureMaker.h
+++ b/src/gpu/GrBitmapTextureMaker.h
@@ -8,7 +8,7 @@
#ifndef GrBitmapTextureMaker_DEFINED
#define GrBitmapTextureMaker_DEFINED
-#include "GrTextureParamsAdjuster.h"
+#include "GrTextureMaker.h"
/** This class manages the conversion of SW-backed bitmaps to GrTextures. If the input bitmap is
non-volatile the texture is cached using a key created from the pixels' image id and the
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index f88423be66..80beffafd7 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -12,7 +12,7 @@
#include "GrProgramDesc.h"
#include "GrSwizzle.h"
#include "GrAllocator.h"
-#include "GrTextureParamsAdjuster.h"
+#include "GrTextureProducer.h"
#include "GrTypes.h"
#include "GrXferProcessor.h"
#include "SkPath.h"
diff --git a/src/gpu/GrImageTextureMaker.h b/src/gpu/GrImageTextureMaker.h
index b156fabf7a..e2f3a5f956 100644
--- a/src/gpu/GrImageTextureMaker.h
+++ b/src/gpu/GrImageTextureMaker.h
@@ -8,7 +8,7 @@
#ifndef GrImageTextureMaker_DEFINED
#define GrImageTextureMaker_DEFINED
-#include "GrTextureParamsAdjuster.h"
+#include "GrTextureMaker.h"
#include "SkImage.h"
class SkImageCacherator;
diff --git a/src/gpu/GrTextureAdjuster.cpp b/src/gpu/GrTextureAdjuster.cpp
new file mode 100644
index 0000000000..24d050a1ed
--- /dev/null
+++ b/src/gpu/GrTextureAdjuster.cpp
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrTextureAdjuster.h"
+
+#include "GrContext.h"
+#include "GrGpu.h"
+#include "GrGpuResourcePriv.h"
+#include "GrTexture.h"
+#include "SkGrPriv.h"
+
+GrTextureAdjuster::GrTextureAdjuster(GrTexture* original, SkAlphaType alphaType,
+ const SkIRect& contentArea, uint32_t uniqueID,
+ SkColorSpace* cs)
+ : INHERITED(contentArea.width(), contentArea.height(),
+ GrPixelConfigIsAlphaOnly(original->config()))
+ , fOriginal(original)
+ , fAlphaType(alphaType)
+ , fColorSpace(cs)
+ , fUniqueID(uniqueID) {
+ SkASSERT(SkIRect::MakeWH(original->width(), original->height()).contains(contentArea));
+ if (contentArea.fLeft > 0 || contentArea.fTop > 0 ||
+ contentArea.fRight < original->width() || contentArea.fBottom < original->height()) {
+ fContentArea.set(contentArea);
+ }
+}
+
+void GrTextureAdjuster::makeCopyKey(const CopyParams& params, GrUniqueKey* copyKey,
+ SkDestinationSurfaceColorMode) {
+ // Color mode is irrelevant in this case - we already have a texture so we're just sub-setting
+ GrUniqueKey baseKey;
+ GrMakeKeyFromImageID(&baseKey, fUniqueID, SkIRect::MakeWH(this->width(), this->height()));
+ MakeCopyKeyFromOrigKey(baseKey, params, copyKey);
+}
+
+void GrTextureAdjuster::didCacheCopy(const GrUniqueKey& copyKey) {
+ // We don't currently have a mechanism for notifications on Images!
+}
+
+GrTexture* GrTextureAdjuster::refCopy(const CopyParams& copyParams) {
+ GrTexture* texture = this->originalTexture();
+ GrContext* context = texture->getContext();
+ const SkIRect* contentArea = this->contentAreaOrNull();
+ GrUniqueKey key;
+ this->makeCopyKey(copyParams, &key, SkDestinationSurfaceColorMode::kGammaAndColorSpaceAware);
+ if (key.isValid()) {
+ GrTexture* cachedCopy = context->textureProvider()->findAndRefTextureByUniqueKey(key);
+ if (cachedCopy) {
+ return cachedCopy;
+ }
+ }
+ GrTexture* copy = CopyOnGpu(texture, contentArea, copyParams);
+ if (copy) {
+ if (key.isValid()) {
+ copy->resourcePriv().setUniqueKey(key);
+ this->didCacheCopy(key);
+ }
+ }
+ return copy;
+}
+
+GrTexture* GrTextureAdjuster::refTextureSafeForParams(const GrSamplerParams& params,
+ SkDestinationSurfaceColorMode colorMode,
+ SkIPoint* outOffset) {
+ GrTexture* texture = this->originalTexture();
+ GrContext* context = texture->getContext();
+ CopyParams copyParams;
+ const SkIRect* contentArea = this->contentAreaOrNull();
+
+ if (!context) {
+ // The texture was abandoned.
+ return nullptr;
+ }
+
+ if (contentArea && GrSamplerParams::kMipMap_FilterMode == params.filterMode()) {
+ // If we generate a MIP chain for texture it will read pixel values from outside the content
+ // area.
+ copyParams.fWidth = contentArea->width();
+ copyParams.fHeight = contentArea->height();
+ copyParams.fFilter = GrSamplerParams::kBilerp_FilterMode;
+ } else if (!context->getGpu()->makeCopyForTextureParams(texture, params, &copyParams)) {
+ if (outOffset) {
+ if (contentArea) {
+ outOffset->set(contentArea->fLeft, contentArea->fRight);
+ } else {
+ outOffset->set(0, 0);
+ }
+ }
+ return SkRef(texture);
+ }
+
+ GrTexture* copy = this->refCopy(copyParams);
+ if (copy && outOffset) {
+ outOffset->set(0, 0);
+ }
+ return copy;
+}
+
+sk_sp<GrFragmentProcessor> GrTextureAdjuster::createFragmentProcessor(
+ const SkMatrix& origTextureMatrix,
+ const SkRect& origConstraintRect,
+ FilterConstraint filterConstraint,
+ bool coordsLimitedToConstraintRect,
+ const GrSamplerParams::FilterMode* filterOrNullForBicubic,
+ SkColorSpace* dstColorSpace,
+ SkDestinationSurfaceColorMode colorMode) {
+
+ SkMatrix textureMatrix = origTextureMatrix;
+ const SkIRect* contentArea = this->contentAreaOrNull();
+ // Convert the constraintRect to be relative to the texture rather than the content area so
+ // that both rects are in the same coordinate system.
+ SkTCopyOnFirstWrite<SkRect> constraintRect(origConstraintRect);
+ if (contentArea) {
+ SkScalar l = SkIntToScalar(contentArea->fLeft);
+ SkScalar t = SkIntToScalar(contentArea->fTop);
+ constraintRect.writable()->offset(l, t);
+ textureMatrix.postTranslate(l, t);
+ }
+
+ SkRect domain;
+ GrSamplerParams params;
+ if (filterOrNullForBicubic) {
+ params.setFilterMode(*filterOrNullForBicubic);
+ }
+ sk_sp<GrTexture> texture(this->refTextureSafeForParams(params, colorMode, nullptr));
+ if (!texture) {
+ return nullptr;
+ }
+ // If we made a copy then we only copied the contentArea, in which case the new texture is all
+ // content.
+ if (texture.get() != this->originalTexture()) {
+ contentArea = nullptr;
+ }
+
+ DomainMode domainMode =
+ DetermineDomainMode(*constraintRect, filterConstraint, coordsLimitedToConstraintRect,
+ texture->width(), texture->height(),
+ contentArea, filterOrNullForBicubic,
+ &domain);
+ if (kTightCopy_DomainMode == domainMode) {
+ // TODO: Copy the texture and adjust the texture matrix (both parts need to consider
+ // non-int constraint rect)
+ // For now: treat as bilerp and ignore what goes on above level 0.
+
+ // We only expect MIP maps to require a tight copy.
+ SkASSERT(filterOrNullForBicubic &&
+ GrSamplerParams::kMipMap_FilterMode == *filterOrNullForBicubic);
+ static const GrSamplerParams::FilterMode kBilerp = GrSamplerParams::kBilerp_FilterMode;
+ domainMode =
+ DetermineDomainMode(*constraintRect, filterConstraint, coordsLimitedToConstraintRect,
+ texture->width(), texture->height(),
+ contentArea, &kBilerp, &domain);
+ SkASSERT(kTightCopy_DomainMode != domainMode);
+ }
+ SkASSERT(kNoDomain_DomainMode == domainMode ||
+ (domain.fLeft <= domain.fRight && domain.fTop <= domain.fBottom));
+ textureMatrix.postIDiv(texture->width(), texture->height());
+ sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(fColorSpace,
+ dstColorSpace);
+ return CreateFragmentProcessorForDomainAndFilter(texture.get(), std::move(colorSpaceXform),
+ textureMatrix, domainMode, domain,
+ filterOrNullForBicubic);
+}
diff --git a/src/gpu/GrTextureAdjuster.h b/src/gpu/GrTextureAdjuster.h
new file mode 100644
index 0000000000..0e3fe52df9
--- /dev/null
+++ b/src/gpu/GrTextureAdjuster.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrTextureAdjuster_DEFINED
+#define GrTextureAdjuster_DEFINED
+
+#include "GrTextureProducer.h"
+#include "SkTLazy.h"
+
+/**
+ * Base class for sources that start out as textures. Optionally allows for a content area subrect.
+ * The intent is not to use content area for subrect rendering. Rather, the pixels outside the
+ * content area have undefined values and shouldn't be read *regardless* of filtering mode or
+ * the SkCanvas::SrcRectConstraint used for subrect draws.
+ */
+class GrTextureAdjuster : public GrTextureProducer {
+public:
+ /** Makes the subset of the texture safe to use with the given texture parameters.
+ outOffset will be the top-left corner of the subset if a copy is not made. Otherwise,
+ the copy will be tight to the contents and outOffset will be (0, 0). If the copy's size
+ does not match subset's dimensions then the contents are scaled to fit the copy.*/
+ GrTexture* refTextureSafeForParams(const GrSamplerParams&, SkDestinationSurfaceColorMode,
+ SkIPoint* outOffset);
+
+ sk_sp<GrFragmentProcessor> createFragmentProcessor(
+ const SkMatrix& textureMatrix,
+ const SkRect& constraintRect,
+ FilterConstraint,
+ bool coordsLimitedToConstraintRect,
+ const GrSamplerParams::FilterMode* filterOrNullForBicubic,
+ SkColorSpace* dstColorSpace,
+ SkDestinationSurfaceColorMode) override;
+
+ // We do not ref the texture nor the colorspace, so the caller must keep them in scope while
+ // this Adjuster is alive.
+ GrTextureAdjuster(GrTexture*, SkAlphaType, const SkIRect& area, uint32_t uniqueID,
+ SkColorSpace*);
+
+protected:
+ SkAlphaType alphaType() const override { return fAlphaType; }
+ void makeCopyKey(const CopyParams& params, GrUniqueKey* copyKey,
+ SkDestinationSurfaceColorMode colorMode) override;
+ void didCacheCopy(const GrUniqueKey& copyKey) override;
+
+ GrTexture* originalTexture() const { return fOriginal; }
+
+ /** Returns the content area or null for the whole original texture */
+ const SkIRect* contentAreaOrNull() { return fContentArea.getMaybeNull(); }
+
+private:
+ SkTLazy<SkIRect> fContentArea;
+ GrTexture* fOriginal;
+ SkAlphaType fAlphaType;
+ SkColorSpace* fColorSpace;
+ uint32_t fUniqueID;
+
+ GrTexture* refCopy(const CopyParams &copyParams);
+
+ typedef GrTextureProducer INHERITED;
+};
+
+#endif
diff --git a/src/gpu/GrTextureMaker.cpp b/src/gpu/GrTextureMaker.cpp
new file mode 100644
index 0000000000..d303dcf895
--- /dev/null
+++ b/src/gpu/GrTextureMaker.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrTextureMaker.h"
+
+#include "GrContext.h"
+#include "GrGpu.h"
+
+GrTexture* GrTextureMaker::refTextureForParams(const GrSamplerParams& params,
+ SkDestinationSurfaceColorMode colorMode,
+ sk_sp<SkColorSpace>* texColorSpace) {
+ CopyParams copyParams;
+ bool willBeMipped = params.filterMode() == GrSamplerParams::kMipMap_FilterMode;
+
+ if (!fContext->caps()->mipMapSupport()) {
+ willBeMipped = false;
+ }
+
+ if (texColorSpace) {
+ *texColorSpace = this->getColorSpace(colorMode);
+ }
+
+ if (!fContext->getGpu()->makeCopyForTextureParams(this->width(), this->height(), params,
+ &copyParams)) {
+ return this->refOriginalTexture(willBeMipped, colorMode);
+ }
+ GrUniqueKey copyKey;
+ this->makeCopyKey(copyParams, &copyKey, colorMode);
+ if (copyKey.isValid()) {
+ GrTexture* result = fContext->textureProvider()->findAndRefTextureByUniqueKey(copyKey);
+ if (result) {
+ return result;
+ }
+ }
+
+ GrTexture* result = this->generateTextureForParams(copyParams, willBeMipped, colorMode);
+ if (!result) {
+ return nullptr;
+ }
+
+ if (copyKey.isValid()) {
+ fContext->textureProvider()->assignUniqueKeyToTexture(copyKey, result);
+ this->didCacheCopy(copyKey);
+ }
+ return result;
+}
+
+sk_sp<GrFragmentProcessor> GrTextureMaker::createFragmentProcessor(
+ const SkMatrix& textureMatrix,
+ const SkRect& constraintRect,
+ FilterConstraint filterConstraint,
+ bool coordsLimitedToConstraintRect,
+ const GrSamplerParams::FilterMode* filterOrNullForBicubic,
+ SkColorSpace* dstColorSpace,
+ SkDestinationSurfaceColorMode colorMode) {
+
+ const GrSamplerParams::FilterMode* fmForDetermineDomain = filterOrNullForBicubic;
+ if (filterOrNullForBicubic && GrSamplerParams::kMipMap_FilterMode == *filterOrNullForBicubic &&
+ kYes_FilterConstraint == filterConstraint) {
+ // TODo: Here we should force a copy restricted to the constraintRect since MIP maps will
+ // read outside the constraint rect. However, as in the adjuster case, we aren't currently
+ // doing that.
+ // We instead we compute the domain as though were bilerping which is only correct if we
+ // only sample level 0.
+ static const GrSamplerParams::FilterMode kBilerp = GrSamplerParams::kBilerp_FilterMode;
+ fmForDetermineDomain = &kBilerp;
+ }
+
+ GrSamplerParams params;
+ if (filterOrNullForBicubic) {
+ params.reset(SkShader::kClamp_TileMode, *filterOrNullForBicubic);
+ } else {
+ // Bicubic doesn't use filtering for it's texture accesses.
+ params.reset(SkShader::kClamp_TileMode, GrSamplerParams::kNone_FilterMode);
+ }
+ sk_sp<SkColorSpace> texColorSpace;
+ sk_sp<GrTexture> texture(this->refTextureForParams(params, colorMode, &texColorSpace));
+ if (!texture) {
+ return nullptr;
+ }
+ SkRect domain;
+ DomainMode domainMode =
+ DetermineDomainMode(constraintRect, filterConstraint, coordsLimitedToConstraintRect,
+ texture->width(), texture->height(), nullptr, fmForDetermineDomain,
+ &domain);
+ SkASSERT(kTightCopy_DomainMode != domainMode);
+ SkMatrix normalizedTextureMatrix = textureMatrix;
+ normalizedTextureMatrix.postIDiv(texture->width(), texture->height());
+ sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(texColorSpace.get(),
+ dstColorSpace);
+ return CreateFragmentProcessorForDomainAndFilter(texture.get(), std::move(colorSpaceXform),
+ normalizedTextureMatrix, domainMode, domain,
+ filterOrNullForBicubic);
+}
+
+GrTexture* GrTextureMaker::generateTextureForParams(const CopyParams& copyParams, bool willBeMipped,
+ SkDestinationSurfaceColorMode colorMode) {
+ sk_sp<GrTexture> original(this->refOriginalTexture(willBeMipped, colorMode));
+ if (!original) {
+ return nullptr;
+ }
+ return CopyOnGpu(original.get(), nullptr, copyParams);
+}
diff --git a/src/gpu/GrTextureMaker.h b/src/gpu/GrTextureMaker.h
new file mode 100644
index 0000000000..8c00e2161e
--- /dev/null
+++ b/src/gpu/GrTextureMaker.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrTextureMaker_DEFINED
+#define GrTextureMaker_DEFINED
+
+#include "GrTextureProducer.h"
+
+/**
+ * Base class for sources that start out as something other than a texture (encoded image,
+ * picture, ...).
+ */
+class GrTextureMaker : public GrTextureProducer {
+public:
+ /**
+ * Returns a texture that is safe for use with the params. If the size of the returned texture
+ * does not match width()/height() then the contents of the original must be scaled to fit
+ * the texture. Places the color space of the texture in (*texColorSpace).
+ */
+ GrTexture* refTextureForParams(const GrSamplerParams&, SkDestinationSurfaceColorMode,
+ sk_sp<SkColorSpace>* texColorSpace);
+
+ sk_sp<GrFragmentProcessor> createFragmentProcessor(
+ const SkMatrix& textureMatrix,
+ const SkRect& constraintRect,
+ FilterConstraint filterConstraint,
+ bool coordsLimitedToConstraintRect,
+ const GrSamplerParams::FilterMode* filterOrNullForBicubic,
+ SkColorSpace* dstColorSpace,
+ SkDestinationSurfaceColorMode) override;
+
+protected:
+ GrTextureMaker(GrContext* context, int width, int height, bool isAlphaOnly)
+ : INHERITED(width, height, isAlphaOnly)
+ , fContext(context) {}
+
+ /**
+ * Return the maker's "original" texture. It is the responsibility of the maker to handle any
+ * caching of the original if desired.
+ */
+ virtual GrTexture* refOriginalTexture(bool willBeMipped, SkDestinationSurfaceColorMode) = 0;
+
+ /**
+ * Returns the color space of the maker's "original" texture, assuming it was retrieved with
+ * the same destination color mode.
+ */
+ virtual sk_sp<SkColorSpace> getColorSpace(SkDestinationSurfaceColorMode) = 0;
+
+ /**
+ * Return a new (uncached) texture that is the stretch of the maker's original.
+ *
+ * The base-class handles general logic for this, and only needs access to the following
+ * method:
+ * - refOriginalTexture()
+ *
+ * Subclass may override this if they can handle creating the texture more directly than
+ * by copying.
+ */
+ virtual GrTexture* generateTextureForParams(const CopyParams&, bool willBeMipped,
+ SkDestinationSurfaceColorMode);
+
+ GrContext* context() const { return fContext; }
+
+private:
+ GrContext* fContext;
+
+ typedef GrTextureProducer INHERITED;
+};
+
+#endif
diff --git a/src/gpu/GrTextureParamsAdjuster.cpp b/src/gpu/GrTextureParamsAdjuster.cpp
deleted file mode 100644
index d924f4a976..0000000000
--- a/src/gpu/GrTextureParamsAdjuster.cpp
+++ /dev/null
@@ -1,524 +0,0 @@
-/*
- * Copyright 2015 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "GrTextureParamsAdjuster.h"
-
-#include "GrCaps.h"
-#include "GrColorSpaceXform.h"
-#include "GrContext.h"
-#include "GrRenderTargetContext.h"
-#include "GrGpu.h"
-#include "GrGpuResourcePriv.h"
-#include "GrResourceKey.h"
-#include "GrTexture.h"
-#include "GrSamplerParams.h"
-#include "GrTextureProvider.h"
-#include "SkCanvas.h"
-#include "SkGr.h"
-#include "SkGrPriv.h"
-#include "effects/GrBicubicEffect.h"
-#include "effects/GrSimpleTextureEffect.h"
-#include "effects/GrTextureDomain.h"
-
-typedef GrTextureProducer::CopyParams CopyParams;
-
-//////////////////////////////////////////////////////////////////////////////
-
-static GrTexture* copy_on_gpu(GrTexture* inputTexture, const SkIRect* subset,
- const CopyParams& copyParams) {
- SkASSERT(!subset || !subset->isEmpty());
- GrContext* context = inputTexture->getContext();
- SkASSERT(context);
-
- GrPixelConfig config = GrMakePixelConfigUncompressed(inputTexture->config());
-
- sk_sp<GrRenderTargetContext> copyRTC = context->makeRenderTargetContextWithFallback(
- SkBackingFit::kExact, copyParams.fWidth, copyParams.fHeight, config, nullptr);
- if (!copyRTC) {
- return nullptr;
- }
-
- GrPaint paint;
- paint.setGammaCorrect(true);
-
- SkScalar sx SK_INIT_TO_AVOID_WARNING;
- SkScalar sy SK_INIT_TO_AVOID_WARNING;
- if (subset) {
- sx = 1.f / inputTexture->width();
- sy = 1.f / inputTexture->height();
- }
-
- if (copyParams.fFilter != GrSamplerParams::kNone_FilterMode && subset &&
- (subset->width() != copyParams.fWidth || subset->height() != copyParams.fHeight)) {
- SkRect domain;
- domain.fLeft = (subset->fLeft + 0.5f) * sx;
- domain.fTop = (subset->fTop + 0.5f)* sy;
- domain.fRight = (subset->fRight - 0.5f) * sx;
- domain.fBottom = (subset->fBottom - 0.5f) * sy;
- // This would cause us to read values from outside the subset. Surely, the caller knows
- // better!
- SkASSERT(copyParams.fFilter != GrSamplerParams::kMipMap_FilterMode);
- paint.addColorFragmentProcessor(
- GrTextureDomainEffect::Make(inputTexture, nullptr, SkMatrix::I(), domain,
- GrTextureDomain::kClamp_Mode,
- copyParams.fFilter));
- } else {
- GrSamplerParams params(SkShader::kClamp_TileMode, copyParams.fFilter);
- paint.addColorTextureProcessor(inputTexture, nullptr, SkMatrix::I(), params);
- }
- paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
-
- SkRect localRect;
- if (subset) {
- localRect = SkRect::Make(*subset);
- localRect.fLeft *= sx;
- localRect.fTop *= sy;
- localRect.fRight *= sx;
- localRect.fBottom *= sy;
- } else {
- localRect = SkRect::MakeWH(1.f, 1.f);
- }
-
- SkRect dstRect = SkRect::MakeIWH(copyParams.fWidth, copyParams.fHeight);
- copyRTC->fillRectToRect(GrNoClip(), paint, SkMatrix::I(), dstRect, localRect);
- return copyRTC->asTexture().release();
-}
-
-GrTextureAdjuster::GrTextureAdjuster(GrTexture* original, SkAlphaType alphaType,
- const SkIRect& contentArea, uint32_t uniqueID,
- SkColorSpace* cs)
- : INHERITED(contentArea.width(), contentArea.height(),
- GrPixelConfigIsAlphaOnly(original->config()))
- , fOriginal(original)
- , fAlphaType(alphaType)
- , fColorSpace(cs)
- , fUniqueID(uniqueID)
-{
- SkASSERT(SkIRect::MakeWH(original->width(), original->height()).contains(contentArea));
- if (contentArea.fLeft > 0 || contentArea.fTop > 0 ||
- contentArea.fRight < original->width() || contentArea.fBottom < original->height()) {
- fContentArea.set(contentArea);
- }
-}
-
-void GrTextureAdjuster::makeCopyKey(const CopyParams& params, GrUniqueKey* copyKey,
- SkDestinationSurfaceColorMode) {
- // Color mode is irrelevant in this case - we already have a texture so we're just sub-setting
- GrUniqueKey baseKey;
- GrMakeKeyFromImageID(&baseKey, fUniqueID, SkIRect::MakeWH(this->width(), this->height()));
- MakeCopyKeyFromOrigKey(baseKey, params, copyKey);
-}
-
-void GrTextureAdjuster::didCacheCopy(const GrUniqueKey& copyKey) {
- // We don't currently have a mechanism for notifications on Images!
-}
-
-GrTexture* GrTextureAdjuster::refCopy(const CopyParams& copyParams) {
- GrTexture* texture = this->originalTexture();
- GrContext* context = texture->getContext();
- const SkIRect* contentArea = this->contentAreaOrNull();
- GrUniqueKey key;
- this->makeCopyKey(copyParams, &key, SkDestinationSurfaceColorMode::kGammaAndColorSpaceAware);
- if (key.isValid()) {
- GrTexture* cachedCopy = context->textureProvider()->findAndRefTextureByUniqueKey(key);
- if (cachedCopy) {
- return cachedCopy;
- }
- }
- GrTexture* copy = copy_on_gpu(texture, contentArea, copyParams);
- if (copy) {
- if (key.isValid()) {
- copy->resourcePriv().setUniqueKey(key);
- this->didCacheCopy(key);
- }
- }
- return copy;
-}
-
-GrTexture* GrTextureAdjuster::refTextureSafeForParams(const GrSamplerParams& params,
- SkDestinationSurfaceColorMode colorMode,
- SkIPoint* outOffset) {
- GrTexture* texture = this->originalTexture();
- GrContext* context = texture->getContext();
- CopyParams copyParams;
- const SkIRect* contentArea = this->contentAreaOrNull();
-
- if (!context) {
- // The texture was abandoned.
- return nullptr;
- }
-
- if (contentArea && GrSamplerParams::kMipMap_FilterMode == params.filterMode()) {
- // If we generate a MIP chain for texture it will read pixel values from outside the content
- // area.
- copyParams.fWidth = contentArea->width();
- copyParams.fHeight = contentArea->height();
- copyParams.fFilter = GrSamplerParams::kBilerp_FilterMode;
- } else if (!context->getGpu()->makeCopyForTextureParams(texture, params, &copyParams)) {
- if (outOffset) {
- if (contentArea) {
- outOffset->set(contentArea->fLeft, contentArea->fRight);
- } else {
- outOffset->set(0, 0);
- }
- }
- return SkRef(texture);
- }
-
- GrTexture* copy = this->refCopy(copyParams);
- if (copy && outOffset) {
- outOffset->set(0, 0);
- }
- return copy;
-}
-
-enum DomainMode {
- kNoDomain_DomainMode,
- kDomain_DomainMode,
- kTightCopy_DomainMode
-};
-
-/** Determines whether a texture domain is necessary and if so what domain to use. There are two
- * rectangles to consider:
- * - The first is the content area specified by the texture adjuster. We can *never* allow
- * filtering to cause bleed of pixels outside this rectangle.
- * - The second rectangle is the constraint rectangle, which is known to be contained by the
- * content area. The filterConstraint specifies whether we are allowed to bleed across this
- * rect.
- *
- * We want to avoid using a domain if possible. We consider the above rectangles, the filter type,
- * and whether the coords generated by the draw would all fall within the constraint rect. If the
- * latter is true we only need to consider whether the filter would extend beyond the rects.
- */
-static DomainMode determine_domain_mode(
- const SkRect& constraintRect,
- GrTextureAdjuster::FilterConstraint filterConstraint,
- bool coordsLimitedToConstraintRect,
- int texW, int texH,
- const SkIRect* textureContentArea,
- const GrSamplerParams::FilterMode* filterModeOrNullForBicubic,
- SkRect* domainRect) {
-
- SkASSERT(SkRect::MakeIWH(texW, texH).contains(constraintRect));
- // We only expect a content area rect if there is some non-content area.
- SkASSERT(!textureContentArea ||
- (!textureContentArea->contains(SkIRect::MakeWH(texW, texH)) &&
- SkRect::Make(*textureContentArea).contains(constraintRect)));
-
- SkRect textureBounds = SkRect::MakeIWH(texW, texH);
- // If the src rectangle contains the whole texture then no need for a domain.
- if (constraintRect.contains(textureBounds)) {
- return kNoDomain_DomainMode;
- }
-
- bool restrictFilterToRect = (filterConstraint == GrTextureProducer::kYes_FilterConstraint);
-
- // If we can filter outside the constraint rect, and there is no non-content area of the
- // texture, and we aren't going to generate sample coords outside the constraint rect then we
- // don't need a domain.
- if (!restrictFilterToRect && !textureContentArea && coordsLimitedToConstraintRect) {
- return kNoDomain_DomainMode;
- }
-
- // Get the domain inset based on sampling mode (or bail if mipped)
- SkScalar filterHalfWidth = 0.f;
- if (filterModeOrNullForBicubic) {
- switch (*filterModeOrNullForBicubic) {
- case GrSamplerParams::kNone_FilterMode:
- if (coordsLimitedToConstraintRect) {
- return kNoDomain_DomainMode;
- } else {
- filterHalfWidth = 0.f;
- }
- break;
- case GrSamplerParams::kBilerp_FilterMode:
- filterHalfWidth = .5f;
- break;
- case GrSamplerParams::kMipMap_FilterMode:
- if (restrictFilterToRect || textureContentArea) {
- // No domain can save us here.
- return kTightCopy_DomainMode;
- }
- return kNoDomain_DomainMode;
- }
- } else {
- // bicubic does nearest filtering internally.
- filterHalfWidth = 1.5f;
- }
-
- // Both bilerp and bicubic use bilinear filtering and so need to be clamped to the center
- // of the edge texel. Pinning to the texel center has no impact on nearest mode and MIP-maps
-
- static const SkScalar kDomainInset = 0.5f;
- // Figure out the limits of pixels we're allowed to sample from.
- // Unless we know the amount of outset and the texture matrix we have to conservatively enforce
- // the domain.
- if (restrictFilterToRect) {
- domainRect->fLeft = constraintRect.fLeft + kDomainInset;
- domainRect->fTop = constraintRect.fTop + kDomainInset;
- domainRect->fRight = constraintRect.fRight - kDomainInset;
- domainRect->fBottom = constraintRect.fBottom - kDomainInset;
- } else if (textureContentArea) {
- // If we got here then: there is a textureContentArea, the coords are limited to the
- // constraint rect, and we're allowed to filter across the constraint rect boundary. So
- // we check whether the filter would reach across the edge of the content area.
- // We will only set the sides that are required.
-
- domainRect->setLargest();
- if (coordsLimitedToConstraintRect) {
- // We may be able to use the fact that the texture coords are limited to the constraint
- // rect in order to avoid having to add a domain.
- bool needContentAreaConstraint = false;
- if (textureContentArea->fLeft > 0 &&
- textureContentArea->fLeft + filterHalfWidth > constraintRect.fLeft) {
- domainRect->fLeft = textureContentArea->fLeft + kDomainInset;
- needContentAreaConstraint = true;
- }
- if (textureContentArea->fTop > 0 &&
- textureContentArea->fTop + filterHalfWidth > constraintRect.fTop) {
- domainRect->fTop = textureContentArea->fTop + kDomainInset;
- needContentAreaConstraint = true;
- }
- if (textureContentArea->fRight < texW &&
- textureContentArea->fRight - filterHalfWidth < constraintRect.fRight) {
- domainRect->fRight = textureContentArea->fRight - kDomainInset;
- needContentAreaConstraint = true;
- }
- if (textureContentArea->fBottom < texH &&
- textureContentArea->fBottom - filterHalfWidth < constraintRect.fBottom) {
- domainRect->fBottom = textureContentArea->fBottom - kDomainInset;
- needContentAreaConstraint = true;
- }
- if (!needContentAreaConstraint) {
- return kNoDomain_DomainMode;
- }
- } else {
- // Our sample coords for the texture are allowed to be outside the constraintRect so we
- // don't consider it when computing the domain.
- if (textureContentArea->fLeft != 0) {
- domainRect->fLeft = textureContentArea->fLeft + kDomainInset;
- }
- if (textureContentArea->fTop != 0) {
- domainRect->fTop = textureContentArea->fTop + kDomainInset;
- }
- if (textureContentArea->fRight != texW) {
- domainRect->fRight = textureContentArea->fRight - kDomainInset;
- }
- if (textureContentArea->fBottom != texH) {
- domainRect->fBottom = textureContentArea->fBottom - kDomainInset;
- }
- }
- } else {
- return kNoDomain_DomainMode;
- }
-
- if (domainRect->fLeft > domainRect->fRight) {
- domainRect->fLeft = domainRect->fRight = SkScalarAve(domainRect->fLeft, domainRect->fRight);
- }
- if (domainRect->fTop > domainRect->fBottom) {
- domainRect->fTop = domainRect->fBottom = SkScalarAve(domainRect->fTop, domainRect->fBottom);
- }
- domainRect->fLeft /= texW;
- domainRect->fTop /= texH;
- domainRect->fRight /= texW;
- domainRect->fBottom /= texH;
- return kDomain_DomainMode;
-}
-
-static sk_sp<GrFragmentProcessor> create_fp_for_domain_and_filter(
- GrTexture* texture,
- sk_sp<GrColorSpaceXform> colorSpaceXform,
- const SkMatrix& textureMatrix,
- DomainMode domainMode,
- const SkRect& domain,
- const GrSamplerParams::FilterMode* filterOrNullForBicubic) {
- SkASSERT(kTightCopy_DomainMode != domainMode);
- if (filterOrNullForBicubic) {
- if (kDomain_DomainMode == domainMode) {
- return GrTextureDomainEffect::Make(texture, std::move(colorSpaceXform), textureMatrix,
- domain, GrTextureDomain::kClamp_Mode,
- *filterOrNullForBicubic);
- } else {
- GrSamplerParams params(SkShader::kClamp_TileMode, *filterOrNullForBicubic);
- return GrSimpleTextureEffect::Make(texture, std::move(colorSpaceXform), textureMatrix,
- params);
- }
- } else {
- if (kDomain_DomainMode == domainMode) {
- return GrBicubicEffect::Make(texture, std::move(colorSpaceXform), textureMatrix,
- domain);
- } else {
- static const SkShader::TileMode kClampClamp[] =
- { SkShader::kClamp_TileMode, SkShader::kClamp_TileMode };
- return GrBicubicEffect::Make(texture, std::move(colorSpaceXform), textureMatrix,
- kClampClamp);
- }
- }
-}
-
-sk_sp<GrFragmentProcessor> GrTextureAdjuster::createFragmentProcessor(
- const SkMatrix& origTextureMatrix,
- const SkRect& origConstraintRect,
- FilterConstraint filterConstraint,
- bool coordsLimitedToConstraintRect,
- const GrSamplerParams::FilterMode* filterOrNullForBicubic,
- SkColorSpace* dstColorSpace,
- SkDestinationSurfaceColorMode colorMode) {
-
- SkMatrix textureMatrix = origTextureMatrix;
- const SkIRect* contentArea = this->contentAreaOrNull();
- // Convert the constraintRect to be relative to the texture rather than the content area so
- // that both rects are in the same coordinate system.
- SkTCopyOnFirstWrite<SkRect> constraintRect(origConstraintRect);
- if (contentArea) {
- SkScalar l = SkIntToScalar(contentArea->fLeft);
- SkScalar t = SkIntToScalar(contentArea->fTop);
- constraintRect.writable()->offset(l, t);
- textureMatrix.postTranslate(l, t);
- }
-
- SkRect domain;
- GrSamplerParams params;
- if (filterOrNullForBicubic) {
- params.setFilterMode(*filterOrNullForBicubic);
- }
- sk_sp<GrTexture> texture(this->refTextureSafeForParams(params, colorMode, nullptr));
- if (!texture) {
- return nullptr;
- }
- // If we made a copy then we only copied the contentArea, in which case the new texture is all
- // content.
- if (texture.get() != this->originalTexture()) {
- contentArea = nullptr;
- }
-
- DomainMode domainMode =
- determine_domain_mode(*constraintRect, filterConstraint, coordsLimitedToConstraintRect,
- texture->width(), texture->height(),
- contentArea, filterOrNullForBicubic,
- &domain);
- if (kTightCopy_DomainMode == domainMode) {
- // TODO: Copy the texture and adjust the texture matrix (both parts need to consider
- // non-int constraint rect)
- // For now: treat as bilerp and ignore what goes on above level 0.
-
- // We only expect MIP maps to require a tight copy.
- SkASSERT(filterOrNullForBicubic &&
- GrSamplerParams::kMipMap_FilterMode == *filterOrNullForBicubic);
- static const GrSamplerParams::FilterMode kBilerp = GrSamplerParams::kBilerp_FilterMode;
- domainMode =
- determine_domain_mode(*constraintRect, filterConstraint, coordsLimitedToConstraintRect,
- texture->width(), texture->height(),
- contentArea, &kBilerp, &domain);
- SkASSERT(kTightCopy_DomainMode != domainMode);
- }
- SkASSERT(kNoDomain_DomainMode == domainMode ||
- (domain.fLeft <= domain.fRight && domain.fTop <= domain.fBottom));
- textureMatrix.postIDiv(texture->width(), texture->height());
- sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(fColorSpace,
- dstColorSpace);
- return create_fp_for_domain_and_filter(texture.get(), std::move(colorSpaceXform), textureMatrix,
- domainMode, domain, filterOrNullForBicubic);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-GrTexture* GrTextureMaker::refTextureForParams(const GrSamplerParams& params,
- SkDestinationSurfaceColorMode colorMode,
- sk_sp<SkColorSpace>* texColorSpace) {
- CopyParams copyParams;
- bool willBeMipped = params.filterMode() == GrSamplerParams::kMipMap_FilterMode;
-
- if (!fContext->caps()->mipMapSupport()) {
- willBeMipped = false;
- }
-
- if (texColorSpace) {
- *texColorSpace = this->getColorSpace(colorMode);
- }
-
- if (!fContext->getGpu()->makeCopyForTextureParams(this->width(), this->height(), params,
- &copyParams)) {
- return this->refOriginalTexture(willBeMipped, colorMode);
- }
- GrUniqueKey copyKey;
- this->makeCopyKey(copyParams, &copyKey, colorMode);
- if (copyKey.isValid()) {
- GrTexture* result = fContext->textureProvider()->findAndRefTextureByUniqueKey(copyKey);
- if (result) {
- return result;
- }
- }
-
- GrTexture* result = this->generateTextureForParams(copyParams, willBeMipped, colorMode);
- if (!result) {
- return nullptr;
- }
-
- if (copyKey.isValid()) {
- fContext->textureProvider()->assignUniqueKeyToTexture(copyKey, result);
- this->didCacheCopy(copyKey);
- }
- return result;
-}
-
-sk_sp<GrFragmentProcessor> GrTextureMaker::createFragmentProcessor(
- const SkMatrix& textureMatrix,
- const SkRect& constraintRect,
- FilterConstraint filterConstraint,
- bool coordsLimitedToConstraintRect,
- const GrSamplerParams::FilterMode* filterOrNullForBicubic,
- SkColorSpace* dstColorSpace,
- SkDestinationSurfaceColorMode colorMode) {
-
- const GrSamplerParams::FilterMode* fmForDetermineDomain = filterOrNullForBicubic;
- if (filterOrNullForBicubic && GrSamplerParams::kMipMap_FilterMode == *filterOrNullForBicubic &&
- kYes_FilterConstraint == filterConstraint) {
- // TODo: Here we should force a copy restricted to the constraintRect since MIP maps will
- // read outside the constraint rect. However, as in the adjuster case, we aren't currently
- // doing that.
- // We instead we compute the domain as though were bilerping which is only correct if we
- // only sample level 0.
- static const GrSamplerParams::FilterMode kBilerp = GrSamplerParams::kBilerp_FilterMode;
- fmForDetermineDomain = &kBilerp;
- }
-
- GrSamplerParams params;
- if (filterOrNullForBicubic) {
- params.reset(SkShader::kClamp_TileMode, *filterOrNullForBicubic);
- } else {
- // Bicubic doesn't use filtering for it's texture accesses.
- params.reset(SkShader::kClamp_TileMode, GrSamplerParams::kNone_FilterMode);
- }
- sk_sp<SkColorSpace> texColorSpace;
- sk_sp<GrTexture> texture(this->refTextureForParams(params, colorMode, &texColorSpace));
- if (!texture) {
- return nullptr;
- }
- SkRect domain;
- DomainMode domainMode =
- determine_domain_mode(constraintRect, filterConstraint, coordsLimitedToConstraintRect,
- texture->width(), texture->height(), nullptr, fmForDetermineDomain,
- &domain);
- SkASSERT(kTightCopy_DomainMode != domainMode);
- SkMatrix normalizedTextureMatrix = textureMatrix;
- normalizedTextureMatrix.postIDiv(texture->width(), texture->height());
- sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(texColorSpace.get(),
- dstColorSpace);
- return create_fp_for_domain_and_filter(texture.get(), std::move(colorSpaceXform),
- normalizedTextureMatrix, domainMode, domain,
- filterOrNullForBicubic);
-}
-
-GrTexture* GrTextureMaker::generateTextureForParams(const CopyParams& copyParams, bool willBeMipped,
- SkDestinationSurfaceColorMode colorMode) {
- sk_sp<GrTexture> original(this->refOriginalTexture(willBeMipped, colorMode));
- if (!original) {
- return nullptr;
- }
- return copy_on_gpu(original.get(), nullptr, copyParams);
-}
diff --git a/src/gpu/GrTextureParamsAdjuster.h b/src/gpu/GrTextureParamsAdjuster.h
deleted file mode 100644
index c3f020196c..0000000000
--- a/src/gpu/GrTextureParamsAdjuster.h
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Copyright 2015 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrTextureMaker_DEFINED
-#define GrTextureMaker_DEFINED
-
-#include "GrSamplerParams.h"
-#include "GrResourceKey.h"
-#include "GrTexture.h"
-#include "SkTLazy.h"
-
-class GrContext;
-class GrSamplerParams;
-class GrUniqueKey;
-class SkBitmap;
-
-/**
- * Different GPUs and API extensions have different requirements with respect to what texture
- * sampling parameters may be used with textures of various types. This class facilitates making
- * texture compatible with a given GrSamplerParams. There are two immediate subclasses defined
- * below. One is a base class for sources that are inherently texture-backed (e.g. a texture-backed
- * SkImage). It supports subsetting the original texture. The other is for use cases where the
- * source can generate a texture that represents some content (e.g. cpu pixels, SkPicture, ...).
- */
-class GrTextureProducer : public SkNoncopyable {
-public:
- struct CopyParams {
- GrSamplerParams::FilterMode fFilter;
- int fWidth;
- int fHeight;
- };
-
- enum FilterConstraint {
- kYes_FilterConstraint,
- kNo_FilterConstraint,
- };
-
- /**
- * Helper for creating a fragment processor to sample the texture with a given filtering mode.
- * It attempts to avoid making texture copies or using domains whenever possible.
- *
- * @param textureMatrix Matrix used to access the texture. It is applied to
- * the local coords. The post-transformed coords should
- * be in texel units (rather than normalized) with
- * respect to this Producer's bounds (width()/height()).
- * @param constraintRect A rect that represents the area of the texture to be
- * sampled. It must be contained in the Producer's bounds
- * as defined by width()/height().
- * @param filterConstriant Indicates whether filtering is limited to
- * constraintRect.
- * @param coordsLimitedToConstraintRect Is it known that textureMatrix*localCoords is bound
- * by the portion of the texture indicated by
- * constraintRect (without consideration of filter
- * width, just the raw coords).
- * @param filterOrNullForBicubic If non-null indicates the filter mode. If null means
- * use bicubic filtering.
- **/
- virtual sk_sp<GrFragmentProcessor> createFragmentProcessor(
- const SkMatrix& textureMatrix,
- const SkRect& constraintRect,
- FilterConstraint filterConstraint,
- bool coordsLimitedToConstraintRect,
- const GrSamplerParams::FilterMode* filterOrNullForBicubic,
- SkColorSpace* dstColorSpace,
- SkDestinationSurfaceColorMode) = 0;
-
- virtual ~GrTextureProducer() {}
-
- int width() const { return fWidth; }
- int height() const { return fHeight; }
- bool isAlphaOnly() const { return fIsAlphaOnly; }
- virtual SkAlphaType alphaType() const = 0;
-
-protected:
- GrTextureProducer(int width, int height, bool isAlphaOnly)
- : fWidth(width)
- , fHeight(height)
- , fIsAlphaOnly(isAlphaOnly) {}
-
- /** Helper for creating a key for a copy from an original key. */
- static void MakeCopyKeyFromOrigKey(const GrUniqueKey& origKey,
- const CopyParams& copyParams,
- GrUniqueKey* copyKey) {
- SkASSERT(!copyKey->isValid());
- if (origKey.isValid()) {
- static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
- GrUniqueKey::Builder builder(copyKey, origKey, kDomain, 3);
- builder[0] = copyParams.fFilter;
- builder[1] = copyParams.fWidth;
- builder[2] = copyParams.fHeight;
- }
- }
-
- /**
- * If we need to make a copy in order to be compatible with GrTextureParams producer is asked to
- * return a key that identifies its original content + the CopyParms parameter. If the producer
- * does not want to cache the stretched version (e.g. the producer is volatile), this should
- * simply return without initializing the copyKey. If the texture generated by this producer
- * depends on colorMode, then that information should also be incorporated in the key.
- */
- virtual void makeCopyKey(const CopyParams&, GrUniqueKey* copyKey,
- SkDestinationSurfaceColorMode colorMode) = 0;
-
- /**
- * If a stretched version of the texture is generated, it may be cached (assuming that
- * makeCopyKey() returns true). In that case, the maker is notified in case it
- * wants to note that for when the maker is destroyed.
- */
- virtual void didCacheCopy(const GrUniqueKey& copyKey) = 0;
-
-private:
- const int fWidth;
- const int fHeight;
- const bool fIsAlphaOnly;
-
- typedef SkNoncopyable INHERITED;
-};
-
-/**
- * Base class for sources that start out as textures. Optionally allows for a content area subrect.
- * The intent is not to use content area for subrect rendering. Rather, the pixels outside the
- * content area have undefined values and shouldn't be read *regardless* of filtering mode or
- * the SkCanvas::SrcRectConstraint used for subrect draws.
- */
-class GrTextureAdjuster : public GrTextureProducer {
-public:
- /** Makes the subset of the texture safe to use with the given texture parameters.
- outOffset will be the top-left corner of the subset if a copy is not made. Otherwise,
- the copy will be tight to the contents and outOffset will be (0, 0). If the copy's size
- does not match subset's dimensions then the contents are scaled to fit the copy.*/
- GrTexture* refTextureSafeForParams(const GrSamplerParams&, SkDestinationSurfaceColorMode,
- SkIPoint* outOffset);
-
- sk_sp<GrFragmentProcessor> createFragmentProcessor(
- const SkMatrix& textureMatrix,
- const SkRect& constraintRect,
- FilterConstraint,
- bool coordsLimitedToConstraintRect,
- const GrSamplerParams::FilterMode* filterOrNullForBicubic,
- SkColorSpace* dstColorSpace,
- SkDestinationSurfaceColorMode) override;
-
- // We do not ref the texture nor the colorspace, so the caller must keep them in scope while
- // this Adjuster is alive.
- GrTextureAdjuster(GrTexture*, SkAlphaType, const SkIRect& area, uint32_t uniqueID,
- SkColorSpace*);
-
-protected:
- SkAlphaType alphaType() const override { return fAlphaType; }
- void makeCopyKey(const CopyParams& params, GrUniqueKey* copyKey,
- SkDestinationSurfaceColorMode colorMode) override;
- void didCacheCopy(const GrUniqueKey& copyKey) override;
-
- GrTexture* originalTexture() const { return fOriginal; }
-
- /** Returns the content area or null for the whole original texture */
- const SkIRect* contentAreaOrNull() { return fContentArea.getMaybeNull(); }
-
-private:
- SkTLazy<SkIRect> fContentArea;
- GrTexture* fOriginal;
- SkAlphaType fAlphaType;
- SkColorSpace* fColorSpace;
- uint32_t fUniqueID;
-
- GrTexture* refCopy(const CopyParams &copyParams);
-
- typedef GrTextureProducer INHERITED;
-};
-
-/**
- * Base class for sources that start out as something other than a texture (encoded image,
- * picture, ...).
- */
-class GrTextureMaker : public GrTextureProducer {
-public:
- /**
- * Returns a texture that is safe for use with the params. If the size of the returned texture
- * does not match width()/height() then the contents of the original must be scaled to fit
- * the texture. Places the color space of the texture in (*texColorSpace).
- */
- GrTexture* refTextureForParams(const GrSamplerParams&, SkDestinationSurfaceColorMode,
- sk_sp<SkColorSpace>* texColorSpace);
-
- sk_sp<GrFragmentProcessor> createFragmentProcessor(
- const SkMatrix& textureMatrix,
- const SkRect& constraintRect,
- FilterConstraint filterConstraint,
- bool coordsLimitedToConstraintRect,
- const GrSamplerParams::FilterMode* filterOrNullForBicubic,
- SkColorSpace* dstColorSpace,
- SkDestinationSurfaceColorMode) override;
-
-protected:
- GrTextureMaker(GrContext* context, int width, int height, bool isAlphaOnly)
- : INHERITED(width, height, isAlphaOnly)
- , fContext(context) {}
-
- /**
- * Return the maker's "original" texture. It is the responsibility of the maker to handle any
- * caching of the original if desired.
- */
- virtual GrTexture* refOriginalTexture(bool willBeMipped, SkDestinationSurfaceColorMode) = 0;
-
- /**
- * Returns the color space of the maker's "original" texture, assuming it was retrieved with
- * the same destination color mode.
- */
- virtual sk_sp<SkColorSpace> getColorSpace(SkDestinationSurfaceColorMode) = 0;
-
- /**
- * Return a new (uncached) texture that is the stretch of the maker's original.
- *
- * The base-class handles general logic for this, and only needs access to the following
- * method:
- * - refOriginalTexture()
- *
- * Subclass may override this if they can handle creating the texture more directly than
- * by copying.
- */
- virtual GrTexture* generateTextureForParams(const CopyParams&, bool willBeMipped,
- SkDestinationSurfaceColorMode);
-
- GrContext* context() const { return fContext; }
-
-private:
- GrContext* fContext;
-
- typedef GrTextureProducer INHERITED;
-};
-
-#endif
diff --git a/src/gpu/GrTextureProducer.cpp b/src/gpu/GrTextureProducer.cpp
new file mode 100644
index 0000000000..14e2c29bb8
--- /dev/null
+++ b/src/gpu/GrTextureProducer.cpp
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrTextureProducer.h"
+
+#include "GrRenderTargetContext.h"
+#include "GrTexture.h"
+#include "effects/GrBicubicEffect.h"
+#include "effects/GrSimpleTextureEffect.h"
+#include "effects/GrTextureDomain.h"
+
+GrTexture* GrTextureProducer::CopyOnGpu(GrTexture* inputTexture, const SkIRect* subset,
+ const CopyParams& copyParams) {
+ SkASSERT(!subset || !subset->isEmpty());
+ GrContext* context = inputTexture->getContext();
+ SkASSERT(context);
+
+ GrPixelConfig config = GrMakePixelConfigUncompressed(inputTexture->config());
+
+ sk_sp<GrRenderTargetContext> copyRTC = context->makeRenderTargetContextWithFallback(
+ SkBackingFit::kExact, copyParams.fWidth, copyParams.fHeight, config, nullptr);
+ if (!copyRTC) {
+ return nullptr;
+ }
+
+ GrPaint paint;
+ paint.setGammaCorrect(true);
+
+ SkScalar sx SK_INIT_TO_AVOID_WARNING;
+ SkScalar sy SK_INIT_TO_AVOID_WARNING;
+ if (subset) {
+ sx = 1.f / inputTexture->width();
+ sy = 1.f / inputTexture->height();
+ }
+
+ if (copyParams.fFilter != GrSamplerParams::kNone_FilterMode && subset &&
+ (subset->width() != copyParams.fWidth || subset->height() != copyParams.fHeight)) {
+ SkRect domain;
+ domain.fLeft = (subset->fLeft + 0.5f) * sx;
+ domain.fTop = (subset->fTop + 0.5f)* sy;
+ domain.fRight = (subset->fRight - 0.5f) * sx;
+ domain.fBottom = (subset->fBottom - 0.5f) * sy;
+ // This would cause us to read values from outside the subset. Surely, the caller knows
+ // better!
+ SkASSERT(copyParams.fFilter != GrSamplerParams::kMipMap_FilterMode);
+ paint.addColorFragmentProcessor(
+ GrTextureDomainEffect::Make(inputTexture, nullptr, SkMatrix::I(), domain,
+ GrTextureDomain::kClamp_Mode,
+ copyParams.fFilter));
+ } else {
+ GrSamplerParams params(SkShader::kClamp_TileMode, copyParams.fFilter);
+ paint.addColorTextureProcessor(inputTexture, nullptr, SkMatrix::I(), params);
+ }
+ paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
+
+ SkRect localRect;
+ if (subset) {
+ localRect = SkRect::Make(*subset);
+ localRect.fLeft *= sx;
+ localRect.fTop *= sy;
+ localRect.fRight *= sx;
+ localRect.fBottom *= sy;
+ } else {
+ localRect = SkRect::MakeWH(1.f, 1.f);
+ }
+
+ SkRect dstRect = SkRect::MakeIWH(copyParams.fWidth, copyParams.fHeight);
+ copyRTC->fillRectToRect(GrNoClip(), paint, SkMatrix::I(), dstRect, localRect);
+ return copyRTC->asTexture().release();
+}
+
+/** Determines whether a texture domain is necessary and if so what domain to use. There are two
+ * rectangles to consider:
+ * - The first is the content area specified by the texture adjuster. We can *never* allow
+ * filtering to cause bleed of pixels outside this rectangle.
+ * - The second rectangle is the constraint rectangle, which is known to be contained by the
+ * content area. The filterConstraint specifies whether we are allowed to bleed across this
+ * rect.
+ *
+ * We want to avoid using a domain if possible. We consider the above rectangles, the filter type,
+ * and whether the coords generated by the draw would all fall within the constraint rect. If the
+ * latter is true we only need to consider whether the filter would extend beyond the rects.
+ */
+GrTextureProducer::DomainMode GrTextureProducer::DetermineDomainMode(
+ const SkRect& constraintRect,
+ FilterConstraint filterConstraint,
+ bool coordsLimitedToConstraintRect,
+ int texW, int texH,
+ const SkIRect* textureContentArea,
+ const GrSamplerParams::FilterMode* filterModeOrNullForBicubic,
+ SkRect* domainRect) {
+
+ SkASSERT(SkRect::MakeIWH(texW, texH).contains(constraintRect));
+ // We only expect a content area rect if there is some non-content area.
+ SkASSERT(!textureContentArea ||
+ (!textureContentArea->contains(SkIRect::MakeWH(texW, texH)) &&
+ SkRect::Make(*textureContentArea).contains(constraintRect)));
+
+ SkRect textureBounds = SkRect::MakeIWH(texW, texH);
+ // If the src rectangle contains the whole texture then no need for a domain.
+ if (constraintRect.contains(textureBounds)) {
+ return kNoDomain_DomainMode;
+ }
+
+ bool restrictFilterToRect = (filterConstraint == GrTextureProducer::kYes_FilterConstraint);
+
+ // If we can filter outside the constraint rect, and there is no non-content area of the
+ // texture, and we aren't going to generate sample coords outside the constraint rect then we
+ // don't need a domain.
+ if (!restrictFilterToRect && !textureContentArea && coordsLimitedToConstraintRect) {
+ return kNoDomain_DomainMode;
+ }
+
+ // Get the domain inset based on sampling mode (or bail if mipped)
+ SkScalar filterHalfWidth = 0.f;
+ if (filterModeOrNullForBicubic) {
+ switch (*filterModeOrNullForBicubic) {
+ case GrSamplerParams::kNone_FilterMode:
+ if (coordsLimitedToConstraintRect) {
+ return kNoDomain_DomainMode;
+ } else {
+ filterHalfWidth = 0.f;
+ }
+ break;
+ case GrSamplerParams::kBilerp_FilterMode:
+ filterHalfWidth = .5f;
+ break;
+ case GrSamplerParams::kMipMap_FilterMode:
+ if (restrictFilterToRect || textureContentArea) {
+ // No domain can save us here.
+ return kTightCopy_DomainMode;
+ }
+ return kNoDomain_DomainMode;
+ }
+ } else {
+ // bicubic does nearest filtering internally.
+ filterHalfWidth = 1.5f;
+ }
+
+ // Both bilerp and bicubic use bilinear filtering and so need to be clamped to the center
+ // of the edge texel. Pinning to the texel center has no impact on nearest mode and MIP-maps
+
+ static const SkScalar kDomainInset = 0.5f;
+ // Figure out the limits of pixels we're allowed to sample from.
+ // Unless we know the amount of outset and the texture matrix we have to conservatively enforce
+ // the domain.
+ if (restrictFilterToRect) {
+ domainRect->fLeft = constraintRect.fLeft + kDomainInset;
+ domainRect->fTop = constraintRect.fTop + kDomainInset;
+ domainRect->fRight = constraintRect.fRight - kDomainInset;
+ domainRect->fBottom = constraintRect.fBottom - kDomainInset;
+ } else if (textureContentArea) {
+ // If we got here then: there is a textureContentArea, the coords are limited to the
+ // constraint rect, and we're allowed to filter across the constraint rect boundary. So
+ // we check whether the filter would reach across the edge of the content area.
+ // We will only set the sides that are required.
+
+ domainRect->setLargest();
+ if (coordsLimitedToConstraintRect) {
+ // We may be able to use the fact that the texture coords are limited to the constraint
+ // rect in order to avoid having to add a domain.
+ bool needContentAreaConstraint = false;
+ if (textureContentArea->fLeft > 0 &&
+ textureContentArea->fLeft + filterHalfWidth > constraintRect.fLeft) {
+ domainRect->fLeft = textureContentArea->fLeft + kDomainInset;
+ needContentAreaConstraint = true;
+ }
+ if (textureContentArea->fTop > 0 &&
+ textureContentArea->fTop + filterHalfWidth > constraintRect.fTop) {
+ domainRect->fTop = textureContentArea->fTop + kDomainInset;
+ needContentAreaConstraint = true;
+ }
+ if (textureContentArea->fRight < texW &&
+ textureContentArea->fRight - filterHalfWidth < constraintRect.fRight) {
+ domainRect->fRight = textureContentArea->fRight - kDomainInset;
+ needContentAreaConstraint = true;
+ }
+ if (textureContentArea->fBottom < texH &&
+ textureContentArea->fBottom - filterHalfWidth < constraintRect.fBottom) {
+ domainRect->fBottom = textureContentArea->fBottom - kDomainInset;
+ needContentAreaConstraint = true;
+ }
+ if (!needContentAreaConstraint) {
+ return kNoDomain_DomainMode;
+ }
+ } else {
+ // Our sample coords for the texture are allowed to be outside the constraintRect so we
+ // don't consider it when computing the domain.
+ if (textureContentArea->fLeft != 0) {
+ domainRect->fLeft = textureContentArea->fLeft + kDomainInset;
+ }
+ if (textureContentArea->fTop != 0) {
+ domainRect->fTop = textureContentArea->fTop + kDomainInset;
+ }
+ if (textureContentArea->fRight != texW) {
+ domainRect->fRight = textureContentArea->fRight - kDomainInset;
+ }
+ if (textureContentArea->fBottom != texH) {
+ domainRect->fBottom = textureContentArea->fBottom - kDomainInset;
+ }
+ }
+ } else {
+ return kNoDomain_DomainMode;
+ }
+
+ if (domainRect->fLeft > domainRect->fRight) {
+ domainRect->fLeft = domainRect->fRight = SkScalarAve(domainRect->fLeft, domainRect->fRight);
+ }
+ if (domainRect->fTop > domainRect->fBottom) {
+ domainRect->fTop = domainRect->fBottom = SkScalarAve(domainRect->fTop, domainRect->fBottom);
+ }
+ domainRect->fLeft /= texW;
+ domainRect->fTop /= texH;
+ domainRect->fRight /= texW;
+ domainRect->fBottom /= texH;
+ return kDomain_DomainMode;
+}
+
+sk_sp<GrFragmentProcessor> GrTextureProducer::CreateFragmentProcessorForDomainAndFilter(
+ GrTexture* texture,
+ sk_sp<GrColorSpaceXform> colorSpaceXform,
+ const SkMatrix& textureMatrix,
+ DomainMode domainMode,
+ const SkRect& domain,
+ const GrSamplerParams::FilterMode* filterOrNullForBicubic) {
+ SkASSERT(kTightCopy_DomainMode != domainMode);
+ if (filterOrNullForBicubic) {
+ if (kDomain_DomainMode == domainMode) {
+ return GrTextureDomainEffect::Make(texture, std::move(colorSpaceXform), textureMatrix,
+ domain, GrTextureDomain::kClamp_Mode,
+ *filterOrNullForBicubic);
+ } else {
+ GrSamplerParams params(SkShader::kClamp_TileMode, *filterOrNullForBicubic);
+ return GrSimpleTextureEffect::Make(texture, std::move(colorSpaceXform), textureMatrix,
+ params);
+ }
+ } else {
+ if (kDomain_DomainMode == domainMode) {
+ return GrBicubicEffect::Make(texture, std::move(colorSpaceXform), textureMatrix,
+ domain);
+ } else {
+ static const SkShader::TileMode kClampClamp[] =
+ { SkShader::kClamp_TileMode, SkShader::kClamp_TileMode };
+ return GrBicubicEffect::Make(texture, std::move(colorSpaceXform), textureMatrix,
+ kClampClamp);
+ }
+ }
+}
diff --git a/src/gpu/GrTextureProducer.h b/src/gpu/GrTextureProducer.h
new file mode 100644
index 0000000000..4cae933168
--- /dev/null
+++ b/src/gpu/GrTextureProducer.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrTextureProducer_DEFINED
+#define GrTextureProducer_DEFINED
+
+#include "GrSamplerParams.h"
+#include "GrResourceKey.h"
+
+class GrColorSpaceXform;
+class GrTexture;
+
+/**
+ * Different GPUs and API extensions have different requirements with respect to what texture
+ * sampling parameters may be used with textures of various types. This class facilitates making
+ * texture compatible with a given GrSamplerParams. There are two immediate subclasses defined
+ * below. One is a base class for sources that are inherently texture-backed (e.g. a texture-backed
+ * SkImage). It supports subsetting the original texture. The other is for use cases where the
+ * source can generate a texture that represents some content (e.g. cpu pixels, SkPicture, ...).
+ */
+class GrTextureProducer : public SkNoncopyable {
+public:
+ struct CopyParams {
+ GrSamplerParams::FilterMode fFilter;
+ int fWidth;
+ int fHeight;
+ };
+
+ enum FilterConstraint {
+ kYes_FilterConstraint,
+ kNo_FilterConstraint,
+ };
+
+ /**
+ * Helper for creating a fragment processor to sample the texture with a given filtering mode.
+ * It attempts to avoid making texture copies or using domains whenever possible.
+ *
+ * @param textureMatrix Matrix used to access the texture. It is applied to
+ * the local coords. The post-transformed coords should
+ * be in texel units (rather than normalized) with
+ * respect to this Producer's bounds (width()/height()).
+ * @param constraintRect A rect that represents the area of the texture to be
+ * sampled. It must be contained in the Producer's
+ * bounds as defined by width()/height().
+ * @param filterConstriant Indicates whether filtering is limited to
+ * constraintRect.
+ * @param coordsLimitedToConstraintRect Is it known that textureMatrix*localCoords is bound
+ * by the portion of the texture indicated by
+ * constraintRect (without consideration of filter
+ * width, just the raw coords).
+ * @param filterOrNullForBicubic If non-null indicates the filter mode. If null means
+ * use bicubic filtering.
+ **/
+ virtual sk_sp<GrFragmentProcessor> createFragmentProcessor(
+ const SkMatrix& textureMatrix,
+ const SkRect& constraintRect,
+ FilterConstraint filterConstraint,
+ bool coordsLimitedToConstraintRect,
+ const GrSamplerParams::FilterMode* filterOrNullForBicubic,
+ SkColorSpace* dstColorSpace,
+ SkDestinationSurfaceColorMode) = 0;
+
+ virtual ~GrTextureProducer() {}
+
+ int width() const { return fWidth; }
+ int height() const { return fHeight; }
+ bool isAlphaOnly() const { return fIsAlphaOnly; }
+ virtual SkAlphaType alphaType() const = 0;
+
+protected:
+ GrTextureProducer(int width, int height, bool isAlphaOnly)
+ : fWidth(width)
+ , fHeight(height)
+ , fIsAlphaOnly(isAlphaOnly) {}
+
+ /** Helper for creating a key for a copy from an original key. */
+ static void MakeCopyKeyFromOrigKey(const GrUniqueKey& origKey,
+ const CopyParams& copyParams,
+ GrUniqueKey* copyKey) {
+ SkASSERT(!copyKey->isValid());
+ if (origKey.isValid()) {
+ static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
+ GrUniqueKey::Builder builder(copyKey, origKey, kDomain, 3);
+ builder[0] = copyParams.fFilter;
+ builder[1] = copyParams.fWidth;
+ builder[2] = copyParams.fHeight;
+ }
+ }
+
+ /**
+ * If we need to make a copy in order to be compatible with GrTextureParams producer is asked to
+ * return a key that identifies its original content + the CopyParms parameter. If the producer
+ * does not want to cache the stretched version (e.g. the producer is volatile), this should
+ * simply return without initializing the copyKey. If the texture generated by this producer
+ * depends on colorMode, then that information should also be incorporated in the key.
+ */
+ virtual void makeCopyKey(const CopyParams&, GrUniqueKey* copyKey,
+ SkDestinationSurfaceColorMode colorMode) = 0;
+
+ /**
+ * If a stretched version of the texture is generated, it may be cached (assuming that
+ * makeCopyKey() returns true). In that case, the maker is notified in case it
+ * wants to note that for when the maker is destroyed.
+ */
+ virtual void didCacheCopy(const GrUniqueKey& copyKey) = 0;
+
+
+ enum DomainMode {
+ kNoDomain_DomainMode,
+ kDomain_DomainMode,
+ kTightCopy_DomainMode
+ };
+
+ static GrTexture* CopyOnGpu(GrTexture* inputTexture, const SkIRect* subset,
+ const CopyParams& copyParams);
+
+ static DomainMode DetermineDomainMode(
+ const SkRect& constraintRect,
+ FilterConstraint filterConstraint,
+ bool coordsLimitedToConstraintRect,
+ int texW, int texH,
+ const SkIRect* textureContentArea,
+ const GrSamplerParams::FilterMode* filterModeOrNullForBicubic,
+ SkRect* domainRect);
+
+ static sk_sp<GrFragmentProcessor> CreateFragmentProcessorForDomainAndFilter(
+ GrTexture* texture,
+ sk_sp<GrColorSpaceXform> colorSpaceXform,
+ const SkMatrix& textureMatrix,
+ DomainMode domainMode,
+ const SkRect& domain,
+ const GrSamplerParams::FilterMode* filterOrNullForBicubic);
+
+private:
+ const int fWidth;
+ const int fHeight;
+ const bool fIsAlphaOnly;
+
+ typedef SkNoncopyable INHERITED;
+};
+
+#endif
diff --git a/src/gpu/GrTextureProvider.cpp b/src/gpu/GrTextureProvider.cpp
index b49c2c96d6..8d6239d2a1 100644
--- a/src/gpu/GrTextureProvider.cpp
+++ b/src/gpu/GrTextureProvider.cpp
@@ -14,6 +14,7 @@
#include "../private/GrSingleOwner.h"
#include "SkMathPriv.h"
#include "SkTArray.h"
+#include "SkTLazy.h"
#define ASSERT_SINGLE_OWNER \
SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index aae3b95ffb..529dfa3097 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -14,6 +14,7 @@
#include "GrImageTextureMaker.h"
#include "GrRenderTargetContextPriv.h"
#include "GrStyle.h"
+#include "GrTextureAdjuster.h"
#include "GrTracing.h"
#include "SkCanvasPriv.h"
diff --git a/src/gpu/SkGpuDevice_drawTexture.cpp b/src/gpu/SkGpuDevice_drawTexture.cpp
index 74afca9beb..93c9f18737 100644
--- a/src/gpu/SkGpuDevice_drawTexture.cpp
+++ b/src/gpu/SkGpuDevice_drawTexture.cpp
@@ -11,7 +11,7 @@
#include "GrCaps.h"
#include "GrRenderTargetContext.h"
#include "GrStyle.h"
-#include "GrTextureParamsAdjuster.h"
+#include "GrTextureAdjuster.h"
#include "SkDraw.h"
#include "SkGrPriv.h"
#include "SkMaskFilter.h"
@@ -168,7 +168,7 @@ void SkGpuDevice::drawTextureProducerImpl(GrTextureProducer* producer,
&doBicubic);
const GrSamplerParams::FilterMode* filterMode = doBicubic ? nullptr : &fm;
- GrTextureAdjuster::FilterConstraint constraintMode;
+ GrTextureProducer::FilterConstraint constraintMode;
if (SkCanvas::kFast_SrcRectConstraint == constraint) {
constraintMode = GrTextureAdjuster::kNo_FilterConstraint;
} else {
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index c8eaac03e6..6ce9caed19 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -14,7 +14,6 @@
#include "GrContext.h"
#include "GrGpuResourcePriv.h"
#include "GrRenderTargetContext.h"
-#include "GrTextureParamsAdjuster.h"
#include "GrTexturePriv.h"
#include "GrTypes.h"
#include "GrXferProcessor.h"