diff options
author | 2012-03-22 20:43:56 +0000 | |
---|---|---|
committer | 2012-03-22 20:43:56 +0000 | |
commit | 7c9594259bbf007bf6dab857544586f2327ea66e (patch) | |
tree | ddee2e50d2cdc95c318d1334e136be7b29802b90 | |
parent | 5fd53858f83776025e63de44b2e0a1822b932c39 (diff) |
Extended debug GL interface to include tracking of render buffers
http://codereview.appspot.com/5875050/
git-svn-id: http://skia.googlecode.com/svn/trunk@3469 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r-- | include/gpu/gl/GrGLDefines.h | 1 | ||||
-rw-r--r-- | include/gpu/gl/SkGLContext.h | 2 | ||||
-rw-r--r-- | src/gpu/gl/GrGLCreateDebugInterface.cpp | 326 | ||||
-rw-r--r-- | src/gpu/gl/SkGLContext.cpp | 23 |
4 files changed, 325 insertions, 27 deletions
diff --git a/include/gpu/gl/GrGLDefines.h b/include/gpu/gl/GrGLDefines.h index e66eec4edf..3697d604cb 100644 --- a/include/gpu/gl/GrGLDefines.h +++ b/include/gpu/gl/GrGLDefines.h @@ -673,7 +673,6 @@ #define GR_GL_COLOR_ATTACHMENT0 0x8CE0 #define GR_GL_DEPTH_ATTACHMENT 0x8D00 #define GR_GL_STENCIL_ATTACHMENT 0x8D20 -#define GR_GL_DEPTH_STENCIL_ATTACHMENT 0x821A #define GR_GL_NONE 0 diff --git a/include/gpu/gl/SkGLContext.h b/include/gpu/gl/SkGLContext.h index 542d1bbc06..e2ac7e0885 100644 --- a/include/gpu/gl/SkGLContext.h +++ b/include/gpu/gl/SkGLContext.h @@ -51,6 +51,8 @@ protected: private: SkString fExtensionString; GrGLuint fFBO; + GrGLuint fColorBufferID; + GrGLuint fDepthStencilBufferID; const GrGLInterface* fGL; }; diff --git a/src/gpu/gl/GrGLCreateDebugInterface.cpp b/src/gpu/gl/GrGLCreateDebugInterface.cpp index de73fa25fb..022cc56fb8 100644 --- a/src/gpu/gl/GrGLCreateDebugInterface.cpp +++ b/src/gpu/gl/GrGLCreateDebugInterface.cpp @@ -10,6 +10,7 @@ #include "gl/GrGLInterface.h" #include "SkTArray.h" +#include "SkTDArray.h" // the OpenGLES 2.0 spec says this must be >= 2 static const GrGLint kDefaultMaxTextureUnits = 8; @@ -158,6 +159,89 @@ private: }; //////////////////////////////////////////////////////////////////////////////// +class GrRenderBufferObj : public GrFakeRefObj +{ +public: + GrRenderBufferObj(GrGLuint ID) + : GrFakeRefObj(ID) + , fBound(false) { + } + + virtual ~GrRenderBufferObj() { + GrAlwaysAssert(0 == fColorReferees.count()); + GrAlwaysAssert(0 == fDepthReferees.count()); + GrAlwaysAssert(0 == fStencilReferees.count()); + } + + void setBound() { fBound = true; } + void resetBound() { fBound = false; } + bool getBound() const { return fBound; } + + void setColorBound(GrFakeRefObj *referee) { + fColorReferees.append(1, &referee); + } + void resetColorBound(GrFakeRefObj *referee) { + int index = fColorReferees.find(referee); + GrAlwaysAssert(0 <= index); + fColorReferees.removeShuffle(index); + } + bool getColorBound(GrFakeRefObj *referee) const { + int index = fColorReferees.find(referee); + return 0 <= index; + } + bool getColorBound() const { + return 0 != fColorReferees.count(); + } + + void setDepthBound(GrFakeRefObj *referee) { + fDepthReferees.append(1, &referee); + } + void resetDepthBound(GrFakeRefObj *referee) { + int index = fDepthReferees.find(referee); + GrAlwaysAssert(0 <= index); + fDepthReferees.removeShuffle(index); + } + bool getDepthBound(GrFakeRefObj *referee) const { + int index = fDepthReferees.find(referee); + return 0 <= index; + } + bool getDepthBound() const { + return 0 != fDepthReferees.count(); + } + + void setStencilBound(GrFakeRefObj *referee) { + fStencilReferees.append(1, &referee); + } + void resetStencilBound(GrFakeRefObj *referee) { + int index = fStencilReferees.find(referee); + GrAlwaysAssert(0 <= index); + fStencilReferees.removeShuffle(index); + } + bool getStencilBound(GrFakeRefObj *referee) const { + int index = fStencilReferees.find(referee); + return 0 <= index; + } + bool getStencilBound() const { + return 0 != fStencilReferees.count(); + } + + virtual void deleteAction() SK_OVERRIDE { + + this->setDeleted(); + } + +protected: +private: + bool fBound; // is this render buffer currently bound via "glBindRenderbuffer"? + + SkTDArray<GrFakeRefObj *> fColorReferees; // frame buffers that use this as a color buffer (via "glFramebufferRenderbuffer") + SkTDArray<GrFakeRefObj *> fDepthReferees; // frame buffers that use this as a depth buffer (via "glFramebufferRenderbuffer") + SkTDArray<GrFakeRefObj *> fStencilReferees; // frame buffers that use this as a stencil buffer (via "glFramebufferRenderbuffer") + + typedef GrFakeRefObj INHERITED; +}; + +//////////////////////////////////////////////////////////////////////////////// // TODO: when a framebuffer obj is bound the GL_SAMPLES query must return 0 // TODO: GL_STENCIL_BITS must also be redirected to the framebuffer class GrFrameBufferObj : public GrFakeRefObj @@ -165,21 +249,96 @@ class GrFrameBufferObj : public GrFakeRefObj public: GrFrameBufferObj(GrGLuint ID) : GrFakeRefObj(ID) - , fBound(false) { + , fBound(false) + , fColorBuffer(NULL) + , fDepthBuffer(NULL) + , fStencilBuffer(NULL) { + } + + virtual ~GrFrameBufferObj() { + fColorBuffer = NULL; + fDepthBuffer = NULL; + fStencilBuffer = NULL; } void setBound() { fBound = true; } void resetBound() { fBound = false; } bool getBound() const { return fBound; } + void setColor(GrRenderBufferObj *buffer) { + if (fColorBuffer) { + // automatically break the binding of the old buffer + GrAlwaysAssert(fColorBuffer->getColorBound(this)); + fColorBuffer->resetColorBound(this); + + GrAlwaysAssert(!fColorBuffer->getDeleted()); + fColorBuffer->unref(); + } + fColorBuffer = buffer; + if (fColorBuffer) { + GrAlwaysAssert(!fColorBuffer->getDeleted()); + fColorBuffer->ref(); + + GrAlwaysAssert(!fColorBuffer->getColorBound(this)); + fColorBuffer->setColorBound(this); + } + } + GrRenderBufferObj *getColor() { return fColorBuffer; } + + void setDepth(GrRenderBufferObj *buffer) { + if (fDepthBuffer) { + // automatically break the binding of the old buffer + GrAlwaysAssert(fDepthBuffer->getDepthBound(this)); + fDepthBuffer->resetDepthBound(this); + + GrAlwaysAssert(!fDepthBuffer->getDeleted()); + fDepthBuffer->unref(); + } + fDepthBuffer = buffer; + if (fDepthBuffer) { + GrAlwaysAssert(!fDepthBuffer->getDeleted()); + fDepthBuffer->ref(); + + GrAlwaysAssert(!fDepthBuffer->getDepthBound(this)); + fDepthBuffer->setDepthBound(this); + } + } + GrRenderBufferObj *getDepth() { return fDepthBuffer; } + + void setStencil(GrRenderBufferObj *buffer) { + if (fStencilBuffer) { + // automatically break the binding of the old buffer + GrAlwaysAssert(fStencilBuffer->getStencilBound(this)); + fStencilBuffer->resetStencilBound(this); + + GrAlwaysAssert(!fStencilBuffer->getDeleted()); + fStencilBuffer->unref(); + } + fStencilBuffer = buffer; + if (fStencilBuffer) { + GrAlwaysAssert(!fStencilBuffer->getDeleted()); + fStencilBuffer->ref(); + + GrAlwaysAssert(!fStencilBuffer->getStencilBound(this)); + fStencilBuffer->setStencilBound(this); + } + } + GrRenderBufferObj *getStencil() { return fStencilBuffer; } + virtual void deleteAction() SK_OVERRIDE { + setColor(NULL); + setDepth(NULL); + setStencil(NULL); this->setDeleted(); } protected: private: bool fBound; // is this frame buffer currently bound via "glBindFramebuffer"? + GrRenderBufferObj * fColorBuffer; + GrRenderBufferObj * fDepthBuffer; + GrRenderBufferObj * fStencilBuffer; typedef GrFakeRefObj INHERITED; }; @@ -271,6 +430,15 @@ public: return reinterpret_cast<GrFrameBufferObj *>(obj); } + GrRenderBufferObj *findRenderBuffer(GrGLuint ID) { + GrFakeRefObj *obj = this->findObject(ID); + if (NULL == obj) { + return NULL; + } + + return reinterpret_cast<GrRenderBufferObj *>(obj); + } + GrShaderObj *findShader(GrGLuint ID) { GrFakeRefObj *obj = this->findObject(ID); if (NULL == obj) { @@ -306,6 +474,14 @@ public: return buffer; } + GrRenderBufferObj *createRenderBuffer() { + GrRenderBufferObj *buffer = new GrRenderBufferObj(++fNextID); + + fObjects.push_back(buffer); + + return buffer; + } + GrShaderObj *createShader(GrGLenum type) { GrShaderObj *shader = new GrShaderObj(++fNextID, type); @@ -389,8 +565,7 @@ public: GrBufferObj *getElementArrayBuffer() { return fElementArrayBuffer; } void setFrameBuffer(GrFrameBufferObj *frameBuffer) { - if (fFrameBuffer) - { + if (fFrameBuffer) { GrAlwaysAssert(fFrameBuffer->getBound()); fFrameBuffer->resetBound(); @@ -400,8 +575,7 @@ public: fFrameBuffer = frameBuffer; - if (fFrameBuffer) - { + if (fFrameBuffer) { GrAlwaysAssert(!fFrameBuffer->getDeleted()); fFrameBuffer->ref(); @@ -412,6 +586,28 @@ public: GrFrameBufferObj *getFrameBuffer() { return fFrameBuffer; } + void setRenderBuffer(GrRenderBufferObj *renderBuffer) { + if (fRenderBuffer) { + GrAlwaysAssert(fRenderBuffer->getBound()); + fRenderBuffer->resetBound(); + + GrAlwaysAssert(!fRenderBuffer->getDeleted()); + fRenderBuffer->unref(); + } + + fRenderBuffer = renderBuffer; + + if (fRenderBuffer) { + GrAlwaysAssert(!fRenderBuffer->getDeleted()); + fRenderBuffer->ref(); + + GrAlwaysAssert(!fRenderBuffer->getBound()); + fRenderBuffer->setBound(); + } + } + + GrRenderBufferObj *getRenderBuffer() { return fRenderBuffer; } + void useProgram(GrProgramObj *program) { if (fProgram) { GrAlwaysAssert(fProgram->getInUse()); @@ -423,8 +619,7 @@ public: fProgram = program; - if (fProgram) - { + if (fProgram) { GrAlwaysAssert(!fProgram->getDeleted()); fProgram->ref(); @@ -455,6 +650,7 @@ private: GrBufferObj * fArrayBuffer; GrBufferObj * fElementArrayBuffer; GrFrameBufferObj *fFrameBuffer; + GrRenderBufferObj *fRenderBuffer; GrProgramObj * fProgram; static int fNextID; // source for globally unique IDs @@ -470,6 +666,7 @@ private: , fArrayBuffer(NULL) , fElementArrayBuffer(NULL) , fFrameBuffer(NULL) + , fRenderBuffer(NULL) , fProgram(NULL) { } @@ -484,6 +681,7 @@ private: fArrayBuffer = NULL; fElementArrayBuffer = NULL; fFrameBuffer = NULL; + fRenderBuffer = NULL; fProgram = NULL; } }; @@ -620,20 +818,28 @@ GrGLvoid GR_GL_FUNCTION_TYPE debugGLBindFramebuffer(GrGLenum target, GrGLuint fr GrAlwaysAssert(GR_GL_FRAMEBUFFER == target); // a frameBufferID of 0 is acceptable - it binds to the default frame buffer - GrFrameBufferObj *framebuffer = GrDebugGL::getInstance()->findFrameBuffer(frameBufferID); + GrFrameBufferObj *frameBuffer = GrDebugGL::getInstance()->findFrameBuffer(frameBufferID); - GrDebugGL::getInstance()->setFrameBuffer(framebuffer); + GrDebugGL::getInstance()->setFrameBuffer(frameBuffer); } -GrGLvoid GR_GL_FUNCTION_TYPE debugGLBindRenderbuffer(GrGLenum target, GrGLuint renderbuffer) {} +GrGLvoid GR_GL_FUNCTION_TYPE debugGLBindRenderbuffer(GrGLenum target, GrGLuint renderBufferID) { + + GrAlwaysAssert(GR_GL_RENDERBUFFER == target); + + // a renderBufferID of 0 is acceptable - it unbinds the bound render buffer + GrRenderBufferObj *renderBuffer = GrDebugGL::getInstance()->findRenderBuffer(renderBufferID); + + GrDebugGL::getInstance()->setRenderBuffer(renderBuffer); +} -GrGLvoid GR_GL_FUNCTION_TYPE debugGLDeleteFramebuffers(GrGLsizei n, const GrGLuint *framebuffers) { +GrGLvoid GR_GL_FUNCTION_TYPE debugGLDeleteFramebuffers(GrGLsizei n, const GrGLuint *frameBuffers) { // first potentially unbind the buffers if (GrDebugGL::getInstance()->getFrameBuffer()) { for (int i = 0; i < n; ++i) { - if (framebuffers[i] == GrDebugGL::getInstance()->getFrameBuffer()->getID()) { + if (frameBuffers[i] == GrDebugGL::getInstance()->getFrameBuffer()->getID()) { // this ID is the current frame buffer - rebind to the default GrDebugGL::getInstance()->setFrameBuffer(NULL); } @@ -642,16 +848,95 @@ GrGLvoid GR_GL_FUNCTION_TYPE debugGLDeleteFramebuffers(GrGLsizei n, const GrGLui // then actually "delete" the buffers for (int i = 0; i < n; ++i) { - GrFrameBufferObj *buffer = GrDebugGL::getInstance()->findFrameBuffer(framebuffers[i]); + GrFrameBufferObj *buffer = GrDebugGL::getInstance()->findFrameBuffer(frameBuffers[i]); + GrAlwaysAssert(buffer); + + GrAlwaysAssert(!buffer->getDeleted()); + buffer->deleteAction(); + } +} + +GrGLvoid GR_GL_FUNCTION_TYPE debugGLDeleteRenderbuffers(GrGLsizei n, const GrGLuint *renderBuffers) { + + // first potentially unbind the buffers + if (GrDebugGL::getInstance()->getRenderBuffer()) { + for (int i = 0; i < n; ++i) { + + if (renderBuffers[i] == GrDebugGL::getInstance()->getRenderBuffer()->getID()) { + // this ID is the current render buffer - make no render buffer be bound + GrDebugGL::getInstance()->setRenderBuffer(NULL); + } + } + } + + // Open GL will remove a deleted render buffer from the active frame buffer but not + // from any other frame buffer + if (GrDebugGL::getInstance()->getFrameBuffer()) { + + GrFrameBufferObj *frameBuffer = GrDebugGL::getInstance()->getFrameBuffer(); + + for (int i = 0; i < n; ++i) { + + if (NULL != frameBuffer->getColor() && renderBuffers[i] == frameBuffer->getColor()->getID()) { + frameBuffer->setColor(NULL); + } + if (NULL != frameBuffer->getDepth() && renderBuffers[i] == frameBuffer->getDepth()->getID()) { + frameBuffer->setDepth(NULL); + } + if (NULL != frameBuffer->getStencil() && renderBuffers[i] == frameBuffer->getStencil()->getID()) { + frameBuffer->setStencil(NULL); + } + } + } + + // then actually "delete" the buffers + for (int i = 0; i < n; ++i) { + GrRenderBufferObj *buffer = GrDebugGL::getInstance()->findRenderBuffer(renderBuffers[i]); GrAlwaysAssert(buffer); + // OpenGL gives no guarantees if a render buffer is deleted while attached to + // something other than the currently bound frame buffer + GrAlwaysAssert(!buffer->getColorBound()); + GrAlwaysAssert(!buffer->getDepthBound()); + GrAlwaysAssert(!buffer->getStencilBound()); + GrAlwaysAssert(!buffer->getDeleted()); buffer->deleteAction(); } } -GrGLvoid GR_GL_FUNCTION_TYPE debugGLDeleteRenderbuffers(GrGLsizei n, const GrGLuint *renderbuffers) {} -GrGLvoid GR_GL_FUNCTION_TYPE debugGLFramebufferRenderbuffer(GrGLenum target, GrGLenum attachment, GrGLenum renderbuffertarget, GrGLuint renderbuffer) {} +GrGLvoid GR_GL_FUNCTION_TYPE debugGLFramebufferRenderbuffer(GrGLenum target, GrGLenum attachment, GrGLenum renderbuffertarget, GrGLuint renderBufferID) { + + GrAlwaysAssert(GR_GL_FRAMEBUFFER == target); + GrAlwaysAssert(GR_GL_COLOR_ATTACHMENT0 == attachment || + GR_GL_DEPTH_ATTACHMENT == attachment || + GR_GL_STENCIL_ATTACHMENT == attachment); + GrAlwaysAssert(GR_GL_RENDERBUFFER == renderbuffertarget); + + GrFrameBufferObj *framebuffer = GrDebugGL::getInstance()->getFrameBuffer(); + // A render buffer cannot be attached to the default framebuffer + GrAlwaysAssert(NULL != framebuffer); + + // a renderBufferID of 0 is acceptable - it unbinds the current render buffer + GrRenderBufferObj *renderbuffer = GrDebugGL::getInstance()->findRenderBuffer(renderBufferID); + + switch (attachment) { + case GR_GL_COLOR_ATTACHMENT0: + framebuffer->setColor(renderbuffer); + break; + case GR_GL_DEPTH_ATTACHMENT: + framebuffer->setDepth(renderbuffer); + break; + case GR_GL_STENCIL_ATTACHMENT: + framebuffer->setStencil(renderbuffer); + break; + default: + GrAlwaysAssert(false); + break; + }; + +} + GrGLvoid GR_GL_FUNCTION_TYPE debugGLFramebufferTexture2D(GrGLenum target, GrGLenum attachment, GrGLenum textarget, GrGLuint texture, GrGLint level) {} GrGLvoid GR_GL_FUNCTION_TYPE debugGLGetFramebufferAttachmentParameteriv(GrGLenum target, GrGLenum attachment, GrGLenum pname, GrGLint* params) {} GrGLvoid GR_GL_FUNCTION_TYPE debugGLGetRenderbufferParameteriv(GrGLenum target, GrGLenum pname, GrGLint* params) {} @@ -733,6 +1018,15 @@ GrGLvoid GR_GL_FUNCTION_TYPE debugGLGenFramebuffers(GrGLsizei n, GrGLuint* ids) } } +GrGLvoid GR_GL_FUNCTION_TYPE debugGLGenRenderbuffers(GrGLsizei n, GrGLuint* ids) { + + for (int i = 0; i < n; ++i) { + GrRenderBufferObj *buffer = GrDebugGL::getInstance()->createRenderBuffer(); + GrAlwaysAssert(buffer); + ids[i] = buffer->getID(); + } +} + // same delete function for all glDelete*(GLsize i, const GLuint*) except buffers GrGLvoid GR_GL_FUNCTION_TYPE debugGLDeleteIds(GrGLsizei n, const GrGLuint* ids) {} @@ -1152,7 +1446,7 @@ const GrGLInterface* GrGLCreateDebugInterface() { interface->fFramebufferRenderbuffer = debugGLFramebufferRenderbuffer; interface->fFramebufferTexture2D = debugGLFramebufferTexture2D; interface->fGenFramebuffers = debugGLGenFramebuffers; - interface->fGenRenderbuffers = debugGLGenIds; + interface->fGenRenderbuffers = debugGLGenRenderbuffers; interface->fGetFramebufferAttachmentParameteriv = debugGLGetFramebufferAttachmentParameteriv; interface->fGetRenderbufferParameteriv = debugGLGetRenderbufferParameteriv; interface->fRenderbufferStorage = debugGLRenderbufferStorage; diff --git a/src/gpu/gl/SkGLContext.cpp b/src/gpu/gl/SkGLContext.cpp index 9b197ac97f..2d9cd6ac86 100644 --- a/src/gpu/gl/SkGLContext.cpp +++ b/src/gpu/gl/SkGLContext.cpp @@ -9,6 +9,8 @@ SkGLContext::SkGLContext() : fFBO(0) + , fColorBufferID(0) + , fDepthStencilBufferID(0) , fGL(NULL) { } @@ -16,6 +18,8 @@ SkGLContext::~SkGLContext() { if (fGL) { SK_GL(*this, DeleteFramebuffers(1, &fFBO)); + SK_GL(*this, DeleteRenderbuffers(1, &fColorBufferID)); + SK_GL(*this, DeleteRenderbuffers(1, &fDepthStencilBufferID)); } SkSafeUnref(fGL); @@ -47,15 +51,12 @@ bool SkGLContext::init(int width, int height) { error = SK_GL(*this, GetError()); } while (GR_GL_NO_ERROR != error); - GrGLuint cbID; - GrGLuint dsID; - GrGLBinding bindingInUse = GrGLGetBindingInUse(this->gl()); SK_GL(*this, GenFramebuffers(1, &fFBO)); SK_GL(*this, BindFramebuffer(GR_GL_FRAMEBUFFER, fFBO)); - SK_GL(*this, GenRenderbuffers(1, &cbID)); - SK_GL(*this, BindRenderbuffer(GR_GL_RENDERBUFFER, cbID)); + SK_GL(*this, GenRenderbuffers(1, &fColorBufferID)); + SK_GL(*this, BindRenderbuffer(GR_GL_RENDERBUFFER, fColorBufferID)); if (kES2_GrGLBinding == bindingInUse) { SK_GL(*this, RenderbufferStorage(GR_GL_RENDERBUFFER, GR_GL_RGBA8, @@ -68,9 +69,9 @@ bool SkGLContext::init(int width, int height) { SK_GL(*this, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0, GR_GL_RENDERBUFFER, - cbID)); - SK_GL(*this, GenRenderbuffers(1, &dsID)); - SK_GL(*this, BindRenderbuffer(GR_GL_RENDERBUFFER, dsID)); + fColorBufferID)); + SK_GL(*this, GenRenderbuffers(1, &fDepthStencilBufferID)); + SK_GL(*this, BindRenderbuffer(GR_GL_RENDERBUFFER, fDepthStencilBufferID)); // Some drivers that support packed depth stencil will only succeed // in binding a packed format an FBO. However, we can't rely on packed @@ -97,7 +98,7 @@ bool SkGLContext::init(int width, int height) { SK_GL(*this, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, GR_GL_DEPTH_ATTACHMENT, GR_GL_RENDERBUFFER, - dsID)); + fDepthStencilBufferID)); } else { GrGLenum format = kES2_GrGLBinding == bindingInUse ? GR_GL_STENCIL_INDEX8 : @@ -109,7 +110,7 @@ bool SkGLContext::init(int width, int height) { SK_GL(*this, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, GR_GL_STENCIL_ATTACHMENT, GR_GL_RENDERBUFFER, - dsID)); + fDepthStencilBufferID)); SK_GL(*this, Viewport(0, 0, width, height)); SK_GL(*this, ClearStencil(0)); SK_GL(*this, Clear(GR_GL_STENCIL_BUFFER_BIT)); @@ -121,6 +122,8 @@ bool SkGLContext::init(int width, int height) { if (GR_GL_FRAMEBUFFER_COMPLETE != status || GR_GL_NO_ERROR != error) { fFBO = 0; + fColorBufferID = 0; + fDepthStencilBufferID = 0; fGL->unref(); fGL = NULL; this->destroyGLContext(); |