diff options
author | Brad Davis <[email protected]> | 2014-07-24 16:47:31 -0700 |
---|---|---|
committer | Brad Davis <[email protected]> | 2014-07-24 16:47:31 -0700 |
commit | 0f49ce8fc6aa54224e4c0d6fda8c4527ad39cce1 (patch) | |
tree | da07ebc6a7f75185bda857dd5f1c34710b416a93 /LibOVR/Src/Displays | |
parent | ca79271759ff7eecd22ec5c4db438370fe51d687 (diff) |
0.4 Win-Beta0.4.0
Diffstat (limited to 'LibOVR/Src/Displays')
-rw-r--r-- | LibOVR/Src/Displays/OVR_Display.cpp | 32 | ||||
-rw-r--r-- | LibOVR/Src/Displays/OVR_Display.h | 196 | ||||
-rw-r--r-- | LibOVR/Src/Displays/OVR_Win32_Display.cpp | 942 | ||||
-rw-r--r-- | LibOVR/Src/Displays/OVR_Win32_Display.h | 169 | ||||
-rw-r--r-- | LibOVR/Src/Displays/OVR_Win32_Dxgi_Display.h | 413 | ||||
-rw-r--r-- | LibOVR/Src/Displays/OVR_Win32_FocusReader.cpp | 80 | ||||
-rw-r--r-- | LibOVR/Src/Displays/OVR_Win32_FocusReader.h | 82 | ||||
-rw-r--r-- | LibOVR/Src/Displays/OVR_Win32_RenderShim.cpp | 788 | ||||
-rw-r--r-- | LibOVR/Src/Displays/OVR_Win32_ShimFunctions.cpp | 230 | ||||
-rw-r--r-- | LibOVR/Src/Displays/OVR_Win32_ShimFunctions.h | 79 |
10 files changed, 3011 insertions, 0 deletions
diff --git a/LibOVR/Src/Displays/OVR_Display.cpp b/LibOVR/Src/Displays/OVR_Display.cpp new file mode 100644 index 0000000..65f0b30 --- /dev/null +++ b/LibOVR/Src/Displays/OVR_Display.cpp @@ -0,0 +1,32 @@ +/************************************************************************************ + +PublicHeader: None +Filename : OVR_Display.cpp +Content : Common implementation for display device +Created : May 6, 2014 +Notes : + +Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. + +Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +you may not use the Oculus VR Rift SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +http://www.oculusvr.com/licenses/LICENSE-3.1 + +Unless required by applicable law or agreed to in writing, the Oculus VR SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +************************************************************************************/ + +#include "OVR_Display.h" + +namespace OVR { + +} diff --git a/LibOVR/Src/Displays/OVR_Display.h b/LibOVR/Src/Displays/OVR_Display.h new file mode 100644 index 0000000..d6e8b90 --- /dev/null +++ b/LibOVR/Src/Displays/OVR_Display.h @@ -0,0 +1,196 @@ +/************************************************************************************ + +PublicHeader: None +Filename : OVR_Display.h +Content : Contains platform independent display management +Created : May 6, 2014 +Notes : + +Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. + +Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +you may not use the Oculus VR Rift SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +http://www.oculusvr.com/licenses/LICENSE-3.1 + +Unless required by applicable law or agreed to in writing, the Oculus VR SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +************************************************************************************/ + +#ifndef OVR_Display_h +#define OVR_Display_h + +#include "../Sensors/OVR_DeviceConstants.h" // Required for HmdTypeEnum + +#include "../Kernel/OVR_Types.h" +#include "../Kernel/OVR_Atomic.h" +#include "../Kernel/OVR_RefCount.h" +#include "../Kernel/OVR_Array.h" +#include "../Kernel/OVR_String.h" +#include "../Kernel/OVR_Math.h" + +namespace OVR { + +class DisplaySearchHandle : virtual public RefCountBaseV<DisplaySearchHandle> +{ +public: + DisplaySearchHandle() {} + + virtual ~DisplaySearchHandle() {} + + void operator= (const DisplaySearchHandle&) {} +}; + +//------------------------------------------------------------------------------------- +// ***** Display + +// Display object describes an Oculus HMD screen in LibOVR, providing information such +// as EDID serial number and resolution in platform-independent manner. +// +// Display is an abstract base class to support OS and driver specific implementations. +// It support HMD screen enumeration through GetDisplayCount/GetDisplay static functions. +// +// Examples of implementations of Display are the following: +// Display_Win32_Generic - Compatibly mode implementation that maintains operation on +// systems without drivers. +// Display_Win32_Driver - Driver-Based display +// Display_OSX_Generic - Additional compatibility mode implementation for OS X + +class Display : public RefCountBase<Display> +{ +protected: + enum MirrorMode + { + MirrorEnabled = 0, + MirrorDisabled = 1 + }; + + MirrorMode mirrorMode; + + Display( + HmdTypeEnum deviceTypeGuess, +#ifdef OVR_OS_MAC + uint32_t displayID, +#else + const String& displayID, +#endif + const String& modelName, + const String& editSerial, + const Sizei& logicalRes, + const Sizei& nativeRes, + const Vector2i& displayOffset, + const uint64_t devNumber, + const uint32_t rotation, + const bool appExclusive): + DeviceTypeGuess(deviceTypeGuess), + DisplayID(displayID), + ModelName(modelName), + EdidSerialNumber(editSerial), + LogicalResolutionInPixels(logicalRes), + NativeResolutionInPixels(nativeRes), + DesktopDisplayOffset(displayOffset), + DeviceNumber(devNumber), + Rotation(rotation), + ApplicationExclusive(appExclusive) + { + } + + void operator = (const Display&) { } // Quiet warning. + +public: + virtual ~Display() { } + + // ----- Platform specific static Display functionality ----- + + // Mandatory function that sets up the display environment with + // any necessary shimming and function hooks. This should be one + // of the very first things your application does when it + // initializes LibOVR + static bool Initialize(); + + // Returns a count of the detected displays. These are Rift displays + // attached directly to an active display port + static int GetDisplayCount( DisplaySearchHandle* handle = NULL, bool extended = true, bool applicationOnly = true, bool extendedEDIDSerials = false ); + // Returns a specific index of a display. Displays are sorted in no particular order. + static Ptr<Display> GetDisplay( int index = 0, DisplaySearchHandle* handle = NULL ); + + + // Returns true if we are referencing the same display; useful for matching display + // objects with the ones already detected. + bool MatchDisplay(const Display* other) + { + // Note this is not checking the DeviceName, which corresponds to which monitor the device is. + // This allows matching to match a display that has changed how it is plugged in. + return (DisplayID == other->DisplayID) && + (EdidSerialNumber == other->EdidSerialNumber) && + (NativeResolutionInPixels == other->NativeResolutionInPixels) && + (DesktopDisplayOffset == other->DesktopDisplayOffset) && + (ApplicationExclusive == other->ApplicationExclusive); + } + + + // ----- Device independent instance based Display functionality ----- + + // Device type guess based on display info. + const HmdTypeEnum DeviceTypeGuess; +#if defined(OVR_OS_MAC) + // CGDirectDisplayID for the rift. + const uint32_t DisplayID; +#else + // A string denoting the display device name so that apps can recognize the monitor + const String DisplayID; +#endif + // A literal string containing the name of the model, i.e. Rift DK2 + const String ModelName; + // Part of the serial number encoded in Edid, used for monitor <-> sensor matching. + const String EdidSerialNumber; + // Logical resolution is the display resolution in presentation terms. + // That is to say, the resolution that represents the orientation the + // display is projected to the user. For DK2, while being a portrait display + // the display is held in landscape and therefore the logical resolution + // is 1920x1080 + const Sizei LogicalResolutionInPixels; + // Native resolution is the resolution reported by the EDID and represents the + // exact hardware resolution of the Rift. For example, on DK2 + // this is 1080x1920 + // In theory, an OS rotated Rift's native and logical resolutions should match + const Sizei NativeResolutionInPixels; + // For displays that are attached to the desktop, this return value has meaning. + // Otherwise it should always return origin + const Vector2i DesktopDisplayOffset; + // For Windows machines this value stores the ChildUid used to identify this display + const uint64_t DeviceNumber; + // Stores the device specific default rotation of the screen + // E.g. DK2 is rotated 90 degrees as it is a portrait display + const uint32_t Rotation; + // Is set if the Display is capable in Application-Only mode + const bool ApplicationExclusive; + + // Functionality for rendering within the window + virtual MirrorMode SetMirrorMode( MirrorMode newMode ) = 0; + + // Functionality for enabling/disabling display + virtual bool SetDisplaySleep(bool off) + { + // Override to implement if supported + OVR_UNUSED(off); + return false; + } + + // In compatibility mode? + static bool InCompatibilityMode(); + static DisplaySearchHandle* GetDisplaySearchHandle(); +}; + + +} // namespace OVR + +#endif diff --git a/LibOVR/Src/Displays/OVR_Win32_Display.cpp b/LibOVR/Src/Displays/OVR_Win32_Display.cpp new file mode 100644 index 0000000..379f69b --- /dev/null +++ b/LibOVR/Src/Displays/OVR_Win32_Display.cpp @@ -0,0 +1,942 @@ +/************************************************************************************ + +Filename : OVR_Win32_Display.cpp +Content : Win32 Display implementation +Created : May 6, 2014 +Authors : Dean Beeler + +Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. + +Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +you may not use the Oculus VR Rift SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +http://www.oculusvr.com/licenses/LICENSE-3.1 + +Unless required by applicable law or agreed to in writing, the Oculus VR SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*************************************************************************************/ + +#include <Windows.h> + +#include "OVR_Win32_Display.h" +#include "OVR_Win32_Dxgi_Display.h" + +#include <stdio.h> +#include <tchar.h> +#include <string.h> +#include <stdlib.h> +#include <winioctl.h> +#include <SetupAPI.h> +#include <Mmsystem.h> +#include <conio.h> +# pragma comment(lib, "wbemuuid.lib") +#include <wbemidl.h> +#include <AtlBase.h> +#include <AtlConv.h> + +// WIN32_LEAN_AND_MEAN included in OVR_Atomic.h may break 'byte' declaration. +#ifdef WIN32_LEAN_AND_MEAN + typedef unsigned char byte; +#endif + +#include "../Kernel/OVR_String.h" +#include "../Kernel/OVR_Log.h" + +typedef struct +{ + HANDLE hDevice; + UINT ExpectedWidth; + UINT ExpectedHeight; + HWND hWindow; + BOOL InCompatibilityMode; +} ContextStruct; + +static ContextStruct GlobalDisplayContext = {0}; + + +//------------------------------------------------------------------------------------- +// ***** Display enumeration Helpers + +// THere are two ways to enumerate display: through our driver (DeviceIoControl) +// and through Win32 EnumDisplayMonitors (compatibility mode). + + +namespace OVR { + +ULONG getRiftCount( HANDLE hDevice ) +{ + ULONG riftCount = 0; + DWORD bytesReturned = 0; + + BOOL result = DeviceIoControl( hDevice, IOCTL_RIFTMGR_GET_RIFT_COUNT, NULL, 0, + &riftCount, sizeof( ULONG ), &bytesReturned, NULL ); + + if( result ) + return riftCount; + else + return 0; +} + +ULONG getRift( HANDLE hDevice, int index ) +{ + ULONG riftCount = getRiftCount( hDevice ); + DWORD bytesReturned = 0; + BOOL result; + + if( riftCount >= (ULONG)index ) + { + RIFT_STATUS riftStatus[16] = {0}; + + result = DeviceIoControl( hDevice, IOCTL_RIFTMGR_GET_RIFT_ARRAY, riftStatus, + riftCount * sizeof( RIFT_STATUS ), &riftCount, + sizeof( ULONG ), &bytesReturned, NULL ); + if( result ) + { + PRIFT_STATUS tmpRift; + unsigned int i; + for( i = 0, tmpRift = riftStatus; i < riftCount; ++i, ++tmpRift ) + { + if( i == (unsigned int)index ) + return tmpRift->childUid; + } + } + else + { + printf("Failed to get array of rift devices\n"); + } + } + + return 0; +} + +#define EDID_LENGTH 0x80 + +#define EDID_HEADER 0x00 +#define EDID_HEADER_END 0x07 + +#define ID_MANUFACTURER_NAME 0x08 +#define ID_MANUFACTURER_NAME_END 0x09 + +#define EDID_STRUCT_VERSION 0x12 +#define EDID_STRUCT_REVISION 0x13 + +#define ESTABLISHED_TIMING_1 0x23 +#define ESTABLISHED_TIMING_2 0x24 +#define MANUFACTURERS_TIMINGS 0x25 + +#define DETAILED_TIMING_DESCRIPTIONS_START 0x36 +#define DETAILED_TIMING_DESCRIPTION_SIZE 18 +#define NO_DETAILED_TIMING_DESCRIPTIONS 4 + +#define DETAILED_TIMING_DESCRIPTION_1 0x36 +#define DETAILED_TIMING_DESCRIPTION_2 0x48 +#define DETAILED_TIMING_DESCRIPTION_3 0x5a +#define DETAILED_TIMING_DESCRIPTION_4 0x6c + +#define MONITOR_NAME 0xfc +#define MONITOR_LIMITS 0xfd +#define MONITOR_SERIAL 0xff + +#define UNKNOWN_DESCRIPTOR -1 +#define DETAILED_TIMING_BLOCK -2 + +#define DESCRIPTOR_DATA 5 + +const byte edid_v1_header[] = { 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00 }; + +const byte edid_v1_descriptor_flag[] = { 0x00, 0x00 }; + + +static int blockType( byte* block ) +{ + if ( !strncmp( (const char*)edid_v1_descriptor_flag, (const char*)block, 2 ) ) + { + // descriptor + if ( block[ 2 ] != 0 ) + return UNKNOWN_DESCRIPTOR; + return block[ 3 ]; + } + else + { + return DETAILED_TIMING_BLOCK; + } +} + +static char* getMonitorName( byte const* block ) +{ + static char name[ 13 ]; + unsigned i; + byte const* ptr = block + DESCRIPTOR_DATA; + + for( i = 0; i < 13; i++, ptr++ ) + { + if ( *ptr == 0xa ) + { + name[ i ] = 0; + return name; + } + + name[ i ] = *ptr; + } + + return name; +} + + +static bool parseEdid( byte* edid, OVR::Win32::DisplayEDID& edidResult ) +{ + unsigned i; + byte* block; + char* monitor_name = "Unknown"; + byte checksum = 0; + + for( i = 0; i < EDID_LENGTH; i++ ) + checksum += edid[ i ]; + + // Bad checksum, fail EDID + if ( checksum != 0 ) + return false; + + if ( strncmp( (const char*)edid+EDID_HEADER, (const char*)edid_v1_header, EDID_HEADER_END+1 ) ) + { + // First bytes don't match EDID version 1 header + return false; + } + + //printf( "\n# EDID version %d revision %d\n", (int)edid[EDID_STRUCT_VERSION],(int)edid[EDID_STRUCT_REVISION] ); + + // Monitor name and timings + + char serialNumber[14]; + memset( serialNumber, 0, 14 ); + + block = edid + DETAILED_TIMING_DESCRIPTIONS_START; + + for( i = 0; i < NO_DETAILED_TIMING_DESCRIPTIONS; i++, + block += DETAILED_TIMING_DESCRIPTION_SIZE ) + { + + if ( blockType( block ) == MONITOR_NAME ) + { + monitor_name = getMonitorName( block ); + } + + if( blockType( block ) == MONITOR_SERIAL ) + { + memcpy( serialNumber, block + 5, 13 ); + break; + } + } + + BYTE vendorString[4] = {0}; + + vendorString[0] = (edid[8] >> 2 & 31) + 64; + vendorString[1] = ((edid[8] & 3) << 3) | (edid[9] >> 5) + 64; + vendorString[2] = (edid[9] & 31) + 64; + + edidResult.ModelNumber = *(UINT16*)&edid[10]; + edidResult.MonitorName = OVR::String(monitor_name); + edidResult.VendorName = OVR::String((const char*)vendorString); + edidResult.SerialNumber = OVR::String(serialNumber); + +#if 0 + printf( "\tIdentifier \"%s\"\n", monitor_name ); + printf( "\tVendorName \"%s\"\n", vendorString ); + printf( "\tModelName \"%s\"\n", monitor_name ); + printf( "\tModelNumber %d\n", modelNumber ); + printf( "\tSerialNumber \"%x\"\n", *serialPointer ); +#endif + + // FIXME: Get timings as well, though they aren't very useful here + // except for the vertical refresh rate, presumably + + return true; +} + +static bool getEdid(HANDLE hDevice, ULONG uid, OVR::Win32::DisplayEDID& edidResult) +{ + ULONG riftCount = 0; + DWORD bytesReturned = 0; + RIFT_STATUS riftStatus[16] = {0}; + + BOOL result = DeviceIoControl( hDevice, IOCTL_RIFTMGR_GET_RIFT_COUNT, NULL, 0, + &riftCount, sizeof( ULONG ), &bytesReturned, NULL ); + + if (!result) + { + return false; + } + + result = DeviceIoControl( hDevice, IOCTL_RIFTMGR_GET_RIFT_ARRAY, &riftStatus, + riftCount * sizeof( RIFT_STATUS ), &riftCount, sizeof(ULONG), + &bytesReturned, NULL ); + if (!result) + { + return false; + } + + for (ULONG i = 0; i < riftCount; ++i) + { + ULONG riftUid = riftStatus[i].childUid; + if (riftUid == uid) + { + char edidBuffer[512]; + + result = DeviceIoControl(hDevice, IOCTL_RIFTMGR_GETEDID, &riftUid, sizeof(ULONG), + edidBuffer, 512, &bytesReturned, NULL); + + if (result) + { + if (parseEdid((byte*)edidBuffer, edidResult)) + { + return true; + } + else + { + OVR_DEBUG_LOG(("[Win32Display] WARNING: The driver was not able to return EDID for a display")); + } + } + + break; + } + } + + return false; +} + + +// Used to capture all the active monitor handles +struct MonitorSet +{ + enum { MaxMonitors = 8 }; + HMONITOR Monitors[MaxMonitors]; + int MonitorCount; + int PrimaryCount; +}; + +static BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC, LPRECT, LPARAM dwData) +{ + MonitorSet* monitorSet = (MonitorSet*)dwData; + if (monitorSet->MonitorCount >= MonitorSet::MaxMonitors) + return FALSE; + + monitorSet->Monitors[monitorSet->MonitorCount] = hMonitor; + monitorSet->MonitorCount++; + return TRUE; +}; + + +static bool getCompatDisplayEDID( WCHAR* displayName, String& serialNumberStr, String& userFriendlyNameStr ) +{ + USES_CONVERSION; + + IWbemLocator *pLoc = NULL; + IWbemServices *pSvc = NULL; + HRESULT hres; + + static bool initialized = false; + static bool selfInitialized = true; + if (!initialized) + { + hres = CoInitializeEx(0, COINIT_MULTITHREADED); + if (FAILED(hres)) + { + OVR_DEBUG_LOG_TEXT(("Failed to initialize COM library. Error code = 0x%x\n", hres)); + return false; + } + + hres = CoInitializeSecurity( + NULL, + -1, // COM authentication + NULL, // Authentication services + NULL, // Reserved + RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication + RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation + NULL, // Authentication info + EOAC_NONE, // Additional capabilities + NULL // Reserved + ); + + if (FAILED(hres)) + { + OVR_DEBUG_LOG_TEXT(("Failed to initialize security. Error code = 0x%x\n", hres)); + //CoUninitialize(); + //return false; + selfInitialized = false; + } + + initialized = true; + } + + hres = CoCreateInstance( + CLSID_WbemLocator, + 0, + CLSCTX_INPROC_SERVER, + IID_IWbemLocator, (LPVOID *)&pLoc); + + if (FAILED(hres)) + { + OVR_DEBUG_LOG_TEXT(("Failed to create IWbemLocator object. Err code = 0x%x\n", hres)); + return false; + } + + BSTR AbackB = SysAllocString(L"root\\WMI"); + // Connect to the root\cimv2 namespace with + // the current user and obtain pointer pSvc + // to make IWbemServices calls. + hres = pLoc->ConnectServer( + AbackB, // Object path of WMI namespace + NULL, // User name. NULL = current user + NULL, // User password. NULL = current + 0, // Locale. NULL indicates current + NULL, // Security flags. + 0, // Authority (e.g. Kerberos) + 0, // Context object + &pSvc // pointer to IWbemServices proxy + ); + SysFreeString(AbackB); + + if (FAILED(hres)) + { + OVR_DEBUG_LOG_TEXT(("Could not connect. Error code = 0x%x\n", hres)); + pLoc->Release(); + return false; + } + + hres = CoSetProxyBlanket( + pSvc, // Indicates the proxy to set + RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx + RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx + NULL, // Server principal name + RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx + RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx + NULL, // client identity + EOAC_NONE // proxy capabilities + ); + + if (FAILED(hres)) + { + OVR_DEBUG_LOG_TEXT(("Could not set proxy blanket. Error code = 0x%x\n", hres)); + pSvc->Release(); + pLoc->Release(); + return false; + } + + + BSTR wql = SysAllocString(L"WQL"); + BSTR select = SysAllocString(L"SELECT * FROM WmiMonitorID"); + IEnumWbemClassObject* pEnumerator = NULL; + hres = pSvc->ExecQuery( + wql, + select, + WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, + NULL, + &pEnumerator); + SysFreeString(wql); + SysFreeString(select); + + if (FAILED(hres)) + { + OVR_DEBUG_LOG_TEXT(( "Query for operating system name failed. Error code = 0x%x\n", hres )); + pSvc->Release(); + pLoc->Release(); + return false; + } + + IWbemClassObject *pclsObj = 0; + while (pEnumerator) + { + ULONG uReturn = 0; + HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); + + if (!uReturn) + { + break; + } + + VARIANT vtProp; + hr = pclsObj->Get(L"InstanceName", 0, &vtProp, 0, 0); + + WCHAR* instanceName = vtProp.bstrVal; + WCHAR* nextToken = NULL; + if (wcstok_s(instanceName, L"\\", &nextToken) != NULL) + { + WCHAR* aToken = wcstok_s(NULL, L"\\", &nextToken); + + if (aToken != NULL) + { + VariantClear(&vtProp); + + if (wcscmp(aToken, displayName) != 0) + { + pclsObj->Release(); + continue; + } + + // Read serial + + UINT32* serialArray = NULL; + + hr = pclsObj->Get(L"SerialNumberID", 0, &vtProp, 0, 0); + + static const int MaxSerialBytes = 14; + char serialNumber[MaxSerialBytes]; + + serialArray = (UINT32*)vtProp.parray->pvData; + + for (int i = 0; i < MaxSerialBytes; ++i) + { + serialNumber[i] = (BYTE)(serialArray[i] & 0xff); + } + serialNumber[sizeof(serialNumber) - 1] = '\0'; + serialNumberStr = serialNumber; + + VariantClear(&vtProp); + + // Read length of name + + hr = pclsObj->Get(L"UserFriendlyNameLength", 0, &vtProp, 0, 0); + + int userFriendlyNameLen = vtProp.iVal; + + VariantClear(&vtProp); + + // Read name + + static const int MaxNameBytes = 64; + char userFriendlyName[MaxNameBytes] = { 0 }; + + UINT32* nameArray = NULL; + + hr = pclsObj->Get(L"UserFriendlyName", 0, &vtProp, 0, 0); + + nameArray = (UINT32*)vtProp.parray->pvData; + for (int i = 0; i < MaxNameBytes && i < userFriendlyNameLen; ++i) + { + userFriendlyName[i] = (BYTE)(nameArray[i] & 0xff); + } + userFriendlyName[sizeof(userFriendlyName) - 1] = '\0'; + userFriendlyNameStr = userFriendlyName; + + VariantClear(&vtProp); + } + } + + pclsObj->Release(); + + break; + } + + HMODULE hModule = GetModuleHandleA("wbemuuid"); + if (hModule) + { + DisableThreadLibraryCalls(hModule); + } + + pSvc->Release(); + pLoc->Release(); + pEnumerator->Release(); + + return true; +} + +static int discoverExtendedRifts(OVR::Win32::DisplayDesc* descriptorArray, int inputArraySize, bool includeEDID) +{ + static bool reportDiscovery = true; + + int result = 0; + + MonitorSet monitors; + monitors.MonitorCount = 0; + // Get all the monitor handles + EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM)&monitors); + + DISPLAY_DEVICE dd, ddm; + UINT i, j; + + for (i = 0; + (ZeroMemory(&dd, sizeof(dd)), dd.cb = sizeof(dd), + EnumDisplayDevices(0, i, &dd, 0)) != 0; i++) + { + for (j = 0; + (ZeroMemory(&ddm, sizeof(ddm)), ddm.cb = sizeof(ddm), + EnumDisplayDevices(dd.DeviceName, j, &ddm, 0)) != 0; j++) + { + if( result >= inputArraySize ) + return result; + + // Our monitor hardware has string "RTD2205" in it + // Nate's device "CVT0003" + if (wcsstr(ddm.DeviceID, L"RTD2205") || + wcsstr(ddm.DeviceID, L"CVT0003") || + wcsstr(ddm.DeviceID, L"MST0030") || + wcsstr(ddm.DeviceID, L"OVR00") ) // Part of Oculus EDID. + { + String deviceId(ddm.DeviceID); + String displayDeviceName(ddm.DeviceName); + Vector2i desktopOffset(0, 0); + Sizei monitorResolution(1280, 800); + + // Make a device type guess + HmdTypeEnum deviceTypeGuess = HmdType_Unknown; + if (wcsstr(ddm.DeviceID, L"OVR0003")) + { + // DK2 prototypes and variants + deviceTypeGuess = HmdType_DK2; + // Could also be: + // HmdType_CrystalCoveProto + } + else if (wcsstr(ddm.DeviceID, L"OVR0002")) + { // HD Prototypes + deviceTypeGuess = HmdType_DKHDProto; + // Could also be: + // HmdType_DKHD2Proto + // HmdType_DKHDProto566Mi + } + else if (wcsstr(ddm.DeviceID, L"OVR0001")) + { // DK1 + deviceTypeGuess = HmdType_DK1; + } + else if (wcsstr(ddm.DeviceID, L"OVR00")) + { // Future Oculus HMD devices + deviceTypeGuess = HmdType_Unknown; + } + else + { + deviceTypeGuess = HmdType_DKProto; + } + + // Find the matching MONITORINFOEX for this device so we can get the + // screen coordinates + MONITORINFOEX info; + for (int m=0; m < monitors.MonitorCount; m++) + { + info.cbSize = sizeof(MONITORINFOEX); + GetMonitorInfo(monitors.Monitors[m], &info); + if (_tcsstr(ddm.DeviceName, info.szDevice) == ddm.DeviceName) + { // If the device name starts with the monitor name + // then we found the matching DISPLAY_DEVICE and MONITORINFO + // so we can gather the monitor coordinates + desktopOffset = Vector2i(info.rcMonitor.left, info.rcMonitor.top); + break; + } + } + + WCHAR* instanceBuffer = (WCHAR*)calloc(wcslen(ddm.DeviceID) + 1, sizeof(WCHAR)); + wcscpy_s(instanceBuffer, wcslen(ddm.DeviceID) + 1, ddm.DeviceID); + WCHAR* instanceName = instanceBuffer; + WCHAR* nextToken = NULL; + if (wcstok_s(instanceName, L"\\", &nextToken)) + { + WCHAR* aToken = wcstok_s(NULL, L"\\", &nextToken); + + if (aToken) + { + String serialNumberStr, userFriendlyNameStr; + if (!includeEDID || getCompatDisplayEDID(aToken, serialNumberStr, userFriendlyNameStr)) + { + // Set descriptor + OVR::Win32::DisplayDesc& desc = descriptorArray[result++]; + + // If not including EDID, + if (!includeEDID) + { + // If DK2 id, + if (wcsstr(ddm.DeviceID, L"OVR0003")) + { + userFriendlyNameStr = "Rift DK2"; + } + else // Assume DK1 for now: + { + userFriendlyNameStr = "Rift DK1"; + } + } + + desc.DeviceTypeGuess = deviceTypeGuess; + desc.DisplayID = displayDeviceName; + desc.ModelName = userFriendlyNameStr; + desc.EdidSerialNumber = serialNumberStr; + desc.LogicalResolutionInPixels = monitorResolution; + desc.DesktopDisplayOffset = desktopOffset; + + // Hard-coded defaults in case the device doesn't have the data itself. + // DK2 prototypes (0003) or DK HD Prototypes (0002) + if (wcsstr(ddm.DeviceID, L"OVR0003") || wcsstr(ddm.DeviceID, L"OVR0002")) + { + desc.LogicalResolutionInPixels = Sizei(1920, 1080); + desc.NativeResolutionInPixels = Sizei(1080, 1920); + } + else + { + desc.LogicalResolutionInPixels = monitorResolution; + desc.NativeResolutionInPixels = monitorResolution; + } + } + } + } + + if (reportDiscovery) + { + // Only report once per run + OVR_DEBUG_LOG_TEXT(("Display Found %s - %s\n", + deviceId.ToCStr(), displayDeviceName.ToCStr())); + reportDiscovery = false; + } + + free(instanceBuffer); + + break; + } + } + } + + return result; +} + + +//------------------------------------------------------------------------------------- +// ***** Display + +bool Display::InCompatibilityMode() +{ + bool result = false; + OVR::Win32::DisplayDesc displayArray[8]; + + int extendedRiftCount = discoverExtendedRifts(displayArray, 8, false); + if( extendedRiftCount ) + { + result = true; + } + else + { + result = !!GlobalDisplayContext.InCompatibilityMode; + } + + return result; +} + +#define OVR_FLAG_COMPATIBILITY_MODE 1 + +bool Display::Initialize() +{ + HANDLE hDevice = INVALID_HANDLE_VALUE; + + hDevice = CreateFile( L"\\\\.\\ovr_video" , + GENERIC_READ | GENERIC_WRITE, NULL, + NULL, OPEN_EXISTING, NULL, NULL); + + if (hDevice != NULL && hDevice != INVALID_HANDLE_VALUE) + { + GlobalDisplayContext.hDevice = hDevice; + GlobalDisplayContext.InCompatibilityMode = FALSE; + + DWORD bytesReturned = 0; + LONG compatiblityResult = OVR_STATUS_SUCCESS; + + BOOL result = DeviceIoControl( hDevice, IOCTL_RIFTMGR_GETCOMPATIBILITYMODE, NULL, 0, + &compatiblityResult, sizeof( LONG ), &bytesReturned, NULL ); + if (result) + { + if( compatiblityResult & OVR_FLAG_COMPATIBILITY_MODE ) + GlobalDisplayContext.InCompatibilityMode = TRUE; + } + else + { + // If calling our driver fails in any way, assume compatibility mode as well + GlobalDisplayContext.InCompatibilityMode = TRUE; + } + + if (!GlobalDisplayContext.InCompatibilityMode) + { + Ptr<DisplaySearchHandle> searchHandle = *Display::GetDisplaySearchHandle(); + + // If a display is actually connected, bring up the shim layers so we can actually use it + if (GetDisplayCount(searchHandle) > 0) + { + // FIXME: Initializing DX9 with landscape numbers rather than portrait + GlobalDisplayContext.ExpectedWidth = 1080; + GlobalDisplayContext.ExpectedHeight = 1920; + } + else + { + GlobalDisplayContext.InCompatibilityMode = TRUE; + } + + } + } + else + { + GlobalDisplayContext.InCompatibilityMode = TRUE; + } + + return true; +} + +DisplaySearchHandle* Display::GetDisplaySearchHandle() +{ + return new Win32::Win32DisplaySearchHandle(); +} + +// FIXME: The handle parameter will be used to unify GetDisplayCount and GetDisplay calls +// The handle will be written to the 64-bit value pointed and will store the enumerated +// display list. This will allow the indexes to be meaningful between obtaining +// the count. With a single handle the count should be stable +int Display::GetDisplayCount(DisplaySearchHandle* handle, bool extended, bool applicationOnly, bool extendedEDIDSerials) +{ + static int extendedCount = -1; + static int applicationCount = -1; + + Win32::Win32DisplaySearchHandle* localHandle = (Win32::Win32DisplaySearchHandle*)handle; + + if( localHandle == NULL ) + return 0; + + if( extendedCount == -1 || extended ) + { + extendedCount = discoverExtendedRifts(localHandle->cachedDescriptorArray, 16, extendedEDIDSerials); + } + + localHandle->extended = true; + localHandle->extendedDisplayCount = extendedCount; + int totalCount = extendedCount; + + if( applicationCount == -1 || applicationOnly ) + { + applicationCount = getRiftCount(GlobalDisplayContext.hDevice); + localHandle->application = true; + } + + totalCount += applicationCount; + localHandle->applicationDisplayCount = applicationCount; + localHandle->displayCount = totalCount; + + return totalCount; +} + +Ptr<Display> Display::GetDisplay(int index, DisplaySearchHandle* handle) +{ + Ptr<Display> result; + + if( index < 0 ) + return result; + + Win32::Win32DisplaySearchHandle* localHandle = (Win32::Win32DisplaySearchHandle*)handle; + + if( localHandle == NULL ) + return NULL; + + if (localHandle->extended) + { + if (index >= 0 && index < (int)localHandle->extendedDisplayCount) + { + return *new Win32::Win32DisplayGeneric(localHandle->cachedDescriptorArray[index]); + } + + index -= localHandle->extendedDisplayCount; + } + + if(localHandle->application) + { + if (index >= 0 && index < (int)getRiftCount(GlobalDisplayContext.hDevice)) + { + ULONG riftChildId = getRift(GlobalDisplayContext.hDevice, index); + Win32::DisplayEDID dEdid; + + if (!getEdid(GlobalDisplayContext.hDevice, riftChildId, dEdid)) + { + return NULL; + } + + // FIXME: We have the EDID. Let's just use that instead. + uint32_t nativeWidth = 1080; + uint32_t nativeHeight = 1920; + uint32_t logicalWidth = 1920; + uint32_t logicalHeight = 1080; + uint32_t rotation = 0; + + switch (dEdid.ModelNumber) + { + case 0: + case 1: + nativeWidth = 1280; + nativeHeight = 800; + logicalWidth = nativeWidth; + logicalHeight = nativeHeight; + break; + case 2: + case 3: + default: + rotation = 90; + break; + } + + HmdTypeEnum deviceTypeGuess = HmdType_Unknown; + switch (dEdid.ModelNumber) + { + case 3: deviceTypeGuess = HmdType_DK2; break; + case 2: deviceTypeGuess = HmdType_DKHDProto; break; + case 1: deviceTypeGuess = HmdType_DK1; break; + default: break; + } + + result = *new Win32::Win32DisplayDriver( + deviceTypeGuess, + "", + dEdid.MonitorName, + dEdid.SerialNumber, + Sizei(logicalWidth, logicalHeight), + Sizei(nativeWidth, nativeHeight), + Vector2i(0), + dEdid, + GlobalDisplayContext.hDevice, + riftChildId, + rotation); + } + } + return result; +} + +Display::MirrorMode Win32::Win32DisplayDriver::SetMirrorMode( Display::MirrorMode newMode ) +{ + return newMode; +} + +static bool SetDisplayPower(HANDLE hDevice, ULONG childId, int mode) +{ + ULONG_PTR longArray[2]; + + longArray[0] = childId; + longArray[1] = mode; + + ULONG localResult = 0; + DWORD bytesReturned = 0; + + BOOL result = DeviceIoControl(hDevice, + IOCTL_RIFTMGR_DISPLAYPOWER, + longArray, + 2 * sizeof(ULONG_PTR), + &localResult, + sizeof(ULONG), + &bytesReturned, + NULL); + + // Note: bytesReturned does not seem to be set + return result != FALSE /* && bytesReturned == sizeof(ULONG) */ && mode == (int)localResult; +} + +bool Win32::Win32DisplayDriver::SetDisplaySleep(bool sleep) +{ + return SetDisplayPower(hDevice, ChildId, sleep ? 2 : 1); +} + + +} // namespace OVR diff --git a/LibOVR/Src/Displays/OVR_Win32_Display.h b/LibOVR/Src/Displays/OVR_Win32_Display.h new file mode 100644 index 0000000..b5cb03e --- /dev/null +++ b/LibOVR/Src/Displays/OVR_Win32_Display.h @@ -0,0 +1,169 @@ +/************************************************************************************ + +Filename : OVR_Win32_Display.h +Content : Win32-specific Display declarations +Created : May 6, 2014 +Authors : Dean Beeler + +Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. + +Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +you may not use the Oculus VR Rift SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +http://www.oculusvr.com/licenses/LICENSE-3.1 + +Unless required by applicable law or agreed to in writing, the Oculus VR SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*************************************************************************************/ + +#ifndef OVR_Win32_Display_h +#define OVR_Win32_Display_h + +#include "OVR_Display.h" + +namespace OVR { namespace Win32 { + + +//------------------------------------------------------------------------------------- +// DisplayDesc + +// Display information enumerable through Win32. +// TBD: Should we just move this to public header, so it's a const member of Display? +struct DisplayDesc +{ + HmdTypeEnum DeviceTypeGuess; // This is a guess about what type of HMD it is connected to + String DisplayID; // This is the device identifier string from MONITORINFO (for app usage) + String ModelName; // This is a "DK2" type string + String EdidSerialNumber; + Sizei LogicalResolutionInPixels; + Sizei NativeResolutionInPixels; + Vector2i DesktopDisplayOffset; +}; + + +//------------------------------------------------------------------------------------- +// DisplayEDID + +// Describes EDID information as reported from our display driver. +struct DisplayEDID +{ + String MonitorName; + UINT16 ModelNumber; + String VendorName; + String SerialNumber; +}; + +class Win32DisplaySearchHandle : public DisplaySearchHandle +{ +public: + static const int ArraySize = 16; + + Win32::DisplayDesc cachedDescriptorArray[ArraySize]; + bool extended; + bool application; + int extendedDisplayCount; + int applicationDisplayCount; + int displayCount; + + Win32DisplaySearchHandle() + { + } + virtual ~Win32DisplaySearchHandle() + { + } +}; + +//------------------------------------------------------------------------------------- +// Win32DisplayGeneric + +// Describes Win32 display in Compatibility mode, containing basic data +class Win32DisplayGeneric : public Display +{ +public: + Win32DisplayGeneric( const DisplayDesc& dd ) : + Display(dd.DeviceTypeGuess, + dd.DisplayID, + dd.ModelName, + dd.EdidSerialNumber, + dd.LogicalResolutionInPixels, + dd.NativeResolutionInPixels, + dd.DesktopDisplayOffset, + 0, + 0, + false) + { + } + + virtual ~Win32DisplayGeneric() + { + } + + // Generic displays are not capable of mirroring + virtual MirrorMode SetMirrorMode( MirrorMode newMode ) + { + OVR_UNUSED( newMode ); + return MirrorDisabled; + } +}; + + +//------------------------------------------------------------------------------------- +// Win32DisplayDriver + +// Oculus driver based display object. +class Win32DisplayDriver : public Display +{ + HANDLE hDevice; + ULONG ChildId; + DisplayEDID Edid; + +public: + Win32DisplayDriver(const HmdTypeEnum deviceTypeGuess, + const String& displayID, + const String& modelName, + const String& edidSerial, + const Sizei& logicalRes, + const Sizei& nativeRes, + const Vector2i& displayOffset, + const DisplayEDID& edid, + HANDLE hdevice, + ULONG child, + uint32_t rotation) : + Display(deviceTypeGuess, + displayID, + modelName, + edidSerial, + logicalRes, + nativeRes, + displayOffset, + child, + rotation, + true), + hDevice(hdevice), + ChildId(child), + Edid(edid) + { + } + + virtual ~Win32DisplayDriver() + { + } + + virtual MirrorMode SetMirrorMode( MirrorMode newMode ); + + // Support sleep/wake + virtual bool SetDisplaySleep(bool off); +}; + + +}} // namespace OVR::Win32 + +#endif // OVR_Win32_Display_h diff --git a/LibOVR/Src/Displays/OVR_Win32_Dxgi_Display.h b/LibOVR/Src/Displays/OVR_Win32_Dxgi_Display.h new file mode 100644 index 0000000..ab1582c --- /dev/null +++ b/LibOVR/Src/Displays/OVR_Win32_Dxgi_Display.h @@ -0,0 +1,413 @@ +/************************************************************************************ + +PublicHeader: None +Filename : dxgi_ovr_filter.h +Content : Shared usermode/kernel mode definitions for IOCTL functionality. + Also used from LibOVR to access the driver. +Created : January 27, 2014 +Authors : Dean Beeler + +Copyright : Copyright 2013 Oculus, LLC. All Rights reserved. + +Use of this software is subject to the terms of the Oculus LLC license +agreement provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +/************************************************************************************/ + +#ifndef OVR_dxgi_ovr_filter_h +#define OVR_dxgi_ovr_filter_h + +#include <InitGuid.h> + +#define USERMODE_TEST_ROTATION 1 + +#if USERMODE_TEST_ROTATION // Used only by the um test application +#define USERMODE_SURFACE_WIDTH 1920 +#define USERMODE_SURFACE_HEIGHT 1080 +#else +#define USERMODE_SURFACE_WIDTH 1080 +#define USERMODE_SURFACE_HEIGHT 1920 +#endif + +#define TEST_ROTATION 0 // Kernel-mode parameters + +#if TEST_ROTATION +#define SURFACE_WIDTH 1920 +#define SURFACE_HEIGHT 1080 +#else +#define SURFACE_WIDTH 1080 +#define SURFACE_HEIGHT 1920 +#endif + +// {46231713-49FD-4922-84E3-9FF907C06803} +DEFINE_GUID(GUID_DEVINTERFACE_OVRRIFTMGR, + 0x46231713, 0x49fd, 0x4922, 0x84, 0xe3, 0x9f, 0xf9, 0x7, 0xc0, 0x68, 0x3); + +#define QUERYADAPTER_MAGICSIZE 17836 +#define QUERYADAPTER_MAGICHEADER 0x4f565246 // OVRF +#define QUERYADAPTER_MAXPATH 2048 + +#define FUNCTION_INDEX 0xb800 + +#pragma pack(push,1) + +#define OVR_RIFT_MODE_OFF 0 // Disabled +#define OVR_RIFT_MODE_ENABLED 1 // Enabled +#define OVR_RIFT_MODE_EXTEND 2 // Extending 2D displays. Without this flag + // 2D displays are disabled when the Rift + // is active +#define OVR_RIFT_MODE_FRONTBUFFER 4 // Enable front buffer only for Rift +#define OVR_RIFT_MODE_LOCKMOUSE 8 // Prevent mouse from entering bounds + +#define OVR_ESCAPE_TYPE_HANDLE 1 // Escape to notify driver of our collected handles + +#define OVR_FlipImmediate 0x2 +#define OVR_FlipOnNextVSync 0x4 + +//----------------------------------------------------------------------------------- +// Structures for application to UM driver + +// Kernel32.dll functionality +typedef HMODULE (WINAPI *WinLoadLibraryA) ( LPCSTR ); +typedef HMODULE (WINAPI *WinLoadLibraryW) ( LPCWSTR ); +typedef HMODULE (WINAPI *WinLoadLibraryExA) ( LPCSTR, HANDLE, DWORD ); +typedef HMODULE (WINAPI *WinLoadLibraryExW) ( LPCWSTR, HANDLE, DWORD ); +typedef BOOL (WINAPI *WinGetModuleHandleExA)( DWORD, LPCSTR, HMODULE* ); +typedef BOOL (WINAPI *WinGetModuleHandleExW)( DWORD, LPCWSTR, HMODULE* ); + +// Overridden DirectX 9 entry points +typedef void* (WINAPI *WinDirect3DCreate9)(UINT SDKVersion); +typedef HRESULT (WINAPI *WinDirect3DCreate9Ex)(UINT SDKVersion, void** aDevice); + +// Overridden DXGI entry points +typedef HRESULT (WINAPI *WinCreateDXGIFactory)( + __in REFIID riid, + __out void **ppFactory + ); + +typedef HRESULT (WINAPI *WinCreateDXGIFactory1)( + __in REFIID riid, + __out void **ppFactory + ); + +typedef HRESULT (WINAPI *WinCreateDXGIFactory2)( + __in UINT flags, + __in const IID &riid, + __out void **ppFactory + ); + +// Application usermode callbacks from usermode driver. These +// functions are all provided by the calling application that uses +// the filter mode driver + +// IsInitializingDisplay is used at runtime to validate that +// the created resource (RT or bind_present) matches the resolution +// of our expected backbuffer. If the application returns true, +// our usermode driver will convert this to a primary +typedef BOOL (WINAPI *IsInitializingDisplay) ( PVOID, UINT, UINT ); +// RiftForContext is a function that will return the Rift device of +// the concerned context. This is for targeting a particular +// device instance with a particular Rift for rendering +typedef ULONG (WINAPI *RiftForContext)( PVOID, HANDLE ); +// CloseRiftForContext is a function that informs the application +// the created device is shutting down and the context +// can freedly disassociate with the particular +typedef BOOL (WINAPI *CloseRiftForContext)( PVOID, HANDLE, ULONG ); +typedef BOOL (WINAPI *WindowDisplayResolution)( PVOID, UINT*, UINT*, UINT*, UINT*, BOOL* ); +// IsCreatingBackBuffer is a function directed at the runtime shim +// to confirm that the runtime is actively creating the additional +// swapchain for rotation and display out to the rift. +// When creating the original swapchain this function should return false +// so the orignal swapchain isn't inadvertantly coopted. +typedef BOOL (WINAPI *IsCreatingBackBuffer)( PVOID ); +// Callback from the usermode driver to obtain the desire to see debug statements from +// the usermode drivers on the output console. Only called one per usermode driver shim +// and usermode runtime. +typedef BOOL (WINAPI *ShouldEnableDebug)( VOID ); +// Callback from the usermode driver to the runtime obtain the vsync status +typedef BOOL (WINAPI *ShouldVSync)( VOID ); +// Callback from usermode mode and runtime driver to obtain expected native width, +// height and degrees rotation of the rift +typedef BOOL (WINAPI *ExpectedResolution)( PVOID, UINT*, UINT*, UINT* ); +// Usermode callback that reports whether or not mirroring is enabled +typedef BOOL (WINAPI *MirroringEnabled)( PVOID ); +// Callback from the shim for Unity and other plugins used to +// report the swapchain that was created by the application +typedef void* (WINAPI *GetDX11SwapChain)( PVOID ); +// Callback to report the HWND associated with this context +typedef HWND (WINAPI* GetWindowForContext)( PVOID ); +// Should present Rift on context +typedef BOOL (WINAPI* PresentRiftOnContext)( PVOID ); +// Used by a pre-loaded shim (d3d9, dxgi, opengl32) to +// identify which api version we loaded +// 1 = OpenGL +// 9 = DirectX 9 +// 10 = DirectX 1X +typedef int (WINAPI* ActiveAPIVersion)( PVOID ); + +#pragma warning(push) +#pragma warning(disable: 4201) + +typedef struct _LINK_APPLICATION_DRIVER +{ + UINT32 version; + PVOID context; + + union + { + struct + { + IsInitializingDisplay pfnInitializingDisplay; + RiftForContext pfnRiftForContext; + CloseRiftForContext pfnCloseRiftForContext; + WindowDisplayResolution pfnWindowDisplayResolution; + IsCreatingBackBuffer pfnIsCreatingBackBuffer; + ShouldEnableDebug pfnShouldEnableDebug; + ShouldVSync pfnShouldVSync; + ExpectedResolution pfnExpectedResolution; + MirroringEnabled pfnMirroringEnabled; + GetDX11SwapChain pfnGetDX11SwapChain; + GetWindowForContext pfnGetWindowForContext; + PresentRiftOnContext pfnPresentRiftOnContext; + ActiveAPIVersion pfnActiveAPIVersion; + }; + + PROC placeholders[128]; + }; + + + // Used by Runtime filter for linking with original libraries + WinDirect3DCreate9 pfnDirect3DCreate9; + WinDirect3DCreate9Ex pfnDirect3DCreate9Ex; + WinCreateDXGIFactory pfnCreateDXGIFactory; + WinCreateDXGIFactory1 pfnCreateDXGIFactory1; + WinCreateDXGIFactory2 pfnCreateDXGIFactory2; +} LINK_APPLICATION_DRIVER, *PLINK_APPLICATION_DRIVER; + +#pragma warning(pop) + + +// OVRDisplay.dll functionality +typedef HRESULT (WINAPI *PreloadLibraryFn) ( WinLoadLibraryA , LPCSTR, PLINK_APPLICATION_DRIVER appDriver ); +typedef HRESULT (WINAPI *PreloadLibraryRTFn) ( PLINK_APPLICATION_DRIVER appDriver ); + +//----------------------------------------------------------------------------------- +// Structures for UM driver to KM driver + +typedef struct _QUERY_KM_DRIVER +{ + UINT32 magic; // Friend or foe identifier for our filter driver + // See: QUERYADAPTER_MAGICHEADER + UINT32 maxVidPnSources; // Returns the maximum number of video present network sources +} QUERY_KM_DRIVER, *PQUERY_KM_DRIVER; + +#ifndef _D3DUKMDT_H_ +typedef UINT D3DKMT_HANDLE; +#endif + +typedef struct _HandleNotepad +{ + // These are assigned around CreateResource + HANDLE hUsermodeInResource; + HANDLE hUsermodeOutResource; + + // These are assigned within the kernel with + // DxgkDdiCreateAllocation and + // DxgkDdiOpenAllocation + D3DKMT_HANDLE hAllocation; + PVOID hDeviceSpecificHandle; + PVOID hKernelDriverHandle; + + // These are assigned around pfnAllocateCb + HANDLE hUsermodeSharedResource; + D3DKMT_HANDLE hKernelModeSharedResource; + + ULONG childUid; + + UINT pitch; + +} HandleNotepad, *PHandleNotepad; + + +typedef struct _ALLOC_PRIVATE_STRUCTURE +{ + UINT32 magic; // Friend or foe identifier for our filter driver + + PVOID originalPrivataDataPtr; // Location in usermode of the original private data structure + UINT originalPrivateSize; // Size of private data structure at the end of this header + + PVOID hAllocationHandle; // User-mode-assigned allocation handle for CreateAllocation + PVOID hDeviceSpecificHandle; // Assigned in kernal OpenAllocation + PVOID hInternalHandle; // Assigned in kernal CreateAllocation + UINT pitch; // Hinted surface pitch + + BYTE originalPrivateData[1]; // Variable length + + +} ALLOC_PRIVATE_STRUCTURE, *PALLOC_PRIVATE_STRUCTURE; + +typedef struct _ESCAPE_STRUCTURE +{ + UINT32 magic; // Friend or foe identifier for our filter driver + + UINT32 escapeType; // Specifier for individual type of escape message + // Type 1 for notepad + union { + HandleNotepad notepad; + }; +} ESCAPE_STRUCTURE, *PESCAPE_STRUCTURE; + +// Structures for internal operation of KM driver + +typedef struct _RIFT_SYNC +{ + ULONG childUid; // ChildUid as reported by RIFT_STATUS + ULONG vsync; // 1 for vsync, 0 for immediate +} RIFT_SYNC, *PRIFT_SYNC; + +typedef struct _RIFT_MODE +{ + ULONG childUid; // ChildUid as reported by RIFT_STATUS + ULONG mode; // Bitmap of mode values, defined by OVR_RIFT_HOME_* + HANDLE userModeHandle; // Handle of render target created in user mode + // that's usable as a primary +} RIFT_MODE, *PRIFT_MODE; + +typedef struct _RIFT_STATUS +{ + ULONG childUid; // Display driver assigned Uid for this display + ULONG mode; // Active rift mode, see OVR_RIFT_MODE_* + ULONG serialNumber; // Serial number as reported in the Rift's EDID + ULONG textureHandle; // Handle of shared render resource -- NULL if not shared +} RIFT_STATUS, *PRIFT_STATUS; + +typedef struct _RIFT_STATUS_ARRAY +{ + ULONG arraySize; // Size of pre-allocated RIFT_STATUS structures. + RIFT_STATUS status[1]; // Array of status blocks containing connection information on each Rift +} RIFT_STATUS_ARRAY, *PRIFT_STATUS_ARRAY; + +#pragma pack(pop) + +// IOCTL for UM application to KM driver + +#define OVR_STATUS_SUCCESS 0 +#define OVR_STATUS_FAIL -1 +#define OVR_STATUS_DRIVER_IN_USE -2 +#define OVR_STATUS_MODE_ALREADY_ACTIVE -3 +#define OVR_STATUS_RIFT_NOT_PRESENT -4 + +// +// Returns the number of Rift displays attached to the video adapter +// If 0, no Rift displays have been connected. +// If greater than 0, use this size to pre-allocate space for an array +// of rift statuses +// +// Input Buffer: Nothing +// Output Buffer: LONG - count of Rift displays attached to video adapter +// +#define IOCTL_RIFTMGR_GET_RIFT_COUNT CTL_CODE(FILE_DEVICE_VIDEO, \ + FUNCTION_INDEX, METHOD_BUFFERED, FILE_ANY_ACCESS) + +// +// Fills out a pre-allocated array with information on the individually attached +// screens. +// +// On Input, specify the arraySize as the size of the allocation. +// +// On Output, the arraySize will be updated with the actual number of Rifts +// reported. Use IOCTL_RIFTMGR_GET_RIFT_COUNT to query the number of Rifts. +// If the count changes (added or removed) between calls, the function will either fail +// due to the buffer being too small, or the arraySize count will be updated +// with a new count of devices along with their respective parameters. +// +// Input Buffer: PRIFT_STATUS - Pointer to allocated status array +// Output Buffer: LONG - Count of Rift displays reported in the structure. -1 if out of +// memory +// +#define IOCTL_RIFTMGR_GET_RIFT_ARRAY CTL_CODE(FILE_DEVICE_VIDEO, \ + FUNCTION_INDEX + 1, METHOD_NEITHER, FILE_ANY_ACCESS) + +// Changes the mode of an attached Rift (DEPRECATED) +// Input Buffer: PRIFT_MODE - Pointer to a mode structure specifying the childUid and +// mode for a particular Rift +// Output Buffer: LONG - Non-zero on error, 0 on successful mode change +// +#define IOCTL_RIFTMGR_SET_RIFT_MODE CTL_CODE(FILE_DEVICE_VIDEO, \ + FUNCTION_INDEX + 2, METHOD_NEITHER, FILE_ANY_ACCESS) + +// Lock the primary of the rift and obtain an address +// Input Buffer: ULONG - ChildUid of a Rift as previously discovered +// Output Buffer: ULONG_PTR - Pointer to a usermode mapped address of the primary +#define IOCTL_RIFTMGR_GET_RIFT_PRIMARY CTL_CODE(FILE_DEVICE_VIDEO, \ + FUNCTION_INDEX + 3, METHOD_NEITHER, FILE_ANY_ACCESS) + +// Release Rift primary +// Input Buffer: PULONG_PTR - ChildUid of a Rift as previously discovered and virtual pointer +// Output Buffer: NOTHING +#define IOCTL_RIFTMGR_RELEASE_RIFT_PRIMARY CTL_CODE(FILE_DEVICE_VIDEO, \ + FUNCTION_INDEX + 4, METHOD_NEITHER, FILE_ANY_ACCESS) + + +// Point the rift to another render target +// Input Buffer: PHANDLE - Array of handles, rift and the render target resource +// Output Buffer: NOTHING +#define IOCTL_RIFTMGR_SETRIFTBUFFER CTL_CODE(FILE_DEVICE_VIDEO, \ + FUNCTION_INDEX + 5, METHOD_NEITHER, FILE_ANY_ACCESS) + +// Enable or disable vsync on Rift present +// Input Buffer: PRIFT_SYNC - Pointer to a mode structure specifying the childUid and +// and sync +// Output Buffer: NOTHING +#define IOCTL_RIFTMGR_SETVSYNCMODE CTL_CODE(FILE_DEVICE_VIDEO, \ + FUNCTION_INDEX + 6, METHOD_NEITHER, FILE_ANY_ACCESS) + +// Get scan line +// Input Buffer: ULONG - ChildUid of a Rift as previously discovered +// Output Buffer: ULONG - 31st bit is set if in vertical blank, high 15 bits has per second +// frame number (0-74), low 16 bits has scanline (0-1919) +#define IOCTL_RIFTMGR_GETSCANLINE CTL_CODE(FILE_DEVICE_VIDEO, \ + FUNCTION_INDEX + 7, METHOD_NEITHER, FILE_ANY_ACCESS) + +// Enable or disable compatibility mode. Entering compatibility mode will fail if +// the Rift is already actively scanning out a surface +// Input Buffer: BOOL - Nonzero if compatibility mode is desired, zero if it's not +// Output Buffer: LONG - Result value (see OVR statuses) +// 0 = success +// -1 = general failure +// -2 = failure, rift scanning out +#define IOCTL_RIFTMGR_SETCOMPATIBILITYMODE CTL_CODE(FILE_DEVICE_VIDEO, \ + FUNCTION_INDEX + 8, METHOD_NEITHER, FILE_ANY_ACCESS) + +// Call to obtain the current status of compatibility mode +// Input Buffer: NOTHING +// Output Buffer: LONG - Result value +// 0 = Not in compatibility mode +// Non-zero = In compatibility mode +#define IOCTL_RIFTMGR_GETCOMPATIBILITYMODE CTL_CODE(FILE_DEVICE_VIDEO, \ + FUNCTION_INDEX + 9, METHOD_NEITHER, FILE_ANY_ACCESS) + +// Call to set the power mode of a particular Rift +// Input Buffer: PULONG_PTR - ChildUid of a Rift as previously discovered and ULONG value +// second ULONG has value of +// 0 to simply obtain the power status of the display +// 1 to set the display into a full power state (needs a primary to fully scan out) +// 2 to set the display into sleep mode +// 3 to set the display into full power off mode (WARNING: Will potentially trash primary) +// Output Buffer: LONG - Result value +// 0 = Failure to obtain power status +// 1 = Full power +// 2 = Sleep +// 3 = Power off +#define IOCTL_RIFTMGR_DISPLAYPOWER CTL_CODE(FILE_DEVICE_VIDEO, \ + FUNCTION_INDEX + 10, METHOD_NEITHER, FILE_ANY_ACCESS) + +// Return the EDID of the display in the output buffer. The driver +// will copy as many bytes as possible to fill the buffer. +// Input Buffer: ULONG - ChildUid of a Rift as previously discovered +// Output Buffer: PCHAR - Preallocated buffer of a variable size to store the EDID from the display +#define IOCTL_RIFTMGR_GETEDID CTL_CODE(FILE_DEVICE_VIDEO, \ + FUNCTION_INDEX + 11, METHOD_NEITHER, FILE_ANY_ACCESS) + +#endif
\ No newline at end of file diff --git a/LibOVR/Src/Displays/OVR_Win32_FocusReader.cpp b/LibOVR/Src/Displays/OVR_Win32_FocusReader.cpp new file mode 100644 index 0000000..852e29e --- /dev/null +++ b/LibOVR/Src/Displays/OVR_Win32_FocusReader.cpp @@ -0,0 +1,80 @@ +/************************************************************************************ + +Filename : OVR_Win32_FocusReader.cpp +Content : Reader for current app with focus on Windows +Created : July 2, 2014 +Authors : Chris Taylor + +Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. + +Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +you may not use the Oculus VR Rift SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +http://www.oculusvr.com/licenses/LICENSE-3.1 + +Unless required by applicable law or agreed to in writing, the Oculus VR SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*************************************************************************************/ + +#include "OVR_Win32_FocusReader.h" +#include "../Kernel/OVR_Log.h" +#include "../Service/Service_NetClient.h" + +OVR_DEFINE_SINGLETON(OVR::Win32::RenderFocusReader); + +namespace OVR { namespace Win32 { + + +HWND RenderFocusReader::ReadActiveWindow() +{ + FocusState = Reader.Get(); + if (!FocusState || NoSharedMemory) + { + if (!Reader.Open(OVR_FOCUS_OBSERVER_SHARE_NAME)) + { + OVR_DEBUG_LOG(("[Win32ShimFunctions] Unable to open the shared memory space")); + // Note: This should only warn and not assert because it is normal behavior when the server is not running. + NoSharedMemory = true; + return 0; + } + + FocusState = Reader.Get(); + if (!FocusState) + { + OVR_DEBUG_LOG(("[Win32ShimFunctions] Unable to get the shared memory space")); + NoSharedMemory = true; + return 0; + } + } + + return (HWND)Ptr64ToPtr(FocusState->ActiveWindowHandle); +} + +RenderFocusReader::RenderFocusReader() +{ + NoSharedMemory = false; + + PushDestroyCallbacks(); +} + +RenderFocusReader::~RenderFocusReader() +{ +} + +void RenderFocusReader::OnSystemDestroy() +{ + delete this; +} + + + + +}} // namespace OVR::Win32 diff --git a/LibOVR/Src/Displays/OVR_Win32_FocusReader.h b/LibOVR/Src/Displays/OVR_Win32_FocusReader.h new file mode 100644 index 0000000..f62b8de --- /dev/null +++ b/LibOVR/Src/Displays/OVR_Win32_FocusReader.h @@ -0,0 +1,82 @@ +/************************************************************************************ + +Filename : OVR_Win32_FocusReader.h +Content : Reader for current app with focus on Windows +Created : July 2, 2014 +Authors : Chris Taylor + +Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. + +Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +you may not use the Oculus VR Rift SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +http://www.oculusvr.com/licenses/LICENSE-3.1 + +Unless required by applicable law or agreed to in writing, the Oculus VR SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*************************************************************************************/ + +#ifndef OVR_Win32_FocusReader_h +#define OVR_Win32_FocusReader_h + +#include "../Kernel/OVR_System.h" +#include "../Kernel/OVR_Lockless.h" +#include "../Kernel/OVR_Array.h" +#include "../Kernel/OVR_SharedMemory.h" + +namespace OVR { namespace Win32 { + + +#define OVR_FOCUS_OBSERVER_SHARE_NAME "OVRAppFocus" + +//----------------------------------------------------------------------------- +// LocklessFocusState + +#pragma pack(push, 8) + +// Focus state data +struct LocklessFocusState +{ + LocklessFocusState(DWORD pid = 0) : + ActiveProcessId(pid), + ActiveWindowHandle(NULL) + { + } + + DWORD ActiveProcessId; + void * POINTER_64 ActiveWindowHandle; +}; + +#pragma pack(pop) + +typedef SharedObjectWriter< LocklessFocusState > SharedFocusWriter; +typedef SharedObjectReader< LocklessFocusState > SharedFocusReader; + + +//----------------------------------------------------------------------------- +// RenderFocusReader + +class RenderFocusReader : public OVR::SystemSingletonBase<RenderFocusReader> +{ + OVR_DECLARE_SINGLETON(RenderFocusReader); + + SharedFocusReader Reader; // Shared memory reader + const LocklessFocusState* FocusState; // Pointer to the current focus state + bool NoSharedMemory; // Flag reporting that no shared memory has been detected; + +public: + HWND ReadActiveWindow(); +}; + + +}} // namespace OVR::Win32 + +#endif // OVR_Win32_FocusReader_h diff --git a/LibOVR/Src/Displays/OVR_Win32_RenderShim.cpp b/LibOVR/Src/Displays/OVR_Win32_RenderShim.cpp new file mode 100644 index 0000000..a58e40d --- /dev/null +++ b/LibOVR/Src/Displays/OVR_Win32_RenderShim.cpp @@ -0,0 +1,788 @@ +/************************************************************************************ + +Filename : OVR_Win32_DisplayShim.cpp +Content : Shared static functions for inclusion that allow for an application + to inject the usermode driver into an application +Created : March 21, 2014 +Authors : Dean Beeler + +Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. + +Use of this software is subject to the terms of the Oculus Inc license +agreement provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +************************************************************************************/ + +#include <windows.h> +#include <DbgHelp.h> +#include <AtlBase.h> +#include <AtlConv.h> + +#include "OVR_Win32_Dxgi_Display.h" + +#if AVOID_LIB_OVR +#define IN_COMPATIBILITY_MODE() (0) +#else +#include "OVR_Win32_Display.h" +#define IN_COMPATIBILITY_MODE() OVR::Display::InCompatibilityMode() +#endif + +#pragma comment(lib, "DbgHelp.lib") + +// Forward declarations +// These functions are implemented in OVR_Win32_DisplayDevice.cpp. + +BOOL WINAPI OVRIsInitializingDisplay( PVOID context, UINT width, UINT height ); +BOOL WINAPI OVRIsCreatingBackBuffer( PVOID context ); +BOOL WINAPI OVRShouldVSync( ); +ULONG WINAPI OVRRiftForContext( PVOID context, HANDLE driverHandle ); +BOOL WINAPI OVRCloseRiftForContext( PVOID context, HANDLE driverHandle, ULONG rift ); +BOOL WINAPI OVRWindowDisplayResolution( PVOID context, UINT* width, UINT* height, + UINT* titleHeight, UINT* borderWidth, + BOOL* vsyncEnabled ); +BOOL WINAPI OVRExpectedResolution( PVOID context, UINT* width, UINT* height, UINT* rotationInDegrees ); +BOOL WINAPI OVRShouldEnableDebug(); +BOOL WINAPI OVRMirroringEnabled( PVOID context ); +HWND WINAPI OVRGetWindowForContext(PVOID context); +BOOL WINAPI OVRShouldPresentOnContext(PVOID context); + +static const char* GFX_DRIVER_KEY_FMT = "SYSTEM\\CurrentControlSet\\Control\\Class\\{4d36e968-e325-11ce-bfc1-08002be10318}\\%04d"; +#ifdef _WIN64 +static const char* RTFilter = "OVRDisplayRT64.dll"; +static const char* UMFilter = "OVRDisplay64.dll"; +#else +static const char* RTFilter = "OVRDisplayRT32.dll"; +static const char* UMFilter = "OVRDisplay32.dll"; +#endif +static const char* OptimusDrivers = "nvumdshimx.dll nvumdshim.dll"; + +typedef enum OVRTargetAPI +{ + DirectX, + OpenGL +}; + +static PVOID lastContext = NULL; +LINK_APPLICATION_DRIVER appDriver = {0}; +static INT apiVersion = 10; + +static CHAR* ReadRegStr(HKEY keySub, const char* keyName, const char* valName) +{ + CHAR *val = NULL; + REGSAM access = KEY_READ; + HKEY hKey; + +TryAgainWOW64: + NTSTATUS res = RegOpenKeyExA( keySub, keyName, 0, access, &hKey ); + if ( res == ERROR_SUCCESS ) + { + DWORD valLen; + res = RegQueryValueExA( hKey, valName, NULL, NULL, NULL, &valLen ); + if( res == ERROR_SUCCESS ) { + val = (CHAR*)calloc( valLen + 1, sizeof(CHAR) ); + res = RegQueryValueExA( hKey, valName, NULL, NULL, (LPBYTE)val, &valLen ); + + if( res == ERROR_SUCCESS ) + { + CHAR* byte = val; + for( DWORD j = 0; j < valLen; ++j ) + { + if( byte[j] == 0 ) + byte[j] = ' '; + } + } + else + { + free( val ); + val = NULL; + } + } + RegCloseKey( hKey ); + } + + if( res == ERROR_FILE_NOT_FOUND && keySub == HKEY_LOCAL_MACHINE && access == KEY_READ ) { +#ifdef _WIN64 + access = KEY_READ | KEY_WOW64_32KEY; +#else + access = KEY_READ | KEY_WOW64_64KEY; +#endif + goto TryAgainWOW64; + } + return val; +} + +#define OLD_DATA_BACKUP_SIZE 16 + +WinLoadLibraryA oldProcA = NULL; +WinLoadLibraryExA oldProcExA = NULL; +WinLoadLibraryW oldProcW = NULL; +WinLoadLibraryExW oldProcExW = NULL; +WinGetModuleHandleExA oldProcModExA = NULL; +WinGetModuleHandleExW oldProcModExW = NULL; +WinDirect3DCreate9 oldDirectX9Create = NULL; +BYTE oldDirectX9CreateData[OLD_DATA_BACKUP_SIZE]; +WinDirect3DCreate9Ex oldDirectX9ExCreate = NULL; +BYTE oldDirectX9ExCreateData[OLD_DATA_BACKUP_SIZE]; +WinCreateDXGIFactory oldCreateDXGIFactory = NULL; +BYTE oldCreateDXGIFactoryData[OLD_DATA_BACKUP_SIZE]; +WinCreateDXGIFactory1 oldCreateDXGIFactory1 = NULL; +BYTE oldCreateDXGIFactory1Data[OLD_DATA_BACKUP_SIZE]; +WinCreateDXGIFactory2 oldCreateDXGIFactory2 = NULL; +BYTE oldCreateDXGIFactory2Data[OLD_DATA_BACKUP_SIZE]; + +static bool checkForOverride( LPCSTR libFileName, OVRTargetAPI& targetApi ) +{ + for (int i=0; ; i++) + { + CHAR keyString[256] = {0}; + + sprintf_s( keyString, 256, GFX_DRIVER_KEY_FMT, i ); + + CHAR* providerName = ReadRegStr( HKEY_LOCAL_MACHINE, keyString, "ProviderName" ); + + // No provider name means we're out of display enumerations + if( providerName == NULL ) + break; + + free( providerName ); + + // Check 64-bit driver names followed by 32-bit driver names + const char* driverKeys[] = {"UserModeDriverName", "UserModeDriverNameWoW", "OpenGLDriverName", "OpenGLDriverNameWoW", "InstalledDisplayDrivers" }; + for( int j = 0; j < 6; ++j ) + { + CHAR userModeList[4096] = {0}; + + switch(j) + { + case 5: + strcpy_s( userModeList, 4095, OptimusDrivers ); + break; + default: + { + CHAR* regString = ReadRegStr( HKEY_LOCAL_MACHINE, keyString, driverKeys[j] ); + if( regString ) + { + strcpy_s( userModeList, 4095, regString ); + free( regString ); + } + + } + break; + } + + char *nextToken = NULL; + + if( userModeList ) + { + char* first = strtok_s( userModeList, " ", &nextToken ); + while( first ) + { + if( strstr( libFileName, first ) != 0 ) + { + if( j < 2 ) + targetApi = DirectX; + else + targetApi = OpenGL; + + return true; + } + first = strtok_s( NULL, " ", &nextToken ); + } + } + } + } + + return false; +} + +static HMODULE createShim( LPCSTR lpLibFileName, OVRTargetAPI targetAPI ) +{ + //Sleep(10000); + if( IN_COMPATIBILITY_MODE() ) + { + return (*oldProcA)( lpLibFileName ); + } + + UNREFERENCED_PARAMETER( targetAPI ); + + HMODULE result = NULL; + + result = (*oldProcA)( UMFilter ); + + if( result ) + { + PreloadLibraryFn loadFunc = (PreloadLibraryFn)GetProcAddress( result, "PreloadLibrary" ); + if( loadFunc ) + { + HRESULT localRes = (*loadFunc)( oldProcA, lpLibFileName, &appDriver ); + if( localRes != S_OK ) + result = NULL; + } + } + + if( !result ) + { + OutputDebugString( L"createShim: unable to load usermode filter\n" ); + result = (*oldProcA)( lpLibFileName ); + } + return result; +} + +static HMODULE + WINAPI + OVRLoadLibraryA( + __in LPCSTR lpLibFileName + ) +{ + OVRTargetAPI targetAPI = DirectX; + bool needShim = checkForOverride( lpLibFileName, targetAPI ); + if( !needShim ) + return (*oldProcA)( lpLibFileName ); + + return createShim( lpLibFileName, targetAPI ); +} + +static HMODULE + WINAPI + OVRLoadLibraryW( + __in LPCWSTR lpLibFileName + ) +{ + USES_CONVERSION; + + OVRTargetAPI targetAPI = DirectX; + + bool needShim = checkForOverride( W2A( lpLibFileName ), targetAPI ); + if( !needShim ) + return (*oldProcW)( lpLibFileName ); + + return createShim( W2A( lpLibFileName ), targetAPI ); +} + +static HMODULE + WINAPI + OVRLoadLibraryExA( + __in LPCSTR lpLibFileName, + __reserved HANDLE hFile, + __in DWORD dwFlags + + ) +{ + OVRTargetAPI targetAPI = DirectX; + + bool needShim = checkForOverride( lpLibFileName, targetAPI ); + if( !needShim ) + return (*oldProcExA)( lpLibFileName, hFile, dwFlags ); + + // FIXME: Don't throw away the flags parameter + return createShim( lpLibFileName, targetAPI ); +} + +static HMODULE + WINAPI + OVRLoadLibraryExW( + __in LPCWSTR lpLibFileName, + __reserved HANDLE hFile, + __in DWORD dwFlags + ) +{ + USES_CONVERSION; + + OVRTargetAPI targetAPI = DirectX; + + bool needShim = checkForOverride( W2A( lpLibFileName ), targetAPI ); + if( !needShim ) + return (*oldProcExW)( lpLibFileName, hFile, dwFlags ); + + // FIXME: Don't throw away the flags parameter + return createShim( W2A( lpLibFileName ), targetAPI ); +} + +static BOOL WINAPI OVRGetModuleHandleExA( + __in DWORD dwFlags, + __in_opt LPCSTR lpModuleName, + __out HMODULE *phModule + ) +{ + OVRTargetAPI targetAPI = DirectX; + + bool needShim = checkForOverride( lpModuleName, targetAPI ); + if( !needShim ) + { + return (*oldProcModExA)( dwFlags, lpModuleName, phModule ); + } + + *phModule = createShim( lpModuleName, targetAPI ); + + return TRUE; +} + +static BOOL WINAPI OVRGetModuleHandleExW( + __in DWORD dwFlags, + __in_opt LPCWSTR lpModuleName, + __out HMODULE *phModule + ) +{ + USES_CONVERSION; + + OVRTargetAPI targetAPI = DirectX; + + bool needShim = checkForOverride( W2A( lpModuleName ), targetAPI ); + if( !needShim ) + { + return (*oldProcModExW)( dwFlags, lpModuleName, phModule ); + } + + *phModule = createShim( W2A( lpModuleName ), targetAPI ); + + return TRUE; +} + +#ifdef _AMD64_ +static void restoreFunction( PROC pfnHookAPIAddr, PBYTE oldData ) +{ + static const LONGLONG addressSize = sizeof(PROC); + static const LONGLONG jmpSize = addressSize + 6; + + DWORD oldProtect; + VirtualProtect((LPVOID)pfnHookAPIAddr, OLD_DATA_BACKUP_SIZE, + PAGE_EXECUTE_READWRITE, &oldProtect); + + memcpy(pfnHookAPIAddr, oldData, OLD_DATA_BACKUP_SIZE); + + VirtualProtect((LPVOID)pfnHookAPIAddr, OLD_DATA_BACKUP_SIZE, oldProtect, NULL); +} + +static void setFunction( PROC pfnHookAPIAddr, PROC replacementFunction, PBYTE oldData ) +{ + static const LONGLONG addressSize = sizeof(PROC); + static const LONGLONG jmpSize = addressSize + 6; + + INT_PTR jumpOffset = (INT_PTR)replacementFunction; + + DWORD oldProtect; + VirtualProtect((LPVOID)pfnHookAPIAddr, OLD_DATA_BACKUP_SIZE, + PAGE_EXECUTE_READWRITE, &oldProtect); + + memcpy(oldData, pfnHookAPIAddr, OLD_DATA_BACKUP_SIZE); + + PBYTE functionData = (PBYTE)pfnHookAPIAddr; + functionData[0] = 0xff; // JMP [RIP+0] + functionData[1] = 0x25; // + functionData[2] = 0x00; // + functionData[3] = 0x00; // + functionData[4] = 0x00; // + functionData[5] = 0x00; // + memcpy( functionData + 6, &jumpOffset, sizeof( INT_PTR ) ); + + VirtualProtect((LPVOID)pfnHookAPIAddr, OLD_DATA_BACKUP_SIZE, oldProtect, NULL); +} +#else +static void restoreFunction( PROC pfnHookAPIAddr, PBYTE oldData ) +{ + static const LONGLONG addressSize = sizeof(PROC); + static const LONGLONG jmpSize = addressSize + 1; + + DWORD oldProtect; + VirtualProtect((LPVOID)pfnHookAPIAddr, jmpSize, + PAGE_EXECUTE_READWRITE, &oldProtect); + + memcpy(pfnHookAPIAddr, oldData, jmpSize); + + VirtualProtect((LPVOID)pfnHookAPIAddr, jmpSize, oldProtect, NULL); +} + +static void setFunction( PROC pfnHookAPIAddr, PROC replacementFunction, PBYTE oldData ) +{ + static const LONGLONG addressSize = sizeof(PROC); + static const LONGLONG jmpSize = addressSize + 1; + + INT_PTR jumpOffset = (INT_PTR)replacementFunction - (INT_PTR)pfnHookAPIAddr - jmpSize; + + DWORD oldProtect; + VirtualProtect((LPVOID)pfnHookAPIAddr, jmpSize, + PAGE_EXECUTE_READWRITE, &oldProtect); + + memcpy(oldData, pfnHookAPIAddr, jmpSize); + + PBYTE functionData = (PBYTE)pfnHookAPIAddr; + memcpy( oldData, functionData, jmpSize ); + functionData[0] = 0xe9; + memcpy( functionData + 1, &jumpOffset, sizeof( INT_PTR ) ); + + VirtualProtect((LPVOID)pfnHookAPIAddr, jmpSize, oldProtect, NULL); +} +#endif + +static BOOL WINAPI OVRLocalIsInitializingDisplay( PVOID context, UINT width, UINT height ) +{ + UINT expectedWidth, expectedHeight, rotation; + + OVRExpectedResolution( context, &expectedWidth, &expectedHeight, &rotation ); + + if( appDriver.pfnActiveAPIVersion ) + apiVersion = (*appDriver.pfnActiveAPIVersion)( context ); + + switch( apiVersion ) + { + case 1: // OpenGL + case 10: // DirectX 1X + if( width == expectedWidth && height == expectedHeight ) + return TRUE; + break; + case 9: // DirectX 9 + if( rotation == 90 || rotation == 270 ) + { + if( width == expectedHeight && height == expectedWidth ) + return TRUE; + } + else + { + if( width == expectedWidth && height == expectedHeight ) + return TRUE; + } + break; + default: + break; + } + + return FALSE; +} + + +HRESULT APIENTRY OVRDirect3DCreate9Ex(UINT SDKVersion, void** aDevice) +{ + apiVersion = 9; + + HRESULT result = S_OK; + + restoreFunction( (PROC)oldDirectX9ExCreate, oldDirectX9ExCreateData ); + + if (IN_COMPATIBILITY_MODE()) + { + result = (*oldDirectX9ExCreate)(SDKVersion, aDevice); + } + else + { + HMODULE rtFilterModule = (*oldProcA)(RTFilter); + WinDirect3DCreate9Ex createFunction = (WinDirect3DCreate9Ex)GetProcAddress(rtFilterModule, "Direct3DCreate9Ex"); + result = (*createFunction)(SDKVersion, aDevice); + } + + setFunction( (PROC)oldDirectX9ExCreate, (PROC)OVRDirect3DCreate9Ex, oldDirectX9ExCreateData ); + + printf("%s result 0x%x\n", __FUNCTION__, result); + + return result; +} + +void* APIENTRY OVRDirect3DCreate9(UINT SDKVersion) +{ + void* result = NULL; + + OVRDirect3DCreate9Ex( SDKVersion, &result ); + + return result; +} + +HRESULT APIENTRY OVRCreateDXGIFactory( + __in REFIID riid, + __out void **ppFactory + ) +{ + HRESULT result = E_FAIL; + + restoreFunction( (PROC)oldCreateDXGIFactory, oldCreateDXGIFactoryData ); + + if (IN_COMPATIBILITY_MODE()) + { + result = (*oldCreateDXGIFactory)(riid, ppFactory); + } + else + { + HMODULE rtFilterModule = (*oldProcA)(RTFilter); + WinCreateDXGIFactory createFunction = (WinCreateDXGIFactory)GetProcAddress(rtFilterModule, "CreateDXGIFactory"); + result = (*createFunction)(riid, ppFactory); + } + + setFunction( (PROC)oldCreateDXGIFactory, (PROC)OVRCreateDXGIFactory, oldCreateDXGIFactoryData ); + + printf("%s result 0x%x\n", __FUNCTION__, result); + + return result; +} + +HRESULT APIENTRY OVRCreateDXGIFactory1( + __in REFIID riid, + __out void **ppFactory + ) +{ + HRESULT result = E_FAIL; + + restoreFunction( (PROC)oldCreateDXGIFactory1, oldCreateDXGIFactory1Data ); + + if (IN_COMPATIBILITY_MODE()) + { + result = (*oldCreateDXGIFactory1)(riid, ppFactory); + } + else + { + HMODULE rtFilterModule = (*oldProcA)(RTFilter); + WinCreateDXGIFactory1 createFunction = (WinCreateDXGIFactory1)GetProcAddress(rtFilterModule, "CreateDXGIFactory1"); + result = (*createFunction)(riid, ppFactory); + } + + setFunction( (PROC)oldCreateDXGIFactory1, (PROC)OVRCreateDXGIFactory1, oldCreateDXGIFactory1Data ); + + printf("%s result 0x%x\n", __FUNCTION__, result); + + return result; +} + +HRESULT APIENTRY OVRCreateDXGIFactory2( + __in UINT flags, + __in const IID &riid, + __out void **ppFactory + ) +{ + HRESULT result = E_FAIL; + + restoreFunction( (PROC)oldCreateDXGIFactory2, oldCreateDXGIFactory2Data ); + + if (IN_COMPATIBILITY_MODE()) + { + result = (*oldCreateDXGIFactory2)(flags, riid, ppFactory); + } + else + { + HMODULE rtFilterModule = (*oldProcA)(RTFilter); + WinCreateDXGIFactory2 createFunction = (WinCreateDXGIFactory2)GetProcAddress(rtFilterModule, "CreateDXGIFactory2"); + result = (*createFunction)(flags, riid, ppFactory); + } + + setFunction( (PROC)oldCreateDXGIFactory2, (PROC)OVRCreateDXGIFactory2, oldCreateDXGIFactory2Data ); + + printf("%s result 0x%x\n", __FUNCTION__, result); + + return result; +} + +static PROC SetProcAddressDirect( + __in HINSTANCE hInstance, + __in LPCSTR lpProcName, + __in PROC newFunction, + __inout BYTE* oldData + ) +{ + static const LONGLONG addressSize = sizeof(PROC); + static const LONGLONG jmpSize = addressSize + 1; + + PROC result = NULL; + + PROC pfnHookAPIAddr = GetProcAddress( hInstance, lpProcName ); + + if( pfnHookAPIAddr ) + { + result = pfnHookAPIAddr; + + setFunction( pfnHookAPIAddr, newFunction, oldData ); + } + + return result; +} + +static PROC SetProcAddressA( + __in HINSTANCE targetModule, + __in LPCSTR lpLibFileName, + __in LPCSTR lpProcName, + __in PROC newFunction + ) +{ + PROC pfnHookAPIAddr = GetProcAddress( LoadLibraryA( lpLibFileName ), lpProcName ); + + HINSTANCE hInstance = targetModule; + + ULONG ulSize; + PIMAGE_IMPORT_DESCRIPTOR pImportDesc = + (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData( + hInstance, + TRUE, + IMAGE_DIRECTORY_ENTRY_IMPORT, + &ulSize + ); + + while (pImportDesc->Name) + { + PSTR pszModName = (PSTR)((PBYTE) hInstance + pImportDesc->Name); + if (_stricmp(pszModName, lpLibFileName) == 0) + break; + pImportDesc++; + } + + PIMAGE_THUNK_DATA pThunk = + (PIMAGE_THUNK_DATA)((PBYTE) hInstance + pImportDesc->FirstThunk); + + while (pThunk->u1.Function) + { + PROC* ppfn = (PROC*) &pThunk->u1.Function; + BOOL bFound = (*ppfn == pfnHookAPIAddr); + + if (bFound) + { + MEMORY_BASIC_INFORMATION mbi; + VirtualQuery( + ppfn, + &mbi, + sizeof(MEMORY_BASIC_INFORMATION) + ); + VirtualProtect( + mbi.BaseAddress, + mbi.RegionSize, + PAGE_READWRITE, + &mbi.Protect); + + *ppfn = *newFunction; + + DWORD dwOldProtect; + VirtualProtect( + mbi.BaseAddress, + mbi.RegionSize, + mbi.Protect, + &dwOldProtect + ); + break; + } + pThunk++; + } + + return pfnHookAPIAddr; +} + +enum ShimedLibraries +{ + ShimLibDXGI = 0, + ShimLibD3D9 = 1, + ShimLibD3D11 = 2, + ShimLibDXGIDebug = 3, + ShimLibD3D10Core = 4, + ShimLibD3D10 = 5, + ShimLibGL = 6, + ShimCountMax = 7 +}; + +void checkUMDriverOverrides( void* context ) +{ + lastContext = context; + if( oldProcA == NULL ) + { + char* dllList[ShimCountMax] = { "dxgi.dll", "d3d9.dll", "d3d11.dll", "dxgidebug.dll", "d3d10core.dll", "d3d10.dll", "opengl32.dll" }; + + PreloadLibraryRTFn loadFunc = NULL; + + for( int i = 0; i < ShimCountMax; ++i ) + { + HINSTANCE hInst = GetModuleHandleA( dllList[i] ); + if( hInst == NULL ) + { + try + { + hInst = LoadLibraryA(dllList[i]); + } + catch(...) + { + + } + + } + + if( hInst ) + { + ShimedLibraries libCount = (ShimedLibraries)i; + switch( libCount ) + { + case ShimLibDXGI: + oldCreateDXGIFactory = (WinCreateDXGIFactory)SetProcAddressDirect( hInst, "CreateDXGIFactory", (PROC)OVRCreateDXGIFactory, oldCreateDXGIFactoryData ); + oldCreateDXGIFactory1 = (WinCreateDXGIFactory1)SetProcAddressDirect( hInst, "CreateDXGIFactory1", (PROC)OVRCreateDXGIFactory1, oldCreateDXGIFactory1Data ); + oldCreateDXGIFactory2 = (WinCreateDXGIFactory2)SetProcAddressDirect( hInst, "CreateDXGIFactory2", (PROC)OVRCreateDXGIFactory2, oldCreateDXGIFactory2Data ); + break; + case ShimLibD3D9: + oldDirectX9Create = (WinDirect3DCreate9)SetProcAddressDirect( hInst, "Direct3DCreate9", (PROC)OVRDirect3DCreate9, oldDirectX9CreateData ); + oldDirectX9ExCreate = (WinDirect3DCreate9Ex)SetProcAddressDirect( hInst, "Direct3DCreate9Ex", (PROC)OVRDirect3DCreate9Ex, oldDirectX9ExCreateData ); + break; + default: + break; + } + + char* loaderLibraryList[4] = {"kernel32.dll", "api-ms-win-core-libraryloader-l1-2-0.dll", "api-ms-win-core-libraryloader-l1-1-0.dll", "api-ms-win-core-libraryloader-l1-1-1.dll"}; + + for( int j = 0; j < 4; ++j ) + { + char* loaderLibrary = loaderLibraryList[j]; + + PROC temp = NULL; + temp = SetProcAddressA( hInst, loaderLibrary, "LoadLibraryA", (PROC)OVRLoadLibraryA ); + if( !oldProcA ) + oldProcA = (WinLoadLibraryA)temp; + + temp = SetProcAddressA( hInst, loaderLibrary, "LoadLibraryW", (PROC)OVRLoadLibraryW ); + if( !oldProcW ) + oldProcW = (WinLoadLibraryW)temp; + + temp = SetProcAddressA( hInst, loaderLibrary, "LoadLibraryExA", (PROC)OVRLoadLibraryExA ); + if( !oldProcExA ) + oldProcExA = (WinLoadLibraryExA)temp; + + temp = SetProcAddressA( hInst, loaderLibrary, "LoadLibraryExW", (PROC)OVRLoadLibraryExW ); + if( !oldProcExW ) + oldProcExW = (WinLoadLibraryExW)temp; + + temp = SetProcAddressA( hInst, loaderLibrary, "GetModuleHandleExA", (PROC)OVRGetModuleHandleExA ); + if( !oldProcModExA ) + oldProcModExA = (WinGetModuleHandleExA)temp; + + temp = SetProcAddressA( hInst, loaderLibrary, "GetModuleHandleExW", (PROC)OVRGetModuleHandleExW ); + if( !oldProcModExW ) + oldProcModExW = (WinGetModuleHandleExW)temp; + } + + if( loadFunc == NULL ) + loadFunc = (PreloadLibraryRTFn)GetProcAddress( hInst, "PreloadLibraryRT" ); + } + } + + HMODULE rtFilterModule = (*oldProcA)( RTFilter ); + + if( loadFunc == NULL ) + loadFunc = (PreloadLibraryRTFn)GetProcAddress( rtFilterModule, "PreloadLibraryRT" ); + IsCreatingBackBuffer backBufferFunc = (IsCreatingBackBuffer)GetProcAddress( rtFilterModule, "OVRIsCreatingBackBuffer" ); + ShouldVSync shouldVSyncFunc = (ShouldVSync)GetProcAddress( rtFilterModule, "OVRShouldVSync" ); + + if( loadFunc ) + { + appDriver.version = 1; + appDriver.context = lastContext; + +// appDriver.pfnInitializingDisplay = OVRIsInitializingDisplay; + appDriver.pfnInitializingDisplay = OVRLocalIsInitializingDisplay; + appDriver.pfnRiftForContext = OVRRiftForContext; + appDriver.pfnCloseRiftForContext = OVRCloseRiftForContext; + appDriver.pfnWindowDisplayResolution = OVRWindowDisplayResolution; + appDriver.pfnShouldEnableDebug = OVRShouldEnableDebug; + appDriver.pfnIsCreatingBackBuffer = (backBufferFunc == NULL) ? OVRIsCreatingBackBuffer : backBufferFunc; + appDriver.pfnShouldVSync = (shouldVSyncFunc == NULL) ? OVRShouldVSync : shouldVSyncFunc; + appDriver.pfnExpectedResolution = OVRExpectedResolution; + appDriver.pfnMirroringEnabled = OVRMirroringEnabled; + appDriver.pfnGetWindowForContext = OVRGetWindowForContext; + appDriver.pfnPresentRiftOnContext = OVRShouldPresentOnContext; + + appDriver.pfnDirect3DCreate9 = oldDirectX9Create; + appDriver.pfnDirect3DCreate9Ex = oldDirectX9ExCreate; + appDriver.pfnCreateDXGIFactory = oldCreateDXGIFactory; + appDriver.pfnCreateDXGIFactory1 = oldCreateDXGIFactory1; + appDriver.pfnCreateDXGIFactory2 = oldCreateDXGIFactory2; + + (*loadFunc)( &appDriver ); + } + } +} diff --git a/LibOVR/Src/Displays/OVR_Win32_ShimFunctions.cpp b/LibOVR/Src/Displays/OVR_Win32_ShimFunctions.cpp new file mode 100644 index 0000000..9e5442c --- /dev/null +++ b/LibOVR/Src/Displays/OVR_Win32_ShimFunctions.cpp @@ -0,0 +1,230 @@ +/************************************************************************************ + +Filename : OVR_Win32_ShimFunctions.cpp +Content : Client-side shim callbacks for usermode/rt hooks +Created : May 6, 2014 +Authors : Dean Beeler + +Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. + +Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +you may not use the Oculus VR Rift SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +http://www.oculusvr.com/licenses/LICENSE-3.1 + +Unless required by applicable law or agreed to in writing, the Oculus VR SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*************************************************************************************/ + +#include "OVR_Win32_Display.h" +#include "OVR_Win32_ShimFunctions.h" +#include "OVR_Win32_Dxgi_Display.h" +#include "../OVR_Stereo.h" +#include "OVR_Win32_FocusReader.h" + +// Exported +extern void checkUMDriverOverrides( void* context ); + +#include <stdio.h> +#include <tchar.h> +#include <string.h> +#include <stdlib.h> +#include <WinSock2.h> +#include <WS2tcpip.h> +#define WIN32_LEAN_AND_MEAN +#include <Windows.h> +#include <winioctl.h> +#include <SetupAPI.h> +#include <Mmsystem.h> +#include <conio.h> + + +//------------------------------------------------------------------------------------- +// ***** User-mode Callbacks +// +// See IsInitializingDisplay, etc in Dxgi_Display.h for details +// + +extern LINK_APPLICATION_DRIVER appDriver; + +BOOL WINAPI OVRIsInitializingDisplay(PVOID context, UINT width, UINT height) +{ + OVR::Win32::DisplayShim* con = (OVR::Win32::DisplayShim*)context; + if (con->ExpectedWidth == (int)width && con->ExpectedHeight == (int)height) + return TRUE; + + return FALSE; +} + +BOOL WINAPI OVRExpectedResolution( PVOID context, UINT* width, UINT* height, UINT* rotationInDegrees ) +{ + OVR::Win32::DisplayShim* con = (OVR::Win32::DisplayShim*)context; + + *width = con->ExpectedWidth; + *height = con->ExpectedHeight; + *rotationInDegrees = con->Rotation; + return TRUE; +} + +BOOL WINAPI OVRIsCreatingBackBuffer(PVOID context) +{ + OVR::Win32::DisplayShim* con = (OVR::Win32::DisplayShim*)context; + if( con->ExpectedWidth != -1 && con->ExpectedHeight != -1 ) + return TRUE; + + return FALSE; +} + +BOOL WINAPI OVRShouldVSync( ) +{ + return FALSE; +} + + +ULONG WINAPI OVRRiftForContext(PVOID context, HANDLE driverHandle) +{ + OVR_UNUSED( driverHandle ); + OVR::Win32::DisplayShim* con = (OVR::Win32::DisplayShim*)context; + + return con->ChildUid; +} + +HWND WINAPI OVRGetWindowForContext(PVOID context) +{ + OVR::Win32::DisplayShim* con = (OVR::Win32::DisplayShim*)context; + + if( con->Active ) + { + return con->hWindow; + } + else + { + return 0; + } +} + +BOOL WINAPI OVRShouldPresentOnContext(PVOID context) +{ + OVR::Win32::DisplayShim* con = (OVR::Win32::DisplayShim*)context; + + return con->Active && ( con->hWindow == OVR::Win32::RenderFocusReader::GetInstance()->ReadActiveWindow() ); +} + +BOOL WINAPI OVRCloseRiftForContext( PVOID context, HANDLE driverHandle, ULONG rift ) +{ + OVR_UNUSED( context ); OVR_UNUSED( driverHandle ); OVR_UNUSED( rift ); + // TODO + return TRUE; +} + +BOOL WINAPI OVRWindowDisplayResolution( PVOID context, UINT* width, UINT* height, + UINT* titleHeight, UINT* borderWidth, + BOOL* vsyncEnabled ) +{ + OVR::Win32::DisplayShim* con = (OVR::Win32::DisplayShim*)context; + void* handle = con->hWindow; + + if( handle ) + { + RECT winRect = { 0 }; + GetWindowRect( (HWND)handle, &winRect ); + + RECT rect = {0}; + if( GetClientRect( (HWND)handle, &rect ) ) + { + LONG barHeight = (winRect.bottom - winRect.top) - (rect.bottom - rect.top); + LONG borderSize = (winRect.right - winRect.left) - (rect.right - rect.left); + + *titleHeight = barHeight - borderSize + (borderSize / 2 ); + *borderWidth = borderSize / 2; + *width = rect.right - rect.left + (borderSize / 2); + *height = rect.bottom - rect.top + *titleHeight; + } + else + { + return FALSE; + } + } + else + { + return FALSE; + } + + *vsyncEnabled = TRUE; + + return TRUE; +} + +BOOL WINAPI OVRShouldEnableDebug() +{ + return FALSE; +} + +BOOL WINAPI OVRMirroringEnabled( PVOID context ) +{ + OVR::Win32::DisplayShim* con = (OVR::Win32::DisplayShim*)context; + + return con->UseMirroring; +} + +namespace OVR { namespace Win32 { + +DisplayShim::DisplayShim() : + ChildUid( 0 ), + ExpectedWidth( 1280 ), + ExpectedHeight( 800 ), + Rotation( 0 ), + hWindow( 0 ), + UseMirroring( TRUE ) +{ + +} + +DisplayShim::~DisplayShim() +{ + +} + +bool DisplayShim::Initialize( bool inCompatibility ) +{ + if( !inCompatibility ) + checkUMDriverOverrides( this ); + + return true; +} + +bool DisplayShim::Shutdown() +{ + return true; +} + +bool DisplayShim::Update(Win32ShimInfo* shimInfo) +{ + ChildUid = shimInfo->DeviceNumber; + ExpectedWidth = shimInfo->NativeWidth; + ExpectedHeight = shimInfo->NativeHeight; + Rotation = shimInfo->Rotation; + UseMirroring = shimInfo->UseMirroring != 0; + return true; +} + +void* DisplayShim::GetDX11SwapChain() +{ + if( appDriver.pfnGetDX11SwapChain ) + { + return (*appDriver.pfnGetDX11SwapChain)(this); + } + + return NULL; +} + + +} } // OVR::Win32 diff --git a/LibOVR/Src/Displays/OVR_Win32_ShimFunctions.h b/LibOVR/Src/Displays/OVR_Win32_ShimFunctions.h new file mode 100644 index 0000000..86de0d6 --- /dev/null +++ b/LibOVR/Src/Displays/OVR_Win32_ShimFunctions.h @@ -0,0 +1,79 @@ +/************************************************************************************ + +Filename : OVR_Win32_ShimFunctions.h +Content : Client-side shim callbacks for usermode/rt hooks +Created : May 6, 2014 +Authors : Dean Beeler + +Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. + +Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +you may not use the Oculus VR Rift SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +http://www.oculusvr.com/licenses/LICENSE-3.1 + +Unless required by applicable law or agreed to in writing, the Oculus VR SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*************************************************************************************/ + +#ifndef OVR_Win32_ShimFunctions_h +#define OVR_Win32_ShimFunctions_h + +#include "OVR_Win32_Display.h" + +namespace OVR { + +struct Win32ShimInfo; + +namespace Win32 { + + +class DisplayShim +{ +public: + +public: + static DisplayShim& GetInstance() + { + static DisplayShim instance; + return instance; + } + + bool Initialize( bool inCompatibility ); + bool Shutdown(); + + bool Update( Win32ShimInfo* shimInfo ); + + void* GetDX11SwapChain(); + + ULONG ChildUid; + int ExpectedWidth; + int ExpectedHeight; + int Rotation; + HWND hWindow; + bool UseMirroring; + bool Active; + +private: + + DisplayShim(); + + virtual ~DisplayShim(); + + DisplayShim(DisplayShim const&); // Don't Implement + void operator=(DisplayShim const&); // Don't implement + +}; + + +}} // namespace OVR::Win32 + +#endif |