Bladeren bron

Merge pull request #1859 from rextimmy/multicanvas_gl_dx11

Multiple canvas support for GL and DX11
Areloch 8 jaren geleden
bovenliggende
commit
fb9bd03073

+ 74 - 218
Engine/source/gfx/D3D11/gfxD3D11Device.cpp

@@ -261,73 +261,59 @@ void GFXD3D11Device::enumerateVideoModes()
    SAFE_RELEASE(DXGIFactory);
 }
 
-IDXGISwapChain* GFXD3D11Device::getSwapChain()
-{
-   return mSwapChain;
-}
-
 void GFXD3D11Device::init(const GFXVideoMode &mode, PlatformWindow *window)
 {
    AssertFatal(window, "GFXD3D11Device::init - must specify a window!");
 
-   HWND winHwnd = (HWND)window->getSystemWindow( PlatformWindow::WindowSystem_Windows );
-
    UINT createDeviceFlags = D3D11_CREATE_DEVICE_SINGLETHREADED | D3D11_CREATE_DEVICE_BGRA_SUPPORT;
 #ifdef TORQUE_DEBUG
    createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
    mDebugLayers = true;
 #endif
 
-   DXGI_SWAP_CHAIN_DESC d3dpp = setupPresentParams(mode, winHwnd);
-
    D3D_FEATURE_LEVEL deviceFeature;
    D3D_DRIVER_TYPE driverType = D3D_DRIVER_TYPE_HARDWARE;// use D3D_DRIVER_TYPE_REFERENCE for reference device
-   // create a device, device context and swap chain using the information in the d3dpp struct
-   HRESULT hres = D3D11CreateDeviceAndSwapChain(NULL,
-                                 driverType,
-                                 NULL,
-                                 createDeviceFlags,
-                                 NULL,
-                                 0,
-                                 D3D11_SDK_VERSION,
-                                 &d3dpp,
-                                 &mSwapChain,
-                                 &mD3DDevice,
-                                 &deviceFeature,
-                                 &mD3DDeviceContext);
+   // create a device & device context
+   HRESULT hres = D3D11CreateDevice(NULL,
+                                    driverType,
+                                    NULL,
+                                    createDeviceFlags,
+                                    NULL,
+                                    0,
+                                    D3D11_SDK_VERSION,
+                                    &mD3DDevice,
+                                    &deviceFeature,
+                                    &mD3DDeviceContext);
 
    if(FAILED(hres))
    {
       #ifdef TORQUE_DEBUG
-      //try again without debug device layer enabled
-      createDeviceFlags &= ~D3D11_CREATE_DEVICE_DEBUG;
-      HRESULT hres = D3D11CreateDeviceAndSwapChain(NULL, driverType,NULL,createDeviceFlags,NULL, 0,
-         D3D11_SDK_VERSION,
-         &d3dpp,
-         &mSwapChain,
-         &mD3DDevice,
-         &deviceFeature,
-         &mD3DDeviceContext);
-      //if we failed again than we definitely have a problem
-      if (FAILED(hres))
-         AssertFatal(false, "GFXD3D11Device::init - D3D11CreateDeviceAndSwapChain failed!");
-
-      Con::warnf("GFXD3D11Device::init - Debug layers not detected!");
-      mDebugLayers = false;
+         //try again without debug device layer enabled
+         createDeviceFlags &= ~D3D11_CREATE_DEVICE_DEBUG;
+         hres = D3D11CreateDevice(NULL,
+                                  driverType,
+                                  NULL,
+                                  createDeviceFlags,
+                                  NULL,
+                                  0,
+                                  D3D11_SDK_VERSION,
+                                  &mD3DDevice,
+                                  &deviceFeature,
+                                  &mD3DDeviceContext);
+         //if we failed again than we definitely have a problem
+         if (FAILED(hres))
+            AssertFatal(false, "GFXD3D11Device::init - D3D11CreateDeviceAndSwapChain failed!");
+
+         Con::warnf("GFXD3D11Device::init - Debug layers not detected!");
+         mDebugLayers = false;
       #else
-      AssertFatal(false, "GFXD3D11Device::init - D3D11CreateDeviceAndSwapChain failed!");
+         AssertFatal(false, "GFXD3D11Device::init - D3D11CreateDeviceAndSwapChain failed!");
       #endif
    }
 
-   //set the fullscreen state here if we need to
-   if(mode.fullScreen)
-   {
-      hres = mSwapChain->SetFullscreenState(TRUE, NULL);
-      if(FAILED(hres))
-      {
-         AssertFatal(false, "GFXD3D11Device::init- Failed to set fullscreen state!");
-      }
-   }
+#ifdef TORQUE_DEBUG
+   _suppressDebugMessages();
+#endif
 
    mTextureManager = new GFXD3D11TextureManager();
 
@@ -355,68 +341,6 @@ void GFXD3D11Device::init(const GFXVideoMode &mode, PlatformWindow *window)
    mCardProfiler = new GFXD3D11CardProfiler();
    mCardProfiler->init();
 
-   D3D11_TEXTURE2D_DESC desc;
-   desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
-   desc.CPUAccessFlags = 0;
-   desc.Format = GFXD3D11TextureFormat[GFXFormatD24S8];
-   desc.MipLevels = 1;
-   desc.ArraySize = 1;
-   desc.Usage = D3D11_USAGE_DEFAULT;
-   desc.Width = mode.resolution.x;
-   desc.Height = mode.resolution.y;
-   desc.SampleDesc.Count =1;
-   desc.SampleDesc.Quality =0;
-   desc.MiscFlags = 0;
-
-   HRESULT hr = mD3DDevice->CreateTexture2D(&desc, NULL, &mDeviceDepthStencil);
-   if(FAILED(hr)) 
-   {
-      AssertFatal(false, "GFXD3D11Device::init - couldn't create device's depth-stencil surface.");
-   }
-
-   D3D11_DEPTH_STENCIL_VIEW_DESC depthDesc;
-   depthDesc.Format = GFXD3D11TextureFormat[GFXFormatD24S8];
-   depthDesc.Flags =0 ;
-   depthDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
-   depthDesc.Texture2D.MipSlice = 0;
-
-   hr = mD3DDevice->CreateDepthStencilView(mDeviceDepthStencil, &depthDesc, &mDeviceDepthStencilView);
-
-   if(FAILED(hr))
-   {
-      AssertFatal(false, "GFXD3D11Device::init - couldn't create depth stencil view");
-   }
-
-   hr = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mDeviceBackbuffer);
-   if(FAILED(hr))
-     AssertFatal(false, "GFXD3D11Device::init - coudln't retrieve backbuffer ref");
-
-   //create back buffer view
-   D3D11_RENDER_TARGET_VIEW_DESC RTDesc;
-
-   RTDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
-   RTDesc.Texture2D.MipSlice = 0;
-   RTDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
-
-   hr = mD3DDevice->CreateRenderTargetView(mDeviceBackbuffer, &RTDesc, &mDeviceBackBufferView);
-
-   if(FAILED(hr))
-       AssertFatal(false, "GFXD3D11Device::init - couldn't create back buffer target view");
-
-#ifdef TORQUE_DEBUG
-   String backBufferName = "MainBackBuffer";
-   String depthSteniclName = "MainDepthStencil";
-   String backBuffViewName = "MainBackBuffView";
-   String depthStencViewName = "MainDepthView";
-   mDeviceBackbuffer->SetPrivateData(WKPDID_D3DDebugObjectName, backBufferName.size(), backBufferName.c_str());
-   mDeviceDepthStencil->SetPrivateData(WKPDID_D3DDebugObjectName, depthSteniclName.size(), depthSteniclName.c_str());
-   mDeviceDepthStencilView->SetPrivateData(WKPDID_D3DDebugObjectName, depthStencViewName.size(), depthStencViewName.c_str());
-   mDeviceBackBufferView->SetPrivateData(WKPDID_D3DDebugObjectName, backBuffViewName.size(), backBuffViewName.c_str());
-
-   _suppressDebugMessages();
-
-#endif
-
    gScreenShot = new ScreenShotD3D11;
 
    mInitialized = true;
