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>
This commit is contained in:
Brian Salomon 2019-06-04 15:58:31 -04:00 committed by Skia Commit-Bot
parent 9893f8e151
commit e2826ab59c
16 changed files with 530 additions and 233 deletions

View File

@ -35,6 +35,7 @@ skia_gpu_sources = [
"$_include/private/GrAuditTrail.h",
"$_include/private/GrColor.h",
"$_include/private/GrContext_Base.h",
"$_include/private/GrGLTypesPriv.h",
"$_include/private/GrImageContext.h",
"$_include/private/GrOpList.h",
"$_include/private/GrProxyRef.h",
@ -471,6 +472,7 @@ skia_gpu_sources = [
"$_src/gpu/gl/GrGLTexture.h",
"$_src/gpu/gl/GrGLTextureRenderTarget.cpp",
"$_src/gpu/gl/GrGLTextureRenderTarget.h",
"$_src/gpu/gl/GrGLTypesPriv.cpp",
"$_src/gpu/gl/GrGLUtil.cpp",
"$_src/gpu/gl/GrGLUtil.h",
"$_src/gpu/gl/GrGLUniformHandler.cpp",

View File

@ -89,6 +89,7 @@ tests_sources = [
"$_tests/GLProgramsTest.cpp",
"$_tests/GeometryTest.cpp",
"$_tests/GifTest.cpp",
"$_tests/GLBackendSurfaceTest.cpp",
"$_tests/GlyphRunTest.cpp",
"$_tests/GpuDrawPathTest.cpp",
"$_tests/GpuRectanizerTest.cpp",

View File

@ -12,9 +12,11 @@
#include "include/gpu/gl/GrGLTypes.h"
#include "include/gpu/mock/GrMockTypes.h"
#include "include/gpu/vk/GrVkTypes.h"
#include "include/private/GrGLTypesPriv.h"
#include "include/private/GrVkTypesPriv.h"
class GrVkImageLayout;
class GrGLTextureParameters;
#ifdef SK_METAL
#include "include/gpu/mtl/GrMtlTypes.h"
@ -171,6 +173,10 @@ public:
// pointer and returns true. Otherwise returns false if the backend API is not GL.
bool getGLTextureInfo(GrGLTextureInfo*) const;
// Call this to indicate that the texture parameters have been modified in the GL context
// externally to GrContext.
void glTextureParametersModified();
// If the backend API is Vulkan, copies a snapshot of the GrVkImageInfo struct into the passed
// in pointer and returns true. This snapshot will set the fImageLayout to the current layout
// state. Otherwise returns false if the backend API is not Vulkan.
@ -229,15 +235,23 @@ private:
GrPixelConfig config() const { return fConfig; }
// Requires friending of GrVkGpu (done above already)
sk_sp<GrVkImageLayout> getGrVkImageLayout() const;
#ifdef SK_GL
friend class GrGLTexture;
GrBackendTexture(int width,
int height,
GrMipMapped,
const GrGLTextureInfo,
sk_sp<GrGLTextureParameters>);
sk_sp<GrGLTextureParameters> getGLTextureParams() const;
#endif
friend class GrVkTexture;
#ifdef SK_VULKAN
GrBackendTexture(int width,
int height,
const GrVkImageInfo& vkInfo,
sk_sp<GrVkImageLayout> layout);
friend class GrVkTexture;
GrBackendTexture(int width,
int height,
const GrVkImageInfo& vkInfo,
sk_sp<GrVkImageLayout> layout);
sk_sp<GrVkImageLayout> getGrVkImageLayout() const;
#endif
// Free and release and resources being held by the GrBackendTexture.
@ -251,7 +265,9 @@ private:
GrBackendApi fBackend;
union {
GrGLTextureInfo fGLInfo;
#ifdef SK_GL
GrGLBackendTextureInfo fGLInfo;
#endif
GrVkBackendSurfaceInfo fVkInfo;
GrMockTextureInfo fMockInfo;
};

View File

@ -0,0 +1,92 @@
/*
* 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/core/SkRefCnt.h"
#include "include/gpu/gl/GrGLTypes.h"
#ifndef GrGLTypesPriv_DEFINED
#define GrGLTypesPriv_DEFINED
class GrGLTextureParameters : public SkNVRefCnt<GrGLTextureParameters> {
public:
// We currently consider texture parameters invalid on all textures
// GrContext::resetContext(). We use this type to track whether instances of
// GrGLTextureParameters were updated before or after the most recent resetContext(). At 10
// resets / frame and 60fps a 64bit timestamp will overflow in about a billion years.
// TODO: Require clients to use GrBackendTexture::glTextureParametersModified() to invalidate
// texture parameters and get rid of timestamp checking.
using ResetTimestamp = uint64_t;
// This initializes the params to have an expired timestamp. They'll be considered invalid the
// first time the texture is used unless set() is called.
GrGLTextureParameters() = default;
// This is texture parameter state that is overridden when a non-zero sampler object is bound.
struct SamplerOverriddenState {
SamplerOverriddenState();
void invalidate();
GrGLenum fMinFilter;
GrGLenum fMagFilter;
GrGLenum fWrapS;
GrGLenum fWrapT;
GrGLfloat fMinLOD;
GrGLfloat fMaxLOD;
// 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;
};
// Texture parameter state that is not overridden by a bound sampler object.
struct NonsamplerState {
NonsamplerState();
void invalidate();
uint32_t fSwizzleKey;
GrGLint fBaseMipMapLevel;
GrGLint fMaxMipMapLevel;
};
void invalidate();
ResetTimestamp resetTimestamp() const { return fResetTimestamp; }
const SamplerOverriddenState& samplerOverriddenState() const { return fSamplerOverriddenState; }
const NonsamplerState& nonsamplerState() const { return fNonsamplerState; }
// SamplerOverriddenState is optional because we don't track it when we're using sampler
// objects.
void set(const SamplerOverriddenState* samplerState,
const NonsamplerState& nonsamplerState,
ResetTimestamp currTimestamp);
private:
static constexpr ResetTimestamp kExpiredTimestamp = 0;
SamplerOverriddenState fSamplerOverriddenState;
NonsamplerState fNonsamplerState;
ResetTimestamp fResetTimestamp = kExpiredTimestamp;
};
class GrGLBackendTextureInfo {
public:
GrGLBackendTextureInfo(const GrGLTextureInfo& info, GrGLTextureParameters* params)
: fInfo(info), fParams(params) {}
GrGLBackendTextureInfo(const GrGLBackendTextureInfo&) = delete;
GrGLBackendTextureInfo& operator=(const GrGLBackendTextureInfo&) = delete;
const GrGLTextureInfo& info() const { return fInfo; }
GrGLTextureParameters* parameters() const { return fParams; }
sk_sp<GrGLTextureParameters> refParameters() const { return sk_ref_sp(fParams); }
void cleanup();
void assign(const GrGLBackendTextureInfo&, bool thisIsValid);
private:
GrGLTextureInfo fInfo;
GrGLTextureParameters* fParams;
};
#endif

View File

@ -187,6 +187,28 @@ GrBackendTexture::GrBackendTexture(int width,
: 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 @@ GrBackendTexture::GrBackendTexture(int width,
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 @@ GrBackendTexture::~GrBackendTexture() {
}
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 @@ GrBackendTexture& GrBackendTexture::operator=(const GrBackendTexture& that) {
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 @@ GrBackendTexture& GrBackendTexture::operator=(const GrBackendTexture& that) {
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 @@ GrBackendTexture& GrBackendTexture::operator=(const GrBackendTexture& that) {
default:
SK_ABORT("Unknown GrBackend");
}
fIsValid = that.fIsValid;
fIsValid = true;
return *this;
}
@ -310,21 +339,14 @@ void GrBackendTexture::setVkImageLayout(VkImageLayout layout) {
#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 @@ bool GrBackendTexture::getMtlTextureInfo(GrMtlTextureInfo* outInfo) const {
#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 @@ bool GrBackendTexture::getGLTextureInfo(GrGLTextureInfo* outInfo) const {
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 @@ bool GrBackendTexture::isSameTexture(const GrBackendTexture& that) {
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 @@ GrBackendFormat GrBackendTexture::getBackendFormat() const {
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 @@ bool GrBackendTexture::TestingOnly_Equals(const GrBackendTexture& t0, const GrBa
}
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 @@ GrBackendRenderTarget& GrBackendRenderTarget::operator=(const GrBackendRenderTar
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 @@ void GrBackendRenderTarget::setVkImageLayout(VkImageLayout layout) {
#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 @@ bool GrBackendRenderTarget::TestingOnly_Equals(const GrBackendRenderTarget& r0,
}
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);

View File

@ -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() {}

View File

@ -249,20 +249,6 @@ public:
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 @@ private:
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;

View File

@ -655,6 +655,7 @@ void GrGLGpu::onResetContext(uint32_t resetBits) {
fHWProgramID = 0;
fHWProgram.reset();
}
++fResetTimestampForTextureParameters;
}
static bool check_backend_texture(const GrBackendTexture& backendTex, const GrGLCaps& caps,
@ -706,8 +707,8 @@ sk_sp<GrTexture> GrGLGpu::onWrapBackendTexture(const GrBackendTexture& backendTe
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 @@ sk_sp<GrTexture> GrGLGpu::onWrapRenderableBackendTexture(const GrBackendTexture&
: 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 @@ static sk_sp<GrTexture> return_null_texture() {
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 @@ sk_sp<GrTexture> GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc,
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 @@ sk_sp<GrTexture> GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc,
} 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 @@ int GrGLGpu::getCompatibleStencilIndex(GrPixelConfig config) {
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 @@ bool GrGLGpu::createTextureImpl(const GrSurfaceDesc& desc, GrGLTextureInfo* info
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 @@ void GrGLGpu::bindTexture(int unitIdx, GrSamplerState samplerState, GrGLTexture*
}
#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 @@ void GrGLGpu::bindTexture(int unitIdx, GrSamplerState samplerState, GrGLTexture*
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 @@ bool GrGLGpu::onRegenerateMipMapLevels(GrTexture* texture) {
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 @@ GrBackendTexture GrGLGpu::createBackendTexture(int w, int h,
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.

View File

@ -216,8 +216,9 @@ private:
// 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 @@ private:
GrPrimitiveType fLastPrimitiveType;
GrGLTextureParameters::ResetTimestamp fResetTimestampForTextureParameters = 0;
class SamplerObjectCache;
std::unique_ptr<SamplerObjectCache> fSamplerObjectCache;

View File

@ -45,7 +45,8 @@ static inline GrGLenum target_from_texture_type(GrTextureType type) {
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, SkBudgeted budgeted, const GrSurfaceDesc&
}
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, GrMipMapsStatu
}
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 @@ GrBackendTexture GrGLTexture::getBackendTexture() const {
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 @@ GrBackendFormat GrGLTexture::backendFormat() const {
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,

View File

@ -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 GrGLGpu;
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 @@ public:
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 @@ public:
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 @@ protected:
bool onStealBackendTexture(GrBackendTexture*, SkImage::BackendTextureReleaseProc*) override;
private:
SamplerParams fSamplerParams;
NonSamplerParams fNonSamplerParams;
GrGpu::ResetTimestamp fParamsTimestamp;
sk_sp<GrGLTextureParameters> fParameters;
GrGLuint fID;
GrGLenum fFormat;
GrBackendObjectOwnership fTextureIDOwnership;

View File

@ -19,7 +19,7 @@ GrGLTextureRenderTarget::GrGLTextureRenderTarget(GrGLGpu* gpu,
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,
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 @@ bool GrGLTextureRenderTarget::canAttemptStencilAttachment() const {
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());
}

View File

@ -37,6 +37,7 @@ public:
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 @@ private:
GrGLTextureRenderTarget(GrGLGpu* gpu,
const GrSurfaceDesc& desc,
const GrGLTexture::IDDesc& texIDDesc,
sk_sp<GrGLTextureParameters> parameters,
const GrGLRenderTarget::IDDesc& rtIDDesc,
GrWrapCacheable,
GrMipMapsStatus);

View File

@ -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); }

View File

@ -0,0 +1,134 @@
/*
* 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/core/SkTypes.h"
#ifdef SK_GL
#include "tests/Test.h"
#include "include/core/SkImage.h"
#include "include/core/SkSurface.h"
#include "include/gpu/GrBackendSurface.h"
#include "include/gpu/GrTexture.h"
#include "include/gpu/gl/GrGLTypes.h"
#include "include/private/GrGLTypesPriv.h"
#include "include/private/GrTextureProxy.h"
#include "src/gpu/GrContextPriv.h"
#include "src/gpu/gl/GrGLCaps.h"
#include "src/gpu/gl/GrGLTexture.h"
#include "src/image/SkImage_Base.h"
static bool sampler_params_invalid(const GrGLTextureParameters& parameters) {
return SkScalarIsNaN(parameters.samplerOverriddenState().fMaxLOD);
}
static bool nonsampler_params_invalid(const GrGLTextureParameters& parameters) {
GrGLTextureParameters::NonsamplerState invalidNSState;
invalidNSState.invalidate();
return 0 == memcmp(&parameters.nonsamplerState(), &invalidNSState, sizeof(invalidNSState));
}
static bool params_invalid(const GrGLTextureParameters& parameters) {
return sampler_params_invalid(parameters) && nonsampler_params_invalid(parameters);
}
static bool params_valid(const GrGLTextureParameters& parameters, const GrGLCaps* caps) {
if (nonsampler_params_invalid(parameters)) {
return false;
}
// We should only set the sampler parameters to valid if we don't have sampler object support.
return caps->samplerObjectSupport() == sampler_params_invalid(parameters);
}
DEF_GPUTEST_FOR_ALL_GL_CONTEXTS(GLTextureParameters, reporter, ctxInfo) {
GrContext* context = ctxInfo.grContext();
GrBackendTexture backendTex = context->createBackendTexture(
1, 1, kRGBA_8888_SkColorType, GrMipMapped::kNo, GrRenderable::kNo);
REPORTER_ASSERT(reporter, backendTex.isValid());
GrGLTextureInfo info;
REPORTER_ASSERT(reporter, backendTex.getGLTextureInfo(&info));
GrBackendTexture backendTexCopy = backendTex;
REPORTER_ASSERT(reporter, backendTexCopy.isSameTexture(backendTex));
sk_sp<SkImage> wrappedImage =
SkImage::MakeFromTexture(context, backendTex, kTopLeft_GrSurfaceOrigin,
kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr);
REPORTER_ASSERT(reporter, wrappedImage);
sk_sp<GrTextureProxy> texProxy = as_IB(wrappedImage)->asTextureProxyRef(context);
REPORTER_ASSERT(reporter, texProxy.get());
REPORTER_ASSERT(reporter, texProxy->isInstantiated());
auto texture = static_cast<GrGLTexture*>(texProxy->peekTexture());
REPORTER_ASSERT(reporter, texture);
auto parameters = texture->parameters();
REPORTER_ASSERT(reporter, parameters);
GrGLTextureParameters::SamplerOverriddenState invalidSState;
invalidSState.invalidate();
GrGLTextureParameters::NonsamplerState invalidNSState;
invalidNSState.invalidate();
// After wrapping we should assume the client's texture can be in any state.
REPORTER_ASSERT(reporter, params_invalid(*parameters));
auto surf = SkSurface::MakeRenderTarget(
context, SkBudgeted::kYes,
SkImageInfo::Make(1, 1, kRGBA_8888_SkColorType, kPremul_SkAlphaType), 1, nullptr);
REPORTER_ASSERT(reporter, surf);
surf->getCanvas()->drawImage(wrappedImage, 0, 0);
surf->flush();
auto caps = static_cast<const GrGLCaps*>(context->priv().caps());
// Now the texture should be in a known state.
REPORTER_ASSERT(reporter, params_valid(*parameters, caps));
// Test invalidating from the GL backend texture.
backendTex.glTextureParametersModified();
REPORTER_ASSERT(reporter, params_invalid(*parameters));
REPORTER_ASSERT(reporter, surf);
surf->getCanvas()->drawImage(wrappedImage, 0, 0);
surf->flush();
REPORTER_ASSERT(reporter, params_valid(*parameters, caps));
// Test invalidating from the copy.
backendTexCopy.glTextureParametersModified();
REPORTER_ASSERT(reporter, params_invalid(*parameters));
// Check that we can do things like assigning the backend texture to invalid one, assign an
// invalid one, assin a backend texture to inself etc. Success here is that we don't hit any of
// our ref counting asserts.
REPORTER_ASSERT(reporter, GrBackendTexture::TestingOnly_Equals(backendTex, backendTexCopy));
GrBackendTexture invalidTexture;
REPORTER_ASSERT(reporter, !invalidTexture.isValid());
REPORTER_ASSERT(reporter,
!GrBackendTexture::TestingOnly_Equals(invalidTexture, backendTexCopy));
backendTexCopy = invalidTexture;
REPORTER_ASSERT(reporter, !backendTexCopy.isValid());
REPORTER_ASSERT(reporter,
!GrBackendTexture::TestingOnly_Equals(invalidTexture, backendTexCopy));
invalidTexture = backendTex;
REPORTER_ASSERT(reporter, invalidTexture.isValid());
REPORTER_ASSERT(reporter, GrBackendTexture::TestingOnly_Equals(invalidTexture, backendTex));
invalidTexture = static_cast<decltype(invalidTexture)&>(invalidTexture);
REPORTER_ASSERT(reporter, invalidTexture.isValid());
REPORTER_ASSERT(reporter, GrBackendTexture::TestingOnly_Equals(invalidTexture, invalidTexture));
wrappedImage.reset();
GrFlushInfo flushInfo;
flushInfo.fFlags = kSyncCpu_GrFlushFlag;
context->flush(flushInfo);
context->deleteBackendTexture(backendTex);
}
#endif

View File

@ -127,8 +127,11 @@ DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SkTraceMemoryDump_unownedGLTexture, report
idDesc.fInfo = glInfo;
idDesc.fOwnership = GrBackendObjectOwnership::kBorrowed;
auto texture = GrGLTexture::MakeWrapped(gpu, desc, GrMipMapsStatus::kNotAllocated, idDesc,
GrWrapCacheable::kNo, kRead_GrIOType);
auto params = sk_make_sp<GrGLTextureParameters>();
auto texture =
GrGLTexture::MakeWrapped(gpu, desc, GrMipMapsStatus::kNotAllocated, idDesc,
std::move(params), GrWrapCacheable::kNo, kRead_GrIOType);
ValidateMemoryDumps(reporter, context, texture->gpuMemorySize(), false /* isOwned */);
}