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
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp
index 0f32839..0ab1600 100644
--- a/src/gpu/GrClipMaskManager.cpp
+++ b/src/gpu/GrClipMaskManager.cpp
@@ -717,7 +717,8 @@
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 @@
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 3d3be74..94fcee0 100644
--- a/src/gpu/GrDrawContext.cpp
+++ b/src/gpu/GrDrawContext.cpp
@@ -63,7 +63,8 @@
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 076b626..3d5f428 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -215,7 +215,7 @@
// 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 @@
// 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 e1b8ed5..96728f3 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 @@
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 @@
}
// 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 73a5264..d8e5681 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -369,8 +369,14 @@
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 @@
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 5cb34e8..c16738e 100644
--- a/src/gpu/GrRenderTarget.cpp
+++ b/src/gpu/GrRenderTarget.cpp
@@ -55,29 +55,24 @@
}
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 59262f4..f4931db 100644
--- a/src/gpu/GrRenderTargetPriv.h
+++ b/src/gpu/GrRenderTargetPriv.h
@@ -21,12 +21,11 @@
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 d3ab8cc..bd9cc9a 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 @@
}
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 72efab1..33a9f3b 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 @@
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 4e697ff..8d6208d 100644
--- a/src/gpu/GrTest.cpp
+++ b/src/gpu/GrTest.cpp
@@ -255,12 +255,10 @@
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 e10b951..c07f704 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -495,20 +495,7 @@
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 @@
// 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 @@
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 @@
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 @@
// 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 fecede0..833f1ff 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -99,6 +99,16 @@
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 @@
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 @@
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 cb9d310..dfb4e88 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 @@
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 @@
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 1e6dc7f..0539a08 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 @@
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 @@
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;