Enable multiple render targets in Renderer11::applyRenderTarget.

TRAC #22656

Signed-off-by: Nicolas Capens
Signed-off-by: Shannon Woods
Author: Jamie Madill

git-svn-id: https://angleproject.googlecode.com/svn/branches/es3proto@2077 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/renderer/Renderer11.cpp b/src/libGLESv2/renderer/Renderer11.cpp
index b50e85e..9f94682 100644
--- a/src/libGLESv2/renderer/Renderer11.cpp
+++ b/src/libGLESv2/renderer/Renderer11.cpp
@@ -814,29 +814,60 @@
 
 bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer)
 {
-    // TODO: mrt support
     // Get the color render buffer and serial
-    gl::Renderbuffer *colorbuffer = NULL;
-    unsigned int renderTargetSerial = 0;
-    if (framebuffer->getColorbufferType(0) != GL_NONE)
+    // Also extract the render target dimensions and view
+    unsigned int renderTargetWidth = 0;
+    unsigned int renderTargetHeight = 0;
+    GLenum renderTargetFormat = 0;
+    unsigned int renderTargetSerials[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {0};
+    ID3D11RenderTargetView* framebufferRTVs[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL};
+    bool missingColorRenderTarget = true;
+
+    for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
     {
-        colorbuffer = framebuffer->getColorbuffer(0);
-
-        if (!colorbuffer)
+        if (framebuffer->getColorbufferType(colorAttachment) != GL_NONE)
         {
-            ERR("render target pointer unexpectedly null.");
-            return false;
-        }
+            gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(colorAttachment);
 
-        // check for zero-sized default framebuffer, which is a special case.
-        // in this case we do not wish to modify any state and just silently return false.
-        // this will not report any gl error but will cause the calling method to return.
-        if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
-        {
-            return false;
-        }
+            if (!colorbuffer)
+            {
+                ERR("render target pointer unexpectedly null.");
+                return false;
+            }
 
-        renderTargetSerial = colorbuffer->getSerial();
+            // check for zero-sized default framebuffer, which is a special case.
+            // in this case we do not wish to modify any state and just silently return false.
+            // this will not report any gl error but will cause the calling method to return.
+            if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
+            {
+                return false;
+            }
+
+            renderTargetSerials[colorAttachment] = colorbuffer->getSerial();
+
+            // Extract the render target dimensions and view
+            RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget());
+            if (!renderTarget)
+            {
+                ERR("render target pointer unexpectedly null.");
+                return false;
+            }
+
+            framebufferRTVs[colorAttachment] = renderTarget->getRenderTargetView();
+            if (!framebufferRTVs[colorAttachment])
+            {
+                ERR("render target view pointer unexpectedly null.");
+                return false;
+            }
+
+            if (missingColorRenderTarget)
+            {
+                renderTargetWidth = colorbuffer->getWidth();
+                renderTargetHeight = colorbuffer->getHeight();
+                renderTargetFormat = colorbuffer->getActualFormat();
+                missingColorRenderTarget = false;
+            }
+        }
     }
 
     // Get the depth stencil render buffer and serials
@@ -849,6 +880,7 @@
         if (!depthStencil)
         {
             ERR("Depth stencil pointer unexpectedly null.");
+            SafeRelease(framebufferRTVs);
             return false;
         }
 
@@ -860,38 +892,13 @@
         if (!depthStencil)
         {
             ERR("Depth stencil pointer unexpectedly null.");
+            SafeRelease(framebufferRTVs);
             return false;
         }
 
         stencilbufferSerial = depthStencil->getSerial();
     }
 
-    // Extract the render target dimensions and view
-    unsigned int renderTargetWidth = 0;
-    unsigned int renderTargetHeight = 0;
-    GLenum renderTargetFormat = 0;
-    ID3D11RenderTargetView* framebufferRTV = NULL;
-    if (colorbuffer)
-    {
-        RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget());
-        if (!renderTarget)
-        {
-            ERR("render target pointer unexpectedly null.");
-            return false;
-        }
-
-        framebufferRTV = renderTarget->getRenderTargetView();
-        if (!framebufferRTV)
-        {
-            ERR("render target view pointer unexpectedly null.");
-            return false;
-        }
-
-        renderTargetWidth = colorbuffer->getWidth();
-        renderTargetHeight = colorbuffer->getHeight();
-        renderTargetFormat = colorbuffer->getActualFormat();
-    }
-
     // Extract the depth stencil sizes and view
     unsigned int depthSize = 0;
     unsigned int stencilSize = 0;
@@ -902,10 +909,7 @@
         if (!depthStencilRenderTarget)
         {
             ERR("render target pointer unexpectedly null.");
-            if (framebufferRTV)
-            {
-                framebufferRTV->Release();
-            }
+            SafeRelease(framebufferRTVs);
             return false;
         }
 
@@ -913,16 +917,13 @@
         if (!framebufferDSV)
         {
             ERR("depth stencil view pointer unexpectedly null.");
-            if (framebufferRTV)
-            {
-                framebufferRTV->Release();
-            }
+            SafeRelease(framebufferRTVs);
             return false;
         }
 
         // If there is no render buffer, the width, height and format values come from
         // the depth stencil
-        if (!colorbuffer)
+        if (missingColorRenderTarget)
         {
             renderTargetWidth = depthStencil->getWidth();
             renderTargetHeight = depthStencil->getHeight();
@@ -935,11 +936,11 @@
 
     // Apply the render target and depth stencil
     if (!mRenderTargetDescInitialized || !mDepthStencilInitialized ||
-        renderTargetSerial != mAppliedRenderTargetSerial ||
+        memcmp(renderTargetSerials, mAppliedRenderTargetSerials, sizeof(renderTargetSerials)) != 0 ||
         depthbufferSerial != mAppliedDepthbufferSerial ||
         stencilbufferSerial != mAppliedStencilbufferSerial)
     {
-        mDeviceContext->OMSetRenderTargets(1, &framebufferRTV, framebufferDSV);
+        mDeviceContext->OMSetRenderTargets(getMaxRenderTargets(), framebufferRTVs, framebufferDSV);
 
         mRenderTargetDesc.width = renderTargetWidth;
         mRenderTargetDesc.height = renderTargetHeight;
@@ -955,21 +956,18 @@
 
         mCurStencilSize = stencilSize;
 
-        mAppliedRenderTargetSerial = renderTargetSerial;
+        for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++)
+        {
+            mAppliedRenderTargetSerials[rtIndex] = renderTargetSerials[rtIndex];
+        }
         mAppliedDepthbufferSerial = depthbufferSerial;
         mAppliedStencilbufferSerial = stencilbufferSerial;
         mRenderTargetDescInitialized = true;
         mDepthStencilInitialized = true;
     }
 
-    if (framebufferRTV)
-    {
-        framebufferRTV->Release();
-    }
-    if (framebufferDSV)
-    {
-        framebufferDSV->Release();
-    }
+    SafeRelease(framebufferRTVs);
+    SafeRelease(framebufferDSV);
 
     return true;
 }
@@ -1695,7 +1693,10 @@
 
 void Renderer11::markAllStateDirty()
 {
-    mAppliedRenderTargetSerial = 0;
+    for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++)
+    {
+        mAppliedRenderTargetSerials[rtIndex] = 0;
+    }
     mAppliedDepthbufferSerial = 0;
     mAppliedStencilbufferSerial = 0;
     mDepthStencilInitialized = false;