aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar egdaniel <egdaniel@google.com>2015-09-14 12:56:10 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-09-14 12:56:10 -0700
commitec00d94199fad7723b5987b86c1abef8ddafe2d8 (patch)
tree4161bb293ffe433cbe0fd41a4ad0263b36eedffd
parent37497dc9de9cf8df4f9dd972b50cbd35b9da6682 (diff)
Move some of the adding stencil attachment logic of Gpu and into Render Target.
The new flow of calls for attaching a Stencil looks like: Client rt->attachStencilAttachment() gpu->getStencilAttachment() glgpu->createStencilAttachment() glrt->completeStencilAttachment() //actually attaches BUG=skia: Review URL: https://codereview.chromium.org/1333383002
-rw-r--r--include/gpu/GrRenderTarget.h14
-rw-r--r--src/gpu/GrClipMaskManager.cpp6
-rw-r--r--src/gpu/GrDrawContext.cpp3
-rw-r--r--src/gpu/GrDrawTarget.cpp4
-rw-r--r--src/gpu/GrGpu.cpp45
-rw-r--r--src/gpu/GrGpu.h21
-rw-r--r--src/gpu/GrRenderTarget.cpp23
-rw-r--r--src/gpu/GrRenderTargetPriv.h9
-rw-r--r--src/gpu/GrResourceProvider.cpp52
-rw-r--r--src/gpu/GrResourceProvider.h8
-rw-r--r--src/gpu/GrTest.cpp10
-rw-r--r--src/gpu/gl/GrGLGpu.cpp139
-rw-r--r--src/gpu/gl/GrGLGpu.h15
-rw-r--r--src/gpu/gl/GrGLRenderTarget.cpp82
-rw-r--r--src/gpu/gl/GrGLRenderTarget.h13
-rw-r--r--tests/ResourceCacheTest.cpp39
16 files changed, 241 insertions, 242 deletions
diff --git a/include/gpu/GrRenderTarget.h b/include/gpu/GrRenderTarget.h
index 8983d53a25..2309dbd876 100644
--- a/include/gpu/GrRenderTarget.h
+++ b/include/gpu/GrRenderTarget.h
@@ -144,15 +144,18 @@ public:
*/
virtual GrBackendObject getRenderTargetHandle() const = 0;
+ // Checked when this object is asked to attach a stencil buffer.
+ virtual bool canAttemptStencilAttachment() const = 0;
+
// Provides access to functions that aren't part of the public API.
GrRenderTargetPriv renderTargetPriv();
const GrRenderTargetPriv renderTargetPriv() const;
protected:
GrRenderTarget(GrGpu* gpu, LifeCycle lifeCycle, const GrSurfaceDesc& desc,
- SampleConfig sampleConfig)
+ SampleConfig sampleConfig, GrStencilAttachment* stencil = nullptr)
: INHERITED(gpu, lifeCycle, desc)
- , fStencilAttachment(NULL)
+ , fStencilAttachment(stencil)
, fSampleConfig(sampleConfig) {
fResolveRect.setLargestInverted();
}
@@ -162,8 +165,11 @@ protected:
void onRelease() override;
private:
- // Checked when this object is asked to attach a stencil buffer.
- virtual bool canAttemptStencilAttachment() const = 0;
+ // Allows the backends to perform any additional work that is required for attaching a
+ // GrStencilAttachment. When this is called, the GrStencilAttachment has already been put onto
+ // the GrRenderTarget. This function must return false if any failures occur when completing the
+ // stencil attachment.
+ virtual bool completeStencilAttachment() = 0;
friend class GrRenderTargetPriv;
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp
index 0f32839a7e..0ab1600b7d 100644
--- a/src/gpu/GrClipMaskManager.cpp
+++ b/src/gpu/GrClipMaskManager.cpp
@@ -717,7 +717,8 @@ bool GrClipMaskManager::createStencilClipMask(GrRenderTarget* rt,
SkASSERT(kNone_ClipMaskType == fCurrClipMaskType);
SkASSERT(rt);
- GrStencilAttachment* stencilAttachment = rt->renderTargetPriv().attachStencilAttachment();
+ GrStencilAttachment* stencilAttachment =
+ fDrawTarget->cmmAccess().resourceProvider()->attachStencilAttachment(rt);
if (nullptr == stencilAttachment) {
return false;
}
@@ -977,7 +978,8 @@ void GrClipMaskManager::setPipelineBuilderStencil(const GrPipelineBuilder& pipel
int stencilBits = 0;
GrRenderTarget* rt = pipelineBuilder.getRenderTarget();
- GrStencilAttachment* stencilAttachment = rt->renderTargetPriv().attachStencilAttachment();
+ GrStencilAttachment* stencilAttachment =
+ fDrawTarget->cmmAccess().resourceProvider()->attachStencilAttachment(rt);
if (stencilAttachment) {
stencilBits = stencilAttachment->bits();
}
diff --git a/src/gpu/GrDrawContext.cpp b/src/gpu/GrDrawContext.cpp
index 3d3be749d0..94fcee0313 100644
--- a/src/gpu/GrDrawContext.cpp
+++ b/src/gpu/GrDrawContext.cpp
@@ -63,7 +63,8 @@ GrTextContext* GrDrawContext::createTextContext(GrRenderTarget* renderTarget,
if (fContext->caps()->shaderCaps()->pathRenderingSupport() &&
renderTarget->isStencilBufferMultisampled() &&
fSurfaceProps.isUseDeviceIndependentFonts()) {
- GrStencilAttachment* sb = renderTarget->renderTargetPriv().attachStencilAttachment();
+ GrStencilAttachment* sb =
+ fContext->resourceProvider()->attachStencilAttachment(renderTarget);
if (sb) {
return GrStencilAndCoverTextContext::Create(fContext, surfaceProps);
}
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index 076b626a1a..3d5f4288f4 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -215,7 +215,7 @@ void GrDrawTarget::stencilPath(const GrPipelineBuilder& pipelineBuilder,
// set stencil settings for path
GrStencilSettings stencilSettings;
GrRenderTarget* rt = pipelineBuilder.getRenderTarget();
- GrStencilAttachment* sb = rt->renderTargetPriv().attachStencilAttachment();
+ GrStencilAttachment* sb = fResourceProvider->attachStencilAttachment(rt);
this->getPathStencilSettingsForFilltype(fill, sb, &stencilSettings);
GrBatch* batch = GrStencilPathBatch::Create(viewMatrix,
@@ -270,7 +270,7 @@ void GrDrawTarget::drawPathBatch(const GrPipelineBuilder& pipelineBuilder,
// Ensure the render target has a stencil buffer and get the stencil settings.
GrStencilSettings stencilSettings;
GrRenderTarget* rt = pipelineBuilder.getRenderTarget();
- GrStencilAttachment* sb = rt->renderTargetPriv().attachStencilAttachment();
+ GrStencilAttachment* sb = fResourceProvider->attachStencilAttachment(rt);
this->getPathStencilSettingsForFilltype(fill, sb, &stencilSettings);
batch->setStencilSettings(stencilSettings);
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index e1b8ed5c85..96728f3ba8 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -16,6 +16,7 @@
#include "GrPathRendering.h"
#include "GrPipeline.h"
#include "GrResourceCache.h"
+#include "GrResourceProvider.h"
#include "GrRenderTargetPriv.h"
#include "GrStencilAttachment.h"
#include "GrSurfacePriv.h"
@@ -134,48 +135,6 @@ GrTexture* GrGpu::createTexture(const GrSurfaceDesc& origDesc, bool budgeted,
return tex;
}
-bool GrGpu::attachStencilAttachmentToRenderTarget(GrRenderTarget* rt) {
- SkASSERT(nullptr == rt->renderTargetPriv().getStencilAttachment());
- GrUniqueKey sbKey;
-
- int width = rt->width();
- int height = rt->height();
-#if 0
- if (this->caps()->oversizedStencilSupport()) {
- width = SkNextPow2(width);
- height = SkNextPow2(height);
- }
-#endif
-
- GrStencilAttachment::ComputeSharedStencilAttachmentKey(width, height,
- rt->numStencilSamples(), &sbKey);
- SkAutoTUnref<GrStencilAttachment> sb(static_cast<GrStencilAttachment*>(
- this->getContext()->getResourceCache()->findAndRefUniqueResource(sbKey)));
- if (sb) {
- if (this->attachStencilAttachmentToRenderTarget(sb, rt)) {
- rt->renderTargetPriv().didAttachStencilAttachment(sb);
- return true;
- }
- return false;
- }
- if (this->createStencilAttachmentForRenderTarget(rt, width, 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
- // be correct because it won't be guaranteed to clear the entire
- // sb.
- // We used to clear down in the GL subclass using a special purpose
- // FBO. But iOS doesn't allow a stencil-only FBO. It reports unsupported
- // FBO status.
- this->clearStencil(rt);
- GrStencilAttachment* sb = rt->renderTargetPriv().getStencilAttachment();
- sb->resourcePriv().setUniqueKey(sbKey);
- return true;
- } else {
- return false;
- }
-}
-
GrTexture* GrGpu::wrapBackendTexture(const GrBackendTextureDesc& desc, GrWrapOwnership ownership) {
this->handleDirtyContext();
GrTexture* tex = this->onWrapBackendTexture(desc, ownership);
@@ -184,7 +143,7 @@ GrTexture* GrGpu::wrapBackendTexture(const GrBackendTextureDesc& desc, GrWrapOwn
}
// TODO: defer this and attach dynamically
GrRenderTarget* tgt = tex->asRenderTarget();
- if (tgt && !this->attachStencilAttachmentToRenderTarget(tgt)) {
+ if (tgt && !fContext->resourceProvider()->attachStencilAttachment(tgt)) {
tex->unref();
return nullptr;
} else {
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index 73a5264bbc..d8e5681de1 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -369,8 +369,14 @@ public:
virtual bool isTestingOnlyBackendTexture(GrBackendObject id) const = 0;
virtual void deleteTestingOnlyBackendTexture(GrBackendObject id) const = 0;
- // Given a rt, find or create a stencil buffer and attach it
- bool attachStencilAttachmentToRenderTarget(GrRenderTarget* target);
+ // width and height may be larger than rt (if underlying API allows it).
+ // Returns nullptr if compatible sb could not be created, otherwise the caller owns the ref on
+ // the GrStencilAttachment.
+ virtual GrStencilAttachment* createStencilAttachmentForRenderTarget(const GrRenderTarget*,
+ int width,
+ int height) = 0;
+ // clears target's entire stencil buffer to 0
+ virtual void clearStencil(GrRenderTarget* target) = 0;
// This is only to be used in GL-specific tests.
virtual const GrGLContext* glContextForTesting() const { return nullptr; }
@@ -466,17 +472,6 @@ private:
const SkIRect& srcRect,
const SkIPoint& dstPoint) = 0;
- // 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 createStencilAttachmentForRenderTarget(GrRenderTarget*, int width, int height) = 0;
-
- // attaches an existing SB to an existing RT.
- virtual bool attachStencilAttachmentToRenderTarget(GrStencilAttachment*, GrRenderTarget*) = 0;
-
- // clears target's entire stencil buffer to 0
- virtual void clearStencil(GrRenderTarget* target) = 0;
-
void resetContext() {
this->onResetContext(fResetBits);
fResetBits = 0;
diff --git a/src/gpu/GrRenderTarget.cpp b/src/gpu/GrRenderTarget.cpp
index 5cb34e849a..c16738e795 100644
--- a/src/gpu/GrRenderTarget.cpp
+++ b/src/gpu/GrRenderTarget.cpp
@@ -55,29 +55,24 @@ void GrRenderTarget::overrideResolveRect(const SkIRect rect) {
}
void GrRenderTarget::onRelease() {
- this->renderTargetPriv().didAttachStencilAttachment(nullptr);
+ SkSafeSetNull(fStencilAttachment);
INHERITED::onRelease();
}
void GrRenderTarget::onAbandon() {
- this->renderTargetPriv().didAttachStencilAttachment(nullptr);
+ SkSafeSetNull(fStencilAttachment);
INHERITED::onAbandon();
}
///////////////////////////////////////////////////////////////////////////////
-void GrRenderTargetPriv::didAttachStencilAttachment(GrStencilAttachment* stencilAttachment) {
- SkRefCnt_SafeAssign(fRenderTarget->fStencilAttachment, stencilAttachment);
-}
-
-GrStencilAttachment* GrRenderTargetPriv::attachStencilAttachment() const {
- if (fRenderTarget->fStencilAttachment) {
- return fRenderTarget->fStencilAttachment;
- }
- if (!fRenderTarget->wasDestroyed() && fRenderTarget->canAttemptStencilAttachment()) {
- fRenderTarget->getGpu()->attachStencilAttachmentToRenderTarget(fRenderTarget);
- }
- return fRenderTarget->fStencilAttachment;
+bool GrRenderTargetPriv::attachStencilAttachment(GrStencilAttachment* stencil) {
+ fRenderTarget->fStencilAttachment = stencil;
+ if (!fRenderTarget->completeStencilAttachment()) {
+ SkSafeSetNull(fRenderTarget->fStencilAttachment);
+ return false;
+ }
+ return true;
}
diff --git a/src/gpu/GrRenderTargetPriv.h b/src/gpu/GrRenderTargetPriv.h
index 59262f4b11..f4931db1db 100644
--- a/src/gpu/GrRenderTargetPriv.h
+++ b/src/gpu/GrRenderTargetPriv.h
@@ -21,12 +21,11 @@ public:
GrStencilAttachment* getStencilAttachment() const { return fRenderTarget->fStencilAttachment; }
/**
- * If this render target already has a stencil buffer, return it. Otherwise attempt to attach
- * one.
+ * Attaches the GrStencilAttachment onto the render target. If stencil is a nullptr then the
+ * currently attached GrStencilAttachment will be removed if one was previously attached. This
+ * function returns false if there were any failure in attaching the GrStencilAttachment.
*/
- GrStencilAttachment* attachStencilAttachment() const;
-
- void didAttachStencilAttachment(GrStencilAttachment*);
+ bool attachStencilAttachment(GrStencilAttachment* stencil);
private:
explicit GrRenderTargetPriv(GrRenderTarget* renderTarget) : fRenderTarget(renderTarget) {}
diff --git a/src/gpu/GrResourceProvider.cpp b/src/gpu/GrResourceProvider.cpp
index d3ab8ccfa1..bd9cc9ac6b 100644
--- a/src/gpu/GrResourceProvider.cpp
+++ b/src/gpu/GrResourceProvider.cpp
@@ -10,8 +10,11 @@
#include "GrGpu.h"
#include "GrIndexBuffer.h"
#include "GrPathRendering.h"
+#include "GrRenderTarget.h"
+#include "GrRenderTargetPriv.h"
#include "GrResourceCache.h"
#include "GrResourceKey.h"
+#include "GrStencilAttachment.h"
#include "GrVertexBuffer.h"
GR_DECLARE_STATIC_UNIQUE_KEY(gQuadIndexBufferKey);
@@ -163,3 +166,52 @@ GrBatchAtlas* GrResourceProvider::createAtlas(GrPixelConfig config,
}
return new GrBatchAtlas(texture, numPlotsX, numPlotsY);
}
+
+GrStencilAttachment* GrResourceProvider::attachStencilAttachment(GrRenderTarget* rt) {
+ SkASSERT(rt);
+ if (rt->renderTargetPriv().getStencilAttachment()) {
+ return rt->renderTargetPriv().getStencilAttachment();
+ }
+
+ if (!rt->wasDestroyed() && rt->canAttemptStencilAttachment()) {
+ GrUniqueKey sbKey;
+
+ int width = rt->width();
+ int height = rt->height();
+#if 0
+ if (this->caps()->oversizedStencilSupport()) {
+ width = SkNextPow2(width);
+ height = SkNextPow2(height);
+ }
+#endif
+ bool newStencil = false;
+ GrStencilAttachment::ComputeSharedStencilAttachmentKey(width, height,
+ rt->numStencilSamples(), &sbKey);
+ GrStencilAttachment* stencil = static_cast<GrStencilAttachment*>(
+ this->findAndRefResourceByUniqueKey(sbKey));
+ if (!stencil) {
+ // Need to try and create a new stencil
+ stencil = this->gpu()->createStencilAttachmentForRenderTarget(rt, width, height);
+ if (stencil) {
+ stencil->resourcePriv().setUniqueKey(sbKey);
+ newStencil = true;
+ }
+ }
+ if (rt->renderTargetPriv().attachStencilAttachment(stencil)) {
+ if (newStencil) {
+ // Right now we're clearing the stencil attachment 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
+ // be correct because it won't be guaranteed to clear the entire
+ // sb.
+ // We used to clear down in the GL subclass using a special purpose
+ // FBO. But iOS doesn't allow a stencil-only FBO. It reports unsupported
+ // FBO status.
+ this->gpu()->clearStencil(rt);
+ }
+ }
+ }
+ return rt->renderTargetPriv().getStencilAttachment();
+}
+
+
diff --git a/src/gpu/GrResourceProvider.h b/src/gpu/GrResourceProvider.h
index 72efab1cef..33a9f3bd12 100644
--- a/src/gpu/GrResourceProvider.h
+++ b/src/gpu/GrResourceProvider.h
@@ -16,6 +16,8 @@
class GrBatchAtlas;
class GrIndexBuffer;
class GrPath;
+class GrRenderTarget;
+class GrStencilAttachment;
class GrStrokeInfo;
class GrVertexBuffer;
class SkDescriptor;
@@ -134,6 +136,12 @@ public:
GrBatchAtlas* createAtlas(GrPixelConfig, int width, int height, int numPlotsX, int numPlotsY,
GrBatchAtlas::EvictionFunc func, void* data);
+ /**
+ * If passed in render target already has a stencil buffer, return it. Otherwise attempt to
+ * attach one.
+ */
+ GrStencilAttachment* attachStencilAttachment(GrRenderTarget* rt);
+
private:
const GrIndexBuffer* createInstancedIndexBuffer(const uint16_t* pattern,
int patternSize,
diff --git a/src/gpu/GrTest.cpp b/src/gpu/GrTest.cpp
index 4e697ff655..8d6208de79 100644
--- a/src/gpu/GrTest.cpp
+++ b/src/gpu/GrTest.cpp
@@ -255,12 +255,10 @@ private:
void onResolveRenderTarget(GrRenderTarget* target) override { return; }
- bool createStencilAttachmentForRenderTarget(GrRenderTarget*, int width, int height) override {
- return false;
- }
-
- bool attachStencilAttachmentToRenderTarget(GrStencilAttachment*, GrRenderTarget*) override {
- return false;
+ GrStencilAttachment* createStencilAttachmentForRenderTarget(const GrRenderTarget*,
+ int width,
+ int height) override {
+ return nullptr;
}
void clearStencil(GrRenderTarget* target) override {}
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index e10b951d32..c07f704d21 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -495,20 +495,7 @@ GrRenderTarget* GrGLGpu::onWrapBackendRenderTarget(const GrBackendRenderTargetDe
desc.fSampleCnt = SkTMin(wrapDesc.fSampleCnt, this->caps()->maxSampleCount());
desc.fOrigin = resolve_origin(wrapDesc.fOrigin, true);
- GrRenderTarget* tgt = new GrGLRenderTarget(this, desc, idDesc);
- if (wrapDesc.fStencilBits) {
- GrGLStencilAttachment::IDDesc sbDesc;
- GrGLStencilAttachment::Format format;
- format.fInternalFormat = GrGLStencilAttachment::kUnknownInternalFormat;
- format.fPacked = false;
- format.fStencilBits = wrapDesc.fStencilBits;
- format.fTotalBits = wrapDesc.fStencilBits;
- GrGLStencilAttachment* sb = new GrGLStencilAttachment(
- this, sbDesc, desc.fWidth, desc.fHeight, desc.fSampleCnt, format);
- tgt->renderTargetPriv().didAttachStencilAttachment(sb);
- sb->unref();
- }
- return tgt;
+ return GrGLRenderTarget::CreateWrapped(this, desc, idDesc, wrapDesc.fStencilBits);
}
////////////////////////////////////////////////////////////////////////////////
@@ -1241,7 +1228,7 @@ int GrGLGpu::getCompatibleStencilIndex(GrPixelConfig config) {
// Create Framebuffer
GrGLuint fb;
GL_CALL(GenFramebuffers(1, &fb));
- GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, fb));
+ GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, fb));
fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID;
GL_CALL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
GR_GL_COLOR_ATTACHMENT0,
@@ -1304,7 +1291,9 @@ int GrGLGpu::getCompatibleStencilIndex(GrPixelConfig config) {
return fPixelConfigToStencilIndex[config];
}
-bool GrGLGpu::createStencilAttachmentForRenderTarget(GrRenderTarget* rt, int width, int height) {
+GrStencilAttachment* GrGLGpu::createStencilAttachmentForRenderTarget(const GrRenderTarget* rt,
+ 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());
@@ -1316,14 +1305,14 @@ bool GrGLGpu::createStencilAttachmentForRenderTarget(GrRenderTarget* rt, int wid
int sIdx = this->getCompatibleStencilIndex(rt->config());
if (sIdx == kUnsupportedStencilIndex) {
- return false;
+ return nullptr;
}
if (!sbDesc.fRenderbufferID) {
GL_CALL(GenRenderbuffers(1, &sbDesc.fRenderbufferID));
}
if (!sbDesc.fRenderbufferID) {
- return false;
+ return nullptr;
}
GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, sbDesc.fRenderbufferID));
const GrGLCaps::StencilFormat& sFmt = this->glCaps().stencilFormats()[sIdx];
@@ -1346,113 +1335,13 @@ bool GrGLGpu::createStencilAttachmentForRenderTarget(GrRenderTarget* rt, int wid
// whatever sizes GL gives us. In that case we query for the size.
GrGLStencilAttachment::Format format = sFmt;
get_stencil_rb_sizes(this->glInterface(), &format);
- SkAutoTUnref<GrGLStencilAttachment> sb(
- new GrGLStencilAttachment(this, sbDesc, width, height, samples, format));
- SkAssertResult(this->attachStencilAttachmentToRenderTarget(sb, rt));
- rt->renderTargetPriv().didAttachStencilAttachment(sb);
- // This work around is currently breaking on windows 7 hd2000 bot when we bind a color buffer
-#if 0
- // Clear the stencil buffer. We use a special purpose FBO for this so that the
- // entire stencil buffer is cleared, even if it is attached to an FBO with a
- // smaller color target.
- if (0 == fStencilClearFBOID) {
- GL_CALL(GenFramebuffers(1, &fStencilClearFBOID));
- }
-
- GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, fStencilClearFBOID));
- fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID;
- fStats.incRenderTargetBinds();
- GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
- GR_GL_STENCIL_ATTACHMENT,
- GR_GL_RENDERBUFFER, sbDesc.fRenderbufferID));
- if (sFmt.fPacked) {
- GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
- GR_GL_DEPTH_ATTACHMENT,
- GR_GL_RENDERBUFFER, sbDesc.fRenderbufferID));
- }
-
- GL_CALL(ClearStencil(0));
- // Many GL implementations seem to have trouble with clearing an FBO with only
- // a stencil buffer.
- GrGLuint tempRB;
- GL_CALL(GenRenderbuffers(1, &tempRB));
- GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, tempRB));
- if (samples > 0) {
- renderbuffer_storage_msaa(fGLContext, samples, GR_GL_RGBA8, width, height);
- } else {
- GL_CALL(RenderbufferStorage(GR_GL_RENDERBUFFER, GR_GL_RGBA8, width, height));
- }
- GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
- GR_GL_COLOR_ATTACHMENT0,
- GR_GL_RENDERBUFFER, tempRB));
-
- GL_CALL(Clear(GR_GL_STENCIL_BUFFER_BIT));
-
- GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
- GR_GL_COLOR_ATTACHMENT0,
- GR_GL_RENDERBUFFER, 0));
- GL_CALL(DeleteRenderbuffers(1, &tempRB));
-
- // Unbind the SB from the FBO so that we don't keep it alive.
- GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
- GR_GL_STENCIL_ATTACHMENT,
- GR_GL_RENDERBUFFER, 0));
- if (sFmt.fPacked) {
- GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
- GR_GL_DEPTH_ATTACHMENT,
- GR_GL_RENDERBUFFER, 0));
- }
-#endif
- return true;
-}
-
-bool GrGLGpu::attachStencilAttachmentToRenderTarget(GrStencilAttachment* sb, GrRenderTarget* rt) {
- GrGLRenderTarget* glrt = static_cast<GrGLRenderTarget*>(rt);
-
- GrGLuint fbo = glrt->renderFBOID();
-
- if (nullptr == sb) {
- if (rt->renderTargetPriv().getStencilAttachment()) {
- GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
- GR_GL_STENCIL_ATTACHMENT,
- GR_GL_RENDERBUFFER, 0));
- GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
- GR_GL_DEPTH_ATTACHMENT,
- GR_GL_RENDERBUFFER, 0));
-#ifdef SK_DEBUG
- GrGLenum status;
- GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
- SkASSERT(GR_GL_FRAMEBUFFER_COMPLETE == status);
-#endif
- }
- return true;
- } else {
- GrGLStencilAttachment* glsb = static_cast<GrGLStencilAttachment*>(sb);
- GrGLuint rb = glsb->renderbufferID();
-
- fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID;
- fStats.incRenderTargetBinds();
- GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, fbo));
- GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
- GR_GL_STENCIL_ATTACHMENT,
- GR_GL_RENDERBUFFER, rb));
- if (glsb->format().fPacked) {
- GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
- GR_GL_DEPTH_ATTACHMENT,
- GR_GL_RENDERBUFFER, rb));
- } else {
- GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
- GR_GL_DEPTH_ATTACHMENT,
- GR_GL_RENDERBUFFER, 0));
- }
-
-#ifdef SK_DEBUG
- GrGLenum status;
- GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
- SkASSERT(GR_GL_FRAMEBUFFER_COMPLETE == status);
-#endif
- return true;
- }
+ GrGLStencilAttachment* stencil = new GrGLStencilAttachment(this,
+ sbDesc,
+ width,
+ height,
+ samples,
+ format);
+ return stencil;
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index fecede06c7..833f1ff7ec 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -99,6 +99,16 @@ public:
return &this->glContext();
}
+ void clearStencil(GrRenderTarget*) override;
+
+ void invalidateBoundRenderTarget() {
+ fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID;
+ }
+
+ GrStencilAttachment* createStencilAttachmentForRenderTarget(const GrRenderTarget* rt,
+ int width,
+ int height) override;
+
GrBackendObject createTestingOnlyBackendTexture(void* pixels, int w, int h,
GrPixelConfig config) const override;
bool isTestingOnlyBackendTexture(GrBackendObject id) const override;
@@ -122,9 +132,6 @@ private:
GrTexture* onWrapBackendTexture(const GrBackendTextureDesc&, GrWrapOwnership) override;
GrRenderTarget* onWrapBackendRenderTarget(const GrBackendRenderTargetDesc&,
GrWrapOwnership) override;
- bool createStencilAttachmentForRenderTarget(GrRenderTarget* rt, int width, int height) override;
- bool attachStencilAttachmentToRenderTarget(GrStencilAttachment* sb,
- GrRenderTarget* rt) override;
// Given a GrPixelConfig return the index into the stencil format array on GrGLCaps to a
// compatible stencil format.
int getCompatibleStencilIndex(GrPixelConfig config);
@@ -154,8 +161,6 @@ private:
const SkIRect& srcRect,
const SkIPoint& dstPoint) override;
- void clearStencil(GrRenderTarget*) override;
-
// binds texture unit in GL
void setTextureUnit(int unitIdx);
diff --git a/src/gpu/gl/GrGLRenderTarget.cpp b/src/gpu/gl/GrGLRenderTarget.cpp
index cb9d310010..dfb4e88ee3 100644
--- a/src/gpu/gl/GrGLRenderTarget.cpp
+++ b/src/gpu/gl/GrGLRenderTarget.cpp
@@ -7,15 +7,20 @@
#include "GrGLRenderTarget.h"
+#include "GrRenderTargetPriv.h"
#include "GrGLGpu.h"
+#include "GrGLUtil.h"
#define GPUGL static_cast<GrGLGpu*>(this->getGpu())
#define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X)
// Because this class is virtually derived from GrSurface we must explicitly call its constructor.
-GrGLRenderTarget::GrGLRenderTarget(GrGLGpu* gpu, const GrSurfaceDesc& desc, const IDDesc& idDesc)
+GrGLRenderTarget::GrGLRenderTarget(GrGLGpu* gpu,
+ const GrSurfaceDesc& desc,
+ const IDDesc& idDesc,
+ GrGLStencilAttachment* stencil)
: GrSurface(gpu, idDesc.fLifeCycle, desc)
- , INHERITED(gpu, idDesc.fLifeCycle, desc, idDesc.fSampleConfig) {
+ , INHERITED(gpu, idDesc.fLifeCycle, desc, idDesc.fSampleConfig, stencil) {
this->init(desc, idDesc);
this->registerWithCache();
}
@@ -56,10 +61,77 @@ void GrGLRenderTarget::init(const GrSurfaceDesc& desc, const IDDesc& idDesc) {
SkASSERT(fGpuMemorySize <= WorseCaseSize(desc));
}
+GrGLRenderTarget* GrGLRenderTarget::CreateWrapped(GrGLGpu* gpu,
+ const GrSurfaceDesc& desc,
+ const IDDesc& idDesc,
+ int stencilBits) {
+ GrGLStencilAttachment* sb = nullptr;
+ if (stencilBits) {
+ GrGLStencilAttachment::IDDesc sbDesc;
+ GrGLStencilAttachment::Format format;
+ format.fInternalFormat = GrGLStencilAttachment::kUnknownInternalFormat;
+ format.fPacked = false;
+ format.fStencilBits = stencilBits;
+ format.fTotalBits = stencilBits;
+ // Owndership of sb is passed to the GrRenderTarget so doesn't need to be deleted
+ sb = new GrGLStencilAttachment(gpu, sbDesc, desc.fWidth, desc.fHeight,
+ desc.fSampleCnt, format);
+ }
+ return (new GrGLRenderTarget(gpu, desc, idDesc, sb));
+}
+
size_t GrGLRenderTarget::onGpuMemorySize() const {
return fGpuMemorySize;
}
+bool GrGLRenderTarget::completeStencilAttachment() {
+ GrGLGpu* gpu = this->getGLGpu();
+ const GrGLInterface* interface = gpu->glInterface();
+ GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment();
+ if (nullptr == stencil) {
+ if (this->renderTargetPriv().getStencilAttachment()) {
+ GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
+ GR_GL_STENCIL_ATTACHMENT,
+ GR_GL_RENDERBUFFER, 0));
+ GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
+ GR_GL_DEPTH_ATTACHMENT,
+ GR_GL_RENDERBUFFER, 0));
+#ifdef SK_DEBUG
+ GrGLenum status;
+ GR_GL_CALL_RET(interface, status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
+ SkASSERT(GR_GL_FRAMEBUFFER_COMPLETE == status);
+#endif
+ }
+ return true;
+ } else {
+ const GrGLStencilAttachment* glStencil = static_cast<const GrGLStencilAttachment*>(stencil);
+ GrGLuint rb = glStencil->renderbufferID();
+
+ gpu->invalidateBoundRenderTarget();
+ gpu->stats()->incRenderTargetBinds();
+ GR_GL_CALL(interface, BindFramebuffer(GR_GL_FRAMEBUFFER, this->renderFBOID()));
+ GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
+ GR_GL_STENCIL_ATTACHMENT,
+ GR_GL_RENDERBUFFER, rb));
+ if (glStencil->format().fPacked) {
+ GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
+ GR_GL_DEPTH_ATTACHMENT,
+ GR_GL_RENDERBUFFER, rb));
+ } else {
+ GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
+ GR_GL_DEPTH_ATTACHMENT,
+ GR_GL_RENDERBUFFER, 0));
+ }
+
+#ifdef SK_DEBUG
+ GrGLenum status;
+ GR_GL_CALL_RET(interface, status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
+ SkASSERT(GR_GL_FRAMEBUFFER_COMPLETE == status);
+#endif
+ return true;
+ }
+}
+
void GrGLRenderTarget::onRelease() {
if (kBorrowed_LifeCycle != fRTLifecycle) {
if (fTexFBOID) {
@@ -84,3 +156,9 @@ void GrGLRenderTarget::onAbandon() {
fMSColorRenderbufferID = 0;
INHERITED::onAbandon();
}
+
+GrGLGpu* GrGLRenderTarget::getGLGpu() const {
+ SkASSERT(!this->wasDestroyed());
+ return static_cast<GrGLGpu*>(this->getGpu());
+}
+
diff --git a/src/gpu/gl/GrGLRenderTarget.h b/src/gpu/gl/GrGLRenderTarget.h
index 1e6dc7f767..0539a08d81 100644
--- a/src/gpu/gl/GrGLRenderTarget.h
+++ b/src/gpu/gl/GrGLRenderTarget.h
@@ -14,6 +14,7 @@
#include "SkScalar.h"
class GrGLGpu;
+class GrGLStencilAttachment;
class GrGLRenderTarget : public GrRenderTarget {
public:
@@ -29,7 +30,10 @@ public:
GrRenderTarget::SampleConfig fSampleConfig;
};
- GrGLRenderTarget(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&);
+ static GrGLRenderTarget* CreateWrapped(GrGLGpu*,
+ const GrSurfaceDesc&,
+ const IDDesc&,
+ int stencilBits);
void setViewport(const GrGLIRect& rect) { fViewport = rect; }
const GrGLIRect& getViewport() const { return fViewport; }
@@ -78,6 +82,13 @@ protected:
size_t onGpuMemorySize() const override;
private:
+ // This ctor is used only for creating wrapped render targets and is only called for the static
+ // create function CreateWrapped(...).
+ GrGLRenderTarget(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&, GrGLStencilAttachment*);
+
+ GrGLGpu* getGLGpu() const;
+ bool completeStencilAttachment() override;
+
GrGLuint fRTFBOID;
GrGLuint fTexFBOID;
GrGLuint fMSColorRenderbufferID;
diff --git a/tests/ResourceCacheTest.cpp b/tests/ResourceCacheTest.cpp
index d76da31920..6370b92490 100644
--- a/tests/ResourceCacheTest.cpp
+++ b/tests/ResourceCacheTest.cpp
@@ -78,33 +78,34 @@ static void test_stencil_buffers(skiatest::Reporter* reporter, GrContext* contex
smallDesc.fSampleCnt = 0;
GrTextureProvider* cache = context->textureProvider();
+ GrResourceProvider* resourceProvider = context->resourceProvider();
// Test that two budgeted RTs with the same desc share a stencil buffer.
SkAutoTUnref<GrTexture> smallRT0(cache->createTexture(smallDesc, true));
if (smallRT0 && smallRT0->asRenderTarget()) {
- smallRT0->asRenderTarget()->renderTargetPriv().attachStencilAttachment();
+ resourceProvider->attachStencilAttachment(smallRT0->asRenderTarget());
}
SkAutoTUnref<GrTexture> smallRT1(cache->createTexture(smallDesc, true));
if (smallRT1 && smallRT1->asRenderTarget()) {
- smallRT1->asRenderTarget()->renderTargetPriv().attachStencilAttachment();
+ resourceProvider->attachStencilAttachment(smallRT1->asRenderTarget());
}
REPORTER_ASSERT(reporter,
smallRT0 && smallRT1 &&
smallRT0->asRenderTarget() && smallRT1->asRenderTarget() &&
- smallRT0->asRenderTarget()->renderTargetPriv().getStencilAttachment() ==
- smallRT1->asRenderTarget()->renderTargetPriv().getStencilAttachment());
+ resourceProvider->attachStencilAttachment(smallRT0->asRenderTarget()) ==
+ resourceProvider->attachStencilAttachment(smallRT1->asRenderTarget()));
// An unbudgeted RT with the same desc should also share.
SkAutoTUnref<GrTexture> smallRT2(cache->createTexture(smallDesc, false));
if (smallRT2 && smallRT2->asRenderTarget()) {
- smallRT2->asRenderTarget()->renderTargetPriv().attachStencilAttachment();
+ resourceProvider->attachStencilAttachment(smallRT2->asRenderTarget());
}
REPORTER_ASSERT(reporter,
smallRT0 && smallRT2 &&
smallRT0->asRenderTarget() && smallRT2->asRenderTarget() &&
- smallRT0->asRenderTarget()->renderTargetPriv().getStencilAttachment() ==
- smallRT2->asRenderTarget()->renderTargetPriv().getStencilAttachment());
+ resourceProvider->attachStencilAttachment(smallRT0->asRenderTarget()) ==
+ resourceProvider->attachStencilAttachment(smallRT2->asRenderTarget()));
// An RT with a much larger size should not share.
GrSurfaceDesc bigDesc;
@@ -115,13 +116,13 @@ static void test_stencil_buffers(skiatest::Reporter* reporter, GrContext* contex
bigDesc.fSampleCnt = 0;
SkAutoTUnref<GrTexture> bigRT(cache->createTexture(bigDesc, false));
if (bigRT && bigRT->asRenderTarget()) {
- bigRT->asRenderTarget()->renderTargetPriv().attachStencilAttachment();
+ resourceProvider->attachStencilAttachment(bigRT->asRenderTarget());
}
REPORTER_ASSERT(reporter,
smallRT0 && bigRT &&
smallRT0->asRenderTarget() && bigRT->asRenderTarget() &&
- smallRT0->asRenderTarget()->renderTargetPriv().getStencilAttachment() !=
- bigRT->asRenderTarget()->renderTargetPriv().getStencilAttachment());
+ resourceProvider->attachStencilAttachment(smallRT0->asRenderTarget()) !=
+ resourceProvider->attachStencilAttachment(bigRT->asRenderTarget()));
if (context->caps()->maxSampleCount() >= 4) {
// An RT with a different sample count should not share.
@@ -129,7 +130,7 @@ static void test_stencil_buffers(skiatest::Reporter* reporter, GrContext* contex
smallMSAADesc.fSampleCnt = 4;
SkAutoTUnref<GrTexture> smallMSAART0(cache->createTexture(smallMSAADesc, false));
if (smallMSAART0 && smallMSAART0->asRenderTarget()) {
- smallMSAART0->asRenderTarget()->renderTargetPriv().attachStencilAttachment();
+ resourceProvider->attachStencilAttachment(smallMSAART0->asRenderTarget());
}
#ifdef SK_BUILD_FOR_ANDROID
if (!smallMSAART0) {
@@ -140,19 +141,19 @@ static void test_stencil_buffers(skiatest::Reporter* reporter, GrContext* contex
REPORTER_ASSERT(reporter,
smallRT0 && smallMSAART0 &&
smallRT0->asRenderTarget() && smallMSAART0->asRenderTarget() &&
- smallRT0->asRenderTarget()->renderTargetPriv().getStencilAttachment() !=
- smallMSAART0->asRenderTarget()->renderTargetPriv().getStencilAttachment());
+ resourceProvider->attachStencilAttachment(smallRT0->asRenderTarget()) !=
+ resourceProvider->attachStencilAttachment(smallMSAART0->asRenderTarget()));
// A second MSAA RT should share with the first MSAA RT.
SkAutoTUnref<GrTexture> smallMSAART1(cache->createTexture(smallMSAADesc, false));
if (smallMSAART1 && smallMSAART1->asRenderTarget()) {
- smallMSAART1->asRenderTarget()->renderTargetPriv().attachStencilAttachment();
+ resourceProvider->attachStencilAttachment(smallMSAART1->asRenderTarget());
}
REPORTER_ASSERT(reporter,
smallMSAART0 && smallMSAART1 &&
smallMSAART0->asRenderTarget() &&
smallMSAART1->asRenderTarget() &&
- smallMSAART0->asRenderTarget()->renderTargetPriv().getStencilAttachment() ==
- smallMSAART1->asRenderTarget()->renderTargetPriv().getStencilAttachment());
+ resourceProvider->attachStencilAttachment(smallMSAART0->asRenderTarget()) ==
+ resourceProvider->attachStencilAttachment(smallMSAART1->asRenderTarget()));
// But not one with a larger sample count should not. (Also check that the request for 4
// samples didn't get rounded up to >= 8 or else they could share.).
if (context->caps()->maxSampleCount() >= 8 &&
@@ -162,14 +163,14 @@ static void test_stencil_buffers(skiatest::Reporter* reporter, GrContext* contex
smallMSAART1.reset(cache->createTexture(smallMSAADesc, false));
SkAutoTUnref<GrTexture> smallMSAART1(cache->createTexture(smallMSAADesc, false));
if (smallMSAART1 && smallMSAART1->asRenderTarget()) {
- smallMSAART1->asRenderTarget()->renderTargetPriv().attachStencilAttachment();
+ resourceProvider->attachStencilAttachment(smallMSAART1->asRenderTarget());
}
REPORTER_ASSERT(reporter,
smallMSAART0 && smallMSAART1 &&
smallMSAART0->asRenderTarget() &&
smallMSAART1->asRenderTarget() &&
- smallMSAART0->asRenderTarget()->renderTargetPriv().getStencilAttachment() !=
- smallMSAART1->asRenderTarget()->renderTargetPriv().getStencilAttachment());
+ resourceProvider->attachStencilAttachment(smallMSAART0->asRenderTarget()) !=
+ resourceProvider->attachStencilAttachment(smallMSAART1->asRenderTarget()));
}
}
}