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>
diff --git a/gn/gpu.gni b/gn/gpu.gni
index caa7fa1..e3b02b8 100644
--- a/gn/gpu.gni
+++ b/gn/gpu.gni
@@ -200,10 +200,14 @@
   "$_src/gpu/GrSurfaceProxy.cpp",
   "$_src/gpu/GrSwizzle.h",
   "$_src/gpu/GrTexture.cpp",
+  "$_src/gpu/GrTextureAdjuster.cpp",
+  "$_src/gpu/GrTextureAdjuster.h",
   "$_src/gpu/GrTextureContext.cpp",
-  "$_src/gpu/GrTextureParamsAdjuster.h",
-  "$_src/gpu/GrTextureParamsAdjuster.cpp",
+  "$_src/gpu/GrTextureMaker.cpp",
+  "$_src/gpu/GrTextureMaker.h",
   "$_src/gpu/GrTexturePriv.h",
+  "$_src/gpu/GrTextureProducer.cpp",
+  "$_src/gpu/GrTextureProducer.h",
   "$_src/gpu/GrTextureProvider.cpp",
   "$_src/gpu/GrTextureProxy.cpp",
   "$_src/gpu/GrTextureRenderTargetProxy.cpp",
diff --git a/src/gpu/GrBitmapTextureMaker.h b/src/gpu/GrBitmapTextureMaker.h
index f66f20c..3314543 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 f88423b..80beffa 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 b156fab..e2f3a5f 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 0000000..24d050a
--- /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 0000000..0e3fe52
--- /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 0000000..d303dcf
--- /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 0000000..8c00e21
--- /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 d924f4a..0000000
--- 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 c3f0201..0000000
--- 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 0000000..14e2c29
--- /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 0000000..4cae933
--- /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 b49c2c9..8d6239d 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 aae3b95..529dfa3 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 74afca9..93c9f18 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 @@
                                         &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 c8eaac0..6ce9cae 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"
diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp
index 780bfbe..0a89cf5 100644
--- a/src/image/SkImage_Gpu.cpp
+++ b/src/image/SkImage_Gpu.cpp
@@ -15,6 +15,7 @@
 #include "GrContext.h"
 #include "GrImageTextureMaker.h"
 #include "GrRenderTargetContext.h"
+#include "GrTextureAdjuster.h"
 #include "GrTexturePriv.h"
 #include "effects/GrYUVEffect.h"
 #include "SkCanvas.h"
diff --git a/src/image/SkImage_Raster.cpp b/src/image/SkImage_Raster.cpp
index 6fc03b2..b781665 100644
--- a/src/image/SkImage_Raster.cpp
+++ b/src/image/SkImage_Raster.cpp
@@ -17,7 +17,7 @@
 
 #if SK_SUPPORT_GPU
 #include "GrContext.h"
-#include "GrTextureParamsAdjuster.h"
+#include "GrTextureAdjuster.h"
 #include "SkGr.h"
 #include "SkGrPriv.h"
 #endif