Support window resizing

TRAC #12660

Automatically resize the D3D swap chain when the eglSwapBuffers is called and the presentation window has changed size.
Also change D3D device init to be performed once when the Display is created using a hidden 1x1 window.

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

Author:    Andrew Lewycky

git-svn-id: https://angleproject.googlecode.com/svn/trunk@365 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libEGL/Display.cpp b/src/libEGL/Display.cpp
index ac12499..941a1b0 100644
--- a/src/libEGL/Display.cpp
+++ b/src/libEGL/Display.cpp
@@ -25,6 +25,7 @@
 {
     mD3d9 = NULL;
     mDevice = NULL;
+    mDeviceWindow = NULL;
 
     mAdapter = D3DADAPTER_DEFAULT;
 
@@ -150,6 +151,13 @@
                 mConfigSet.mSet.insert(configuration);
             }
         }
+
+        if (!createDevice())
+        {
+            terminate();
+
+            return false;
+        }
     }
 
     if (!isInitialized())
@@ -185,6 +193,12 @@
         mD3d9->Release();
         mD3d9 = NULL;
     }
+
+    if (mDeviceWindow)
+    {
+        DestroyWindow(mDeviceWindow);
+        mDeviceWindow = NULL;
+    }
 }
 
 void Display::startScene()
@@ -254,126 +268,65 @@
     return true;
 }
 
+bool Display::createDevice()

+{

+    static const TCHAR windowName[] = TEXT("AngleHiddenWindow");

+    static const TCHAR className[] = TEXT("STATIC");

+

+    mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL);

+

+    D3DPRESENT_PARAMETERS presentParameters = {0};

+

+    // The default swap chain is never actually used. Surface will create a new swap chain with the proper parameters.

+    presentParameters.AutoDepthStencilFormat = D3DFMT_UNKNOWN;

+    presentParameters.BackBufferCount = 1;

+    presentParameters.BackBufferFormat = D3DFMT_UNKNOWN;

+    presentParameters.BackBufferWidth = 1;

+    presentParameters.BackBufferHeight = 1;

+    presentParameters.EnableAutoDepthStencil = FALSE;

+    presentParameters.Flags = 0;

+    presentParameters.hDeviceWindow = mDeviceWindow;

+    presentParameters.MultiSampleQuality = 0;

+    presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;

+    presentParameters.PresentationInterval = convertInterval(mMinSwapInterval);

+    presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;

+    presentParameters.Windowed = TRUE;

+

+    DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES;

+

+    HRESULT result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice);

+

+    if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)

+    {

+        return error(EGL_BAD_ALLOC, false);

+    }

+

+    if (FAILED(result))

+    {

+        result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice);

+

+        if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)

+        {

+            return error(EGL_BAD_ALLOC, false);

+        }

+    }

+

+    ASSERT(SUCCEEDED(result));

+

+    // Permanent non-default states

+    mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);

+

+    mSceneStarted = false;

+

+    return true;

