Reland "Reland "Revert "Use OpenGL sampler objects when available."""

This reverts commit bfb3df4cc0.

Reason for revert: <INSERT REASONING HERE>

Original change's description:
> Revert "Reland "Revert "Use OpenGL sampler objects when available."""
> 
> This reverts commit bffe4ed34b.
> 
> Reason for revert: <INSERT REASONING HERE>
> 
> Original change's description:
> > Reland "Revert "Use OpenGL sampler objects when available.""
> >
> > This reverts commit d46987bb74.
> >
> > Reason for revert: breaking asan bot in chrome roll
> >
> > Original change's description:
> > > Revert "Revert "Use OpenGL sampler objects when available.""
> > >
> > > Put setting GL min/max texture lod behind caps check.
> > >
> > > Bug: skia:8471
> > >
> > >
> > > This reverts commit 1bccae517a.
> > >
> > > Change-Id: I8b98df6578a678bbb8b283d8203621a992be4ede
> > > Reviewed-on: https://skia-review.googlesource.com/c/163782
> > > Reviewed-by: Brian Salomon <bsalomon@google.com>
> > > Commit-Queue: Brian Salomon <bsalomon@google.com>
> >
> > TBR=bsalomon@google.com
> >
> > Change-Id: I8e3a0daea12659721d95967ef94c87f856e21948
> > No-Presubmit: true
> > No-Tree-Checks: true
> > No-Try: true
> > Bug: skia:8471
> > Reviewed-on: https://skia-review.googlesource.com/c/163887
> > Reviewed-by: Greg Daniel <egdaniel@google.com>
> > Commit-Queue: Greg Daniel <egdaniel@google.com>
> 
> TBR=egdaniel@google.com,bsalomon@google.com
> 
> Change-Id: Ia35bb7ad13527ffbd04173b517f7399e4a486ff1
> Bug: skia:8471
> Reviewed-on: https://skia-review.googlesource.com/c/163891
> Commit-Queue: Brian Salomon <bsalomon@google.com>
> Reviewed-by: Greg Daniel <egdaniel@google.com>

TBR=egdaniel@google.com,bsalomon@google.com

Change-Id: Ie49071bef7f7c20f0b116cd3a7abfda84728de12
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:8471
Reviewed-on: https://skia-review.googlesource.com/c/164241
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
This commit is contained in:
Brian Salomon 2018-10-22 15:39:22 +00:00 committed by Skia Commit-Bot
parent 3b5c8b73a6
commit 327955b1ba
7 changed files with 191 additions and 329 deletions

View File

@ -238,7 +238,6 @@ enum GrSurfaceOrigin {
*/
enum GrGLBackendState {
kRenderTarget_GrGLBackendState = 1 << 0,
// Also includes samplers bound to texture units.
kTextureBinding_GrGLBackendState = 1 << 1,
// View state stands for scissor and viewport
kView_GrGLBackendState = 1 << 2,

View File

@ -52,11 +52,6 @@ public:
/** 4 char null terminated string consisting only of chars 'r', 'g', 'b', 'a'. */
const char* c_str() const { return fSwiz; }
char operator[](int i) const {
SkASSERT(i >= 0 && i < 4);
return fSwiz[i];
}
/** Applies this swizzle to the input color and returns the swizzled color. */
GrColor applyTo(GrColor color) const {
int idx;
@ -121,7 +116,7 @@ private:
case GrColor_SHIFT_G : return 'g';
case GrColor_SHIFT_B : return 'b';
case GrColor_SHIFT_A : return 'a';
default: return -1;
default: return -1;
}
}

View File

@ -419,10 +419,6 @@ public:
SK_ABORT("Not implemented");
}
GrGLvoid genSamplers(GrGLsizei n, GrGLuint* samplers) override {
this->genGenericIds(n, samplers);
}
GrGLvoid genTextures(GrGLsizei n, GrGLuint *textures) override {
this->genGenericIds(n, textures);
}

View File

