diff options
author | Brad Davis <[email protected]> | 2014-04-14 21:25:09 -0700 |
---|---|---|
committer | Brad Davis <[email protected]> | 2014-04-14 21:25:09 -0700 |
commit | 07d0f4d0bbf3477ac6a9584f726e8ec6ab285707 (patch) | |
tree | 1854d0c690eff32e77b137567c88a52d56d8b660 /Samples/CommonSrc/Render/Render_GL_Win32_Device.cpp | |
parent | f28388ff2af14b56ef2d973b2f4f9da021716d4c (diff) |
Adding windows 0.3.1 SDK
Diffstat (limited to 'Samples/CommonSrc/Render/Render_GL_Win32_Device.cpp')
-rw-r--r-- | Samples/CommonSrc/Render/Render_GL_Win32_Device.cpp | 248 |
1 files changed, 242 insertions, 6 deletions
diff --git a/Samples/CommonSrc/Render/Render_GL_Win32_Device.cpp b/Samples/CommonSrc/Render/Render_GL_Win32_Device.cpp index 4f22a50..1065c98 100644 --- a/Samples/CommonSrc/Render/Render_GL_Win32_Device.cpp +++ b/Samples/CommonSrc/Render/Render_GL_Win32_Device.cpp @@ -3,7 +3,7 @@ Filename : Render_GL_Win32 Device.cpp Content : Win32 OpenGL Device implementation Created : September 10, 2012 -Authors : Andrew Reisse, Michael Antonov +Authors : Andrew Reisse, Michael Antonov, David Borel Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. @@ -22,16 +22,46 @@ limitations under the License. ************************************************************************************/ #include "Render_GL_Win32_Device.h" +#include "OVR_CAPI_GL.h" + +#include <dwmapi.h> namespace OVR { namespace Render { namespace GL { namespace Win32 { +typedef HRESULT (__stdcall *PFNDWMENABLECOMPOSITIONPROC) (UINT); + +#pragma warning(disable : 4995) +PFNDWMENABLECOMPOSITIONPROC DwmEnableComposition; + // ***** GL::Win32::RenderDevice + +RenderDevice::RenderDevice(const Render::RendererParams& p, HWND win, HDC dc, HGLRC gl) + : GL::RenderDevice(p) + , Window(win) + , WglContext(gl) + , GdiDc(dc) + , PreFullscreen(0, 0, 0, 0) + , HMonitor(0) + , FSDesktop(0, 0, 0, 0) +{ + OVR_UNUSED(p); +} // Implement static initializer function to create this class. -Render::RenderDevice* RenderDevice::CreateDevice(const RendererParams&, void* oswnd) +Render::RenderDevice* RenderDevice::CreateDevice(const RendererParams& rp, void* oswnd) { HWND hwnd = (HWND)oswnd; + + if (!DwmEnableComposition) + { + HINSTANCE hInst = LoadLibrary( L"dwmapi.dll" ); + OVR_ASSERT(hInst); + DwmEnableComposition = (PFNDWMENABLECOMPOSITIONPROC)GetProcAddress( hInst, "DwmEnableComposition" ); + OVR_ASSERT(DwmEnableComposition); + } + + DwmEnableComposition(DWM_EC_DISABLECOMPOSITION); PIXELFORMATDESCRIPTOR pfd; memset(&pfd, 0, sizeof(pfd)); @@ -63,18 +93,40 @@ Render::RenderDevice* RenderDevice::CreateDevice(const RendererParams&, void* os return NULL; } - // return new RenderDevice(rp, hwnd, dc, context); - return 0; + InitGLExtensions(); + + return new RenderDevice(rp, hwnd, dc, context); } +ovrRenderAPIConfig RenderDevice::Get_ovrRenderAPIConfig() const +{ + static ovrGLConfig cfg; + cfg.OGL.Header.API = ovrRenderAPI_OpenGL; + cfg.OGL.Header.RTSize = Sizei(WindowWidth, WindowHeight); + cfg.OGL.Header.Multisample = Params.Multisample; + cfg.OGL.WglContext = WglContext; + cfg.OGL.Window = Window; + cfg.OGL.GdiDc = GdiDc; -void RenderDevice::Present() + return cfg.Config; +} + +void RenderDevice::Present(bool useVsync) { - SwapBuffers(GdiDc); + BOOL success; + int swapInterval = (useVsync) ? 1 : 0; + if (wglGetSwapIntervalEXT() != swapInterval) + wglSwapIntervalEXT(swapInterval); + + success = SwapBuffers(GdiDc); + OVR_ASSERT(success); } void RenderDevice::Shutdown() { + //Release any remaining GL resources. + GL::RenderDevice::Shutdown(); + if (WglContext) { wglMakeCurrent(NULL,NULL); @@ -86,5 +138,189 @@ void RenderDevice::Shutdown() } } +bool RenderDevice::SetParams(const RendererParams& newParams) +{ + Params = newParams; + //TODO: Apply changes now. + return true; +} + +BOOL CALLBACK MonitorEnumFunc(HMONITOR hMonitor, HDC, LPRECT, LPARAM dwData) +{ + RenderDevice* renderer = (RenderDevice*)dwData; + + MONITORINFOEX monitor; + monitor.cbSize = sizeof(monitor); + + if (::GetMonitorInfo(hMonitor, &monitor) && monitor.szDevice[0]) + { + DISPLAY_DEVICE dispDev; + memset(&dispDev, 0, sizeof(dispDev)); + dispDev.cb = sizeof(dispDev); + + if (::EnumDisplayDevices(monitor.szDevice, 0, &dispDev, 0)) + { + if (strstr(String(dispDev.DeviceName).ToCStr(), renderer->GetParams().Display.MonitorName.ToCStr())) + { + renderer->HMonitor = hMonitor; + renderer->FSDesktop.x = monitor.rcMonitor.left; + renderer->FSDesktop.y = monitor.rcMonitor.top; + renderer->FSDesktop.w = monitor.rcMonitor.right - monitor.rcMonitor.left; + renderer->FSDesktop.h = monitor.rcMonitor.bottom - monitor.rcMonitor.top; + return FALSE; + } + } + } + + return TRUE; +} + +bool RenderDevice::SetFullscreen(DisplayMode fullscreen) +{ + if (fullscreen == Params.Fullscreen) + { + return true; + } + + if (Params.Fullscreen == Display_FakeFullscreen) + { + SetWindowLong(Window, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPSIBLINGS); + SetWindowPos(Window, HWND_NOTOPMOST, PreFullscreen.x, PreFullscreen.y, + PreFullscreen.w, PreFullscreen.h, SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED); + } + else if (Params.Fullscreen == Display_Fullscreen) + { + { + // Find out the name of the device this window + // is on (this is for multi-monitor setups) + HMONITOR hMonitor = MonitorFromWindow(Window, MONITOR_DEFAULTTOPRIMARY); + MONITORINFOEX monInfo; + memset(&monInfo, 0, sizeof(MONITORINFOEX)); + monInfo.cbSize = sizeof(MONITORINFOEX); + GetMonitorInfo(hMonitor, &monInfo); + + // Restore the display resolution + ChangeDisplaySettingsEx(monInfo.szDevice, NULL, NULL, 0, NULL); + //ChangeDisplaySettings(NULL, 0); + } + { + // Restore the window styles + DWORD style = (DWORD)GetWindowLongPtr(Window, GWL_STYLE); + DWORD exstyle = (DWORD)GetWindowLongPtr(Window, GWL_EXSTYLE); + SetWindowLongPtr(Window, GWL_STYLE, style | WS_OVERLAPPEDWINDOW); + SetWindowLongPtr(Window, GWL_EXSTYLE, exstyle & (~(WS_EX_APPWINDOW | WS_EX_TOPMOST))); + + MONITORINFOEX monInfo; + memset(&monInfo, 0, sizeof(MONITORINFOEX)); + monInfo.cbSize = sizeof(MONITORINFOEX); + GetMonitorInfo(HMonitor, &monInfo); + + // Restore the window size/position + SetWindowPos(Window, NULL, PreFullscreen.x, PreFullscreen.y, PreFullscreen.w, PreFullscreen.h, + SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOOWNERZORDER | SWP_NOREPOSITION | SWP_NOZORDER); + } + } + + + if (!Params.Display.MonitorName.IsEmpty()) + { + EnumDisplayMonitors(0, 0, MonitorEnumFunc, (LPARAM)this); + } + + if (fullscreen == Display_FakeFullscreen) + { + // Get WINDOWPLACEMENT before changing style to get OVERLAPPED coordinates, + // which we will restore. + WINDOWPLACEMENT wp; + wp.length = sizeof(wp); + GetWindowPlacement(Window, &wp); + PreFullscreen.w = wp.rcNormalPosition.right - wp.rcNormalPosition.left; + PreFullscreen.h = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top; + PreFullscreen.x = wp.rcNormalPosition.left; + PreFullscreen.y = wp.rcNormalPosition.top; + // Warning: SetWindowLong sends message computed based on old size (incorrect). + // A proper work-around would be to mask that message out during window frame change in Platform. + SetWindowLong(Window, GWL_STYLE, WS_OVERLAPPED | WS_VISIBLE | WS_CLIPSIBLINGS); + SetWindowPos(Window, NULL, FSDesktop.x, FSDesktop.y, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | SWP_FRAMECHANGED); + + // Relocate cursor into the window to avoid losing focus on first click. + POINT oldCursor; + if (GetCursorPos(&oldCursor) && + ((oldCursor.x < FSDesktop.x) || (oldCursor.x > (FSDesktop.x + PreFullscreen.w)) || + (oldCursor.y < FSDesktop.y) || (oldCursor.x > (FSDesktop.y + PreFullscreen.h)))) + { + // TBD: FullScreen window logic should really be in platform; it causes world rotation + // in relative mouse mode. + ::SetCursorPos(FSDesktop.x, FSDesktop.y); + } + } + else if (fullscreen == Display_Fullscreen) + { + // Find out the name of the device this window + // is on (this is for multi-monitor setups) + MONITORINFOEX monInfo; + memset(&monInfo, 0, sizeof(MONITORINFOEX)); + monInfo.cbSize = sizeof(MONITORINFOEX); + GetMonitorInfo(HMonitor, &monInfo); + + // Find the requested device mode + DEVMODE dmode; + bool foundMode = false; + memset(&dmode, 0, sizeof(DEVMODE)); + dmode.dmSize = sizeof(DEVMODE); + Recti vp = VP; + for(int i=0 ; EnumDisplaySettings(monInfo.szDevice, i, &dmode); ++i) + { + foundMode = (dmode.dmPelsWidth==(DWORD)vp.w) && + (dmode.dmPelsHeight==(DWORD)vp.h) && + (dmode.dmBitsPerPel==(DWORD)32); + if (foundMode) + break; + } + if(!foundMode) + return false; + + dmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; + + // Save the current window position/size + RECT rect; + GetWindowRect(Window, &rect); + PreFullscreen.x = rect.left; + PreFullscreen.y = rect.top; + PreFullscreen.w = rect.right - rect.left; + PreFullscreen.h = rect.bottom - rect.top; + + // Save the window style and set it for fullscreen mode + DWORD style = (DWORD)GetWindowLongPtr(Window, GWL_STYLE); + DWORD exstyle = (DWORD)GetWindowLongPtr(Window, GWL_EXSTYLE); + SetWindowLongPtr(Window, GWL_STYLE, style & (~WS_OVERLAPPEDWINDOW)); + SetWindowLongPtr(Window, GWL_EXSTYLE, exstyle | WS_EX_APPWINDOW | WS_EX_TOPMOST); + + // Attempt to change the resolution + LONG ret = ChangeDisplaySettingsEx(monInfo.szDevice, &dmode, NULL, CDS_FULLSCREEN, NULL); + //LONG ret = ChangeDisplaySettings(&dmode, CDS_FULLSCREEN); + + // If it failed, clean up and return. + if (ret != DISP_CHANGE_SUCCESSFUL) + { + SetWindowLongPtr(Window, GWL_STYLE, style); + SetWindowLongPtr(Window, GWL_EXSTYLE, exstyle); + return false; + } + + // We need to call GetMonitorInfo() again becase + // details may have changed with the resolution + GetMonitorInfo(HMonitor, &monInfo); + + // Set the window's size and position so + // that it covers the entire screen + SetWindowPos(Window, HWND_TOPMOST, monInfo.rcMonitor.left, monInfo.rcMonitor.top, vp.w, vp.h, + SWP_SHOWWINDOW | SWP_NOZORDER | SWP_FRAMECHANGED); + } + + Params.Fullscreen = fullscreen; + return true; +} + }}}} |