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
diff --git a/include/gpu/gl/GrGLDefines.h b/include/gpu/gl/GrGLDefines.h
index e66eec4..3697d60 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 542d1bb..e2ac7e0 100644
--- a/include/gpu/gl/SkGLContext.h
+++ b/include/gpu/gl/SkGLContext.h
@@ -51,6 +51,8 @@
 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 de73fa2..022cc56 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,20 +159,72 @@
 };
 
 ////////////////////////////////////////////////////////////////////////////////
-// 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
+class GrRenderBufferObj : public GrFakeRefObj
 {
 public:
-    GrFrameBufferObj(GrGLuint ID)
+    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();
@@ -179,7 +232,113 @@
 
 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
+{
+public:
+    GrFrameBufferObj(GrGLuint ID)
+        : GrFakeRefObj(ID)
+        , 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 @@
         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 @@
         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 @@
     GrBufferObj *getElementArrayBuffer()                            { return fElementArrayBuffer; }
 
     void setFrameBuffer(GrFrameBufferObj *frameBuffer)  { 
-        if (fFrameBuffer)
-        {
+        if (fFrameBuffer) {
             GrAlwaysAssert(fFrameBuffer->getBound());
             fFrameBuffer->resetBound();
 
@@ -400,8 +575,7 @@
 
         fFrameBuffer = frameBuffer; 
 
-        if (fFrameBuffer)
-        {
+        if (fFrameBuffer) {
             GrAlwaysAssert(!fFrameBuffer->getDeleted());
             fFrameBuffer->ref();
 
@@ -412,6 +586,28 @@
 
     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 @@
 
         fProgram = program;
 
-        if (fProgram)
-        {
+        if (fProgram) {
             GrAlwaysAssert(!fProgram->getDeleted());
             fProgram->ref();
 
@@ -455,6 +650,7 @@
     GrBufferObj *   fArrayBuffer;
     GrBufferObj *   fElementArrayBuffer;
     GrFrameBufferObj *fFrameBuffer;
+    GrRenderBufferObj *fRenderBuffer;
     GrProgramObj *  fProgram;
 
     static int fNextID;                     // source for globally unique IDs
@@ -470,6 +666,7 @@
         , fArrayBuffer(NULL)
         , fElementArrayBuffer(NULL)
         , fFrameBuffer(NULL)
+        , fRenderBuffer(NULL)
         , fProgram(NULL) {
     }
 
@@ -484,6 +681,7 @@
         fArrayBuffer = NULL;
         fElementArrayBuffer = NULL;
         fFrameBuffer = NULL;
+        fRenderBuffer = NULL;
         fProgram = NULL;
     }
 };
@@ -620,20 +818,28 @@
     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) {
 
-GrGLvoid GR_GL_FUNCTION_TYPE debugGLDeleteFramebuffers(GrGLsizei n, const GrGLuint *framebuffers) {
+    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) {
 
     // 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,7 +848,7 @@
 
     // 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());
@@ -650,8 +856,87 @@
     }
 }
 
-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 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 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 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 @@
         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 9b197ac..2d9cd6a 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 @@
 
     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 @@
             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 @@
         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 @@
             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 @@
         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 @@
         if (GR_GL_FRAMEBUFFER_COMPLETE != status ||
             GR_GL_NO_ERROR != error) {
             fFBO = 0;
+            fColorBufferID = 0;
+            fDepthStencilBufferID = 0;
             fGL->unref();
             fGL = NULL;
             this->destroyGLContext();