diff --git a/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DProfilerFrameCapture.cpp b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DProfilerFrameCapture.cpp index 4c2f9b40a39..57c4c68a893 100644 --- a/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DProfilerFrameCapture.cpp +++ b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DProfilerFrameCapture.cpp @@ -103,8 +103,8 @@ void W3DProfilerFrameCapture::Capture(UnsignedInt displayWidth, UnsignedInt disp return; } - // get the backbuffer - SurfaceClass *backBuffer = DX8Wrapper::_Get_DX8_Back_Buffer(); + // get the surface the scene is rendered into + SurfaceClass *backBuffer = DX8Wrapper::_Get_DX8_Scene_Surface(); if (!backBuffer) { REF_PTR_RELEASE(surfaceClass); diff --git a/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DSmudge.cpp b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DSmudge.cpp index 37fc8609328..1d3c2318427 100644 --- a/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DSmudge.cpp +++ b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DSmudge.cpp @@ -80,7 +80,8 @@ void W3DSmudgeManager::ReAcquireResources() { ReleaseResources(); - SurfaceClass *surface=DX8Wrapper::_Get_DX8_Back_Buffer(); + // TheSuperHackers @bugfix coconutbird 05/11/2026 Match the surface the scene is rendered into, which is not always the back buffer. + SurfaceClass *surface=DX8Wrapper::_Get_DX8_Scene_Surface(); SurfaceClass::SurfaceDescription surface_desc; surface->Get_Description(surface_desc); @@ -323,7 +324,8 @@ void W3DSmudgeManager::render(RenderInfoClass &rinfo) return; } - SurfaceClass *backBuffer = DX8Wrapper::_Get_DX8_Back_Buffer(); + // TheSuperHackers @bugfix coconutbird 05/11/2026 Copy from the surface the scene is rendered into, which is not always the back buffer. + SurfaceClass *backBuffer = DX8Wrapper::_Get_DX8_Scene_Surface(); if (!backBuffer) return; diff --git a/Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp b/Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp index 5597ef73649..86b82f736cf 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp +++ b/Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp @@ -120,6 +120,15 @@ int DX8Wrapper::TextureBitDepth = DEFAULT_TEXTURE_BIT_DEPTH; bool DX8Wrapper::IsWindowed = false; D3DFORMAT DX8Wrapper::DisplayFormat = D3DFMT_UNKNOWN; D3DMULTISAMPLE_TYPE DX8Wrapper::MultiSampleAntiAliasing = DEFAULT_MSAA; +bool DX8Wrapper::FullscreenBackBufferUsesDisplayFormat = false; +unsigned DX8Wrapper::FullscreenResetsWithoutPresent = 0; +bool DX8Wrapper::UseSceneAlphaTarget = false; +D3DMULTISAMPLE_TYPE DX8Wrapper::SceneAlphaMultiSampleType = D3DMULTISAMPLE_NONE; +IDirect3DTexture8 * DX8Wrapper::SceneAlphaTexture = nullptr; +IDirect3DSurface8 * DX8Wrapper::SceneAlphaTextureSurface = nullptr; +IDirect3DSurface8 * DX8Wrapper::SceneAlphaMultisampleSurface = nullptr; +IDirect3DSurface8 * DX8Wrapper::SceneAlphaDepthSurface = nullptr; +DWORD DX8Wrapper::SceneAlphaStateBlock = 0; // shader system additions KJM v DWORD DX8Wrapper::Vertex_Shader = 0; @@ -622,6 +631,7 @@ bool DX8Wrapper::Reset_Device(bool reload_assets) DynamicIBAccessClass::_Deinit(); DX8TextureManagerClass::Release_Textures(); SHD_SHUTDOWN_SHADERS; + Release_Scene_Alpha_Target(); // Reset frame count to reflect the flipping chain being reset by Reset() FrameCount = 0; @@ -631,9 +641,28 @@ bool DX8Wrapper::Reset_Device(bool reload_assets) HRESULT hr=_Get_D3D_Device8()->TestCooperativeLevel(); if (hr != D3DERR_DEVICELOST ) - { DX8CALL_HRES(Reset(&_PresentParameters),hr) + { + // TheSuperHackers @bugfix coconutbird 05/11/2026 A fullscreen back buffer with destination alpha does not + // match the display format, so every Reset() sets the display mode again. On systems where a display mode + // change loses the device, the device is lost again by its own Reset() before it presents a single frame, + // and the game resets forever while the screen keeps switching modes. When the previous Reset() did not + // last until a frame was presented, use the display format for the back buffer, so that Reset() can + // restore the device without changing the display mode. + if (!IsWindowed && FullscreenResetsWithoutPresent != 0 && _PresentParameters.BackBufferFormat != DisplayFormat) + { + Use_Display_Format_For_Fullscreen_Back_Buffer(); + } + + Prepare_Scene_Alpha_Target(); + + DX8CALL_HRES(Reset(&_PresentParameters),hr) if (hr != D3D_OK) return false; //reset failed. + + if (!IsWindowed) + ++FullscreenResetsWithoutPresent; + + Create_Scene_Alpha_Target(); } else return false; //device is lost and can't be reset. @@ -658,6 +687,7 @@ bool DX8Wrapper::Reset_Device(bool reload_assets) void DX8Wrapper::Release_Device() { if (D3DDevice) { + Release_Scene_Alpha_Target(); for (int a=0;aCheckDeviceType(0,D3DDEVTYPE_HAL,*set_colorbuffer,D3DFMT_A8R8G8B8, TRUE) == D3D_OK) + // TheSuperHackers @bugfix coconutbird 05/11/2026 Keep the display format once Reset_Device found that a back buffer + // with destination alpha cannot be kept in fullscreen. + if (bitdepth==32 && *set_colorbuffer == D3DFMT_X8R8G8B8 && !FullscreenBackBufferUsesDisplayFormat && D3DInterface->CheckDeviceType(0,D3DDEVTYPE_HAL,*set_colorbuffer,D3DFMT_A8R8G8B8, TRUE) == D3D_OK) { //promote 32-bit modes to include destination alpha when supported *set_backbuffer = D3DFMT_A8R8G8B8; @@ -1624,6 +1656,245 @@ bool DX8Wrapper::Test_Z_Mode(D3DFORMAT colorbuffer,D3DFORMAT backbuffer, D3DFORM return true; } +void DX8Wrapper::Use_Display_Format_For_Fullscreen_Back_Buffer() +{ + D3DFORMAT zmode; + if (!Find_Z_Mode(DisplayFormat, DisplayFormat, &zmode)) + { + WWDEBUG_SAY(("DX8Wrapper::Reset_Device did not last until a frame was presented, but no depth buffer format matches the display format. Keeping the fullscreen back buffer format.")); + return; + } + + WWDEBUG_SAY(("DX8Wrapper::Reset_Device did not last until a frame was presented. Using the display format for the fullscreen back buffer.")); + FullscreenBackBufferUsesDisplayFormat = true; + _PresentParameters.BackBufferFormat = DisplayFormat; + _PresentParameters.AutoDepthStencilFormat = zmode; + + if (_PresentParameters.MultiSampleType != D3DMULTISAMPLE_NONE) + { + const HRESULT hrBack = D3DInterface->CheckDeviceMultiSampleType(CurRenderDevice, D3DDEVTYPE_HAL, + _PresentParameters.BackBufferFormat, FALSE, _PresentParameters.MultiSampleType); + const HRESULT hrDepth = D3DInterface->CheckDeviceMultiSampleType(CurRenderDevice, D3DDEVTYPE_HAL, + _PresentParameters.AutoDepthStencilFormat, FALSE, _PresentParameters.MultiSampleType); + + if (FAILED(hrBack) || FAILED(hrDepth)) + { + WWDEBUG_SAY(("Requested MSAA Mode Not Supported")); + MultiSampleAntiAliasing = D3DMULTISAMPLE_NONE; + _PresentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; + } + } +} + +// TheSuperHackers @bugfix coconutbird 05/11/2026 When the fullscreen back buffer uses the display format, it has no +// destination alpha, and effects that need it, such as the soft shoreline of standing water, would be lost. Render the +// scene into an A8R8G8B8 target instead and copy it onto the back buffer in End_Scene. With multisampling, the scene +// target is multisampled instead of the back buffer: the scene renders into a multisampled surface with its own depth +// buffer, which is resolved into the texture before the copy. The device keeps this target as its render target, so +// code that restores the previous render target returns to it. +// The back buffer multisampling depends on whether the scene target is used, so this is decided before Reset(). +void DX8Wrapper::Prepare_Scene_Alpha_Target() +{ + UseSceneAlphaTarget = false; + + if (IsWindowed || !FullscreenBackBufferUsesDisplayFormat || BitDepth != 32 || _PresentParameters.BackBufferFormat != D3DFMT_X8R8G8B8) + return; + + const D3DMULTISAMPLE_TYPE multiSampleType = MultiSampleAntiAliasing; + + if (FAILED(D3DInterface->CheckDeviceFormat(CurRenderDevice, D3DDEVTYPE_HAL, DisplayFormat, + D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8)) + || FAILED(D3DInterface->CheckDepthStencilMatch(CurRenderDevice, D3DDEVTYPE_HAL, DisplayFormat, + D3DFMT_A8R8G8B8, _PresentParameters.AutoDepthStencilFormat)) + || (multiSampleType != D3DMULTISAMPLE_NONE + && (FAILED(D3DInterface->CheckDeviceMultiSampleType(CurRenderDevice, D3DDEVTYPE_HAL, + D3DFMT_A8R8G8B8, FALSE, multiSampleType)) + || FAILED(D3DInterface->CheckDeviceMultiSampleType(CurRenderDevice, D3DDEVTYPE_HAL, + _PresentParameters.AutoDepthStencilFormat, FALSE, multiSampleType))))) + { + WWDEBUG_SAY(("DX8Wrapper::Prepare_Scene_Alpha_Target: A8R8G8B8 scene target is not supported.")); + return; + } + + UseSceneAlphaTarget = true; + SceneAlphaMultiSampleType = multiSampleType; + _PresentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; +} + +void DX8Wrapper::Create_Scene_Alpha_Target() +{ + WWASSERT(SceneAlphaTexture == nullptr); + + if (!UseSceneAlphaTarget) + return; + + const UINT width = _PresentParameters.BackBufferWidth; + const UINT height = _PresentParameters.BackBufferHeight; + + HRESULT hr = D3DDevice->CreateTexture(width, height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &SceneAlphaTexture); + if (SUCCEEDED(hr)) + hr = SceneAlphaTexture->GetSurfaceLevel(0, &SceneAlphaTextureSurface); + if (SUCCEEDED(hr) && SceneAlphaMultiSampleType != D3DMULTISAMPLE_NONE) + { + hr = D3DDevice->CreateRenderTarget(width, height, D3DFMT_A8R8G8B8, SceneAlphaMultiSampleType, FALSE, &SceneAlphaMultisampleSurface); + if (SUCCEEDED(hr)) + hr = D3DDevice->CreateDepthStencilSurface(width, height, _PresentParameters.AutoDepthStencilFormat, SceneAlphaMultiSampleType, &SceneAlphaDepthSurface); + } + + if (SUCCEEDED(hr)) + hr = D3DDevice->CreateStateBlock(D3DSBT_ALL, &SceneAlphaStateBlock); + + IDirect3DSurface8 *depthBuffer = nullptr; + if (SUCCEEDED(hr)) + hr = D3DDevice->GetDepthStencilSurface(&depthBuffer); + if (SUCCEEDED(hr)) + hr = D3DDevice->SetRenderTarget(Get_Scene_Alpha_Render_Surface(), SceneAlphaDepthSurface ? SceneAlphaDepthSurface : depthBuffer); + if (depthBuffer) + depthBuffer->Release(); + + if (FAILED(hr)) + { + WWDEBUG_SAY(("DX8Wrapper::Create_Scene_Alpha_Target: failed with 0x%08X.", (unsigned)hr)); + Release_Scene_Alpha_Target(); + UseSceneAlphaTarget = false; + // The back buffer was reset without multisampling for the scene target, so report what the device has now. + MultiSampleAntiAliasing = _PresentParameters.MultiSampleType; + return; + } + + WWDEBUG_SAY(("DX8Wrapper::Create_Scene_Alpha_Target: rendering the scene into a %ux%u A8R8G8B8 target, multisample type %d.", + width, height, (int)SceneAlphaMultiSampleType)); +} + +void DX8Wrapper::Release_Scene_Alpha_Target() +{ + if (SceneAlphaTexture == nullptr) + return; + + // The device holds references to its render target and depth buffer, so give it the back buffer back first. + // The back buffer cannot use the multisampled depth buffer of the scene target, so when that one is set, no + // depth buffer is set until Reset() restores the automatic one. + IDirect3DSurface8 *backBuffer = nullptr; + IDirect3DSurface8 *depthBuffer = nullptr; + D3DDevice->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &backBuffer); + D3DDevice->GetDepthStencilSurface(&depthBuffer); + if (depthBuffer != nullptr && depthBuffer == SceneAlphaDepthSurface) + { + depthBuffer->Release(); + depthBuffer = nullptr; + } + if (backBuffer) + { + D3DDevice->SetRenderTarget(backBuffer, depthBuffer); + backBuffer->Release(); + } + if (depthBuffer) + depthBuffer->Release(); + + if (SceneAlphaStateBlock) + { + D3DDevice->DeleteStateBlock(SceneAlphaStateBlock); + SceneAlphaStateBlock = 0; + } + + if (SceneAlphaDepthSurface) + { + SceneAlphaDepthSurface->Release(); + SceneAlphaDepthSurface = nullptr; + } + + if (SceneAlphaMultisampleSurface) + { + SceneAlphaMultisampleSurface->Release(); + SceneAlphaMultisampleSurface = nullptr; + } + if (SceneAlphaTextureSurface) + { + SceneAlphaTextureSurface->Release(); + SceneAlphaTextureSurface = nullptr; + } + SceneAlphaTexture->Release(); + SceneAlphaTexture = nullptr; +} + +void DX8Wrapper::Copy_Scene_Alpha_Target_To_Back_Buffer() +{ + WWPROFILE("DX8Wrapper::Copy_Scene_Alpha_Target_To_Back_Buffer"); + + if (SceneAlphaMultisampleSurface) + { + DX8CALL(CopyRects(SceneAlphaMultisampleSurface, nullptr, 0, SceneAlphaTextureSurface, nullptr)); + } + + IDirect3DSurface8 *backBuffer = nullptr; + DX8CALL(GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &backBuffer)); + if (backBuffer == nullptr) + return; + + IDirect3DSurface8 *depthBuffer = nullptr; + DX8CALL(GetDepthStencilSurface(&depthBuffer)); + + // Restore every device state after the copy, so the render state cache stays valid. + DX8CALL(CaptureStateBlock(SceneAlphaStateBlock)); + + // The copy needs no depth buffer, and the back buffer cannot use the multisampled depth buffer of the scene target. + DX8CALL(SetRenderTarget(backBuffer, nullptr)); + DX8CALL(BeginScene()); + + DX8CALL(SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE)); + DX8CALL(SetRenderState(D3DRS_ZWRITEENABLE, FALSE)); + DX8CALL(SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE)); + DX8CALL(SetRenderState(D3DRS_ALPHATESTENABLE, FALSE)); + DX8CALL(SetRenderState(D3DRS_STENCILENABLE, FALSE)); + DX8CALL(SetRenderState(D3DRS_FOGENABLE, FALSE)); + DX8CALL(SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE)); + DX8CALL(SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID)); + DX8CALL(SetRenderState(D3DRS_DITHERENABLE, FALSE)); + DX8CALL(SetRenderState(D3DRS_LIGHTING, FALSE)); + DX8CALL(SetRenderState(D3DRS_SPECULARENABLE, FALSE)); + DX8CALL(SetRenderState(D3DRS_WRAP0, 0)); + DX8CALL(SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_ALPHA)); + + DX8CALL(SetPixelShader(0)); + DX8CALL(SetVertexShader(D3DFVF_XYZRHW | D3DFVF_TEX1)); + DX8CALL(SetTexture(0, SceneAlphaTexture)); + DX8CALL(SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1)); + DX8CALL(SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE)); + DX8CALL(SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1)); + DX8CALL(SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE)); + DX8CALL(SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0)); + DX8CALL(SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE)); + DX8CALL(SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP)); + DX8CALL(SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP)); + DX8CALL(SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_POINT)); + DX8CALL(SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_POINT)); + DX8CALL(SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_NONE)); + DX8CALL(SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE)); + DX8CALL(SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE)); + + // Offset by half a pixel so that each texel maps onto exactly one pixel. + struct QuadVertex { float x, y, z, rhw, u, v; }; + const float right = (float)_PresentParameters.BackBufferWidth - 0.5f; + const float bottom = (float)_PresentParameters.BackBufferHeight - 0.5f; + const QuadVertex quad[4] = + { + { -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f }, + { right, -0.5f, 0.0f, 1.0f, 1.0f, 0.0f }, + { -0.5f, bottom, 0.0f, 1.0f, 0.0f, 1.0f }, + { right, bottom, 0.0f, 1.0f, 1.0f, 1.0f }, + }; + DX8CALL(DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(QuadVertex))); + + DX8CALL(EndScene()); + DX8CALL(SetRenderTarget(Get_Scene_Alpha_Render_Surface(), depthBuffer)); + + DX8CALL(ApplyStateBlock(SceneAlphaStateBlock)); + + backBuffer->Release(); + if (depthBuffer) + depthBuffer->Release(); +} + void DX8Wrapper::Reset_Statistics() { @@ -1672,6 +1943,9 @@ void DX8Wrapper::End_Scene(bool flip_frames) DX8_THREAD_ASSERT(); DX8CALL(EndScene()); + if (flip_frames && SceneAlphaTexture) + Copy_Scene_Alpha_Target_To_Back_Buffer(); + DX8WebBrowser::Render(0); if (flip_frames) { @@ -1692,6 +1966,7 @@ void DX8Wrapper::End_Scene(bool flip_frames) #endif IsDeviceLost=false; FrameCount++; + FullscreenResetsWithoutPresent = 0; } else { IsDeviceLost=true; @@ -1760,6 +2035,7 @@ void DX8Wrapper::Flip_To_Primary() if (SUCCEEDED(hr)) { IsDeviceLost=false; FrameCount++; + FullscreenResetsWithoutPresent = 0; WWDEBUG_SAY(("Flip to primary succeeded %ld", FrameCount)); } else { @@ -3146,6 +3422,17 @@ SurfaceClass * DX8Wrapper::_Get_DX8_Back_Buffer(unsigned int num) return surf; } +SurfaceClass * DX8Wrapper::_Get_DX8_Scene_Surface() +{ + DX8_THREAD_ASSERT(); + + IDirect3DSurface8 * surface = Get_Scene_Alpha_Render_Surface(); + if (surface == nullptr) + return _Get_DX8_Back_Buffer(); + + return NEW_REF(SurfaceClass,(surface)); +} + TextureClass * DX8Wrapper::Create_Render_Target (int width, int height, WW3DFormat format) @@ -4441,5 +4728,8 @@ const char* DX8Wrapper::Get_DX8_Blend_Op_Name(unsigned value) WW3DFormat DX8Wrapper::getBackBufferFormat() { + if (SceneAlphaTexture) + return WW3D_FORMAT_A8R8G8B8; + return D3DFormat_To_WW3DFormat( _PresentParameters.BackBufferFormat ); } diff --git a/Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.h b/Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.h index 2e929450484..7404e4fb44a 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.h +++ b/Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.h @@ -423,6 +423,8 @@ class DX8Wrapper static IDirect3DSurface8 * _Create_DX8_Surface(const char *filename); static IDirect3DSurface8 * _Get_DX8_Front_Buffer(); static SurfaceClass * _Get_DX8_Back_Buffer(unsigned int num=0); + /// Returns the surface the scene is rendered into: the scene alpha target when there is one, otherwise the back buffer. + static SurfaceClass * _Get_DX8_Scene_Surface(); static void _Copy_DX8_Rects( IDirect3DSurface8* pSourceSurface, @@ -532,7 +534,7 @@ class DX8Wrapper static IDirect3DDevice8* _Get_D3D_Device8() { return D3DDevice; } static IDirect3D8* _Get_D3D8() { return D3DInterface; } - /// Returns the display format - added by TR for video playback - not part of W3D + /// Returns the format of the surface the scene is rendered into - added by TR for video playback - not part of W3D static WW3DFormat getBackBufferFormat(); static bool Reset_Device(bool reload_assets=true); @@ -624,6 +626,12 @@ class DX8Wrapper static bool Find_Color_Mode(D3DFORMAT colorbuffer, int resx, int resy, UINT *mode); static bool Find_Z_Mode(D3DFORMAT colorbuffer,D3DFORMAT backbuffer, D3DFORMAT *zmode); static bool Test_Z_Mode(D3DFORMAT colorbuffer,D3DFORMAT backbuffer, D3DFORMAT zmode); + static void Use_Display_Format_For_Fullscreen_Back_Buffer(); + static void Prepare_Scene_Alpha_Target(); + static void Create_Scene_Alpha_Target(); + static void Release_Scene_Alpha_Target(); + static void Copy_Scene_Alpha_Target_To_Back_Buffer(); + static IDirect3DSurface8 * Get_Scene_Alpha_Render_Surface() { return SceneAlphaMultisampleSurface ? SceneAlphaMultisampleSurface : SceneAlphaTextureSurface; } static void Compute_Caps(WW3DFormat display_format); /* @@ -651,6 +659,15 @@ class DX8Wrapper static bool IsWindowed; static D3DFORMAT DisplayFormat; static D3DMULTISAMPLE_TYPE MultiSampleAntiAliasing; + static bool FullscreenBackBufferUsesDisplayFormat; + static unsigned FullscreenResetsWithoutPresent; + static bool UseSceneAlphaTarget; + static D3DMULTISAMPLE_TYPE SceneAlphaMultiSampleType; + static IDirect3DTexture8 * SceneAlphaTexture; + static IDirect3DSurface8 * SceneAlphaTextureSurface; + static IDirect3DSurface8 * SceneAlphaMultisampleSurface; + static IDirect3DSurface8 * SceneAlphaDepthSurface; + static DWORD SceneAlphaStateBlock; // shader system updates KJM v