+}
+
 Surface *Display::createWindowSurface(HWND window, EGLConfig config)
 {
     const Config *configuration = mConfigSet.get(config);
 
-    D3DPRESENT_PARAMETERS presentParameters = {0};
-
-    presentParameters.AutoDepthStencilFormat = configuration->mDepthStencilFormat;
-    presentParameters.BackBufferCount = 1;
-    presentParameters.BackBufferFormat = configuration->mRenderTargetFormat;
-    presentParameters.BackBufferWidth = 0;
-    presentParameters.BackBufferHeight = 0;
-    presentParameters.EnableAutoDepthStencil = configuration->mDepthSize ? TRUE : FALSE;
-    presentParameters.Flags = 0;
-    presentParameters.hDeviceWindow = window;
-    presentParameters.MultiSampleQuality = 0;                  // FIXME: Unimplemented
-    presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;   // FIXME: Unimplemented
-    presentParameters.PresentationInterval = convertInterval(mMinSwapInterval);
-    presentParameters.SwapEffect = D3DSWAPEFFECT_COPY;
-    presentParameters.Windowed = TRUE;   // FIXME
-
-    IDirect3DSwapChain9 *swapChain = NULL;
-    IDirect3DSurface9 *depthStencilSurface = NULL;
-
-    if (!mDevice)
-    {
-        DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES;
-
-        HRESULT result = mD3d9->CreateDevice(mAdapter, mDeviceType, window, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice);
-
-        if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
-        {
-            return error(EGL_BAD_ALLOC, (egl::Surface*)NULL);
-        }
-
-        if (FAILED(result))
-        {
-            result = mD3d9->CreateDevice(mAdapter, mDeviceType, window, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice);
-
-            if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
-            {
-                return error(EGL_BAD_ALLOC, (egl::Surface*)NULL);
-            }
-        }
-
-        ASSERT(SUCCEEDED(result));
-
-        if (mDevice)
-        {
-            mSceneStarted = false;
-            mDevice->GetSwapChain(0, &swapChain);
-            mDevice->GetDepthStencilSurface(&depthStencilSurface);
-        }
-    }
-    else
-    {
-        if (!mSurfaceSet.empty())
-        {
-            // 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);
-
-            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 reset presentation parameters for device. Out of memory.");
-                return error(EGL_BAD_ALLOC, (egl::Surface*)NULL);
-            }
-
-            ASSERT(SUCCEEDED(result));
-
-            if (mDevice)
-            {
-                mSceneStarted = false;
-                mDevice->GetSwapChain(0, &swapChain);
-                mDevice->GetDepthStencilSurface(&depthStencilSurface);
-            }
-        }
-    }
-
-    // Permanent non-default states
-    mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
-
-    Surface *surface = NULL;
-
-    if (swapChain)
-    {
-        surface = new Surface(this, swapChain, depthStencilSurface, configuration);
-        mSurfaceSet.insert(surface);
-
-        swapChain->Release();
-    }
+    Surface *surface = new Surface(this, configuration, window);
+    mSurfaceSet.insert(surface);
 
     return surface;
 }
diff --git a/src/libEGL/Display.h b/src/libEGL/Display.h
index 8f3aea3..12ce6c9 100644
--- a/src/libEGL/Display.h
+++ b/src/libEGL/Display.h
@@ -70,6 +70,7 @@
     IDirect3D9 *mD3d9;
     IDirect3DDevice9 *mDevice;
     D3DCAPS9 mDeviceCaps;
+    HWND mDeviceWindow;
 
     bool mSceneStarted;
     GLint mSwapInterval;
@@ -84,6 +85,8 @@
 
     typedef std::set<gl::Context*> ContextSet;
     ContextSet mContextSet;
+
+    bool createDevice();
 };
 }
 
diff --git a/src/libEGL/Surface.cpp b/src/libEGL/Surface.cpp
index ef5c6c7..1acc46e 100644
--- a/src/libEGL/Surface.cpp
+++ b/src/libEGL/Surface.cpp
@@ -17,9 +17,11 @@
 
 namespace egl
 {
-Surface::Surface(Display *display, IDirect3DSwapChain9 *swapChain, IDirect3DSurface9 *depthStencil, const Config *config) 
-    : mDisplay(display), mSwapChain(swapChain), mDepthStencil(depthStencil), mConfig(config)
+Surface::Surface(Display *display, const Config *config, HWND window) 
+    : mDisplay(display), mConfig(config), mWindow(window)
 {
+    mSwapChain = NULL;
+    mDepthStencil = NULL;
     mBackBuffer = NULL;
     mRenderTarget = NULL;
     mFlipTexture = NULL;
@@ -30,42 +32,7 @@
     mRenderBuffer = EGL_BACK_BUFFER;
     mSwapBehavior = EGL_BUFFER_PRESERVED;
 
-    if (mSwapChain)
-    {
-        mSwapChain->AddRef();
-        mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer);
-
-        D3DSURFACE_DESC description;
-        mBackBuffer->GetDesc(&description);
-
-        mWidth = description.Width;
-        mHeight = description.Height;
-
-        IDirect3DDevice9 *device = display->getDevice();
-        HRESULT result = device->CreateRenderTarget(mWidth, mHeight, description.Format, description.MultiSampleType, description.MultiSampleQuality, FALSE, &mRenderTarget, NULL);
-
-        if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
-        {
-            error(EGL_BAD_ALLOC);
-
-            return;
-        }
-
-        ASSERT(SUCCEEDED(result));
-
-        result = device->CreateTexture(mWidth, mHeight, 1, D3DUSAGE_RENDERTARGET, description.Format, D3DPOOL_DEFAULT, &mFlipTexture, NULL);
-
-        if (FAILED(result))
-        {
-            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-
-            error(EGL_BAD_ALLOC);
-
-            mRenderTarget->Release();
-
-            return;
-        }
-    }
+    resetSwapChain();
 }
 
 Surface::~Surface()
