Creates new depthstencils for surfaces.

Trac #11396

Creates new depthstencils for new windows when multiple windows exist,
repurposes original depthstencil if old windows have all been destroyed.
Author: Shannon Woods
Signed-off-by: Nicolas Capens
Signed-off-by: Daniel Koch

git-svn-id: https://angleproject.googlecode.com/svn/trunk@28 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/libEGL/Display.cpp b/libEGL/Display.cpp
index 31c25ef..9127577 100644
--- a/libEGL/Display.cpp
+++ b/libEGL/Display.cpp
@@ -235,6 +235,7 @@
     presentParameters.Windowed = TRUE;   // FIXME
 
     IDirect3DSwapChain9 *swapChain = NULL;
+    IDirect3DSurface9 *depthStencilSurface = NULL;
 
     if (!mDevice)
     {
@@ -250,25 +251,68 @@
         if (mDevice)
         {
             mDevice->GetSwapChain(0, &swapChain);
+            mDevice->GetDepthStencilSurface(&depthStencilSurface);
         }
     }
     else
     {
-        HRESULT result = mDevice->CreateAdditionalSwapChain(&presentParameters, &swapChain);
-
-        if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+        if (!mSurfaceSet.empty())
         {
-            return error(EGL_BAD_ALLOC, (egl::Surface*)NULL);
-        }
+            // if the device already exists, and there are other surfaces/windows currently in use, we need to create
+            // a separate swap chain for the new draw surface.
+            HRESULT result = mDevice->CreateAdditionalSwapChain(&presentParameters, &swapChain);
 
-        ASSERT(SUCCEEDED(result));
+            if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+            {
+                ERR("Could not create additional swap chains. Out of memory.");
+                return error(EGL_BAD_ALLOC, (egl::Surface*)NULL);
+            }
+
+            ASSERT(SUCCEEDED(result));
+
+            // CreateAdditionalSwapChain does not automatically generate a depthstencil surface, unlike 
+            // CreateDevice, so we must do so explicitly.
+            result = mDevice->CreateDepthStencilSurface(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight,
+                                                        presentParameters.AutoDepthStencilFormat, presentParameters.MultiSampleType,
+                                                        presentParameters.MultiSampleQuality, FALSE, &depthStencilSurface, NULL);
+
+            if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+            {
+                swapChain->Release();
+                ERR("Could not create depthstencil surface for new swap chain. Out of memory.");
+                return error(EGL_BAD_ALLOC, (egl::Surface*)NULL);
+            }
+
+            ASSERT(SUCCEEDED(result));
+        }
+        else
+        {
+            // if the device already exists, but there are no surfaces in use, then all the surfaces/windows
+            // have been destroyed, and we should repurpose the originally created depthstencil surface for
+            // use with the new surface we are creating.
+            HRESULT result = mDevice->Reset(&presentParameters);
+
+            if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+            {
+                ERR("Could not resent presentation parameters for device. Out of memory.");
+                return error(EGL_BAD_ALLOC, (egl::Surface*)NULL);
+            }
+
+            ASSERT(SUCCEEDED(result));
+
+            if (mDevice)
+            {
+                mDevice->GetSwapChain(0, &swapChain);
+                mDevice->GetDepthStencilSurface(&depthStencilSurface);
+            }
+        }
     }
 
     Surface *surface = NULL;
 
     if (swapChain)
     {
-        surface = new Surface(mDevice, swapChain, configuration->mConfigID);
+        surface = new Surface(mDevice, swapChain, depthStencilSurface, configuration->mConfigID);
         mSurfaceSet.insert(surface);
 
         swapChain->Release();