RenderTarget11 now stores a shader resource.

TRAC #22358

Signed-off-by: Nicolas Capens
Signed-off-by: Shannon Woods
Author: Geoff Lang

git-svn-id: https://angleproject.googlecode.com/svn/branches/dx11proto@1744 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/renderer/RenderTarget11.cpp b/src/libGLESv2/renderer/RenderTarget11.cpp
index 0fb5043..98cc78d 100644
--- a/src/libGLESv2/renderer/RenderTarget11.cpp
+++ b/src/libGLESv2/renderer/RenderTarget11.cpp
@@ -177,44 +177,46 @@
     return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels);
 }
 
-RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *view, GLsizei width, GLsizei height)
+RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *rtv, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height)
 {
     mRenderer = Renderer11::makeRenderer11(renderer);
-    mRenderTarget = view;
+    mRenderTarget = rtv;
     mDepthStencil = NULL;
+    mShaderResource = srv;
 
     if (mRenderTarget)
     {
         D3D11_RENDER_TARGET_VIEW_DESC desc;
-        view->GetDesc(&desc);
+        mRenderTarget->GetDesc(&desc);
 
         mSubresourceIndex = getRTVSubresourceIndex(mRenderTarget);
         mWidth = width;
         mHeight = height;
 
-        mInternalFormat = d3d11_gl::ConvertRenderbufferFormat(desc.Format);
-        mActualFormat = d3d11_gl::ConvertRenderbufferFormat(desc.Format);
+        mInternalFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format);
+        mActualFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format);
         mSamples = 1; // TEMP?
     }
 }
 
-RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *view, GLsizei width, GLsizei height)
+RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height)
 {
     mRenderer = Renderer11::makeRenderer11(renderer);
     mRenderTarget = NULL;
-    mDepthStencil = view;
+    mDepthStencil = dsv;
+    mShaderResource = srv;
 
     if (mDepthStencil)
     {
         D3D11_DEPTH_STENCIL_VIEW_DESC desc;
-        view->GetDesc(&desc);
+        mDepthStencil->GetDesc(&desc);
 
         mSubresourceIndex = getDSVSubresourceIndex(mDepthStencil);
         mWidth = width;
         mHeight = height;
 
-        mInternalFormat = d3d11_gl::ConvertRenderbufferFormat(desc.Format);
-        mActualFormat = d3d11_gl::ConvertRenderbufferFormat(desc.Format);
+        mInternalFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format);
+        mActualFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format);
         mSamples = 1; // TEMP?
     }
 }
@@ -224,6 +226,7 @@
     mRenderer = Renderer11::makeRenderer11(renderer);
     mRenderTarget = NULL;
     mDepthStencil = NULL;
+    mShaderResource = NULL;
 
     DXGI_FORMAT requestedFormat = gl_d3d11::ConvertRenderbufferFormat(format);
     int supportedSamples = 0; // TODO - Multisample support query
@@ -251,43 +254,68 @@
         desc.Usage = D3D11_USAGE_DEFAULT;
         desc.CPUAccessFlags = 0;
         desc.MiscFlags = 0;
-        desc.BindFlags = (depth ? D3D11_BIND_DEPTH_STENCIL : D3D11_BIND_RENDER_TARGET);
+        desc.BindFlags = (depth ? D3D11_BIND_DEPTH_STENCIL : (D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE));
         ID3D11Texture2D *rtTexture = NULL;
 
         ID3D11Device *device = mRenderer->getDevice();
         HRESULT result = device->CreateTexture2D(&desc, NULL, &rtTexture);
 
-        if (SUCCEEDED(result))
-        {
-            if (depth)
-            {
-                D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
-                dsvDesc.Format = requestedFormat;
-                dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
-                dsvDesc.Texture2D.MipSlice = 0;
-                dsvDesc.Flags = 0;
-                result = device->CreateDepthStencilView(rtTexture, &dsvDesc, &mDepthStencil);
-            }
-            else
-            {   
-                D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
-                rtvDesc.Format = requestedFormat;
-                rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
-                rtvDesc.Texture2D.MipSlice = 0;
-                result = device->CreateRenderTargetView(rtTexture, &rtvDesc, &mRenderTarget);
-            }
-
-            rtTexture->Release();
-        }
-
         if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
         {
             error(GL_OUT_OF_MEMORY);
-
             return;
         }
-
         ASSERT(SUCCEEDED(result));
+
+        if (depth)
+        {
+            D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
+            dsvDesc.Format = requestedFormat;
+            dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
+            dsvDesc.Texture2D.MipSlice = 0;
+            dsvDesc.Flags = 0;
+            result = device->CreateDepthStencilView(rtTexture, &dsvDesc, &mDepthStencil);
+
+            if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+            {
+                rtTexture->Release();
+                error(GL_OUT_OF_MEMORY);
+                return;
+            }
+            ASSERT(SUCCEEDED(result));
+        }
+        else
+        {
+            D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+            rtvDesc.Format = requestedFormat;
+            rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+            rtvDesc.Texture2D.MipSlice = 0;
+            result = device->CreateRenderTargetView(rtTexture, &rtvDesc, &mRenderTarget);
+
+            if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+            {
+                rtTexture->Release();
+                error(GL_OUT_OF_MEMORY);
+                return;
+            }
+            ASSERT(SUCCEEDED(result));
+
+            D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+            srvDesc.Format = requestedFormat;
+            srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+            srvDesc.Texture2D.MostDetailedMip = 0;
+            srvDesc.Texture2D.MipLevels = 1;
+            result = device->CreateShaderResourceView(rtTexture, &srvDesc, &mShaderResource);
+
+            if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+            {
+                rtTexture->Release();
+                mRenderTarget->Release();
+                error(GL_OUT_OF_MEMORY);
+                return;
+            }
+            ASSERT(SUCCEEDED(result));
+        }
     }
 
     mWidth = width;
