Merge pull request #1859 from rextimmy/multicanvas_gl_dx11

Multiple canvas support for GL and DX11
This commit is contained in:
Areloch 2016-12-20 23:36:13 -06:00 committed by GitHub
commit fb9bd03073
8 changed files with 352 additions and 269 deletions

View file

@ -261,73 +261,59 @@ void GFXD3D11Device::enumerateVideoModes()
SAFE_RELEASE(DXGIFactory); SAFE_RELEASE(DXGIFactory);
} }
IDXGISwapChain* GFXD3D11Device::getSwapChain()
{
return mSwapChain;
}
void GFXD3D11Device::init(const GFXVideoMode &mode, PlatformWindow *window) void GFXD3D11Device::init(const GFXVideoMode &mode, PlatformWindow *window)
{ {
AssertFatal(window, "GFXD3D11Device::init - must specify a 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; UINT createDeviceFlags = D3D11_CREATE_DEVICE_SINGLETHREADED | D3D11_CREATE_DEVICE_BGRA_SUPPORT;
#ifdef TORQUE_DEBUG #ifdef TORQUE_DEBUG
createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
mDebugLayers = true; mDebugLayers = true;
#endif #endif
DXGI_SWAP_CHAIN_DESC d3dpp = setupPresentParams(mode, winHwnd);
D3D_FEATURE_LEVEL deviceFeature; D3D_FEATURE_LEVEL deviceFeature;
D3D_DRIVER_TYPE driverType = D3D_DRIVER_TYPE_HARDWARE;// use D3D_DRIVER_TYPE_REFERENCE for reference device 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 // create a device & device context
HRESULT hres = D3D11CreateDeviceAndSwapChain(NULL, HRESULT hres = D3D11CreateDevice(NULL,
driverType, driverType,
NULL, NULL,
createDeviceFlags, createDeviceFlags,
NULL, NULL,
0, 0,
D3D11_SDK_VERSION, D3D11_SDK_VERSION,
&d3dpp, &mD3DDevice,
&mSwapChain, &deviceFeature,
&mD3DDevice, &mD3DDeviceContext);
&deviceFeature,
&mD3DDeviceContext);
if(FAILED(hres)) if(FAILED(hres))
{ {
#ifdef TORQUE_DEBUG #ifdef TORQUE_DEBUG
//try again without debug device layer enabled //try again without debug device layer enabled
createDeviceFlags &= ~D3D11_CREATE_DEVICE_DEBUG; createDeviceFlags &= ~D3D11_CREATE_DEVICE_DEBUG;
HRESULT hres = D3D11CreateDeviceAndSwapChain(NULL, driverType,NULL,createDeviceFlags,NULL, 0, hres = D3D11CreateDevice(NULL,
D3D11_SDK_VERSION, driverType,
&d3dpp, NULL,
&mSwapChain, createDeviceFlags,
&mD3DDevice, NULL,
&deviceFeature, 0,
&mD3DDeviceContext); D3D11_SDK_VERSION,
//if we failed again than we definitely have a problem &mD3DDevice,
if (FAILED(hres)) &deviceFeature,
AssertFatal(false, "GFXD3D11Device::init - D3D11CreateDeviceAndSwapChain failed!"); &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!"); Con::warnf("GFXD3D11Device::init - Debug layers not detected!");
mDebugLayers = false; mDebugLayers = false;
#else #else
AssertFatal(false, "GFXD3D11Device::init - D3D11CreateDeviceAndSwapChain failed!"); AssertFatal(false, "GFXD3D11Device::init - D3D11CreateDeviceAndSwapChain failed!");
#endif #endif
} }
//set the fullscreen state here if we need to #ifdef TORQUE_DEBUG
if(mode.fullScreen) _suppressDebugMessages();
{ #endif
hres = mSwapChain->SetFullscreenState(TRUE, NULL);
if(FAILED(hres))
{
AssertFatal(false, "GFXD3D11Device::init- Failed to set fullscreen state!");
}
}
mTextureManager = new GFXD3D11TextureManager(); mTextureManager = new GFXD3D11TextureManager();
@ -355,68 +341,6 @@ void GFXD3D11Device::init(const GFXVideoMode &mode, PlatformWindow *window)
mCardProfiler = new GFXD3D11CardProfiler(); mCardProfiler = new GFXD3D11CardProfiler();
mCardProfiler->init(); 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; gScreenShot = new ScreenShotD3D11;
mInitialized = true; mInitialized = true;
@ -466,14 +390,35 @@ GFXWindowTarget * GFXD3D11Device::allocWindowTarget(PlatformWindow *window)
{ {
AssertFatal(window,"GFXD3D11Device::allocWindowTarget - no window provided!"); AssertFatal(window,"GFXD3D11Device::allocWindowTarget - no window provided!");
// Allocate the device.
init(window->getVideoMode(), window);
// Set up a new window target... // Set up a new window target...
GFXD3D11WindowTarget *gdwt = new GFXD3D11WindowTarget(); GFXD3D11WindowTarget *gdwt = new GFXD3D11WindowTarget();
gdwt->mWindow = window; gdwt->mWindow = window;
gdwt->mSize = window->getClientExtent(); 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); gdwt->registerResourceWithDevice(this);
return gdwt; return gdwt;
@ -487,13 +432,15 @@ GFXTextureTarget* GFXD3D11Device::allocRenderToTextureTarget()
return targ; return targ;
} }
void GFXD3D11Device::reset(DXGI_SWAP_CHAIN_DESC &d3dpp) void GFXD3D11Device::beginReset()
{ {
if (!mD3DDevice) if (!mD3DDevice)
return; return;
mInitialized = false; mInitialized = false;
releaseDefaultPoolResources();
// Clean up some commonly dangling state. This helps prevents issues with // Clean up some commonly dangling state. This helps prevents issues with
// items that are destroyed by the texture manager callbacks and recreated // items that are destroyed by the texture manager callbacks and recreated
// later, but still left bound. // later, but still left bound.
@ -504,117 +451,26 @@ void GFXD3D11Device::reset(DXGI_SWAP_CHAIN_DESC &d3dpp)
mD3DDeviceContext->ClearState(); mD3DDeviceContext->ClearState();
DXGI_MODE_DESC displayModes; //release old buffers and views
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);
SAFE_RELEASE(mDeviceDepthStencilView); SAFE_RELEASE(mDeviceDepthStencilView);
SAFE_RELEASE(mDeviceBackBufferView);
SAFE_RELEASE(mDeviceDepthStencil); 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); void GFXD3D11Device::endReset(GFXD3D11WindowTarget *windowTarget)
{
if (FAILED(hr)) //grab new references
{ mDeviceBackbuffer = windowTarget->getBackBuffer();
AssertFatal(false, "D3D11Device::reset - failed to resize back buffer!"); mDeviceDepthStencil = windowTarget->getDepthStencil();
} mDeviceBackBufferView = windowTarget->getBackBufferView();
mDeviceDepthStencilView = windowTarget->getDepthStencilView();
//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");
mD3DDeviceContext->OMSetRenderTargets(1, &mDeviceBackBufferView, mDeviceDepthStencilView); mD3DDeviceContext->OMSetRenderTargets(1, &mDeviceBackBufferView, mDeviceDepthStencilView);
hr = mSwapChain->SetFullscreenState(!d3dpp.Windowed, NULL); // Now reacquire all the resources we trashed earlier
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
reacquireDefaultPoolResources(); reacquireDefaultPoolResources();
mInitialized = true;
// Mark everything dirty and flush to card, for sanity. // Mark everything dirty and flush to card, for sanity.
updateStates(true); updateStates(true);
} }

View file

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

View file

@ -314,21 +314,34 @@ void GFXD3D11TextureTarget::resurrect()
GFXD3D11WindowTarget::GFXD3D11WindowTarget() GFXD3D11WindowTarget::GFXD3D11WindowTarget()
{ {
mWindow = NULL; mWindow = NULL;
mBackbuffer = NULL; mBackBuffer = NULL;
mDepthStencilView = NULL;
mDepthStencil = NULL;
mBackBufferView = NULL;
mSecondaryWindow = false;
} }
GFXD3D11WindowTarget::~GFXD3D11WindowTarget() GFXD3D11WindowTarget::~GFXD3D11WindowTarget()
{ {
SAFE_RELEASE(mBackbuffer); SAFE_RELEASE(mDepthStencilView)
SAFE_RELEASE(mDepthStencil);
SAFE_RELEASE(mBackBufferView);
SAFE_RELEASE(mBackBuffer);
SAFE_RELEASE(mSwapChain);
} }
void GFXD3D11WindowTarget::initPresentationParams() void GFXD3D11WindowTarget::initPresentationParams()
{ {
// Get some video mode related info. // Get some video mode related info.
GFXVideoMode vm = mWindow->getVideoMode(); const GFXVideoMode &vm = mWindow->getVideoMode();
Win32Window* win = static_cast<Win32Window*>(mWindow); HWND hwnd = (HWND)mWindow->getSystemWindow(PlatformWindow::WindowSystem_Windows);
HWND hwnd = win->getHWND();
// Do some validation...
if (vm.fullScreen && mSecondaryWindow)
{
AssertFatal(false, "GFXD3D11WindowTarget::initPresentationParams - Cannot go fullscreen with secondary window!");
}
mPresentationParams = D3D11->setupPresentParams(vm, hwnd); mPresentationParams = D3D11->setupPresentParams(vm, hwnd);
} }
@ -347,40 +360,178 @@ GFXFormat GFXD3D11WindowTarget::getFormat()
bool GFXD3D11WindowTarget::present() bool GFXD3D11WindowTarget::present()
{ {
return (D3D11->getSwapChain()->Present(!D3D11->smDisableVSync, 0) == S_OK); return (mSwapChain->Present(!D3D11->smDisableVSync, 0) == S_OK);
} }
void GFXD3D11WindowTarget::setImplicitSwapChain() void GFXD3D11WindowTarget::createSwapChain()
{ {
if (!mBackbuffer) //create dxgi factory & swapchain
D3D11->mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackbuffer); 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::createBuffersAndViews()
{
//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() 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); mWindow->setSuppressReset(true);
// Setup our presentation params. // Setup our presentation params.
initPresentationParams(); initPresentationParams();
// Otherwise, we have to reset the device, if we're the implicit swapchain. if (!mPresentationParams.Windowed)
D3D11->reset(mPresentationParams); {
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. // Update our size, too.
mSize = Point2I(mPresentationParams.BufferDesc.Width, mPresentationParams.BufferDesc.Height); mSize = Point2I(mPresentationParams.BufferDesc.Width, mPresentationParams.BufferDesc.Height);
mWindow->setSuppressReset(false); mWindow->setSuppressReset(false);
GFX->beginReset();
//re-create buffers and views
createBuffersAndViews();
if (!mSecondaryWindow)
D3D11->endReset(this);
} }
void GFXD3D11WindowTarget::zombify() void GFXD3D11WindowTarget::zombify()
{ {
SAFE_RELEASE(mBackbuffer); SAFE_RELEASE(mBackBuffer);
} }
void GFXD3D11WindowTarget::resurrect() void GFXD3D11WindowTarget::resurrect()
{ {
setImplicitSwapChain(); setBackBuffer();
}
void GFXD3D11WindowTarget::setBackBuffer()
{
if (!mBackBuffer)
mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBuffer);
} }
void GFXD3D11WindowTarget::activate() void GFXD3D11WindowTarget::activate()
@ -391,10 +542,10 @@ void GFXD3D11WindowTarget::activate()
ID3D11RenderTargetView* rtViews[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; ID3D11RenderTargetView* rtViews[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
D3D11DEVICECONTEXT->OMSetRenderTargets(8, rtViews, NULL); D3D11DEVICECONTEXT->OMSetRenderTargets(8, rtViews, NULL);
D3D11DEVICECONTEXT->OMSetRenderTargets(1, &D3D11->mDeviceBackBufferView, D3D11->mDeviceDepthStencilView); D3D11DEVICECONTEXT->OMSetRenderTargets(1, &mBackBufferView, mDepthStencilView);
DXGI_SWAP_CHAIN_DESC pp; DXGI_SWAP_CHAIN_DESC pp;
D3D11->mSwapChain->GetDesc(&pp); mSwapChain->GetDesc(&pp);
// Update our video mode here, too. // Update our video mode here, too.
GFXVideoMode vm; GFXVideoMode vm;
@ -412,5 +563,35 @@ void GFXD3D11WindowTarget::resolveTo(GFXTextureObject *tex)
D3D11_TEXTURE2D_DESC desc; D3D11_TEXTURE2D_DESC desc;
ID3D11Texture2D* surf = ((GFXD3D11TextureObject*)(tex))->get2DTex(); ID3D11Texture2D* surf = ((GFXD3D11TextureObject*)(tex))->get2DTex();
surf->GetDesc(&desc); 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;
} }

View file

@ -76,17 +76,22 @@ class GFXD3D11WindowTarget : public GFXWindowTarget
friend class GFXD3D11Device; friend class GFXD3D11Device;
/// Our backbuffer /// Our backbuffer
ID3D11Texture2D *mBackbuffer; ID3D11Texture2D *mBackBuffer;
ID3D11Texture2D *mDepthStencil;
ID3D11RenderTargetView* mBackBufferView;
ID3D11DepthStencilView* mDepthStencilView;
IDXGISwapChain *mSwapChain;
/// Maximum size we can render to. /// Maximum size we can render to.
Point2I mSize; Point2I mSize;
/// D3D presentation info. /// D3D presentation info.
DXGI_SWAP_CHAIN_DESC mPresentationParams; DXGI_SWAP_CHAIN_DESC mPresentationParams;
/// Internal interface that notifies us we need to reset our video mode. /// Internal interface that notifies us we need to reset our video mode.
void resetMode(); void resetMode();
/// Is this a secondary window
bool mSecondaryWindow;
public: public:
GFXD3D11WindowTarget(); GFXD3D11WindowTarget();
@ -97,7 +102,9 @@ public:
virtual bool present(); virtual bool present();
void initPresentationParams(); void initPresentationParams();
void setImplicitSwapChain(); void createSwapChain();
void createBuffersAndViews();
void setBackBuffer();
virtual void activate(); virtual void activate();
@ -105,6 +112,13 @@ public:
void resurrect(); void resurrect();
virtual void resolveTo( GFXTextureObject *tex ); 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 #endif

View file

@ -37,7 +37,7 @@ GFX_ImplementTextureProfile( BackBufferDepthProfile,
GFXGLWindowTarget::GFXGLWindowTarget(PlatformWindow *win, GFXDevice *d) GFXGLWindowTarget::GFXGLWindowTarget(PlatformWindow *win, GFXDevice *d)
: GFXWindowTarget(win), mDevice(d), mContext(NULL), mFullscreenContext(NULL) : GFXWindowTarget(win), mDevice(d), mContext(NULL), mFullscreenContext(NULL)
, mCopyFBO(0), mBackBufferFBO(0) , mCopyFBO(0), mBackBufferFBO(0), mSecondaryWindow(false)
{ {
win->appEvent.notify(this, &GFXGLWindowTarget::_onAppSignal); win->appEvent.notify(this, &GFXGLWindowTarget::_onAppSignal);
} }
@ -52,7 +52,14 @@ GFXGLWindowTarget::~GFXGLWindowTarget()
void GFXGLWindowTarget::resetMode() 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(); _teardownCurrentMode();
_setupNewMode(); _setupNewMode();

View file

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

View file

@ -191,19 +191,21 @@ U32 GFXGLDevice::getTotalVideoMemory()
GFXWindowTarget *GFXGLDevice::allocWindowTarget( PlatformWindow *window ) GFXWindowTarget *GFXGLDevice::allocWindowTarget( PlatformWindow *window )
{ {
AssertFatal(!mContext, "This GFXGLDevice is already assigned to a window"); GFXGLWindowTarget* ggwt = new GFXGLWindowTarget(window, this);
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; //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() GFXFence* GFXGLDevice::_createPlatformSpecificFence()

View file

@ -255,14 +255,6 @@ void GFXGLDevice::init( const GFXVideoMode &mode, PlatformWindow *window )
HDC hdcGL = GetDC( hwnd ); HDC hdcGL = GetDC( hwnd );
AssertFatal( hdcGL != NULL, "Failed to create device context" ); 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_MAJOR = 3;
int OGL_MINOR = 2; 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); GFXGLWindowTarget *ggwt = new GFXGLWindowTarget(window, this);
ggwt->registerResourceWithDevice(this); ggwt->registerResourceWithDevice(this);
ggwt->createPixelFormat();
//first window
if (!mContext)
{
init(window->getVideoMode(), window);
ggwt->mSecondaryWindow = false;
}
else
ggwt->mSecondaryWindow = true;
ggwt->mContext = mContext; ggwt->mContext = mContext;
AssertFatal(ggwt->mContext, "GFXGLDevice::allocWindowTarget - failed to allocate window target!"); 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() void GFXGLWindowTarget::_makeContextCurrent()
{ {
HWND hwnd = GETHWND(getWindow()); HWND hwnd = GETHWND(getWindow());
HDC hdc = GetDC(hwnd); HDC hdc = GetDC(hwnd);
if (!wglMakeCurrent(hdc, (HGLRC)mContext)) if (!wglMakeCurrent(hdc, (HGLRC)mContext))
{ {
//HRESULT if needed for debug //HRESULT if needed for debug
//HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); //HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
AssertFatal(false, "GFXGLWindowTarget::_makeContextCurrent() - cannot make our context current."); AssertFatal(false, "GFXGLWindowTarget::_makeContextCurrent() - cannot make our context current.");
} }
} }