Specify monitor when changing display mode

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

View file

@ -72,6 +72,7 @@ struct IOcclusionQuery;
/// A Graphic Mode descriptor. /// A Graphic Mode descriptor.
struct GfxMode struct GfxMode
{ {
std::string DisplayDevice;
bool OffScreen; bool OffScreen;
bool Windowed; bool Windowed;
uint16 Width; uint16 Width;
@ -90,7 +91,7 @@ struct GfxMode
Frequency = 0; Frequency = 0;
AntiAlias = -1; 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 getTextures();
void recycleTextures(); 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 /// Gets the required screen resolution for this device
virtual bool getScreenResolution(uint &width, uint &height); virtual bool getScreenResolution(uint &width, uint &height);
/// Set latest camera position etcetera /// Set latest camera position etcetera

View file

@ -94,6 +94,11 @@ public:
/// Sets driver and generates necessary render targets /// Sets driver and generates necessary render targets
virtual void setDriver(NL3D::UDriver *driver) = 0; 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 /// Gets the required screen resolution for this device
virtual bool getScreenResolution(uint &width, uint &height) = 0; virtual bool getScreenResolution(uint &width, uint &height) = 0;

View file

@ -59,6 +59,7 @@
#include <nel/3d/frustum.h> #include <nel/3d/frustum.h>
#include <nel/3d/viewport.h> #include <nel/3d/viewport.h>
#include <nel/3d/u_material.h> #include <nel/3d/u_material.h>
#include <nel/3d/u_driver.h>
#include <nel/3d/index_buffer.h> #include <nel/3d/index_buffer.h>
#include <nel/3d/vertex_buffer.h> #include <nel/3d/vertex_buffer.h>
@ -89,6 +90,11 @@ public:
/// Sets driver and generates necessary render targets /// Sets driver and generates necessary render targets
virtual void setDriver(NL3D::UDriver *driver); 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 /// Gets the required screen resolution for this device
virtual bool getScreenResolution(uint &width, uint &height); virtual bool getScreenResolution(uint &width, uint &height);
/// Set latest camera position etcetera /// Set latest camera position etcetera
@ -194,6 +200,11 @@ private:
UMaterial m_UnlitMat; UMaterial m_UnlitMat;
UDriver::CMode m_OriginalMode;
sint32 m_OriginalWinPosX;
sint32 m_OriginalWinPosY;
bool m_AttachedDisplay;
/* /*
NL3D::UMaterial m_BarrelMat; NL3D::UMaterial m_BarrelMat;
NLMISC::CQuadUV m_BarrelQuadLeft; NLMISC::CQuadUV m_BarrelQuadLeft;

View file

@ -92,6 +92,7 @@ public:
/// A Graphic Mode descriptor. /// A Graphic Mode descriptor.
struct CMode struct CMode
{ {
std::string DisplayDevice;
bool Windowed; bool Windowed;
uint16 Width; uint16 Width;
uint16 Height; uint16 Height;
@ -108,8 +109,9 @@ public:
Frequency = 0; Frequency = 0;
AntiAlias = -1; 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; Windowed = windowed;
Width = w; Width = w;
Height = h; 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; Windowed = windowed;
Width = w; Width = w;
Height = h; 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) bool CDriverGL::setScreenMode(const GfxMode &mode)
{ {
H_AUTO_OGL(CDriverGL_setScreenMode) H_AUTO_OGL(CDriverGL_setScreenMode)
nldebug("3D: setScreenMode");
if (mode.Windowed) if (mode.Windowed)
{ {
// if fullscreen, switch back to desktop screen mode // if fullscreen, switch back to desktop screen mode
@ -1284,13 +1336,16 @@ bool CDriverGL::setScreenMode(const GfxMode &mode)
return true; return true;
} }
if (!mode.DisplayDevice.empty())
restoreScreenMode();
// save previous screen mode only if switching from windowed to fullscreen // save previous screen mode only if switching from windowed to fullscreen
if (_CurrentMode.Windowed) if (_CurrentMode.Windowed)
saveScreenMode(); saveScreenMode();
// if switching exactly to the same screen mode, doesn't change it // if switching exactly to the same screen mode, doesn't change it
GfxMode previousMode; GfxMode previousMode;
if (getCurrentScreenMode(previousMode) if (mode.DisplayDevice.empty() && getCurrentScreenMode(previousMode)
&& mode.Width == previousMode.Width && mode.Width == previousMode.Width
&& mode.Height == previousMode.Height && mode.Height == previousMode.Height
&& mode.Depth == previousMode.Depth && mode.Depth == previousMode.Depth
@ -1299,7 +1354,9 @@ bool CDriverGL::setScreenMode(const GfxMode &mode)
#if defined(NL_OS_WINDOWS) #if defined(NL_OS_WINDOWS)
DEVMODE devMode; const char *deviceName = mode.DisplayDevice.c_str();
DEVMODEA devMode;
memset(&devMode, 0, sizeof(DEVMODE)); memset(&devMode, 0, sizeof(DEVMODE));
devMode.dmSize = sizeof(DEVMODE); devMode.dmSize = sizeof(DEVMODE);
devMode.dmDriverExtra = 0; devMode.dmDriverExtra = 0;
@ -1307,22 +1364,42 @@ bool CDriverGL::setScreenMode(const GfxMode &mode)
devMode.dmPelsWidth = mode.Width; devMode.dmPelsWidth = mode.Width;
devMode.dmPelsHeight = mode.Height; devMode.dmPelsHeight = mode.Height;
if(mode.Depth > 0) if (mode.Depth > 0)
{ {
devMode.dmBitsPerPel = mode.Depth; devMode.dmBitsPerPel = mode.Depth;
devMode.dmFields |= DM_BITSPERPEL; devMode.dmFields |= DM_BITSPERPEL;
} }
if(mode.Frequency > 0) if (mode.Frequency > 0)
{ {
devMode.dmDisplayFrequency = mode.Frequency; devMode.dmDisplayFrequency = mode.Frequency;
devMode.dmFields |= DM_DISPLAYFREQUENCY; devMode.dmFields |= DM_DISPLAYFREQUENCY;
} }
if (ChangeDisplaySettings(&devMode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) if (deviceName[0])
{ {
nlwarning("3D: Fullscreen mode switch failed"); // First attempt exclusive fullscreen
return false; 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) #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; NL3D_HAUTO_UI_DRIVER;
// window init. // 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 // Always true
nlverify (activate()); nlverify (activate());
@ -293,7 +293,7 @@ bool CDriverUser::setDisplay(nlWindow wnd, const CMode &mode, bool show, bool
// *************************************************************************** // ***************************************************************************
bool CDriverUser::setMode(const CMode& mode) 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); bool res = _Driver->getModes(vTmp);
modes.clear(); modes.clear();
for (uint i = 0; i < vTmp.size(); ++i) 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()); 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 // clip
ClipTrav.traverse(); ClipTrav.traverse();
if (doTrav) // animDetail
{ AnimDetailTrav.traverse();
// animDetail
AnimDetailTrav.traverse();
}
// loadBalance // loadBalance
LoadBalancingTrav.traverse(); LoadBalancingTrav.traverse();

View file

@ -211,6 +211,16 @@ void CStereoDebugger::setDriver(NL3D::UDriver *driver)
} }
} }
void CStereoDebugger::attachToDisplay()
{
}
void CStereoDebugger::detachFromDisplay()
{
}
void CStereoDebugger::getTextures() void CStereoDebugger::getTextures()
{ {
nlassert(!m_LeftTexU); nlassert(!m_LeftTexU);
@ -437,12 +447,12 @@ bool CStereoDebugger::wantInterface2D()
bool CStereoDebugger::isSceneFirst() bool CStereoDebugger::isSceneFirst()
{ {
return m_Stage == 1; return m_Stage != 3;
} }
bool CStereoDebugger::isSceneLast() 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 /// 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)); 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); nlctassert(NL_OVR_EYE_COUNT == ovrEye_Count);
@ -371,6 +371,11 @@ CStereoOVR::CStereoOVR(const CStereoOVRDeviceFactory *factory) : m_DevicePtr(NUL
CStereoOVR::~CStereoOVR() CStereoOVR::~CStereoOVR()
{ {
if (m_AttachedDisplay)
{
detachFromDisplay();
}
if (!m_UnlitMat.empty()) if (!m_UnlitMat.empty())
{ {
m_Driver->deleteMaterial(m_UnlitMat); m_Driver->deleteMaterial(m_UnlitMat);
@ -439,6 +444,38 @@ bool CStereoOVR::getScreenResolution(uint &width, uint &height)
return false; 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) void CStereoOVR::initCamera(uint cid, const NL3D::UCamera *camera)
{ {
m_OriginalFrustum[cid] = camera->getFrustum(); m_OriginalFrustum[cid] = camera->getFrustum();
@ -679,6 +716,8 @@ bool CStereoOVR::isSceneFirst()
{ {
case 3: case 3:
return true; return true;
case 4:
return false;
} }
return m_Driver->getPolygonMode() != UDriver::Filled; return m_Driver->getPolygonMode() != UDriver::Filled;
} }
@ -687,6 +726,8 @@ bool CStereoOVR::isSceneLast()
{ {
switch (m_Stage) switch (m_Stage)
{ {
case 3:
return false;
case 4: case 4:
return true; return true;
} }

View file

@ -31,6 +31,7 @@
// 3D Interface. // 3D Interface.
#include "nel/3d/u_driver.h" #include "nel/3d/u_driver.h"
#include "nel/3d/u_text_context.h" #include "nel/3d/u_text_context.h"
#include <nel/3d/stereo_display.h>
// Game Share // Game Share
//#include "game_share/gd_time.h" // \todo GUIGUI : TO DELETE/CHANGE //#include "game_share/gd_time.h" // \todo GUIGUI : TO DELETE/CHANGE
#include "game_share/gender.h" #include "game_share/gender.h"
@ -217,6 +218,9 @@ void connectionRestaureVideoMode ()
setVideoMode(mode); setVideoMode(mode);
} }
if (StereoDisplay)
StereoDisplay->attachToDisplay();
// And setup hardware mouse if we have to // And setup hardware mouse if we have to
InitMouseWithCursor (ClientCfg.HardwareCursor); InitMouseWithCursor (ClientCfg.HardwareCursor);
SetMouseFreeLook (); SetMouseFreeLook ();
@ -253,6 +257,9 @@ void setOutGameFullScreen()
// NB: don't setup fullscreen if player wants to play in window // NB: don't setup fullscreen if player wants to play in window
if (!ClientCfg.Local && ClientCfg.SelectCharacter == -1) if (!ClientCfg.Local && ClientCfg.SelectCharacter == -1)
{ {
if (StereoDisplay)
StereoDisplay->detachFromDisplay();
UDriver::CMode currMode; UDriver::CMode currMode;
Driver->getCurrentScreenMode(currMode); Driver->getCurrentScreenMode(currMode);
UDriver::CMode wantedMode; UDriver::CMode wantedMode;

View file

@ -20,6 +20,7 @@
#include <nel/3d/u_driver.h> #include <nel/3d/u_driver.h>
#include <nel/3d/u_cloud_scape.h> #include <nel/3d/u_cloud_scape.h>
#include <nel/3d/fxaa.h> #include <nel/3d/fxaa.h>
#include <nel/3d/stereo_display.h>
#include "game_share/scenario_entry_points.h" #include "game_share/scenario_entry_points.h"
@ -60,6 +61,8 @@ void updateFromClientCfg()
nldebug("Apply VR device change"); nldebug("Apply VR device change");
releaseStereoDisplayDevice(); releaseStereoDisplayDevice();
initStereoDisplayDevice(); initStereoDisplayDevice();
if (StereoDisplay)
StereoDisplay->attachToDisplay();
} }
// GRAPHICS - GENERAL // GRAPHICS - GENERAL
@ -70,8 +73,11 @@ void updateFromClientCfg()
(ClientCfg.Depth != LastClientCfg.Depth) || (ClientCfg.Depth != LastClientCfg.Depth) ||
(ClientCfg.Frequency != LastClientCfg.Frequency)) (ClientCfg.Frequency != LastClientCfg.Frequency))
{ {
setVideoMode(UDriver::CMode(ClientCfg.Width, ClientCfg.Height, (uint8)ClientCfg.Depth, if (!StereoDisplay) // TODO
ClientCfg.Windowed, ClientCfg.Frequency)); {
setVideoMode(UDriver::CMode(ClientCfg.Width, ClientCfg.Height, (uint8)ClientCfg.Depth,
ClientCfg.Windowed, ClientCfg.Frequency));
}
} }
if (ClientCfg.DivideTextureSizeBy2 != LastClientCfg.DivideTextureSizeBy2) if (ClientCfg.DivideTextureSizeBy2 != LastClientCfg.DivideTextureSizeBy2)