@@ -303,11 +331,19 @@
     if (mRenderTarget)
     {
         mRenderTarget->Release();
+        mRenderTarget = NULL;
     }
 
     if (mDepthStencil)
     {
         mDepthStencil->Release();
+        mDepthStencil = NULL;
+    }
+
+    if (mShaderResource)
+    {
+        mShaderResource->Release();
+        mShaderResource = NULL;
     }
 }
 
@@ -339,9 +375,20 @@
     return mDepthStencil;
 }
 
+// Adds reference, caller must call Release
+ID3D11ShaderResourceView *RenderTarget11::getShaderResourceView() const
+{
+    if (mShaderResource)
+    {
+        mShaderResource->AddRef();
+    }
+
+    return mShaderResource;
+}
+
 unsigned int RenderTarget11::getSubresourceIndex() const
 {
     return mSubresourceIndex;
 }
 
-}
\ No newline at end of file
+}
diff --git a/src/libGLESv2/renderer/RenderTarget11.h b/src/libGLESv2/renderer/RenderTarget11.h
index 6a0c07e..a6c3d7c 100644
--- a/src/libGLESv2/renderer/RenderTarget11.h
+++ b/src/libGLESv2/renderer/RenderTarget11.h
@@ -22,8 +22,8 @@
 class RenderTarget11 : public RenderTarget
 {
   public:
-    RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *view, GLsizei width, GLsizei height);
-    RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *view, GLsizei width, GLsizei height);
+    RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *rtv, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height);
+    RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height);
     RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples, bool depth);
     virtual ~RenderTarget11();
 
@@ -35,6 +35,9 @@
     // Adds reference, caller must call Release
     ID3D11DepthStencilView *getDepthStencilView() const;
 
+    // Adds reference, caller must call Release
+    ID3D11ShaderResourceView *getShaderResourceView() const;
+
     unsigned int getSubresourceIndex() const;
 
   private:
@@ -43,6 +46,7 @@
     unsigned int mSubresourceIndex;
     ID3D11RenderTargetView *mRenderTarget;
     ID3D11DepthStencilView *mDepthStencil;
+    ID3D11ShaderResourceView *mShaderResource;
 
     Renderer11 *mRenderer;
 };
diff --git a/src/libGLESv2/renderer/Renderer11.cpp b/src/libGLESv2/renderer/Renderer11.cpp
index 412f6c1..d215e4b 100644
--- a/src/libGLESv2/renderer/Renderer11.cpp
+++ b/src/libGLESv2/renderer/Renderer11.cpp
@@ -1687,15 +1687,18 @@
 
 RenderTarget *Renderer11::createRenderTarget(SwapChain *swapChain, bool depth)
 {
-    SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain); 
+    SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain);
     RenderTarget11 *renderTarget = NULL;
     if (depth)
     {
-        renderTarget = new RenderTarget11(this, swapChain11->getDepthStencil(), swapChain11->getWidth(), swapChain11->getHeight());
+        renderTarget = new RenderTarget11(this, swapChain11->getDepthStencil(), NULL,
+                                          swapChain11->getWidth(), swapChain11->getHeight());
     }
     else
     {
-        renderTarget = new RenderTarget11(this, swapChain11->getRenderTarget(), swapChain11->getWidth(), swapChain11->getHeight());
+        renderTarget = new RenderTarget11(this, swapChain11->getRenderTarget(),
+                                          swapChain11->getRenderTargetShaderResource(),
+                                          swapChain11->getWidth(), swapChain11->getHeight());
     }
     return renderTarget;
 }
diff --git a/src/libGLESv2/renderer/TextureStorage11.cpp b/src/libGLESv2/renderer/TextureStorage11.cpp
index 5afe418..43a3a04 100644
--- a/src/libGLESv2/renderer/TextureStorage11.cpp
+++ b/src/libGLESv2/renderer/TextureStorage11.cpp
@@ -265,7 +265,23 @@
             }
             ASSERT(SUCCEEDED(result));
 
-            mRenderTarget[level] = new RenderTarget11(mRenderer, rtv,
+            D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+            srvDesc.Format = mTextureFormat;
+            srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+            srvDesc.Texture2D.MostDetailedMip = level;
+            srvDesc.Texture2D.MipLevels = 1;
+
+            ID3D11ShaderResourceView *srv;
+            result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
+
+            if (result == E_OUTOFMEMORY)
+            {
+                rtv->Release();
+                return error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
+            }
+            ASSERT(SUCCEEDED(result));
+
+            mRenderTarget[level] = new RenderTarget11(mRenderer, rtv, srv,
                                                       std::max(mTextureWidth >> level, 1U),
                                                       std::max(mTextureHeight >> level, 1U));
         }
@@ -430,7 +446,25 @@
                 }
                 ASSERT(SUCCEEDED(result));
 
-                mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, rtv,
+                D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+                srvDesc.Format = mTextureFormat;
+                srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
+                srvDesc.Texture2DArray.MostDetailedMip = level;
+                srvDesc.Texture2DArray.MipLevels = 1;
+                srvDesc.Texture2DArray.FirstArraySlice = faceIdx;
+                srvDesc.Texture2DArray.ArraySize = 1;
+
+                ID3D11ShaderResourceView *srv;
+                result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
+
+                if (result == E_OUTOFMEMORY)
+                {
+                    rtv->Release();
+                    return error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
+                }
+                ASSERT(SUCCEEDED(result));
+
+                mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, rtv, srv,
                                                                    std::max(mTextureWidth >> level, 1U),
                                                                    std::max(mTextureHeight >> level, 1U));
             }