Add API to invalidate GL texture parameters from GrBackendTexture.

This is modeled on how we coordinate VkImage layout changes between
GrContext and clients.

A type GrGLTextureParameters is used to track the current parameter
state.

When a client creates a GrBackendTexture in order to wrap a resource
they created a new GrGLTextureParameters is created and the wrapped
GrGLTexture will share ownership.

When GrContext creates a non-wrapped GrGLTexture, the GrGLTexture
creates a new GrGLTextureParameters and any GrBackendTextures created
from that GrGLTexture will share ownership.

Clients indicate parameter changes by calling
GrBackendTexture::glTextureParametersModified().

We still assume all texture parameters may have changed after a call
to GrContext::resetContext() (for now). The "timestamp" that is used
to implement this has been moved from GrGpu to GrGLGpu as there were
no other use cases.

Change-Id: Ic24e00488fad254a29d5eec6890278b67df6efae
Bug: skia:7966
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/217385
Auto-Submit: Brian Salomon <bsalomon@google.com>
Commit-Queue: Greg Daniel <egdaniel@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 2a9b0f4..8edb3fa 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -655,6 +655,7 @@
         fHWProgramID = 0;
         fHWProgram.reset();
     }
+    ++fResetTimestampForTextureParameters;
 }
 
 static bool check_backend_texture(const GrBackendTexture& backendTex, const GrGLCaps& caps,
@@ -706,8 +707,8 @@
     GrMipMapsStatus mipMapsStatus = backendTex.hasMipMaps() ? GrMipMapsStatus::kValid
                                                             : GrMipMapsStatus::kNotAllocated;
 
-    auto texture =
-            GrGLTexture::MakeWrapped(this, surfDesc, mipMapsStatus, idDesc, cacheable, ioType);
+    auto texture = GrGLTexture::MakeWrapped(this, surfDesc, mipMapsStatus, idDesc,
+                                            backendTex.getGLTextureParams(), cacheable, ioType);
     // We don't know what parameters are already set on wrapped textures.
     texture->textureParamsModified();
     return std::move(texture);
@@ -755,7 +756,8 @@
                                                             : GrMipMapsStatus::kNotAllocated;
 
     sk_sp<GrGLTextureRenderTarget> texRT(GrGLTextureRenderTarget::MakeWrapped(
-            this, surfDesc, idDesc, rtIDDesc, cacheable, mipMapsStatus));
+            this, surfDesc, idDesc, backendTex.getGLTextureParams(), rtIDDesc, cacheable,
+            mipMapsStatus));
     texRT->baseLevelWasBoundToFBO();
     // We don't know what parameters are already set on wrapped textures.
     texRT->textureParamsModified();
@@ -1564,21 +1566,21 @@
     return nullptr;
 }
 
-static GrGLTexture::SamplerParams set_initial_texture_params(const GrGLInterface* interface,
-                                                             const GrGLTextureInfo& info) {
+static GrGLTextureParameters::SamplerOverriddenState set_initial_texture_params(
+        const GrGLInterface* interface, const GrGLTextureInfo& info) {
     // Some drivers like to know filter/wrap before seeing glTexImage2D. Some
     // drivers have a bug where an FBO won't be complete if it includes a
     // texture that is not mipmap complete (considering the filter in use).
-    GrGLTexture::SamplerParams params;
-    params.fMinFilter = GR_GL_NEAREST;
-    params.fMagFilter = GR_GL_NEAREST;
-    params.fWrapS = GR_GL_CLAMP_TO_EDGE;
-    params.fWrapT = GR_GL_CLAMP_TO_EDGE;
-    GR_GL_CALL(interface, TexParameteri(info.fTarget, GR_GL_TEXTURE_MAG_FILTER, params.fMagFilter));
-    GR_GL_CALL(interface, TexParameteri(info.fTarget, GR_GL_TEXTURE_MIN_FILTER, params.fMinFilter));
-    GR_GL_CALL(interface, TexParameteri(info.fTarget, GR_GL_TEXTURE_WRAP_S, params.fWrapS));
-    GR_GL_CALL(interface, TexParameteri(info.fTarget, GR_GL_TEXTURE_WRAP_T, params.fWrapT));
-    return params;
+    GrGLTextureParameters::SamplerOverriddenState state;
+    state.fMinFilter = GR_GL_NEAREST;
+    state.fMagFilter = GR_GL_NEAREST;
+    state.fWrapS = GR_GL_CLAMP_TO_EDGE;
+    state.fWrapT = GR_GL_CLAMP_TO_EDGE;
+    GR_GL_CALL(interface, TexParameteri(info.fTarget, GR_GL_TEXTURE_MAG_FILTER, state.fMagFilter));
+    GR_GL_CALL(interface, TexParameteri(info.fTarget, GR_GL_TEXTURE_MIN_FILTER, state.fMinFilter));
+    GR_GL_CALL(interface, TexParameteri(info.fTarget, GR_GL_TEXTURE_WRAP_S, state.fWrapS));
+    GR_GL_CALL(interface, TexParameteri(info.fTarget, GR_GL_TEXTURE_WRAP_T, state.fWrapT));
+    return state;
 }
 
 size_t GLBytesPerPixel(GrGLenum glFormat) {
@@ -1654,10 +1656,10 @@
     GrGLTexture::IDDesc idDesc;
     idDesc.fOwnership = GrBackendObjectOwnership::kOwned;
     GrMipMapsStatus mipMapsStatus;
-    GrGLTexture::SamplerParams initialTexParams;
+    GrGLTextureParameters::SamplerOverriddenState initialState;
     if (!this->createTextureImpl(desc, &idDesc.fInfo,
                                  isRenderTarget ? GrRenderable::kYes : GrRenderable::kNo,
-                                 &initialTexParams, texels, mipLevelCount, &mipMapsStatus)) {
+                                 &initialState, texels, mipLevelCount, &mipMapsStatus)) {
         return return_null_texture();
     }
 
@@ -1677,9 +1679,9 @@
     } else {
         tex = sk_make_sp<GrGLTexture>(this, budgeted, desc, idDesc, mipMapsStatus);
     }
