Revert of Improve tracking of bound FBOs in GrGLGpu. (patchset #12 id:220001 of https://codereview.chromium.org/949263002/)

Reason for revert:
That one needs to be reverted to fix black boxes with GPU
raster, and GPU bot failures.

BUG=466690

Original issue's description:
> Improve tracking of bound FBOs in GrGLGpu.
>
> Committed: https://skia.googlesource.com/skia/+/d2ad8eb5801e2c8c0fa544a6a776bb46eedde2a0
>
> Committed: https://skia.googlesource.com/skia/+/b2af2d8b83ca4774c3b3bb1e49bc72605faa9589
>
> Committed: https://skia.googlesource.com/skia/+/0b70b86a7e9fda52ee7ebc1b9897eeaa09b9abef
>
> Committed: https://skia.googlesource.com/skia/+/6ba6fa15261be591f33cf0e5df7134e4fc6432ac

TBR=egdaniel@google.com
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true

Review URL: https://codereview.chromium.org/1011493002
This commit is contained in:
bsalomon 2015-03-14 12:08:51 -07:00 committed by Commit bot
parent 3700c9a2d3
commit 1e0bf7e113
8 changed files with 224 additions and 365 deletions

View File

@ -52,8 +52,6 @@ void GrGLCaps::reset() {
fDropsTileOnZeroDivide = false;
fFBFetchSupport = false;
fFBFetchNeedsCustomOutput = false;
fBindFBOToReadAndDrawForAddingAttachments = false;
fFBFetchColorName = NULL;
fFBFetchExtensionString = NULL;
@ -101,7 +99,6 @@ GrGLCaps& GrGLCaps::operator= (const GrGLCaps& caps) {
fFBFetchNeedsCustomOutput = caps.fFBFetchNeedsCustomOutput;
fFBFetchColorName = caps.fFBFetchColorName;
fFBFetchExtensionString = caps.fFBFetchExtensionString;
fBindFBOToReadAndDrawForAddingAttachments = caps.fBindFBOToReadAndDrawForAddingAttachments;
return *this;
}
@ -282,12 +279,6 @@ bool GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
this->initFSAASupport(ctxInfo, gli);
this->initStencilFormats(ctxInfo);
#ifdef SK_BUILD_FOR_MAC
// This relies on the fact that initFSAASupport() was already called.
fBindFBOToReadAndDrawForAddingAttachments = ctxInfo.isChromium() &&
this->usesMSAARenderBuffers();
#endif
/**************************************************************************
* GrDrawTargetCaps fields
**************************************************************************/

View File

@ -267,10 +267,6 @@ public:
bool fullClearIsFree() const { return fFullClearIsFree; }
bool dropsTileOnZeroDivide() const { return fDropsTileOnZeroDivide; }
bool bindFBOToReadAndDrawForAddingAttachments() const {
return fBindFBOToReadAndDrawForAddingAttachments;
}
/**
* Returns a string containing the caps info.
@ -393,7 +389,6 @@ private:
bool fDropsTileOnZeroDivide : 1;
bool fFBFetchSupport : 1;
bool fFBFetchNeedsCustomOutput : 1;
bool fBindFBOToReadAndDrawForAddingAttachments : 1;
const char* fFBFetchColorName;
const char* fFBFetchExtensionString;

View File

@ -151,6 +151,9 @@ GrGLGpu::GrGLGpu(const GrGLContext& ctx, GrContext* context)
fLastSuccessfulStencilFmtIdx = 0;
fHWProgramID = 0;
fTempSrcFBOID = 0;
fTempDstFBOID = 0;
fStencilClearFBOID = 0;
if (this->glCaps().pathRenderingSupport()) {
fPathRendering.reset(new GrGLPathRendering(this));
@ -165,17 +168,14 @@ GrGLGpu::~GrGLGpu() {
GL_CALL(UseProgram(0));
}
if (fTempSrcFBO) {
fTempSrcFBO->release(this->glInterface());
fTempSrcFBO.reset(NULL);
if (0 != fTempSrcFBOID) {
GL_CALL(DeleteFramebuffers(1, &fTempSrcFBOID));
}
if (fTempDstFBO) {
fTempDstFBO->release(this->glInterface());
fTempDstFBO.reset(NULL);
if (0 != fTempDstFBOID) {
GL_CALL(DeleteFramebuffers(1, &fTempDstFBOID));
}
if (fStencilClearFBO) {
fStencilClearFBO->release(this->glInterface());
fStencilClearFBO.reset(NULL);
if (0 != fStencilClearFBOID) {
GL_CALL(DeleteFramebuffers(1, &fStencilClearFBOID));
}
delete fProgramCache;
@ -185,19 +185,9 @@ void GrGLGpu::contextAbandoned() {
INHERITED::contextAbandoned();
fProgramCache->abandon();
fHWProgramID = 0;
if (fTempSrcFBO) {
fTempSrcFBO->abandon();
fTempSrcFBO.reset(NULL);
}
if (fTempDstFBO) {
fTempDstFBO->abandon();
fTempDstFBO.reset(NULL);
}
if (fStencilClearFBO) {
fStencilClearFBO->abandon();
fStencilClearFBO.reset(NULL);
}
fTempSrcFBOID = 0;
fTempDstFBOID = 0;
fStencilClearFBOID = 0;
if (this->glCaps().pathRenderingSupport()) {
this->glPathRendering()->abandonGpuResources();
}
@ -341,9 +331,7 @@ void GrGLGpu::onResetContext(uint32_t resetBits) {
}
if (resetBits & kRenderTarget_GrGLBackendState) {
for (size_t i = 0; i < SK_ARRAY_COUNT(fHWFBOBinding); ++i) {
fHWFBOBinding[i].invalidate();
}
fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID;
}
if (resetBits & kPathRendering_GrGLBackendState) {
@ -444,9 +432,9 @@ GrTexture* GrGLGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc) {
GrRenderTarget* GrGLGpu::onWrapBackendRenderTarget(const GrBackendRenderTargetDesc& wrapDesc) {
GrGLRenderTarget::IDDesc idDesc;
GrGLuint fboID = static_cast<GrGLuint>(wrapDesc.fRenderTargetHandle);
idDesc.fRenderFBO.reset(SkNEW_ARGS(GrGLFBO, (fboID)));
idDesc.fRTFBOID = static_cast<GrGLuint>(wrapDesc.fRenderTargetHandle);
idDesc.fMSColorRenderbufferID = 0;
idDesc.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID;
idDesc.fLifeCycle = GrGpuResource::kWrapped_LifeCycle;
GrSurfaceDesc desc;
@ -826,34 +814,34 @@ static bool renderbuffer_storage_msaa(GrGLContext& ctx,
bool GrGLGpu::createRenderTargetObjects(const GrSurfaceDesc& desc, bool budgeted, GrGLuint texID,
GrGLRenderTarget::IDDesc* idDesc) {
idDesc->fMSColorRenderbufferID = 0;
idDesc->fRTFBOID = 0;
idDesc->fTexFBOID = 0;
idDesc->fLifeCycle = budgeted ? GrGpuResource::kCached_LifeCycle :
GrGpuResource::kUncached_LifeCycle;
GrGLenum status;
GrGLenum msColorFormat = 0; // suppress warning
GrGLenum fboTarget = 0; // suppress warning
if (desc.fSampleCnt > 0 && GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType()) {
goto FAILED;
}
idDesc->fTextureFBO.reset(SkNEW_ARGS(GrGLFBO, (this->glInterface())));
if (!idDesc->fTextureFBO->isValid()) {
GL_CALL(GenFramebuffers(1, &idDesc->fTexFBOID));
if (!idDesc->fTexFBOID) {
goto FAILED;
}
// If we are using multisampling we will create two FBOS. We render to one and then resolve to
// the texture bound to the other. The exception is the IMG multisample extension. With this
// extension the texture is multisampled when rendered to and then auto-resolves it when it is
// rendered from.
if (desc.fSampleCnt > 0 && this->glCaps().usesMSAARenderBuffers()) {
idDesc->fRenderFBO.reset(SkNEW_ARGS(GrGLFBO, (this->glInterface())));
if (!idDesc->fRenderFBO->isValid()) {
goto FAILED;
}
GL_CALL(GenFramebuffers(1, &idDesc->fRTFBOID));
GL_CALL(GenRenderbuffers(1, &idDesc->fMSColorRenderbufferID));
if (!idDesc->fMSColorRenderbufferID ||
if (!idDesc->fRTFBOID ||
!idDesc->fMSColorRenderbufferID ||
!this->configToGLFormats(desc.fConfig,
// ES2 and ES3 require sized internal formats for rb storage.
kGLES_GrGLStandard == this->glStandard(),
@ -863,10 +851,12 @@ bool GrGLGpu::createRenderTargetObjects(const GrSurfaceDesc& desc, bool budgeted
goto FAILED;
}
} else {
idDesc->fRenderFBO.reset(SkRef(idDesc->fTextureFBO.get()));
idDesc->fRTFBOID = idDesc->fTexFBOID;
}
if (idDesc->fRenderFBO != idDesc->fTextureFBO) {
// below here we may bind the FBO
fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID;
if (idDesc->fRTFBOID != idDesc->fTexFBOID) {
SkASSERT(desc.fSampleCnt > 0);
GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, idDesc->fMSColorRenderbufferID));
if (!renderbuffer_storage_msaa(fGLContext,
@ -875,11 +865,12 @@ bool GrGLGpu::createRenderTargetObjects(const GrSurfaceDesc& desc, bool budgeted
desc.fWidth, desc.fHeight)) {
goto FAILED;
}
fboTarget = this->bindFBOForAddingAttachments(idDesc->fRenderFBO);
GL_CALL(FramebufferRenderbuffer(fboTarget,
GR_GL_COLOR_ATTACHMENT0,
GR_GL_RENDERBUFFER,
idDesc->fMSColorRenderbufferID));
fStats.incRenderTargetBinds();
GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, idDesc->fRTFBOID));
GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
GR_GL_COLOR_ATTACHMENT0,
GR_GL_RENDERBUFFER,
idDesc->fMSColorRenderbufferID));
if ((desc.fFlags & kCheckAllocation_GrSurfaceFlag) ||
!this->glCaps().isConfigVerifiedColorAttachment(desc.fConfig)) {
GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
@ -889,22 +880,23 @@ bool GrGLGpu::createRenderTargetObjects(const GrSurfaceDesc& desc, bool budgeted
fGLContext.caps()->markConfigAsValidColorAttachment(desc.fConfig);
}
}
fboTarget = this->bindFBOForAddingAttachments(idDesc->fTextureFBO);
fStats.incRenderTargetBinds();
GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, idDesc->fTexFBOID));
if (this->glCaps().usesImplicitMSAAResolve() && desc.fSampleCnt > 0) {
GL_CALL(FramebufferTexture2DMultisample(fboTarget,
GL_CALL(FramebufferTexture2DMultisample(GR_GL_FRAMEBUFFER,
GR_GL_COLOR_ATTACHMENT0,
GR_GL_TEXTURE_2D,
texID, 0, desc.fSampleCnt));
} else {
GL_CALL(FramebufferTexture2D(fboTarget,
GL_CALL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
GR_GL_COLOR_ATTACHMENT0,
GR_GL_TEXTURE_2D,
texID, 0));
}
if ((desc.fFlags & kCheckAllocation_GrSurfaceFlag) ||
!this->glCaps().isConfigVerifiedColorAttachment(desc.fConfig)) {
GL_CALL_RET(status, CheckFramebufferStatus(fboTarget));
GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
goto FAILED;
}
@ -917,11 +909,11 @@ FAILED:
if (idDesc->fMSColorRenderbufferID) {
GL_CALL(DeleteRenderbuffers(1, &idDesc->fMSColorRenderbufferID));
}
if (idDesc->fRenderFBO) {
idDesc->fRenderFBO->release(this->glInterface());
if (idDesc->fRTFBOID != idDesc->fTexFBOID) {
GL_CALL(DeleteFramebuffers(1, &idDesc->fRTFBOID));
}
if (idDesc->fTextureFBO) {
idDesc->fTextureFBO->release(this->glInterface());
if (idDesc->fTexFBOID) {
GL_CALL(DeleteFramebuffers(1, &idDesc->fTexFBOID));
}
return false;
}
@ -1194,17 +1186,18 @@ bool GrGLGpu::createStencilBufferForRenderTarget(GrRenderTarget* rt, int width,
// 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 (!fStencilClearFBO) {
fStencilClearFBO.reset(SkNEW_ARGS(GrGLFBO, (this->glInterface())));
if (0 == fStencilClearFBOID) {
GL_CALL(GenFramebuffers(1, &fStencilClearFBOID));
}
SkASSERT(fStencilClearFBO->isValid());
GrGLenum fboTarget = this->bindFBOForAddingAttachments(fStencilClearFBO);
GL_CALL(FramebufferRenderbuffer(fboTarget,
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(fboTarget,
GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
GR_GL_DEPTH_ATTACHMENT,
GR_GL_RENDERBUFFER, sbDesc.fRenderbufferID));
}
@ -1213,11 +1206,11 @@ bool GrGLGpu::createStencilBufferForRenderTarget(GrRenderTarget* rt, int width,
GL_CALL(Clear(GR_GL_STENCIL_BUFFER_BIT));
// Unbind the SB from the FBO so that we don't keep it alive.
GL_CALL(FramebufferRenderbuffer(fboTarget,
GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
GR_GL_STENCIL_ATTACHMENT,
GR_GL_RENDERBUFFER, 0));
if (sFmt.fPacked) {
GL_CALL(FramebufferRenderbuffer(fboTarget,
GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
GR_GL_DEPTH_ATTACHMENT,
GR_GL_RENDERBUFFER, 0));
}
@ -1237,6 +1230,9 @@ bool GrGLGpu::createStencilBufferForRenderTarget(GrRenderTarget* rt, int width,
bool GrGLGpu::attachStencilBufferToRenderTarget(GrStencilBuffer* sb, GrRenderTarget* rt) {
GrGLRenderTarget* glrt = static_cast<GrGLRenderTarget*>(rt);
GrGLuint fbo = glrt->renderFBOID();
if (NULL == sb) {
if (rt->renderTargetPriv().getStencilBuffer()) {
GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
@ -1256,17 +1252,18 @@ bool GrGLGpu::attachStencilBufferToRenderTarget(GrStencilBuffer* sb, GrRenderTar
GrGLStencilBuffer* glsb = static_cast<GrGLStencilBuffer*>(sb);
GrGLuint rb = glsb->renderbufferID();
GrGLenum fboTarget = this->bindFBOForAddingAttachments(glrt->renderFBO());
GL_CALL(FramebufferRenderbuffer(fboTarget,
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(fboTarget,
GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
GR_GL_DEPTH_ATTACHMENT,
GR_GL_RENDERBUFFER, rb));
} else {
GL_CALL(FramebufferRenderbuffer(fboTarget,
GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
GR_GL_DEPTH_ATTACHMENT,
GR_GL_RENDERBUFFER, 0));
}
@ -1275,13 +1272,13 @@ bool GrGLGpu::attachStencilBufferToRenderTarget(GrStencilBuffer* sb, GrRenderTar
if (!this->glCaps().isColorConfigAndStencilFormatVerified(rt->config(), glsb->format())) {
GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
GL_CALL(FramebufferRenderbuffer(fboTarget,
GR_GL_STENCIL_ATTACHMENT,
GR_GL_RENDERBUFFER, 0));
GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
GR_GL_STENCIL_ATTACHMENT,
GR_GL_RENDERBUFFER, 0));
if (glsb->format().fPacked) {
GL_CALL(FramebufferRenderbuffer(fboTarget,
GR_GL_DEPTH_ATTACHMENT,
GR_GL_RENDERBUFFER, 0));
GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
GR_GL_DEPTH_ATTACHMENT,
GR_GL_RENDERBUFFER, 0));
}
return false;
} else {
@ -1426,7 +1423,7 @@ bool GrGLGpu::flushGLState(const DrawArgs& args, bool isLineDraw) {
// This must come after textures are flushed because a texture may need
// to be msaa-resolved (which will modify bound FBO state).
this->prepareToDrawToRenderTarget(glRT, NULL);
this->flushRenderTarget(glRT, NULL);
return true;
}
@ -1523,7 +1520,7 @@ void GrGLGpu::onClear(GrRenderTarget* target, const SkIRect* rect, GrColor color
}
}
this->prepareToDrawToRenderTarget(glRT, rect);
this->flushRenderTarget(glRT, rect);
GrScissorState scissorState;
if (rect) {
scissorState.set(*rect);
@ -1551,36 +1548,40 @@ void GrGLGpu::discard(GrRenderTarget* renderTarget) {
}
GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(renderTarget);
GrGLenum fboTarget = this->bindFBO(kDraw_FBOBinding, glRT->renderFBO());
if (renderTarget->getUniqueID() != fHWBoundRenderTargetUniqueID) {
fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID;
fStats.incRenderTargetBinds();
GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, glRT->renderFBOID()));
}
switch (this->glCaps().invalidateFBType()) {
case GrGLCaps::kNone_InvalidateFBType:
SkFAIL("Should never get here.");
break;
case GrGLCaps::kInvalidate_InvalidateFBType:
if (glRT->renderFBO()->isDefaultFramebuffer()) {
if (0 == glRT->renderFBOID()) {
// When rendering to the default framebuffer the legal values for attachments
// are GL_COLOR, GL_DEPTH, GL_STENCIL, ... rather than the various FBO attachment
// types.
static const GrGLenum attachments[] = { GR_GL_COLOR };
GL_CALL(InvalidateFramebuffer(fboTarget, SK_ARRAY_COUNT(attachments),
GL_CALL(InvalidateFramebuffer(GR_GL_FRAMEBUFFER, SK_ARRAY_COUNT(attachments),
attachments));
} else {
static const GrGLenum attachments[] = { GR_GL_COLOR_ATTACHMENT0 };
GL_CALL(InvalidateFramebuffer(fboTarget, SK_ARRAY_COUNT(attachments),
GL_CALL(InvalidateFramebuffer(GR_GL_FRAMEBUFFER, SK_ARRAY_COUNT(attachments),
attachments));
}
break;
case GrGLCaps::kDiscard_InvalidateFBType: {
if (glRT->renderFBO()->isDefaultFramebuffer()) {
if (0 == glRT->renderFBOID()) {
// When rendering to the default framebuffer the legal values for attachments
// are GL_COLOR, GL_DEPTH, GL_STENCIL, ... rather than the various FBO attachment
// types. See glDiscardFramebuffer() spec.
static const GrGLenum attachments[] = { GR_GL_COLOR };
GL_CALL(DiscardFramebuffer(fboTarget, SK_ARRAY_COUNT(attachments),
GL_CALL(DiscardFramebuffer(GR_GL_FRAMEBUFFER, SK_ARRAY_COUNT(attachments),
attachments));
} else {
static const GrGLenum attachments[] = { GR_GL_COLOR_ATTACHMENT0 };
GL_CALL(DiscardFramebuffer(fboTarget, SK_ARRAY_COUNT(attachments),
GL_CALL(DiscardFramebuffer(GR_GL_FRAMEBUFFER, SK_ARRAY_COUNT(attachments),
attachments));
}
break;
@ -1595,7 +1596,7 @@ void GrGLGpu::clearStencil(GrRenderTarget* target) {
return;
}
GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(target);
this->prepareToDrawToRenderTarget(glRT, &SkIRect::EmptyIRect());
this->flushRenderTarget(glRT, &SkIRect::EmptyIRect());
this->disableScissor();
@ -1631,7 +1632,7 @@ void GrGLGpu::onClearStencilClip(GrRenderTarget* target, const SkIRect& rect, bo
value = 0;
}
GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(target);
this->prepareToDrawToRenderTarget(glRT, &SkIRect::EmptyIRect());
this->flushRenderTarget(glRT, &SkIRect::EmptyIRect());
GrScissorState scissorState;
scissorState.set(rect);
@ -1701,13 +1702,22 @@ bool GrGLGpu::onReadPixels(GrRenderTarget* target,
// resolve the render target if necessary
GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(target);
if (tgt->getResolveType() == GrGLRenderTarget::kCantResolve_ResolveType) {
return false;
switch (tgt->getResolveType()) {
case GrGLRenderTarget::kCantResolve_ResolveType:
return false;
case GrGLRenderTarget::kAutoResolves_ResolveType:
this->flushRenderTarget(static_cast<GrGLRenderTarget*>(target), &SkIRect::EmptyIRect());
break;
case GrGLRenderTarget::kCanResolve_ResolveType:
this->onResolveRenderTarget(tgt);
// we don't track the state of the READ FBO ID.
fStats.incRenderTargetBinds();
GL_CALL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
tgt->textureFBOID()));
break;
default:
SkFAIL("Unknown resolve type");
}
if (tgt->getResolveType() == GrGLRenderTarget::kCanResolve_ResolveType) {
this->onResolveRenderTarget(tgt);
}
this->bindFBO(kRead_FBOBinding, tgt->textureFBO());
const GrGLIRect& glvp = tgt->getViewport();
@ -1772,8 +1782,7 @@ bool GrGLGpu::onReadPixels(GrRenderTarget* target,
}
}
} else {
SkASSERT(readDst != buffer);
SkASSERT(rowBytes != tightRowBytes);
SkASSERT(readDst != buffer); SkASSERT(rowBytes != tightRowBytes);
// copy from readDst to buffer while flipping y
// const int halfY = height >> 1;
const char* src = reinterpret_cast<const char*>(readDst);
@ -1794,67 +1803,34 @@ bool GrGLGpu::onReadPixels(GrRenderTarget* target,
return true;
}
GrGLenum GrGLGpu::bindFBO(FBOBinding binding, const GrGLFBO* fbo) {
SkASSERT(fbo);
SkASSERT(fbo->isValid());
GrGLenum target;
HWFBOBinding* hwFBOState;
if (!this->glCaps().usesMSAARenderBuffers()) {
target = GR_GL_FRAMEBUFFER;
hwFBOState = &fHWFBOBinding[0];
} else {
target = kDraw_FBOBinding == binding ? GR_GL_DRAW_FRAMEBUFFER : GR_GL_READ_FRAMEBUFFER;
hwFBOState = &fHWFBOBinding[binding];
}
void GrGLGpu::flushRenderTarget(GrGLRenderTarget* target, const SkIRect* bound) {
if (hwFBOState->fFBO != fbo) {
fStats.incRenderTargetBinds();
GL_CALL(BindFramebuffer(target, fbo->fboID()));
hwFBOState->fFBO.reset(SkRef(fbo));
}
return target;
}
GrGLenum GrGLGpu::bindFBOForAddingAttachments(const GrGLFBO* fbo) {
if (this->glCaps().bindFBOToReadAndDrawForAddingAttachments()) {
if (fHWFBOBinding[kDraw_FBOBinding].fFBO != fbo ||
fHWFBOBinding[kRead_FBOBinding].fFBO != fbo) {
fStats.incRenderTargetBinds();
GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, fbo->fboID()));
fHWFBOBinding[kDraw_FBOBinding].fFBO.reset(SkRef(fbo));
fHWFBOBinding[kRead_FBOBinding].fFBO.reset(SkRef(fbo));
}
return GR_GL_FRAMEBUFFER;
} else {
return this->bindFBO(kDraw_FBOBinding, fbo);
}
}
void GrGLGpu::setViewport(const GrGLIRect& viewport) {
if (viewport != fHWViewport) {
viewport.pushToGLViewport(this->glInterface());
fHWViewport = viewport;
}
}
void GrGLGpu::prepareToDrawToRenderTarget(GrGLRenderTarget* target, const SkIRect* bound) {
SkASSERT(target);
this->bindFBO(kDraw_FBOBinding, target->renderFBO());
uint32_t rtID = target->getUniqueID();
if (fHWBoundRenderTargetUniqueID != rtID) {
fStats.incRenderTargetBinds();
GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, target->renderFBOID()));
#ifdef SK_DEBUG
// don't do this check in Chromium -- this is causing
// lots of repeated command buffer flushes when the compositor is
// rendering with Ganesh, which is really slow; even too slow for
// Debug mode.
if (!this->glContext().isChromium()) {
GrGLenum status;
GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
SkDebugf("GrGLGpu::flushRenderTarget glCheckFramebufferStatus %x\n", status);
// don't do this check in Chromium -- this is causing
// lots of repeated command buffer flushes when the compositor is
// rendering with Ganesh, which is really slow; even too slow for
// Debug mode.
if (!this->glContext().isChromium()) {
GrGLenum status;
GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
SkDebugf("GrGLGpu::flushRenderTarget glCheckFramebufferStatus %x\n", status);
}
}
#endif
fHWBoundRenderTargetUniqueID = rtID;
const GrGLIRect& vp = target->getViewport();
if (fHWViewport != vp) {
vp.pushToGLViewport(this->glInterface());
fHWViewport = vp;
}
}
#endif
this->setViewport(target->getViewport());
if (NULL == bound || !bound->isEmpty()) {
target->flagAsNeedingResolve(bound);
}
@ -1943,7 +1919,7 @@ void GrGLGpu::onStencilPath(const GrPath* path, const StencilPathState& state) {
this->glPathRendering()->setProjectionMatrix(*state.fViewMatrix, size, rt->origin());
this->flushScissor(*state.fScissor, rt->getViewport(), rt->origin());
this->flushHWAAState(rt, state.fUseHWAA, false);
this->prepareToDrawToRenderTarget(rt, NULL);
this->flushRenderTarget(rt, NULL);
fPathRendering->stencilPath(path, *state.fStencil);
}
@ -1976,9 +1952,14 @@ void GrGLGpu::onResolveRenderTarget(GrRenderTarget* target) {
if (rt->needsResolve()) {
// Some extensions automatically resolves the texture when it is read.
if (this->glCaps().usesMSAARenderBuffers()) {
SkASSERT(rt->textureFBO() != rt->renderFBO());
this->bindFBO(kRead_FBOBinding, rt->renderFBO());
this->bindFBO(kDraw_FBOBinding, rt->textureFBO());
SkASSERT(rt->textureFBOID() != rt->renderFBOID());
fStats.incRenderTargetBinds();
fStats.incRenderTargetBinds();
GL_CALL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, rt->renderFBOID()));
GL_CALL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER, rt->textureFBOID()));
// make sure we go through flushRenderTarget() since we've modified
// the bound DRAW FBO ID.
fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID;
const GrGLIRect& vp = rt->getViewport();
const SkIRect dirtyRect = rt->getResolveRect();
@ -2541,13 +2522,13 @@ inline bool can_copy_texsubimage(const GrSurface* dst,
const GrGLRenderTarget* dstRT = static_cast<const GrGLRenderTarget*>(dst->asRenderTarget());
// If dst is multisampled (and uses an extension where there is a separate MSAA renderbuffer)
// then we don't want to copy to the texture but to the MSAA buffer.
if (dstRT && dstRT->renderFBO() != dstRT->textureFBO()) {
if (dstRT && dstRT->renderFBOID() != dstRT->textureFBOID()) {
return false;
}
const GrGLRenderTarget* srcRT = static_cast<const GrGLRenderTarget*>(src->asRenderTarget());
// If the src is multisampled (and uses an extension where there is a separate MSAA
// renderbuffer) then it is an invalid operation to call CopyTexSubImage
if (srcRT && srcRT->renderFBO() != srcRT->textureFBO()) {
if (srcRT && srcRT->renderFBOID() != srcRT->textureFBOID()) {
return false;
}
if (gpu->glCaps().isConfigRenderable(src->config(), src->desc().fSampleCnt > 0) &&
@ -2564,31 +2545,22 @@ inline bool can_copy_texsubimage(const GrSurface* dst,
// If a temporary FBO was created, its non-zero ID is returned. The viewport that the copy rect is
// relative to is output.
GrGLGpu::FBOBinding GrGLGpu::bindSurfaceAsFBOForCopy(GrSurface* surface, FBOBinding binding,
GrGLIRect* viewport) {
GrGLuint GrGLGpu::bindSurfaceAsFBO(GrSurface* surface, GrGLenum fboTarget, GrGLIRect* viewport,
TempFBOTarget tempFBOTarget) {
GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(surface->asRenderTarget());
if (NULL == rt) {
SkASSERT(surface->asTexture());
GrGLuint texID = static_cast<GrGLTexture*>(surface->asTexture())->textureID();
GrGLFBO* tempFBO;
GrGLuint* tempFBOID;
tempFBOID = kSrc_TempFBOTarget == tempFBOTarget ? &fTempSrcFBOID : &fTempDstFBOID;
if (kRead_FBOBinding == binding) {
if (!fTempSrcFBO) {
fTempSrcFBO.reset(SkNEW_ARGS(GrGLFBO, (this->glInterface())));
SkASSERT(fTempSrcFBO->isValid());
}
tempFBO = fTempSrcFBO;
} else {
SkASSERT(kDraw_FBOBinding == binding);
if (!fTempDstFBO) {
fTempDstFBO.reset(SkNEW_ARGS(GrGLFBO, (this->glInterface())));
SkASSERT(fTempDstFBO->isValid());
}
tempFBO = fTempDstFBO;
if (0 == *tempFBOID) {
GR_GL_CALL(this->glInterface(), GenFramebuffers(1, tempFBOID));
}
GrGLenum target = this->bindFBO(binding, tempFBO);
GR_GL_CALL(this->glInterface(), FramebufferTexture2D(target,
fStats.incRenderTargetBinds();
GR_GL_CALL(this->glInterface(), BindFramebuffer(fboTarget, *tempFBOID));
GR_GL_CALL(this->glInterface(), FramebufferTexture2D(fboTarget,
GR_GL_COLOR_ATTACHMENT0,
GR_GL_TEXTURE_2D,
texID,
@ -2597,21 +2569,18 @@ GrGLGpu::FBOBinding GrGLGpu::bindSurfaceAsFBOForCopy(GrSurface* surface, FBOBind
viewport->fBottom = 0;
viewport->fWidth = surface->width();
viewport->fHeight = surface->height();
return binding;
return *tempFBOID;
} else {
this->bindFBO(binding, rt->renderFBO());
GrGLuint tempFBOID = 0;
fStats.incRenderTargetBinds();
GR_GL_CALL(this->glInterface(), BindFramebuffer(fboTarget, rt->renderFBOID()));
*viewport = rt->getViewport();
return kInvalidFBOBinding;
return tempFBOID;
}
}
void GrGLGpu::unbindSurfaceAsFBOForCopy(FBOBinding binding) {
if (kInvalidFBOBinding == binding) {
return;
}
GrGLFBO* tempFBO = kDraw_FBOBinding == binding ? fTempSrcFBO : fTempDstFBO;
GrGLenum target = this->bindFBO(binding, tempFBO);
GR_GL_CALL(this->glInterface(), FramebufferTexture2D(target,
void GrGLGpu::unbindTextureFromFBO(GrGLenum fboTarget) {
GR_GL_CALL(this->glInterface(), FramebufferTexture2D(fboTarget,
GR_GL_COLOR_ATTACHMENT0,
GR_GL_TEXTURE_2D,
0,
@ -2642,7 +2611,7 @@ bool GrGLGpu::initCopySurfaceDstDesc(const GrSurface* src, GrSurfaceDesc* desc)
}
const GrGLRenderTarget* srcRT = static_cast<const GrGLRenderTarget*>(src->asRenderTarget());
if (srcRT && srcRT->renderFBO() != srcRT->textureFBO()) {
if (srcRT && srcRT->renderFBOID() != srcRT->textureFBOID()) {
// It's illegal to call CopyTexSubImage2D on a MSAA renderbuffer. Set up for FBO blit or
// fail.
if (this->caps()->isConfigRenderable(src->config(), false)) {
@ -2667,10 +2636,13 @@ bool GrGLGpu::copySurface(GrSurface* dst,
const SkIPoint& dstPoint) {
bool copied = false;
if (can_copy_texsubimage(dst, src, this)) {
GrGLuint srcFBO;
GrGLIRect srcVP;
FBOBinding srcFBOBinding = this->bindSurfaceAsFBOForCopy(src, kRead_FBOBinding, &srcVP);
srcFBO = this->bindSurfaceAsFBO(src, GR_GL_FRAMEBUFFER, &srcVP, kSrc_TempFBOTarget);
GrGLTexture* dstTex = static_cast<GrGLTexture*>(dst->asTexture());
SkASSERT(dstTex);
// We modified the bound FBO
fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID;
GrGLIRect srcGLRect;
srcGLRect.setRelativeTo(srcVP,
srcRect.fLeft,
@ -2692,7 +2664,9 @@ bool GrGLGpu::copySurface(GrSurface* dst,
srcGLRect.fLeft, srcGLRect.fBottom,
srcGLRect.fWidth, srcGLRect.fHeight));
copied = true;
this->unbindSurfaceAsFBOForCopy(srcFBOBinding);
if (srcFBO) {
this->unbindTextureFromFBO(GR_GL_FRAMEBUFFER);
}
} else if (can_blit_framebuffer(dst, src, this)) {
SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY,
srcRect.width(), srcRect.height());
@ -2702,11 +2676,16 @@ bool GrGLGpu::copySurface(GrSurface* dst,
}
if (!selfOverlap) {
GrGLuint dstFBO;
GrGLuint srcFBO;
GrGLIRect dstVP;
GrGLIRect srcVP;
FBOBinding dstFBOBinding = this->bindSurfaceAsFBOForCopy(dst, kDraw_FBOBinding, &dstVP);
FBOBinding srcFBOBinding = this->bindSurfaceAsFBOForCopy(src, kRead_FBOBinding, &srcVP);
dstFBO = this->bindSurfaceAsFBO(dst, GR_GL_DRAW_FRAMEBUFFER, &dstVP,
kDst_TempFBOTarget);
srcFBO = this->bindSurfaceAsFBO(src, GR_GL_READ_FRAMEBUFFER, &srcVP,
kSrc_TempFBOTarget);
// We modified the bound FBO
fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID;
GrGLIRect srcGLRect;
GrGLIRect dstGLRect;
srcGLRect.setRelativeTo(srcVP,
@ -2744,8 +2723,12 @@ bool GrGLGpu::copySurface(GrSurface* dst,
dstGLRect.fLeft + dstGLRect.fWidth,
dstGLRect.fBottom + dstGLRect.fHeight,
GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
this->unbindSurfaceAsFBOForCopy(dstFBOBinding);
this->unbindSurfaceAsFBOForCopy(srcFBOBinding);
if (dstFBO) {
this->unbindTextureFromFBO(GR_GL_DRAW_FRAMEBUFFER);
}
if (srcFBO) {
this->unbindTextureFromFBO(GR_GL_READ_FRAMEBUFFER);
}
copied = true;
}
}

View File

@ -246,28 +246,9 @@ private:
// ensures that such operations don't negatively interact with tracking bound textures.
void setScratchTextureUnit();
// Binds the render target, sets the viewport, tracks dirty are for resolve, and tracks whether
// mip maps need rebuilding. bounds is region that may be modified by the draw. NULL means whole
// target. Can be an empty rect.
void prepareToDrawToRenderTarget(GrGLRenderTarget*, const SkIRect* bounds);
// On older GLs there may not be separate FBO bindings for draw and read. In that case these
// alias each other.
enum FBOBinding {
kDraw_FBOBinding, // drawing or dst of blit
kRead_FBOBinding, // src of blit, read pixels.
kLast_FBOBinding = kRead_FBOBinding
};
static const int kFBOBindingCnt = kLast_FBOBinding + 1;
// binds the FBO and returns the GL enum of the framebuffer target it was bound to.
GrGLenum bindFBO(FBOBinding, const GrGLFBO*);
// This version invokes a workaround for a bug in Chromium. It should be called before
// attachments are changed on a FBO.
GrGLenum bindFBOForAddingAttachments(const GrGLFBO*);
void setViewport(const GrGLIRect& viewport);
// bounds is region that may be modified and therefore has to be resolved.
// NULL means whole target. Can be an empty rect.
void flushRenderTarget(GrGLRenderTarget*, const SkIRect* bounds);
void flushStencil(const GrStencilSettings&);
void flushHWAAState(GrRenderTarget* rt, bool useHWAA, bool isLineDraw);
@ -300,14 +281,15 @@ private:
bool createRenderTargetObjects(const GrSurfaceDesc&, bool budgeted, GrGLuint texID,
GrGLRenderTarget::IDDesc*);
static const FBOBinding kInvalidFBOBinding = static_cast<FBOBinding>(-1);
enum TempFBOTarget {
kSrc_TempFBOTarget,
kDst_TempFBOTarget
};
// Binds a surface as an FBO. A temporary FBO ID may be used if the surface is not already
// a render target. Afterwards unbindSurfaceAsFBOForCopy must be called with the value returned.
FBOBinding bindSurfaceAsFBOForCopy(GrSurface*, FBOBinding, GrGLIRect* viewport);
GrGLuint bindSurfaceAsFBO(GrSurface* surface, GrGLenum fboTarget, GrGLIRect* viewport,
TempFBOTarget tempFBOTarget);
// Must be matched with bindSurfaceAsFBOForCopy.
void unbindSurfaceAsFBOForCopy(FBOBinding);
void unbindTextureFromFBO(GrGLenum fboTarget);
GrGLContext fGLContext;
@ -327,9 +309,10 @@ private:
kUnknown_TriState
};
SkAutoTUnref<GrGLFBO> fTempSrcFBO;
SkAutoTUnref<GrGLFBO> fTempDstFBO;
SkAutoTUnref<GrGLFBO> fStencilClearFBO;
GrGLuint fTempSrcFBOID;
GrGLuint fTempDstFBOID;
GrGLuint fStencilClearFBOID;
// last scissor / viewport scissor state seen by the GL.
struct {
@ -475,14 +458,9 @@ private:
GrPipelineBuilder::DrawFace fHWDrawFace;
TriState fHWWriteToColor;
TriState fHWDitherEnabled;
uint32_t fHWBoundRenderTargetUniqueID;
SkTArray<uint32_t, true> fHWBoundTextureUniqueIDs;
// Track fbo binding state.
struct HWFBOBinding {
SkAutoTUnref<const GrGLFBO> fFBO;
void invalidate() { fFBO.reset(NULL); }
} fHWFBOBinding[kFBOBindingCnt];
///@}
// we record what stencil format worked last time to hopefully exit early

View File

@ -440,8 +440,7 @@ GrGLvoid GR_GL_FUNCTION_TYPE noOpGLBindFragDataLocationIndexed(GrGLuint program,
GrGLenum GR_GL_FUNCTION_TYPE noOpGLCheckFramebufferStatus(GrGLenum target) {
GrAlwaysAssert(GR_GL_FRAMEBUFFER == target || GR_GL_READ_FRAMEBUFFER == target ||
GR_GL_DRAW_FRAMEBUFFER == target);
GrAlwaysAssert(GR_GL_FRAMEBUFFER == target);
return GR_GL_FRAMEBUFFER_COMPLETE;
}

View File

@ -9,20 +9,8 @@
#include "GrGLGpu.h"
void GrGLFBO::release(const GrGLInterface* gl) {
SkASSERT(gl);
if (this->isValid()) {
GR_GL_CALL(gl, DeleteFramebuffers(1, &fID));
fIsValid = false;
}
}
void GrGLFBO::abandon() { fIsValid = false; }
//////////////////////////////////////////////////////////////////////////////
#define GLGPU static_cast<GrGLGpu*>(this->getGpu())
#define GL_CALL(X) GR_GL_CALL(GLGPU->glInterface(), X)
#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)
@ -40,10 +28,8 @@ GrGLRenderTarget::GrGLRenderTarget(GrGLGpu* gpu, const GrSurfaceDesc& desc, cons
}
void GrGLRenderTarget::init(const GrSurfaceDesc& desc, const IDDesc& idDesc) {
fRenderFBO.reset(SkRef(idDesc.fRenderFBO.get()));
fTextureFBO.reset(SkSafeRef(idDesc.fTextureFBO.get()));
SkASSERT(fRenderFBO->isValid());
SkASSERT(!fTextureFBO || fTextureFBO->isValid());
fRTFBOID = idDesc.fRTFBOID;
fTexFBOID = idDesc.fTexFBOID;
fMSColorRenderbufferID = idDesc.fMSColorRenderbufferID;
fIsWrapped = kWrapped_LifeCycle == idDesc.fLifeCycle;
@ -54,7 +40,7 @@ void GrGLRenderTarget::init(const GrSurfaceDesc& desc, const IDDesc& idDesc) {
// We own one color value for each MSAA sample.
fColorValuesPerPixel = SkTMax(1, fDesc.fSampleCnt);
if (fTextureFBO && fTextureFBO != fRenderFBO) {
if (fTexFBOID != fRTFBOID) {
// If we own the resolve buffer then that is one more sample per pixel.
fColorValuesPerPixel += 1;
}
@ -70,42 +56,27 @@ size_t GrGLRenderTarget::onGpuMemorySize() const {
void GrGLRenderTarget::onRelease() {
if (!fIsWrapped) {
const GrGLInterface* gl = GLGPU->glInterface();
if (fRenderFBO) {
fRenderFBO->release(gl);
fRenderFBO.reset(NULL);
if (fTexFBOID) {
GL_CALL(DeleteFramebuffers(1, &fTexFBOID));
}
if (fTextureFBO) {
fTextureFBO->release(gl);
fTextureFBO.reset(NULL);
if (fRTFBOID && fRTFBOID != fTexFBOID) {
GL_CALL(DeleteFramebuffers(1, &fRTFBOID));
}
if (fMSColorRenderbufferID) {
GL_CALL(DeleteRenderbuffers(1, &fMSColorRenderbufferID));
fMSColorRenderbufferID = 0;
}
} else {
if (fRenderFBO) {
fRenderFBO->abandon();
fRenderFBO.reset(NULL);
}
if (fTextureFBO) {
fTextureFBO->abandon();
fTextureFBO.reset(NULL);
}
fMSColorRenderbufferID = 0;
}
fRTFBOID = 0;
fTexFBOID = 0;
fMSColorRenderbufferID = 0;
fIsWrapped = false;
INHERITED::onRelease();
}
void GrGLRenderTarget::onAbandon() {
if (fRenderFBO) {
fRenderFBO->abandon();
fRenderFBO.reset(NULL);
}
if (fTextureFBO) {
fTextureFBO->abandon();
fTextureFBO.reset(NULL);
}
fRTFBOID = 0;
fTexFBOID = 0;
fMSColorRenderbufferID = 0;
fIsWrapped = false;
INHERITED::onAbandon();
}

View File

@ -15,59 +15,15 @@
class GrGLGpu;
/** Represents a GL FBO object. It has a gen ID which is valid whenever the FBO ID owned by the
object is valid. The gen IDs are not recycled after FBOs are freed, unlike FBO IDs, and so
can be used to uniquely identity FBO ID instantiations. If this object owns an FBO ID, the ID
must be deleted or abandoned before this object is freed. FBO IDs should never be owned by
more than one instance. */
class GrGLFBO : public SkNVRefCnt<GrGLFBO> {
public:
SK_DECLARE_INST_COUNT(GrGLFBO);
/** Initializes to an FBO. The FBO should already be valid in the relevant GL context. */
GrGLFBO(GrGLint id) : fID(id), fIsValid(true) {}
/** Initializes to an FBO ID generated using the interface. */
GrGLFBO(const GrGLInterface* gl) {
GR_GL_CALL(gl, GenFramebuffers(1, &fID));
fIsValid = SkToBool(fID);
}
~GrGLFBO() { SkASSERT(!this->isValid()); }
/** Has this object been released or abandoned? */
bool isValid() const { return fIsValid; }
GrGLint fboID() const { SkASSERT(this->isValid()); return fID; }
bool isDefaultFramebuffer() const { return fIsValid && 0 == fID; }
/** Give up ownership of the FBO ID owned by this object without deleting it. */
void abandon();
/** Delete and give up ownership of the the FBO ID if it is valid. */
void release(const GrGLInterface*);
private:
static uint32_t NextGenID() {
static int32_t gGenID = SK_InvalidGenID + 1;
return static_cast<uint32_t>(sk_atomic_inc(&gGenID));
}
GrGLuint fID;
bool fIsValid;
typedef SkRefCnt INHERITED;
};
//////////////////////////////////////////////////////////////////////////////
/** GL-specific subclass of GrRenderTarget. */
class GrGLRenderTarget : public GrRenderTarget {
public:
// set fTexFBOID to this value to indicate that it is multisampled but
// Gr doesn't know how to resolve it.
enum { kUnresolvableFBOID = 0 };
struct IDDesc {
SkAutoTUnref<GrGLFBO> fRenderFBO;
SkAutoTUnref<GrGLFBO> fTextureFBO;
GrGLuint fRTFBOID;
GrGLuint fTexFBOID;
GrGLuint fMSColorRenderbufferID;
GrGpuResource::LifeCycle fLifeCycle;
};
@ -77,33 +33,21 @@ public:
void setViewport(const GrGLIRect& rect) { fViewport = rect; }
const GrGLIRect& getViewport() const { return fViewport; }
// For multisampled renderbuffer render targets, these will return different GrGLFBO objects. If
// the render target is not texturable, textureFBO() returns NULL. If the render target auto
// resolves to a texture, the same object is returned.
// FBO that should be rendered into. Always non-NULL unless this resource is destroyed
// (this->wasDestroyed()).
const GrGLFBO* renderFBO() const {
SkASSERT(fRenderFBO && fRenderFBO->isValid());
return fRenderFBO;
}
// FBO that has the target's texture ID attached. The return value may be:
// * NULL when this render target is not a texture,
// * the same as renderFBO() when this surface is not multisampled or auto-resolves,
// * or different than renderFBO() when it requires explicit resolving via
// glBlitFramebuffer.
const GrGLFBO* textureFBO() const {
SkASSERT(!fTextureFBO || fTextureFBO->isValid());
return fTextureFBO;
}
// The following two functions return the same ID when a
// texture/render target is multisampled, and different IDs when
// it is.
// FBO ID used to render into
GrGLuint renderFBOID() const { return fRTFBOID; }
// FBO ID that has texture ID attached.
GrGLuint textureFBOID() const { return fTexFBOID; }
// override of GrRenderTarget
ResolveType getResolveType() const SK_OVERRIDE {
if (!this->isMultisampled() || this->renderFBO() == this->textureFBO()) {
if (!this->isMultisampled() ||
fRTFBOID == fTexFBOID) {
// catches FBO 0 and non MSAA case
return kAutoResolves_ResolveType;
} else if (!this->textureFBO()) {
} else if (kUnresolvableFBOID == fTexFBOID) {
return kCantResolve_ResolveType;
} else {
return kCanResolve_ResolveType;
@ -129,23 +73,23 @@ protected:
size_t onGpuMemorySize() const SK_OVERRIDE;
private:
SkAutoTUnref<GrGLFBO> fRenderFBO;
SkAutoTUnref<GrGLFBO> fTextureFBO;
GrGLuint fMSColorRenderbufferID;
GrGLuint fRTFBOID;
GrGLuint fTexFBOID;
GrGLuint fMSColorRenderbufferID;
// We track this separately from GrGpuResource because this may be both a texture and a render
// target, and the texture may be wrapped while the render target is not.
bool fIsWrapped;
bool fIsWrapped;
// when we switch to this render target we want to set the viewport to
// only render to content area (as opposed to the whole allocation) and
// we want the rendering to be at top left (GL has origin in bottom left)
GrGLIRect fViewport;
GrGLIRect fViewport;
// onGpuMemorySize() needs to know what how many color values are owned per pixel. However,
// abandon and release zero out the IDs and the cache needs to know the size even after those
// actions.
uint8_t fColorValuesPerPixel;
uint8_t fColorValuesPerPixel;
typedef GrRenderTarget INHERITED;
};

View File

@ -382,8 +382,7 @@ GrGLvoid GR_GL_FUNCTION_TYPE debugGLReadPixels(GrGLint x,
GrGLenum renderbuffertarget,
GrGLuint renderBufferID) {
GrAlwaysAssert(GR_GL_FRAMEBUFFER == target || GR_GL_READ_FRAMEBUFFER == target ||
GR_GL_DRAW_FRAMEBUFFER == target);
GrAlwaysAssert(GR_GL_FRAMEBUFFER == target);
GrAlwaysAssert(GR_GL_COLOR_ATTACHMENT0 == attachment ||
GR_GL_DEPTH_ATTACHMENT == attachment ||
GR_GL_STENCIL_ATTACHMENT == attachment);
@ -423,8 +422,7 @@ GrGLvoid GR_GL_FUNCTION_TYPE debugGLReadPixels(GrGLint x,
GrGLuint textureID,
GrGLint level) {
GrAlwaysAssert(GR_GL_FRAMEBUFFER == target || GR_GL_READ_FRAMEBUFFER == target ||
GR_GL_DRAW_FRAMEBUFFER == target);
GrAlwaysAssert(GR_GL_FRAMEBUFFER == target);
GrAlwaysAssert(GR_GL_COLOR_ATTACHMENT0 == attachment ||
GR_GL_DEPTH_ATTACHMENT == attachment ||
GR_GL_STENCIL_ATTACHMENT == attachment);