From 7bd9216a6f470bc35bdeaaeab3830e942928f9cf Mon Sep 17 00:00:00 2001 From: kaetemi Date: Thu, 7 Aug 2014 01:04:58 +0200 Subject: [PATCH] Specify monitor when changing display mode --- code/nel/include/nel/3d/driver.h | 3 +- code/nel/include/nel/3d/stereo_debugger.h | 5 + code/nel/include/nel/3d/stereo_display.h | 5 + code/nel/include/nel/3d/stereo_ovr_04.h | 11 +++ code/nel/include/nel/3d/u_driver.h | 4 +- code/nel/src/3d/driver.cpp | 3 +- .../3d/driver/opengl/driver_opengl_window.cpp | 93 +++++++++++++++++-- code/nel/src/3d/driver_user.cpp | 6 +- code/nel/src/3d/scene.cpp | 7 +- code/nel/src/3d/stereo_debugger.cpp | 14 ++- code/nel/src/3d/stereo_ovr_04.cpp | 43 ++++++++- code/ryzom/client/src/connection.cpp | 7 ++ code/ryzom/client/src/main_loop_utilities.cpp | 10 +- 13 files changed, 187 insertions(+), 24 deletions(-) diff --git a/code/nel/include/nel/3d/driver.h b/code/nel/include/nel/3d/driver.h index f19428cfb..8738a7dda 100644 --- a/code/nel/include/nel/3d/driver.h +++ b/code/nel/include/nel/3d/driver.h @@ -72,6 +72,7 @@ struct IOcclusionQuery; /// A Graphic Mode descriptor. struct GfxMode { + std::string DisplayDevice; bool OffScreen; bool Windowed; uint16 Width; @@ -90,7 +91,7 @@ struct GfxMode Frequency = 0; AntiAlias = -1; } - GfxMode(uint16 w, uint16 h, uint8 d, bool windowed = true, bool offscreen = false, uint frequency = 0, sint8 aa = -1); + GfxMode(uint16 w, uint16 h, uint8 d, bool windowed = true, bool offscreen = false, uint frequency = 0, sint8 aa = -1, const std::string &displayDevice = std::string()); }; // **************************************************************************** diff --git a/code/nel/include/nel/3d/stereo_debugger.h b/code/nel/include/nel/3d/stereo_debugger.h index cd66a4fdc..81432d672 100644 --- a/code/nel/include/nel/3d/stereo_debugger.h +++ b/code/nel/include/nel/3d/stereo_debugger.h @@ -72,6 +72,11 @@ public: void getTextures(); void recycleTextures(); + /// Attach the driver to the display + virtual void attachToDisplay(); + /// Detach the driver from the display + virtual void detachFromDisplay(); + /// Gets the required screen resolution for this device virtual bool getScreenResolution(uint &width, uint &height); /// Set latest camera position etcetera diff --git a/code/nel/include/nel/3d/stereo_display.h b/code/nel/include/nel/3d/stereo_display.h index 52ec37354..2e37f0663 100644 --- a/code/nel/include/nel/3d/stereo_display.h +++ b/code/nel/include/nel/3d/stereo_display.h @@ -94,6 +94,11 @@ public: /// Sets driver and generates necessary render targets virtual void setDriver(NL3D::UDriver *driver) = 0; + + /// Attach the driver to the display + virtual void attachToDisplay() = 0; + /// Detach the driver from the display + virtual void detachFromDisplay() = 0; /// Gets the required screen resolution for this device virtual bool getScreenResolution(uint &width, uint &height) = 0; diff --git a/code/nel/include/nel/3d/stereo_ovr_04.h b/code/nel/include/nel/3d/stereo_ovr_04.h index 7523819a5..f87ba2754 100644 --- a/code/nel/include/nel/3d/stereo_ovr_04.h +++ b/code/nel/include/nel/3d/stereo_ovr_04.h @@ -59,6 +59,7 @@ #include #include #include +#include #include #include @@ -89,6 +90,11 @@ public: /// Sets driver and generates necessary render targets virtual void setDriver(NL3D::UDriver *driver); + /// Attach the driver to the display + virtual void attachToDisplay(); + /// Detach the driver from the display + virtual void detachFromDisplay(); + /// Gets the required screen resolution for this device virtual bool getScreenResolution(uint &width, uint &height); /// Set latest camera position etcetera @@ -194,6 +200,11 @@ private: UMaterial m_UnlitMat; + UDriver::CMode m_OriginalMode; + sint32 m_OriginalWinPosX; + sint32 m_OriginalWinPosY; + bool m_AttachedDisplay; + /* NL3D::UMaterial m_BarrelMat; NLMISC::CQuadUV m_BarrelQuadLeft; diff --git a/code/nel/include/nel/3d/u_driver.h b/code/nel/include/nel/3d/u_driver.h index a64e13dd6..dc2b02e56 100644 --- a/code/nel/include/nel/3d/u_driver.h +++ b/code/nel/include/nel/3d/u_driver.h @@ -92,6 +92,7 @@ public: /// A Graphic Mode descriptor. struct CMode { + std::string DisplayDevice; bool Windowed; uint16 Width; uint16 Height; @@ -108,8 +109,9 @@ public: Frequency = 0; AntiAlias = -1; } - CMode(uint16 w, uint16 h, uint8 d, bool windowed= true, uint frequency = 0, sint8 aa = -1) + CMode(uint16 w, uint16 h, uint8 d, bool windowed= true, uint frequency = 0, sint8 aa = -1, const std::string &displayDevice = std::string()) { + DisplayDevice = displayDevice; Windowed = windowed; Width = w; Height = h; diff --git a/code/nel/src/3d/driver.cpp b/code/nel/src/3d/driver.cpp index 134c24410..791172700 100644 --- a/code/nel/src/3d/driver.cpp +++ b/code/nel/src/3d/driver.cpp @@ -123,8 +123,9 @@ bool IDriver::release(void) // *************************************************************************** -GfxMode::GfxMode(uint16 w, uint16 h, uint8 d, bool windowed, bool offscreen, uint frequency, sint8 aa) +GfxMode::GfxMode(uint16 w, uint16 h, uint8 d, bool windowed, bool offscreen, uint frequency, sint8 aa, const std::string &displayDevice) { + DisplayDevice = displayDevice; Windowed = windowed; Width = w; Height = h; diff --git a/code/nel/src/3d/driver/opengl/driver_opengl_window.cpp b/code/nel/src/3d/driver/opengl/driver_opengl_window.cpp index 03796206c..cb93a900c 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl_window.cpp +++ b/code/nel/src/3d/driver/opengl/driver_opengl_window.cpp @@ -1271,10 +1271,62 @@ static sint modeInfoToFrequency(XF86VidModeModeInfo *info) // *************************************************************************** +#if defined(NL_OS_WINDOWS) + +struct CMonitorEnumParams +{ +public: + HWND Window; + const char *deviceName; +}; + +static BOOL CALLBACK monitorEnumProcFullscreen(HMONITOR hMonitor, HDC, LPRECT, LPARAM dwData) +{ + CMonitorEnumParams *p = reinterpret_cast(dwData); + + MONITORINFOEXA monitorInfo; + memset(&monitorInfo, 0, sizeof(monitorInfo)); + monitorInfo.cbSize = sizeof(monitorInfo); + GetMonitorInfoA(hMonitor, &monitorInfo); + nldebug("3D: Monitor: '%s'", monitorInfo.szDevice); + + size_t devLen = strlen(monitorInfo.szDevice); + size_t targetLen = strlen(p->deviceName); + + nlassert(devLen < 32); + size_t minLen = min(devLen, targetLen); + if (!memcmp(monitorInfo.szDevice, p->deviceName, minLen)) + { + if (devLen == targetLen + || (devLen < targetLen && (p->deviceName[minLen] == '\\')) + || (devLen > targetLen && (monitorInfo.szDevice[minLen] == '\\'))) + { + nldebug("3D: Remap '%s' to '%s'", p->deviceName, monitorInfo.szDevice); + nldebug("Found our monitor at %i, %i", monitorInfo.rcMonitor.left, monitorInfo.rcMonitor.top); + LONG dwStyle = GetWindowLong(p->Window, GWL_STYLE); + SetWindowLong(p->Window, GWL_STYLE, dwStyle & ~WS_OVERLAPPEDWINDOW); + SetWindowPos(p->Window, NULL, + monitorInfo.rcMonitor.left, + monitorInfo.rcMonitor.top, + monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left, + monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top, + SWP_FRAMECHANGED); + return FALSE; + } + } + return TRUE; // continue +}; + +#endif + +// *************************************************************************** + bool CDriverGL::setScreenMode(const GfxMode &mode) { H_AUTO_OGL(CDriverGL_setScreenMode) + nldebug("3D: setScreenMode"); + if (mode.Windowed) { // if fullscreen, switch back to desktop screen mode @@ -1284,13 +1336,16 @@ bool CDriverGL::setScreenMode(const GfxMode &mode) return true; } + if (!mode.DisplayDevice.empty()) + restoreScreenMode(); + // save previous screen mode only if switching from windowed to fullscreen if (_CurrentMode.Windowed) saveScreenMode(); // if switching exactly to the same screen mode, doesn't change it GfxMode previousMode; - if (getCurrentScreenMode(previousMode) + if (mode.DisplayDevice.empty() && getCurrentScreenMode(previousMode) && mode.Width == previousMode.Width && mode.Height == previousMode.Height && mode.Depth == previousMode.Depth @@ -1299,7 +1354,9 @@ bool CDriverGL::setScreenMode(const GfxMode &mode) #if defined(NL_OS_WINDOWS) - DEVMODE devMode; + const char *deviceName = mode.DisplayDevice.c_str(); + + DEVMODEA devMode; memset(&devMode, 0, sizeof(DEVMODE)); devMode.dmSize = sizeof(DEVMODE); devMode.dmDriverExtra = 0; @@ -1307,22 +1364,42 @@ bool CDriverGL::setScreenMode(const GfxMode &mode) devMode.dmPelsWidth = mode.Width; devMode.dmPelsHeight = mode.Height; - if(mode.Depth > 0) + if (mode.Depth > 0) { devMode.dmBitsPerPel = mode.Depth; devMode.dmFields |= DM_BITSPERPEL; } - if(mode.Frequency > 0) + if (mode.Frequency > 0) { devMode.dmDisplayFrequency = mode.Frequency; devMode.dmFields |= DM_DISPLAYFREQUENCY; } - - if (ChangeDisplaySettings(&devMode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) + + if (deviceName[0]) { - nlwarning("3D: Fullscreen mode switch failed"); - return false; + // First attempt exclusive fullscreen + nldebug("3D: ChangeDisplaySettingsEx"); + LONG resex; + if ((resex = ChangeDisplaySettingsExA(deviceName, &devMode, NULL, CDS_FULLSCREEN, NULL)) != DISP_CHANGE_SUCCESSFUL) + { + nlwarning("3D: Fullscreen mode switch failed (%i)", (sint)resex); + // Workaround, resize to monitor and make borderless + CMonitorEnumParams p; + p.deviceName = deviceName; + p.Window = _win; + EnumDisplayMonitors(NULL, NULL, monitorEnumProcFullscreen, (LPARAM)&p); + return false; // FIXME: This is a hack, don't process further + } + } + else + { + nldebug("3D: ChangeDisplaySettings"); + if (ChangeDisplaySettingsA(&devMode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) + { + nlwarning("3D: Fullscreen mode switch failed"); + return false; + } } #elif defined(NL_OS_MAC) diff --git a/code/nel/src/3d/driver_user.cpp b/code/nel/src/3d/driver_user.cpp index 403b5859c..c4dc97655 100644 --- a/code/nel/src/3d/driver_user.cpp +++ b/code/nel/src/3d/driver_user.cpp @@ -249,7 +249,7 @@ bool CDriverUser::setDisplay(nlWindow wnd, const CMode &mode, bool show, bool NL3D_HAUTO_UI_DRIVER; // window init. - if (_Driver->setDisplay(wnd, GfxMode(mode.Width, mode.Height, mode.Depth, mode.Windowed, false, mode.Frequency, mode.AntiAlias), show, resizeable)) + if (_Driver->setDisplay(wnd, GfxMode(mode.Width, mode.Height, mode.Depth, mode.Windowed, false, mode.Frequency, mode.AntiAlias, mode.DisplayDevice), show, resizeable)) { // Always true nlverify (activate()); @@ -293,7 +293,7 @@ bool CDriverUser::setDisplay(nlWindow wnd, const CMode &mode, bool show, bool // *************************************************************************** bool CDriverUser::setMode(const CMode& mode) { - return _Driver->setMode(GfxMode(mode.Width, mode.Height, mode.Depth, mode.Windowed, false, mode.Frequency, mode.AntiAlias)); + return _Driver->setMode(GfxMode(mode.Width, mode.Height, mode.Depth, mode.Windowed, false, mode.Frequency, mode.AntiAlias, mode.DisplayDevice)); } // ---------------------------------------------------------------------------- @@ -319,7 +319,7 @@ bool CDriverUser::getModes(std::vector &modes) bool res = _Driver->getModes(vTmp); modes.clear(); for (uint i = 0; i < vTmp.size(); ++i) - modes.push_back(CMode(vTmp[i].Width, vTmp[i].Height, vTmp[i].Depth, vTmp[i].Windowed, vTmp[i].Frequency, vTmp[i].AntiAlias)); + modes.push_back(CMode(vTmp[i].Width, vTmp[i].Height, vTmp[i].Depth, vTmp[i].Windowed, vTmp[i].Frequency, vTmp[i].AntiAlias, vTmp[i].DisplayDevice)); std::sort(modes.begin(), modes.end(), CModeSorter()); diff --git a/code/nel/src/3d/scene.cpp b/code/nel/src/3d/scene.cpp index b58ad046c..67465eb8c 100644 --- a/code/nel/src/3d/scene.cpp +++ b/code/nel/src/3d/scene.cpp @@ -629,11 +629,8 @@ void CScene::renderPart(UScene::TRenderPart rp, bool doHrcPass, bool doTrav, boo // clip ClipTrav.traverse(); - if (doTrav) - { - // animDetail - AnimDetailTrav.traverse(); - } + // animDetail + AnimDetailTrav.traverse(); // loadBalance LoadBalancingTrav.traverse(); diff --git a/code/nel/src/3d/stereo_debugger.cpp b/code/nel/src/3d/stereo_debugger.cpp index f8067d99d..940ada508 100644 --- a/code/nel/src/3d/stereo_debugger.cpp +++ b/code/nel/src/3d/stereo_debugger.cpp @@ -211,6 +211,16 @@ void CStereoDebugger::setDriver(NL3D::UDriver *driver) } } +void CStereoDebugger::attachToDisplay() +{ + +} + +void CStereoDebugger::detachFromDisplay() +{ + +} + void CStereoDebugger::getTextures() { nlassert(!m_LeftTexU); @@ -437,12 +447,12 @@ bool CStereoDebugger::wantInterface2D() bool CStereoDebugger::isSceneFirst() { - return m_Stage == 1; + return m_Stage != 3; } bool CStereoDebugger::isSceneLast() { - return m_Stage == 2; + return m_Stage != 3; } /// Returns true if a new render target was set, always fase if not using render targets diff --git a/code/nel/src/3d/stereo_ovr_04.cpp b/code/nel/src/3d/stereo_ovr_04.cpp index 0f1f0738e..0fd4b9ba2 100644 --- a/code/nel/src/3d/stereo_ovr_04.cpp +++ b/code/nel/src/3d/stereo_ovr_04.cpp @@ -165,7 +165,7 @@ static float lerp(float f0, float f1, float factor) return (f1 * factor) + (f0 * (1.0f - factor)); } -CStereoOVR::CStereoOVR(const CStereoOVRDeviceFactory *factory) : m_DevicePtr(NULL), m_Stage(0), m_SubStage(0), m_OrientationCached(false), m_Driver(NULL), m_SceneTexture(NULL), m_GUITexture(NULL), m_EyePosition(0.0f, 0.09f, 0.15f), m_Scale(1.0f) +CStereoOVR::CStereoOVR(const CStereoOVRDeviceFactory *factory) : m_DevicePtr(NULL), m_Stage(0), m_SubStage(0), m_OrientationCached(false), m_Driver(NULL), m_SceneTexture(NULL), m_GUITexture(NULL), m_EyePosition(0.0f, 0.09f, 0.15f), m_Scale(1.0f), m_AttachedDisplay(false) { nlctassert(NL_OVR_EYE_COUNT == ovrEye_Count); @@ -371,6 +371,11 @@ CStereoOVR::CStereoOVR(const CStereoOVRDeviceFactory *factory) : m_DevicePtr(NUL CStereoOVR::~CStereoOVR() { + if (m_AttachedDisplay) + { + detachFromDisplay(); + } + if (!m_UnlitMat.empty()) { m_Driver->deleteMaterial(m_UnlitMat); @@ -439,6 +444,38 @@ bool CStereoOVR::getScreenResolution(uint &width, uint &height) return false; } +void CStereoOVR::attachToDisplay() +{ + nldebug("OVR: Attach to display '%s'", m_DevicePtr->DisplayDeviceName); + + if (!m_AttachedDisplay) + { + m_Driver->getCurrentScreenMode(m_OriginalMode); + m_Driver->getWindowPos(m_OriginalWinPosX, m_OriginalWinPosY); + } + + UDriver::CMode mode; + mode.DisplayDevice = m_DevicePtr->DisplayDeviceName; + mode.Windowed = false; + mode.Width = m_DevicePtr->Resolution.w; + mode.Height = m_DevicePtr->Resolution.h; + m_Driver->setMode(mode); + m_AttachedDisplay = true; +} + +void CStereoOVR::detachFromDisplay() +{ + if (!m_OriginalMode.Windowed) + { + m_OriginalMode.Windowed = true; + m_Driver->setMode(m_OriginalMode); + m_OriginalMode.Windowed = false; + } + m_Driver->setMode(m_OriginalMode); + m_Driver->setWindowPos(m_OriginalWinPosX, m_OriginalWinPosY); + m_AttachedDisplay = false; +} + void CStereoOVR::initCamera(uint cid, const NL3D::UCamera *camera) { m_OriginalFrustum[cid] = camera->getFrustum(); @@ -679,6 +716,8 @@ bool CStereoOVR::isSceneFirst() { case 3: return true; + case 4: + return false; } return m_Driver->getPolygonMode() != UDriver::Filled; } @@ -687,6 +726,8 @@ bool CStereoOVR::isSceneLast() { switch (m_Stage) { + case 3: + return false; case 4: return true; } diff --git a/code/ryzom/client/src/connection.cpp b/code/ryzom/client/src/connection.cpp index 9376b6059..58dbca399 100644 --- a/code/ryzom/client/src/connection.cpp +++ b/code/ryzom/client/src/connection.cpp @@ -31,6 +31,7 @@ // 3D Interface. #include "nel/3d/u_driver.h" #include "nel/3d/u_text_context.h" +#include // Game Share //#include "game_share/gd_time.h" // \todo GUIGUI : TO DELETE/CHANGE #include "game_share/gender.h" @@ -217,6 +218,9 @@ void connectionRestaureVideoMode () setVideoMode(mode); } + if (StereoDisplay) + StereoDisplay->attachToDisplay(); + // And setup hardware mouse if we have to InitMouseWithCursor (ClientCfg.HardwareCursor); SetMouseFreeLook (); @@ -253,6 +257,9 @@ void setOutGameFullScreen() // NB: don't setup fullscreen if player wants to play in window if (!ClientCfg.Local && ClientCfg.SelectCharacter == -1) { + if (StereoDisplay) + StereoDisplay->detachFromDisplay(); + UDriver::CMode currMode; Driver->getCurrentScreenMode(currMode); UDriver::CMode wantedMode; diff --git a/code/ryzom/client/src/main_loop_utilities.cpp b/code/ryzom/client/src/main_loop_utilities.cpp index 0fe52e53c..7db7cc0bb 100644 --- a/code/ryzom/client/src/main_loop_utilities.cpp +++ b/code/ryzom/client/src/main_loop_utilities.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include "game_share/scenario_entry_points.h" @@ -60,6 +61,8 @@ void updateFromClientCfg() nldebug("Apply VR device change"); releaseStereoDisplayDevice(); initStereoDisplayDevice(); + if (StereoDisplay) + StereoDisplay->attachToDisplay(); } // GRAPHICS - GENERAL @@ -70,8 +73,11 @@ void updateFromClientCfg() (ClientCfg.Depth != LastClientCfg.Depth) || (ClientCfg.Frequency != LastClientCfg.Frequency)) { - setVideoMode(UDriver::CMode(ClientCfg.Width, ClientCfg.Height, (uint8)ClientCfg.Depth, - ClientCfg.Windowed, ClientCfg.Frequency)); + if (!StereoDisplay) // TODO + { + setVideoMode(UDriver::CMode(ClientCfg.Width, ClientCfg.Height, (uint8)ClientCfg.Depth, + ClientCfg.Windowed, ClientCfg.Frequency)); + } } if (ClientCfg.DivideTextureSizeBy2 != LastClientCfg.DivideTextureSizeBy2)