Apply the depth texture correctly as the DepthStencil surface in applyRenderTarget

Trac #20875
Signed-off-by: Nicolas Capens

git-svn-id: https://angleproject.googlecode.com/svn/trunk@1115 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/Context.cpp b/src/libGLESv2/Context.cpp
index b395130..3ad2cf8 100644
--- a/src/libGLESv2/Context.cpp
+++ b/src/libGLESv2/Context.cpp
@@ -1841,13 +1841,31 @@
         return error(GL_INVALID_FRAMEBUFFER_OPERATION, false);
     }
 
+    // if there is no color attachment we must synthesize a NULL colorattachment
+    // to keep the D3D runtime happy.  This should only be possible if depth texturing.
+    Renderbuffer *renderbufferObject = NULL;
+    if (framebufferObject->getColorbufferType() != GL_NONE)
+    {
+        renderbufferObject = framebufferObject->getColorbuffer();
+    }
+    else
+    {
+        renderbufferObject = framebufferObject->getNullColorbuffer();
+    }
+    if (!renderbufferObject)
+    {
+        ERR("unable to locate renderbuffer for FBO.");
+        return false;
+    }
+
     bool renderTargetChanged = false;
-    unsigned int renderTargetSerial = framebufferObject->getRenderTargetSerial();
+    unsigned int renderTargetSerial = renderbufferObject->getSerial();
     if (renderTargetSerial != mAppliedRenderTargetSerial)
     {
-        IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
+        IDirect3DSurface9 *renderTarget = renderbufferObject->getRenderTarget();
         if (!renderTarget)
         {
+            ERR("render target pointer unexpectedly null.");
             return false;   // Context must be lost
         }
         mDevice->SetRenderTarget(0, renderTarget);
@@ -1862,25 +1880,27 @@
     unsigned int stencilbufferSerial = 0;
     if (framebufferObject->getDepthbufferType() != GL_NONE)
     {
-        depthStencil = framebufferObject->getDepthbuffer()->getDepthStencil();
+        Renderbuffer *depthbuffer = framebufferObject->getDepthbuffer();
+        depthStencil = depthbuffer->getDepthStencil();
         if (!depthStencil)
         {
             ERR("Depth stencil pointer unexpectedly null.");
             return false;
         }
         
-        depthbufferSerial = framebufferObject->getDepthbuffer()->getSerial();
+        depthbufferSerial = depthbuffer->getSerial();
     }
     else if (framebufferObject->getStencilbufferType() != GL_NONE)
     {
-        depthStencil = framebufferObject->getStencilbuffer()->getDepthStencil();
+        Renderbuffer *stencilbuffer = framebufferObject->getStencilbuffer();
+        depthStencil = stencilbuffer->getDepthStencil();
         if (!depthStencil)
         {
             ERR("Depth stencil pointer unexpectedly null.");
             return false;
         }
         
-        stencilbufferSerial = framebufferObject->getStencilbuffer()->getSerial();
+        stencilbufferSerial = stencilbuffer->getSerial();
     }
 
     if (depthbufferSerial != mAppliedDepthbufferSerial ||
@@ -1900,7 +1920,7 @@
 
     if (!mRenderTargetDescInitialized || renderTargetChanged)
     {
-        IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
+        IDirect3DSurface9 *renderTarget = renderbufferObject->getRenderTarget();
         if (!renderTarget)
         {
             return false;   // Context must be lost
diff --git a/src/libGLESv2/Framebuffer.cpp b/src/libGLESv2/Framebuffer.cpp
index 1277c06..21972ac 100644
--- a/src/libGLESv2/Framebuffer.cpp
+++ b/src/libGLESv2/Framebuffer.cpp
@@ -29,6 +29,7 @@
     mColorbufferPointer.set(NULL);
     mDepthbufferPointer.set(NULL);
     mStencilbufferPointer.set(NULL);
+    mNullColorbufferPointer.set(NULL);
 }
 
 Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle) const
@@ -200,6 +201,30 @@
     return mStencilbufferPointer.get();
 }
 
+Renderbuffer *Framebuffer::getNullColorbuffer()
+{
+    Renderbuffer *nullbuffer  = mNullColorbufferPointer.get();
+    Renderbuffer *depthbuffer = getDepthbuffer();
+
+    if (!depthbuffer)
+    {
+        ERR("Unexpected null depthbuffer for depth-only FBO.");
+        return NULL;
+    }
+
+    GLsizei width  = depthbuffer->getWidth();
+    GLsizei height = depthbuffer->getHeight();
+
+    if (!nullbuffer ||
+        width != nullbuffer->getWidth() || height != nullbuffer->getHeight())
+    {
+        nullbuffer = new Renderbuffer(0, new Colorbuffer(width, height, GL_NONE, 0));
+        mNullColorbufferPointer.set(nullbuffer);
+    }
+
+    return nullbuffer;
+}
+
 GLenum Framebuffer::getColorbufferType()
 {
     return mColorbufferType;
diff --git a/src/libGLESv2/Framebuffer.h b/src/libGLESv2/Framebuffer.h
index b73f9a0..14d9c2a 100644
--- a/src/libGLESv2/Framebuffer.h
+++ b/src/libGLESv2/Framebuffer.h
@@ -49,6 +49,7 @@
     Renderbuffer *getColorbuffer();
     Renderbuffer *getDepthbuffer();
     Renderbuffer *getStencilbuffer();
+    Renderbuffer *getNullColorbuffer();
 
     GLenum getColorbufferType();
     GLenum getDepthbufferType();
@@ -73,6 +74,8 @@
     GLenum mStencilbufferType;
     BindingPointer<Renderbuffer> mStencilbufferPointer;
 
+    BindingPointer<Renderbuffer> mNullColorbufferPointer;
+
   private:
     DISALLOW_COPY_AND_ASSIGN(Framebuffer);
 
diff --git a/src/libGLESv2/Renderbuffer.cpp b/src/libGLESv2/Renderbuffer.cpp
index f5abd9d..4b911e8 100644
--- a/src/libGLESv2/Renderbuffer.cpp
+++ b/src/libGLESv2/Renderbuffer.cpp
@@ -98,7 +98,7 @@
 // caller must Release() the returned surface
 IDirect3DSurface9 *RenderbufferTexture2D::getDepthStencil()
 {
-    return NULL;
+    return mTexture2D->getDepthStencil(mTarget);
 }
 
 GLsizei RenderbufferTexture2D::getWidth() const
diff --git a/src/libGLESv2/Texture.cpp b/src/libGLESv2/Texture.cpp
index 683ccc5..1af08cb 100644
--- a/src/libGLESv2/Texture.cpp
+++ b/src/libGLESv2/Texture.cpp
@@ -2374,6 +2374,33 @@
 
     updateTexture();
     
+    // ensure this is NOT a depth texture
+    if (isDepth(0))
+    {
+        return NULL;
+    }
+    return mTexStorage->getSurfaceLevel(0);
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+IDirect3DSurface9 *Texture2D::getDepthStencil(GLenum target)
+{
+    ASSERT(target == GL_TEXTURE_2D);
+
+    // ensure the underlying texture is created
+    if (getStorage(true) == NULL)
+    {
+        return NULL;
+    }
+
+    updateTexture();
+
+    // ensure this is actually a depth texture
+    if (!isDepth(0))
+    {
+        return NULL;
+    }
     return mTexStorage->getSurfaceLevel(0);
 }
 
diff --git a/src/libGLESv2/Texture.h b/src/libGLESv2/Texture.h
index 12f102b..2e63131 100644
--- a/src/libGLESv2/Texture.h
+++ b/src/libGLESv2/Texture.h
@@ -306,6 +306,7 @@
   protected:
     friend class RenderbufferTexture2D;
     virtual IDirect3DSurface9 *getRenderTarget(GLenum target);
+    virtual IDirect3DSurface9 *getDepthStencil(GLenum target);
 
   private:
     DISALLOW_COPY_AND_ASSIGN(Texture2D);
diff --git a/src/libGLESv2/utilities.cpp b/src/libGLESv2/utilities.cpp
index 3b77cd8..d34c665 100644
--- a/src/libGLESv2/utilities.cpp
+++ b/src/libGLESv2/utilities.cpp
@@ -795,6 +795,7 @@
 {
     switch (format)
     {
+      case GL_NONE:                 return D3DFMT_NULL;
       case GL_RGBA4:
       case GL_RGB5_A1:
       case GL_RGBA8_OES:            return D3DFMT_A8R8G8B8;