-
-    tex->setCachedParams(&initialTexParams, tex->getCachedNonSamplerParams(),
-                         this->getResetTimestamp());
+    // The non-sampler params are still at their default values.
+    tex->parameters()->set(&initialState, GrGLTextureParameters::NonsamplerState(),
+                           fResetTimestampForTextureParameters);
 #ifdef TRACE_TEXTURE_CREATION
     SkDebugf("--- new texture [%d] size=(%d %d) config=%d\n",
              idDesc.fInfo.fID, desc.fWidth, desc.fHeight, desc.fConfig);
@@ -1842,7 +1844,7 @@
 
 bool GrGLGpu::createTextureImpl(const GrSurfaceDesc& desc, GrGLTextureInfo* info,
                                 GrRenderable renderable,
-                                GrGLTexture::SamplerParams* initialTexParams,
+                                GrGLTextureParameters::SamplerOverriddenState* initialState,
                                 const GrMipLevel texels[], int mipLevelCount,
                                 GrMipMapsStatus* mipMapsStatus) {
     info->fID = 0;
@@ -1864,7 +1866,7 @@
                               GR_GL_FRAMEBUFFER_ATTACHMENT));
     }
 
-    *initialTexParams = set_initial_texture_params(this->glInterface(), *info);
+    *initialState = set_initial_texture_params(this->glInterface(), *info);
 
     bool success = false;
     if (GrGLFormatIsCompressed(info->fFormat)) {
@@ -3052,71 +3054,73 @@
     }
 #endif
 
-    ResetTimestamp timestamp = texture->getCachedParamsTimestamp();
-    bool setAll = timestamp < this->getResetTimestamp();
+    auto timestamp = texture->parameters()->resetTimestamp();
+    bool setAll = timestamp < fResetTimestampForTextureParameters;
 
-    const GrGLTexture::SamplerParams* samplerParamsToRecord = nullptr;
-    GrGLTexture::SamplerParams newSamplerParams;
+    const GrGLTextureParameters::SamplerOverriddenState* samplerStateToRecord = nullptr;
+    GrGLTextureParameters::SamplerOverriddenState newSamplerState;
     if (fSamplerObjectCache) {
         fSamplerObjectCache->bindSampler(unitIdx, samplerState);
     } else {
-        const GrGLTexture::SamplerParams& oldSamplerParams = texture->getCachedSamplerParams();
-        samplerParamsToRecord = &newSamplerParams;
+        const GrGLTextureParameters::SamplerOverriddenState& oldSamplerState =
+                texture->parameters()->samplerOverriddenState();
+        samplerStateToRecord = &newSamplerState;
 
-        newSamplerParams.fMinFilter = filter_to_gl_min_filter(samplerState.filter());
-        newSamplerParams.fMagFilter = filter_to_gl_mag_filter(samplerState.filter());
+        newSamplerState.fMinFilter = filter_to_gl_min_filter(samplerState.filter());
+        newSamplerState.fMagFilter = filter_to_gl_mag_filter(samplerState.filter());
 
-        newSamplerParams.fWrapS = wrap_mode_to_gl_wrap(samplerState.wrapModeX(), this->glCaps());
-        newSamplerParams.fWrapT = wrap_mode_to_gl_wrap(samplerState.wrapModeY(), this->glCaps());
+        newSamplerState.fWrapS = wrap_mode_to_gl_wrap(samplerState.wrapModeX(), this->glCaps());
+        newSamplerState.fWrapT = wrap_mode_to_gl_wrap(samplerState.wrapModeY(), this->glCaps());
 
         // These are the OpenGL default values.
-        newSamplerParams.fMinLOD = -1000.f;
-        newSamplerParams.fMaxLOD = 1000.f;
+        newSamplerState.fMinLOD = -1000.f;
+        newSamplerState.fMaxLOD = 1000.f;
 
-        if (setAll || newSamplerParams.fMagFilter != oldSamplerParams.fMagFilter) {
+        if (setAll || newSamplerState.fMagFilter != oldSamplerState.fMagFilter) {
             this->setTextureUnit(unitIdx);
-            GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MAG_FILTER, newSamplerParams.fMagFilter));
+            GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MAG_FILTER, newSamplerState.fMagFilter));
         }