@@ -466,14 +390,35 @@ GFXWindowTarget * GFXD3D11Device::allocWindowTarget(PlatformWindow *window)
 {
    AssertFatal(window,"GFXD3D11Device::allocWindowTarget - no window provided!");
 
-   // Allocate the device.
-   init(window->getVideoMode(), window);
-
    // Set up a new window target...
    GFXD3D11WindowTarget *gdwt = new GFXD3D11WindowTarget();
    gdwt->mWindow = window;
    gdwt->mSize = window->getClientExtent();
-   gdwt->initPresentationParams();
+   
+   if (!mInitialized)
+   {
+      gdwt->mSecondaryWindow = false;
+      // Allocate the device.
+      init(window->getVideoMode(), window);
+      gdwt->initPresentationParams();
+      gdwt->createSwapChain();
+      gdwt->createBuffersAndViews();
+
+      mSwapChain = gdwt->getSwapChain();
+      mDeviceBackbuffer = gdwt->getBackBuffer();
+      mDeviceDepthStencil = gdwt->getDepthStencil();
+      mDeviceBackBufferView = gdwt->getBackBufferView();
+      mDeviceDepthStencilView = gdwt->getDepthStencilView();
+
+   }
+   else //additional window/s
+   {
+      gdwt->mSecondaryWindow = true;
+      gdwt->initPresentationParams();
+      gdwt->createSwapChain();
+      gdwt->createBuffersAndViews();
+   }
+   
    gdwt->registerResourceWithDevice(this);
 
    return gdwt;
@@ -487,13 +432,15 @@ GFXTextureTarget* GFXD3D11Device::allocRenderToTextureTarget()
    return targ;
 }
 