@@ -106,20 +73,116 @@
     }
 }
 
-HWND Surface::getWindowHandle()
+void Surface::resetSwapChain()
 {
-    if (mSwapChain)
-    {
-        D3DPRESENT_PARAMETERS presentParameters;
-        mSwapChain->GetPresentParameters(&presentParameters);
+    IDirect3DDevice9 *device = mDisplay->getDevice();
 
-        return presentParameters.hDeviceWindow;
+    D3DPRESENT_PARAMETERS presentParameters = {0};
+
+    presentParameters.AutoDepthStencilFormat = mConfig->mDepthStencilFormat;
+    presentParameters.BackBufferCount = 1;
+    presentParameters.BackBufferFormat = mConfig->mRenderTargetFormat;
+    presentParameters.EnableAutoDepthStencil = FALSE;
+    presentParameters.Flags = 0;
+    presentParameters.hDeviceWindow = getWindowHandle();
+    presentParameters.MultiSampleQuality = 0;                  // FIXME: Unimplemented
+    presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;   // FIXME: Unimplemented
+    presentParameters.PresentationInterval = Display::convertInterval(mConfig->mMinSwapInterval);
+    presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
+    presentParameters.Windowed = TRUE;
+
+    RECT windowRect;
+    GetClientRect(getWindowHandle(), &windowRect);
+    presentParameters.BackBufferWidth = windowRect.right - windowRect.left;
+    presentParameters.BackBufferHeight = windowRect.bottom - windowRect.top;
+
+    IDirect3DSwapChain9 *swapChain = NULL;
+    HRESULT result = device->CreateAdditionalSwapChain(&presentParameters, &swapChain);
+
+    if (FAILED(result))
+    {
+        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+
+        ERR("Could not create additional swap chains: %08lX", result);
+        return error(EGL_BAD_ALLOC);
     }
 
-    return NULL;
+    IDirect3DSurface9 *depthStencilSurface = NULL;
+    result = device->CreateDepthStencilSurface(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight,
+                                               presentParameters.AutoDepthStencilFormat, presentParameters.MultiSampleType,
+                                               presentParameters.MultiSampleQuality, FALSE, &depthStencilSurface, NULL);
+
+    if (FAILED(result))
+    {
+        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+
+        swapChain->Release();
+
+        ERR("Could not create depthstencil surface for new swap chain: %08lX", result);
+        return error(EGL_BAD_ALLOC);
+    }
+
+    IDirect3DSurface9 *renderTarget = NULL;
+    result = device->CreateRenderTarget(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight, presentParameters.BackBufferFormat,
+                                        presentParameters.MultiSampleType, presentParameters.MultiSampleQuality, FALSE, &renderTarget, NULL);
+
+    if (FAILED(result))
+    {
+        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+
+        swapChain->Release();
+        depthStencilSurface->Release();
+
+        ERR("Could not create render target surface for new swap chain: %08lX", result);
+        return error(EGL_BAD_ALLOC);
+    }
+
+    ASSERT(SUCCEEDED(result));
+
+    IDirect3DTexture9 *flipTexture = NULL;
+    result = device->CreateTexture(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight, 1, D3DUSAGE_RENDERTARGET,
+                                   presentParameters.BackBufferFormat, D3DPOOL_DEFAULT, &flipTexture, NULL);
+
+    if (FAILED(result))
+    {
+        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+
+        swapChain->Release();
+        depthStencilSurface->Release();
+        renderTarget->Release();
+
+        ERR("Could not create flip texture for new swap chain: %08lX", result);
+        return error(EGL_BAD_ALLOC);
+    }
+
+    IDirect3DSurface9 *backBuffer = NULL;
+    swapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);
+
+    if (mSwapChain) mSwapChain->Release();
+    if (mDepthStencil) mDepthStencil->Release();
+    if (mBackBuffer) mBackBuffer->Release();
+    if (mRenderTarget) mRenderTarget->Release();
+    if (mFlipTexture) mFlipTexture->Release();
+
+    mWidth = presentParameters.BackBufferWidth;
+    mHeight = presentParameters.BackBufferHeight;
+
+    mSwapChain = swapChain;
+    mDepthStencil = depthStencilSurface;
+    mBackBuffer = backBuffer;
+    mRenderTarget = renderTarget;
+    mFlipTexture = flipTexture;
+
+    // The flip state block recorded mFlipTexture so it is now invalid.
+    releaseRecordedState(device);
 }
 