-        if (setAll || newSamplerParams.fMinFilter != oldSamplerParams.fMinFilter) {
+        if (setAll || newSamplerState.fMinFilter != oldSamplerState.fMinFilter) {
             this->setTextureUnit(unitIdx);
-            GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MIN_FILTER, newSamplerParams.fMinFilter));
+            GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MIN_FILTER, newSamplerState.fMinFilter));
         }
         if (this->glCaps().mipMapLevelAndLodControlSupport()) {
-            if (setAll || newSamplerParams.fMinLOD != oldSamplerParams.fMinLOD) {
+            if (setAll || newSamplerState.fMinLOD != oldSamplerState.fMinLOD) {
                 this->setTextureUnit(unitIdx);
-                GL_CALL(TexParameterf(target, GR_GL_TEXTURE_MIN_LOD, newSamplerParams.fMinLOD));
+                GL_CALL(TexParameterf(target, GR_GL_TEXTURE_MIN_LOD, newSamplerState.fMinLOD));
             }
-            if (setAll || newSamplerParams.fMaxLOD != oldSamplerParams.fMaxLOD) {
+            if (setAll || newSamplerState.fMaxLOD != oldSamplerState.fMaxLOD) {
                 this->setTextureUnit(unitIdx);
-                GL_CALL(TexParameterf(target, GR_GL_TEXTURE_MAX_LOD, newSamplerParams.fMaxLOD));
+                GL_CALL(TexParameterf(target, GR_GL_TEXTURE_MAX_LOD, newSamplerState.fMaxLOD));
             }
         }
-        if (setAll || newSamplerParams.fWrapS != oldSamplerParams.fWrapS) {
+        if (setAll || newSamplerState.fWrapS != oldSamplerState.fWrapS) {
             this->setTextureUnit(unitIdx);
-            GL_CALL(TexParameteri(target, GR_GL_TEXTURE_WRAP_S, newSamplerParams.fWrapS));
+            GL_CALL(TexParameteri(target, GR_GL_TEXTURE_WRAP_S, newSamplerState.fWrapS));
         }
-        if (setAll || newSamplerParams.fWrapT != oldSamplerParams.fWrapT) {
+        if (setAll || newSamplerState.fWrapT != oldSamplerState.fWrapT) {
             this->setTextureUnit(unitIdx);
-            GL_CALL(TexParameteri(target, GR_GL_TEXTURE_WRAP_T, newSamplerParams.fWrapT));
+            GL_CALL(TexParameteri(target, GR_GL_TEXTURE_WRAP_T, newSamplerState.fWrapT));
         }
         if (this->glCaps().clampToBorderSupport()) {
             // Make sure the border color is transparent black (the default)
-            if (setAll || oldSamplerParams.fBorderColorInvalid) {
+            if (setAll || oldSamplerState.fBorderColorInvalid) {
                 this->setTextureUnit(unitIdx);
                 static const GrGLfloat kTransparentBlack[4] = {0.f, 0.f, 0.f, 0.f};
                 GL_CALL(TexParameterfv(target, GR_GL_TEXTURE_BORDER_COLOR, kTransparentBlack));
             }
         }
     }
-    GrGLTexture::NonSamplerParams newNonSamplerParams;
-    newNonSamplerParams.fBaseMipMapLevel = 0;
-    newNonSamplerParams.fMaxMipMapLevel = texture->texturePriv().maxMipMapLevel();
+    GrGLTextureParameters::NonsamplerState newNonsamplerState;
+    newNonsamplerState.fBaseMipMapLevel = 0;
+    newNonsamplerState.fMaxMipMapLevel = texture->texturePriv().maxMipMapLevel();
 
-    const GrGLTexture::NonSamplerParams& oldNonSamplerParams = texture->getCachedNonSamplerParams();
+    const GrGLTextureParameters::NonsamplerState& oldNonsamplerState =
+            texture->parameters()->nonsamplerState();
     if (this->glCaps().textureSwizzleSupport()) {
         auto swizzle = this->glCaps().configSwizzle(texture->config());
-        newNonSamplerParams.fSwizzleKey = swizzle.asKey();
-        if (setAll || swizzle.asKey() != oldNonSamplerParams.fSwizzleKey) {
+        newNonsamplerState.fSwizzleKey = swizzle.asKey();
+        if (setAll || swizzle.asKey() != oldNonsamplerState.fSwizzleKey) {
             GrGLenum glValues[4];
             get_gl_swizzle_values(swizzle, glValues);
             this->setTextureUnit(unitIdx);
@@ -3137,18 +3141,19 @@
     if (this->glCaps().mipMapLevelAndLodControlSupport() &&
         (texture->texturePriv().textureType() != GrTextureType::kExternal ||
          !this->glCaps().dontSetBaseOrMaxLevelForExternalTextures())) {
-        if (newNonSamplerParams.fBaseMipMapLevel != oldNonSamplerParams.fBaseMipMapLevel) {
+        if (newNonsamplerState.fBaseMipMapLevel != oldNonsamplerState.fBaseMipMapLevel) {
             this->setTextureUnit(unitIdx);
             GL_CALL(TexParameteri(target, GR_GL_TEXTURE_BASE_LEVEL,
-                                  newNonSamplerParams.fBaseMipMapLevel));
+                                  newNonsamplerState.fBaseMipMapLevel));
         }
-        if (newNonSamplerParams.fMaxMipMapLevel != oldNonSamplerParams.fMaxMipMapLevel) {
+        if (newNonsamplerState.fMaxMipMapLevel != oldNonsamplerState.fMaxMipMapLevel) {
             this->setTextureUnit(unitIdx);
             GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MAX_LEVEL,
-                                  newNonSamplerParams.fMaxMipMapLevel));
+                                  newNonsamplerState.fMaxMipMapLevel));
         }
     }
-    texture->setCachedParams(samplerParamsToRecord, newNonSamplerParams, this->getResetTimestamp());
+    texture->parameters()->set(samplerStateToRecord, newNonsamplerState,
+                               fResetTimestampForTextureParameters);
 }
 
 void GrGLGpu::onResetTextureBindings() {
@@ -3952,9 +3957,10 @@
                                  GR_GL_TEXTURE_2D, 0, 0));
 
     // We modified the base level param.
-    GrGLTexture::NonSamplerParams params = glTex->getCachedNonSamplerParams();
-    params.fBaseMipMapLevel = levelCount - 2; // we drew the 2nd to last level into the last level.
-    glTex->setCachedParams(nullptr, params, this->getResetTimestamp());
+    GrGLTextureParameters::NonsamplerState nonsamplerState = glTex->parameters()->nonsamplerState();
+    // We drew the 2nd to last level into the last level.
+    nonsamplerState.fBaseMipMapLevel = levelCount - 2;
+    glTex->parameters()->set(nullptr, nonsamplerState, fResetTimestampForTextureParameters);
 
     return true;
 }
