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/GrBackendSurface.cpp b/src/gpu/GrBackendSurface.cpp
index dc58250..7420ab3 100644
--- a/src/gpu/GrBackendSurface.cpp
+++ b/src/gpu/GrBackendSurface.cpp
@@ -187,6 +187,28 @@
: fIsValid(false) {}
#endif
+#ifdef SK_GL
+GrBackendTexture::GrBackendTexture(int width,
+ int height,
+ GrMipMapped mipMapped,
+ const GrGLTextureInfo glInfo,
+ sk_sp<GrGLTextureParameters> params)
+ : fIsValid(true)
+ , fWidth(width)
+ , fHeight(height)
+ , fConfig(kUnknown_GrPixelConfig)
+ , fMipMapped(mipMapped)
+ , fBackend(GrBackendApi::kOpenGL)
+ , fGLInfo(glInfo, params.release()) {}
+
+sk_sp<GrGLTextureParameters> GrBackendTexture::getGLTextureParams() const {
+ if (fBackend != GrBackendApi::kOpenGL) {
+ return nullptr;
+ }
+ return fGLInfo.refParameters();
+}
+#endif
+
#ifdef SK_VULKAN
GrBackendTexture::GrBackendTexture(int width,
int height,
@@ -220,13 +242,10 @@
int height,
GrMipMapped mipMapped,
const GrGLTextureInfo& glInfo)
- : fIsValid(true)
- , fWidth(width)
- , fHeight(height)
- , fConfig(kUnknown_GrPixelConfig)
- , fMipMapped(mipMapped)
- , fBackend(GrBackendApi::kOpenGL)
- , fGLInfo(glInfo) {}
+ : GrBackendTexture(width, height, mipMapped, glInfo, sk_make_sp<GrGLTextureParameters>()) {
+ // Make no assumptions about client's texture's parameters.
+ this->glTextureParametersModified();
+}
GrBackendTexture::GrBackendTexture(int width,
int height,
@@ -245,6 +264,11 @@
}
void GrBackendTexture::cleanup() {
+#ifdef SK_GL
+ if (this->isValid() && GrBackendApi::kOpenGL == fBackend) {
+ fGLInfo.cleanup();
+ }
+#endif
#ifdef SK_VULKAN
if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
fVkInfo.cleanup();
@@ -261,6 +285,9 @@
this->cleanup();
fIsValid = false;
return *this;
+ } else if (this->fBackend != that.fBackend) {
+ this->cleanup();
+ fIsValid = false;
}
fWidth = that.fWidth;
fHeight = that.fHeight;
@@ -269,14 +296,16 @@
fBackend = that.fBackend;
switch (that.fBackend) {
+#ifdef SK_GL
case GrBackendApi::kOpenGL:
- fGLInfo = that.fGLInfo;
+ fGLInfo.assign(that.fGLInfo, this->isValid());
break;
- case GrBackendApi::kVulkan:
-#ifdef SK_VULKAN
- fVkInfo.assign(that.fVkInfo, this->isValid());
#endif
+#ifdef SK_VULKAN
+ case GrBackendApi::kVulkan:
+ fVkInfo.assign(that.fVkInfo, this->isValid());
break;
+#endif
#ifdef SK_METAL
case GrBackendApi::kMetal:
fMtlInfo = that.fMtlInfo;
@@ -288,7 +317,7 @@
default:
SK_ABORT("Unknown GrBackend");
}
- fIsValid = that.fIsValid;
+ fIsValid = true;
return *this;
}
@@ -310,21 +339,14 @@
#endif
}
-// We need a stubbed version of GrVkImageLayout for non vulkan builds
-#ifndef SK_VULKAN
-class GrVkImageLayout : public SkRefCnt {
- GrVkImageLayout(VkImageLayout layout) {}
-};
-#endif
-
-sk_sp<GrVkImageLayout> GrBackendTexture::getGrVkImageLayout() const {
#ifdef SK_VULKAN
+sk_sp<GrVkImageLayout> GrBackendTexture::getGrVkImageLayout() const {
if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
return fVkInfo.getGrVkImageLayout();
}
-#endif
return nullptr;
}
+#endif
#ifdef SK_METAL
bool GrBackendTexture::getMtlTextureInfo(GrMtlTextureInfo* outInfo) const {
@@ -337,8 +359,9 @@
#endif
bool GrBackendTexture::getGLTextureInfo(GrGLTextureInfo* outInfo) const {
+#ifdef SK_GL
if (this->isValid() && GrBackendApi::kOpenGL == fBackend) {
- *outInfo = fGLInfo;
+ *outInfo = fGLInfo.info();
return true;
} else if (this->isValid() && GrBackendApi::kMock == fBackend) {
// Hack! This allows some blink unit tests to work when using the Mock GrContext.
@@ -349,9 +372,18 @@
GR_GL_RGBA8 };
return true;
}
+#endif
return false;
}
+void GrBackendTexture::glTextureParametersModified() {
+#ifdef SK_GL
+ if (this->isValid() && fBackend == GrBackendApi::kOpenGL) {
+ fGLInfo.parameters()->invalidate();
+ }
+#endif
+}
+
bool GrBackendTexture::getMockTextureInfo(GrMockTextureInfo* outInfo) const {
if (this->isValid() && GrBackendApi::kMock == fBackend) {
*outInfo = fMockInfo;
@@ -368,8 +400,10 @@
return false;
}
switch (fBackend) {
+#ifdef SK_GL
case GrBackendApi::kOpenGL:
- return fGLInfo.fID == that.fGLInfo.fID;
+ return fGLInfo.info().fID == that.fGLInfo.info().fID;
+#endif
#ifdef SK_VULKAN
case GrBackendApi::kVulkan:
return fVkInfo.snapImageInfo().fImage == that.fVkInfo.snapImageInfo().fImage;
@@ -390,8 +424,10 @@
return GrBackendFormat();
}
switch (fBackend) {
+#ifdef SK_GL
case GrBackendApi::kOpenGL:
- return GrBackendFormat::MakeGL(fGLInfo.fFormat, fGLInfo.fTarget);
+ return GrBackendFormat::MakeGL(fGLInfo.info().fFormat, fGLInfo.info().fTarget);
+#endif
#ifdef SK_VULKAN
case GrBackendApi::kVulkan: {
auto info = fVkInfo.snapImageInfo();
@@ -431,28 +467,23 @@
}
switch (t0.fBackend) {
- case GrBackendApi::kOpenGL:
- return t0.fGLInfo == t1.fGLInfo;
- case GrBackendApi::kMock:
- return t0.fMockInfo == t1.fMockInfo;
- case GrBackendApi::kVulkan:
+#ifdef SK_GL
+ case GrBackendApi::kOpenGL:
+ return t0.fGLInfo.info() == t1.fGLInfo.info();
+#endif
+ case GrBackendApi::kMock:
+ return t0.fMockInfo == t1.fMockInfo;
#ifdef SK_VULKAN
- return t0.fVkInfo == t1.fVkInfo;
-#else
- // fall through
+ case GrBackendApi::kVulkan:
+ return t0.fVkInfo == t1.fVkInfo;
#endif
- case GrBackendApi::kMetal:
#ifdef SK_METAL
- return t0.fMtlInfo == t1.fMtlInfo;
-#else
- // fall through
+ case GrBackendApi::kMetal:
+ return t0.fMtlInfo == t1.fMtlInfo;
#endif
- default:
- return false;
+ default:
+ return false;
}
-
- SkASSERT(0);
- return false;
}
#endif
@@ -559,6 +590,9 @@
this->cleanup();
fIsValid = false;
return *this;
+ } else if (this->fBackend != that.fBackend) {
+ this->cleanup();
+ fIsValid = false;
}
fWidth = that.fWidth;
fHeight = that.fHeight;
@@ -609,14 +643,14 @@
#endif
}
-sk_sp<GrVkImageLayout> GrBackendRenderTarget::getGrVkImageLayout() const {
#ifdef SK_VULKAN
+sk_sp<GrVkImageLayout> GrBackendRenderTarget::getGrVkImageLayout() const {
if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
return fVkInfo.getGrVkImageLayout();
}
-#endif
return nullptr;
}
+#endif
#ifdef SK_METAL
bool GrBackendRenderTarget::getMtlTextureInfo(GrMtlTextureInfo* outInfo) const {
@@ -661,24 +695,22 @@
}
switch (r0.fBackend) {
- case GrBackendApi::kOpenGL:
- return r0.fGLInfo == r1.fGLInfo;
- case GrBackendApi::kMock:
- return r0.fMockInfo == r1.fMockInfo;
- case GrBackendApi::kVulkan:
+#ifdef SK_GL
+ case GrBackendApi::kOpenGL:
+ return r0.fGLInfo == r1.fGLInfo;
+#endif
+ case GrBackendApi::kMock:
+ return r0.fMockInfo == r1.fMockInfo;
#ifdef SK_VULKAN
- return r0.fVkInfo == r1.fVkInfo;
-#else
- // fall through
+ case GrBackendApi::kVulkan:
+ return r0.fVkInfo == r1.fVkInfo;
#endif
- case GrBackendApi::kMetal:
#ifdef SK_METAL
- return r0.fMtlInfo == r1.fMtlInfo;
-#else
- // fall through
+ case GrBackendApi::kMetal:
+ return r0.fMtlInfo == r1.fMtlInfo;
#endif
- default:
- return false;
+ default:
+ return false;
}
SkASSERT(0);
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index 23d8218..ce151b1 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -32,11 +32,7 @@
////////////////////////////////////////////////////////////////////////////////
-GrGpu::GrGpu(GrContext* context)
- : fResetTimestamp(kExpiredTimestamp+1)
- , fResetBits(kAll_GrBackendState)
- , fContext(context) {
-}
+GrGpu::GrGpu(GrContext* context) : fResetBits(kAll_GrBackendState), fContext(context) {}
GrGpu::~GrGpu() {}
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index 630644a..467e1db 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -249,20 +249,6 @@
GrColorType bufferColorType, GrGpuBuffer* transferBuffer,
size_t offset);
- // After the client interacts directly with the 3D context state the GrGpu
- // must resync its internal state and assumptions about 3D context state.
- // Each time this occurs the GrGpu bumps a timestamp.
- // state of the 3D context
- // At 10 resets / frame and 60fps a 64bit timestamp will overflow in about
- // a billion years.
- typedef uint64_t ResetTimestamp;
-
- // This timestamp is always older than the current timestamp
- static const ResetTimestamp kExpiredTimestamp = 0;
- // Returns a timestamp based on the number of times the context was reset.
- // This timestamp can be used to lazily detect when cached 3D context state
- // is dirty.
- ResetTimestamp getResetTimestamp() const { return fResetTimestamp; }
// Called to perform a surface to surface copy. Fallbacks to issuing a draw from the src to dst
// take place at the GrOpList level and this function implement faster copy paths. The rect
@@ -566,10 +552,8 @@
void resetContext() {
this->onResetContext(fResetBits);
fResetBits = 0;
- ++fResetTimestamp;
}
- ResetTimestamp fResetTimestamp;
uint32_t fResetBits;
// The context owns us, not vice-versa, so this ptr is not ref'ed by Gpu.
GrContext* fContext;
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); }