-void Surface::writeRecordableFlipState(IDirect3DDevice9 *device, IDirect3DTexture9 *source)
+HWND Surface::getWindowHandle()
+{
+    return mWindow;
+}
+
+void Surface::writeRecordableFlipState(IDirect3DDevice9 *device)
 {
     // Disable all pipeline operations
     device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
@@ -138,16 +201,18 @@
     device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
     device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
     device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
-    device->SetTexture(0, source);
+    device->SetTexture(0, NULL); // The actual texture will change after resizing. But the pre-flip state block must save/restore the texture.
     device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
     device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
     device->SetSamplerState(0, D3DSAMP_SRGBTEXTURE, FALSE);
+    device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
+    device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
     device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
 
     device->SetStreamSourceFreq(0, 1); // DrawPrimitiveUP only cares about stream 0, not the rest.
 }
 
-void Surface::applyFlipState(IDirect3DDevice9 *device, IDirect3DTexture9 *source)
+void Surface::applyFlipState(IDirect3DDevice9 *device)
 {
     HRESULT hr;
 
@@ -158,7 +223,7 @@
         // mPreFlipState will record the original state each entry.
         hr = device->BeginStateBlock();
         ASSERT(SUCCEEDED(hr));
-        writeRecordableFlipState(device, source);
+        writeRecordableFlipState(device);
         hr = device->EndStateBlock(&mPreFlipState);
         ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
 
@@ -171,7 +236,7 @@
         hr = device->BeginStateBlock();
         ASSERT(SUCCEEDED(hr));
 
-        writeRecordableFlipState(device, source);
+        writeRecordableFlipState(device);
 
         hr = device->EndStateBlock(&mFlipState);
         ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
@@ -223,29 +288,83 @@
     }
 }
 