-void GFXD3D11Device::reset(DXGI_SWAP_CHAIN_DESC &d3dpp)
+void GFXD3D11Device::beginReset()
 {
    if (!mD3DDevice)
       return;
 
    mInitialized = false;
 
+   releaseDefaultPoolResources();
+
    // Clean up some commonly dangling state. This helps prevents issues with
    // items that are destroyed by the texture manager callbacks and recreated
    // later, but still left bound.
@@ -504,117 +451,26 @@ void GFXD3D11Device::reset(DXGI_SWAP_CHAIN_DESC &d3dpp)
 
    mD3DDeviceContext->ClearState();
 
-   DXGI_MODE_DESC displayModes;
-   displayModes.Format = d3dpp.BufferDesc.Format;
-   displayModes.Height = d3dpp.BufferDesc.Height;
-   displayModes.Width = d3dpp.BufferDesc.Width;
-   displayModes.RefreshRate = d3dpp.BufferDesc.RefreshRate;
-   displayModes.Scaling = d3dpp.BufferDesc.Scaling;
-   displayModes.ScanlineOrdering = d3dpp.BufferDesc.ScanlineOrdering;
-
-   HRESULT hr;
-   if (!d3dpp.Windowed)
-   {
-      hr = mSwapChain->ResizeTarget(&displayModes);
-
-      if (FAILED(hr))
-      {
-         AssertFatal(false, "D3D11Device::reset - failed to resize target!");
-      }
-   }
-
-   // First release all the stuff we allocated from D3DPOOL_DEFAULT
-   releaseDefaultPoolResources();
-
-   //release the backbuffer, depthstencil, and their views
-   SAFE_RELEASE(mDeviceBackBufferView);
-   SAFE_RELEASE(mDeviceBackbuffer);
+   //release old buffers and views
    SAFE_RELEASE(mDeviceDepthStencilView);
+   SAFE_RELEASE(mDeviceBackBufferView);
    SAFE_RELEASE(mDeviceDepthStencil);
+   SAFE_RELEASE(mDeviceBackbuffer);
+}
 
-   hr = mSwapChain->ResizeBuffers(d3dpp.BufferCount, d3dpp.BufferDesc.Width, d3dpp.BufferDesc.Height, d3dpp.BufferDesc.Format, d3dpp.Windowed ? 0 : DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH);
-
-   if (FAILED(hr))
-   {
-      AssertFatal(false, "D3D11Device::reset - failed to resize back buffer!");
-   }
-
-   //recreate backbuffer view. depth stencil view and texture
-   D3D11_TEXTURE2D_DESC desc;
-   desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
-   desc.CPUAccessFlags = 0;
-   desc.Format = GFXD3D11TextureFormat[GFXFormatD24S8];
-   desc.MipLevels = 1;
-   desc.ArraySize = 1;
-   desc.Usage = D3D11_USAGE_DEFAULT;
-   desc.Width = d3dpp.BufferDesc.Width;
-   desc.Height = d3dpp.BufferDesc.Height;
-   desc.SampleDesc.Count = 1;
-   desc.SampleDesc.Quality = 0;
-   desc.MiscFlags = 0;
-
-   hr = mD3DDevice->CreateTexture2D(&desc, NULL, &mDeviceDepthStencil);
-   if (FAILED(hr))
-   {
-      AssertFatal(false, "GFXD3D11Device::reset - couldn't create device's depth-stencil surface.");
-   }
-
-   D3D11_DEPTH_STENCIL_VIEW_DESC depthDesc;
-   depthDesc.Format = GFXD3D11TextureFormat[GFXFormatD24S8];
-   depthDesc.Flags = 0;
-   depthDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
-   depthDesc.Texture2D.MipSlice = 0;
-
-   hr = mD3DDevice->CreateDepthStencilView(mDeviceDepthStencil, &depthDesc, &mDeviceDepthStencilView);
-
-   if (FAILED(hr))
-   {
-      AssertFatal(false, "GFXD3D11Device::reset - couldn't create depth stencil view");
-   }
-
-   hr = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mDeviceBackbuffer);
-   if (FAILED(hr))
-      AssertFatal(false, "GFXD3D11Device::reset - coudln't retrieve backbuffer ref");
-
-   //create back buffer view
-   D3D11_RENDER_TARGET_VIEW_DESC RTDesc;
-
-   RTDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
-   RTDesc.Texture2D.MipSlice = 0;
-   RTDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
-
-   hr = mD3DDevice->CreateRenderTargetView(mDeviceBackbuffer, &RTDesc, &mDeviceBackBufferView);
-
-   if (FAILED(hr))
-      AssertFatal(false, "GFXD3D11Device::reset - couldn't create back buffer target view");
+void GFXD3D11Device::endReset(GFXD3D11WindowTarget *windowTarget)
+{
+   //grab new references
+   mDeviceBackbuffer = windowTarget->getBackBuffer();
+   mDeviceDepthStencil = windowTarget->getDepthStencil();
+   mDeviceBackBufferView = windowTarget->getBackBufferView();
+   mDeviceDepthStencilView = windowTarget->getDepthStencilView();
 
    mD3DDeviceContext->OMSetRenderTargets(1, &mDeviceBackBufferView, mDeviceDepthStencilView);
 
-   hr = mSwapChain->SetFullscreenState(!d3dpp.Windowed, NULL);
-
-   if (FAILED(hr))
-   {
-      AssertFatal(false, "D3D11Device::reset - failed to change screen states!");
-   }
-
-   //Microsoft recommend this, see DXGI documentation
-   if (!d3dpp.Windowed)
-   {
-      displayModes.RefreshRate.Numerator = 0;
-      displayModes.RefreshRate.Denominator = 0;
-      hr = mSwapChain->ResizeTarget(&displayModes);
-
-      if (FAILED(hr))
-      {
-         AssertFatal(false, "D3D11Device::reset - failed to resize target!");
-      }
-   }
-
-   mInitialized = true;
-
-   // Now re aquire all the resources we trashed earlier
+   // Now reacquire all the resources we trashed earlier
    reacquireDefaultPoolResources();
-
+   mInitialized = true;
    // Mark everything dirty and flush to card, for sanity.
    updateStates(true);
 }

