Specify monitor when changing display mode

This commit is contained in:
kaetemi 2014-08-07 01:04:58 +02:00
parent 7db83ce7da
commit 7bd9216a6f
13 changed files with 187 additions and 24 deletions

View file

@ -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());
};
// ****************************************************************************

View file

@ -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

View file

@ -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;

View file

@ -59,6 +59,7 @@
#include <nel/3d/frustum.h>
#include <nel/3d/viewport.h>
#include <nel/3d/u_material.h>
#include <nel/3d/u_driver.h>
#include <nel/3d/index_buffer.h>
#include <nel/3d/vertex_buffer.h>
@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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<CMonitorEnumParams *>(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)

View file

@ -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<CMode> &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());

View file

@ -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();

View file

@ -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

View file

@ -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;
}

View file

@ -31,6 +31,7 @@
// 3D Interface.
#include "nel/3d/u_driver.h"
#include "nel/3d/u_text_context.h"
#include <nel/3d/stereo_display.h>
// 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;

View file

@ -20,6 +20,7 @@
#include <nel/3d/u_driver.h>
#include <nel/3d/u_cloud_scape.h>
#include <nel/3d/fxaa.h>
#include <nel/3d/stereo_display.h>
#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)