@ -173,123 +173,6 @@ bool GrGLGpu::BlendCoeffReferencesConstant(GrBlendCoeff coeff) {
GR_STATIC_ASSERT(kGrBlendCoeffCnt == SK_ARRAY_COUNT(gXfermodeCoeff2Blend));
}
static GrGLenum filter_to_gl_mag_filter(GrSamplerState::Filter filter) {
switch (filter) {
case GrSamplerState::Filter::kNearest: return GR_GL_NEAREST;
case GrSamplerState::Filter::kBilerp: return GR_GL_LINEAR;
case GrSamplerState::Filter::kMipMap: return GR_GL_LINEAR;
}
SK_ABORT("Unknown filter");
return 0;
}
static GrGLenum filter_to_gl_min_filter(GrSamplerState::Filter filter) {
switch (filter) {
case GrSamplerState::Filter::kNearest: return GR_GL_NEAREST;
case GrSamplerState::Filter::kBilerp: return GR_GL_LINEAR;
case GrSamplerState::Filter::kMipMap: return GR_GL_LINEAR_MIPMAP_LINEAR;
}
SK_ABORT("Unknown filter");
return 0;
}
static inline GrGLenum wrap_mode_to_gl_wrap(GrSamplerState::WrapMode wrapMode) {
switch (wrapMode) {
case GrSamplerState::WrapMode::kClamp: return GR_GL_CLAMP_TO_EDGE;
case GrSamplerState::WrapMode::kRepeat: return GR_GL_REPEAT;
case GrSamplerState::WrapMode::kMirrorRepeat: return GR_GL_MIRRORED_REPEAT;
};
SK_ABORT("Unknown wrap mode");
return 0;
}
///////////////////////////////////////////////////////////////////////////////
class GrGLGpu::SamplerObjectCache {
public:
SamplerObjectCache(GrGLGpu* gpu) : fGpu(gpu) {
fNumTextureUnits = fGpu->glCaps().shaderCaps()->maxFragmentSamplers();
fHWBoundSamplers.reset(new GrGLuint[fNumTextureUnits]);
std::fill_n(fHWBoundSamplers.get(), fNumTextureUnits, 0);
std::fill_n(fSamplers, kNumSamplers, 0);
}
~SamplerObjectCache() {
if (!fNumTextureUnits) {
// We've already been abandoned.
return;
}
GR_GL_CALL(fGpu->glInterface(), DeleteSamplers(kNumSamplers, fSamplers));
}
void bindSampler(int unitIdx, const GrSamplerState& state) {
int index = StateToIndex(state);
if (!fSamplers[index]) {
GrGLuint s;
GR_GL_CALL(fGpu->glInterface(), GenSamplers(1, &s));
if (!s) {
return;
}
fSamplers[index] = s;
auto minFilter = filter_to_gl_min_filter(state.filter());
auto magFilter = filter_to_gl_mag_filter(state.filter());
auto wrapX = wrap_mode_to_gl_wrap(state.wrapModeX());
auto wrapY = wrap_mode_to_gl_wrap(state.wrapModeY());
GR_GL_CALL(fGpu->glInterface(),
SamplerParameteri(s, GR_GL_TEXTURE_MIN_FILTER, minFilter));
GR_GL_CALL(fGpu->glInterface(),
SamplerParameteri(s, GR_GL_TEXTURE_MAG_FILTER, magFilter));
GR_GL_CALL(fGpu->glInterface(), SamplerParameteri(s, GR_GL_TEXTURE_WRAP_S, wrapX));
GR_GL_CALL(fGpu->glInterface(), SamplerParameteri(s, GR_GL_TEXTURE_WRAP_T, wrapY));
}
if (fHWBoundSamplers[unitIdx] != fSamplers[index]) {
GR_GL_CALL(fGpu->glInterface(), BindSampler(unitIdx, fSamplers[index]));
fHWBoundSamplers[unitIdx] = fSamplers[index];
}
}
void invalidateBindings() {
// When we have sampler support we always use samplers. So setting these to zero will cause
// a rebind on next usage.
std::fill_n(fHWBoundSamplers.get(), fNumTextureUnits, 0);
}
void abandon() {
fHWBoundSamplers.reset();
fNumTextureUnits = 0;
}
void release() {
if (!fNumTextureUnits) {
// We've already been abandoned.
return;
}
GR_GL_CALL(fGpu->glInterface(), DeleteSamplers(kNumSamplers, fSamplers));
std::fill_n(fSamplers, kNumSamplers, 0);
// Deleting a bound sampler implicitly binds sampler 0.
std::fill_n(fHWBoundSamplers.get(), fNumTextureUnits, 0);
}
private:
static int StateToIndex(const GrSamplerState& state) {
int filter = static_cast<int>(state.filter());
SkASSERT(filter >= 0 && filter < 3);
int wrapX = static_cast<int>(state.wrapModeX());
SkASSERT(wrapX >= 0 && wrapX < 3);
int wrapY = static_cast<int>(state.wrapModeY());
SkASSERT(wrapY >= 0 && wrapY < 3);
int idx = 9 * filter + 3 * wrapX + wrapY;
SkASSERT(idx < kNumSamplers);
return idx;
}
GrGLGpu* fGpu;
static constexpr int kNumSamplers = 27;
std::unique_ptr<GrGLuint[]> fHWBoundSamplers;
GrGLuint fSamplers[kNumSamplers];
int fNumTextureUnits;
};
///////////////////////////////////////////////////////////////////////////////
sk_sp<GrGpu> GrGLGpu::Make(sk_sp<const GrGLInterface> interface, const GrContextOptions& options,
@ -325,7 +208,6 @@ GrGLGpu::GrGLGpu(std::unique_ptr<GrGLContext> ctx, GrContext* context)
, fStencilClearFBOID(0)
, fHWMinSampleShading(0.0) {
SkASSERT(fGLContext);
GrGLClearErr(this->glInterface());
fCaps = sk_ref_sp(fGLContext->caps());
fHWBoundTextureUniqueIDs.reset(this->caps()->shaderCaps()->maxFragmentSamplers());
@ -352,9 +234,7 @@ GrGLGpu::GrGLGpu(std::unique_ptr<GrGLContext> ctx, GrContext* context)
fPathRendering.reset(new GrGLPathRendering(this));
}
if (this->glCaps().samplerObjectSupport()) {
fSamplerObjectCache.reset(new SamplerObjectCache(this));
}
GrGLClearErr(this->glInterface());
}
GrGLGpu::~GrGLGpu() {
@ -403,7 +283,6 @@ GrGLGpu::~GrGLGpu() {
}
delete fProgramCache;
fSamplerObjectCache.reset();
}
void GrGLGpu::disconnect(DisconnectType type) {
@ -438,16 +317,10 @@ void GrGLGpu::disconnect(DisconnectType type) {
if (fClearColorProgram.fProgram) {
GL_CALL(DeleteProgram(fClearColorProgram.fProgram));
}
if (fSamplerObjectCache) {
fSamplerObjectCache->release();
}
} else {
if (fProgramCache) {
fProgramCache->abandon();
}
if (fSamplerObjectCache) {
fSamplerObjectCache->abandon();
}
}
fHWProgram.reset();
@ -559,9 +432,6 @@ void GrGLGpu::onResetContext(uint32_t resetBits) {
for (int s = 0; s < fHWBoundTextureUniqueIDs.count(); ++s) {
fHWBoundTextureUniqueIDs[s].makeInvalid();
}
if (fSamplerObjectCache) {
fSamplerObjectCache->invalidateBindings();
}
}
if (resetBits & kBlend_GrGLBackendState) {
@ -670,10 +540,7 @@ sk_sp<GrTexture> GrGLGpu::onWrapBackendTexture(const GrBackendTexture& backendTe
GrMipMapsStatus mipMapsStatus = backendTex.hasMipMaps() ? GrMipMapsStatus::kValid
: GrMipMapsStatus::kNotAllocated;
auto texture = GrGLTexture::MakeWrapped(this, surfDesc, mipMapsStatus, idDesc);
// We don't know what parameters are already set on wrapped textures.
texture->textureParamsModified();
return std::move(texture);
return GrGLTexture::MakeWrapped(this, surfDesc, mipMapsStatus, idDesc);
}
sk_sp<GrTexture> GrGLGpu::onWrapRenderableBackendTexture(const GrBackendTexture& backendTex,
@ -719,8 +586,6 @@ sk_sp<GrTexture> GrGLGpu::onWrapRenderableBackendTexture(const GrBackendTexture&
sk_sp<GrGLTextureRenderTarget> texRT(
GrGLTextureRenderTarget::MakeWrapped(this, surfDesc, idDesc, rtIDDesc, mipMapsStatus));
texRT->baseLevelWasBoundToFBO();
// We don't know what parameters are already set on wrapped textures.
texRT->textureParamsModified();
return std::move(texRT);
}
@ -1382,21 +1247,36 @@ static sk_sp<GrTexture> return_null_texture() {
return nullptr;
}
static GrGLTexture::SamplerParams set_initial_texture_params(const GrGLInterface* interface,
const GrGLTextureInfo& info) {
#if 0 && defined(SK_DEBUG)
static size_t as_size_t(int x) {
return x;
}
#endif
static void set_initial_texture_params(const GrGLInterface* interface,
const GrGLTextureInfo& info,
GrGLTexture::TexParams* initialTexParams) {
// 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;
// we only set a subset here so invalidate first
initialTexParams->invalidate();
initialTexParams->fMinFilter = GR_GL_NEAREST;
initialTexParams->fMagFilter = GR_GL_NEAREST;
initialTexParams->fWrapS = GR_GL_CLAMP_TO_EDGE;
initialTexParams->fWrapT = GR_GL_CLAMP_TO_EDGE;
GR_GL_CALL(interface, TexParameteri(info.fTarget,
GR_GL_TEXTURE_MAG_FILTER,
initialTexParams->fMagFilter));
GR_GL_CALL(interface, TexParameteri(info.fTarget,
GR_GL_TEXTURE_MIN_FILTER,
initialTexParams->fMinFilter));
GR_GL_CALL(interface, TexParameteri(info.fTarget,
GR_GL_TEXTURE_WRAP_S,
initialTexParams->fWrapS));
GR_GL_CALL(interface, TexParameteri(info.fTarget,
GR_GL_TEXTURE_WRAP_T,
initialTexParams->fWrapT));
}
sk_sp<GrTexture> GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc,
@ -1431,7 +1311,7 @@ sk_sp<GrTexture> GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc,
GrGLTexture::IDDesc idDesc;
idDesc.fOwnership = GrBackendObjectOwnership::kOwned;
GrMipMapsStatus mipMapsStatus;
GrGLTexture::SamplerParams initialTexParams;
GrGLTexture::TexParams initialTexParams;
if (!this->createTextureImpl(desc, &idDesc.fInfo, isRenderTarget, &initialTexParams, texels,
mipLevelCount, &mipMapsStatus)) {
return return_null_texture();
@ -1453,9 +1333,7 @@ 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());
tex->setCachedTexParams(initialTexParams, this->getResetTimestamp());
#ifdef TRACE_TEXTURE_CREATION
SkDebugf("--- new texture [%d] size=(%d %d) config=%d\n",
idDesc.fInfo.fID, desc.fWidth, desc.fHeight, desc.fConfig);
@ -1621,9 +1499,8 @@ int GrGLGpu::getCompatibleStencilIndex(GrPixelConfig config) {
}
bool GrGLGpu::createTextureImpl(const GrSurfaceDesc& desc, GrGLTextureInfo* info, bool renderTarget,
GrGLTexture::SamplerParams* initialTexParams,
const GrMipLevel texels[], int mipLevelCount,
GrMipMapsStatus* mipMapsStatus) {
GrGLTexture::TexParams* initialTexParams, const GrMipLevel texels[],
int mipLevelCount, GrMipMapsStatus* mipMapsStatus) {
info->fID = 0;
info->fTarget = GR_GL_TEXTURE_2D;
GL_CALL(GenTextures(1, &(info->fID)));
@ -1643,7 +1520,7 @@ bool GrGLGpu::createTextureImpl(const GrSurfaceDesc& desc, GrGLTextureInfo* info
}
if (info) {
*initialTexParams = set_initial_texture_params(this->glInterface(), *info);
set_initial_texture_params(this->glInterface(), *info, initialTexParams);
}
if (!this->uploadTexData(desc.fConfig, desc.fWidth, desc.fHeight, info->fTarget,
@ -2813,19 +2690,73 @@ void GrGLGpu::flushBlend(const GrXferProcessor::BlendInfo& blendInfo, const GrSw
}
}
static void get_gl_swizzle_values(const GrSwizzle& swizzle, GrGLenum glValues[4]) {
for (int i = 0; i < 4; ++i) {
switch (swizzle[i]) {
case 'r': glValues[i] = GR_GL_RED; break;
case 'g': glValues[i] = GR_GL_GREEN; break;
case 'b': glValues[i] = GR_GL_BLUE; break;
case 'a': glValues[i] = GR_GL_ALPHA; break;
default: SK_ABORT("Unsupported component");
}
static inline GrGLenum wrap_mode_to_gl_wrap(GrSamplerState::WrapMode wrapMode) {
switch (wrapMode) {
case GrSamplerState::WrapMode::kClamp:
return GR_GL_CLAMP_TO_EDGE;
case GrSamplerState::WrapMode::kRepeat:
return GR_GL_REPEAT;
case GrSamplerState::WrapMode::kMirrorRepeat:
return GR_GL_MIRRORED_REPEAT;
};
SK_ABORT("Unknown wrap mode");
return 0;
}
static GrGLenum get_component_enum_from_char(char component) {
switch (component) {
case 'r':
return GR_GL_RED;
case 'g':
return GR_GL_GREEN;
case 'b':
return GR_GL_BLUE;
case 'a':
return GR_GL_ALPHA;
default:
SK_ABORT("Unsupported component");
return 0;
}
}
void GrGLGpu::bindTexture(int unitIdx, GrSamplerState samplerState, GrGLTexture* texture) {
/** If texture swizzling is available using tex parameters then it is preferred over mangling
the generated shader code. This potentially allows greater reuse of cached shaders. */
static void get_tex_param_swizzle(GrPixelConfig config,
const GrGLCaps& caps,
GrGLenum* glSwizzle) {
const GrSwizzle& swizzle = caps.configSwizzle(config);
for (int i = 0; i < 4; ++i) {
glSwizzle[i] = get_component_enum_from_char(swizzle.c_str()[i]);
}
}
static GrGLenum filter_to_gl_mag_filter(GrSamplerState::Filter filter) {
switch (filter) {
case GrSamplerState::Filter::kNearest:
return GR_GL_NEAREST;
case GrSamplerState::Filter::kBilerp:
return GR_GL_LINEAR;
case GrSamplerState::Filter::kMipMap:
return GR_GL_LINEAR;
}
SK_ABORT("Unknown filter");
return 0;
}
static GrGLenum filter_to_gl_min_filter(GrSamplerState::Filter filter) {
switch (filter) {
case GrSamplerState::Filter::kNearest:
return GR_GL_NEAREST;
case GrSamplerState::Filter::kBilerp:
return GR_GL_LINEAR;
case GrSamplerState::Filter::kMipMap:
return GR_GL_LINEAR_MIPMAP_LINEAR;
}
SK_ABORT("Unknown filter");
return 0;
}
void GrGLGpu::bindTexture(int unitIdx, const GrSamplerState& samplerState, GrGLTexture* texture) {
SkASSERT(texture);
#ifdef SK_DEBUG
@ -2854,109 +2785,87 @@ void GrGLGpu::bindTexture(int unitIdx, GrSamplerState samplerState, GrGLTexture*
fHWBoundTextureUniqueIDs[unitIdx] = textureID;
}
if (samplerState.filter() == GrSamplerState::Filter::kMipMap) {
ResetTimestamp timestamp;
const GrGLTexture::TexParams& oldTexParams = texture->getCachedTexParams(&timestamp);
bool setAll = timestamp < this->getResetTimestamp();
GrGLTexture::TexParams newTexParams;
GrSamplerState::Filter filterMode = samplerState.filter();
if (GrSamplerState::Filter::kMipMap == filterMode) {
if (!this->caps()->mipMapSupport() ||
texture->texturePriv().mipMapped() == GrMipMapped::kNo) {
samplerState.setFilterMode(GrSamplerState::Filter::kBilerp);
filterMode = GrSamplerState::Filter::kBilerp;
}
}
newTexParams.fMinFilter = filter_to_gl_min_filter(filterMode);
newTexParams.fMagFilter = filter_to_gl_mag_filter(filterMode);
#ifdef SK_DEBUG
// We were supposed to ensure MipMaps were up-to-date before getting here.
if (samplerState.filter() == GrSamplerState::Filter::kMipMap) {
if (GrSamplerState::Filter::kMipMap == filterMode) {
SkASSERT(!texture->texturePriv().mipMapsAreDirty());
}
#endif
ResetTimestamp timestamp = texture->getCachedParamsTimestamp();
bool setAll = timestamp < this->getResetTimestamp();
newTexParams.fMaxMipMapLevel = texture->texturePriv().maxMipMapLevel();
const GrGLTexture::SamplerParams* samplerParamsToRecord = nullptr;
GrGLTexture::SamplerParams newSamplerParams;
if (fSamplerObjectCache) {
fSamplerObjectCache->bindSampler(unitIdx, samplerState);
} else {
const GrGLTexture::SamplerParams& oldSamplerParams = texture->getCachedSamplerParams();
samplerParamsToRecord = &newSamplerParams;
newSamplerParams.fMinFilter = filter_to_gl_min_filter(samplerState.filter());
newSamplerParams.fMagFilter = filter_to_gl_mag_filter(samplerState.filter());
newSamplerParams.fWrapS = wrap_mode_to_gl_wrap(samplerState.wrapModeX());
newSamplerParams.fWrapT = wrap_mode_to_gl_wrap(samplerState.wrapModeY());
// These are the OpenGL default values.
newSamplerParams.fMinLOD = -1000;
newSamplerParams.fMaxLOD = 1000;
if (setAll || newSamplerParams.fMagFilter != oldSamplerParams.fMagFilter) {
this->setTextureUnit(unitIdx);
GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MAG_FILTER, newSamplerParams.fMagFilter));
}
if (setAll || newSamplerParams.fMinFilter != oldSamplerParams.fMinFilter) {
this->setTextureUnit(unitIdx);
GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MIN_FILTER, newSamplerParams.fMinFilter));
}
newTexParams.fWrapS = wrap_mode_to_gl_wrap(samplerState.wrapModeX());
newTexParams.fWrapT = wrap_mode_to_gl_wrap(samplerState.wrapModeY());
get_tex_param_swizzle(texture->config(), this->glCaps(), newTexParams.fSwizzleRGBA);
if (setAll || newTexParams.fMagFilter != oldTexParams.fMagFilter) {
this->setTextureUnit(unitIdx);
GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MAG_FILTER, newTexParams.fMagFilter));
}
if (setAll || newTexParams.fMinFilter != oldTexParams.fMinFilter) {
this->setTextureUnit(unitIdx);
GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MIN_FILTER, newTexParams.fMinFilter));
}
if (setAll || newTexParams.fMaxMipMapLevel != oldTexParams.fMaxMipMapLevel) {
// These are not supported in ES2 contexts
if (this->glCaps().mipMapLevelAndLodControlSupport()) {
// Min and max LOD are actually floats. We don't curently support glTexParameterf.
// However, we only set these to integral floats (see above).
if (setAll || newSamplerParams.fMinLOD != oldSamplerParams.fMinLOD) {
if (newTexParams.fMaxMipMapLevel != 0) {
this->setTextureUnit(unitIdx);
GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MIN_LOD, newSamplerParams.fMinLOD));
GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MIN_LOD, 0));
GL_CALL(TexParameteri(target, GR_GL_TEXTURE_BASE_LEVEL, 0));
GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MAX_LOD,
newTexParams.fMaxMipMapLevel));
GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MAX_LEVEL,
newTexParams.fMaxMipMapLevel));
}
if (setAll || newSamplerParams.fMaxLOD != oldSamplerParams.fMaxLOD) {
this->setTextureUnit(unitIdx);
GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MAX_LOD, newSamplerParams.fMaxLOD));
}
}
if (setAll || newSamplerParams.fWrapS != oldSamplerParams.fWrapS) {
this->setTextureUnit(unitIdx);
GL_CALL(TexParameteri(target, GR_GL_TEXTURE_WRAP_S, newSamplerParams.fWrapS));
}
if (setAll || newSamplerParams.fWrapT != oldSamplerParams.fWrapT) {
this->setTextureUnit(unitIdx);
GL_CALL(TexParameteri(target, GR_GL_TEXTURE_WRAP_T, newSamplerParams.fWrapT));
}
}
GrGLTexture::NonSamplerParams newNonSamplerParams;
newNonSamplerParams.fBaseMipMapLevel = 0;
newNonSamplerParams.fMaxMipMapLevel = texture->texturePriv().maxMipMapLevel();
if (setAll || newTexParams.fWrapS != oldTexParams.fWrapS) {
this->setTextureUnit(unitIdx);
GL_CALL(TexParameteri(target, GR_GL_TEXTURE_WRAP_S, newTexParams.fWrapS));
}
if (setAll || newTexParams.fWrapT != oldTexParams.fWrapT) {
this->setTextureUnit(unitIdx);
GL_CALL(TexParameteri(target, GR_GL_TEXTURE_WRAP_T, newTexParams.fWrapT));
}
if (this->glCaps().textureSwizzleSupport() &&
(setAll || memcmp(newTexParams.fSwizzleRGBA,
oldTexParams.fSwizzleRGBA,
sizeof(newTexParams.fSwizzleRGBA)))) {
this->setTextureSwizzle(unitIdx, target, newTexParams.fSwizzleRGBA);
}
texture->setCachedTexParams(newTexParams, this->getResetTimestamp());
}
const GrGLTexture::NonSamplerParams& oldNonSamplerParams = texture->getCachedNonSamplerParams();
if (this->glCaps().textureSwizzleSupport()) {
auto swizzle = this->glCaps().configSwizzle(texture->config());
newNonSamplerParams.fSwizzleKey = swizzle.asKey();
if (setAll || swizzle.asKey() != oldNonSamplerParams.fSwizzleKey) {
GrGLenum glValues[4];
get_gl_swizzle_values(swizzle, glValues);
this->setTextureUnit(unitIdx);
if (this->glStandard() == kGLES_GrGLStandard) {
// ES3 added swizzle support but not GL_TEXTURE_SWIZZLE_RGBA.
GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_R, glValues[0]));
GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_G, glValues[1]));
GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_B, glValues[2]));
GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_A, glValues[3]));
} else {
GR_STATIC_ASSERT(sizeof(glValues[0]) == sizeof(GrGLint));
GL_CALL(TexParameteriv(target, GR_GL_TEXTURE_SWIZZLE_RGBA,
reinterpret_cast<const GrGLint*>(glValues)));
}
}
void GrGLGpu::setTextureSwizzle(int unitIdx, GrGLenum target, const GrGLenum swizzle[]) {
this->setTextureUnit(unitIdx);
if (this->glStandard() == kGLES_GrGLStandard) {
// ES3 added swizzle support but not GL_TEXTURE_SWIZZLE_RGBA.
GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_R, swizzle[0]));
GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_G, swizzle[1]));
GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_B, swizzle[2]));
GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_A, swizzle[3]));
} else {
GR_STATIC_ASSERT(sizeof(swizzle[0]) == sizeof(GrGLint));
GL_CALL(TexParameteriv(target, GR_GL_TEXTURE_SWIZZLE_RGBA,
reinterpret_cast<const GrGLint*>(swizzle)));
}
// These are not supported in ES2 contexts
if (this->glCaps().mipMapLevelAndLodControlSupport()) {
if (newNonSamplerParams.fBaseMipMapLevel != oldNonSamplerParams.fBaseMipMapLevel) {
this->setTextureUnit(unitIdx);
GL_CALL(TexParameteri(target, GR_GL_TEXTURE_BASE_LEVEL,
newNonSamplerParams.fBaseMipMapLevel));
}
if (newNonSamplerParams.fMaxMipMapLevel != oldNonSamplerParams.fMaxMipMapLevel) {
this->setTextureUnit(unitIdx);
GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MAX_LEVEL,
newNonSamplerParams.fMaxMipMapLevel));
}
}
texture->setCachedParams(samplerParamsToRecord, newNonSamplerParams, this->getResetTimestamp());
}
void GrGLGpu::flushColorWrite(bool writeColor) {
@ -3945,15 +3854,12 @@ bool GrGLGpu::onRegenerateMipMapLevels(GrTexture* texture) {
GrGLIRect viewport;
viewport.fLeft = 0;
viewport.fBottom = 0;
for (GrGLint level = 1; level < levelCount; ++level) {
// Get and bind the program for this particular downsample (filter shape can vary):
int progIdx = TextureSizeToMipmapProgramIdx(width, height);
if (!fMipmapPrograms[progIdx].fProgram) {
if (!this->createMipmapProgram(progIdx)) {
SkDebugf("Failed to create mipmap program.\n");
// Invalidate all params to cover base level change in a previous iteration.
glTex->textureParamsModified();
return false;
}
}
@ -3986,10 +3892,7 @@ 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());
texture->textureParamsModified();
return true;
}

View File

@ -56,7 +56,7 @@ public:
}
// Used by GrGLProgram to configure OpenGL state.
void bindTexture(int unitIdx, GrSamplerState samplerState, GrGLTexture* texture);
void bindTexture(int unitIdx, const GrSamplerState& samplerState, GrGLTexture* texture);
// These functions should be used to bind GL objects. They track the GL state and skip redundant
// bindings. Making the equivalent glBind calls directly will confuse the state tracking.
@ -208,7 +208,7 @@ private:
// The texture is populated with |texels|, if it exists.
// The texture parameters are cached in |initialTexParams|.
bool createTextureImpl(const GrSurfaceDesc& desc, GrGLTextureInfo* info, bool renderTarget,
GrGLTexture::SamplerParams* initialTexParams, const GrMipLevel texels[],
GrGLTexture::TexParams* initialTexParams, const GrMipLevel texels[],
int mipLevelCount, GrMipMapsStatus* mipMapsStatus);
// Checks whether glReadPixels can be called to get pixel values in readConfig from the
@ -631,9 +631,6 @@ private:
GrPrimitiveType fLastPrimitiveType;
bool fRequiresFlushBeforeNextInstancedDraw = false;
class SamplerObjectCache;
std::unique_ptr<SamplerObjectCache> fSamplerObjectCache;
std::unique_ptr<GrGLGpuRTCommandBuffer> fCachedRTCommandBuffer;
std::unique_ptr<GrGLGpuTextureCommandBuffer> fCachedTexCommandBuffer;