+ 2 - 2
Engine/source/gfx/D3D11/gfxD3D11Device.h

@@ -146,7 +146,6 @@ protected:
    virtual GFXD3D11VertexBuffer* findVBPool( const GFXVertexFormat *vertexFormat, U32 numVertsNeeded );
    virtual GFXD3D11VertexBuffer* createVBPool( const GFXVertexFormat *vertexFormat, U32 vertSize );
 
-   IDXGISwapChain* getSwapChain();
    // State overrides
    // {
 
@@ -281,7 +280,8 @@ public:
    ID3D11Device* getDevice(){ return mD3DDevice; }
 
    /// Reset
-   void reset( DXGI_SWAP_CHAIN_DESC &d3dpp );
+   void beginReset();
+   void endReset(GFXD3D11WindowTarget *windowTarget);
 
    virtual void setupGenericShaders( GenericShaderType type  = GSColor );
 

+ 199 - 18
Engine/source/gfx/D3D11/gfxD3D11Target.cpp

@@ -314,21 +314,34 @@ void GFXD3D11TextureTarget::resurrect()
 
 GFXD3D11WindowTarget::GFXD3D11WindowTarget()
 {
-   mWindow       = NULL;
-   mBackbuffer   = NULL;
+   mWindow = NULL;
+   mBackBuffer = NULL;
+   mDepthStencilView = NULL;
+   mDepthStencil = NULL;
+   mBackBufferView = NULL;
+   mSecondaryWindow = false;
 }
 
 GFXD3D11WindowTarget::~GFXD3D11WindowTarget()
 {
-   SAFE_RELEASE(mBackbuffer);
+   SAFE_RELEASE(mDepthStencilView)
+   SAFE_RELEASE(mDepthStencil);
+   SAFE_RELEASE(mBackBufferView);
+   SAFE_RELEASE(mBackBuffer);
+   SAFE_RELEASE(mSwapChain);
 }
 
 void GFXD3D11WindowTarget::initPresentationParams()
 {
    // Get some video mode related info.
-   GFXVideoMode vm = mWindow->getVideoMode();
-   Win32Window* win = static_cast<Win32Window*>(mWindow);
-   HWND hwnd = win->getHWND();
+   const GFXVideoMode &vm = mWindow->getVideoMode();
+   HWND hwnd = (HWND)mWindow->getSystemWindow(PlatformWindow::WindowSystem_Windows);
+
+   // Do some validation...
+   if (vm.fullScreen && mSecondaryWindow)
+   {
+      AssertFatal(false, "GFXD3D11WindowTarget::initPresentationParams - Cannot go fullscreen with secondary window!");
+   }
 
    mPresentationParams = D3D11->setupPresentParams(vm, hwnd);
 }
