diff options
Diffstat (limited to 'src/gpu/gl/GrGLCreateDebugInterface.cpp')
-rw-r--r-- | src/gpu/gl/GrGLCreateDebugInterface.cpp | 326 |
1 files changed, 310 insertions, 16 deletions
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; |