diff --git a/src/Include/xrAPI/xrAPI.h b/src/Include/xrAPI/xrAPI.h index 6611a7916a6..0150edb4b35 100644 --- a/src/Include/xrAPI/xrAPI.h +++ b/src/Include/xrAPI/xrAPI.h @@ -15,9 +15,6 @@ class UICore; class XRAPI_API EngineGlobalEnvironment { - using SupportCheck = bool(*)(); - using SetupEnv = void(*)(); - public: IRender* Render; IDebugRender* DRender; @@ -34,16 +31,6 @@ class XRAPI_API EngineGlobalEnvironment bool isDedicatedServer; int CurrentRenderer; - SupportCheck CheckR2; - SupportCheck CheckR3; - SupportCheck CheckR4; - SupportCheck CheckRGL; - SetupEnv SetupR1; - SetupEnv SetupR2; - SetupEnv SetupR3; - SetupEnv SetupR4; - SetupEnv SetupRGL; - SetupEnv SetupCurrentRenderer; }; extern XRAPI_API EngineGlobalEnvironment GEnv; diff --git a/src/Layers/xrRender/HW.cpp b/src/Layers/xrRender/HW.cpp index 48c113a4e14..bca6c1e5e60 100644 --- a/src/Layers/xrRender/HW.cpp +++ b/src/Layers/xrRender/HW.cpp @@ -29,6 +29,7 @@ void CHW::DestroyD3D() { _SHOW_REF("refCount:pD3D", pD3D); _RELEASE(pD3D); + hD3D = nullptr; } void CHW::CreateDevice(SDL_Window* m_sdlWnd) diff --git a/src/Layers/xrRenderPC_GL/xrRender_GL.cpp b/src/Layers/xrRenderPC_GL/xrRender_GL.cpp index daab1a74256..f44d657445f 100644 --- a/src/Layers/xrRenderPC_GL/xrRender_GL.cpp +++ b/src/Layers/xrRenderPC_GL/xrRender_GL.cpp @@ -1,11 +1,11 @@ -// xrRender_GL.cpp : Defines the entry point for the DLL application. -// #include "stdafx.h" #include "Layers/xrRender/dxRenderFactory.h" #include "Layers/xrRender/dxUIRender.h" #include "Layers/xrRender/dxDebugRender.h" -void SetupEnvRGL() +extern "C" +{ +XR_EXPORT void SetupEnv() { GEnv.Render = &RImplementation; GEnv.RenderFactory = &RenderFactoryImpl; @@ -17,25 +17,14 @@ void SetupEnvRGL() xrRender_initconsole(); } -bool SupportsOpenGLRendering() +XR_EXPORT pcstr GetModeName() { - // XXX: do a real check - return true; + return "renderer_gl"; } -// This must not be optimized by compiler -static const volatile class GEnvHelper +XR_EXPORT bool CheckRendererSupport() { -public: - GEnvHelper() - { - GEnv.CheckRGL = SupportsOpenGLRendering; - GEnv.SetupRGL = SetupEnvRGL; - } - - ~GEnvHelper() - { - GEnv.SetupRGL = nullptr; - GEnv.SetupRGL = nullptr; - } -} helper; + // XXX: do a real check + return true; +} +} diff --git a/src/Layers/xrRenderPC_R1/xrRender_R1.cpp b/src/Layers/xrRenderPC_R1/xrRender_R1.cpp index be6f0ed3269..fd56e55aa46 100644 --- a/src/Layers/xrRenderPC_R1/xrRender_R1.cpp +++ b/src/Layers/xrRenderPC_R1/xrRender_R1.cpp @@ -3,7 +3,9 @@ #include "Layers/xrRender/dxUIRender.h" #include "Layers/xrRender/dxDebugRender.h" -void SetupEnvR1() +extern "C" +{ +XR_EXPORT void SetupEnv() { GEnv.Render = &RImplementation; GEnv.RenderFactory = &RenderFactoryImpl; @@ -15,16 +17,17 @@ void SetupEnvR1() xrRender_initconsole(); } -// This must not be optimized by compiler -static const volatile class GEnvHelper +XR_EXPORT pcstr GetModeName() +{ + return "renderer_r1"; +} + +XR_EXPORT bool CheckRendererSupport() { -public: - GEnvHelper() - { - GEnv.SetupR1 = SetupEnvR1; - } - ~GEnvHelper() - { - GEnv.SetupR1 = nullptr; - } -} helper; + CHW _HW; + _HW.CreateD3D(); + if (_HW.pD3D) + return true; + return false; +} +} diff --git a/src/Layers/xrRenderPC_R2/xrRender_R2.cpp b/src/Layers/xrRenderPC_R2/xrRender_R2.cpp index 9e3d8e95b34..cb9e1c2e323 100644 --- a/src/Layers/xrRenderPC_R2/xrRender_R2.cpp +++ b/src/Layers/xrRenderPC_R2/xrRender_R2.cpp @@ -3,7 +3,9 @@ #include "Layers/xrRender/dxUIRender.h" #include "Layers/xrRender/dxDebugRender.h" -void SetupEnvR2() +extern "C" +{ +XR_EXPORT void SetupEnv() { GEnv.Render = &RImplementation; GEnv.RenderFactory = &RenderFactoryImpl; @@ -15,7 +17,12 @@ void SetupEnvR2() xrRender_initconsole(); } -bool SupportsAdvancedRendering() +XR_EXPORT pcstr GetModeName() +{ + return "renderer_r2"; +} + +XR_EXPORT bool CheckRendererSupport() { D3DCAPS9 caps; CHW _HW; @@ -26,22 +33,7 @@ bool SupportsAdvancedRendering() if (ps_ver_major < 3) return false; - else - return true; -} -// This must not be optimized by compiler -static const volatile class GEnvHelper -{ -public: - GEnvHelper() - { - GEnv.CheckR2 = SupportsAdvancedRendering; - GEnv.SetupR2 = SetupEnvR2; - } - ~GEnvHelper() - { - GEnv.CheckR2 = nullptr; - GEnv.SetupR2 = nullptr; - } -} helper; + return true; +} +} diff --git a/src/Layers/xrRenderPC_R3/xrRender_R3.cpp b/src/Layers/xrRenderPC_R3/xrRender_R3.cpp index b129f5b4c96..e82ef53259e 100644 --- a/src/Layers/xrRenderPC_R3/xrRender_R3.cpp +++ b/src/Layers/xrRenderPC_R3/xrRender_R3.cpp @@ -3,7 +3,9 @@ #include "Layers/xrRender/dxUIRender.h" #include "Layers/xrRender/dxDebugRender.h" -void SetupEnvR3() +extern "C" +{ +XR_EXPORT void SetupEnv() { GEnv.Render = &RImplementation; GEnv.RenderFactory = &RenderFactoryImpl; @@ -15,36 +17,13 @@ void SetupEnvR3() xrRender_initconsole(); } -bool SupportsDX10Rendering() +XR_EXPORT pcstr GetModeName() { - return xrRender_test_hw() ? true : false; - /* - D3DCAPS9 caps; - CHW _HW; - _HW.CreateD3D (); - _HW.pD3D->GetDeviceCaps (D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,&caps); - _HW.DestroyD3D (); - u16 ps_ver_major = u16 ( u32(u32(caps.PixelShaderVersion)&u32(0xf << 8ul))>>8 ); - - if (ps_ver_major<3) - return false; - else - return true; - */ + return "renderer_r3"; } -// This must not be optimized by compiler -static const volatile class GEnvHelper +XR_EXPORT bool CheckRendererSupport() { -public: - GEnvHelper() - { - GEnv.CheckR3 = SupportsDX10Rendering; - GEnv.SetupR3 = SetupEnvR3; - } - ~GEnvHelper() - { - GEnv.CheckR3 = nullptr; - GEnv.SetupR3 = nullptr; - } -} helper; + return xrRender_test_hw() ? true : false; +} +} diff --git a/src/Layers/xrRenderPC_R4/xrRender_R4.cpp b/src/Layers/xrRenderPC_R4/xrRender_R4.cpp index 37514429cd6..623267385b5 100644 --- a/src/Layers/xrRenderPC_R4/xrRender_R4.cpp +++ b/src/Layers/xrRenderPC_R4/xrRender_R4.cpp @@ -2,9 +2,10 @@ #include "Layers/xrRender/dxRenderFactory.h" #include "Layers/xrRender/dxUIRender.h" #include "Layers/xrRender/dxDebugRender.h" -#include "Include/xrAPI/xrAPI.h" -void SetupEnvR4() +extern "C" +{ +XR_EXPORT void SetupEnv() { GEnv.Render = &RImplementation; GEnv.RenderFactory = &RenderFactoryImpl; @@ -16,36 +17,13 @@ void SetupEnvR4() xrRender_initconsole(); } -bool SupportsDX11Rendering() +XR_EXPORT pcstr GetModeName() { - return xrRender_test_hw() ? true : false; - /* - D3DCAPS9 caps; - CHW _HW; - _HW.CreateD3D (); - _HW.pD3D->GetDeviceCaps (D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,&caps); - _HW.DestroyD3D (); - u16 ps_ver_major = u16 ( u32(u32(caps.PixelShaderVersion)&u32(0xf << 8ul))>>8 ); - - if (ps_ver_major<3) - return false; - else - return true; - */ + return "renderer_r4"; } -// This must not be optimized by compiler -static const volatile class GEnvHelper +XR_EXPORT bool CheckRendererSupport() { -public: - GEnvHelper() - { - GEnv.CheckR4 = SupportsDX11Rendering; - GEnv.SetupR4 = SetupEnvR4; - } - ~GEnvHelper() - { - GEnv.CheckR4 = nullptr; - GEnv.SetupR4 = nullptr; - } -} helper; + return xrRender_test_hw() ? true : false; +} +} diff --git a/src/xrEngine/EngineAPI.cpp b/src/xrEngine/EngineAPI.cpp index 5c05f750db6..4ce3ff95bbb 100644 --- a/src/xrEngine/EngineAPI.cpp +++ b/src/xrEngine/EngineAPI.cpp @@ -12,6 +12,24 @@ extern void FillMonitorsToken(); extern xr_vector VidQualityToken; +constexpr pcstr check_function = "CheckRendererSupport"; +constexpr pcstr setup_function = "SetupEnv"; +constexpr pcstr mode_function = "GetModeName"; + +constexpr pcstr r1_library = "xrRender_R1"; +constexpr pcstr r2_library = "xrRender_R2"; +constexpr pcstr r3_library = "xrRender_R3"; +constexpr pcstr r4_library = "xrRender_R4"; +constexpr pcstr gl_library = "xrRender_GL"; + +constexpr pcstr renderer_r1 = "renderer_r1"; +constexpr pcstr renderer_r2a = "renderer_r2a"; +constexpr pcstr renderer_r2 = "renderer_r2"; +constexpr pcstr renderer_r2_5 = "renderer_r2.5"; +constexpr pcstr renderer_r3 = "renderer_r3"; +constexpr pcstr renderer_r4 = "renderer_r4"; +constexpr pcstr renderer_gl = "renderer_gl"; + ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// @@ -22,11 +40,6 @@ CEngineAPI::CEngineAPI() { hGame = nullptr; hTuner = nullptr; - hRenderR1 = nullptr; - hRenderR2 = nullptr; - hRenderR3 = nullptr; - hRenderR4 = nullptr; - hRenderRGL = nullptr; pCreate = nullptr; pDestroy = nullptr; tune_enabled = false; @@ -46,122 +59,81 @@ bool is_enough_address_space_available() GetSystemInfo(&system_info); return (*(u32*)&system_info.lpMaximumApplicationAddress) > 0x90000000; #else - return TRUE; // In linux allocated memory limited only by pointer size + return true; // In Linux allocated memory limited only by pointer size #endif } -void CEngineAPI::SetupCurrentRenderer() +void CEngineAPI::SelectRenderer() { GEnv.CurrentRenderer = -1; - if (psDeviceFlags.test(rsRGL)) + const auto select = [&](pcstr library, u32 selected, int index, u32 fallback = 0) { - if (hRenderRGL->IsLoaded()) - { - GEnv.CurrentRenderer = 5; - GEnv.SetupCurrentRenderer = GEnv.SetupRGL; - } - else - { - psDeviceFlags.set(rsRGL, false); - psDeviceFlags.set(rsR4, true); - } - } - -#if defined(WINDOWS) - if (psDeviceFlags.test(rsR4)) - { - if (hRenderR4->IsLoaded()) - { - GEnv.CurrentRenderer = 4; - GEnv.SetupCurrentRenderer = GEnv.SetupR4; - } - else + if (psDeviceFlags.test(selected)) { - psDeviceFlags.set(rsR4, false); - psDeviceFlags.set(rsR3, true); + if (renderers[library]->IsLoaded()) + { + GEnv.CurrentRenderer = index; + setupSelectedRenderer = setupFunctions[library]; + } + else // Selected is unavailable + { + psDeviceFlags.set(selected, false); + if (fallback > 0) // try to use another + psDeviceFlags.set(fallback, true); + } } - } + }; - if (psDeviceFlags.test(rsR3)) - { - if (hRenderR3->IsLoaded()) - { - GEnv.CurrentRenderer = 3; - GEnv.SetupCurrentRenderer = GEnv.SetupR3; - } - else - { - psDeviceFlags.set(rsR3, false); - psDeviceFlags.set(rsR2, true); - } - } + select(gl_library, rsRGL, 5, rsR4); - if (psDeviceFlags.test(rsR2)) - { - if (hRenderR2->IsLoaded()) - { - GEnv.CurrentRenderer = 2; - GEnv.SetupCurrentRenderer = GEnv.SetupR2; - } - else - { - psDeviceFlags.set(rsR2, false); - psDeviceFlags.set(rsR1, true); - } - } +#if defined(WINDOWS) + select(r4_library, rsR4, 4, rsR3); + select(r3_library, rsR3, 3, rsR2); + select(r2_library, rsR2, 2, rsR4); #endif - if (psDeviceFlags.test(rsR1)) - { - if (hRenderR1->IsLoaded()) - { - GEnv.CurrentRenderer = 1; - GEnv.SetupCurrentRenderer = GEnv.SetupR1; - } - else - psDeviceFlags.set(rsR1, false); - } + select(r1_library, rsR1, 1); } void CEngineAPI::InitializeRenderers() { - SetupCurrentRenderer(); + SelectRenderer(); - if (GEnv.SetupCurrentRenderer == nullptr + if (setupSelectedRenderer == nullptr && VidQualityToken[0].id != -1) { // if engine failed to load renderer // but there is at least one available // then try again - string32 buf; + string64 buf; xr_sprintf(buf, "renderer %s", VidQualityToken[0].name); Console->Execute(buf); // Second attempt - SetupCurrentRenderer(); + SelectRenderer(); } - // ask current renderer to setup GlobalEnv - R_ASSERT2(GEnv.SetupCurrentRenderer, "Can't setup renderer"); - GEnv.SetupCurrentRenderer(); + // Ask current renderer to setup GEnv + R_ASSERT2(setupSelectedRenderer, "Can't setup renderer"); + setupSelectedRenderer(); // Now unload unused renderers // XXX: Unloading disabled due to typeids invalidation /*if (GEnv.CurrentRenderer != 5) - hRenderRGL->close(); + renderers[gl_library]->close(); if (GEnv.CurrentRenderer != 4) - hRenderR4->close(); + renderers[r4_library]->close(); if (GEnv.CurrentRenderer != 3) - hRenderR3->close(); + renderers[r3_library]->close(); if (GEnv.CurrentRenderer != 2) - hRenderR2->close(); + renderers[r2_library]->close(); if (GEnv.CurrentRenderer != 1) - hRenderR1->close();*/ + renderers[r1_library]->close();*/ FillMonitorsToken(); } @@ -204,13 +176,11 @@ void CEngineAPI::Destroy(void) { hGame = nullptr; hTuner = nullptr; - hRenderR1 = nullptr; - hRenderR2 = nullptr; - hRenderR3 = nullptr; - hRenderR4 = nullptr; - hRenderRGL = nullptr; pCreate = nullptr; pDestroy = nullptr; + checkFunctions.clear(); + setupFunctions.clear(); + renderers.clear(); Engine.Event._destroy(); XRC.r_clear_compact(); } @@ -220,19 +190,19 @@ void CEngineAPI::CreateRendererList() if (!VidQualityToken.empty()) return; - hRenderRGL = XRay::LoadModule("xrRender_GL"); + renderers[gl_library] = XRay::LoadModule(gl_library); #if defined(WINDOWS) - hRenderR1 = XRay::LoadModule("xrRender_R1"); + renderers[r1_library] = XRay::LoadModule(r1_library); #endif if (GEnv.isDedicatedServer) { #if defined(WINDOWS) - R_ASSERT2(hRenderR1->IsLoaded(), "Dedicated server needs xrRender_R1 to work"); - VidQualityToken.emplace_back("renderer_r1", 0); + R_ASSERT2(renderers[r1_library]->IsLoaded(), "Dedicated server needs xrRender_R1 to work"); + VidQualityToken.emplace_back(renderer_r1, 0); #elif defined(LINUX) - R_ASSERT2(hRenderRGL->IsLoaded(), "Dedicated server needs xrRender_GL to work"); - VidQualityToken.emplace_back("renderer_gl", 0); + R_ASSERT2(renderers[gl_library]->IsLoaded(), "Dedicated server needs xrRender_GL to work"); + VidQualityToken.emplace_back(renderer_gl, 0); #endif VidQualityToken.emplace_back(nullptr, -1); return; @@ -244,51 +214,45 @@ void CEngineAPI::CreateRendererList() // Hide "d3d10.dll not found" message box for XP SetErrorMode(SEM_FAILCRITICALERRORS); - hRenderR2 = XRay::LoadModule("xrRender_R2"); - hRenderR3 = XRay::LoadModule("xrRender_R3"); - hRenderR4 = XRay::LoadModule("xrRender_R4"); + renderers[r2_library] = XRay::LoadModule(r2_library); + renderers[r3_library] = XRay::LoadModule(r3_library); + renderers[r4_library] = XRay::LoadModule(r4_library); // Restore error handling SetErrorMode(0); +#endif - if (hRenderR1->IsLoaded()) - { - modes.emplace_back("renderer_r1", 0); - } - - - if (hRenderR2->IsLoaded()) - { - modes.emplace_back("renderer_r2a", 1); - modes.emplace_back("renderer_r2", 2); - if (GEnv.CheckR2 && GEnv.CheckR2()) - modes.emplace_back("renderer_r2.5", 3); - } - - if (hRenderR3->IsLoaded()) + const auto checkRenderer = [&](pcstr library, pcstr mode, int index) { - if (GEnv.CheckR3 && GEnv.CheckR3()) - modes.emplace_back("renderer_r3", 4); - else - hRenderR3->Close(); - } + if (renderers[library]->IsLoaded()) + { + // Load SupportCheck, SetupEnv and GetModeName functions from DLL + checkFunctions[library] = (SupportCheck)renderers[library]->GetProcAddress(check_function); + setupFunctions[library] = (SetupEnv)renderers[library]->GetProcAddress(setup_function); + const auto getModeName = (GetModeName)renderers[library]->GetProcAddress(mode_function); + + // Test availability + if (checkFunctions[library] && checkFunctions[library]()) + modes.emplace_back(getModeName ? getModeName() : mode, index); + else // Close the handle if test is failed + renderers[library]->Close(); + } + }; - if (hRenderR4->IsLoaded()) +#if defined(WINDOWS) + checkRenderer(r1_library, renderer_r1, 0); + if (renderers[r2_library]->IsLoaded()) { - if (GEnv.CheckR4 && GEnv.CheckR4()) - modes.emplace_back("renderer_r4", 5); - else - hRenderR4->Close(); + modes.emplace_back(renderer_r2a, 1); + modes.emplace_back(renderer_r2, 2); } + checkRenderer(r2_library, renderer_r2_5, 3); + checkRenderer(r3_library, renderer_r3, 4); + checkRenderer(r4_library, renderer_r4, 5); #endif - if (hRenderRGL->IsLoaded()) - { - if (GEnv.CheckRGL && GEnv.CheckRGL()) - modes.emplace_back("renderer_gl", 6); - else - hRenderRGL->Close(); - } + checkRenderer(gl_library, renderer_gl, 6); + modes.emplace_back(nullptr, -1); Msg("Available render modes[%d]:", modes.size()); diff --git a/src/xrEngine/EngineAPI.h b/src/xrEngine/EngineAPI.h index e8e2b421072..d6171528a34 100644 --- a/src/xrEngine/EngineAPI.h +++ b/src/xrEngine/EngineAPI.h @@ -41,31 +41,38 @@ using Factory_Destroy = DLL_API void __cdecl(IFactoryObject* O); // Tuning interface extern "C" { -using VTPause = void __cdecl(void); -using VTResume = void __cdecl(void); +using VTPause = void __cdecl(); +using VTResume = void __cdecl(); }; class ENGINE_API CEngineAPI { + using SupportCheck = bool(*)(); + using SetupEnv = void(*)(); + using GetModeName = pcstr(*)(); + XRay::Module hGame; XRay::Module hTuner; - XRay::Module hRenderR1; - XRay::Module hRenderR2; - XRay::Module hRenderR3; - XRay::Module hRenderR4; - XRay::Module hRenderRGL; + xr_map renderers; + xr_map checkFunctions; + xr_map setupFunctions; + + SetupEnv setupSelectedRenderer; public: BENCH_SEC_SCRAMBLEMEMBER1 - Factory_Create* pCreate; + + Factory_Create* pCreate; Factory_Destroy* pDestroy; - bool tune_enabled; - VTPause* tune_pause; + + bool tune_enabled; + VTPause* tune_pause; VTResume* tune_resume; + void Initialize(); void InitializeRenderers(); - void SetupCurrentRenderer(); + void SelectRenderer(); void Destroy();