Make stencil buffers uncached for uncached render target textures

Make new stencil buffers of uncached render target textures not affect the
cache budgets. This is consistent with render buffer storage of uncached
render target textures.

Affects only newly created stencil buffers. An uncached render target
might still receive a cached stencil buffer if such is available from
cache.

BUG=skia:3119
BUG=skia:3301

Review URL: https://codereview.chromium.org/859013002
This commit is contained in:
kkinnunen 2015-01-27 00:30:18 -08:00 committed by Commit bot
parent 7f7036ab3f
commit 36c57dfb4f
7 changed files with 43 additions and 27 deletions

View File

@ -65,7 +65,7 @@ GrTexture* GrGpu::createTexture(const GrSurfaceDesc& desc, bool budgeted,
!(kNoStencil_GrSurfaceFlag & desc.fFlags)) {
SkASSERT(tex->asRenderTarget());
// TODO: defer this and attach dynamically
if (!this->attachStencilBufferToRenderTarget(tex->asRenderTarget())) {
if (!this->attachStencilBufferToRenderTarget(tex->asRenderTarget(), budgeted)) {
tex->unref();
return NULL;
}
@ -77,7 +77,7 @@ GrTexture* GrGpu::createTexture(const GrSurfaceDesc& desc, bool budgeted,
return tex;
}
bool GrGpu::attachStencilBufferToRenderTarget(GrRenderTarget* rt) {
bool GrGpu::attachStencilBufferToRenderTarget(GrRenderTarget* rt, bool budgeted) {
SkASSERT(NULL == rt->getStencilBuffer());
GrScratchKey sbKey;
GrStencilBuffer::ComputeKey(rt->width(), rt->height(), rt->numSamples(), &sbKey);
@ -91,7 +91,7 @@ bool GrGpu::attachStencilBufferToRenderTarget(GrRenderTarget* rt) {
}
return attached;
}
if (this->createStencilBufferForRenderTarget(rt, rt->width(), rt->height())) {
if (this->createStencilBufferForRenderTarget(rt, budgeted, rt->width(), rt->height())) {
// Right now we're clearing the stencil buffer here after it is
// attached to an RT for the first time. When we start matching
// stencil buffers with smaller color targets this will no longer
@ -116,7 +116,7 @@ GrTexture* GrGpu::wrapBackendTexture(const GrBackendTextureDesc& desc) {
// TODO: defer this and attach dynamically
GrRenderTarget* tgt = tex->asRenderTarget();
if (tgt &&
!this->attachStencilBufferToRenderTarget(tgt)) {
!this->attachStencilBufferToRenderTarget(tgt, true /*budgeted*/)) {
tex->unref();
return NULL;
} else {

View File

@ -469,7 +469,8 @@ private:
// width and height may be larger than rt (if underlying API allows it).
// Should attach the SB to the RT. Returns false if compatible sb could
// not be created.
virtual bool createStencilBufferForRenderTarget(GrRenderTarget*, int width, int height) = 0;
virtual bool createStencilBufferForRenderTarget(GrRenderTarget*, bool budgeted,
int width, int height) = 0;
// attaches an existing SB to an existing RT.
virtual bool attachStencilBufferToRenderTarget(GrStencilBuffer*, GrRenderTarget*) = 0;
@ -478,7 +479,7 @@ private:
virtual void clearStencil(GrRenderTarget* target) = 0;
// Given a rt, find or create a stencil buffer and attach it
bool attachStencilBufferToRenderTarget(GrRenderTarget* target);
bool attachStencilBufferToRenderTarget(GrRenderTarget* target, bool budgeted);
virtual void didAddGpuTraceMarker() = 0;
virtual void didRemoveGpuTraceMarker() = 0;

View File

@ -50,16 +50,18 @@ public:
static void ComputeKey(int width, int height, int sampleCnt, GrScratchKey* key);
protected:
GrStencilBuffer(GrGpu* gpu, int width, int height, int bits, int sampleCnt)
: GrGpuResource(gpu, kCached_LifeCycle)
GrStencilBuffer(GrGpu* gpu, LifeCycle lifeCycle, int width, int height, int bits, int sampleCnt)
: GrGpuResource(gpu, lifeCycle)
, fWidth(width)
, fHeight(height)
, fBits(bits)
, fSampleCnt(sampleCnt)
, fLastClipStackGenID(SkClipStack::kInvalidGenID) {
GrScratchKey key;
ComputeKey(width, height, sampleCnt, &key);
this->setScratchKey(key);
if (kCached_LifeCycle == lifeCycle) {
GrScratchKey key;
ComputeKey(width, height, sampleCnt, &key);
this->setScratchKey(key);
}
fLastClipStackRect.setEmpty();
}

View File

@ -144,7 +144,8 @@ private:
void onResolveRenderTarget(GrRenderTarget* target) SK_OVERRIDE { return; }
bool createStencilBufferForRenderTarget(GrRenderTarget*, int width, int height) SK_OVERRIDE {
bool createStencilBufferForRenderTarget(GrRenderTarget*, bool budgeted,
int width, int height) SK_OVERRIDE {
return false;
}

View File

@ -430,6 +430,9 @@ GrRenderTarget* GrGLGpu::onWrapBackendRenderTarget(const GrBackendRenderTargetDe
GrRenderTarget* tgt = SkNEW_ARGS(GrGLRenderTarget, (this, desc, idDesc));
if (wrapDesc.fStencilBits) {
GrGLStencilBuffer::IDDesc sbDesc;
sbDesc.fRenderbufferID = 0;
sbDesc.fLifeCycle = GrGpuResource::kWrapped_LifeCycle;
GrGLStencilBuffer::Format format;
format.fInternalFormat = GrGLStencilBuffer::kUnknownInternalFormat;
format.fPacked = false;
@ -437,7 +440,7 @@ GrRenderTarget* GrGLGpu::onWrapBackendRenderTarget(const GrBackendRenderTargetDe
format.fTotalBits = wrapDesc.fStencilBits;
GrGLStencilBuffer* sb = SkNEW_ARGS(GrGLStencilBuffer,
(this,
0,
sbDesc,
desc.fWidth,
desc.fHeight,
desc.fSampleCnt,
@ -1114,8 +1117,8 @@ void inline get_stencil_rb_sizes(const GrGLInterface* gl,
}
}
bool GrGLGpu::createStencilBufferForRenderTarget(GrRenderTarget* rt, int width, int height) {
bool GrGLGpu::createStencilBufferForRenderTarget(GrRenderTarget* rt, bool budgeted, int width,
int height) {
// All internally created RTs are also textures. We don't create
// SBs for a client's standalone RT (that is a RT that isn't also a texture).
SkASSERT(rt->asTexture());
@ -1123,17 +1126,20 @@ bool GrGLGpu::createStencilBufferForRenderTarget(GrRenderTarget* rt, int width,
SkASSERT(height >= rt->height());
int samples = rt->numSamples();
GrGLuint sbID = 0;
GrGLStencilBuffer::IDDesc sbDesc;
sbDesc.fRenderbufferID = 0;
sbDesc.fLifeCycle = budgeted ? GrGpuResource::kCached_LifeCycle
: GrGpuResource::kUncached_LifeCycle;
int stencilFmtCnt = this->glCaps().stencilFormats().count();
for (int i = 0; i < stencilFmtCnt; ++i) {
if (!sbID) {
GL_CALL(GenRenderbuffers(1, &sbID));
if (!sbDesc.fRenderbufferID) {
GL_CALL(GenRenderbuffers(1, &sbDesc.fRenderbufferID));
}
if (!sbID) {
if (!sbDesc.fRenderbufferID) {
return false;
}
GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, sbID));
GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, sbDesc.fRenderbufferID));
// we start with the last stencil format that succeeded in hopes
// that we won't go through this loop more than once after the
// first (painful) stencil creation.
@ -1155,12 +1161,13 @@ bool GrGLGpu::createStencilBufferForRenderTarget(GrRenderTarget* rt, int width,
created = (GR_GL_NO_ERROR == check_alloc_error(rt->desc(), this->glInterface()));
}
if (created) {
// After sized formats we attempt an unsized format and take
// whatever sizes GL gives us. In that case we query for the size.
GrGLStencilBuffer::Format format = sFmt;
get_stencil_rb_sizes(this->glInterface(), &format);
SkAutoTUnref<GrStencilBuffer> sb(SkNEW_ARGS(GrGLStencilBuffer,
(this, sbID, width, height, samples, format)));
(this, sbDesc, width, height, samples, format)));
if (this->attachStencilBufferToRenderTarget(sb, rt)) {
fLastSuccessfulStencilFmtIdx = sIdx;
rt->setStencilBuffer(sb);
@ -1170,10 +1177,10 @@ bool GrGLGpu::createStencilBufferForRenderTarget(GrRenderTarget* rt, int width,
// again.
sb->cacheAccess().removeScratchKey();
// Set this to 0 since we handed the valid ID off to the failed stencil buffer resource.
sbID = 0;
sbDesc.fRenderbufferID = 0;
}
}
GL_CALL(DeleteRenderbuffers(1, &sbID));
GL_CALL(DeleteRenderbuffers(1, &sbDesc.fRenderbufferID));
return false;
}

View File

@ -123,7 +123,7 @@ private:
GrIndexBuffer* onCreateIndexBuffer(size_t size, bool dynamic) SK_OVERRIDE;
GrTexture* onWrapBackendTexture(const GrBackendTextureDesc&) SK_OVERRIDE;
GrRenderTarget* onWrapBackendRenderTarget(const GrBackendRenderTargetDesc&) SK_OVERRIDE;
bool createStencilBufferForRenderTarget(GrRenderTarget* rt,
bool createStencilBufferForRenderTarget(GrRenderTarget* rt, bool budgeted,
int width, int height) SK_OVERRIDE;
bool attachStencilBufferToRenderTarget(GrStencilBuffer* sb, GrRenderTarget* rt) SK_OVERRIDE;

View File

@ -23,14 +23,19 @@ public:
bool fPacked;
};
struct IDDesc {
GrGLuint fRenderbufferID;
GrGpuResource::LifeCycle fLifeCycle;
};
GrGLStencilBuffer(GrGpu* gpu,
GrGLint rbid,
const IDDesc& idDesc,
int width, int height,
int sampleCnt,
const Format& format)
: GrStencilBuffer(gpu, width, height, format.fStencilBits, sampleCnt)
: GrStencilBuffer(gpu, idDesc.fLifeCycle, width, height, format.fStencilBits, sampleCnt)
, fFormat(format)
, fRenderbufferID(rbid) {
, fRenderbufferID(idDesc.fRenderbufferID) {
this->registerWithCache();
}