View File

@ -68,7 +68,8 @@ GrGLTexture::GrGLTexture(GrGLGpu* gpu, const GrSurfaceDesc& desc, const IDDesc&
void GrGLTexture::init(const GrSurfaceDesc& desc, const IDDesc& idDesc) {
SkASSERT(0 != idDesc.fInfo.fID);
SkASSERT(0 != idDesc.fInfo.fFormat);
fParamsTimestamp = GrGpu::kExpiredTimestamp;
fTexParams.invalidate();
fTexParamsTimestamp = GrGpu::kExpiredTimestamp;
fID = idDesc.fInfo.fID;
fFormat = idDesc.fInfo.fFormat;
fTextureIDOwnership = idDesc.fOwnership;

View File

@ -17,37 +17,14 @@ 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;
void invalidate() {
fMinFilter = ~0U;
fMagFilter = ~0U;
fWrapS = ~0U;
fWrapT = ~0U;
fMinLOD = SK_ScalarNaN;
fMaxLOD = SK_ScalarNaN;
}
};
// 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 TexParams {
GrGLenum fMinFilter;
GrGLenum fMagFilter;
GrGLenum fWrapS;
GrGLenum fWrapT;
GrGLenum fMaxMipMapLevel;
GrGLenum fSwizzleRGBA[4];
void invalidate() { memset(this, 0xff, sizeof(TexParams)); }
};
struct IDDesc {
@ -66,28 +43,22 @@ public:
GrBackendTexture getBackendTexture() const override;
void textureParamsModified() override {
fSamplerParams.invalidate();
fNonSamplerParams.invalidate();
}
void textureParamsModified() override { fTexParams.invalidate(); }
void setRelease(sk_sp<GrReleaseProcHelper> releaseHelper) override {
fReleaseHelper = std::move(releaseHelper);
}
// 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; }
const TexParams& getCachedTexParams(GrGpu::ResetTimestamp* timestamp) const {
*timestamp = fTexParamsTimestamp;
return fTexParams;
}
void setCachedParams(const SamplerParams* samplerParams,
const NonSamplerParams& nonSamplerParams,
GrGpu::ResetTimestamp currTimestamp) {
if (samplerParams) {
fSamplerParams = *samplerParams;
}
fNonSamplerParams = nonSamplerParams;
fParamsTimestamp = currTimestamp;
void setCachedTexParams(const TexParams& texParams,
GrGpu::ResetTimestamp timestamp) {
fTexParams = texParams;
fTexParamsTimestamp = timestamp;
}
GrGLuint textureID() const { return fID; }
@ -126,14 +97,14 @@ private:
}
}
SamplerParams fSamplerParams;
NonSamplerParams fNonSamplerParams;
GrGpu::ResetTimestamp fParamsTimestamp;
sk_sp<GrReleaseProcHelper> fReleaseHelper;
GrGLuint fID;
GrGLenum fFormat;
GrBackendObjectOwnership fTextureIDOwnership;
bool fBaseLevelHasBeenBoundToFBO = false;
TexParams fTexParams;
GrGpu::ResetTimestamp fTexParamsTimestamp;
GrGLuint fID;
GrGLenum fFormat;
GrBackendObjectOwnership fTextureIDOwnership;
bool fBaseLevelHasBeenBoundToFBO = false;
sk_sp<GrReleaseProcHelper> fReleaseHelper;
typedef GrTexture INHERITED;
};