Add new ref-counted Renderbuffer class.

Renderbuffers are a clear object type in GL, and this patch adds
a more consistent state representation for them. They're managed
by the ResourceManager, and have a storage implementation similar
to Textures, but much simpler.

BUG=angle:660

Change-Id: Ia17199bb8cb570d48db42e1f28ccbcc12a902fcf
Reviewed-on: https://chromium-review.googlesource.com/201834
Tested-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Shannon Woods <shannonwoods@chromium.org>
diff --git a/src/libGLESv2/Context.cpp b/src/libGLESv2/Context.cpp
index 1454538..93f3ae2 100644
--- a/src/libGLESv2/Context.cpp
+++ b/src/libGLESv2/Context.cpp
@@ -1066,7 +1066,7 @@
     return mResourceManager->getTexture(handle);
 }
 
-FramebufferAttachment *Context::getRenderbuffer(GLuint handle)
+Renderbuffer *Context::getRenderbuffer(GLuint handle)
 {
     return mResourceManager->getRenderbuffer(handle);
 }
@@ -1399,7 +1399,7 @@
         return;
     }
 
-    FramebufferAttachment *renderbufferObject = mState.renderbuffer.get();
+    Renderbuffer *renderbufferObject = mState.renderbuffer.get();
     renderbufferObject->setStorage(renderbuffer);
 }
 
diff --git a/src/libGLESv2/Context.h b/src/libGLESv2/Context.h
index 13bd50b..d448361 100644
--- a/src/libGLESv2/Context.h
+++ b/src/libGLESv2/Context.h
@@ -51,7 +51,7 @@
 class Texture3D;
 class Texture2DArray;
 class Framebuffer;
-class FramebufferAttachment;
+class Renderbuffer;
 class RenderbufferStorage;
 class Colorbuffer;
 class Depthbuffer;
@@ -101,7 +101,7 @@
     BindingPointer<Buffer> arrayBuffer;
     GLuint readFramebuffer;
     GLuint drawFramebuffer;
-    BindingPointer<FramebufferAttachment> renderbuffer;
+    BindingPointer<Renderbuffer> renderbuffer;
     GLuint currentProgram;
 
     VertexAttribCurrentValueData vertexAttribCurrentValues[MAX_VERTEX_ATTRIBS]; // From glVertexAttrib
@@ -332,7 +332,7 @@
     Program *getProgram(GLuint handle) const;
     Texture *getTexture(GLuint handle);
     Framebuffer *getFramebuffer(GLuint handle) const;
-    FramebufferAttachment *getRenderbuffer(GLuint handle);
+    Renderbuffer *getRenderbuffer(GLuint handle);
     VertexArray *getVertexArray(GLuint handle) const;
     Sampler *getSampler(GLuint handle) const;
     Query *getQuery(GLuint handle, bool create, GLenum type);
diff --git a/src/libGLESv2/Framebuffer.cpp b/src/libGLESv2/Framebuffer.cpp
index e209dee..1fba656 100644
--- a/src/libGLESv2/Framebuffer.cpp
+++ b/src/libGLESv2/Framebuffer.cpp
@@ -42,8 +42,13 @@
     mStencilbuffer.set(NULL, GL_NONE, 0, 0);
 }
 
