diff options
Diffstat (limited to 'LibOVR/Src/Displays')
-rw-r--r-- | LibOVR/Src/Displays/OVR_Display.cpp | 6 | ||||
-rw-r--r-- | LibOVR/Src/Displays/OVR_Display.h | 4 | ||||
-rw-r--r-- | LibOVR/Src/Displays/OVR_Win32_Display.cpp | 422 | ||||
-rw-r--r-- | LibOVR/Src/Displays/OVR_Win32_Dxgi_Display.h | 22 | ||||
-rw-r--r-- | LibOVR/Src/Displays/OVR_Win32_FocusReader.cpp | 2 | ||||
-rw-r--r-- | LibOVR/Src/Displays/OVR_Win32_FocusReader.h | 2 | ||||
-rw-r--r-- | LibOVR/Src/Displays/OVR_Win32_RenderShim.cpp | 337 | ||||
-rw-r--r-- | LibOVR/Src/Displays/OVR_Win32_ShimFunctions.cpp | 5 |
8 files changed, 622 insertions, 178 deletions
diff --git a/LibOVR/Src/Displays/OVR_Display.cpp b/LibOVR/Src/Displays/OVR_Display.cpp index 65f0b30..c7a624f 100644 --- a/LibOVR/Src/Displays/OVR_Display.cpp +++ b/LibOVR/Src/Displays/OVR_Display.cpp @@ -29,4 +29,8 @@ limitations under the License. namespace OVR { -} + +// Place platform-independent code here + + +} // namespace OVR diff --git a/LibOVR/Src/Displays/OVR_Display.h b/LibOVR/Src/Displays/OVR_Display.h index 3184182..bcba4bc 100644 --- a/LibOVR/Src/Displays/OVR_Display.h +++ b/LibOVR/Src/Displays/OVR_Display.h @@ -189,6 +189,10 @@ public: // Check if right now the current rendering application should be in compatibility mode static bool InCompatibilityMode( bool displaySearch = true ); + // Get/set the mode for all applications + static bool GetDriverMode(bool& driverInstalled, bool& compatMode, bool& hideDK1Mode); + static bool SetDriverMode(bool compatMode, bool hideDK1Mode); + static DisplaySearchHandle* GetDisplaySearchHandle(); }; diff --git a/LibOVR/Src/Displays/OVR_Win32_Display.cpp b/LibOVR/Src/Displays/OVR_Win32_Display.cpp index 8300468..6bebc7b 100644 --- a/LibOVR/Src/Displays/OVR_Win32_Display.cpp +++ b/LibOVR/Src/Displays/OVR_Win32_Display.cpp @@ -37,10 +37,14 @@ limitations under the License. #include <SetupAPI.h> #include <Mmsystem.h> #include <conio.h> + +#ifdef OVR_COMPAT_EDID_VIA_WMI # pragma comment(lib, "wbemuuid.lib") #include <wbemidl.h> -#include <AtlBase.h> -#include <AtlConv.h> +#else // OVR_COMPAT_EDID_VIA_WMI +#include <setupapi.h> +#include <initguid.h> +#endif // OVR_COMPAT_EDID_VIA_WMI // WIN32_LEAN_AND_MEAN included in OVR_Atomic.h may break 'byte' declaration. #ifdef WIN32_LEAN_AND_MEAN @@ -56,7 +60,8 @@ typedef struct UINT ExpectedWidth; UINT ExpectedHeight; HWND hWindow; - bool InCompatibilityMode; + bool CompatibilityMode; + bool HideDK1Mode; } ContextStruct; static ContextStruct GlobalDisplayContext = {0}; @@ -89,7 +94,7 @@ ULONG getRift( HANDLE hDevice, int index ) { ULONG riftCount = getRiftCount( hDevice ); DWORD bytesReturned = 0; - BOOL result; + BOOL result; if( riftCount >= (ULONG)index ) { @@ -334,11 +339,10 @@ static BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC, LPRECT, LPARAM dwDa return TRUE; }; +#ifdef OVR_COMPAT_EDID_VIA_WMI static bool getCompatDisplayEDID( WCHAR* displayName, String& serialNumberStr, String& userFriendlyNameStr ) { - USES_CONVERSION; - IWbemLocator *pLoc = NULL; IWbemServices *pSvc = NULL; HRESULT hres; @@ -350,8 +354,10 @@ static bool getCompatDisplayEDID( WCHAR* displayName, String& serialNumberStr, S 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; + + LogError("{ERR-082} [Display] WARNING: Failed to initialize COM library. Error code = 0x%x", hres); + OVR_ASSERT(false); + return false; } hres = CoInitializeSecurity( @@ -368,10 +374,9 @@ static bool getCompatDisplayEDID( WCHAR* displayName, String& serialNumberStr, S if (FAILED(hres)) { - OVR_DEBUG_LOG_TEXT(("Failed to initialize security. Error code = 0x%x\n", hres)); - //CoUninitialize(); - //return false; - selfInitialized = false; + LogError("{ERR-083} [Display] WARNING: Failed to initialize security. Error code = 0x%x", hres); + OVR_ASSERT(false); + selfInitialized = false; } initialized = true; @@ -385,8 +390,9 @@ static bool getCompatDisplayEDID( WCHAR* displayName, String& serialNumberStr, S if (FAILED(hres)) { - OVR_DEBUG_LOG_TEXT(("Failed to create IWbemLocator object. Err code = 0x%x\n", hres)); - return false; + LogError("{ERR-084} [Display] WARNING: Failed to create IWbemLocator object.Err code = 0x%x", hres); + OVR_ASSERT(false); + return false; } BSTR AbackB = SysAllocString(L"root\\WMI"); @@ -407,8 +413,9 @@ static bool getCompatDisplayEDID( WCHAR* displayName, String& serialNumberStr, S if (FAILED(hres)) { - OVR_DEBUG_LOG_TEXT(("Could not connect. Error code = 0x%x\n", hres)); - pLoc->Release(); + LogError("{ERR-085} [Display] WARNING: Could not connect to root\\WMI. Error code = 0x%x", hres); + OVR_ASSERT(false); + pLoc->Release(); return false; } @@ -425,8 +432,9 @@ static bool getCompatDisplayEDID( WCHAR* displayName, String& serialNumberStr, S if (FAILED(hres)) { - OVR_DEBUG_LOG_TEXT(("Could not set proxy blanket. Error code = 0x%x\n", hres)); - pSvc->Release(); + LogError("{ERR-086} [Display] WARNING: Could not set proxy blanket. Error code = 0x%x", hres); + OVR_ASSERT(false); + pSvc->Release(); pLoc->Release(); return false; } @@ -446,12 +454,16 @@ static bool getCompatDisplayEDID( WCHAR* displayName, String& serialNumberStr, S if (FAILED(hres)) { - OVR_DEBUG_LOG_TEXT(( "Query for operating system name failed. Error code = 0x%x\n", hres )); - pSvc->Release(); + LogError("{ERR-087} [Display] WARNING: Query for operating system name failed. Error code = 0x%x", hres); + OVR_ASSERT(false); + pSvc->Release(); pLoc->Release(); return false; } + int enumeratedCount = 0; + bool found = false; + IWbemClassObject *pclsObj = 0; while (pEnumerator) { @@ -463,29 +475,31 @@ static bool getCompatDisplayEDID( WCHAR* displayName, String& serialNumberStr, S break; } - VARIANT vtProp; - hr = pclsObj->Get(L"InstanceName", 0, &vtProp, 0, 0); + ++enumeratedCount; + + VARIANT vtProp; + hr = pclsObj->Get(L"InstanceName", 0, &vtProp, 0, 0); - WCHAR* instanceName = vtProp.bstrVal; - WCHAR* nextToken = NULL; - if (SUCCEEDED(hr) && + WCHAR* instanceName = vtProp.bstrVal; + WCHAR* nextToken = NULL; + if (SUCCEEDED(hr) && wcstok_s(instanceName, L"\\", &nextToken) != NULL) - { - WCHAR* aToken = wcstok_s(NULL, L"\\", &nextToken); + { + WCHAR* aToken = wcstok_s(NULL, L"\\", &nextToken); - if (aToken != NULL) - { - VariantClear(&vtProp); + if (aToken != NULL) + { + VariantClear(&vtProp); - if (wcscmp(aToken, displayName) != 0) - { + if (wcscmp(aToken, displayName) != 0) + { pclsObj->Release(); continue; - } + } - // Read serial + // Read serial - hr = pclsObj->Get(L"SerialNumberID", 0, &vtProp, 0, 0); + hr = pclsObj->Get(L"SerialNumberID", 0, &vtProp, 0, 0); if (SUCCEEDED(hr)) { @@ -505,21 +519,21 @@ static bool getCompatDisplayEDID( WCHAR* displayName, String& serialNumberStr, S } else { - OVR_DEBUG_LOG(("[Win32Display] WARNING: Wrong data format for SerialNumberID")); + LogError("{ERR-088} [Display] WARNING: Wrong data format for SerialNumberID"); } VariantClear(&vtProp); } else { - OVR_DEBUG_LOG(("[Win32Display] WARNING: Failure getting display SerialNumberID: %d", (int)hr)); + LogError("{ERR-089} [Display] WARNING: Failure getting display SerialNumberID: %d", (int)hr); } - // Read length of name + // Read length of name int userFriendlyNameLen = 0; - hr = pclsObj->Get(L"UserFriendlyNameLength", 0, &vtProp, 0, 0); + hr = pclsObj->Get(L"UserFriendlyNameLength", 0, &vtProp, 0, 0); if (SUCCEEDED(hr)) { @@ -531,24 +545,24 @@ static bool getCompatDisplayEDID( WCHAR* displayName, String& serialNumberStr, S { userFriendlyNameLen = 0; - OVR_DEBUG_LOG(("[Win32Display] WARNING: UserFriendlyNameLength = 0")); + LogError("{ERR-090} [Display] WARNING: UserFriendlyNameLength = 0"); } } else { - OVR_DEBUG_LOG(("[Win32Display] WARNING: Wrong data format for UserFriendlyNameLength")); + LogError("{ERR-091} [Display] WARNING: Wrong data format for UserFriendlyNameLength"); } VariantClear(&vtProp); } else { - OVR_DEBUG_LOG(("[Win32Display] WARNING: Failure getting display UserFriendlyNameLength: %d", (int)hr)); + LogError("{ERR-092} [Display] WARNING: Failure getting display UserFriendlyNameLength: %d", (int)hr); } - // Read name + // Read name - hr = pclsObj->Get(L"UserFriendlyName", 0, &vtProp, 0, 0); + hr = pclsObj->Get(L"UserFriendlyName", 0, &vtProp, 0, 0); if (SUCCEEDED(hr) && userFriendlyNameLen > 0) { @@ -570,20 +584,23 @@ static bool getCompatDisplayEDID( WCHAR* displayName, String& serialNumberStr, S { // See: https://developer.oculusvr.com/forums/viewtopic.php?f=34&t=10961 // This can happen if someone has an EDID override in the registry. - OVR_DEBUG_LOG(("[Win32Display] WARNING: Wrong data format for UserFriendlyName")); + LogError("{ERR-093} [Display] WARNING: Wrong data format for UserFriendlyName"); } VariantClear(&vtProp); } else { - OVR_DEBUG_LOG(("[Win32Display] WARNING: Failure getting display UserFriendlyName: %d", (int)hr)); + LogError("{ERR-094} [Display] WARNING: Failure getting display UserFriendlyName: %d", (int)hr); } - } + } + + found = true; + pclsObj->Release(); + break; } - pclsObj->Release(); - break; + pclsObj->Release(); } HMODULE hModule = GetModuleHandleA("wbemuuid"); @@ -596,9 +613,201 @@ static bool getCompatDisplayEDID( WCHAR* displayName, String& serialNumberStr, S pLoc->Release(); pEnumerator->Release(); - return true; + if (!found) + { + LogError("{ERR-095} [Display] WARNING: Unable to enumerate the rift via WMI (found %d monitors). This is not normally an issue. Running as a user with Administrator privileges has fixed this problem in the past.", enumeratedCount); + OVR_ASSERT(false); + } + + return found; +} + +#else // OVR_COMPAT_EDID_VIA_WMI + +#define NAME_SIZE 128 + +DEFINE_GUID(GUID_CLASS_MONITOR, + 0x4d36e96e, 0xe325, 0x11ce, 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, + 0x03, 0x18); + +static void truncateNonalphanum(char* str, int len) +{ + for (int i = 0; i < len; ++i) + { + char ch = str[i]; + + if ((ch < 'A' || ch > 'Z') && + (ch < 'a' || ch > 'z') && + (ch < '0' || ch > '9') && + ch != ' ') + { + str[i] = '\0'; + break; + } + } +} + +static bool AccessDeviceRegistry(IN HDEVINFO devInfo, IN PSP_DEVINFO_DATA devInfoData, + const WCHAR* displayName, String& serialNumberStr, String& userFriendlyNameStr) +{ + // Match hardware id to display name + WCHAR hardwareId[128]; + if (!SetupDiGetDeviceRegistryProperty( + devInfo, + devInfoData, + SPDRP_HARDWAREID, + NULL, + (PBYTE)hardwareId, + sizeof(hardwareId), + NULL)) + { + LogError("{ERR-096} [Display] WARNING: SetupDiGetDeviceRegistryProperty for SPDRP_HARDWAREID failed. LastErr=%d", GetLastError()); + OVR_ASSERT(false); + return false; + } + hardwareId[127] = 0; + + // If the hardware id did not match, + if (!wcsstr(hardwareId, displayName)) + { + // Stop here + return false; + } + + // Grab hardware info registry key + HKEY hDevRegKey = SetupDiOpenDevRegKey( + devInfo, + devInfoData, + DICS_FLAG_GLOBAL, + 0, + DIREG_DEV, + KEY_READ); // Only read permissions so it can be run without Administrator privs + + if (hDevRegKey == INVALID_HANDLE_VALUE) + { + LogError("{ERR-097} [Display] WARNING: SetupDiOpenDevRegKey failed. LastErr=%d", GetLastError()); + OVR_ASSERT(false); + return false; + } + + // Enumerate keys in registry + bool found = false; + + // For each key, + for (int i = 0;; i++) + { + BYTE EDIDdata[1024]; + DWORD edidsize = sizeof(EDIDdata); + + DWORD dwType, ActualValueNameLength = NAME_SIZE; + CHAR valueName[NAME_SIZE]; + + // Read the key value data + LSTATUS retValue = RegEnumValueA( + hDevRegKey, + i, + &valueName[0], + &ActualValueNameLength, + NULL, + &dwType, + EDIDdata, + &edidsize); + + if (FAILED(retValue)) + { + if (retValue == ERROR_NO_MORE_ITEMS) + { + break; + } + + LogError("{ERR-098} [Display] WARNING: RegEnumValueA failed to read a key. LastErr=%d", retValue); + OVR_ASSERT(false); + } + else if (0 == strcmp(valueName, "EDID")) // Value is EDID: + { + // Tested working for DK1 and DK2: + + char friendlyString[9]; + memcpy(friendlyString, EDIDdata + 77, 8); + truncateNonalphanum(friendlyString, 8); + friendlyString[8] = '\0'; + + char edidString[14]; + memcpy(edidString, EDIDdata + 95, 13); + truncateNonalphanum(edidString, 13); + edidString[13] = '\0'; + + serialNumberStr = edidString; + userFriendlyNameStr = friendlyString; + + found = true; + break; + } + } + + RegCloseKey(hDevRegKey); + + return found; +} + +static bool getCompatDisplayEDID(const WCHAR* displayName, String& serialNumberStr, String& userFriendlyNameStr) +{ + HDEVINFO devInfo = NULL; + + devInfo = SetupDiGetClassDevsEx( + &GUID_CLASS_MONITOR, //class GUID + NULL, //enumerator + NULL, //HWND + DIGCF_PRESENT, // Flags //DIGCF_ALLCLASSES| + NULL, // device info, create a new one. + NULL, // machine name, local machine + NULL);// reserved + + if (NULL == devInfo) + { + return false; + } + + DWORD lastError = 0; + + // For each display, + for (int i = 0;; i++) + { + SP_DEVINFO_DATA devInfoData = {}; + devInfoData.cbSize = sizeof(devInfoData); + + // Grab device info + if (SetupDiEnumDeviceInfo(devInfo, i, &devInfoData)) + { + // Access device info from registry + if (AccessDeviceRegistry(devInfo, &devInfoData, displayName, serialNumberStr, userFriendlyNameStr)) + { + return true; + } + } + else + { + lastError = GetLastError(); + + // If no more items found, + if (lastError != ERROR_NO_MORE_ITEMS) + { + LogError("{ERR-099} [Display] WARNING: SetupDiEnumDeviceInfo failed. LastErr=%d", lastError); + OVR_ASSERT(false); + } + + break; + } + } + + LogError("{ERR-100} [Display] WARNING: SetupDiEnumDeviceInfo did not return the rift display. LastErr=%d", lastError); + OVR_ASSERT(false); + + return false; } +#endif // OVR_COMPAT_EDID_VIA_WMI + // This is function that's used bool anyRiftsInExtendedMode() { @@ -797,27 +1006,28 @@ bool Display::InCompatibilityMode( bool displaySearch ) bool result = false; if( displaySearch ) { - OVR::Win32::DisplayDesc displayArray[8]; + OVR::Win32::DisplayDesc displayArray[8]; - int extendedRiftCount = discoverExtendedRifts(displayArray, 8, false); - if( extendedRiftCount ) - { - result = true; - } - else - { - result = GlobalDisplayContext.InCompatibilityMode; + int extendedRiftCount = discoverExtendedRifts(displayArray, 8, false); + if( extendedRiftCount ) + { + result = true; + } + else + { + result = GlobalDisplayContext.CompatibilityMode; } } else { - result = GlobalDisplayContext.InCompatibilityMode; + result = GlobalDisplayContext.CompatibilityMode; } return result; } #define OVR_FLAG_COMPATIBILITY_MODE 1 +#define OVR_FLAG_HIDE_DK1 2 bool Display::Initialize() { @@ -830,7 +1040,7 @@ bool Display::Initialize() if (hDevice != NULL && hDevice != INVALID_HANDLE_VALUE) { GlobalDisplayContext.hDevice = hDevice; - GlobalDisplayContext.InCompatibilityMode = FALSE; + GlobalDisplayContext.CompatibilityMode = false; DWORD bytesReturned = 0; LONG compatiblityResult = OVR_STATUS_SUCCESS; @@ -839,16 +1049,16 @@ bool Display::Initialize() &compatiblityResult, sizeof( LONG ), &bytesReturned, NULL ); if (result) { - if( compatiblityResult & OVR_FLAG_COMPATIBILITY_MODE ) - GlobalDisplayContext.InCompatibilityMode = TRUE; - } + GlobalDisplayContext.CompatibilityMode = (compatiblityResult & OVR_FLAG_COMPATIBILITY_MODE) != 0; + GlobalDisplayContext.HideDK1Mode = (compatiblityResult & OVR_FLAG_HIDE_DK1) != 0; + } else { // If calling our driver fails in any way, assume compatibility mode as well - GlobalDisplayContext.InCompatibilityMode = TRUE; + GlobalDisplayContext.CompatibilityMode = true; } - if (!GlobalDisplayContext.InCompatibilityMode) + if (!GlobalDisplayContext.CompatibilityMode) { Ptr<DisplaySearchHandle> searchHandle = *Display::GetDisplaySearchHandle(); @@ -861,19 +1071,89 @@ bool Display::Initialize() } else { - GlobalDisplayContext.InCompatibilityMode = TRUE; + GlobalDisplayContext.CompatibilityMode = true; } } } else { - GlobalDisplayContext.InCompatibilityMode = TRUE; + GlobalDisplayContext.CompatibilityMode = true; } return true; } +bool Display::GetDriverMode(bool& driverInstalled, bool& compatMode, bool& hideDK1Mode) +{ + if (GlobalDisplayContext.hDevice == NULL) + { + driverInstalled = false; + compatMode = true; + hideDK1Mode = false; + } + else + { + driverInstalled = true; + compatMode = GlobalDisplayContext.CompatibilityMode; + hideDK1Mode = GlobalDisplayContext.HideDK1Mode; + } + + return true; +} + +bool Display::SetDriverMode(bool compatMode, bool hideDK1Mode) +{ + // If device is not initialized, + if (GlobalDisplayContext.hDevice == NULL) + { + OVR_ASSERT(false); + return false; + } + + // If no change, + if ((compatMode == GlobalDisplayContext.CompatibilityMode) && + (hideDK1Mode == GlobalDisplayContext.HideDK1Mode)) + { + return true; + } + + LONG mode_flags = 0; + if (compatMode) + { + mode_flags |= OVR_FLAG_COMPATIBILITY_MODE; + } + if (hideDK1Mode) + { + mode_flags |= OVR_FLAG_HIDE_DK1; + } + + DWORD bytesReturned = 0; + LONG err = 1; + + if (!DeviceIoControl(GlobalDisplayContext.hDevice, + IOCTL_RIFTMGR_SETCOMPATIBILITYMODE, + &mode_flags, + sizeof(LONG), + &err, + sizeof(LONG), + &bytesReturned, + NULL) || + (err != 0 && err != -3)) + { + LogError("{ERR-001w} [Win32Display] Unable to set device mode to (compat=%d dk1hide=%d): err=%d", + (int)compatMode, (int)hideDK1Mode, (int)err); + return false; + } + + OVR_DEBUG_LOG(("[Win32Display] Set device mode to (compat=%d dk1hide=%d)", + (int)compatMode, (int)hideDK1Mode)); + + GlobalDisplayContext.HideDK1Mode = hideDK1Mode; + GlobalDisplayContext.CompatibilityMode = compatMode; + return true; +} + DisplaySearchHandle* Display::GetDisplaySearchHandle() { return new Win32::Win32DisplaySearchHandle(); @@ -950,10 +1230,8 @@ Ptr<Display> Display::GetDisplay(int index, DisplaySearchHandle* handle) } // 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 nativeWidth = 1080, nativeHeight = 1920; + uint32_t logicalWidth = 1920, logicalHeight = 1080; uint32_t rotation = 0; switch (dEdid.ModelNumber) diff --git a/LibOVR/Src/Displays/OVR_Win32_Dxgi_Display.h b/LibOVR/Src/Displays/OVR_Win32_Dxgi_Display.h index ab1582c..bdcd813 100644 --- a/LibOVR/Src/Displays/OVR_Win32_Dxgi_Display.h +++ b/LibOVR/Src/Displays/OVR_Win32_Dxgi_Display.h @@ -372,19 +372,31 @@ typedef struct _RIFT_STATUS_ARRAY // 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 +// Input Buffer: LONG - Bit assignments: +// LSB (bit 0) is a flag for compatibility mode itself. +// 1 means compatibility mode. +// 0 means application direct mode. +// Bit 1 means "Hide DK1's". +// 1 means operate DK1's in synchronous with the compatibility mode exactly. +// 0 means operate in DK1 legacy mode. // Output Buffer: LONG - Result value (see OVR statuses) // 0 = success // -1 = general failure // -2 = failure, rift scanning out +// -3 = already active +// -4 = rift not present #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 +// Output Buffer: LONG - Bit assignments: +// LSB (bit 0) is a flag for compatibility mode itself. +// 1 means compatibility mode. +// 0 means application direct mode. +// Bit 1 means "Hide DK1's". +// 1 means operate DK1's in synchronous with the compatibility mode exactly. +// 0 means operate in DK1 legacy mode. #define IOCTL_RIFTMGR_GETCOMPATIBILITYMODE CTL_CODE(FILE_DEVICE_VIDEO, \ FUNCTION_INDEX + 9, METHOD_NEITHER, FILE_ANY_ACCESS) @@ -410,4 +422,4 @@ typedef struct _RIFT_STATUS_ARRAY #define IOCTL_RIFTMGR_GETEDID CTL_CODE(FILE_DEVICE_VIDEO, \ FUNCTION_INDEX + 11, METHOD_NEITHER, FILE_ANY_ACCESS) -#endif
\ No newline at end of file +#endif diff --git a/LibOVR/Src/Displays/OVR_Win32_FocusReader.cpp b/LibOVR/Src/Displays/OVR_Win32_FocusReader.cpp index 852e29e..d665546 100644 --- a/LibOVR/Src/Displays/OVR_Win32_FocusReader.cpp +++ b/LibOVR/Src/Displays/OVR_Win32_FocusReader.cpp @@ -75,6 +75,4 @@ void RenderFocusReader::OnSystemDestroy() } - - }} // namespace OVR::Win32 diff --git a/LibOVR/Src/Displays/OVR_Win32_FocusReader.h b/LibOVR/Src/Displays/OVR_Win32_FocusReader.h index f62b8de..1d58264 100644 --- a/LibOVR/Src/Displays/OVR_Win32_FocusReader.h +++ b/LibOVR/Src/Displays/OVR_Win32_FocusReader.h @@ -64,7 +64,7 @@ typedef SharedObjectReader< LocklessFocusState > SharedFocusReader; //----------------------------------------------------------------------------- // RenderFocusReader -class RenderFocusReader : public OVR::SystemSingletonBase<RenderFocusReader> +class RenderFocusReader : public OVR::SystemSingletonBase<RenderFocusReader>, public NewOverrideBase { OVR_DECLARE_SINGLETON(RenderFocusReader); diff --git a/LibOVR/Src/Displays/OVR_Win32_RenderShim.cpp b/LibOVR/Src/Displays/OVR_Win32_RenderShim.cpp index a58e40d..80b33a2 100644 --- a/LibOVR/Src/Displays/OVR_Win32_RenderShim.cpp +++ b/LibOVR/Src/Displays/OVR_Win32_RenderShim.cpp @@ -16,8 +16,7 @@ otherwise accompanies this software in either electronic or hard copy form. #include <windows.h> #include <DbgHelp.h> -#include <AtlBase.h> -#include <AtlConv.h> +#include <malloc.h> #include "OVR_Win32_Dxgi_Display.h" @@ -30,6 +29,12 @@ otherwise accompanies this software in either electronic or hard copy form. #pragma comment(lib, "DbgHelp.lib") +#define WIDE_TO_MB(wideString) \ + int wideString ## _slen = (int)wcslen(wideString); \ + char* wideString ## _cstr = (char*)alloca(wideString ## _slen * 2); \ + int count = WideCharToMultiByte(GetACP(), 0, wideString, -1, wideString ## _cstr, wideString ## _slen * 2, NULL, NULL); \ + wideString ## _cstr[count] = '\0'; + // Forward declarations // These functions are implemented in OVR_Win32_DisplayDevice.cpp. @@ -114,22 +119,63 @@ TryAgainWOW64: #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 WinLoadLibraryA oldProcA = NULL; // Note: This is used to indicate that the shim is in place +static WinLoadLibraryExA oldProcExA = NULL; +static WinLoadLibraryW oldProcW = NULL; +static WinLoadLibraryExW oldProcExW = NULL; +static WinGetModuleHandleExA oldProcModExA = NULL; +static WinGetModuleHandleExW oldProcModExW = NULL; +static WinDirect3DCreate9 oldDirectX9Create = NULL; +static BYTE oldDirectX9CreateData[OLD_DATA_BACKUP_SIZE]; +static WinDirect3DCreate9Ex oldDirectX9ExCreate = NULL; +static BYTE oldDirectX9ExCreateData[OLD_DATA_BACKUP_SIZE]; +static WinCreateDXGIFactory oldCreateDXGIFactory = NULL; +static BYTE oldCreateDXGIFactoryData[OLD_DATA_BACKUP_SIZE]; +static WinCreateDXGIFactory1 oldCreateDXGIFactory1 = NULL; +static BYTE oldCreateDXGIFactory1Data[OLD_DATA_BACKUP_SIZE]; +static WinCreateDXGIFactory2 oldCreateDXGIFactory2 = NULL; +static BYTE oldCreateDXGIFactory2Data[OLD_DATA_BACKUP_SIZE]; + +#define NUM_LOADER_LIBS 4 + +static const char* loaderLibraryList[NUM_LOADER_LIBS] = { + "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" +}; + +enum ShimedLibraries +{ + ShimLibDXGI = 0, + ShimLibD3D9 = 1, + ShimLibD3D11 = 2, + ShimLibDXGIDebug = 3, + ShimLibD3D10Core = 4, + ShimLibD3D10 = 5, + ShimLibGL = 6, + ShimCountMax = 7 +}; + +static const char* dllList[ShimCountMax] = { + "dxgi.dll", + "d3d9.dll", + "d3d11.dll", + "dxgidebug.dll", + "d3d10core.dll", + "d3d10.dll", + "opengl32.dll" +}; + +static HINSTANCE oldLoaderInstances[ShimCountMax] = { NULL }; +static PROC oldLoaderProcA[ShimCountMax][NUM_LOADER_LIBS] = { { NULL } }; +static PROC oldLoaderProcW[ShimCountMax][NUM_LOADER_LIBS] = { { NULL } }; +static PROC oldLoaderProcExA[ShimCountMax][NUM_LOADER_LIBS] = { { NULL } }; +static PROC oldLoaderProcExW[ShimCountMax][NUM_LOADER_LIBS] = { { NULL } }; +static PROC oldLoaderProcModExA[ShimCountMax][NUM_LOADER_LIBS] = { { NULL } }; +static PROC oldLoaderProcModExW[ShimCountMax][NUM_LOADER_LIBS] = { { NULL } }; + +static HMODULE rtFilterModule = NULL; static bool checkForOverride( LPCSTR libFileName, OVRTargetAPI& targetApi ) { @@ -249,15 +295,15 @@ static HMODULE __in LPCWSTR lpLibFileName ) { - USES_CONVERSION; + WIDE_TO_MB(lpLibFileName); // Convert lpLibFileName -> lpLibFileName_cstr OVRTargetAPI targetAPI = DirectX; - bool needShim = checkForOverride( W2A( lpLibFileName ), targetAPI ); + bool needShim = checkForOverride( lpLibFileName_cstr, targetAPI ); if( !needShim ) return (*oldProcW)( lpLibFileName ); - return createShim( W2A( lpLibFileName ), targetAPI ); + return createShim( lpLibFileName_cstr, targetAPI ); } static HMODULE @@ -287,16 +333,16 @@ static HMODULE __in DWORD dwFlags ) { - USES_CONVERSION; + WIDE_TO_MB(lpLibFileName); // Convert lpLibFileName -> lpLibFileName_cstr OVRTargetAPI targetAPI = DirectX; - bool needShim = checkForOverride( W2A( lpLibFileName ), targetAPI ); + bool needShim = checkForOverride( lpLibFileName_cstr, targetAPI ); if( !needShim ) return (*oldProcExW)( lpLibFileName, hFile, dwFlags ); // FIXME: Don't throw away the flags parameter - return createShim( W2A( lpLibFileName ), targetAPI ); + return createShim( lpLibFileName_cstr, targetAPI ); } static BOOL WINAPI OVRGetModuleHandleExA( @@ -324,17 +370,17 @@ static BOOL WINAPI OVRGetModuleHandleExW( __out HMODULE *phModule ) { - USES_CONVERSION; + WIDE_TO_MB(lpModuleName); // Convert lpModuleName -> lpModuleName_cstr - OVRTargetAPI targetAPI = DirectX; + OVRTargetAPI targetAPI = DirectX; - bool needShim = checkForOverride( W2A( lpModuleName ), targetAPI ); + bool needShim = checkForOverride( lpModuleName_cstr, targetAPI ); if( !needShim ) { return (*oldProcModExW)( dwFlags, lpModuleName, phModule ); } - *phModule = createShim( W2A( lpModuleName ), targetAPI ); + *phModule = createShim( lpModuleName_cstr, targetAPI ); return TRUE; } @@ -465,7 +511,6 @@ HRESULT APIENTRY OVRDirect3DCreate9Ex(UINT SDKVersion, void** aDevice) } else { - HMODULE rtFilterModule = (*oldProcA)(RTFilter); WinDirect3DCreate9Ex createFunction = (WinDirect3DCreate9Ex)GetProcAddress(rtFilterModule, "Direct3DCreate9Ex"); result = (*createFunction)(SDKVersion, aDevice); } @@ -501,7 +546,6 @@ HRESULT APIENTRY OVRCreateDXGIFactory( } else { - HMODULE rtFilterModule = (*oldProcA)(RTFilter); WinCreateDXGIFactory createFunction = (WinCreateDXGIFactory)GetProcAddress(rtFilterModule, "CreateDXGIFactory"); result = (*createFunction)(riid, ppFactory); } @@ -528,7 +572,6 @@ HRESULT APIENTRY OVRCreateDXGIFactory1( } else { - HMODULE rtFilterModule = (*oldProcA)(RTFilter); WinCreateDXGIFactory1 createFunction = (WinCreateDXGIFactory1)GetProcAddress(rtFilterModule, "CreateDXGIFactory1"); result = (*createFunction)(riid, ppFactory); } @@ -556,7 +599,6 @@ HRESULT APIENTRY OVRCreateDXGIFactory2( } else { - HMODULE rtFilterModule = (*oldProcA)(RTFilter); WinCreateDXGIFactory2 createFunction = (WinCreateDXGIFactory2)GetProcAddress(rtFilterModule, "CreateDXGIFactory2"); result = (*createFunction)(flags, riid, ppFactory); } @@ -659,43 +701,27 @@ static PROC SetProcAddressA( return pfnHookAPIAddr; } -enum ShimedLibraries -{ - ShimLibDXGI = 0, - ShimLibD3D9 = 1, - ShimLibD3D11 = 2, - ShimLibDXGIDebug = 3, - ShimLibD3D10Core = 4, - ShimLibD3D10 = 5, - ShimLibGL = 6, - ShimCountMax = 7 -}; -void checkUMDriverOverrides( void* context ) +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 ) + HINSTANCE hInst = NULL; + try + { + hInst = LoadLibraryA(dllList[i]); + } + catch(...) { - try - { - hInst = LoadLibraryA(dllList[i]); - } - catch(...) - { - - } - } + oldLoaderInstances[i] = hInst; + if( hInst ) { ShimedLibraries libCount = (ShimedLibraries)i; @@ -714,52 +740,75 @@ void checkUMDriverOverrides( void* context ) 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]; + for (int j = 0; j < NUM_LOADER_LIBS; ++j) + { + const 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" ); + temp = SetProcAddressA(hInst, loaderLibrary, "LoadLibraryA", (PROC)OVRLoadLibraryA); + if (!oldProcA) + { + oldProcA = (WinLoadLibraryA)temp; + } + oldLoaderProcA[i][j] = temp; + + temp = SetProcAddressA(hInst, loaderLibrary, "LoadLibraryW", (PROC)OVRLoadLibraryW); + if (!oldProcW) + { + oldProcW = (WinLoadLibraryW)temp; + } + oldLoaderProcW[i][j] = temp; + + temp = SetProcAddressA(hInst, loaderLibrary, "LoadLibraryExA", (PROC)OVRLoadLibraryExA); + if (!oldProcExA) + { + oldProcExA = (WinLoadLibraryExA)temp; + } + oldLoaderProcExA[i][j] = temp; + + temp = SetProcAddressA(hInst, loaderLibrary, "LoadLibraryExW", (PROC)OVRLoadLibraryExW); + if (!oldProcExW) + { + oldProcExW = (WinLoadLibraryExW)temp; + } + oldLoaderProcExW[i][j] = temp; + + temp = SetProcAddressA(hInst, loaderLibrary, "GetModuleHandleExA", (PROC)OVRGetModuleHandleExA); + if (!oldProcModExA) + { + oldProcModExA = (WinGetModuleHandleExA)temp; + } + oldLoaderProcModExA[i][j] = temp; + + temp = SetProcAddressA(hInst, loaderLibrary, "GetModuleHandleExW", (PROC)OVRGetModuleHandleExW); + if (!oldProcModExW) + { + oldProcModExW = (WinGetModuleHandleExW)temp; + } + oldLoaderProcModExW[i][j] = temp; + } + + if (loadFunc == NULL) + { + loadFunc = (PreloadLibraryRTFn)GetProcAddress(hInst, "PreloadLibraryRT"); + } } } - HMODULE rtFilterModule = (*oldProcA)( RTFilter ); + rtFilterModule = (*oldProcA)( RTFilter ); - if( loadFunc == NULL ) - loadFunc = (PreloadLibraryRTFn)GetProcAddress( rtFilterModule, "PreloadLibraryRT" ); - IsCreatingBackBuffer backBufferFunc = (IsCreatingBackBuffer)GetProcAddress( rtFilterModule, "OVRIsCreatingBackBuffer" ); - ShouldVSync shouldVSyncFunc = (ShouldVSync)GetProcAddress( rtFilterModule, "OVRShouldVSync" ); + IsCreatingBackBuffer backBufferFunc = NULL; + ShouldVSync shouldVSyncFunc = NULL; - if( loadFunc ) - { + if (rtFilterModule != NULL) + { + loadFunc = (PreloadLibraryRTFn)GetProcAddress(rtFilterModule, "PreloadLibraryRT"); + backBufferFunc = (IsCreatingBackBuffer)GetProcAddress(rtFilterModule, "OVRIsCreatingBackBuffer"); + shouldVSyncFunc = (ShouldVSync)GetProcAddress(rtFilterModule, "OVRShouldVSync"); + } + + if (loadFunc != NULL) + { appDriver.version = 1; appDriver.context = lastContext; @@ -786,3 +835,99 @@ void checkUMDriverOverrides( void* context ) } } } + +void clearUMDriverOverrides() +{ + if (oldProcA != NULL) + { + // Unpatch all the things. + + if (oldCreateDXGIFactory) + { + restoreFunction((PROC)oldCreateDXGIFactory, oldCreateDXGIFactoryData); + } + if (oldCreateDXGIFactory1) + { + restoreFunction((PROC)oldCreateDXGIFactory1, oldCreateDXGIFactory1Data); + } + if (oldCreateDXGIFactory2) + { + restoreFunction((PROC)oldCreateDXGIFactory2, oldCreateDXGIFactory2Data); + } + if (oldDirectX9Create) + { + restoreFunction((PROC)oldDirectX9Create, oldDirectX9CreateData); + } + if (oldDirectX9ExCreate) + { + restoreFunction((PROC)oldDirectX9ExCreate, oldDirectX9ExCreateData); + } + if (oldCreateDXGIFactory2) + { + restoreFunction((PROC)oldCreateDXGIFactory2, oldCreateDXGIFactory2Data); + } + + for (int i = 0; i < ShimCountMax; ++i) + { + HINSTANCE hInst = oldLoaderInstances[i]; + + if (hInst != NULL) + { + for (int j = 0; j < NUM_LOADER_LIBS; ++j) + { + const char* loaderLibrary = loaderLibraryList[j]; + + if (oldLoaderProcA[j]) + { + SetProcAddressA(hInst, loaderLibrary, "LoadLibraryA", oldLoaderProcA[i][j]); + } + if (oldLoaderProcW[j]) + { + SetProcAddressA(hInst, loaderLibrary, "LoadLibraryW", oldLoaderProcW[i][j]); + } + if (oldLoaderProcExA[j]) + { + SetProcAddressA(hInst, loaderLibrary, "LoadLibraryExA", oldLoaderProcExA[i][j]); + } + if (oldLoaderProcExW[j]) + { + SetProcAddressA(hInst, loaderLibrary, "LoadLibraryExW", oldLoaderProcExW[i][j]); + } + if (oldLoaderProcModExA[j]) + { + SetProcAddressA(hInst, loaderLibrary, "GetModuleHandleExA", oldLoaderProcModExA[i][j]); + } + if (oldLoaderProcModExW[j]) + { + SetProcAddressA(hInst, loaderLibrary, "GetModuleHandleExW", oldLoaderProcModExW[i][j]); + } + } + + FreeLibrary(hInst); + } + } + + if (rtFilterModule != NULL) + { + LPFNCANUNLOADNOW pfnCanUnloadNow = (LPFNCANUNLOADNOW)GetProcAddress(rtFilterModule, "DllCanUnloadNow"); + if (pfnCanUnloadNow && pfnCanUnloadNow() == S_OK) + { + FreeLibrary(rtFilterModule); + rtFilterModule = NULL; + } + } + + oldProcA = NULL; + oldProcExA = NULL; + oldProcW = NULL; + oldProcExW = NULL; + oldProcModExA = NULL; + oldProcModExW = NULL; + oldDirectX9Create = NULL; + oldDirectX9ExCreate = NULL; + oldCreateDXGIFactory = NULL; + oldCreateDXGIFactory1 = NULL; + oldCreateDXGIFactory2 = NULL; + lastContext = NULL; + } +} diff --git a/LibOVR/Src/Displays/OVR_Win32_ShimFunctions.cpp b/LibOVR/Src/Displays/OVR_Win32_ShimFunctions.cpp index 9e5442c..907dc13 100644 --- a/LibOVR/Src/Displays/OVR_Win32_ShimFunctions.cpp +++ b/LibOVR/Src/Displays/OVR_Win32_ShimFunctions.cpp @@ -31,7 +31,8 @@ limitations under the License. #include "OVR_Win32_FocusReader.h" // Exported -extern void checkUMDriverOverrides( void* context ); +extern void checkUMDriverOverrides(void* context); +extern void clearUMDriverOverrides(); #include <stdio.h> #include <tchar.h> @@ -203,6 +204,8 @@ bool DisplayShim::Initialize( bool inCompatibility ) bool DisplayShim::Shutdown() { + clearUMDriverOverrides(); + return true; } |