@@ -347,40 +360,178 @@ GFXFormat GFXD3D11WindowTarget::getFormat()
 
 bool GFXD3D11WindowTarget::present()
 {
-   return (D3D11->getSwapChain()->Present(!D3D11->smDisableVSync, 0) == S_OK);
+   return (mSwapChain->Present(!D3D11->smDisableVSync, 0) == S_OK);
+}
+
+void GFXD3D11WindowTarget::createSwapChain()
+{
+   //create dxgi factory & swapchain
+   IDXGIFactory1* DXGIFactory;
+   HRESULT hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), reinterpret_cast<void**>(&DXGIFactory));
+   if (FAILED(hr))
+      AssertFatal(false, "GFXD3D11WindowTarget::createSwapChain - couldn't create dxgi factory.");
+
+   hr = DXGIFactory->CreateSwapChain(D3D11DEVICE, &mPresentationParams, &mSwapChain);
+
+   if (FAILED(hr))
+      AssertFatal(false, "GFXD3D11WindowTarget::createSwapChain - couldn't create swap chain.");
+
+   SAFE_RELEASE(DXGIFactory);   
 }
 
-void GFXD3D11WindowTarget::setImplicitSwapChain()
+void GFXD3D11WindowTarget::createBuffersAndViews()
 {
-   if (!mBackbuffer)      
-      D3D11->mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackbuffer);
+   //release old if they exist
+   SAFE_RELEASE(mDepthStencilView);
+   SAFE_RELEASE(mDepthStencil);
+   SAFE_RELEASE(mBackBufferView);
+   SAFE_RELEASE(mBackBuffer);
+
+   //grab video mode
+   const GFXVideoMode &vm = mWindow->getVideoMode();
+   //create depth/stencil
+   D3D11_TEXTURE2D_DESC desc;
+   desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
+   desc.CPUAccessFlags = 0;
+   desc.Format = GFXD3D11TextureFormat[GFXFormatD24S8];
+   desc.MipLevels = 1;
+   desc.ArraySize = 1;
+   desc.Usage = D3D11_USAGE_DEFAULT;
+   desc.Width = vm.resolution.x;
+   desc.Height = vm.resolution.y;
+   desc.SampleDesc.Count = 1;
+   desc.SampleDesc.Quality = 0;
+   desc.MiscFlags = 0;
+
+   HRESULT hr = D3D11DEVICE->CreateTexture2D(&desc, NULL, &mDepthStencil);
+   if (FAILED(hr))
+      AssertFatal(false, "GFXD3D11WindowTarget::createBuffersAndViews - couldn't create device's depth-stencil surface.");
+
+   D3D11_DEPTH_STENCIL_VIEW_DESC depthDesc;
+   depthDesc.Format = GFXD3D11TextureFormat[GFXFormatD24S8];
+   depthDesc.Flags = 0;
+   depthDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
+   depthDesc.Texture2D.MipSlice = 0;
+
+   hr = D3D11DEVICE->CreateDepthStencilView(mDepthStencil, &depthDesc, &mDepthStencilView);
+   if (FAILED(hr))
+      AssertFatal(false, "GFXD3D11WindowTarget::createBuffersAndViews - couldn't create depth stencil view");
+
+   setBackBuffer();
+
+   //create back buffer view
+   D3D11_RENDER_TARGET_VIEW_DESC RTDesc;
+   RTDesc.Format = GFXD3D11TextureFormat[GFXFormatR8G8B8A8];
+   RTDesc.Texture2D.MipSlice = 0;
+   RTDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+
+   hr = D3D11DEVICE->CreateRenderTargetView(mBackBuffer, &RTDesc, &mBackBufferView);
+
+   if (FAILED(hr))
+      AssertFatal(false, "GFXD3D11WindowTarget::createBuffersAndViews - couldn't create back buffer target view");
+
+   //debug names
+#ifdef TORQUE_DEBUG
+   if (!mSecondaryWindow)
+   {
+      String backBufferName = "MainBackBuffer";
+      String depthSteniclName = "MainDepthStencil";
+      String backBuffViewName = "MainBackBuffView";
+      String depthStencViewName = "MainDepthView";
+      mBackBuffer->SetPrivateData(WKPDID_D3DDebugObjectName, backBufferName.size(), backBufferName.c_str());
+      mDepthStencil->SetPrivateData(WKPDID_D3DDebugObjectName, depthSteniclName.size(), depthSteniclName.c_str());
+      mDepthStencilView->SetPrivateData(WKPDID_D3DDebugObjectName, depthStencViewName.size(), depthStencViewName.c_str());
+      mBackBufferView->SetPrivateData(WKPDID_D3DDebugObjectName, backBuffViewName.size(), backBuffViewName.c_str());
+   }
+#endif
 }
 
 void GFXD3D11WindowTarget::resetMode()
 {
+   HRESULT hr;
+   if (mSwapChain)
+   {
+      // The current video settings.
+      DXGI_SWAP_CHAIN_DESC desc;
+      hr = mSwapChain->GetDesc(&desc);
+      if (FAILED(hr))
+         AssertFatal(false, "GFXD3D11WindowTarget::resetMode - failed to get swap chain description!");
+
+      bool fullscreen = !desc.Windowed;
+      Point2I backbufferSize(desc.BufferDesc.Width, desc.BufferDesc.Height);
+
+      // The settings we are now applying.
+      const GFXVideoMode &vm = mWindow->getVideoMode();
+
+      // Early out if none of the settings which require a device reset
+      // have changed.      
+      if (backbufferSize == vm.resolution &&
+         fullscreen == vm.fullScreen)
+         return;
+   }
+
+   //release old buffers and views
+   SAFE_RELEASE(mDepthStencilView)
+   SAFE_RELEASE(mDepthStencil);
+   SAFE_RELEASE(mBackBufferView);
+   SAFE_RELEASE(mBackBuffer);
+
+   if(!mSecondaryWindow)
+      D3D11->beginReset();
+
    mWindow->setSuppressReset(true);
 
    // Setup our presentation params.
    initPresentationParams();
 
-   // Otherwise, we have to reset the device, if we're the implicit swapchain.
-   D3D11->reset(mPresentationParams);
+   if (!mPresentationParams.Windowed)
+   {
+      mPresentationParams.BufferDesc.RefreshRate.Numerator = 0;
+      mPresentationParams.BufferDesc.RefreshRate.Denominator = 0;
+      hr = mSwapChain->ResizeTarget(&mPresentationParams.BufferDesc);
+
+      if (FAILED(hr))
+         AssertFatal(false, "GFXD3D11WindowTarget::resetMode - failed to resize target!");
+
+   }
+
+   hr = mSwapChain->ResizeBuffers(mPresentationParams.BufferCount, mPresentationParams.BufferDesc.Width, mPresentationParams.BufferDesc.Height, 
+      mPresentationParams.BufferDesc.Format, mPresentationParams.Windowed ? 0 : DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH);
+
+   if (FAILED(hr))
+      AssertFatal(false, "GFXD3D11WindowTarget::resetMode - failed to resize back buffer!");
+
+   hr = mSwapChain->SetFullscreenState(!mPresentationParams.Windowed, NULL);
+
+   if (FAILED(hr))
+      AssertFatal(false, "GFXD3D11WindowTarget::resetMode - failed to change screen states!");
 
    // Update our size, too.
    mSize = Point2I(mPresentationParams.BufferDesc.Width, mPresentationParams.BufferDesc.Height);
 
    mWindow->setSuppressReset(false);
-   GFX->beginReset();
+
+   //re-create buffers and views
+   createBuffersAndViews();
+
+   if (!mSecondaryWindow)
+      D3D11->endReset(this);
 }
 
 void GFXD3D11WindowTarget::zombify()
 {
-   SAFE_RELEASE(mBackbuffer);
+   SAFE_RELEASE(mBackBuffer);
 }
 
 void GFXD3D11WindowTarget::resurrect()
 {
-   setImplicitSwapChain();
+   setBackBuffer();
+}
+
+void GFXD3D11WindowTarget::setBackBuffer()
+{
+   if (!mBackBuffer)
+      mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBuffer);
 }
 
 void GFXD3D11WindowTarget::activate()