-FramebufferAttachment *Framebuffer::lookupAttachment(GLenum type, GLuint handle, GLint level, GLint layer) const
+FramebufferAttachmentImpl *Framebuffer::createAttachmentImpl(GLenum type, GLuint handle, GLint level, GLint layer) const
 {
+    if (handle == 0)
+    {
+        return NULL;
+    }
+
     gl::Context *context = gl::getContext();
 
     switch (type)
@@ -52,14 +57,15 @@
         return NULL;
 
       case GL_RENDERBUFFER:
-        return context->getRenderbuffer(handle);
+        return new RenderbufferAttachment(context->getRenderbuffer(handle));
 
       case GL_TEXTURE_2D:
         {
             Texture *texture = context->getTexture(handle);
             if (texture && texture->getTarget() == GL_TEXTURE_2D)
             {
-                return static_cast<Texture2D*>(texture)->getAttachment(level);
+                Texture2D *tex2D = static_cast<Texture2D*>(texture);
+                return new Texture2DAttachment(tex2D, level);
             }
             else
             {
@@ -77,7 +83,8 @@
             Texture *texture = context->getTexture(handle);
             if (texture && texture->getTarget() == GL_TEXTURE_CUBE_MAP)
             {
-                return static_cast<TextureCubeMap*>(texture)->getAttachment(type, level);
+                TextureCubeMap *texCube = static_cast<TextureCubeMap*>(texture);
+                return new TextureCubeMapAttachment(texCube, type, level);
             }
             else
             {
@@ -90,7 +97,8 @@
             Texture *texture = context->getTexture(handle);
             if (texture && texture->getTarget() == GL_TEXTURE_3D)
             {
-                return static_cast<Texture3D*>(texture)->getAttachment(level, layer);
+                Texture3D *tex3D = static_cast<Texture3D*>(texture);
+                return new Texture3DAttachment(tex3D, level, layer);
             }
             else
             {
@@ -103,7 +111,8 @@
             Texture *texture = context->getTexture(handle);
             if (texture && texture->getTarget() == GL_TEXTURE_2D_ARRAY)
             {
-                return static_cast<Texture2DArray*>(texture)->getAttachment(level, layer);
+                Texture2DArray *tex2DArray = static_cast<Texture2DArray*>(texture);
+                return new Texture2DArrayAttachment(tex2DArray, level, layer);
             }
             else
             {
@@ -120,10 +129,11 @@
 void Framebuffer::setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer, GLint level, GLint layer)
 {
     ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
-    FramebufferAttachment *attachment = lookupAttachment(type, colorbuffer, level, layer);
-    if (attachment)
+    FramebufferAttachmentImpl *attachmentImpl = createAttachmentImpl(type, colorbuffer, level, layer);
+    if (attachmentImpl)
     {
-        mColorbuffers[colorAttachment].set(attachment, type, level, layer);
+        FramebufferAttachment *newAttachment = new FramebufferAttachment(mRenderer, colorbuffer, attachmentImpl);
+        mColorbuffers[colorAttachment].set(newAttachment, type, level, layer);
     }
     else
     {
@@ -133,10 +143,11 @@
 
 void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer, GLint level, GLint layer)
 {
-    FramebufferAttachment *attachment = lookupAttachment(type, depthbuffer, level, layer);
-    if (attachment)
+    FramebufferAttachmentImpl *attachmentImpl = createAttachmentImpl(type, depthbuffer, level, layer);
+    if (attachmentImpl)
     {
-        mDepthbuffer.set(attachment, type, level, layer);
+        FramebufferAttachment *newAttachment = new FramebufferAttachment(mRenderer, depthbuffer, attachmentImpl);
+        mDepthbuffer.set(newAttachment, type, level, layer);
     }
     else
     {
@@ -146,10 +157,11 @@
 
 void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer, GLint level, GLint layer)
 {
-    FramebufferAttachment *attachment = lookupAttachment(type, stencilbuffer, level, layer);
-    if (attachment)
+    FramebufferAttachmentImpl *attachmentImpl = createAttachmentImpl(type, stencilbuffer, level, layer);
+    if (attachmentImpl)
     {
-        mStencilbuffer.set(attachment, type, level, layer);
+        FramebufferAttachment *newAttachment = new FramebufferAttachment(mRenderer, stencilbuffer, attachmentImpl);
+        mStencilbuffer.set(newAttachment, type, level, layer);
     }
     else
     {
@@ -159,16 +171,18 @@
 
 void Framebuffer::setDepthStencilBuffer(GLenum type, GLuint depthStencilBuffer, GLint level, GLint layer)
 {
-    FramebufferAttachment *attachment = lookupAttachment(type, depthStencilBuffer, level, layer);
-    if (attachment && attachment->getDepthSize() > 0 && attachment->getStencilSize() > 0)
+    mDepthbuffer.set(NULL, GL_NONE, 0, 0);
+    mStencilbuffer.set(NULL, GL_NONE, 0, 0);
+
+    FramebufferAttachmentImpl *attachmentImpl = createAttachmentImpl(type, depthStencilBuffer, level, layer);
+    if (attachmentImpl)
     {
-        mDepthbuffer.set(attachment, type, level, layer);
-        mStencilbuffer.set(attachment, type, level, layer);
-    }
-    else
-    {
-        mDepthbuffer.set(NULL, GL_NONE, 0, 0);
-        mStencilbuffer.set(NULL, GL_NONE, 0, 0);
+        FramebufferAttachment *newAttachment = new FramebufferAttachment(mRenderer, depthStencilBuffer, attachmentImpl);
+        if (newAttachment->getDepthSize() > 0 && newAttachment->getStencilSize() > 0)
+        {
+            mDepthbuffer.set(newAttachment, type, level, layer);
+            mStencilbuffer.set(newAttachment, type, level, layer);
+        }
     }
 }
 
@@ -683,7 +697,9 @@
 
     // if we have both a depth and stencil buffer, they must refer to the same object
     // since we only support packed_depth_stencil and not separate depth and stencil
-    if (depthbuffer && stencilbuffer && (depthbuffer != stencilbuffer))
+    if (depthbuffer && stencilbuffer &&
+        !(depthbuffer->id() == stencilbuffer->id() &&
+          depthbuffer->isTexture() == stencilbuffer->isTexture()))
     {
         return GL_FRAMEBUFFER_UNSUPPORTED;
     }
@@ -700,11 +716,14 @@
 DefaultFramebuffer::DefaultFramebuffer(rx::Renderer *renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil)
     : Framebuffer(renderer)
 {
-    mColorbuffers[0].set(new FramebufferAttachment(mRenderer, 0, colorbuffer), GL_RENDERBUFFER, 0, 0);
+    Renderbuffer *colorRenderbuffer = new Renderbuffer(mRenderer, 0, colorbuffer);
+    FramebufferAttachment *colorAttachment = new FramebufferAttachment(mRenderer, 0, new RenderbufferAttachment(colorRenderbuffer));
+    mColorbuffers[0].set(colorAttachment, GL_RENDERBUFFER, 0, 0);
 
-    FramebufferAttachment *depthStencilRenderbuffer = new FramebufferAttachment(mRenderer, 0, depthStencil);
-    mDepthbuffer.set(depthStencilRenderbuffer, (depthStencilRenderbuffer->getDepthSize() != 0) ? GL_RENDERBUFFER : GL_NONE, 0, 0);
-    mStencilbuffer.set(depthStencilRenderbuffer, (depthStencilRenderbuffer->getStencilSize() != 0) ? GL_RENDERBUFFER : GL_NONE, 0, 0);
+    Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(mRenderer, 0, depthStencil);
+    FramebufferAttachment *depthStencilAttachment = new FramebufferAttachment(mRenderer, 0, new RenderbufferAttachment(depthStencilRenderbuffer));
+    mDepthbuffer.set(depthStencilAttachment, (depthStencilRenderbuffer->getDepthSize() != 0) ? GL_RENDERBUFFER : GL_NONE, 0, 0);
+    mStencilbuffer.set(depthStencilAttachment, (depthStencilRenderbuffer->getStencilSize() != 0) ? GL_RENDERBUFFER : GL_NONE, 0, 0);
 
     mDrawBufferStates[0] = GL_BACK;
     mReadBufferState = GL_BACK;
diff --git a/src/libGLESv2/Framebuffer.h b/src/libGLESv2/Framebuffer.h
index 1a5e2b6..0c5a8d7 100644
--- a/src/libGLESv2/Framebuffer.h
+++ b/src/libGLESv2/Framebuffer.h
@@ -22,6 +22,7 @@
 namespace gl
 {
 class FramebufferAttachment;
+class FramebufferAttachmentImpl;
 class Colorbuffer;
 class Depthbuffer;
 class Stencilbuffer;
@@ -99,7 +100,7 @@
   private:
     DISALLOW_COPY_AND_ASSIGN(Framebuffer);
 
-    FramebufferAttachment *lookupAttachment(GLenum type, GLuint handle, GLint level, GLint layer) const;
+    FramebufferAttachmentImpl *createAttachmentImpl(GLenum type, GLuint handle, GLint level, GLint layer) const;
 };
 
 class DefaultFramebuffer : public Framebuffer
diff --git a/src/libGLESv2/FramebufferAttachment.cpp b/src/libGLESv2/FramebufferAttachment.cpp
index fa90f28..b9e4728 100644
--- a/src/libGLESv2/FramebufferAttachment.cpp
+++ b/src/libGLESv2/FramebufferAttachment.cpp
@@ -21,18 +21,18 @@
 namespace gl
 {
 
-FramebufferAttachmentInterface::FramebufferAttachmentInterface()
+FramebufferAttachmentImpl::FramebufferAttachmentImpl()
 {
 }
 
-// The default case for classes inherited from FramebufferAttachmentInterface is not to
+// The default case for classes inherited from FramebufferAttachmentImpl is not to
 // need to do anything upon the reference count to the parent FramebufferAttachment incrementing
 // or decrementing.
-void FramebufferAttachmentInterface::addProxyRef(const FramebufferAttachment *proxy)
+void FramebufferAttachmentImpl::addProxyRef(const FramebufferAttachment *proxy)
 {
 }
 
-void FramebufferAttachmentInterface::releaseProxy(const FramebufferAttachment *proxy)
+void FramebufferAttachmentImpl::releaseProxy(const FramebufferAttachment *proxy)
 {
 }
 
@@ -355,69 +355,69 @@
 
 ////// FramebufferAttachment Implementation //////
 
-FramebufferAttachment::FramebufferAttachment(rx::Renderer *renderer, GLuint id, FramebufferAttachmentInterface *instance) : RefCountObject(id)
+FramebufferAttachment::FramebufferAttachment(rx::Renderer *renderer, GLuint id, FramebufferAttachmentImpl *instance)
+  : RefCountObject(id),
+    mRenderer(renderer),
+    mImpl(instance)
 {
-    ASSERT(instance != NULL);
-    mInstance = instance;
-
-    ASSERT(renderer != NULL);
-    mRenderer = renderer;
+    ASSERT(mRenderer != NULL);
+    ASSERT(mImpl != NULL);
 }
 
 FramebufferAttachment::~FramebufferAttachment()
 {
-    delete mInstance;
+    SafeDelete(mImpl);
 }
 
-// The FramebufferAttachmentInterface contained in this FramebufferAttachment may need to maintain
+// The FramebufferAttachmentImpl contained in this FramebufferAttachment may need to maintain
 // its own reference count, so we pass it on here.
 void FramebufferAttachment::addRef() const
 {
-    mInstance->addProxyRef(this);
+    mImpl->addProxyRef(this);
 
     RefCountObject::addRef();
 }
 
 void FramebufferAttachment::release() const
 {
-    mInstance->releaseProxy(this);
+    mImpl->releaseProxy(this);
 
     RefCountObject::release();
 }
 
 rx::RenderTarget *FramebufferAttachment::getRenderTarget()
 {
-    return mInstance->getRenderTarget();
+    return mImpl->getRenderTarget();
 }
 
 rx::RenderTarget *FramebufferAttachment::getDepthStencil()
 {
-    return mInstance->getDepthStencil();
+    return mImpl->getDepthStencil();
 }
 
 rx::TextureStorage *FramebufferAttachment::getTextureStorage()
 {
-    return mInstance->getTextureStorage();
+    return mImpl->getTextureStorage();
 }
 
 GLsizei FramebufferAttachment::getWidth() const
 {
-    return mInstance->getWidth();
+    return mImpl->getWidth();
 }
 
 GLsizei FramebufferAttachment::getHeight() const
 {
-    return mInstance->getHeight();
+    return mImpl->getHeight();
 }
 
 GLenum FramebufferAttachment::getInternalFormat() const
 {
-    return mInstance->getInternalFormat();
+    return mImpl->getInternalFormat();
 }
 
 GLenum FramebufferAttachment::getActualFormat() const
 {
-    return mInstance->getActualFormat();
+    return mImpl->getActualFormat();
 }
 
 GLuint FramebufferAttachment::getRedSize() const
@@ -504,30 +504,98 @@
 
 GLsizei FramebufferAttachment::getSamples() const
 {
-    return mInstance->getSamples();
+    return mImpl->getSamples();
 }
 
 unsigned int FramebufferAttachment::getSerial() const
 {
-    return mInstance->getSerial();
+    return mImpl->getSerial();
 }
 
 bool FramebufferAttachment::isTexture() const
 {
-    return mInstance->isTexture();
+    return mImpl->isTexture();
 }
 
 unsigned int FramebufferAttachment::getTextureSerial() const
 {
-    return mInstance->getTextureSerial();
+    return mImpl->getTextureSerial();
 }
 
-void FramebufferAttachment::setStorage(RenderbufferStorage *newStorage)
+void FramebufferAttachment::setImplementation(FramebufferAttachmentImpl *newImpl)
 {
-    ASSERT(newStorage != NULL);
+    ASSERT(newImpl != NULL);
 
-    delete mInstance;
-    mInstance = newStorage;
+    delete mImpl;
+    mImpl = newImpl;
+}
+
+RenderbufferAttachment::RenderbufferAttachment(Renderbuffer *renderbuffer)
+{
+    ASSERT(renderbuffer);
+    mRenderbuffer.set(renderbuffer);
+}
+
+RenderbufferAttachment::~RenderbufferAttachment()
+{
+    mRenderbuffer.set(NULL);
+}
+
+rx::RenderTarget *RenderbufferAttachment::getRenderTarget()
+{
+    return mRenderbuffer->getStorage()->getRenderTarget();
+}
+
+rx::RenderTarget *RenderbufferAttachment::getDepthStencil()
+{
+    return mRenderbuffer->getStorage()->getDepthStencil();
+}
+
+rx::TextureStorage *RenderbufferAttachment::getTextureStorage()
+{
+    UNREACHABLE();
+    return NULL;
+}
+
+GLsizei RenderbufferAttachment::getWidth() const
+{
+    return mRenderbuffer->getWidth();
+}
+
+GLsizei RenderbufferAttachment::getHeight() const
+{
+    return mRenderbuffer->getHeight();
+}
+
+GLenum RenderbufferAttachment::getInternalFormat() const
+{
+    return mRenderbuffer->getInternalFormat();
+}
+
+GLenum RenderbufferAttachment::getActualFormat() const
+{
+    return mRenderbuffer->getActualFormat();
+}
+
+GLsizei RenderbufferAttachment::getSamples() const
+{
+    return mRenderbuffer->getStorage()->getSamples();
+}
+
+unsigned int RenderbufferAttachment::getSerial() const
+{
+    return mRenderbuffer->getStorage()->getSerial();
+}
+
+bool RenderbufferAttachment::isTexture() const
+{
+    return false;
+}
+
+unsigned int RenderbufferAttachment::getTextureSerial() const
+{
+    UNREACHABLE();
+    return 0;
 }
 
 }
diff --git a/src/libGLESv2/FramebufferAttachment.h b/src/libGLESv2/FramebufferAttachment.h
index 9ba63cc..40553db 100644
--- a/src/libGLESv2/FramebufferAttachment.h
+++ b/src/libGLESv2/FramebufferAttachment.h
@@ -29,24 +29,27 @@
 class TextureCubeMap;
 class Texture3D;
 class Texture2DArray;
-class FramebufferAttachment;
-class FramebufferAttachmentInterface;
-class RenderbufferStorage;
+class FramebufferAttachmentImpl;
+class Renderbuffer;
 
-// FramebufferAttachment implements the GL renderbuffer object.
-// It's only a proxy for a FramebufferAttachmentInterface instance; the internal object
-// can change whenever glRenderbufferStorage is called.
+// FramebufferAttachment implements a GL framebuffer attachment.
+// Attachments are "light" containers, which store pointers to ref-counted GL objects.
+// We support GL texture (2D/3D/Cube/2D array) and renderbuffer object attachments.
+// Note: Renderbuffers are specialized storage for depth and stencil buffes. Our old
+// naming scheme used the term "Renderbuffer" for both GL renderbuffers and for
+// framebuffer attachments, which confused their usage.
+
 class FramebufferAttachment : public RefCountObject
 {
   public:
-    FramebufferAttachment(rx::Renderer *renderer, GLuint id, FramebufferAttachmentInterface *storage);
+    FramebufferAttachment(rx::Renderer *renderer, GLuint id, FramebufferAttachmentImpl *storage);
 
     virtual ~FramebufferAttachment();
 
     // These functions from RefCountObject are overloaded here because
     // Textures need to maintain their own count of references to them via
     // Renderbuffers/RenderbufferTextures. These functions invoke those
-    // reference counting functions on the FramebufferAttachmentInterface.
+    // reference counting functions on the FramebufferAttachmentImpl.
     void addRef() const;
     void release() const;
 
@@ -73,21 +76,21 @@
     bool isTexture() const;
     unsigned int getTextureSerial() const;
 
-    void setStorage(RenderbufferStorage *newStorage);
+    void setImplementation(FramebufferAttachmentImpl *newImpl);
 
   private:
     DISALLOW_COPY_AND_ASSIGN(FramebufferAttachment);
 
     rx::Renderer const *mRenderer;
-    FramebufferAttachmentInterface *mInstance;
+    FramebufferAttachmentImpl *mImpl;
 };
 
-class FramebufferAttachmentInterface
+class FramebufferAttachmentImpl
 {
   public:
-    FramebufferAttachmentInterface();
+    FramebufferAttachmentImpl();
 
-    virtual ~FramebufferAttachmentInterface() {};
+    virtual ~FramebufferAttachmentImpl() {};
 
     virtual void addProxyRef(const FramebufferAttachment *proxy);
     virtual void releaseProxy(const FramebufferAttachment *proxy);
@@ -108,10 +111,10 @@
     virtual unsigned int getTextureSerial() const = 0;
 
   private:
-    DISALLOW_COPY_AND_ASSIGN(FramebufferAttachmentInterface);
+    DISALLOW_COPY_AND_ASSIGN(FramebufferAttachmentImpl);
 };
 
-class Texture2DAttachment : public FramebufferAttachmentInterface
+class Texture2DAttachment : public FramebufferAttachmentImpl
 {
   public:
     Texture2DAttachment(Texture2D *texture, GLint level);
@@ -143,7 +146,7 @@
     const GLint mLevel;
 };
 
-class TextureCubeMapAttachment : public FramebufferAttachmentInterface
+class TextureCubeMapAttachment : public FramebufferAttachmentImpl
 {
   public:
     TextureCubeMapAttachment(TextureCubeMap *texture, GLenum faceTarget, GLint level);
@@ -176,7 +179,7 @@
     const GLenum mFaceTarget;
 };
 
-class Texture3DAttachment : public FramebufferAttachmentInterface
+class Texture3DAttachment : public FramebufferAttachmentImpl
 {
   public:
     Texture3DAttachment(Texture3D *texture, GLint level, GLint layer);
@@ -209,7 +212,7 @@
     const GLint mLayer;
 };
 
-class Texture2DArrayAttachment : public FramebufferAttachmentInterface
+class Texture2DArrayAttachment : public FramebufferAttachmentImpl
 {
   public:
     Texture2DArrayAttachment(Texture2DArray *texture, GLint level, GLint layer);
@@ -242,6 +245,34 @@
     const GLint mLayer;
 };
 
+class RenderbufferAttachment : public FramebufferAttachmentImpl
+{
+  public:
+    RenderbufferAttachment(Renderbuffer *renderbuffer);
+
+    virtual ~RenderbufferAttachment();
+
+    rx::RenderTarget *getRenderTarget();
+    rx::RenderTarget *getDepthStencil();
+    rx::TextureStorage *getTextureStorage();
+
+    virtual GLsizei getWidth() const;
+    virtual GLsizei getHeight() const;
+    virtual GLenum getInternalFormat() const;
+    virtual GLenum getActualFormat() const;
+    virtual GLsizei getSamples() const;
+
+    virtual unsigned int getSerial() const;
+
+    virtual bool isTexture() const;
+    virtual unsigned int getTextureSerial() const;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(RenderbufferAttachment);
+
+    BindingPointer<Renderbuffer> mRenderbuffer;
+};
+
 }
 
 #endif // LIBGLESV2_FRAMEBUFFERATTACHMENT_H_
diff --git a/src/libGLESv2/Renderbuffer.cpp b/src/libGLESv2/Renderbuffer.cpp
index dade014..266084c 100644
--- a/src/libGLESv2/Renderbuffer.cpp
+++ b/src/libGLESv2/Renderbuffer.cpp
@@ -22,6 +22,88 @@
 {
 unsigned int RenderbufferStorage::mCurrentSerial = 1;
 
+Renderbuffer::Renderbuffer(rx::Renderer *renderer, GLuint id, RenderbufferStorage *newStorage)
+  : RefCountObject(id),
+    mRenderer(renderer),
+    mStorage(newStorage)
+{
+    ASSERT(mStorage);
+}
+
+void Renderbuffer::setStorage(RenderbufferStorage *newStorage)
+{
+    ASSERT(newStorage);
+
+    SafeDelete(mStorage);
+    mStorage = newStorage;
+}
+
+RenderbufferStorage *Renderbuffer::getStorage()
+{
+    ASSERT(mStorage);
+    return mStorage;
+}
+
+GLsizei Renderbuffer::getWidth() const
+{
+    ASSERT(mStorage);
+    return mStorage->getWidth();
+}
+
+GLsizei Renderbuffer::getHeight() const
+{
+    ASSERT(mStorage);
+    return mStorage->getHeight();
+}
+
+GLenum Renderbuffer::getInternalFormat() const
+{
+    ASSERT(mStorage);
+    return mStorage->getInternalFormat();
+}
+
+GLenum Renderbuffer::getActualFormat() const
+{
+    ASSERT(mStorage);
+    return mStorage->getActualFormat();
+}
+
+GLsizei Renderbuffer::getSamples() const
+{
+    ASSERT(mStorage);
+    return mStorage->getSamples();
+}
+
+GLuint Renderbuffer::getRedSize() const
+{
+    return gl::GetRedBits(getActualFormat(), mRenderer->getCurrentClientVersion());
+}
+
+GLuint Renderbuffer::getGreenSize() const
+{
+    return gl::GetGreenBits(getActualFormat(), mRenderer->getCurrentClientVersion());
+}
+
+GLuint Renderbuffer::getBlueSize() const
+{
+    return gl::GetBlueBits(getActualFormat(), mRenderer->getCurrentClientVersion());
+}
+
+GLuint Renderbuffer::getAlphaSize() const
+{
+    return gl::GetAlphaBits(getActualFormat(), mRenderer->getCurrentClientVersion());
+}
+
+GLuint Renderbuffer::getDepthSize() const
+{
+    return gl::GetDepthBits(getActualFormat(), mRenderer->getCurrentClientVersion());
+}
+
+GLuint Renderbuffer::getStencilSize() const
+{
+    return gl::GetStencilBits(getActualFormat(), mRenderer->getCurrentClientVersion());
+}
+
 RenderbufferStorage::RenderbufferStorage() : mSerial(issueSerials(1))
 {
     mWidth = 0;
diff --git a/src/libGLESv2/Renderbuffer.h b/src/libGLESv2/Renderbuffer.h
index 4da447a..ef7989e 100644
--- a/src/libGLESv2/Renderbuffer.h
+++ b/src/libGLESv2/Renderbuffer.h
@@ -29,11 +29,42 @@
 
 namespace gl
 {
+class RenderbufferStorage;
+
+// A GL renderbuffer object is usually used as a depth or stencil buffer attachment
+// for a framebuffer object. The renderbuffer itself is a distinct GL object, see
+// FramebufferAttachment and Framebuffer for how they are applied to an FBO via an
+// attachment point.
+
+class Renderbuffer : public RefCountObject
+{
+  public:
+    Renderbuffer(rx::Renderer *renderer, GLuint id, RenderbufferStorage *newStorage);
+
+    void setStorage(RenderbufferStorage *newStorage);
+    RenderbufferStorage *getStorage();
+
+    GLsizei getWidth() const;
+    GLsizei getHeight() const;
+    GLenum getInternalFormat() const;
+    GLenum getActualFormat() const;
+    GLsizei getSamples() const;
+    GLuint getRedSize() const;
+    GLuint getGreenSize() const;
+    GLuint getBlueSize() const;
+    GLuint getAlphaSize() const;
+    GLuint getDepthSize() const;
+    GLuint getStencilSize() const;
+
+  private:
+    rx::Renderer *mRenderer;
+    RenderbufferStorage *mStorage;
+};
 
 // A class derived from RenderbufferStorage is created whenever glRenderbufferStorage
 // is called. The specific concrete type depends on whether the internal format is
 // colour depth, stencil or packed depth/stencil.
-class RenderbufferStorage : public FramebufferAttachmentInterface
+class RenderbufferStorage
 {
   public:
     RenderbufferStorage();
@@ -126,6 +157,7 @@
   private:
     DISALLOW_COPY_AND_ASSIGN(Stencilbuffer);
 };
+
 }
 
 #endif   // LIBGLESV2_RENDERBUFFER_H_
diff --git a/src/libGLESv2/ResourceManager.cpp b/src/libGLESv2/ResourceManager.cpp
index cf0812d..97c28cb 100644
--- a/src/libGLESv2/ResourceManager.cpp
+++ b/src/libGLESv2/ResourceManager.cpp
@@ -311,7 +311,7 @@
     }
 }
 
-FramebufferAttachment *ResourceManager::getRenderbuffer(unsigned int handle)
+Renderbuffer *ResourceManager::getRenderbuffer(unsigned int handle)
 {
     RenderbufferMap::iterator renderbuffer = mRenderbufferMap.find(handle);
 
@@ -353,7 +353,7 @@
     }
 }
 
-void ResourceManager::setRenderbuffer(GLuint handle, FramebufferAttachment *buffer)
+void ResourceManager::setRenderbuffer(GLuint handle, Renderbuffer *buffer)
 {
     mRenderbufferMap[handle] = buffer;
 }
@@ -405,7 +405,7 @@
 {
     if (renderbuffer != 0 && !getRenderbuffer(renderbuffer))
     {
-        FramebufferAttachment *renderbufferObject = new FramebufferAttachment(mRenderer, renderbuffer, new Colorbuffer(mRenderer, 0, 0, GL_RGBA4, 0));
+        Renderbuffer *renderbufferObject = new Renderbuffer(mRenderer, renderbuffer, new Colorbuffer(mRenderer, 0, 0, GL_RGBA4, 0));
         mRenderbufferMap[renderbuffer] = renderbufferObject;
         renderbufferObject->addRef();
     }
diff --git a/src/libGLESv2/ResourceManager.h b/src/libGLESv2/ResourceManager.h
index a08a6aa..85e6b4b 100644
--- a/src/libGLESv2/ResourceManager.h
+++ b/src/libGLESv2/ResourceManager.h
@@ -30,7 +30,7 @@
 class Shader;
 class Program;
 class Texture;
-class FramebufferAttachment;
+class Renderbuffer;
 class Sampler;
 class FenceSync;
 
@@ -63,11 +63,11 @@
     Shader *getShader(GLuint handle);
     Program *getProgram(GLuint handle);
     Texture *getTexture(GLuint handle);
-    FramebufferAttachment *getRenderbuffer(GLuint handle);
+    Renderbuffer *getRenderbuffer(GLuint handle);
     Sampler *getSampler(GLuint handle);
     FenceSync *getFenceSync(GLuint handle);
     
-    void setRenderbuffer(GLuint handle, FramebufferAttachment *renderbuffer);
+    void setRenderbuffer(GLuint handle, Renderbuffer *renderbuffer);
 
     void checkBufferAllocation(unsigned int buffer);
     void checkTextureAllocation(GLuint texture, TextureType type);
@@ -97,7 +97,7 @@
     TextureMap mTextureMap;
     HandleAllocator mTextureHandleAllocator;
 
-    typedef std::unordered_map<GLuint, FramebufferAttachment*> RenderbufferMap;
+    typedef std::unordered_map<GLuint, Renderbuffer*> RenderbufferMap;
     RenderbufferMap mRenderbufferMap;
     HandleAllocator mRenderbufferHandleAllocator;
 
diff --git a/src/libGLESv2/libGLESv2.cpp b/src/libGLESv2/libGLESv2.cpp
index e8c8aa3..70179cc 100644
--- a/src/libGLESv2/libGLESv2.cpp
+++ b/src/libGLESv2/libGLESv2.cpp
@@ -3092,25 +3092,25 @@
                 return gl::error(GL_INVALID_OPERATION);
             }
 
-            gl::FramebufferAttachment *attachment = context->getRenderbuffer(context->getRenderbufferHandle());
+            gl::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getRenderbufferHandle());
 
             switch (pname)
             {
-              case GL_RENDERBUFFER_WIDTH:           *params = attachment->getWidth();          break;
-              case GL_RENDERBUFFER_HEIGHT:          *params = attachment->getHeight();         break;
-              case GL_RENDERBUFFER_INTERNAL_FORMAT: *params = attachment->getInternalFormat(); break;
-              case GL_RENDERBUFFER_RED_SIZE:        *params = attachment->getRedSize();        break;
-              case GL_RENDERBUFFER_GREEN_SIZE:      *params = attachment->getGreenSize();      break;
-              case GL_RENDERBUFFER_BLUE_SIZE:       *params = attachment->getBlueSize();       break;
-              case GL_RENDERBUFFER_ALPHA_SIZE:      *params = attachment->getAlphaSize();      break;
-              case GL_RENDERBUFFER_DEPTH_SIZE:      *params = attachment->getDepthSize();      break;
-              case GL_RENDERBUFFER_STENCIL_SIZE:    *params = attachment->getStencilSize();    break;
+              case GL_RENDERBUFFER_WIDTH:           *params = renderbuffer->getWidth();          break;
+              case GL_RENDERBUFFER_HEIGHT:          *params = renderbuffer->getHeight();         break;
+              case GL_RENDERBUFFER_INTERNAL_FORMAT: *params = renderbuffer->getInternalFormat(); break;
+              case GL_RENDERBUFFER_RED_SIZE:        *params = renderbuffer->getRedSize();        break;
+              case GL_RENDERBUFFER_GREEN_SIZE:      *params = renderbuffer->getGreenSize();      break;
+              case GL_RENDERBUFFER_BLUE_SIZE:       *params = renderbuffer->getBlueSize();       break;
+              case GL_RENDERBUFFER_ALPHA_SIZE:      *params = renderbuffer->getAlphaSize();      break;
+              case GL_RENDERBUFFER_DEPTH_SIZE:      *params = renderbuffer->getDepthSize();      break;
+              case GL_RENDERBUFFER_STENCIL_SIZE:    *params = renderbuffer->getStencilSize();    break;
               case GL_RENDERBUFFER_SAMPLES_ANGLE:
                 if (!context->getCaps().extensions.framebufferMultisample)
                 {
                     return gl::error(GL_INVALID_ENUM);
                 }
-                *params = attachment->getSamples();
+                *params = renderbuffer->getSamples();
                 break;
               default:
                 return gl::error(GL_INVALID_ENUM);
@@ -4138,7 +4138,7 @@
 
         if (context && renderbuffer)
         {
-            gl::FramebufferAttachment *renderbufferObject = context->getRenderbuffer(renderbuffer);
+            gl::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer);
 
             if (renderbufferObject)
             {
diff --git a/src/libGLESv2/renderer/d3d9/Renderer9.cpp b/src/libGLESv2/renderer/d3d9/Renderer9.cpp
index e8e4053..b6889f9 100644
--- a/src/libGLESv2/renderer/d3d9/Renderer9.cpp
+++ b/src/libGLESv2/renderer/d3d9/Renderer9.cpp
@@ -1121,7 +1121,8 @@
         }
     }
 
-    gl::FramebufferAttachment *nullbuffer = new gl::FramebufferAttachment(this, 0, new gl::Colorbuffer(this, width, height, GL_NONE, 0));
+    gl::Renderbuffer *nullRenderbuffer = new gl::Renderbuffer(this, 0, new gl::Colorbuffer(this, width, height, GL_NONE, 0));
+    gl::FramebufferAttachment *nullbuffer = new gl::FramebufferAttachment(this, 0, new gl::RenderbufferAttachment(nullRenderbuffer));
 
     // add nullbuffer to the cache
     NullColorbufferCacheEntry *oldest = &mNullColorbufferCache[0];