Add VSync and fullscreen settings, fix swap chain resize and revert lighting changes
- Add VSync and Exclusive Fullscreen toggles to the graphics settings menu - Rewrite D3D11 swap chain to use DXGI flip model with tearing support - Fix black screen on resize by creating new swap chain instead of ResizeBuffers - Revert conditional lighting optimization in Level::setTileAndData back to unconditional checkLight - Revert deferred lightGaps flagging in LevelChunk::recalcHeight back to immediate lightGap calls - Add SWF/ARC editing tools used to add new UI checkboxes
This commit is contained in:
@@ -52,6 +52,7 @@ set_target_properties(Minecraft.Client PROPERTIES
|
||||
target_link_libraries(Minecraft.Client PRIVATE
|
||||
Minecraft.World
|
||||
d3d11
|
||||
dxgi
|
||||
d3dcompiler
|
||||
XInput9_1_0
|
||||
wsock32
|
||||
|
||||
@@ -105,6 +105,8 @@ enum EGameHostOptionWorldSize
|
||||
#define GAMESETTING_ANIMATEDCHARACTER 0x00008000
|
||||
#define GAMESETTING_PS3EULAREAD 0x00010000
|
||||
#define GAMESETTING_PSVITANETWORKMODEADHOC 0x00020000
|
||||
#define GAMESETTING_VSYNC 0x00040000
|
||||
#define GAMESETTING_EXCLUSIVEFULLSCREEN 0x00080000
|
||||
|
||||
|
||||
// defines for languages
|
||||
|
||||
@@ -178,6 +178,9 @@ enum eGameSetting
|
||||
// PSVita
|
||||
eGameSetting_PSVita_NetworkModeAdhoc,
|
||||
|
||||
// PC
|
||||
eGameSetting_VSync,
|
||||
eGameSetting_ExclusiveFullscreen,
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -1382,6 +1382,7 @@ void CMinecraftApp::ApplyGameSettingsChanged(int iPad)
|
||||
ActionGameSettings(iPad,eGameSetting_AnimatedCharacter);
|
||||
|
||||
ActionGameSettings(iPad,eGameSetting_PS3_EULA_Read);
|
||||
ActionGameSettings(iPad,eGameSetting_VSync);
|
||||
|
||||
}
|
||||
|
||||
@@ -1617,6 +1618,22 @@ void CMinecraftApp::ActionGameSettings(int iPad,eGameSetting eVal)
|
||||
case eGameSetting_PSVita_NetworkModeAdhoc:
|
||||
//nothing to do here
|
||||
break;
|
||||
case eGameSetting_VSync:
|
||||
#ifdef _WINDOWS64
|
||||
{
|
||||
extern bool g_bVSync;
|
||||
g_bVSync = (GetGameSettings(iPad, eGameSetting_VSync) != 0);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case eGameSetting_ExclusiveFullscreen:
|
||||
#ifdef _WINDOWS64
|
||||
{
|
||||
extern void SetExclusiveFullscreen(bool enabled);
|
||||
SetExclusiveFullscreen(GetGameSettings(iPad, eGameSetting_ExclusiveFullscreen) != 0);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2328,6 +2345,38 @@ void CMinecraftApp::SetGameSettings(int iPad,eGameSetting eVal,unsigned char ucV
|
||||
}
|
||||
break;
|
||||
|
||||
case eGameSetting_VSync:
|
||||
if(((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_VSYNC)>>18)!=(ucVal&0x01))
|
||||
{
|
||||
if(ucVal==1)
|
||||
{
|
||||
GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_VSYNC;
|
||||
}
|
||||
else
|
||||
{
|
||||
GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_VSYNC;
|
||||
}
|
||||
ActionGameSettings(iPad,eVal);
|
||||
GameSettingsA[iPad]->bSettingsChanged=true;
|
||||
}
|
||||
break;
|
||||
|
||||
case eGameSetting_ExclusiveFullscreen:
|
||||
if(((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_EXCLUSIVEFULLSCREEN)>>19)!=(ucVal&0x01))
|
||||
{
|
||||
if(ucVal==1)
|
||||
{
|
||||
GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_EXCLUSIVEFULLSCREEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_EXCLUSIVEFULLSCREEN;
|
||||
}
|
||||
ActionGameSettings(iPad,eVal);
|
||||
GameSettingsA[iPad]->bSettingsChanged=true;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2463,6 +2512,12 @@ unsigned char CMinecraftApp::GetGameSettings(int iPad,eGameSetting eVal)
|
||||
case eGameSetting_PSVita_NetworkModeAdhoc:
|
||||
return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_PSVITANETWORKMODEADHOC)>>17;
|
||||
|
||||
case eGameSetting_VSync:
|
||||
return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_VSYNC)>>18;
|
||||
|
||||
case eGameSetting_ExclusiveFullscreen:
|
||||
return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_EXCLUSIVEFULLSCREEN)>>19;
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -5,6 +5,11 @@
|
||||
#include "..\..\Options.h"
|
||||
#include "..\..\GameRenderer.h"
|
||||
|
||||
#ifdef _WINDOWS64
|
||||
extern bool g_bVSync;
|
||||
extern void SetExclusiveFullscreen(bool enabled);
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr int FOV_MIN = 70;
|
||||
@@ -62,8 +67,10 @@ UIScene_SettingsGraphicsMenu::UIScene_SettingsGraphicsMenu(int iPad, void *initD
|
||||
m_checkboxClouds.init(app.GetString(IDS_CHECKBOX_RENDER_CLOUDS),eControl_Clouds,(app.GetGameSettings(m_iPad,eGameSetting_Clouds)!=0));
|
||||
m_checkboxBedrockFog.init(app.GetString(IDS_CHECKBOX_RENDER_BEDROCKFOG),eControl_BedrockFog,(app.GetGameSettings(m_iPad,eGameSetting_BedrockFog)!=0));
|
||||
m_checkboxCustomSkinAnim.init(app.GetString(IDS_CHECKBOX_CUSTOM_SKIN_ANIM),eControl_CustomSkinAnim,(app.GetGameSettings(m_iPad,eGameSetting_CustomSkinAnim)!=0));
|
||||
m_checkboxVSync.init(L"VSync",eControl_VSync,(app.GetGameSettings(m_iPad,eGameSetting_VSync)!=0));
|
||||
m_checkboxExclusiveFullscreen.init(L"Fullscreen",eControl_ExclusiveFullscreen,(app.GetGameSettings(m_iPad,eGameSetting_ExclusiveFullscreen)!=0));
|
||||
|
||||
|
||||
|
||||
WCHAR TempString[256];
|
||||
|
||||
swprintf(TempString, 256, L"Render Distance: %d",app.GetGameSettings(m_iPad,eGameSetting_RenderDistance));
|
||||
@@ -82,9 +89,15 @@ UIScene_SettingsGraphicsMenu::UIScene_SettingsGraphicsMenu(int iPad, void *initD
|
||||
|
||||
doHorizontalResizeCheck();
|
||||
|
||||
#ifndef _WINDOWS64
|
||||
// VSync and Exclusive Fullscreen are only available on PC
|
||||
removeControl(&m_checkboxVSync, true);
|
||||
removeControl(&m_checkboxExclusiveFullscreen, true);
|
||||
#endif
|
||||
|
||||
const bool bInGame=(Minecraft::GetInstance()->level!=nullptr);
|
||||
const bool bIsPrimaryPad=(ProfileManager.GetPrimaryPad()==m_iPad);
|
||||
// if we're not in the game, we need to use basescene 0
|
||||
// if we're not in the game, we need to use basescene 0
|
||||
if(bInGame)
|
||||
{
|
||||
// If the game has started, then you need to be the host to change the in-game gamertags
|
||||
@@ -165,6 +178,12 @@ void UIScene_SettingsGraphicsMenu::handleInput(int iPad, int key, bool repeat, b
|
||||
app.SetGameSettings(m_iPad,eGameSetting_Clouds,m_checkboxClouds.IsChecked()?1:0);
|
||||
app.SetGameSettings(m_iPad,eGameSetting_BedrockFog,m_checkboxBedrockFog.IsChecked()?1:0);
|
||||
app.SetGameSettings(m_iPad,eGameSetting_CustomSkinAnim,m_checkboxCustomSkinAnim.IsChecked()?1:0);
|
||||
app.SetGameSettings(m_iPad,eGameSetting_VSync,m_checkboxVSync.IsChecked()?1:0);
|
||||
app.SetGameSettings(m_iPad,eGameSetting_ExclusiveFullscreen,m_checkboxExclusiveFullscreen.IsChecked()?1:0);
|
||||
#ifdef _WINDOWS64
|
||||
g_bVSync = m_checkboxVSync.IsChecked();
|
||||
SetExclusiveFullscreen(m_checkboxExclusiveFullscreen.IsChecked());
|
||||
#endif
|
||||
|
||||
navigateBack();
|
||||
handled = true;
|
||||
|
||||
@@ -12,18 +12,22 @@ private:
|
||||
eControl_Clouds,
|
||||
eControl_BedrockFog,
|
||||
eControl_CustomSkinAnim,
|
||||
eControl_VSync,
|
||||
eControl_ExclusiveFullscreen,
|
||||
eControl_RenderDistance,
|
||||
eControl_Gamma,
|
||||
eControl_FOV,
|
||||
eControl_InterfaceOpacity
|
||||
};
|
||||
|
||||
UIControl_CheckBox m_checkboxClouds, m_checkboxBedrockFog, m_checkboxCustomSkinAnim; // Checkboxes
|
||||
UIControl_CheckBox m_checkboxClouds, m_checkboxBedrockFog, m_checkboxCustomSkinAnim, m_checkboxVSync, m_checkboxExclusiveFullscreen; // Checkboxes
|
||||
UIControl_Slider m_sliderRenderDistance, m_sliderGamma, m_sliderFOV, m_sliderInterfaceOpacity; // Sliders
|
||||
UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene)
|
||||
UI_MAP_ELEMENT( m_checkboxClouds, "Clouds")
|
||||
UI_MAP_ELEMENT( m_checkboxBedrockFog, "BedrockFog")
|
||||
UI_MAP_ELEMENT( m_checkboxCustomSkinAnim, "CustomSkinAnim")
|
||||
UI_MAP_ELEMENT( m_checkboxVSync, "VSync")
|
||||
UI_MAP_ELEMENT( m_checkboxExclusiveFullscreen, "ExclusiveFullscreen")
|
||||
UI_MAP_ELEMENT( m_sliderRenderDistance, "RenderDistance")
|
||||
UI_MAP_ELEMENT( m_sliderGamma, "Gamma")
|
||||
UI_MAP_ELEMENT(m_sliderFOV, "FOV")
|
||||
|
||||
@@ -467,6 +467,57 @@ D3D_FEATURE_LEVEL g_featureLevel = D3D_FEATURE_LEVEL_11_0;
|
||||
ID3D11Device* g_pd3dDevice = nullptr;
|
||||
ID3D11DeviceContext* g_pImmediateContext = nullptr;
|
||||
IDXGISwapChain* g_pSwapChain = nullptr;
|
||||
bool g_bVSync = false;
|
||||
static bool g_bTearingSupported = false;
|
||||
static bool g_bPendingExclusiveFullscreen = false;
|
||||
static bool g_bPendingExclusiveFullscreenValue = false;
|
||||
|
||||
// COM proxy for IDXGISwapChain — delegates all calls to the real swap chain,
|
||||
// but overrides Present() to set SyncInterval=1 when VSync is enabled.
|
||||
// Avoids vtable patching, which conflicts with the D3D11 debug layer.
|
||||
static class SwapChainVSyncProxy : public IDXGISwapChain
|
||||
{
|
||||
public:
|
||||
void SetTarget(IDXGISwapChain* pReal) { m_pReal = pReal; }
|
||||
|
||||
// IUnknown
|
||||
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) override { return m_pReal->QueryInterface(riid, ppvObject); }
|
||||
ULONG STDMETHODCALLTYPE AddRef() override { return m_pReal->AddRef(); }
|
||||
ULONG STDMETHODCALLTYPE Release() override { return m_pReal->Release(); }
|
||||
|
||||
// IDXGIObject
|
||||
HRESULT STDMETHODCALLTYPE SetPrivateData(REFGUID Name, UINT DataSize, const void* pData) override { return m_pReal->SetPrivateData(Name, DataSize, pData); }
|
||||
HRESULT STDMETHODCALLTYPE SetPrivateDataInterface(REFGUID Name, const IUnknown* pUnknown) override { return m_pReal->SetPrivateDataInterface(Name, pUnknown); }
|
||||
HRESULT STDMETHODCALLTYPE GetPrivateData(REFGUID Name, UINT* pDataSize, void* pData) override { return m_pReal->GetPrivateData(Name, pDataSize, pData); }
|
||||
HRESULT STDMETHODCALLTYPE GetParent(REFIID riid, void** ppParent) override { return m_pReal->GetParent(riid, ppParent); }
|
||||
|
||||
// IDXGIDeviceSubObject
|
||||
HRESULT STDMETHODCALLTYPE GetDevice(REFIID riid, void** ppDevice) override { return m_pReal->GetDevice(riid, ppDevice); }
|
||||
|
||||
// IDXGISwapChain
|
||||
HRESULT STDMETHODCALLTYPE Present(UINT SyncInterval, UINT Flags) override
|
||||
{
|
||||
if (g_bVSync)
|
||||
return m_pReal->Present(1, Flags);
|
||||
// DXGI_PRESENT_ALLOW_TEARING is only valid in windowed mode
|
||||
if (g_bTearingSupported)
|
||||
Flags |= DXGI_PRESENT_ALLOW_TEARING;
|
||||
return m_pReal->Present(0, Flags);
|
||||
}
|
||||
HRESULT STDMETHODCALLTYPE GetBuffer(UINT Buffer, REFIID riid, void** ppSurface) override { return m_pReal->GetBuffer(Buffer, riid, ppSurface); }
|
||||
HRESULT STDMETHODCALLTYPE SetFullscreenState(BOOL Fullscreen, IDXGIOutput* pTarget) override { return m_pReal->SetFullscreenState(Fullscreen, pTarget); }
|
||||
HRESULT STDMETHODCALLTYPE GetFullscreenState(BOOL* pFullscreen, IDXGIOutput** ppTarget) override { return m_pReal->GetFullscreenState(pFullscreen, ppTarget); }
|
||||
HRESULT STDMETHODCALLTYPE GetDesc(DXGI_SWAP_CHAIN_DESC* pDesc) override { return m_pReal->GetDesc(pDesc); }
|
||||
HRESULT STDMETHODCALLTYPE ResizeBuffers(UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT NewFormat, UINT SwapChainFlags) override { return m_pReal->ResizeBuffers(BufferCount, Width, Height, NewFormat, SwapChainFlags); }
|
||||
HRESULT STDMETHODCALLTYPE ResizeTarget(const DXGI_MODE_DESC* pNewTargetParameters) override { return m_pReal->ResizeTarget(pNewTargetParameters); }
|
||||
HRESULT STDMETHODCALLTYPE GetContainingOutput(IDXGIOutput** ppOutput) override { return m_pReal->GetContainingOutput(ppOutput); }
|
||||
HRESULT STDMETHODCALLTYPE GetFrameStatistics(DXGI_FRAME_STATISTICS* pStats) override { return m_pReal->GetFrameStatistics(pStats); }
|
||||
HRESULT STDMETHODCALLTYPE GetLastPresentCount(UINT* pLastPresentCount) override { return m_pReal->GetLastPresentCount(pLastPresentCount); }
|
||||
|
||||
private:
|
||||
IDXGISwapChain* m_pReal = nullptr;
|
||||
} g_swapChainProxy;
|
||||
|
||||
ID3D11RenderTargetView* g_pRenderTargetView = nullptr;
|
||||
ID3D11DepthStencilView* g_pDepthStencilView = nullptr;
|
||||
ID3D11Texture2D* g_pDepthStencilBuffer = nullptr;
|
||||
@@ -817,19 +868,33 @@ HRESULT InitDevice()
|
||||
};
|
||||
UINT numFeatureLevels = ARRAYSIZE( featureLevels );
|
||||
|
||||
// Check tearing support before device/swap chain creation
|
||||
{
|
||||
IDXGIFactory5* factory5 = nullptr;
|
||||
if (SUCCEEDED(CreateDXGIFactory1(__uuidof(IDXGIFactory5), (void**)&factory5)))
|
||||
{
|
||||
BOOL allowTearing = FALSE;
|
||||
if (SUCCEEDED(factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allowTearing, sizeof(allowTearing))))
|
||||
g_bTearingSupported = (allowTearing == TRUE);
|
||||
factory5->Release();
|
||||
}
|
||||
}
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC sd;
|
||||
ZeroMemory( &sd, sizeof( sd ) );
|
||||
sd.BufferCount = 1;
|
||||
sd.BufferCount = 2;
|
||||
sd.BufferDesc.Width = width;
|
||||
sd.BufferDesc.Height = height;
|
||||
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
sd.BufferDesc.RefreshRate.Numerator = 60;
|
||||
sd.BufferDesc.RefreshRate.Denominator = 1;
|
||||
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT;
|
||||
sd.BufferDesc.RefreshRate.Numerator = 0;
|
||||
sd.BufferDesc.RefreshRate.Denominator = 0;
|
||||
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
sd.OutputWindow = g_hWnd;
|
||||
sd.SampleDesc.Count = 1;
|
||||
sd.SampleDesc.Quality = 0;
|
||||
sd.Windowed = TRUE;
|
||||
sd.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||
sd.Flags = g_bTearingSupported ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0;
|
||||
|
||||
for( UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++ )
|
||||
{
|
||||
@@ -890,7 +955,8 @@ HRESULT InitDevice()
|
||||
vp.TopLeftY = 0;
|
||||
g_pImmediateContext->RSSetViewports( 1, &vp );
|
||||
|
||||
RenderManager.Initialise(g_pd3dDevice, g_pSwapChain);
|
||||
g_swapChainProxy.SetTarget(g_pSwapChain);
|
||||
RenderManager.Initialise(g_pd3dDevice, &g_swapChainProxy);
|
||||
|
||||
PostProcesser::GetInstance().Init();
|
||||
|
||||
@@ -906,7 +972,7 @@ void Render()
|
||||
const float ClearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f }; //red,green,blue,alpha
|
||||
|
||||
g_pImmediateContext->ClearRenderTargetView( g_pRenderTargetView, ClearColor );
|
||||
g_pSwapChain->Present( 0, 0 );
|
||||
g_pSwapChain->Present(0, g_bTearingSupported ? DXGI_PRESENT_ALLOW_TEARING : 0);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
@@ -981,59 +1047,61 @@ static bool ResizeD3D(int newW, int newH)
|
||||
|
||||
gdraw_D3D11_PreReset();
|
||||
|
||||
// Get IDXGIFactory from the existing device BEFORE destroying the old swap chain.
|
||||
// If anything fails before we have a new swap chain, we abort without destroying
|
||||
// the old one — leaving the Renderer in a valid (old-size) state.
|
||||
IDXGISwapChain* pOldSwapChain = g_pSwapChain;
|
||||
bool success = false;
|
||||
HRESULT hr;
|
||||
|
||||
IDXGIDevice* dxgiDevice = NULL;
|
||||
IDXGIAdapter* dxgiAdapter = NULL;
|
||||
IDXGIFactory* dxgiFactory = NULL;
|
||||
hr = g_pd3dDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice);
|
||||
if (FAILED(hr)) goto postReset;
|
||||
hr = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&dxgiAdapter);
|
||||
if (FAILED(hr)) { dxgiDevice->Release(); goto postReset; }
|
||||
hr = dxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&dxgiFactory);
|
||||
dxgiAdapter->Release();
|
||||
dxgiDevice->Release();
|
||||
if (FAILED(hr)) goto postReset;
|
||||
|
||||
// Create new swap chain at backbuffer size
|
||||
// Create a brand-new swap chain instead of ResizeBuffers.
|
||||
// ResizeBuffers requires ALL backbuffer refs released, but the closed-source
|
||||
// Renderer holds hidden refs we can't track — causing DXGI_ERROR_INVALID_CALL
|
||||
// and leaving the Renderer with NULL views (black screen).
|
||||
// Creating a new swap chain orphans the old backbuffer (tiny leak) but avoids
|
||||
// the need to release every hidden reference.
|
||||
{
|
||||
IDXGIDevice* dxgiDevice = NULL;
|
||||
IDXGIAdapter* dxgiAdapter = NULL;
|
||||
IDXGIFactory* dxgiFactory = NULL;
|
||||
hr = g_pd3dDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice);
|
||||
if (FAILED(hr)) goto postReset;
|
||||
hr = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&dxgiAdapter);
|
||||
dxgiDevice->Release();
|
||||
if (FAILED(hr)) goto postReset;
|
||||
hr = dxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&dxgiFactory);
|
||||
dxgiAdapter->Release();
|
||||
if (FAILED(hr)) goto postReset;
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC sd = {};
|
||||
sd.BufferCount = 1;
|
||||
sd.BufferCount = 2;
|
||||
sd.BufferDesc.Width = bbW;
|
||||
sd.BufferDesc.Height = bbH;
|
||||
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
sd.BufferDesc.RefreshRate.Numerator = 60;
|
||||
sd.BufferDesc.RefreshRate.Denominator = 1;
|
||||
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT;
|
||||
sd.BufferDesc.RefreshRate.Numerator = 0;
|
||||
sd.BufferDesc.RefreshRate.Denominator = 0;
|
||||
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
sd.OutputWindow = g_hWnd;
|
||||
sd.SampleDesc.Count = 1;
|
||||
sd.SampleDesc.Quality = 0;
|
||||
sd.Windowed = TRUE;
|
||||
sd.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||
sd.Flags = g_bTearingSupported ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0;
|
||||
|
||||
IDXGISwapChain* pNewSwapChain = NULL;
|
||||
hr = dxgiFactory->CreateSwapChain(g_pd3dDevice, &sd, &pNewSwapChain);
|
||||
dxgiFactory->Release();
|
||||
if (FAILED(hr) || pNewSwapChain == NULL)
|
||||
if (FAILED(hr))
|
||||
{
|
||||
app.DebugPrintf("[RESIZE] CreateSwapChain FAILED hr=0x%08X — keeping old swap chain\n", (unsigned)hr);
|
||||
app.DebugPrintf("[RESIZE] CreateSwapChain FAILED hr=0x%08X\n", (unsigned)hr);
|
||||
goto postReset;
|
||||
}
|
||||
|
||||
// New swap chain created successfully — NOW destroy the old one.
|
||||
// The Renderer's internal RTV/SRV still reference the old backbuffer —
|
||||
// those COM objects become orphaned (tiny leak, harmless). We DON'T
|
||||
// release them because unknown code may also hold refs.
|
||||
// Destroy old, install new
|
||||
pOldSwapChain->Release();
|
||||
g_pSwapChain = pNewSwapChain;
|
||||
g_swapChainProxy.SetTarget(g_pSwapChain);
|
||||
}
|
||||
|
||||
// Patch Renderer's swap chain pointer
|
||||
*ppRM_SC = g_pSwapChain;
|
||||
// Patch Renderer's swap chain pointer (use proxy so VSync override stays active)
|
||||
*ppRM_SC = &g_swapChainProxy;
|
||||
|
||||
// Create render target views from new backbuffer
|
||||
{
|
||||
@@ -1218,6 +1286,29 @@ void ToggleFullscreen()
|
||||
g_KBMInput.SetWindowFocused(true);
|
||||
}
|
||||
|
||||
// Called from UI thread — defers the actual transition to the main game loop
|
||||
void SetExclusiveFullscreen(bool enabled)
|
||||
{
|
||||
if (enabled == g_isFullscreen)
|
||||
return;
|
||||
g_bPendingExclusiveFullscreen = true;
|
||||
g_bPendingExclusiveFullscreenValue = enabled;
|
||||
}
|
||||
|
||||
// Uses borderless fullscreen (ToggleFullscreen) rather than DXGI SetFullscreenState.
|
||||
// With DXGI_SWAP_EFFECT_FLIP_DISCARD + DXGI_PRESENT_ALLOW_TEARING, borderless
|
||||
// fullscreen gets the same direct-flip path as exclusive fullscreen on Windows 10+ —
|
||||
// identical latency and uncapped FPS. True DXGI exclusive fullscreen is blocked by
|
||||
// the 4J Renderer holding hidden backbuffer references that prevent ResizeBuffers.
|
||||
static void ApplyExclusiveFullscreen(bool enabled)
|
||||
{
|
||||
// Toggle into/out of borderless fullscreen if state doesn't match
|
||||
if (enabled && !g_isFullscreen)
|
||||
ToggleFullscreen();
|
||||
else if (!enabled && g_isFullscreen)
|
||||
ToggleFullscreen();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Clean up the objects we've created
|
||||
//--------------------------------------------------------------------------------------
|
||||
@@ -1801,6 +1892,13 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
|
||||
ToggleFullscreen();
|
||||
}
|
||||
|
||||
// Apply deferred exclusive fullscreen toggle
|
||||
if (g_bPendingExclusiveFullscreen)
|
||||
{
|
||||
g_bPendingExclusiveFullscreen = false;
|
||||
ApplyExclusiveFullscreen(g_bPendingExclusiveFullscreenValue);
|
||||
}
|
||||
|
||||
// TAB opens game info menu. - Vvis :3 - Updated by detectiveren
|
||||
if (g_KBMInput.IsKeyPressed(KeyboardMouseInput::KEY_HOST_SETTINGS) && !ui.GetMenuDisplayed(0))
|
||||
{
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
// TODO: reference additional headers your program requires here
|
||||
#include <DirectXMath.h>
|
||||
#include <d3d11.h>
|
||||
#include <dxgi1_5.h>
|
||||
using namespace DirectX;
|
||||
|
||||
#define HRESULT_SUCCEEDED(hr) (((HRESULT)(hr)) >= 0)
|
||||
|
||||
Reference in New Issue
Block a user