Merge pull request #506 from Armada651/d3dfullscreen

D3D: Add exclusive fullscreen support.
This commit is contained in:
Pierre Bourdon
2014-07-26 13:22:11 +02:00
18 changed files with 209 additions and 135 deletions

View File

@ -264,20 +264,28 @@ HRESULT Create(HWND wnd)
swap_chain_desc.OutputWindow = wnd;
swap_chain_desc.SampleDesc.Count = 1;
swap_chain_desc.SampleDesc.Quality = 0;
swap_chain_desc.Windowed = TRUE;
swap_chain_desc.Windowed = !g_ActiveConfig.bFullscreen;
DXGI_OUTPUT_DESC out_desc;
memset(&out_desc, 0, sizeof(out_desc));
output->GetDesc(&out_desc);
DXGI_MODE_DESC mode_desc;
memset(&mode_desc, 0, sizeof(mode_desc));
mode_desc.Width = xres;
mode_desc.Height = yres;
mode_desc.Width = out_desc.DesktopCoordinates.right - out_desc.DesktopCoordinates.left;
mode_desc.Height = out_desc.DesktopCoordinates.bottom - out_desc.DesktopCoordinates.top;
mode_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
mode_desc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
hr = output->FindClosestMatchingMode(&mode_desc, &swap_chain_desc.BufferDesc, nullptr);
if (FAILED(hr)) MessageBox(wnd, _T("Failed to find a supported video mode"), _T("Dolphin Direct3D 11 backend"), MB_OK | MB_ICONERROR);
// forcing buffer resolution to xres and yres.. TODO: The new video mode might not actually be supported!
swap_chain_desc.BufferDesc.Width = xres;
swap_chain_desc.BufferDesc.Height = yres;
if (swap_chain_desc.Windowed)
{
// forcing buffer resolution to xres and yres..
// this is not a problem as long as we're in windowed mode
swap_chain_desc.BufferDesc.Width = xres;
swap_chain_desc.BufferDesc.Height = yres;
}
#if defined(_DEBUG) || defined(DEBUGFAST)
// Creating debug devices can sometimes fail if the user doesn't have the correct
@ -308,6 +316,13 @@ HRESULT Create(HWND wnd)
SAFE_RELEASE(swapchain);
return E_FAIL;
}
// prevent DXGI from responding to Alt+Enter, unfortunately DXGI_MWA_NO_ALT_ENTER
// does not work so we disable all monitoring of window messages. However this
// may make it more difficult for DXGI to handle display mode changes.
hr = factory->MakeWindowAssociation(wnd, DXGI_MWA_NO_WINDOW_CHANGES);
if (FAILED(hr)) MessageBox(wnd, _T("Failed to associate the window"), _T("Dolphin Direct3D 11 backend"), MB_OK | MB_ICONERROR);
SetDebugObjectName((ID3D11DeviceChild*)context, "device context");
SAFE_RELEASE(factory);
SAFE_RELEASE(output);
@ -342,6 +357,9 @@ HRESULT Create(HWND wnd)
void Close()
{
// we can't release the swapchain while in fullscreen.
swapchain->SetFullscreenState(false, nullptr);
// release all bound resources
context->ClearState();
SAFE_RELEASE(backbuf);
@ -474,6 +492,24 @@ void Present()
swapchain->Present((UINT)g_ActiveConfig.IsVSync(), 0);
}
HRESULT SetFullscreenState(bool enable_fullscreen)
{
return swapchain->SetFullscreenState(enable_fullscreen, nullptr);
}
HRESULT GetFullscreenState(bool* fullscreen_state)
{
if (fullscreen_state == nullptr)
{
return E_POINTER;
}
BOOL state;
HRESULT hr = swapchain->GetFullscreenState(&state, nullptr);
*fullscreen_state = !!state;
return hr;
}
} // namespace D3D
} // namespace DX11

View File

@ -58,6 +58,9 @@ bool BGRATexturesSupported();
unsigned int GetMaxTextureSize();
HRESULT SetFullscreenState(bool enable_fullscreen);
HRESULT GetFullscreenState(bool* fullscreen_state);
// Ihis function will assign a name to the given resource.
// The DirectX debug layer will make it easier to identify resources that way,
// e.g. when listing up all resources who have unreleased references.

View File

@ -42,6 +42,8 @@ static u32 s_LastAA = 0;
static Television s_television;
static bool s_last_fullscreen_mode = false;
ID3D11Buffer* access_efb_cbuf = nullptr;
ID3D11BlendState* clearblendstates[4] = {nullptr};
ID3D11DepthStencilState* cleardepthstates[3] = {nullptr};
@ -936,6 +938,22 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangl
SetWindowSize(fbWidth, fbHeight);
const bool windowResized = CheckForResize();
const bool fullscreen = g_ActiveConfig.ExclusiveFullscreenEnabled() &&
!SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain;
bool fullscreen_changed = s_last_fullscreen_mode != fullscreen;
bool fullscreen_state;
if (SUCCEEDED(D3D::GetFullscreenState(&fullscreen_state)))
{
if (fullscreen_state != fullscreen && Host_RendererHasFocus())
{
// The current fullscreen state does not match the configuration,
// this may happen when the renderer frame loses focus. When the
// render frame is in focus again we can re-apply the configuration.
fullscreen_changed = true;
}
}
bool xfbchanged = false;
@ -951,17 +969,31 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangl
// Flip/present backbuffer to frontbuffer here
D3D::Present();
// resize the back buffers NOW to avoid flickering
// Resize the back buffers NOW to avoid flickering
if (xfbchanged ||
windowResized ||
fullscreen_changed ||
s_LastEFBScale != g_ActiveConfig.iEFBScale ||
s_LastAA != g_ActiveConfig.iMultisampleMode)
{
s_LastAA = g_ActiveConfig.iMultisampleMode;
PixelShaderCache::InvalidateMSAAShaders();
if (windowResized)
if (windowResized || fullscreen_changed)
{
// Apply fullscreen state
if (fullscreen_changed)
{
s_last_fullscreen_mode = fullscreen;
D3D::SetFullscreenState(fullscreen);
// Notify the host that it is safe to exit fullscreen
if (!fullscreen)
{
Host_RequestFullscreen(false);
}
}
// TODO: Aren't we still holding a reference to the back buffer right now?
D3D::Reset();
SAFE_RELEASE(s_screenshot_texture);

View File

@ -84,7 +84,7 @@ void InitBackendInfo()
g_Config.backend_info.APIType = API_D3D;
g_Config.backend_info.bUseRGBATextures = true; // the GX formats barely match any D3D11 formats
g_Config.backend_info.bUseMinimalMipCount = true;
g_Config.backend_info.bSupports3DVision = false;
g_Config.backend_info.bSupportsExclusiveFullscreen = true;
g_Config.backend_info.bSupportsDualSourceBlend = true;
g_Config.backend_info.bSupportsPrimitiveRestart = true;
g_Config.backend_info.bSupportsOversizedViewports = false;