Implement the DEPTH_STENCIL attachment point for FBOs.

Trac #23469

Signed-off-by: Jamie Madill
Signed-off-by: Shannon Woods
Author: Geoff Lang
diff --git a/src/common/version.h b/src/common/version.h
index 91339cc..0b1e363 100644
--- a/src/common/version.h
+++ b/src/common/version.h
@@ -1,7 +1,7 @@
 #define MAJOR_VERSION 2
 #define MINOR_VERSION 0
 #define BUILD_VERSION 0
-#define BUILD_REVISION 1996
+#define BUILD_REVISION 1997
 
 #define STRINGIFY(x) #x
 #define MACRO_STRINGIFY(x) STRINGIFY(x)
diff --git a/src/libGLESv2/Framebuffer.cpp b/src/libGLESv2/Framebuffer.cpp
index 2f8d374..1d83ded 100644
--- a/src/libGLESv2/Framebuffer.cpp
+++ b/src/libGLESv2/Framebuffer.cpp
@@ -90,6 +90,24 @@
     mStencilbufferPointer.set(lookupRenderbuffer(type, stencilbuffer));
 }
 
+void Framebuffer::setDepthStencilBuffer(GLenum type, GLuint depthStencilBuffer)
+{
+    Renderbuffer *renderBuffer = lookupRenderbuffer(type, depthStencilBuffer);
+    if (renderBuffer && renderBuffer->getDepthSize() > 0 && renderBuffer->getStencilSize() > 0)
+    {
+        mDepthbufferType = type;
+        mDepthbufferPointer.set(renderBuffer);
+
+        mStencilbufferType = type;
+        mStencilbufferPointer.set(renderBuffer);
+    }
+    else
+    {
+        mDepthbufferType = GL_NONE;
+        mStencilbufferType = GL_NONE;
+    }
+}
+
 void Framebuffer::detachTexture(GLuint texture)
 {
     for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
@@ -245,6 +263,11 @@
     return mStencilbufferType;
 }
 
+GLenum Framebuffer::getDepthStencilbufferType() const
+{
+    return (mDepthbufferPointer.id() == mStencilbufferPointer.id()) ? mDepthbufferType : GL_NONE;
+}
+
 GLuint Framebuffer::getColorbufferHandle(unsigned int colorAttachment) const
 {
     ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
@@ -261,6 +284,11 @@
     return mStencilbufferPointer.id();
 }
 
+GLenum Framebuffer::getDepthStencilbufferHandle() const
+{
+    return (mDepthbufferPointer.id() == mStencilbufferPointer.id()) ? mDepthbufferPointer.id() : 0;
+}
+
 GLenum Framebuffer::getDrawBufferState(unsigned int colorAttachment) const
 {
     return mDrawBufferStates[colorAttachment];
diff --git a/src/libGLESv2/Framebuffer.h b/src/libGLESv2/Framebuffer.h
index b54e008..5c679db 100644
--- a/src/libGLESv2/Framebuffer.h
+++ b/src/libGLESv2/Framebuffer.h
@@ -37,6 +37,7 @@
     void setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer);
     void setDepthbuffer(GLenum type, GLuint depthbuffer);
     void setStencilbuffer(GLenum type, GLuint stencilbuffer);
+    void setDepthStencilBuffer(GLenum type, GLuint depthStencilBuffer);
 
     void detachTexture(GLuint texture);
     void detachRenderbuffer(GLuint renderbuffer);
@@ -56,10 +57,12 @@
     GLenum getColorbufferType(unsigned int colorAttachment) const;
     GLenum getDepthbufferType() const;
     GLenum getStencilbufferType() const;
+    GLenum getDepthStencilbufferType() const;
 
     GLuint getColorbufferHandle(unsigned int colorAttachment) const;
     GLuint getDepthbufferHandle() const;
     GLuint getStencilbufferHandle() const;
+    GLenum getDepthStencilbufferHandle() const;
 
     GLenum getDrawBufferState(unsigned int colorAttachment) const;
     void setDrawBufferState(unsigned int colorAttachment, GLenum drawBuffer);
diff --git a/src/libGLESv2/libGLESv2.cpp b/src/libGLESv2/libGLESv2.cpp
index e872131..47d23bf 100644
--- a/src/libGLESv2/libGLESv2.cpp
+++ b/src/libGLESv2/libGLESv2.cpp
@@ -4170,6 +4170,12 @@
                   case GL_DEPTH_ATTACHMENT:
                   case GL_STENCIL_ATTACHMENT:
                     break;
+                  case GL_DEPTH_STENCIL_ATTACHMENT:
+                    if (context->getClientVersion() < 3)
+                    {
+                        return gl::error(GL_INVALID_ENUM);
+                    }
+                    break;
                   default:
                     return gl::error(GL_INVALID_ENUM);
                 }
@@ -4266,8 +4272,9 @@
             {
                 switch (attachment)
                 {
-                  case GL_DEPTH_ATTACHMENT:   framebuffer->setDepthbuffer(textarget, texture);   break;
-                  case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture); break;
+                  case GL_DEPTH_ATTACHMENT:         framebuffer->setDepthbuffer(textarget, texture);        break;
+                  case GL_STENCIL_ATTACHMENT:       framebuffer->setStencilbuffer(textarget, texture);      break;
+                  case GL_DEPTH_STENCIL_ATTACHMENT: framebuffer->setDepthStencilBuffer(textarget, texture); break;
                 }
             }
         }
@@ -5065,6 +5072,17 @@
                     attachmentType = framebuffer->getStencilbufferType();
                     attachmentHandle = framebuffer->getStencilbufferHandle();
                     break;
+                  case GL_DEPTH_STENCIL_ATTACHMENT:
+                    if (context->getClientVersion() < 3)
+                    {
+                        return gl::error(GL_INVALID_ENUM);
+                    }
+                    if (framebuffer->getDepthbufferHandle() != framebuffer->getStencilbufferHandle())
+                    {
+                        return gl::error(GL_INVALID_OPERATION);
+                    }
+                    attachmentType = framebuffer->getDepthStencilbufferType();
+                    attachmentHandle = framebuffer->getDepthStencilbufferHandle();
                   default: return gl::error(GL_INVALID_ENUM);
                 }
             }