+// On the next flip, this will cause the state to be recorded from scratch.
+// In particular we need to do this if the flip texture changes.
+void Surface::releaseRecordedState(IDirect3DDevice9 *device)
+{
+    if (mFlipState)
+    {
+        mFlipState->Release();
+        mFlipState = NULL;
+    }
+
+    if (mPreFlipState)
+    {
+        mPreFlipState->Release();
+        mPreFlipState = NULL;
+    }
+}
+
+bool Surface::checkForWindowResize()
+{
+    RECT client;
+    GetClientRect(getWindowHandle(), &client);
+    if (getWidth() != client.right - client.left || getHeight() != client.bottom - client.top)
+    {
+        resetSwapChain();
+
+        if (static_cast<egl::Surface*>(getCurrentDrawSurface()) == this)
+        {
+            glMakeCurrent(glGetCurrentContext(), static_cast<egl::Display*>(getCurrentDisplay()), this);
+        }
+
+        return true;
+    }
+
+    return false;
+}
+
 bool Surface::swap()
 {
     if (mSwapChain)
     {
+        IDirect3DTexture9 *flipTexture = mFlipTexture;
+        flipTexture->AddRef();
+
+        IDirect3DSurface9 *renderTarget = mRenderTarget;
+        renderTarget->AddRef();
+
+        EGLint oldWidth = mWidth;
+        EGLint oldHeight = mHeight;
+
+        checkForWindowResize();
+
         IDirect3DDevice9 *device = mDisplay->getDevice();
 
         IDirect3DSurface9 *textureSurface;
-        mFlipTexture->GetSurfaceLevel(0, &textureSurface);
+        flipTexture->GetSurfaceLevel(0, &textureSurface);
 
         mDisplay->endScene();
-        device->StretchRect(mRenderTarget, NULL, textureSurface, NULL, D3DTEXF_NONE);
+        device->StretchRect(renderTarget, NULL, textureSurface, NULL, D3DTEXF_NONE);
+        renderTarget->Release();
 
-        applyFlipState(device, mFlipTexture);
+        applyFlipState(device);
+        device->SetTexture(0, flipTexture);
+
+        float xscale = (float)mWidth / oldWidth;
+        float yscale = (float)mHeight / oldHeight;
 
         // Render the texture upside down into the back buffer
-        float quad[4][6] = {{     0 - 0.5f,       0 - 0.5f, 0.0f, 1.0f, 0.0f, 1.0f},
-                            {mWidth - 0.5f,       0 - 0.5f, 0.0f, 1.0f, 1.0f, 1.0f},
-                            {mWidth - 0.5f, mHeight - 0.5f, 0.0f, 1.0f, 1.0f, 0.0f},
-                            {     0 - 0.5f, mHeight - 0.5f, 0.0f, 1.0f, 0.0f, 0.0f}};   // x, y, z, rhw, u, v
+        // Texcoords are chosen to pin a potentially resized image into the upper-left corner without scaling.
+        float quad[4][6] = {{     0 - 0.5f,       0 - 0.5f, 0.0f, 1.0f, 0.0f,   1.0f       },
+                            {mWidth - 0.5f,       0 - 0.5f, 0.0f, 1.0f, xscale, 1.0f       },
+                            {mWidth - 0.5f, mHeight - 0.5f, 0.0f, 1.0f, xscale, 1.0f-yscale},
+                            {     0 - 0.5f, mHeight - 0.5f, 0.0f, 1.0f, 0.0f,   1.0f-yscale}};   // x, y, z, rhw, u, v
 
         mDisplay->startScene();
         device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float));
 
+        flipTexture->Release();
         textureSurface->Release();
 
         restoreState(device);
@@ -264,6 +383,7 @@
         }
 
         ASSERT(SUCCEEDED(result));
+
     }
 
     return true;
diff --git a/src/libEGL/Surface.h b/src/libEGL/Surface.h
index 8c684a0..5bc912c 100644
--- a/src/libEGL/Surface.h
+++ b/src/libEGL/Surface.h
@@ -25,7 +25,7 @@
 class Surface
 {
   public:
-    Surface(Display *display, IDirect3DSwapChain9 *swapChain, IDirect3DSurface9* depthStencil, const egl::Config *config);
+    Surface(Display *display, const egl::Config *config, HWND window);
 
     ~Surface();
 
@@ -42,20 +42,25 @@
     DISALLOW_COPY_AND_ASSIGN(Surface);
 
     Display *const mDisplay;
-    IDirect3DSwapChain9 *const mSwapChain;
+    IDirect3DSwapChain9 *mSwapChain;
     IDirect3DSurface9 *mBackBuffer;
     IDirect3DSurface9 *mRenderTarget;
     IDirect3DSurface9 *mDepthStencil;
     IDirect3DTexture9 *mFlipTexture;
 
-    void applyFlipState(IDirect3DDevice9 *device, IDirect3DTexture9 *source);
+    void resetSwapChain();
+    bool checkForWindowResize();
+
+    void applyFlipState(IDirect3DDevice9 *device);
     void restoreState(IDirect3DDevice9 *device);
-    void writeRecordableFlipState(IDirect3DDevice9 *device, IDirect3DTexture9 *source);
+    void writeRecordableFlipState(IDirect3DDevice9 *device);
+    void releaseRecordedState(IDirect3DDevice9 *device);
     IDirect3DStateBlock9 *mFlipState;
     IDirect3DStateBlock9 *mPreFlipState;
     IDirect3DSurface9 *mPreFlipBackBuffer;
     IDirect3DSurface9 *mPreFlipDepthStencil;
 
+    const HWND mWindow;            // Window that the surface is created for.
     const egl::Config *mConfig;    // EGL config surface was created with
     EGLint mHeight;                // Height of surface
     EGLint mWidth;                 // Width of surface