Pass the RenderTarget, not the D3D surface, up the Renderbuffer heirarchy.

TRAC #22094

Signed-off-by: Nicolas Capens
Signed-off-by: Daniel Koch

git-svn-id: https://angleproject.googlecode.com/svn/branches/dx11proto@1449 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/renderer/Blit.cpp b/src/libGLESv2/renderer/Blit.cpp
index 2d12594..0250e34 100644
--- a/src/libGLESv2/renderer/Blit.cpp
+++ b/src/libGLESv2/renderer/Blit.cpp
@@ -14,6 +14,7 @@
 #include "libGLESv2/utilities.h"
 #include "libGLESv2/renderer/renderer9_utils.h" // D3D9_REPLACE
 #include "libGLESv2/renderer/TextureStorage.h"
+#include "libGLESv2/renderer/RenderTarget9.h"
 #include "libGLESv2/Framebuffer.h"
 
 namespace
@@ -215,7 +216,20 @@
 bool Blit::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorage2D *storage, GLint level)
 {
     // D3D9_REPLACE
-    IDirect3DSurface9 *source = framebuffer->getRenderTarget();
+    RenderTarget9 *renderTarget = NULL;
+    IDirect3DSurface9 *source = NULL;
+    gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer();
+
+    if (colorbuffer)
+    {
+        renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget());
+    }
+    
+    if (renderTarget)
+    {
+        source = renderTarget->getSurface();
+    }
+
     if (!source)
     {
         ERR("Failed to retrieve the render target.");
@@ -238,7 +252,20 @@
 bool Blit::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageCubeMap *storage, GLenum target, GLint level)
 {
     // D3D9_REPLACE
-    IDirect3DSurface9 *source = framebuffer->getRenderTarget();
+    RenderTarget9 *renderTarget = NULL;
+    IDirect3DSurface9 *source = NULL;
+    gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer();
+
+    if (colorbuffer)
+    {
+        renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget());
+    }
+    
+    if (renderTarget)
+    {
+        source = renderTarget->getSurface();
+    }
+
     if (!source)
     {
         ERR("Failed to retrieve the render target.");
diff --git a/src/libGLESv2/renderer/Image.cpp b/src/libGLESv2/renderer/Image.cpp
index 0d73c14..b069d1c 100644
--- a/src/libGLESv2/renderer/Image.cpp
+++ b/src/libGLESv2/renderer/Image.cpp
@@ -16,6 +16,7 @@
 #include "libGLESv2/utilities.h"
 #include "libGLESv2/Texture.h"
 #include "libGLESv2/Framebuffer.h"
+#include "libGLESv2/renderer/RenderTarget9.h"
 
 #include "libGLESv2/renderer/renderer9_utils.h"
 
@@ -984,9 +985,21 @@
 // This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures
 void Image::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
 {
-    IDirect3DSurface9 *renderTarget = source->getRenderTarget();
+    RenderTarget9 *renderTarget = NULL;
+    IDirect3DSurface9 *surface = NULL;
+    gl::Renderbuffer *colorbuffer = source->getColorbuffer();
 
-    if (!renderTarget)
+    if (colorbuffer)
+    {
+        renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget());
+    }
+    
+    if (renderTarget)
+    {
+        surface = renderTarget->getSurface();
+    }
+
+    if (!surface)
     {
         ERR("Failed to retrieve the render target.");
         return error(GL_OUT_OF_MEMORY);
@@ -996,24 +1009,24 @@
 
     IDirect3DSurface9 *renderTargetData = NULL;
     D3DSURFACE_DESC description;
-    renderTarget->GetDesc(&description);
+    surface->GetDesc(&description);
     
     HRESULT result = device->CreateOffscreenPlainSurface(description.Width, description.Height, description.Format, D3DPOOL_SYSTEMMEM, &renderTargetData, NULL);
 
     if (FAILED(result))
     {
         ERR("Could not create matching destination surface.");
-        renderTarget->Release();
+        surface->Release();
         return error(GL_OUT_OF_MEMORY);
     }
 
-    result = device->GetRenderTargetData(renderTarget, renderTargetData);
+    result = device->GetRenderTargetData(surface, renderTargetData);
 
     if (FAILED(result))
     {
         ERR("GetRenderTargetData unexpectedly failed.");
         renderTargetData->Release();
-        renderTarget->Release();
+        surface->Release();
         return error(GL_OUT_OF_MEMORY);
     }
 
@@ -1027,7 +1040,7 @@
     {
         ERR("Failed to lock the source surface (rectangle might be invalid).");
         renderTargetData->Release();
-        renderTarget->Release();
+        surface->Release();
         return error(GL_OUT_OF_MEMORY);
     }
 
@@ -1039,7 +1052,7 @@
         ERR("Failed to lock the destination surface (rectangle might be invalid).");
         renderTargetData->UnlockRect();
         renderTargetData->Release();
-        renderTarget->Release();
+        surface->Release();
         return error(GL_OUT_OF_MEMORY);
     }
 
@@ -1214,7 +1227,7 @@
     renderTargetData->UnlockRect();
 
     renderTargetData->Release();
-    renderTarget->Release();
+    surface->Release();
 
     mDirty = true;
 }