@@ -391,10 +542,10 @@ void GFXD3D11WindowTarget::activate()
    ID3D11RenderTargetView* rtViews[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
 
    D3D11DEVICECONTEXT->OMSetRenderTargets(8, rtViews, NULL);
-   D3D11DEVICECONTEXT->OMSetRenderTargets(1, &D3D11->mDeviceBackBufferView, D3D11->mDeviceDepthStencilView);
+   D3D11DEVICECONTEXT->OMSetRenderTargets(1, &mBackBufferView, mDepthStencilView);
 
    DXGI_SWAP_CHAIN_DESC pp;
-   D3D11->mSwapChain->GetDesc(&pp);
+   mSwapChain->GetDesc(&pp);
 
    // Update our video mode here, too.
    GFXVideoMode vm;
@@ -412,5 +563,35 @@ void GFXD3D11WindowTarget::resolveTo(GFXTextureObject *tex)
    D3D11_TEXTURE2D_DESC desc;
    ID3D11Texture2D* surf = ((GFXD3D11TextureObject*)(tex))->get2DTex();
    surf->GetDesc(&desc);
-   D3D11DEVICECONTEXT->ResolveSubresource(surf, 0, D3D11->mDeviceBackbuffer, 0, desc.Format);
+   D3D11DEVICECONTEXT->ResolveSubresource(surf, 0, mBackBuffer, 0, desc.Format);
+}
+
+IDXGISwapChain *GFXD3D11WindowTarget::getSwapChain()
+{
+   mSwapChain->AddRef();
+   return mSwapChain;
+}
+
+ID3D11Texture2D *GFXD3D11WindowTarget::getBackBuffer()
+{
+   mBackBuffer->AddRef();
+   return mBackBuffer;
+}
+
+ID3D11Texture2D *GFXD3D11WindowTarget::getDepthStencil()
+{
+   mDepthStencil->AddRef();
+   return mDepthStencil;
+}
+
+ID3D11RenderTargetView* GFXD3D11WindowTarget::getBackBufferView()
+{
+   mBackBufferView->AddRef();
+   return mBackBufferView;
+}
+
+ID3D11DepthStencilView* GFXD3D11WindowTarget::getDepthStencilView()
+{
+   mDepthStencilView->AddRef();
+   return mDepthStencilView;
 }