@@ -4146,17 +4152,20 @@
     desc.fConfig = config;
 
     GrGLTextureInfo info;
-    GrGLTexture::SamplerParams initialTexParams;
+    GrGLTextureParameters::SamplerOverriddenState initialState;
 
-    if (!this->createTextureImpl(desc, &info, renderable, &initialTexParams,
-                                 texels.get(), mipLevelCount, nullptr)) {
+    if (!this->createTextureImpl(desc, &info, renderable, &initialState, texels.get(),
+                                 mipLevelCount, nullptr)) {
         return GrBackendTexture();  // invalid
     }
 
     // unbind the texture from the texture unit to avoid asserts
     GL_CALL(BindTexture(info.fTarget, 0));
 
-    GrBackendTexture beTex = GrBackendTexture(w, h, mipMapped, info);
+    auto parameters = sk_make_sp<GrGLTextureParameters>();
+    parameters->set(&initialState, GrGLTextureParameters::NonsamplerState(),
+                    fResetTimestampForTextureParameters);
+    GrBackendTexture beTex = GrBackendTexture(w, h, mipMapped, info, std::move(parameters));
 #if GR_TEST_UTILS
     // Lots of tests don't go through Skia's public interface, which will set the config, so for
     // testing we make sure we set a config here.
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index 869a3f2..5a6c6d8 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -216,8 +216,9 @@
     // The texture is populated with |texels|, if it exists.
     // The texture parameters are cached in |initialTexParams|.
     bool createTextureImpl(const GrSurfaceDesc& desc, GrGLTextureInfo* info, GrRenderable,
-                           GrGLTexture::SamplerParams* initialTexParams, const GrMipLevel texels[],
-                           int mipLevelCount, GrMipMapsStatus* mipMapsStatus);
+                           GrGLTextureParameters::SamplerOverriddenState* initialState,
+                           const GrMipLevel texels[], int mipLevelCount,
+                           GrMipMapsStatus* mipMapsStatus);
 
     // Checks whether glReadPixels can be called to get pixel values in readConfig from the
     // render target.