diff --git a/src/libGLESv2/renderer/RenderTarget9.cpp b/src/libGLESv2/renderer/RenderTarget9.cpp
index a1f8ad1..1d30672 100644
--- a/src/libGLESv2/renderer/RenderTarget9.cpp
+++ b/src/libGLESv2/renderer/RenderTarget9.cpp
@@ -94,6 +94,12 @@
     }
 }
 
+RenderTarget9 *RenderTarget9::makeRenderTarget9(RenderTarget *target)
+{
+    ASSERT(dynamic_cast<rx::RenderTarget9*>(target) != NULL);
+    return static_cast<rx::RenderTarget9*>(target);
+}
+
 IDirect3DSurface9 *RenderTarget9::getSurface()
 {
     // Caller is responsible for releasing the returned surface reference.
diff --git a/src/libGLESv2/renderer/RenderTarget9.h b/src/libGLESv2/renderer/RenderTarget9.h
index e7af7fa..dfc003e 100644
--- a/src/libGLESv2/renderer/RenderTarget9.h
+++ b/src/libGLESv2/renderer/RenderTarget9.h
@@ -26,6 +26,7 @@
     RenderTarget9(Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples);
     virtual ~RenderTarget9();
 
+    static RenderTarget9 *makeRenderTarget9(RenderTarget *renderTarget);
     IDirect3DSurface9 *getSurface();
 
   private:
diff --git a/src/libGLESv2/renderer/Renderer9.cpp b/src/libGLESv2/renderer/Renderer9.cpp
index 8bf6d17..c496af0 100644
--- a/src/libGLESv2/renderer/Renderer9.cpp
+++ b/src/libGLESv2/renderer/Renderer9.cpp
@@ -17,6 +17,7 @@
 #include "libGLESv2/renderer/TextureStorage.h"
 #include "libGLESv2/renderer/Image.h"
 #include "libGLESv2/renderer/Blit.h"
+#include "libGLESv2/renderer/RenderTarget9.h"
 
 #include "libEGL/Config.h"
 #include "libEGL/Display.h"
@@ -1446,8 +1447,36 @@
 
     if (blitRenderTarget)
     {
-        IDirect3DSurface9* readRenderTarget = readFramebuffer->getRenderTarget();
-        IDirect3DSurface9* drawRenderTarget = drawFramebuffer->getRenderTarget();
+        gl::Renderbuffer *readBuffer = readFramebuffer->getColorbuffer();
+        gl::Renderbuffer *drawBuffer = drawFramebuffer->getColorbuffer();
+        RenderTarget9 *readRenderTarget = NULL;
+        RenderTarget9 *drawRenderTarget = NULL;
+        IDirect3DSurface9* readSurface = NULL;
+        IDirect3DSurface9* drawSurface = NULL;
+
+        if (readBuffer)
+        {
+            readRenderTarget = RenderTarget9::makeRenderTarget9(readBuffer->getRenderTarget());
+        }
+        if (drawBuffer)
+        {
+            drawRenderTarget = RenderTarget9::makeRenderTarget9(drawBuffer->getRenderTarget());
+        }
+
+        if (readRenderTarget)
+        {
+            readSurface = readRenderTarget->getSurface();
+        }
+        if (drawRenderTarget)
+        {
+            drawSurface = drawRenderTarget->getSurface();
+        }
+
+        if (!readSurface || !drawSurface)
+        {
+            ERR("Failed to retrieve the render target.");
+            return error(GL_OUT_OF_MEMORY, false);
+        }
 
         RECT srcRect, dstRect;
         RECT *srcRectPtr = NULL;
@@ -1471,10 +1500,10 @@
             dstRectPtr = &dstRect;
         }
 
-        HRESULT result = mDevice->StretchRect(readRenderTarget, srcRectPtr, drawRenderTarget, dstRectPtr, D3DTEXF_NONE);
+        HRESULT result = mDevice->StretchRect(readSurface, srcRectPtr, drawSurface, dstRectPtr, D3DTEXF_NONE);
 
-        readRenderTarget->Release();
-        drawRenderTarget->Release();
+        readSurface->Release();
+        drawSurface->Release();
 
         if (FAILED(result))
         {
@@ -1485,13 +1514,41 @@
 
     if (blitDepthStencil)
     {
-        IDirect3DSurface9* readDepthStencil = readFramebuffer->getDepthStencil();
-        IDirect3DSurface9* drawDepthStencil = drawFramebuffer->getDepthStencil();
+        gl::Renderbuffer *readBuffer = readFramebuffer->getDepthOrStencilbuffer();
+        gl::Renderbuffer *drawBuffer = drawFramebuffer->getDepthOrStencilbuffer();
+        RenderTarget9 *readDepthStencil = NULL;
+        RenderTarget9 *drawDepthStencil = NULL;
+        IDirect3DSurface9* readSurface = NULL;
+        IDirect3DSurface9* drawSurface = NULL;
 
-        HRESULT result = mDevice->StretchRect(readDepthStencil, NULL, drawDepthStencil, NULL, D3DTEXF_NONE);
+        if (readBuffer)
+        {
+            readDepthStencil = RenderTarget9::makeRenderTarget9(readBuffer->getDepthStencil());
+        }
+        if (drawBuffer)
+        {
+            drawDepthStencil = RenderTarget9::makeRenderTarget9(drawBuffer->getDepthStencil());
+        }
 
-        readDepthStencil->Release();
-        drawDepthStencil->Release();
+        if (readDepthStencil)
+        {
+            readSurface = readDepthStencil->getSurface();
+        }
+        if (drawDepthStencil)
+        {
+            drawSurface = drawDepthStencil->getSurface();
+        }
+
+        if (!readSurface || !drawSurface)
+        {
+            ERR("Failed to retrieve the render target.");
+            return error(GL_OUT_OF_MEMORY, false);
+        }
+
+        HRESULT result = mDevice->StretchRect(readSurface, NULL, drawSurface, NULL, D3DTEXF_NONE);
+
+        readSurface->Release();
+        drawSurface->Release();
 
         if (FAILED(result))
         {
@@ -1506,19 +1563,33 @@
 void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, 
                            GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels)
 {
-    IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget();
-    if (!renderTarget)
+    RenderTarget9 *renderTarget = NULL;
+    IDirect3DSurface9 *surface = NULL;
+    gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer();
+
+    if (colorbuffer)
     {
-        return;   // Context must be lost, return silently
+        renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget());
+    }
+    
+    if (renderTarget)
+    {
+        surface = renderTarget->getSurface();
+    }
+
+    if (!surface)
+    {
+        // context must be lost
+        return;
     }
 
     D3DSURFACE_DESC desc;
-    renderTarget->GetDesc(&desc);
+    surface->GetDesc(&desc);
 
     if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
     {
         UNIMPLEMENTED();   // FIXME: Requires resolve using StretchRect into non-multisampled render target
-        renderTarget->Release();
+        surface->Release();
         return error(GL_OUT_OF_MEMORY);
     }
 
@@ -1546,14 +1617,14 @@
         if (FAILED(result))
         {
             ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-            renderTarget->Release();
+            surface->Release();
             return error(GL_OUT_OF_MEMORY);
         }
     }
 
-    result = mDevice->GetRenderTargetData(renderTarget, systemSurface);
-    renderTarget->Release();
-    renderTarget = NULL;
+    result = mDevice->GetRenderTargetData(surface, systemSurface);
+    surface->Release();
+    surface = NULL;
 
     if (FAILED(result))
     {
@@ -1824,19 +1895,24 @@
 
 bool Renderer9::setRenderTarget(gl::Renderbuffer *renderbuffer)
 {
-    IDirect3DSurface9 *renderTarget = NULL;
+    IDirect3DSurface9 *renderTargetSurface = NULL;
     
     if (renderbuffer)
     {
-        renderTarget = renderbuffer->getRenderTarget();
-        if (!renderTarget)
+        RenderTarget *renderTarget = renderbuffer->getRenderTarget();
+        if (renderTarget)
+        {
+            renderTargetSurface = renderTarget->getSurface();
+        }
+
+        if (!renderTargetSurface)
         {
             ERR("render target pointer unexpectedly null.");
             return false;   // Context must be lost
         }
 
-        mDevice->SetRenderTarget(0, renderTarget);
-        renderTarget->Release();
+        mDevice->SetRenderTarget(0, renderTargetSurface);
+        renderTargetSurface->Release();
     }
     else
     {
@@ -1848,18 +1924,25 @@
 
 bool Renderer9::setDepthStencil(gl::Renderbuffer *renderbuffer)
 {
-    IDirect3DSurface9 *depthStencil = NULL;
+    IDirect3DSurface9 *depthStencilSurface = NULL;
     
     if (renderbuffer)
     {
-        depthStencil = renderbuffer->getDepthStencil();
-        if (!depthStencil)
+        RenderTarget *depthStencil = renderbuffer->getDepthStencil();
+        
+        if (depthStencil)
+        {
+            depthStencilSurface = depthStencil->getSurface();
+        }
+
+        if (!depthStencilSurface)
         {
             ERR("depth stencil pointer unexpectedly null.");
             return false;   // Context must be lost
         }
-        mDevice->SetDepthStencilSurface(depthStencil);
-        depthStencil->Release();
+
+        mDevice->SetDepthStencilSurface(depthStencilSurface);
+        depthStencilSurface->Release();
     }
     else
     {