+ 18 - 4
Engine/source/gfx/D3D11/gfxD3D11Target.h

@@ -76,17 +76,22 @@ class GFXD3D11WindowTarget : public GFXWindowTarget
    friend class GFXD3D11Device;
 
    /// Our backbuffer
-   ID3D11Texture2D *mBackbuffer;
+   ID3D11Texture2D *mBackBuffer;
+   ID3D11Texture2D *mDepthStencil;
+   ID3D11RenderTargetView* mBackBufferView;
+   ID3D11DepthStencilView* mDepthStencilView;
+   IDXGISwapChain *mSwapChain;
 
    /// Maximum size we can render to.
    Point2I mSize;
-
    /// D3D presentation info.
    DXGI_SWAP_CHAIN_DESC mPresentationParams;
-
    /// Internal interface that notifies us we need to reset our video mode.
    void resetMode();
 
+   /// Is this a secondary window
+   bool mSecondaryWindow;
+
 public:
 
    GFXD3D11WindowTarget();
@@ -97,7 +102,9 @@ public:
    virtual bool present();
 
    void initPresentationParams();
-   void setImplicitSwapChain();
+   void createSwapChain();
+   void createBuffersAndViews();
+   void setBackBuffer();
 
    virtual void activate();   
 
@@ -105,6 +112,13 @@ public:
    void resurrect();
 
    virtual void resolveTo( GFXTextureObject *tex );
+
+   // These are all reference counted and must be released by whomever uses the get* function
+   IDXGISwapChain *getSwapChain();
+   ID3D11Texture2D *getBackBuffer();
+   ID3D11Texture2D *getDepthStencil();
+   ID3D11RenderTargetView* getBackBufferView();
+   ID3D11DepthStencilView* getDepthStencilView();
 };
 
 #endif

+ 9 - 2
Engine/source/gfx/gl/gfxGLWindowTarget.cpp

