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:
parent
7f7036ab3f
commit
36c57dfb4f
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
if (kCached_LifeCycle == lifeCycle) {
|
||||
GrScratchKey key;
|
||||
ComputeKey(width, height, sampleCnt, &key);
|
||||
this->setScratchKey(key);
|
||||
}
|
||||
fLastClipStackRect.setEmpty();
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user