@@ -665,6 +666,8 @@
 
     GrPrimitiveType fLastPrimitiveType;
 
+    GrGLTextureParameters::ResetTimestamp fResetTimestampForTextureParameters = 0;
+
     class SamplerObjectCache;
     std::unique_ptr<SamplerObjectCache> fSamplerObjectCache;
 
diff --git a/src/gpu/gl/GrGLTexture.cpp b/src/gpu/gl/GrGLTexture.cpp
index 942f125..899ff8c 100644
--- a/src/gpu/gl/GrGLTexture.cpp
+++ b/src/gpu/gl/GrGLTexture.cpp
@@ -45,7 +45,8 @@
 GrGLTexture::GrGLTexture(GrGLGpu* gpu, SkBudgeted budgeted, const GrSurfaceDesc& desc,
                          const IDDesc& idDesc, GrMipMapsStatus mipMapsStatus)
         : GrSurface(gpu, desc)
-        , INHERITED(gpu, desc, TextureTypeFromTarget(idDesc.fInfo.fTarget), mipMapsStatus) {
+        , INHERITED(gpu, desc, TextureTypeFromTarget(idDesc.fInfo.fTarget), mipMapsStatus)
+        , fParameters(sk_make_sp<GrGLTextureParameters>()) {
     this->init(desc, idDesc);
     this->registerWithCache(budgeted);
     if (GrPixelConfigIsCompressed(desc.fConfig)) {
@@ -54,9 +55,12 @@
 }
 
 GrGLTexture::GrGLTexture(GrGLGpu* gpu, const GrSurfaceDesc& desc, GrMipMapsStatus mipMapsStatus,
-                         const IDDesc& idDesc, GrWrapCacheable cacheable, GrIOType ioType)
+                         const IDDesc& idDesc, sk_sp<GrGLTextureParameters> parameters,
+                         GrWrapCacheable cacheable, GrIOType ioType)
         : GrSurface(gpu, desc)
-        , INHERITED(gpu, desc, TextureTypeFromTarget(idDesc.fInfo.fTarget), mipMapsStatus) {
+        , INHERITED(gpu, desc, TextureTypeFromTarget(idDesc.fInfo.fTarget), mipMapsStatus)
+        , fParameters(std::move(parameters)) {
+    SkASSERT(fParameters);
     this->init(desc, idDesc);
     this->registerWithCacheWrapped(cacheable);
     if (ioType == kRead_GrIOType) {
@@ -65,16 +69,17 @@
 }
 
 GrGLTexture::GrGLTexture(GrGLGpu* gpu, const GrSurfaceDesc& desc, const IDDesc& idDesc,
-                         GrMipMapsStatus mipMapsStatus)
+                         sk_sp<GrGLTextureParameters> parameters, GrMipMapsStatus mipMapsStatus)
         : GrSurface(gpu, desc)
         , INHERITED(gpu, desc, TextureTypeFromTarget(idDesc.fInfo.fTarget), mipMapsStatus) {
+    SkASSERT(parameters || idDesc.fOwnership == GrBackendObjectOwnership::kOwned);
+    fParameters = parameters ? std::move(parameters) : sk_make_sp<GrGLTextureParameters>();
     this->init(desc, idDesc);
 }
 
 void GrGLTexture::init(const GrSurfaceDesc& desc, const IDDesc& idDesc) {
     SkASSERT(0 != idDesc.fInfo.fID);
     SkASSERT(0 != idDesc.fInfo.fFormat);
-    fParamsTimestamp = GrGpu::kExpiredTimestamp;
     fID = idDesc.fInfo.fID;
     fFormat = idDesc.fInfo.fFormat;
     fTextureIDOwnership = idDesc.fOwnership;
@@ -104,7 +109,8 @@
     info.fTarget = target_from_texture_type(this->texturePriv().textureType());
     info.fID = fID;
     info.fFormat = fFormat;
-    return GrBackendTexture(this->width(), this->height(), this->texturePriv().mipMapped(), info);
+    return GrBackendTexture(this->width(), this->height(), this->texturePriv().mipMapped(), info,
+                            fParameters);
 }
 
 GrBackendFormat GrGLTexture::backendFormat() const {
@@ -114,8 +120,10 @@
 
 sk_sp<GrGLTexture> GrGLTexture::MakeWrapped(GrGLGpu* gpu, const GrSurfaceDesc& desc,
                                             GrMipMapsStatus mipMapsStatus, const IDDesc& idDesc,
+                                            sk_sp<GrGLTextureParameters> parameters,
                                             GrWrapCacheable cacheable, GrIOType ioType) {
-    return sk_sp<GrGLTexture>(new GrGLTexture(gpu, desc, mipMapsStatus, idDesc, cacheable, ioType));
+    return sk_sp<GrGLTexture>(new GrGLTexture(gpu, desc, mipMapsStatus, idDesc,
+                                              std::move(parameters), cacheable, ioType));
 }
 
 bool GrGLTexture::onStealBackendTexture(GrBackendTexture* backendTexture,
diff --git a/src/gpu/gl/GrGLTexture.h b/src/gpu/gl/GrGLTexture.h
index 54d419c..cb3f158 100644
--- a/src/gpu/gl/GrGLTexture.h
+++ b/src/gpu/gl/GrGLTexture.h
@@ -10,6 +10,7 @@
 #define GrGLTexture_DEFINED
 
 #include "include/gpu/GrTexture.h"
+#include "include/private/GrGLTypesPriv.h"
 #include "src/gpu/GrGpu.h"
 #include "src/gpu/gl/GrGLUtil.h"
 
@@ -17,44 +18,6 @@
 
 class GrGLTexture : public GrTexture {
 public:
-    // Texture state that overlaps with sampler object state. We don't need to track this if we
-    // are using sampler objects.
-    struct SamplerParams {
-        // These are the OpenGL defaults.
-        GrGLenum fMinFilter = GR_GL_NEAREST_MIPMAP_LINEAR;
-        GrGLenum fMagFilter = GR_GL_LINEAR;
-        GrGLenum fWrapS = GR_GL_REPEAT;
-        GrGLenum fWrapT = GR_GL_REPEAT;
-        GrGLfloat fMinLOD = -1000.f;
-        GrGLfloat fMaxLOD = 1000.f;
-        // We always want the border color to be transparent black, so no need to store 4 floats.
-        // Just track if it's been invalidated and no longer the default
-        bool fBorderColorInvalid = false;
-
-        void invalidate() {
-            fMinFilter = ~0U;
-            fMagFilter = ~0U;
-            fWrapS = ~0U;
-            fWrapT = ~0U;
-            fMinLOD = SK_ScalarNaN;
-            fMaxLOD = SK_ScalarNaN;
-            fBorderColorInvalid = true;
-        }
-    };
-
-    // Texture state that does not overlap with sampler object state.
-    struct NonSamplerParams {
-        // These are the OpenGL defaults.
-        uint32_t fSwizzleKey = GrSwizzle::RGBA().asKey();
-        GrGLint fBaseMipMapLevel = 0;
-        GrGLint fMaxMipMapLevel = 1000;
-        void invalidate() {
-            fSwizzleKey = ~0U;
-            fBaseMipMapLevel = ~0;
-            fMaxMipMapLevel = ~0;
-        }
-    };
-
     struct IDDesc {
         GrGLTextureInfo             fInfo;
         GrBackendObjectOwnership    fOwnership;
@@ -70,25 +33,10 @@
 
     GrBackendFormat backendFormat() const override;
 
-    void textureParamsModified() override {
-        fSamplerParams.invalidate();
-        fNonSamplerParams.invalidate();
-    }
+    // TODO: Remove once clients are no longer calling this.
+    void textureParamsModified() override { fParameters->invalidate(); }
 
-    // These functions are used to track the texture parameters associated with the texture.
-    GrGpu::ResetTimestamp getCachedParamsTimestamp() const { return fParamsTimestamp; }
-    const SamplerParams& getCachedSamplerParams() const { return fSamplerParams; }
-    const NonSamplerParams& getCachedNonSamplerParams() const { return fNonSamplerParams; }
-
-    void setCachedParams(const SamplerParams* samplerParams,
-                         const NonSamplerParams& nonSamplerParams,
-                         GrGpu::ResetTimestamp currTimestamp) {
-        if (samplerParams) {
-            fSamplerParams = *samplerParams;
-        }
-        fNonSamplerParams = nonSamplerParams;
-        fParamsTimestamp = currTimestamp;
-    }
+    GrGLTextureParameters* parameters() { return fParameters.get(); }
 
     GrGLuint textureID() const { return fID; }
 
@@ -98,17 +46,19 @@
     void baseLevelWasBoundToFBO() { fBaseLevelHasBeenBoundToFBO = true; }
 
     static sk_sp<GrGLTexture> MakeWrapped(GrGLGpu*, const GrSurfaceDesc&, GrMipMapsStatus,
-                                          const IDDesc&, GrWrapCacheable, GrIOType);
+                                          const IDDesc&, sk_sp<GrGLTextureParameters>,
+                                          GrWrapCacheable, GrIOType);
 
     void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const override;
 
 protected:
     // Constructor for subclasses.
-    GrGLTexture(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&, GrMipMapsStatus);
+    GrGLTexture(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&, sk_sp<GrGLTextureParameters>,
+                GrMipMapsStatus);
 
     // Constructor for instances wrapping backend objects.
-    GrGLTexture(GrGLGpu*, const GrSurfaceDesc&, GrMipMapsStatus, const IDDesc&, GrWrapCacheable,
-                GrIOType);
+    GrGLTexture(GrGLGpu*, const GrSurfaceDesc&, GrMipMapsStatus, const IDDesc&,
+                sk_sp<GrGLTextureParameters>, GrWrapCacheable, GrIOType);
 
     void init(const GrSurfaceDesc&, const IDDesc&);
 
@@ -118,9 +68,7 @@
     bool onStealBackendTexture(GrBackendTexture*, SkImage::BackendTextureReleaseProc*) override;
 
 private:
-    SamplerParams fSamplerParams;
-    NonSamplerParams fNonSamplerParams;
-    GrGpu::ResetTimestamp fParamsTimestamp;
+    sk_sp<GrGLTextureParameters> fParameters;
     GrGLuint fID;
     GrGLenum fFormat;
     GrBackendObjectOwnership fTextureIDOwnership;
diff --git a/src/gpu/gl/GrGLTextureRenderTarget.cpp b/src/gpu/gl/GrGLTextureRenderTarget.cpp
index ab86162..6739b79 100644
--- a/src/gpu/gl/GrGLTextureRenderTarget.cpp
+++ b/src/gpu/gl/GrGLTextureRenderTarget.cpp
@@ -19,7 +19,7 @@
                                                  const GrGLRenderTarget::IDDesc& rtIDDesc,
                                                  GrMipMapsStatus mipMapsStatus)
         : GrSurface(gpu, desc)
-        , GrGLTexture(gpu, desc, texIDDesc, mipMapsStatus)
+        , GrGLTexture(gpu, desc, texIDDesc, nullptr, mipMapsStatus)
         , GrGLRenderTarget(gpu, desc, texIDDesc.fInfo.fFormat, rtIDDesc) {
     this->registerWithCache(budgeted);
 }
@@ -27,11 +27,12 @@
 GrGLTextureRenderTarget::GrGLTextureRenderTarget(GrGLGpu* gpu,
                                                  const GrSurfaceDesc& desc,
                                                  const GrGLTexture::IDDesc& texIDDesc,
+                                                 sk_sp<GrGLTextureParameters> parameters,
                                                  const GrGLRenderTarget::IDDesc& rtIDDesc,
                                                  GrWrapCacheable cacheable,
                                                  GrMipMapsStatus mipMapsStatus)
         : GrSurface(gpu, desc)
-        , GrGLTexture(gpu, desc, texIDDesc, mipMapsStatus)
+        , GrGLTexture(gpu, desc, texIDDesc, std::move(parameters), mipMapsStatus)
         , GrGLRenderTarget(gpu, desc, texIDDesc.fInfo.fFormat, rtIDDesc) {
     this->registerWithCacheWrapped(cacheable);
 }
@@ -58,14 +59,13 @@
 
 sk_sp<GrGLTextureRenderTarget> GrGLTextureRenderTarget::MakeWrapped(
         GrGLGpu* gpu, const GrSurfaceDesc& desc, const GrGLTexture::IDDesc& texIDDesc,
-        const GrGLRenderTarget::IDDesc& rtIDDesc, GrWrapCacheable cacheable,
-        GrMipMapsStatus mipMapsStatus) {
-    return sk_sp<GrGLTextureRenderTarget>(
-            new GrGLTextureRenderTarget(gpu, desc, texIDDesc, rtIDDesc, cacheable, mipMapsStatus));
+        sk_sp<GrGLTextureParameters> parameters, const GrGLRenderTarget::IDDesc& rtIDDesc,
+        GrWrapCacheable cacheable, GrMipMapsStatus mipMapsStatus) {
+    return sk_sp<GrGLTextureRenderTarget>(new GrGLTextureRenderTarget(
+            gpu, desc, texIDDesc, std::move(parameters), rtIDDesc, cacheable, mipMapsStatus));
 }
 
 size_t GrGLTextureRenderTarget::onGpuMemorySize() const {
     return GrSurface::ComputeSize(this->config(), this->width(), this->height(),
-                                    this->numSamplesOwnedPerPixel(),
-                                    this->texturePriv().mipMapped());
+                                  this->numSamplesOwnedPerPixel(), this->texturePriv().mipMapped());
 }
diff --git a/src/gpu/gl/GrGLTextureRenderTarget.h b/src/gpu/gl/GrGLTextureRenderTarget.h
index 75cdf01..c386822 100644
--- a/src/gpu/gl/GrGLTextureRenderTarget.h
+++ b/src/gpu/gl/GrGLTextureRenderTarget.h
@@ -37,6 +37,7 @@
 
     static sk_sp<GrGLTextureRenderTarget> MakeWrapped(GrGLGpu* gpu, const GrSurfaceDesc& desc,
                                                       const GrGLTexture::IDDesc& texIDDesc,
+                                                      sk_sp<GrGLTextureParameters> parameters,
                                                       const GrGLRenderTarget::IDDesc& rtIDDesc,
                                                       GrWrapCacheable cacheble, GrMipMapsStatus);
 
@@ -61,6 +62,7 @@
     GrGLTextureRenderTarget(GrGLGpu* gpu,
                             const GrSurfaceDesc& desc,
                             const GrGLTexture::IDDesc& texIDDesc,
+                            sk_sp<GrGLTextureParameters> parameters,
                             const GrGLRenderTarget::IDDesc& rtIDDesc,
                             GrWrapCacheable,
                             GrMipMapsStatus);
diff --git a/src/gpu/gl/GrGLTypesPriv.cpp b/src/gpu/gl/GrGLTypesPriv.cpp
new file mode 100644
index 0000000..debb408
--- /dev/null
+++ b/src/gpu/gl/GrGLTypesPriv.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2019 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/private/GrGLTypesPriv.h"
+#include "include/core/SkScalar.h"
+#include "src/gpu/GrSwizzle.h"
+#include "src/gpu/gl/GrGLDefines.h"
+
+GrGLTextureParameters::SamplerOverriddenState::SamplerOverriddenState()
+        // These are the OpenGL defaults.
+        : fMinFilter(GR_GL_NEAREST_MIPMAP_LINEAR)
+        , fMagFilter(GR_GL_LINEAR)
+        , fWrapS(GR_GL_REPEAT)
+        , fWrapT(GR_GL_REPEAT)
+        , fMinLOD(-1000.f)
+        , fMaxLOD(1000.f)
+        , fBorderColorInvalid(false) {}
+
+void GrGLTextureParameters::SamplerOverriddenState::invalidate() {
+    fMinFilter = ~0U;
+    fMagFilter = ~0U;
+    fWrapS = ~0U;
+    fWrapT = ~0U;
+    fMinLOD = SK_ScalarNaN;
+    fMaxLOD = SK_ScalarNaN;
+    fBorderColorInvalid = true;
+}
+
+GrGLTextureParameters::NonsamplerState::NonsamplerState()
+        // These are the OpenGL defaults.
+        : fSwizzleKey(GrSwizzle::RGBA().asKey()), fBaseMipMapLevel(0), fMaxMipMapLevel(1000) {}
+
+void GrGLTextureParameters::NonsamplerState::invalidate() {
+    fSwizzleKey = ~0U;
+    fBaseMipMapLevel = ~0;
+    fMaxMipMapLevel = ~0;
+}
+
+void GrGLTextureParameters::invalidate() {
+    fSamplerOverriddenState.invalidate();
+    fNonsamplerState.invalidate();
+}
+
+void GrGLTextureParameters::set(const SamplerOverriddenState* samplerState,
+                                const NonsamplerState& nonsamplerState,
+                                ResetTimestamp currTimestamp) {
+    if (samplerState) {
+        fSamplerOverriddenState = *samplerState;
+    }
+    fNonsamplerState = nonsamplerState;
+    fResetTimestamp = currTimestamp;
+}
+
+void GrGLBackendTextureInfo::assign(const GrGLBackendTextureInfo& that, bool thisIsValid) {
+    fInfo = that.fInfo;
+    SkSafeRef(that.fParams);
+    if (thisIsValid) {
+        SkSafeUnref(fParams);
+    }
+    fParams = that.fParams;
+}
+
+void GrGLBackendTextureInfo::cleanup() { SkSafeUnref(fParams); }