@@ -37,7 +37,7 @@ GFX_ImplementTextureProfile( BackBufferDepthProfile,
 
 GFXGLWindowTarget::GFXGLWindowTarget(PlatformWindow *win, GFXDevice *d)
       : GFXWindowTarget(win), mDevice(d), mContext(NULL), mFullscreenContext(NULL)
-      , mCopyFBO(0), mBackBufferFBO(0)
+      , mCopyFBO(0), mBackBufferFBO(0), mSecondaryWindow(false)
 {      
    win->appEvent.notify(this, &GFXGLWindowTarget::_onAppSignal);
 }
@@ -52,7 +52,14 @@ GFXGLWindowTarget::~GFXGLWindowTarget()
 
 void GFXGLWindowTarget::resetMode()
 {
-   if(mWindow->getVideoMode().fullScreen != mWindow->isFullscreen())
+   // Do some validation...
+   bool fullscreen = mWindow->getVideoMode().fullScreen;
+   if (fullscreen && mSecondaryWindow)
+   {
+      AssertFatal(false, "GFXGLWindowTarget::resetMode - Cannot go fullscreen with secondary window!");
+   }
+
+   if(fullscreen != mWindow->isFullscreen())
    {
       _teardownCurrentMode();
       _setupNewMode();

+ 6 - 0
Engine/source/gfx/gl/gfxGLWindowTarget.h

@@ -50,6 +50,9 @@ public:
    virtual void resolveTo(GFXTextureObject* obj);
    
    void _onAppSignal(WindowId wnd, S32 event);
+
+   // create pixel format for the window
+   void createPixelFormat();
    
 private:
    friend class GFXGLDevice;
@@ -58,6 +61,8 @@ private:
    GFXTexHandle mBackBufferColorTex, mBackBufferDepthTex;
    Point2I size;   
    GFXDevice* mDevice;
+   /// Is this a secondary window
+   bool mSecondaryWindow;
    void* mContext;
    void* mFullscreenContext;
    void _teardownCurrentMode();
@@ -66,6 +71,7 @@ private:
    void _WindowPresent();
    //set this windows context to be current
    void _makeContextCurrent();
+   
 };
 
 #endif

+ 15 - 13
Engine/source/gfx/gl/sdl/gfxGLDevice.sdl.cpp

@@ -191,19 +191,21 @@ U32 GFXGLDevice::getTotalVideoMemory()
 
 GFXWindowTarget *GFXGLDevice::allocWindowTarget( PlatformWindow *window )
 {
-    AssertFatal(!mContext, "This GFXGLDevice is already assigned to a window");
-    
-    GFXGLWindowTarget* ggwt = 0;
-    if( !mContext )
-    {
-        // no context, init the device now
-        init(window->getVideoMode(), window);
-        ggwt = new GFXGLWindowTarget(window, this);
-        ggwt->registerResourceWithDevice(this);
-        ggwt->mContext = mContext;
-    }
-
-    return ggwt;
+   GFXGLWindowTarget* ggwt = new GFXGLWindowTarget(window, this);
+
+   //first window
+   if (!mContext)
+   {
+      init(window->getVideoMode(), window);
+      ggwt->mSecondaryWindow = false;
+   }
+   else
+      ggwt->mSecondaryWindow = true;
+
+   ggwt->registerResourceWithDevice(this);
+   ggwt->mContext = mContext;
+
+   return ggwt;
 }
 
 GFXFence* GFXGLDevice::_createPlatformSpecificFence()

+ 31 - 14
Engine/source/gfx/gl/win32/gfxGLDevice.win.cpp

@@ -255,14 +255,6 @@ void GFXGLDevice::init( const GFXVideoMode &mode, PlatformWindow *window )
    HDC hdcGL = GetDC( hwnd );
    AssertFatal( hdcGL != NULL, "Failed to create device context" );
 
-   // Create pixel format descriptor...
-   PIXELFORMATDESCRIPTOR pfd;
-   CreatePixelFormat( &pfd, 32, 0, 0, false ); // 32 bit color... We do not need depth or stencil, OpenGL renders into a FBO and then copy the image to window
-   if( !SetPixelFormat( hdcGL, ChoosePixelFormat( hdcGL, &pfd ), &pfd ) )
-   {
-      AssertFatal( false, "GFXGLDevice::init - cannot get the one and only pixel format we check for." );
-   }
-
    int OGL_MAJOR = 3;
    int OGL_MINOR = 2;
    
@@ -330,13 +322,21 @@ U32 GFXGLDevice::getTotalVideoMemory()
 
 //------------------------------------------------------------------------------
 
-GFXWindowTarget *GFXGLDevice::allocWindowTarget( PlatformWindow *window )
+GFXWindowTarget *GFXGLDevice::allocWindowTarget(PlatformWindow *window)
 {
-   AssertFatal(!mContext, "");
-   
-   init(window->getVideoMode(), window);
    GFXGLWindowTarget *ggwt = new GFXGLWindowTarget(window, this);
    ggwt->registerResourceWithDevice(this);
+   ggwt->createPixelFormat();
+
+   //first window
+   if (!mContext)
+   {
+      init(window->getVideoMode(), window);
+      ggwt->mSecondaryWindow = false;
+   }
+   else
+      ggwt->mSecondaryWindow = true;
+
    ggwt->mContext = mContext;
    AssertFatal(ggwt->mContext, "GFXGLDevice::allocWindowTarget - failed to allocate window target!");
 
@@ -364,15 +364,32 @@ void GFXGLWindowTarget::_setupNewMode()
 {
 }
 
+void GFXGLWindowTarget::createPixelFormat()
+{
+   HWND hwnd = GETHWND(mWindow);
+   // Create a device context
+   HDC hdcGL = GetDC(hwnd);
+   AssertFatal(hdcGL != NULL, "GFXGLWindowTarget::createPixelFormat() - Failed to create device context");
+
+   // Create pixel format descriptor...
+   PIXELFORMATDESCRIPTOR pfd;
+   CreatePixelFormat(&pfd, 32, 0, 0, false); // 32 bit color... We do not need depth or stencil, OpenGL renders into a FBO and then copy the image to window
+   if (!SetPixelFormat(hdcGL, ChoosePixelFormat(hdcGL, &pfd), &pfd))
+   {
+      AssertFatal(false, "GFXGLWindowTarget::createPixelFormat() - cannot get the one and only pixel format we check for.");
+   }
+}
+
 void GFXGLWindowTarget::_makeContextCurrent()
 {
    HWND hwnd = GETHWND(getWindow());
    HDC hdc = GetDC(hwnd);
+
    if (!wglMakeCurrent(hdc, (HGLRC)mContext))
    {
       //HRESULT if needed for debug
       //HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
       AssertFatal(false, "GFXGLWindowTarget::_makeContextCurrent() - cannot make our context current.");
    }
-   
-}
+
+}