diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..ee4aff70 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,66 @@ +# Set the minimum required version of CMake for this project. +cmake_minimum_required(VERSION 2.8) + +# Set project name. +project(OpenVRSDK) + +# Setup some options. +option(BUILD_SHARED "Builds the library as shared library" OFF) +option(USE_LIBCXX "Uses libc++ instead of libstdc++" ON) +option(USE_CUSTOM_LIBCXX "Uses a custom libc++" OFF) + +add_definitions( -DVR_API_PUBLIC ) + +# Check if 32 or 64 bit system. +set(SIZEOF_VOIDP ${CMAKE_SIZEOF_VOID_P}) +if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(PROCESSOR_ARCH "64") +else() + set(PROCESSOR_ARCH "32") +endif() + +# Get platform. +if(WIN32) + set(PLATFORM_NAME "win") +elseif(UNIX AND NOT APPLE) + if(CMAKE_SYSTEM_NAME MATCHES ".*Linux") + set(PLATFORM_NAME "linux") + add_definitions(-DLINUX -DPOSIX) + if(PROCESSOR_ARCH MATCHES "64") + add_definitions(-DLINUX64) + endif() + endif() +elseif(APPLE) + if(CMAKE_SYSTEM_NAME MATCHES ".*Darwin.*" OR CMAKE_SYSTEM_NAME MATCHES ".*MacOS.*") + set(PLATFORM_NAME "osx") + add_definitions(-DOSX -DPOSIX) + endif() +endif() + +# Set output folder for static and shared libraries +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin/${PLATFORM_NAME}${PROCESSOR_ARCH}) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin/${PLATFORM_NAME}${PROCESSOR_ARCH}) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin/${PLATFORM_NAME}${PROCESSOR_ARCH}) + +# Enable some properties. +if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang") + # Enable c++11 and hide symbols which shouldn't be visible + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fPIC -fvisibility=hidden") + + # Set custom libc++ usage here + if(CMAKE_C_COMPILER_ID MATCHES "Clang" AND USE_LIBCXX) + if(USE_CUSTOM_LIBCXX) + if(BUILD_SHARED) + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -stdlib=libc++") + endif() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostdinc++") + include_directories( ${LIBCXX_INCLUDE} ${LIBCXX_ABI_INCLUDE}) + message(STATUS "Using custom libc++") + else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") + message(STATUS "Using libc++") + endif() + endif() +endif() + +add_subdirectory(src) diff --git a/Toolchain-clang.cmake b/Toolchain-clang.cmake new file mode 100644 index 00000000..fb6b0ac0 --- /dev/null +++ b/Toolchain-clang.cmake @@ -0,0 +1,9 @@ +set(CMAKE_SYSTEM_NAME Linux) + +set(CMAKE_C_COMPILER clang) +set(CMAKE_CXX_COMPILER clang++) + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) diff --git a/bin/linux64/libopenvr_api.so b/bin/linux64/libopenvr_api.so index 7b6f2d2d..eafad11e 100755 Binary files a/bin/linux64/libopenvr_api.so and b/bin/linux64/libopenvr_api.so differ diff --git a/bin/linux64/libopenvr_api.so.dbg b/bin/linux64/libopenvr_api.so.dbg index c100646c..877c2840 100755 Binary files a/bin/linux64/libopenvr_api.so.dbg and b/bin/linux64/libopenvr_api.so.dbg differ diff --git a/bin/osx32/libopenvr_api.dylib b/bin/osx32/libopenvr_api.dylib index 647ec3fa..b3da84f1 100755 Binary files a/bin/osx32/libopenvr_api.dylib and b/bin/osx32/libopenvr_api.dylib differ diff --git a/bin/osx32/libopenvr_api.dylib.dSYM/Contents/Resources/DWARF/libopenvr_api.dylib b/bin/osx32/libopenvr_api.dylib.dSYM/Contents/Resources/DWARF/libopenvr_api.dylib index 67ae4daf..8ca6951d 100644 Binary files a/bin/osx32/libopenvr_api.dylib.dSYM/Contents/Resources/DWARF/libopenvr_api.dylib and b/bin/osx32/libopenvr_api.dylib.dSYM/Contents/Resources/DWARF/libopenvr_api.dylib differ diff --git a/bin/win32/openvr_api.dll b/bin/win32/openvr_api.dll index 7aa2b993..83ead53b 100644 Binary files a/bin/win32/openvr_api.dll and b/bin/win32/openvr_api.dll differ diff --git a/bin/win32/openvr_api.pdb b/bin/win32/openvr_api.pdb index a5d24ae1..a7bb091e 100644 Binary files a/bin/win32/openvr_api.pdb and b/bin/win32/openvr_api.pdb differ diff --git a/bin/win64/openvr_api.dll b/bin/win64/openvr_api.dll index bbcccde5..5767d725 100644 Binary files a/bin/win64/openvr_api.dll and b/bin/win64/openvr_api.dll differ diff --git a/bin/win64/openvr_api.pdb b/bin/win64/openvr_api.pdb index b2e1f159..082d4780 100644 Binary files a/bin/win64/openvr_api.pdb and b/bin/win64/openvr_api.pdb differ diff --git a/headers/openvr.h b/headers/openvr.h index 6617b4d3..19f2a0b7 100644 --- a/headers/openvr.h +++ b/headers/openvr.h @@ -21,6 +21,10 @@ struct VkPhysicalDevice_T; struct VkInstance_T; struct VkQueue_T; +// Forward declarations to avoid requiring d3d12.h +struct ID3D12Resource; +struct ID3D12CommandQueue; + namespace vr { @@ -116,6 +120,8 @@ enum ETextureType TextureType_DirectX = 0, // Handle is an ID3D11Texture TextureType_OpenGL = 1, // Handle is an OpenGL texture name or an OpenGL render buffer name, depending on submit flags TextureType_Vulkan = 2, // Handle is a pointer to a VRVulkanTextureData_t structure + TextureType_IOSurface = 3, // Handle is a macOS cross-process-sharable IOSurface + TextureType_DirectX12 = 4, // Handle is a pointer to a D3D12TextureData_t structure }; enum EColorSpace @@ -199,6 +205,30 @@ enum ETrackingUniverseOrigin TrackingUniverseRawAndUncalibrated = 2, // Poses are provided in the coordinate system defined by the driver. It has Y up and is unified for devices of the same driver. You usually don't want this one. }; +// Refers to a single container of properties +typedef uint64_t PropertyContainerHandle_t; +typedef uint32_t PropertyTypeTag_t; + +static const PropertyContainerHandle_t k_ulInvalidPropertyContainer = 0; +static const PropertyTypeTag_t k_unInvalidPropertyTag = 0; + +// Use these tags to set/get common types as struct properties +static const PropertyTypeTag_t k_unFloatPropertyTag = 1; +static const PropertyTypeTag_t k_unInt32PropertyTag = 2; +static const PropertyTypeTag_t k_unUint64PropertyTag = 3; +static const PropertyTypeTag_t k_unBoolPropertyTag = 4; +static const PropertyTypeTag_t k_unStringPropertyTag = 5; + +static const PropertyTypeTag_t k_unHmdMatrix34PropertyTag = 20; +static const PropertyTypeTag_t k_unHmdMatrix44PropertyTag = 21; +static const PropertyTypeTag_t k_unHmdVector3PropertyTag = 22; +static const PropertyTypeTag_t k_unHmdVector4PropertyTag = 23; + +static const PropertyTypeTag_t k_unHiddenAreaPropertyTag = 30; + +static const PropertyTypeTag_t k_unOpenVRInternalReserved_Start = 1000; +static const PropertyTypeTag_t k_unOpenVRInternalReserved_End = 10000; + /** Each entry in this enum represents a property that can be retrieved about a * tracked device. Many fields are only valid for one ETrackedDeviceClass. */ @@ -241,6 +271,8 @@ enum ETrackedDeviceProperty Prop_DriverVersion_String = 1031, Prop_Firmware_ForceUpdateRequired_Bool = 1032, Prop_ViveSystemButtonFixRequired_Bool = 1033, + Prop_ParentDriver_Uint64 = 1034, + // Properties that are unique to TrackedDeviceClass_HMD Prop_ReportsTimeSinceVSync_Bool = 2000, @@ -281,6 +313,11 @@ enum ETrackedDeviceProperty Prop_ScreenshotVerticalFieldOfViewDegrees_Float = 2035, Prop_DisplaySuppressed_Bool = 2036, Prop_DisplayAllowNightMode_Bool = 2037, + Prop_DisplayMCImageWidth_Int32 = 2038, + Prop_DisplayMCImageHeight_Int32 = 2039, + Prop_DisplayMCImageNumChannels_Int32 = 2040, + Prop_DisplayMCImageData_Binary = 2041, + Prop_UsesDriverDirectMode_Bool = 2042, // Properties that are unique to TrackedDeviceClass_Controller Prop_AttachedDeviceId_String = 3000, @@ -312,6 +349,14 @@ enum ETrackedDeviceProperty Prop_NamedIconPathDeviceStandby_String = 5007, // PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others Prop_NamedIconPathDeviceAlertLow_String = 5008, // PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others + // Properties that are used by helpers, but are opaque to applications + Prop_DisplayHiddenArea_Binary_Start = 5100, + Prop_DisplayHiddenArea_Binary_End = 5150, + + // Properties that are unique to drivers + Prop_UserConfigPath_String = 6000, + Prop_InstallPath_String = 6001, + // Vendors are free to expose private debug data in this reserved region Prop_VendorSpecific_Reserved_Start = 10000, Prop_VendorSpecific_Reserved_End = 10999, @@ -327,13 +372,14 @@ enum ETrackedPropertyError TrackedProp_WrongDataType = 1, TrackedProp_WrongDeviceClass = 2, TrackedProp_BufferTooSmall = 3, - TrackedProp_UnknownProperty = 4, + TrackedProp_UnknownProperty = 4, // Driver has not set the property (and may not ever). TrackedProp_InvalidDevice = 5, TrackedProp_CouldNotContactServer = 6, TrackedProp_ValueNotProvidedByDevice = 7, TrackedProp_StringExceedsMaximumLength = 8, TrackedProp_NotYetAvailable = 9, // The property value isn't known yet, but is expected soon. Call again later. TrackedProp_PermissionDenied = 10, + TrackedProp_InvalidOperation = 11, }; /** Allows the application to control what part of the provided texture will be used in the @@ -376,6 +422,14 @@ struct VRVulkanTextureData_t uint32_t m_nWidth, m_nHeight, m_nFormat, m_nSampleCount; }; +/** Data required for passing D3D12 textures to IVRCompositor::Submit. +* Be sure to call OpenVR_Shutdown before destroying these resources. */ +struct D3D12TextureData_t +{ + ID3D12Resource *m_pResource; + ID3D12CommandQueue *m_pCommandQueue; + uint32_t m_nNodeMask; +}; /** Status of the overall system or tracked objects */ enum EVRState @@ -399,7 +453,7 @@ enum EVREventType VREvent_TrackedDeviceActivated = 100, VREvent_TrackedDeviceDeactivated = 101, VREvent_TrackedDeviceUpdated = 102, - VREvent_TrackedDeviceUserInteractionStarted = 103, + VREvent_TrackedDeviceUserInteractionStarted = 103, VREvent_TrackedDeviceUserInteractionEnded = 104, VREvent_IpdChanged = 105, VREvent_EnterStandbyMode = 106, @@ -407,6 +461,7 @@ enum EVREventType VREvent_TrackedDeviceRoleChanged = 108, VREvent_WatchdogWakeUpRequested = 109, VREvent_LensDistortionChanged = 110, + VREvent_PropertyChanged = 111, VREvent_ButtonPress = 200, // data is controller VREvent_ButtonUnpress = 201, // data is controller @@ -436,78 +491,81 @@ enum EVREventType VREvent_OverlayShown = 500, VREvent_OverlayHidden = 501, - VREvent_DashboardActivated = 502, - VREvent_DashboardDeactivated = 503, - VREvent_DashboardThumbSelected = 504, // Sent to the overlay manager - data is overlay - VREvent_DashboardRequested = 505, // Sent to the overlay manager - data is overlay - VREvent_ResetDashboard = 506, // Send to the overlay manager - VREvent_RenderToast = 507, // Send to the dashboard to render a toast - data is the notification ID - VREvent_ImageLoaded = 508, // Sent to overlays when a SetOverlayRaw or SetOverlayFromFile call finishes loading - VREvent_ShowKeyboard = 509, // Sent to keyboard renderer in the dashboard to invoke it - VREvent_HideKeyboard = 510, // Sent to keyboard renderer in the dashboard to hide it - VREvent_OverlayGamepadFocusGained = 511, // Sent to an overlay when IVROverlay::SetFocusOverlay is called on it - VREvent_OverlayGamepadFocusLost = 512, // Send to an overlay when it previously had focus and IVROverlay::SetFocusOverlay is called on something else + VREvent_DashboardActivated = 502, + VREvent_DashboardDeactivated = 503, + VREvent_DashboardThumbSelected = 504, // Sent to the overlay manager - data is overlay + VREvent_DashboardRequested = 505, // Sent to the overlay manager - data is overlay + VREvent_ResetDashboard = 506, // Send to the overlay manager + VREvent_RenderToast = 507, // Send to the dashboard to render a toast - data is the notification ID + VREvent_ImageLoaded = 508, // Sent to overlays when a SetOverlayRaw or SetOverlayFromFile call finishes loading + VREvent_ShowKeyboard = 509, // Sent to keyboard renderer in the dashboard to invoke it + VREvent_HideKeyboard = 510, // Sent to keyboard renderer in the dashboard to hide it + VREvent_OverlayGamepadFocusGained = 511, // Sent to an overlay when IVROverlay::SetFocusOverlay is called on it + VREvent_OverlayGamepadFocusLost = 512, // Send to an overlay when it previously had focus and IVROverlay::SetFocusOverlay is called on something else VREvent_OverlaySharedTextureChanged = 513, - VREvent_DashboardGuideButtonDown = 514, - VREvent_DashboardGuideButtonUp = 515, - VREvent_ScreenshotTriggered = 516, // Screenshot button combo was pressed, Dashboard should request a screenshot - VREvent_ImageFailed = 517, // Sent to overlays when a SetOverlayRaw or SetOverlayfromFail fails to load - VREvent_DashboardOverlayCreated = 518, + VREvent_DashboardGuideButtonDown = 514, + VREvent_DashboardGuideButtonUp = 515, + VREvent_ScreenshotTriggered = 516, // Screenshot button combo was pressed, Dashboard should request a screenshot + VREvent_ImageFailed = 517, // Sent to overlays when a SetOverlayRaw or SetOverlayfromFail fails to load + VREvent_DashboardOverlayCreated = 518, // Screenshot API - VREvent_RequestScreenshot = 520, // Sent by vrclient application to compositor to take a screenshot - VREvent_ScreenshotTaken = 521, // Sent by compositor to the application that the screenshot has been taken - VREvent_ScreenshotFailed = 522, // Sent by compositor to the application that the screenshot failed to be taken - VREvent_SubmitScreenshotToDashboard = 523, // Sent by compositor to the dashboard that a completed screenshot was submitted - VREvent_ScreenshotProgressToDashboard = 524, // Sent by compositor to the dashboard that a completed screenshot was submitted + VREvent_RequestScreenshot = 520, // Sent by vrclient application to compositor to take a screenshot + VREvent_ScreenshotTaken = 521, // Sent by compositor to the application that the screenshot has been taken + VREvent_ScreenshotFailed = 522, // Sent by compositor to the application that the screenshot failed to be taken + VREvent_SubmitScreenshotToDashboard = 523, // Sent by compositor to the dashboard that a completed screenshot was submitted + VREvent_ScreenshotProgressToDashboard = 524, // Sent by compositor to the dashboard that a completed screenshot was submitted + + VREvent_PrimaryDashboardDeviceChanged = 525, VREvent_Notification_Shown = 600, VREvent_Notification_Hidden = 601, VREvent_Notification_BeginInteraction = 602, VREvent_Notification_Destroyed = 603, - VREvent_Quit = 700, // data is process - VREvent_ProcessQuit = 701, // data is process - VREvent_QuitAborted_UserPrompt = 702, // data is process - VREvent_QuitAcknowledged = 703, // data is process - VREvent_DriverRequestedQuit = 704, // The driver has requested that SteamVR shut down + VREvent_Quit = 700, // data is process + VREvent_ProcessQuit = 701, // data is process + VREvent_QuitAborted_UserPrompt = 702, // data is process + VREvent_QuitAcknowledged = 703, // data is process + VREvent_DriverRequestedQuit = 704, // The driver has requested that SteamVR shut down - VREvent_ChaperoneDataHasChanged = 800, - VREvent_ChaperoneUniverseHasChanged = 801, - VREvent_ChaperoneTempDataHasChanged = 802, - VREvent_ChaperoneSettingsHaveChanged = 803, - VREvent_SeatedZeroPoseReset = 804, + VREvent_ChaperoneDataHasChanged = 800, + VREvent_ChaperoneUniverseHasChanged = 801, + VREvent_ChaperoneTempDataHasChanged = 802, + VREvent_ChaperoneSettingsHaveChanged = 803, + VREvent_SeatedZeroPoseReset = 804, - VREvent_AudioSettingsHaveChanged = 820, + VREvent_AudioSettingsHaveChanged = 820, - VREvent_BackgroundSettingHasChanged = 850, - VREvent_CameraSettingsHaveChanged = 851, - VREvent_ReprojectionSettingHasChanged = 852, - VREvent_ModelSkinSettingsHaveChanged = 853, - VREvent_EnvironmentSettingsHaveChanged = 854, - VREvent_PowerSettingsHaveChanged = 855, + VREvent_BackgroundSettingHasChanged = 850, + VREvent_CameraSettingsHaveChanged = 851, + VREvent_ReprojectionSettingHasChanged = 852, + VREvent_ModelSkinSettingsHaveChanged = 853, + VREvent_EnvironmentSettingsHaveChanged = 854, + VREvent_PowerSettingsHaveChanged = 855, - VREvent_StatusUpdate = 900, + VREvent_StatusUpdate = 900, - VREvent_MCImageUpdated = 1000, + VREvent_MCImageUpdated = 1000, - VREvent_FirmwareUpdateStarted = 1100, - VREvent_FirmwareUpdateFinished = 1101, + VREvent_FirmwareUpdateStarted = 1100, + VREvent_FirmwareUpdateFinished = 1101, - VREvent_KeyboardClosed = 1200, - VREvent_KeyboardCharInput = 1201, - VREvent_KeyboardDone = 1202, // Sent when DONE button clicked on keyboard + VREvent_KeyboardClosed = 1200, + VREvent_KeyboardCharInput = 1201, + VREvent_KeyboardDone = 1202, // Sent when DONE button clicked on keyboard - VREvent_ApplicationTransitionStarted = 1300, - VREvent_ApplicationTransitionAborted = 1301, - VREvent_ApplicationTransitionNewAppStarted = 1302, - VREvent_ApplicationListUpdated = 1303, - VREvent_ApplicationMimeTypeLoad = 1304, + VREvent_ApplicationTransitionStarted = 1300, + VREvent_ApplicationTransitionAborted = 1301, + VREvent_ApplicationTransitionNewAppStarted = 1302, + VREvent_ApplicationListUpdated = 1303, + VREvent_ApplicationMimeTypeLoad = 1304, + VREvent_ApplicationTransitionNewAppLaunchComplete = 1305, - VREvent_Compositor_MirrorWindowShown = 1400, - VREvent_Compositor_MirrorWindowHidden = 1401, - VREvent_Compositor_ChaperoneBoundsShown = 1410, - VREvent_Compositor_ChaperoneBoundsHidden = 1411, + VREvent_Compositor_MirrorWindowShown = 1400, + VREvent_Compositor_MirrorWindowHidden = 1401, + VREvent_Compositor_ChaperoneBoundsShown = 1410, + VREvent_Compositor_ChaperoneBoundsHidden = 1411, VREvent_TrackedCamera_StartVideoStream = 1500, VREvent_TrackedCamera_StopVideoStream = 1501, @@ -515,15 +573,15 @@ enum EVREventType VREvent_TrackedCamera_ResumeVideoStream = 1503, VREvent_TrackedCamera_EditingSurface = 1550, - VREvent_PerformanceTest_EnableCapture = 1600, - VREvent_PerformanceTest_DisableCapture = 1601, - VREvent_PerformanceTest_FidelityLevel = 1602, + VREvent_PerformanceTest_EnableCapture = 1600, + VREvent_PerformanceTest_DisableCapture = 1601, + VREvent_PerformanceTest_FidelityLevel = 1602, - VREvent_MessageOverlay_Closed = 1650, + VREvent_MessageOverlay_Closed = 1650, // Vendors are free to expose private events in this reserved region - VREvent_VendorSpecific_Reserved_Start = 10000, - VREvent_VendorSpecific_Reserved_End = 19999, + VREvent_VendorSpecific_Reserved_Start = 10000, + VREvent_VendorSpecific_Reserved_End = 19999, }; @@ -711,6 +769,12 @@ struct VREvent_MessageOverlay_t uint32_t unVRMessageOverlayResponse; // vr::VRMessageOverlayResponse enum }; +struct VREvent_Property_t +{ + PropertyContainerHandle_t container; + ETrackedDeviceProperty prop; +}; + /** NOTE!!! If you change this you MUST manually update openvr_interop.cs.py */ typedef union { @@ -733,6 +797,7 @@ typedef union VREvent_ApplicationLaunch_t applicationLaunch; VREvent_EditingCameraSurface_t cameraSurface; VREvent_MessageOverlay_t messageOverlay; + VREvent_Property_t property; } VREvent_Data_t; /** An event posted by the server to all running applications */ @@ -764,6 +829,8 @@ enum EHiddenAreaMeshType k_eHiddenAreaMesh_Standard = 0, k_eHiddenAreaMesh_Inverse = 1, k_eHiddenAreaMesh_LineLoop = 2, + + k_eHiddenAreaMesh_Max = 3, }; @@ -1173,9 +1240,7 @@ class IVRSystem /** [D3D10/11 Only] * Returns the adapter index that the user should pass into EnumAdapters to create the device - * and swap chain in DX10 and DX11. If an error occurs the index will be set to -1. The index will - * also be -1 if the headset is in direct mode on the driver side instead of using the compositor's - * builtin direct mode support. + * and swap chain in DX10 and DX11. If an error occurs the index will be set to -1. */ virtual void GetDXGIOutputInfo( int32_t *pnAdapterIndex ) = 0; @@ -1453,6 +1518,7 @@ namespace vr VRApplicationProperty_IsDashboardOverlay_Bool = 60, VRApplicationProperty_IsTemplate_Bool = 61, VRApplicationProperty_IsInstanced_Bool = 62, + VRApplicationProperty_IsInternal_Bool = 63, VRApplicationProperty_LastLaunchTime_Uint64 = 70, }; @@ -1600,6 +1666,11 @@ namespace vr * If working directory is NULL or "" the directory portion of the binary path will be * the working directory. */ virtual EVRApplicationError LaunchInternalProcess( const char *pchBinaryPath, const char *pchArguments, const char *pchWorkingDirectory ) = 0; + + /** Returns the current scene process ID according to the application system. A scene process will get scene + * focus once it starts rendering, but it will appear here once it calls VR_Init with the Scene application + * type. */ + virtual uint32_t GetCurrentSceneProcessId() = 0; }; static const char * const IVRApplications_Version = "IVRApplications_006"; @@ -1708,7 +1779,6 @@ namespace vr //----------------------------------------------------------------------------- // null keys static const char * const k_pch_Null_Section = "driver_null"; - static const char * const k_pch_Null_EnableNullDriver_Bool = "enable"; static const char * const k_pch_Null_SerialNumber_String = "serialNumber"; static const char * const k_pch_Null_ModelNumber_String = "modelNumber"; static const char * const k_pch_Null_WindowX_Int32 = "windowX"; @@ -1809,6 +1879,10 @@ namespace vr // model skin keys static const char * const k_pch_modelskin_Section = "modelskins"; + //----------------------------------------------------------------------------- + // driver keys - These could be checked in any driver_ section + static const char * const k_pch_Driver_Enable_Bool = "enable"; + } // namespace vr // ivrchaperone.h @@ -2237,8 +2311,10 @@ class IVRCompositor /** Temporarily suspends rendering (useful for finer control over scene transitions). */ virtual void SuspendRendering( bool bSuspend ) = 0; - /** Opens a shared D3D11 texture with the undistorted composited image for each eye. */ + /** Opens a shared D3D11 texture with the undistorted composited image for each eye. Use ReleaseMirrorTextureD3D11 when finished + * instead of calling Release on the resource itself. */ virtual vr::EVRCompositorError GetMirrorTextureD3D11( vr::EVREye eEye, void *pD3D11DeviceOrResource, void **ppD3D11ShaderResourceView ) = 0; + virtual void ReleaseMirrorTextureD3D11( void *pD3D11ShaderResourceView ) = 0; /** Access to mirror textures from OpenGL. */ virtual vr::EVRCompositorError GetMirrorTextureGL( vr::EVREye eEye, vr::glUInt_t *pglTextureId, vr::glSharedTextureHandle_t *pglSharedTextureHandle ) = 0; @@ -2258,7 +2334,7 @@ class IVRCompositor }; -static const char * const IVRCompositor_Version = "IVRCompositor_019"; +static const char * const IVRCompositor_Version = "IVRCompositor_020"; } // namespace vr diff --git a/headers/openvr_api.cs b/headers/openvr_api.cs index 98e09ef0..33bfd258 100644 --- a/headers/openvr_api.cs +++ b/headers/openvr_api.cs @@ -475,6 +475,11 @@ public struct IVRApplications [MarshalAs(UnmanagedType.FunctionPtr)] internal _LaunchInternalProcess LaunchInternalProcess; + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate uint _GetCurrentSceneProcessId(); + [MarshalAs(UnmanagedType.FunctionPtr)] + internal _GetCurrentSceneProcessId GetCurrentSceneProcessId; + } [StructLayout(LayoutKind.Sequential)] @@ -800,6 +805,11 @@ public struct IVRCompositor [MarshalAs(UnmanagedType.FunctionPtr)] internal _GetMirrorTextureD3D11 GetMirrorTextureD3D11; + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate void _ReleaseMirrorTextureD3D11(IntPtr pD3D11ShaderResourceView); + [MarshalAs(UnmanagedType.FunctionPtr)] + internal _ReleaseMirrorTextureD3D11 ReleaseMirrorTextureD3D11; + [UnmanagedFunctionPointer(CallingConvention.StdCall)] internal delegate EVRCompositorError _GetMirrorTextureGL(EVREye eEye, ref uint pglTextureId, IntPtr pglSharedTextureHandle); [MarshalAs(UnmanagedType.FunctionPtr)] @@ -1613,13 +1623,61 @@ public HiddenAreaMesh_t GetHiddenAreaMesh(EVREye eEye,EHiddenAreaMeshType type) HiddenAreaMesh_t result = FnTable.GetHiddenAreaMesh(eEye,type); return result; } +// This is a terrible hack to workaround the fact that VRControllerState_t was +// originally mis-compiled with the wrong packing for Linux and OSX. + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate bool _GetControllerStatePacked(uint unControllerDeviceIndex,ref VRControllerState_t_Packed pControllerState,uint unControllerStateSize); + [StructLayout(LayoutKind.Explicit)] + struct GetControllerStateUnion + { + [FieldOffset(0)] + public IVRSystem._GetControllerState pGetControllerState; + [FieldOffset(0)] + public _GetControllerStatePacked pGetControllerStatePacked; + } public bool GetControllerState(uint unControllerDeviceIndex,ref VRControllerState_t pControllerState,uint unControllerStateSize) { + if ((System.Environment.OSVersion.Platform == System.PlatformID.MacOSX) || + (System.Environment.OSVersion.Platform == System.PlatformID.Unix)) + { + GetControllerStateUnion u; + VRControllerState_t_Packed state_packed = new VRControllerState_t_Packed(); + u.pGetControllerStatePacked = null; + u.pGetControllerState = FnTable.GetControllerState; + bool packed_result = u.pGetControllerStatePacked(unControllerDeviceIndex,ref state_packed,(uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(VRControllerState_t_Packed))); + + state_packed.Unpack(ref pControllerState); + return packed_result; + } bool result = FnTable.GetControllerState(unControllerDeviceIndex,ref pControllerState,unControllerStateSize); return result; } +// This is a terrible hack to workaround the fact that VRControllerState_t was +// originally mis-compiled with the wrong packing for Linux and OSX. + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate bool _GetControllerStateWithPosePacked(ETrackingUniverseOrigin eOrigin,uint unControllerDeviceIndex,ref VRControllerState_t_Packed pControllerState,uint unControllerStateSize,ref TrackedDevicePose_t pTrackedDevicePose); + [StructLayout(LayoutKind.Explicit)] + struct GetControllerStateWithPoseUnion + { + [FieldOffset(0)] + public IVRSystem._GetControllerStateWithPose pGetControllerStateWithPose; + [FieldOffset(0)] + public _GetControllerStateWithPosePacked pGetControllerStateWithPosePacked; + } public bool GetControllerStateWithPose(ETrackingUniverseOrigin eOrigin,uint unControllerDeviceIndex,ref VRControllerState_t pControllerState,uint unControllerStateSize,ref TrackedDevicePose_t pTrackedDevicePose) { + if ((System.Environment.OSVersion.Platform == System.PlatformID.MacOSX) || + (System.Environment.OSVersion.Platform == System.PlatformID.Unix)) + { + GetControllerStateWithPoseUnion u; + VRControllerState_t_Packed state_packed = new VRControllerState_t_Packed(); + u.pGetControllerStateWithPosePacked = null; + u.pGetControllerStateWithPose = FnTable.GetControllerStateWithPose; + bool packed_result = u.pGetControllerStateWithPosePacked(eOrigin,unControllerDeviceIndex,ref state_packed,(uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(VRControllerState_t_Packed)),ref pTrackedDevicePose); + + state_packed.Unpack(ref pControllerState); + return packed_result; + } bool result = FnTable.GetControllerStateWithPose(eOrigin,unControllerDeviceIndex,ref pControllerState,unControllerStateSize,ref pTrackedDevicePose); return result; } @@ -1939,6 +1997,11 @@ public EVRApplicationError LaunchInternalProcess(string pchBinaryPath,string pch EVRApplicationError result = FnTable.LaunchInternalProcess(pchBinaryPath,pchArguments,pchWorkingDirectory); return result; } + public uint GetCurrentSceneProcessId() + { + uint result = FnTable.GetCurrentSceneProcessId(); + return result; + } } @@ -2269,6 +2332,10 @@ public EVRCompositorError GetMirrorTextureD3D11(EVREye eEye,IntPtr pD3D11DeviceO EVRCompositorError result = FnTable.GetMirrorTextureD3D11(eEye,pD3D11DeviceOrResource,ref ppD3D11ShaderResourceView); return result; } + public void ReleaseMirrorTextureD3D11(IntPtr pD3D11ShaderResourceView) + { + FnTable.ReleaseMirrorTextureD3D11(pD3D11ShaderResourceView); + } public EVRCompositorError GetMirrorTextureGL(EVREye eEye,ref uint pglTextureId,IntPtr pglSharedTextureHandle) { pglTextureId = 0; @@ -2776,8 +2843,32 @@ public uint GetComponentRenderModelName(string pchRenderModelName,string pchComp uint result = FnTable.GetComponentRenderModelName(pchRenderModelName,pchComponentName,pchComponentRenderModelName,unComponentRenderModelNameLen); return result; } +// This is a terrible hack to workaround the fact that VRControllerState_t was +// originally mis-compiled with the wrong packing for Linux and OSX. + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate bool _GetComponentStatePacked(string pchRenderModelName,string pchComponentName,ref VRControllerState_t_Packed pControllerState,ref RenderModel_ControllerMode_State_t pState,ref RenderModel_ComponentState_t pComponentState); + [StructLayout(LayoutKind.Explicit)] + struct GetComponentStateUnion + { + [FieldOffset(0)] + public IVRRenderModels._GetComponentState pGetComponentState; + [FieldOffset(0)] + public _GetComponentStatePacked pGetComponentStatePacked; + } public bool GetComponentState(string pchRenderModelName,string pchComponentName,ref VRControllerState_t pControllerState,ref RenderModel_ControllerMode_State_t pState,ref RenderModel_ComponentState_t pComponentState) { + if ((System.Environment.OSVersion.Platform == System.PlatformID.MacOSX) || + (System.Environment.OSVersion.Platform == System.PlatformID.Unix)) + { + GetComponentStateUnion u; + VRControllerState_t_Packed state_packed = new VRControllerState_t_Packed(); + u.pGetComponentStatePacked = null; + u.pGetComponentState = FnTable.GetComponentState; + bool packed_result = u.pGetComponentStatePacked(pchRenderModelName,pchComponentName,ref state_packed,ref pState,ref pComponentState); + + state_packed.Unpack(ref pControllerState); + return packed_result; + } bool result = FnTable.GetComponentState(pchRenderModelName,pchComponentName,ref pControllerState,ref pState,ref pComponentState); return result; } @@ -2986,6 +3077,8 @@ public enum ETextureType DirectX = 0, OpenGL = 1, Vulkan = 2, + IOSurface = 3, + DirectX12 = 4, } public enum EColorSpace { @@ -3058,6 +3151,7 @@ public enum ETrackedDeviceProperty Prop_DriverVersion_String = 1031, Prop_Firmware_ForceUpdateRequired_Bool = 1032, Prop_ViveSystemButtonFixRequired_Bool = 1033, + Prop_ParentDriver_Uint64 = 1034, Prop_ReportsTimeSinceVSync_Bool = 2000, Prop_SecondsFromVsyncToPhotons_Float = 2001, Prop_DisplayFrequency_Float = 2002, @@ -3096,6 +3190,11 @@ public enum ETrackedDeviceProperty Prop_ScreenshotVerticalFieldOfViewDegrees_Float = 2035, Prop_DisplaySuppressed_Bool = 2036, Prop_DisplayAllowNightMode_Bool = 2037, + Prop_DisplayMCImageWidth_Int32 = 2038, + Prop_DisplayMCImageHeight_Int32 = 2039, + Prop_DisplayMCImageNumChannels_Int32 = 2040, + Prop_DisplayMCImageData_Binary = 2041, + Prop_UsesDriverDirectMode_Bool = 2042, Prop_AttachedDeviceId_String = 3000, Prop_SupportedButtons_Uint64 = 3001, Prop_Axis0Type_Int32 = 3002, @@ -3120,6 +3219,10 @@ public enum ETrackedDeviceProperty Prop_NamedIconPathDeviceNotReady_String = 5006, Prop_NamedIconPathDeviceStandby_String = 5007, Prop_NamedIconPathDeviceAlertLow_String = 5008, + Prop_DisplayHiddenArea_Binary_Start = 5100, + Prop_DisplayHiddenArea_Binary_End = 5150, + Prop_UserConfigPath_String = 6000, + Prop_InstallPath_String = 6001, Prop_VendorSpecific_Reserved_Start = 10000, Prop_VendorSpecific_Reserved_End = 10999, } @@ -3136,6 +3239,7 @@ public enum ETrackedPropertyError TrackedProp_StringExceedsMaximumLength = 8, TrackedProp_NotYetAvailable = 9, TrackedProp_PermissionDenied = 10, + TrackedProp_InvalidOperation = 11, } public enum EVRSubmitFlags { @@ -3170,6 +3274,7 @@ public enum EVREventType VREvent_TrackedDeviceRoleChanged = 108, VREvent_WatchdogWakeUpRequested = 109, VREvent_LensDistortionChanged = 110, + VREvent_PropertyChanged = 111, VREvent_ButtonPress = 200, VREvent_ButtonUnpress = 201, VREvent_ButtonTouch = 202, @@ -3216,6 +3321,7 @@ public enum EVREventType VREvent_ScreenshotFailed = 522, VREvent_SubmitScreenshotToDashboard = 523, VREvent_ScreenshotProgressToDashboard = 524, + VREvent_PrimaryDashboardDeviceChanged = 525, VREvent_Notification_Shown = 600, VREvent_Notification_Hidden = 601, VREvent_Notification_BeginInteraction = 602, @@ -3249,6 +3355,7 @@ public enum EVREventType VREvent_ApplicationTransitionNewAppStarted = 1302, VREvent_ApplicationListUpdated = 1303, VREvent_ApplicationMimeTypeLoad = 1304, + VREvent_ApplicationTransitionNewAppLaunchComplete = 1305, VREvent_Compositor_MirrorWindowShown = 1400, VREvent_Compositor_MirrorWindowHidden = 1401, VREvent_Compositor_ChaperoneBoundsShown = 1410, @@ -3305,6 +3412,7 @@ public enum EHiddenAreaMeshType k_eHiddenAreaMesh_Standard = 0, k_eHiddenAreaMesh_Inverse = 1, k_eHiddenAreaMesh_LineLoop = 2, + k_eHiddenAreaMesh_Max = 3, } public enum EVRControllerAxisType { @@ -3536,6 +3644,7 @@ public enum EVRApplicationProperty IsDashboardOverlay_Bool = 60, IsTemplate_Bool = 61, IsInstanced_Bool = 62, + IsInternal_Bool = 63, LastLaunchTime_Uint64 = 70, } public enum EVRApplicationTransitionState @@ -3863,6 +3972,12 @@ public enum EVRScreenshotError public uint m_nFormat; public uint m_nSampleCount; } +[StructLayout(LayoutKind.Sequential)] public struct D3D12TextureData_t +{ + public IntPtr m_pResource; // struct ID3D12Resource * + public IntPtr m_pCommandQueue; // struct ID3D12CommandQueue * + public uint m_nNodeMask; +} [StructLayout(LayoutKind.Sequential)] public struct VREvent_Controller_t { public uint button; @@ -3960,6 +4075,11 @@ public enum EVRScreenshotError { public uint unVRMessageOverlayResponse; } +[StructLayout(LayoutKind.Sequential)] public struct VREvent_Property_t +{ + public ulong container; + public ETrackedDeviceProperty prop; +} [StructLayout(LayoutKind.Sequential)] public struct VREvent_t { public uint eventType; @@ -3988,6 +4108,29 @@ public enum EVRScreenshotError public VRControllerAxis_t rAxis3; public VRControllerAxis_t rAxis4; } +// This structure is for backwards binary compatibility on Linux and OSX only +[StructLayout(LayoutKind.Sequential, Pack = 4)] public struct VRControllerState_t_Packed +{ + public uint unPacketNum; + public ulong ulButtonPressed; + public ulong ulButtonTouched; + public VRControllerAxis_t rAxis0; //VRControllerAxis_t[5] + public VRControllerAxis_t rAxis1; + public VRControllerAxis_t rAxis2; + public VRControllerAxis_t rAxis3; + public VRControllerAxis_t rAxis4; + public void Unpack(ref VRControllerState_t unpacked) + { + unpacked.unPacketNum = this.unPacketNum; + unpacked.ulButtonPressed = this.ulButtonPressed; + unpacked.ulButtonTouched = this.ulButtonTouched; + unpacked.rAxis0 = this.rAxis0; + unpacked.rAxis1 = this.rAxis1; + unpacked.rAxis2 = this.rAxis2; + unpacked.rAxis3 = this.rAxis3; + unpacked.rAxis4 = this.rAxis4; + } +} [StructLayout(LayoutKind.Sequential)] public struct Compositor_OverlaySettings { public uint size; @@ -4116,6 +4259,19 @@ public enum EVRScreenshotError public char unHeight; public IntPtr rubTextureMapData; // const uint8_t * } +// This structure is for backwards binary compatibility on Linux and OSX only +[StructLayout(LayoutKind.Sequential, Pack = 4)] public struct RenderModel_TextureMap_t_Packed +{ + public char unWidth; + public char unHeight; + public IntPtr rubTextureMapData; // const uint8_t * + public void Unpack(ref RenderModel_TextureMap_t unpacked) + { + unpacked.unWidth = this.unWidth; + unpacked.unHeight = this.unHeight; + unpacked.rubTextureMapData = this.rubTextureMapData; + } +} [StructLayout(LayoutKind.Sequential)] public struct RenderModel_t { public IntPtr rVertexData; // const struct vr::RenderModel_Vertex_t * @@ -4124,6 +4280,23 @@ public enum EVRScreenshotError public uint unTriangleCount; public int diffuseTextureId; } +// This structure is for backwards binary compatibility on Linux and OSX only +[StructLayout(LayoutKind.Sequential, Pack = 4)] public struct RenderModel_t_Packed +{ + public IntPtr rVertexData; // const struct vr::RenderModel_Vertex_t * + public uint unVertexCount; + public IntPtr rIndexData; // const uint16_t * + public uint unTriangleCount; + public int diffuseTextureId; + public void Unpack(ref RenderModel_t unpacked) + { + unpacked.rVertexData = this.rVertexData; + unpacked.unVertexCount = this.unVertexCount; + unpacked.rIndexData = this.rIndexData; + unpacked.unTriangleCount = this.unTriangleCount; + unpacked.diffuseTextureId = this.diffuseTextureId; + } +} [StructLayout(LayoutKind.Sequential)] public struct RenderModel_ControllerMode_State_t { [MarshalAs(UnmanagedType.I1)] @@ -4200,6 +4373,20 @@ public static uint GetInitToken() public const uint k_unMaxTrackedDeviceCount = 16; public const uint k_unTrackedDeviceIndexOther = 4294967294; public const uint k_unTrackedDeviceIndexInvalid = 4294967295; + public const ulong k_ulInvalidPropertyContainer = 0; + public const uint k_unInvalidPropertyTag = 0; + public const uint k_unFloatPropertyTag = 1; + public const uint k_unInt32PropertyTag = 2; + public const uint k_unUint64PropertyTag = 3; + public const uint k_unBoolPropertyTag = 4; + public const uint k_unStringPropertyTag = 5; + public const uint k_unHmdMatrix34PropertyTag = 20; + public const uint k_unHmdMatrix44PropertyTag = 21; + public const uint k_unHmdVector3PropertyTag = 22; + public const uint k_unHmdVector4PropertyTag = 23; + public const uint k_unHiddenAreaPropertyTag = 30; + public const uint k_unOpenVRInternalReserved_Start = 1000; + public const uint k_unOpenVRInternalReserved_End = 10000; public const uint k_unMaxPropertyStringSize = 32768; public const uint k_unControllerStateAxisCount = 5; public const ulong k_ulOverlayHandleInvalid = 0; @@ -4213,7 +4400,7 @@ public static uint GetInitToken() public const string IVRApplications_Version = "IVRApplications_006"; public const string IVRChaperone_Version = "IVRChaperone_003"; public const string IVRChaperoneSetup_Version = "IVRChaperoneSetup_005"; - public const string IVRCompositor_Version = "IVRCompositor_019"; + public const string IVRCompositor_Version = "IVRCompositor_020"; public const uint k_unVROverlayMaxKeyLength = 128; public const uint k_unVROverlayMaxNameLength = 128; public const uint k_unMaxOverlayCount = 64; @@ -4280,7 +4467,6 @@ public static uint GetInitToken() public const string k_pch_Lighthouse_PrimaryBasestation_Int32 = "primarybasestation"; public const string k_pch_Lighthouse_DBHistory_Bool = "dbhistory"; public const string k_pch_Null_Section = "driver_null"; - public const string k_pch_Null_EnableNullDriver_Bool = "enable"; public const string k_pch_Null_SerialNumber_String = "serialNumber"; public const string k_pch_Null_ModelNumber_String = "modelNumber"; public const string k_pch_Null_WindowX_Int32 = "windowX"; @@ -4350,6 +4536,7 @@ public static uint GetInitToken() public const string k_pch_Dashboard_EnableDashboard_Bool = "enableDashboard"; public const string k_pch_Dashboard_ArcadeMode_Bool = "arcadeMode"; public const string k_pch_modelskin_Section = "modelskins"; + public const string k_pch_Driver_Enable_Bool = "enable"; public const string IVRScreenshots_Version = "IVRScreenshots_001"; public const string IVRResources_Version = "IVRResources_001"; diff --git a/headers/openvr_api.json b/headers/openvr_api.json index 24509ee0..688e1370 100644 --- a/headers/openvr_api.json +++ b/headers/openvr_api.json @@ -3,6 +3,8 @@ ,{"typedef": "vr::glUInt_t","type": "uint32_t"} ,{"typedef": "vr::SharedTextureHandle_t","type": "uint64_t"} ,{"typedef": "vr::TrackedDeviceIndex_t","type": "uint32_t"} +,{"typedef": "vr::PropertyContainerHandle_t","type": "uint64_t"} +,{"typedef": "vr::PropertyTypeTag_t","type": "uint32_t"} ,{"typedef": "vr::VREvent_Data_t","type": "union VREvent_Data_t"} ,{"typedef": "vr::VRControllerState_t","type": "struct vr::VRControllerState001_t"} ,{"typedef": "vr::VROverlayHandle_t","type": "uint64_t"} @@ -37,6 +39,8 @@ {"name": "TextureType_DirectX","value": "0"} ,{"name": "TextureType_OpenGL","value": "1"} ,{"name": "TextureType_Vulkan","value": "2"} + ,{"name": "TextureType_IOSurface","value": "3"} + ,{"name": "TextureType_DirectX12","value": "4"} ]} , {"enumname": "vr::EColorSpace","values": [ {"name": "ColorSpace_Auto","value": "0"} @@ -103,6 +107,7 @@ ,{"name": "Prop_DriverVersion_String","value": "1031"} ,{"name": "Prop_Firmware_ForceUpdateRequired_Bool","value": "1032"} ,{"name": "Prop_ViveSystemButtonFixRequired_Bool","value": "1033"} + ,{"name": "Prop_ParentDriver_Uint64","value": "1034"} ,{"name": "Prop_ReportsTimeSinceVSync_Bool","value": "2000"} ,{"name": "Prop_SecondsFromVsyncToPhotons_Float","value": "2001"} ,{"name": "Prop_DisplayFrequency_Float","value": "2002"} @@ -141,6 +146,11 @@ ,{"name": "Prop_ScreenshotVerticalFieldOfViewDegrees_Float","value": "2035"} ,{"name": "Prop_DisplaySuppressed_Bool","value": "2036"} ,{"name": "Prop_DisplayAllowNightMode_Bool","value": "2037"} + ,{"name": "Prop_DisplayMCImageWidth_Int32","value": "2038"} + ,{"name": "Prop_DisplayMCImageHeight_Int32","value": "2039"} + ,{"name": "Prop_DisplayMCImageNumChannels_Int32","value": "2040"} + ,{"name": "Prop_DisplayMCImageData_Binary","value": "2041"} + ,{"name": "Prop_UsesDriverDirectMode_Bool","value": "2042"} ,{"name": "Prop_AttachedDeviceId_String","value": "3000"} ,{"name": "Prop_SupportedButtons_Uint64","value": "3001"} ,{"name": "Prop_Axis0Type_Int32","value": "3002"} @@ -165,6 +175,10 @@ ,{"name": "Prop_NamedIconPathDeviceNotReady_String","value": "5006"} ,{"name": "Prop_NamedIconPathDeviceStandby_String","value": "5007"} ,{"name": "Prop_NamedIconPathDeviceAlertLow_String","value": "5008"} + ,{"name": "Prop_DisplayHiddenArea_Binary_Start","value": "5100"} + ,{"name": "Prop_DisplayHiddenArea_Binary_End","value": "5150"} + ,{"name": "Prop_UserConfigPath_String","value": "6000"} + ,{"name": "Prop_InstallPath_String","value": "6001"} ,{"name": "Prop_VendorSpecific_Reserved_Start","value": "10000"} ,{"name": "Prop_VendorSpecific_Reserved_End","value": "10999"} ]} @@ -180,6 +194,7 @@ ,{"name": "TrackedProp_StringExceedsMaximumLength","value": "8"} ,{"name": "TrackedProp_NotYetAvailable","value": "9"} ,{"name": "TrackedProp_PermissionDenied","value": "10"} + ,{"name": "TrackedProp_InvalidOperation","value": "11"} ]} , {"enumname": "vr::EVRSubmitFlags","values": [ {"name": "Submit_Default","value": "0"} @@ -211,6 +226,7 @@ ,{"name": "VREvent_TrackedDeviceRoleChanged","value": "108"} ,{"name": "VREvent_WatchdogWakeUpRequested","value": "109"} ,{"name": "VREvent_LensDistortionChanged","value": "110"} + ,{"name": "VREvent_PropertyChanged","value": "111"} ,{"name": "VREvent_ButtonPress","value": "200"} ,{"name": "VREvent_ButtonUnpress","value": "201"} ,{"name": "VREvent_ButtonTouch","value": "202"} @@ -257,6 +273,7 @@ ,{"name": "VREvent_ScreenshotFailed","value": "522"} ,{"name": "VREvent_SubmitScreenshotToDashboard","value": "523"} ,{"name": "VREvent_ScreenshotProgressToDashboard","value": "524"} + ,{"name": "VREvent_PrimaryDashboardDeviceChanged","value": "525"} ,{"name": "VREvent_Notification_Shown","value": "600"} ,{"name": "VREvent_Notification_Hidden","value": "601"} ,{"name": "VREvent_Notification_BeginInteraction","value": "602"} @@ -290,6 +307,7 @@ ,{"name": "VREvent_ApplicationTransitionNewAppStarted","value": "1302"} ,{"name": "VREvent_ApplicationListUpdated","value": "1303"} ,{"name": "VREvent_ApplicationMimeTypeLoad","value": "1304"} + ,{"name": "VREvent_ApplicationTransitionNewAppLaunchComplete","value": "1305"} ,{"name": "VREvent_Compositor_MirrorWindowShown","value": "1400"} ,{"name": "VREvent_Compositor_MirrorWindowHidden","value": "1401"} ,{"name": "VREvent_Compositor_ChaperoneBoundsShown","value": "1410"} @@ -342,6 +360,7 @@ {"name": "k_eHiddenAreaMesh_Standard","value": "0"} ,{"name": "k_eHiddenAreaMesh_Inverse","value": "1"} ,{"name": "k_eHiddenAreaMesh_LineLoop","value": "2"} + ,{"name": "k_eHiddenAreaMesh_Max","value": "3"} ]} , {"enumname": "vr::EVRControllerAxisType","values": [ {"name": "k_eControllerAxis_None","value": "0"} @@ -559,6 +578,7 @@ ,{"name": "VRApplicationProperty_IsDashboardOverlay_Bool","value": "60"} ,{"name": "VRApplicationProperty_IsTemplate_Bool","value": "61"} ,{"name": "VRApplicationProperty_IsInstanced_Bool","value": "62"} + ,{"name": "VRApplicationProperty_IsInternal_Bool","value": "63"} ,{"name": "VRApplicationProperty_LastLaunchTime_Uint64","value": "70"} ]} , {"enumname": "vr::EVRApplicationTransitionState","values": [ @@ -717,6 +737,34 @@ "constname": "k_unTrackedDeviceIndexOther","consttype": "const uint32_t", "constval": "4294967294"} ,{ "constname": "k_unTrackedDeviceIndexInvalid","consttype": "const uint32_t", "constval": "4294967295"} +,{ + "constname": "k_ulInvalidPropertyContainer","consttype": "const PropertyContainerHandle_t", "constval": "0"} +,{ + "constname": "k_unInvalidPropertyTag","consttype": "const PropertyTypeTag_t", "constval": "0"} +,{ + "constname": "k_unFloatPropertyTag","consttype": "const PropertyTypeTag_t", "constval": "1"} +,{ + "constname": "k_unInt32PropertyTag","consttype": "const PropertyTypeTag_t", "constval": "2"} +,{ + "constname": "k_unUint64PropertyTag","consttype": "const PropertyTypeTag_t", "constval": "3"} +,{ + "constname": "k_unBoolPropertyTag","consttype": "const PropertyTypeTag_t", "constval": "4"} +,{ + "constname": "k_unStringPropertyTag","consttype": "const PropertyTypeTag_t", "constval": "5"} +,{ + "constname": "k_unHmdMatrix34PropertyTag","consttype": "const PropertyTypeTag_t", "constval": "20"} +,{ + "constname": "k_unHmdMatrix44PropertyTag","consttype": "const PropertyTypeTag_t", "constval": "21"} +,{ + "constname": "k_unHmdVector3PropertyTag","consttype": "const PropertyTypeTag_t", "constval": "22"} +,{ + "constname": "k_unHmdVector4PropertyTag","consttype": "const PropertyTypeTag_t", "constval": "23"} +,{ + "constname": "k_unHiddenAreaPropertyTag","consttype": "const PropertyTypeTag_t", "constval": "30"} +,{ + "constname": "k_unOpenVRInternalReserved_Start","consttype": "const PropertyTypeTag_t", "constval": "1000"} +,{ + "constname": "k_unOpenVRInternalReserved_End","consttype": "const PropertyTypeTag_t", "constval": "10000"} ,{ "constname": "k_unMaxPropertyStringSize","consttype": "const uint32_t", "constval": "32768"} ,{ @@ -744,7 +792,7 @@ ,{ "constname": "IVRChaperoneSetup_Version","consttype": "const char *const", "constval": "IVRChaperoneSetup_005"} ,{ - "constname": "IVRCompositor_Version","consttype": "const char *const", "constval": "IVRCompositor_019"} + "constname": "IVRCompositor_Version","consttype": "const char *const", "constval": "IVRCompositor_020"} ,{ "constname": "k_unVROverlayMaxKeyLength","consttype": "const uint32_t", "constval": "128"} ,{ @@ -877,8 +925,6 @@ "constname": "k_pch_Lighthouse_DBHistory_Bool","consttype": "const char *const", "constval": "dbhistory"} ,{ "constname": "k_pch_Null_Section","consttype": "const char *const", "constval": "driver_null"} -,{ - "constname": "k_pch_Null_EnableNullDriver_Bool","consttype": "const char *const", "constval": "enable"} ,{ "constname": "k_pch_Null_SerialNumber_String","consttype": "const char *const", "constval": "serialNumber"} ,{ @@ -1017,6 +1063,8 @@ "constname": "k_pch_Dashboard_ArcadeMode_Bool","consttype": "const char *const", "constval": "arcadeMode"} ,{ "constname": "k_pch_modelskin_Section","consttype": "const char *const", "constval": "modelskins"} +,{ + "constname": "k_pch_Driver_Enable_Bool","consttype": "const char *const", "constval": "enable"} ,{ "constname": "IVRScreenshots_Version","consttype": "const char *const", "constval": "IVRScreenshots_001"} ,{ @@ -1080,6 +1128,10 @@ { "fieldname": "m_nHeight", "fieldtype": "uint32_t"}, { "fieldname": "m_nFormat", "fieldtype": "uint32_t"}, { "fieldname": "m_nSampleCount", "fieldtype": "uint32_t"}]} +,{"struct": "vr::D3D12TextureData_t","fields": [ +{ "fieldname": "m_pResource", "fieldtype": "struct ID3D12Resource *"}, +{ "fieldname": "m_pCommandQueue", "fieldtype": "struct ID3D12CommandQueue *"}, +{ "fieldname": "m_nNodeMask", "fieldtype": "uint32_t"}]} ,{"struct": "vr::VREvent_Controller_t","fields": [ { "fieldname": "button", "fieldtype": "uint32_t"}]} ,{"struct": "vr::VREvent_Mouse_t","fields": [ @@ -1136,6 +1188,9 @@ { "fieldname": "nVisualMode", "fieldtype": "uint32_t"}]} ,{"struct": "vr::VREvent_MessageOverlay_t","fields": [ { "fieldname": "unVRMessageOverlayResponse", "fieldtype": "uint32_t"}]} +,{"struct": "vr::VREvent_Property_t","fields": [ +{ "fieldname": "container", "fieldtype": "PropertyContainerHandle_t"}, +{ "fieldname": "prop", "fieldtype": "enum vr::ETrackedDeviceProperty"}]} ,{"struct": "vr::(anonymous)","fields": [ { "fieldname": "reserved", "fieldtype": "struct vr::VREvent_Reserved_t"}, { "fieldname": "controller", "fieldtype": "struct vr::VREvent_Controller_t"}, @@ -1155,7 +1210,8 @@ { "fieldname": "screenshotProgress", "fieldtype": "struct vr::VREvent_ScreenshotProgress_t"}, { "fieldname": "applicationLaunch", "fieldtype": "struct vr::VREvent_ApplicationLaunch_t"}, { "fieldname": "cameraSurface", "fieldtype": "struct vr::VREvent_EditingCameraSurface_t"}, -{ "fieldname": "messageOverlay", "fieldtype": "struct vr::VREvent_MessageOverlay_t"}]} +{ "fieldname": "messageOverlay", "fieldtype": "struct vr::VREvent_MessageOverlay_t"}, +{ "fieldname": "property", "fieldtype": "struct vr::VREvent_Property_t"}]} ,{"struct": "vr::VREvent_t","fields": [ { "fieldname": "eventType", "fieldtype": "uint32_t"}, { "fieldname": "trackedDeviceIndex", "fieldtype": "TrackedDeviceIndex_t"}, @@ -2094,6 +2150,11 @@ { "paramname": "pchWorkingDirectory" ,"paramtype": "const char *"} ] } +,{ + "classname": "vr::IVRApplications", + "methodname": "GetCurrentSceneProcessId", + "returntype": "uint32_t" +} ,{ "classname": "vr::IVRChaperone", "methodname": "GetCalibrationState", @@ -2559,6 +2620,14 @@ { "paramname": "ppD3D11ShaderResourceView" ,"paramtype": "void **"} ] } +,{ + "classname": "vr::IVRCompositor", + "methodname": "ReleaseMirrorTextureD3D11", + "returntype": "void", + "params": [ +{ "paramname": "pD3D11ShaderResourceView" ,"paramtype": "void *"} + ] +} ,{ "classname": "vr::IVRCompositor", "methodname": "GetMirrorTextureGL", diff --git a/headers/openvr_capi.h b/headers/openvr_capi.h index daffdfb2..a7ab2cfe 100644 --- a/headers/openvr_capi.h +++ b/headers/openvr_capi.h @@ -50,6 +50,9 @@ typedef char bool; #include #endif +typedef uint64_t PropertyContainerHandle_t; +typedef uint32_t PropertyTypeTag_t; + // OpenVR Constants @@ -58,6 +61,20 @@ static const unsigned int k_unTrackedDeviceIndex_Hmd = 0; static const unsigned int k_unMaxTrackedDeviceCount = 16; static const unsigned int k_unTrackedDeviceIndexOther = 4294967294; static const unsigned int k_unTrackedDeviceIndexInvalid = 4294967295; +static const unsigned long k_ulInvalidPropertyContainer = 0; +static const unsigned int k_unInvalidPropertyTag = 0; +static const unsigned int k_unFloatPropertyTag = 1; +static const unsigned int k_unInt32PropertyTag = 2; +static const unsigned int k_unUint64PropertyTag = 3; +static const unsigned int k_unBoolPropertyTag = 4; +static const unsigned int k_unStringPropertyTag = 5; +static const unsigned int k_unHmdMatrix34PropertyTag = 20; +static const unsigned int k_unHmdMatrix44PropertyTag = 21; +static const unsigned int k_unHmdVector3PropertyTag = 22; +static const unsigned int k_unHmdVector4PropertyTag = 23; +static const unsigned int k_unHiddenAreaPropertyTag = 30; +static const unsigned int k_unOpenVRInternalReserved_Start = 1000; +static const unsigned int k_unOpenVRInternalReserved_End = 10000; static const unsigned int k_unMaxPropertyStringSize = 32768; static const unsigned int k_unControllerStateAxisCount = 5; static const unsigned long k_ulOverlayHandleInvalid = 0; @@ -71,7 +88,7 @@ static const char * k_pch_MimeType_GameTheater = "vr/game_theater"; static const char * IVRApplications_Version = "IVRApplications_006"; static const char * IVRChaperone_Version = "IVRChaperone_003"; static const char * IVRChaperoneSetup_Version = "IVRChaperoneSetup_005"; -static const char * IVRCompositor_Version = "IVRCompositor_019"; +static const char * IVRCompositor_Version = "IVRCompositor_020"; static const unsigned int k_unVROverlayMaxKeyLength = 128; static const unsigned int k_unVROverlayMaxNameLength = 128; static const unsigned int k_unMaxOverlayCount = 64; @@ -138,7 +155,6 @@ static const char * k_pch_Lighthouse_DisambiguationDebug_Int32 = "disambiguation static const char * k_pch_Lighthouse_PrimaryBasestation_Int32 = "primarybasestation"; static const char * k_pch_Lighthouse_DBHistory_Bool = "dbhistory"; static const char * k_pch_Null_Section = "driver_null"; -static const char * k_pch_Null_EnableNullDriver_Bool = "enable"; static const char * k_pch_Null_SerialNumber_String = "serialNumber"; static const char * k_pch_Null_ModelNumber_String = "modelNumber"; static const char * k_pch_Null_WindowX_Int32 = "windowX"; @@ -208,6 +224,7 @@ static const char * k_pch_Dashboard_Section = "dashboard"; static const char * k_pch_Dashboard_EnableDashboard_Bool = "enableDashboard"; static const char * k_pch_Dashboard_ArcadeMode_Bool = "arcadeMode"; static const char * k_pch_modelskin_Section = "modelskins"; +static const char * k_pch_Driver_Enable_Bool = "enable"; static const char * IVRScreenshots_Version = "IVRScreenshots_001"; static const char * IVRResources_Version = "IVRResources_001"; @@ -224,6 +241,8 @@ typedef enum ETextureType ETextureType_TextureType_DirectX = 0, ETextureType_TextureType_OpenGL = 1, ETextureType_TextureType_Vulkan = 2, + ETextureType_TextureType_IOSurface = 3, + ETextureType_TextureType_DirectX12 = 4, } ETextureType; typedef enum EColorSpace @@ -302,6 +321,7 @@ typedef enum ETrackedDeviceProperty ETrackedDeviceProperty_Prop_DriverVersion_String = 1031, ETrackedDeviceProperty_Prop_Firmware_ForceUpdateRequired_Bool = 1032, ETrackedDeviceProperty_Prop_ViveSystemButtonFixRequired_Bool = 1033, + ETrackedDeviceProperty_Prop_ParentDriver_Uint64 = 1034, ETrackedDeviceProperty_Prop_ReportsTimeSinceVSync_Bool = 2000, ETrackedDeviceProperty_Prop_SecondsFromVsyncToPhotons_Float = 2001, ETrackedDeviceProperty_Prop_DisplayFrequency_Float = 2002, @@ -340,6 +360,11 @@ typedef enum ETrackedDeviceProperty ETrackedDeviceProperty_Prop_ScreenshotVerticalFieldOfViewDegrees_Float = 2035, ETrackedDeviceProperty_Prop_DisplaySuppressed_Bool = 2036, ETrackedDeviceProperty_Prop_DisplayAllowNightMode_Bool = 2037, + ETrackedDeviceProperty_Prop_DisplayMCImageWidth_Int32 = 2038, + ETrackedDeviceProperty_Prop_DisplayMCImageHeight_Int32 = 2039, + ETrackedDeviceProperty_Prop_DisplayMCImageNumChannels_Int32 = 2040, + ETrackedDeviceProperty_Prop_DisplayMCImageData_Binary = 2041, + ETrackedDeviceProperty_Prop_UsesDriverDirectMode_Bool = 2042, ETrackedDeviceProperty_Prop_AttachedDeviceId_String = 3000, ETrackedDeviceProperty_Prop_SupportedButtons_Uint64 = 3001, ETrackedDeviceProperty_Prop_Axis0Type_Int32 = 3002, @@ -364,6 +389,10 @@ typedef enum ETrackedDeviceProperty ETrackedDeviceProperty_Prop_NamedIconPathDeviceNotReady_String = 5006, ETrackedDeviceProperty_Prop_NamedIconPathDeviceStandby_String = 5007, ETrackedDeviceProperty_Prop_NamedIconPathDeviceAlertLow_String = 5008, + ETrackedDeviceProperty_Prop_DisplayHiddenArea_Binary_Start = 5100, + ETrackedDeviceProperty_Prop_DisplayHiddenArea_Binary_End = 5150, + ETrackedDeviceProperty_Prop_UserConfigPath_String = 6000, + ETrackedDeviceProperty_Prop_InstallPath_String = 6001, ETrackedDeviceProperty_Prop_VendorSpecific_Reserved_Start = 10000, ETrackedDeviceProperty_Prop_VendorSpecific_Reserved_End = 10999, } ETrackedDeviceProperty; @@ -381,6 +410,7 @@ typedef enum ETrackedPropertyError ETrackedPropertyError_TrackedProp_StringExceedsMaximumLength = 8, ETrackedPropertyError_TrackedProp_NotYetAvailable = 9, ETrackedPropertyError_TrackedProp_PermissionDenied = 10, + ETrackedPropertyError_TrackedProp_InvalidOperation = 11, } ETrackedPropertyError; typedef enum EVRSubmitFlags @@ -418,6 +448,7 @@ typedef enum EVREventType EVREventType_VREvent_TrackedDeviceRoleChanged = 108, EVREventType_VREvent_WatchdogWakeUpRequested = 109, EVREventType_VREvent_LensDistortionChanged = 110, + EVREventType_VREvent_PropertyChanged = 111, EVREventType_VREvent_ButtonPress = 200, EVREventType_VREvent_ButtonUnpress = 201, EVREventType_VREvent_ButtonTouch = 202, @@ -464,6 +495,7 @@ typedef enum EVREventType EVREventType_VREvent_ScreenshotFailed = 522, EVREventType_VREvent_SubmitScreenshotToDashboard = 523, EVREventType_VREvent_ScreenshotProgressToDashboard = 524, + EVREventType_VREvent_PrimaryDashboardDeviceChanged = 525, EVREventType_VREvent_Notification_Shown = 600, EVREventType_VREvent_Notification_Hidden = 601, EVREventType_VREvent_Notification_BeginInteraction = 602, @@ -497,6 +529,7 @@ typedef enum EVREventType EVREventType_VREvent_ApplicationTransitionNewAppStarted = 1302, EVREventType_VREvent_ApplicationListUpdated = 1303, EVREventType_VREvent_ApplicationMimeTypeLoad = 1304, + EVREventType_VREvent_ApplicationTransitionNewAppLaunchComplete = 1305, EVREventType_VREvent_Compositor_MirrorWindowShown = 1400, EVREventType_VREvent_Compositor_MirrorWindowHidden = 1401, EVREventType_VREvent_Compositor_ChaperoneBoundsShown = 1410, @@ -557,6 +590,7 @@ typedef enum EHiddenAreaMeshType EHiddenAreaMeshType_k_eHiddenAreaMesh_Standard = 0, EHiddenAreaMeshType_k_eHiddenAreaMesh_Inverse = 1, EHiddenAreaMeshType_k_eHiddenAreaMesh_LineLoop = 2, + EHiddenAreaMeshType_k_eHiddenAreaMesh_Max = 3, } EHiddenAreaMeshType; typedef enum EVRControllerAxisType @@ -802,6 +836,7 @@ typedef enum EVRApplicationProperty EVRApplicationProperty_VRApplicationProperty_IsDashboardOverlay_Bool = 60, EVRApplicationProperty_VRApplicationProperty_IsTemplate_Bool = 61, EVRApplicationProperty_VRApplicationProperty_IsInstanced_Bool = 62, + EVRApplicationProperty_VRApplicationProperty_IsInternal_Bool = 63, EVRApplicationProperty_VRApplicationProperty_LastLaunchTime_Uint64 = 70, } EVRApplicationProperty; @@ -994,11 +1029,14 @@ typedef enum EVRScreenshotError typedef uint32_t TrackedDeviceIndex_t; typedef uint32_t VRNotificationId; typedef uint64_t VROverlayHandle_t; + typedef void * glSharedTextureHandle_t; typedef int32_t glInt_t; typedef uint32_t glUInt_t; typedef uint64_t SharedTextureHandle_t; typedef uint32_t TrackedDeviceIndex_t; +typedef uint64_t PropertyContainerHandle_t; +typedef uint32_t PropertyTypeTag_t; typedef uint64_t VROverlayHandle_t; typedef uint64_t TrackedCameraHandle_t; typedef uint32_t ScreenshotHandle_t; @@ -1126,6 +1164,13 @@ typedef struct VRVulkanTextureData_t uint32_t m_nSampleCount; } VRVulkanTextureData_t; +typedef struct D3D12TextureData_t +{ + struct ID3D12Resource * m_pResource; // struct ID3D12Resource * + struct ID3D12CommandQueue * m_pCommandQueue; // struct ID3D12CommandQueue * + uint32_t m_nNodeMask; +} D3D12TextureData_t; + typedef struct VREvent_Controller_t { uint32_t button; @@ -1239,6 +1284,12 @@ typedef struct VREvent_MessageOverlay_t uint32_t unVRMessageOverlayResponse; } VREvent_MessageOverlay_t; +typedef struct VREvent_Property_t +{ + PropertyContainerHandle_t container; + enum ETrackedDeviceProperty prop; +} VREvent_Property_t; + typedef struct HiddenAreaMesh_t { struct HmdVector2_t * pVertexData; // const struct vr::HmdVector2_t * @@ -1577,6 +1628,7 @@ struct VR_IVRApplications_FnTable char * (OPENVR_FNTABLE_CALLTYPE *GetApplicationsTransitionStateNameFromEnum)(EVRApplicationTransitionState state); bool (OPENVR_FNTABLE_CALLTYPE *IsQuitUserPromptRequested)(); EVRApplicationError (OPENVR_FNTABLE_CALLTYPE *LaunchInternalProcess)(char * pchBinaryPath, char * pchArguments, char * pchWorkingDirectory); + uint32_t (OPENVR_FNTABLE_CALLTYPE *GetCurrentSceneProcessId)(); }; struct VR_IVRChaperone_FnTable @@ -1651,6 +1703,7 @@ struct VR_IVRCompositor_FnTable void (OPENVR_FNTABLE_CALLTYPE *ForceReconnectProcess)(); void (OPENVR_FNTABLE_CALLTYPE *SuspendRendering)(bool bSuspend); EVRCompositorError (OPENVR_FNTABLE_CALLTYPE *GetMirrorTextureD3D11)(EVREye eEye, void * pD3D11DeviceOrResource, void ** ppD3D11ShaderResourceView); + void (OPENVR_FNTABLE_CALLTYPE *ReleaseMirrorTextureD3D11)(void * pD3D11ShaderResourceView); EVRCompositorError (OPENVR_FNTABLE_CALLTYPE *GetMirrorTextureGL)(EVREye eEye, glUInt_t * pglTextureId, glSharedTextureHandle_t * pglSharedTextureHandle); bool (OPENVR_FNTABLE_CALLTYPE *ReleaseSharedGLTexture)(glUInt_t glTextureId, glSharedTextureHandle_t glSharedTextureHandle); void (OPENVR_FNTABLE_CALLTYPE *LockGLSharedTextureForAccess)(glSharedTextureHandle_t glSharedTextureHandle); diff --git a/headers/openvr_driver.h b/headers/openvr_driver.h index c2d550eb..455f8e8e 100644 --- a/headers/openvr_driver.h +++ b/headers/openvr_driver.h @@ -21,6 +21,10 @@ struct VkPhysicalDevice_T; struct VkInstance_T; struct VkQueue_T; +// Forward declarations to avoid requiring d3d12.h +struct ID3D12Resource; +struct ID3D12CommandQueue; + namespace vr { @@ -116,6 +120,8 @@ enum ETextureType TextureType_DirectX = 0, // Handle is an ID3D11Texture TextureType_OpenGL = 1, // Handle is an OpenGL texture name or an OpenGL render buffer name, depending on submit flags TextureType_Vulkan = 2, // Handle is a pointer to a VRVulkanTextureData_t structure + TextureType_IOSurface = 3, // Handle is a macOS cross-process-sharable IOSurface + TextureType_DirectX12 = 4, // Handle is a pointer to a D3D12TextureData_t structure }; enum EColorSpace @@ -199,6 +205,30 @@ enum ETrackingUniverseOrigin TrackingUniverseRawAndUncalibrated = 2, // Poses are provided in the coordinate system defined by the driver. It has Y up and is unified for devices of the same driver. You usually don't want this one. }; +// Refers to a single container of properties +typedef uint64_t PropertyContainerHandle_t; +typedef uint32_t PropertyTypeTag_t; + +static const PropertyContainerHandle_t k_ulInvalidPropertyContainer = 0; +static const PropertyTypeTag_t k_unInvalidPropertyTag = 0; + +// Use these tags to set/get common types as struct properties +static const PropertyTypeTag_t k_unFloatPropertyTag = 1; +static const PropertyTypeTag_t k_unInt32PropertyTag = 2; +static const PropertyTypeTag_t k_unUint64PropertyTag = 3; +static const PropertyTypeTag_t k_unBoolPropertyTag = 4; +static const PropertyTypeTag_t k_unStringPropertyTag = 5; + +static const PropertyTypeTag_t k_unHmdMatrix34PropertyTag = 20; +static const PropertyTypeTag_t k_unHmdMatrix44PropertyTag = 21; +static const PropertyTypeTag_t k_unHmdVector3PropertyTag = 22; +static const PropertyTypeTag_t k_unHmdVector4PropertyTag = 23; + +static const PropertyTypeTag_t k_unHiddenAreaPropertyTag = 30; + +static const PropertyTypeTag_t k_unOpenVRInternalReserved_Start = 1000; +static const PropertyTypeTag_t k_unOpenVRInternalReserved_End = 10000; + /** Each entry in this enum represents a property that can be retrieved about a * tracked device. Many fields are only valid for one ETrackedDeviceClass. */ @@ -241,6 +271,8 @@ enum ETrackedDeviceProperty Prop_DriverVersion_String = 1031, Prop_Firmware_ForceUpdateRequired_Bool = 1032, Prop_ViveSystemButtonFixRequired_Bool = 1033, + Prop_ParentDriver_Uint64 = 1034, + // Properties that are unique to TrackedDeviceClass_HMD Prop_ReportsTimeSinceVSync_Bool = 2000, @@ -281,6 +313,11 @@ enum ETrackedDeviceProperty Prop_ScreenshotVerticalFieldOfViewDegrees_Float = 2035, Prop_DisplaySuppressed_Bool = 2036, Prop_DisplayAllowNightMode_Bool = 2037, + Prop_DisplayMCImageWidth_Int32 = 2038, + Prop_DisplayMCImageHeight_Int32 = 2039, + Prop_DisplayMCImageNumChannels_Int32 = 2040, + Prop_DisplayMCImageData_Binary = 2041, + Prop_UsesDriverDirectMode_Bool = 2042, // Properties that are unique to TrackedDeviceClass_Controller Prop_AttachedDeviceId_String = 3000, @@ -312,6 +349,14 @@ enum ETrackedDeviceProperty Prop_NamedIconPathDeviceStandby_String = 5007, // PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others Prop_NamedIconPathDeviceAlertLow_String = 5008, // PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others + // Properties that are used by helpers, but are opaque to applications + Prop_DisplayHiddenArea_Binary_Start = 5100, + Prop_DisplayHiddenArea_Binary_End = 5150, + + // Properties that are unique to drivers + Prop_UserConfigPath_String = 6000, + Prop_InstallPath_String = 6001, + // Vendors are free to expose private debug data in this reserved region Prop_VendorSpecific_Reserved_Start = 10000, Prop_VendorSpecific_Reserved_End = 10999, @@ -327,13 +372,14 @@ enum ETrackedPropertyError TrackedProp_WrongDataType = 1, TrackedProp_WrongDeviceClass = 2, TrackedProp_BufferTooSmall = 3, - TrackedProp_UnknownProperty = 4, + TrackedProp_UnknownProperty = 4, // Driver has not set the property (and may not ever). TrackedProp_InvalidDevice = 5, TrackedProp_CouldNotContactServer = 6, TrackedProp_ValueNotProvidedByDevice = 7, TrackedProp_StringExceedsMaximumLength = 8, TrackedProp_NotYetAvailable = 9, // The property value isn't known yet, but is expected soon. Call again later. TrackedProp_PermissionDenied = 10, + TrackedProp_InvalidOperation = 11, }; /** Allows the application to control what part of the provided texture will be used in the @@ -376,6 +422,14 @@ struct VRVulkanTextureData_t uint32_t m_nWidth, m_nHeight, m_nFormat, m_nSampleCount; }; +/** Data required for passing D3D12 textures to IVRCompositor::Submit. +* Be sure to call OpenVR_Shutdown before destroying these resources. */ +struct D3D12TextureData_t +{ + ID3D12Resource *m_pResource; + ID3D12CommandQueue *m_pCommandQueue; + uint32_t m_nNodeMask; +}; /** Status of the overall system or tracked objects */ enum EVRState @@ -399,7 +453,7 @@ enum EVREventType VREvent_TrackedDeviceActivated = 100, VREvent_TrackedDeviceDeactivated = 101, VREvent_TrackedDeviceUpdated = 102, - VREvent_TrackedDeviceUserInteractionStarted = 103, + VREvent_TrackedDeviceUserInteractionStarted = 103, VREvent_TrackedDeviceUserInteractionEnded = 104, VREvent_IpdChanged = 105, VREvent_EnterStandbyMode = 106, @@ -407,6 +461,7 @@ enum EVREventType VREvent_TrackedDeviceRoleChanged = 108, VREvent_WatchdogWakeUpRequested = 109, VREvent_LensDistortionChanged = 110, + VREvent_PropertyChanged = 111, VREvent_ButtonPress = 200, // data is controller VREvent_ButtonUnpress = 201, // data is controller @@ -436,78 +491,81 @@ enum EVREventType VREvent_OverlayShown = 500, VREvent_OverlayHidden = 501, - VREvent_DashboardActivated = 502, - VREvent_DashboardDeactivated = 503, - VREvent_DashboardThumbSelected = 504, // Sent to the overlay manager - data is overlay - VREvent_DashboardRequested = 505, // Sent to the overlay manager - data is overlay - VREvent_ResetDashboard = 506, // Send to the overlay manager - VREvent_RenderToast = 507, // Send to the dashboard to render a toast - data is the notification ID - VREvent_ImageLoaded = 508, // Sent to overlays when a SetOverlayRaw or SetOverlayFromFile call finishes loading - VREvent_ShowKeyboard = 509, // Sent to keyboard renderer in the dashboard to invoke it - VREvent_HideKeyboard = 510, // Sent to keyboard renderer in the dashboard to hide it - VREvent_OverlayGamepadFocusGained = 511, // Sent to an overlay when IVROverlay::SetFocusOverlay is called on it - VREvent_OverlayGamepadFocusLost = 512, // Send to an overlay when it previously had focus and IVROverlay::SetFocusOverlay is called on something else + VREvent_DashboardActivated = 502, + VREvent_DashboardDeactivated = 503, + VREvent_DashboardThumbSelected = 504, // Sent to the overlay manager - data is overlay + VREvent_DashboardRequested = 505, // Sent to the overlay manager - data is overlay + VREvent_ResetDashboard = 506, // Send to the overlay manager + VREvent_RenderToast = 507, // Send to the dashboard to render a toast - data is the notification ID + VREvent_ImageLoaded = 508, // Sent to overlays when a SetOverlayRaw or SetOverlayFromFile call finishes loading + VREvent_ShowKeyboard = 509, // Sent to keyboard renderer in the dashboard to invoke it + VREvent_HideKeyboard = 510, // Sent to keyboard renderer in the dashboard to hide it + VREvent_OverlayGamepadFocusGained = 511, // Sent to an overlay when IVROverlay::SetFocusOverlay is called on it + VREvent_OverlayGamepadFocusLost = 512, // Send to an overlay when it previously had focus and IVROverlay::SetFocusOverlay is called on something else VREvent_OverlaySharedTextureChanged = 513, - VREvent_DashboardGuideButtonDown = 514, - VREvent_DashboardGuideButtonUp = 515, - VREvent_ScreenshotTriggered = 516, // Screenshot button combo was pressed, Dashboard should request a screenshot - VREvent_ImageFailed = 517, // Sent to overlays when a SetOverlayRaw or SetOverlayfromFail fails to load - VREvent_DashboardOverlayCreated = 518, + VREvent_DashboardGuideButtonDown = 514, + VREvent_DashboardGuideButtonUp = 515, + VREvent_ScreenshotTriggered = 516, // Screenshot button combo was pressed, Dashboard should request a screenshot + VREvent_ImageFailed = 517, // Sent to overlays when a SetOverlayRaw or SetOverlayfromFail fails to load + VREvent_DashboardOverlayCreated = 518, // Screenshot API - VREvent_RequestScreenshot = 520, // Sent by vrclient application to compositor to take a screenshot - VREvent_ScreenshotTaken = 521, // Sent by compositor to the application that the screenshot has been taken - VREvent_ScreenshotFailed = 522, // Sent by compositor to the application that the screenshot failed to be taken - VREvent_SubmitScreenshotToDashboard = 523, // Sent by compositor to the dashboard that a completed screenshot was submitted - VREvent_ScreenshotProgressToDashboard = 524, // Sent by compositor to the dashboard that a completed screenshot was submitted + VREvent_RequestScreenshot = 520, // Sent by vrclient application to compositor to take a screenshot + VREvent_ScreenshotTaken = 521, // Sent by compositor to the application that the screenshot has been taken + VREvent_ScreenshotFailed = 522, // Sent by compositor to the application that the screenshot failed to be taken + VREvent_SubmitScreenshotToDashboard = 523, // Sent by compositor to the dashboard that a completed screenshot was submitted + VREvent_ScreenshotProgressToDashboard = 524, // Sent by compositor to the dashboard that a completed screenshot was submitted + + VREvent_PrimaryDashboardDeviceChanged = 525, VREvent_Notification_Shown = 600, VREvent_Notification_Hidden = 601, VREvent_Notification_BeginInteraction = 602, VREvent_Notification_Destroyed = 603, - VREvent_Quit = 700, // data is process - VREvent_ProcessQuit = 701, // data is process - VREvent_QuitAborted_UserPrompt = 702, // data is process - VREvent_QuitAcknowledged = 703, // data is process - VREvent_DriverRequestedQuit = 704, // The driver has requested that SteamVR shut down + VREvent_Quit = 700, // data is process + VREvent_ProcessQuit = 701, // data is process + VREvent_QuitAborted_UserPrompt = 702, // data is process + VREvent_QuitAcknowledged = 703, // data is process + VREvent_DriverRequestedQuit = 704, // The driver has requested that SteamVR shut down - VREvent_ChaperoneDataHasChanged = 800, - VREvent_ChaperoneUniverseHasChanged = 801, - VREvent_ChaperoneTempDataHasChanged = 802, - VREvent_ChaperoneSettingsHaveChanged = 803, - VREvent_SeatedZeroPoseReset = 804, + VREvent_ChaperoneDataHasChanged = 800, + VREvent_ChaperoneUniverseHasChanged = 801, + VREvent_ChaperoneTempDataHasChanged = 802, + VREvent_ChaperoneSettingsHaveChanged = 803, + VREvent_SeatedZeroPoseReset = 804, - VREvent_AudioSettingsHaveChanged = 820, + VREvent_AudioSettingsHaveChanged = 820, - VREvent_BackgroundSettingHasChanged = 850, - VREvent_CameraSettingsHaveChanged = 851, - VREvent_ReprojectionSettingHasChanged = 852, - VREvent_ModelSkinSettingsHaveChanged = 853, - VREvent_EnvironmentSettingsHaveChanged = 854, - VREvent_PowerSettingsHaveChanged = 855, + VREvent_BackgroundSettingHasChanged = 850, + VREvent_CameraSettingsHaveChanged = 851, + VREvent_ReprojectionSettingHasChanged = 852, + VREvent_ModelSkinSettingsHaveChanged = 853, + VREvent_EnvironmentSettingsHaveChanged = 854, + VREvent_PowerSettingsHaveChanged = 855, - VREvent_StatusUpdate = 900, + VREvent_StatusUpdate = 900, - VREvent_MCImageUpdated = 1000, + VREvent_MCImageUpdated = 1000, - VREvent_FirmwareUpdateStarted = 1100, - VREvent_FirmwareUpdateFinished = 1101, + VREvent_FirmwareUpdateStarted = 1100, + VREvent_FirmwareUpdateFinished = 1101, - VREvent_KeyboardClosed = 1200, - VREvent_KeyboardCharInput = 1201, - VREvent_KeyboardDone = 1202, // Sent when DONE button clicked on keyboard + VREvent_KeyboardClosed = 1200, + VREvent_KeyboardCharInput = 1201, + VREvent_KeyboardDone = 1202, // Sent when DONE button clicked on keyboard - VREvent_ApplicationTransitionStarted = 1300, - VREvent_ApplicationTransitionAborted = 1301, - VREvent_ApplicationTransitionNewAppStarted = 1302, - VREvent_ApplicationListUpdated = 1303, - VREvent_ApplicationMimeTypeLoad = 1304, + VREvent_ApplicationTransitionStarted = 1300, + VREvent_ApplicationTransitionAborted = 1301, + VREvent_ApplicationTransitionNewAppStarted = 1302, + VREvent_ApplicationListUpdated = 1303, + VREvent_ApplicationMimeTypeLoad = 1304, + VREvent_ApplicationTransitionNewAppLaunchComplete = 1305, - VREvent_Compositor_MirrorWindowShown = 1400, - VREvent_Compositor_MirrorWindowHidden = 1401, - VREvent_Compositor_ChaperoneBoundsShown = 1410, - VREvent_Compositor_ChaperoneBoundsHidden = 1411, + VREvent_Compositor_MirrorWindowShown = 1400, + VREvent_Compositor_MirrorWindowHidden = 1401, + VREvent_Compositor_ChaperoneBoundsShown = 1410, + VREvent_Compositor_ChaperoneBoundsHidden = 1411, VREvent_TrackedCamera_StartVideoStream = 1500, VREvent_TrackedCamera_StopVideoStream = 1501, @@ -515,15 +573,15 @@ enum EVREventType VREvent_TrackedCamera_ResumeVideoStream = 1503, VREvent_TrackedCamera_EditingSurface = 1550, - VREvent_PerformanceTest_EnableCapture = 1600, - VREvent_PerformanceTest_DisableCapture = 1601, - VREvent_PerformanceTest_FidelityLevel = 1602, + VREvent_PerformanceTest_EnableCapture = 1600, + VREvent_PerformanceTest_DisableCapture = 1601, + VREvent_PerformanceTest_FidelityLevel = 1602, - VREvent_MessageOverlay_Closed = 1650, + VREvent_MessageOverlay_Closed = 1650, // Vendors are free to expose private events in this reserved region - VREvent_VendorSpecific_Reserved_Start = 10000, - VREvent_VendorSpecific_Reserved_End = 19999, + VREvent_VendorSpecific_Reserved_Start = 10000, + VREvent_VendorSpecific_Reserved_End = 19999, }; @@ -711,6 +769,12 @@ struct VREvent_MessageOverlay_t uint32_t unVRMessageOverlayResponse; // vr::VRMessageOverlayResponse enum }; +struct VREvent_Property_t +{ + PropertyContainerHandle_t container; + ETrackedDeviceProperty prop; +}; + /** NOTE!!! If you change this you MUST manually update openvr_interop.cs.py */ typedef union { @@ -733,6 +797,7 @@ typedef union VREvent_ApplicationLaunch_t applicationLaunch; VREvent_EditingCameraSurface_t cameraSurface; VREvent_MessageOverlay_t messageOverlay; + VREvent_Property_t property; } VREvent_Data_t; /** An event posted by the server to all running applications */ @@ -764,6 +829,8 @@ enum EHiddenAreaMeshType k_eHiddenAreaMesh_Standard = 0, k_eHiddenAreaMesh_Inverse = 1, k_eHiddenAreaMesh_LineLoop = 2, + + k_eHiddenAreaMesh_Max = 3, }; @@ -1325,7 +1392,6 @@ namespace vr //----------------------------------------------------------------------------- // null keys static const char * const k_pch_Null_Section = "driver_null"; - static const char * const k_pch_Null_EnableNullDriver_Bool = "enable"; static const char * const k_pch_Null_SerialNumber_String = "serialNumber"; static const char * const k_pch_Null_ModelNumber_String = "modelNumber"; static const char * const k_pch_Null_WindowX_Int32 = "windowX"; @@ -1426,6 +1492,10 @@ namespace vr // model skin keys static const char * const k_pch_modelskin_Section = "modelskins"; + //----------------------------------------------------------------------------- + // driver keys - These could be checked in any driver_ section + static const char * const k_pch_Driver_Enable_Bool = "enable"; + } // namespace vr // iservertrackeddevicedriver.h @@ -1543,37 +1613,11 @@ class ITrackedDeviceServerDriver // Tracking Methods // ------------------------------------ virtual DriverPose_t GetPose() = 0; - - // ------------------------------------ - // Property Methods - // ------------------------------------ - - /** Returns a bool property. If the property is not available this function will return false. */ - virtual bool GetBoolTrackedDeviceProperty( ETrackedDeviceProperty prop, ETrackedPropertyError *pError ) = 0; - - /** Returns a float property. If the property is not available this function will return 0. */ - virtual float GetFloatTrackedDeviceProperty( ETrackedDeviceProperty prop, ETrackedPropertyError *pError ) = 0; - - /** Returns an int property. If the property is not available this function will return 0. */ - virtual int32_t GetInt32TrackedDeviceProperty( ETrackedDeviceProperty prop, ETrackedPropertyError *pError ) = 0; - - /** Returns a uint64 property. If the property is not available this function will return 0. */ - virtual uint64_t GetUint64TrackedDeviceProperty( ETrackedDeviceProperty prop, ETrackedPropertyError *pError ) = 0; - - /** Returns a matrix property. If the device index is not valid or the property is not a matrix type, this function will return identity. */ - virtual HmdMatrix34_t GetMatrix34TrackedDeviceProperty( ETrackedDeviceProperty prop, ETrackedPropertyError *pError ) = 0; - - /** Returns a string property. If the property is not available this function will return 0 and pError will be - * set to an error. Otherwise it returns the length of the number of bytes necessary to hold this string including - * the trailing null. If the buffer is too small the error will be TrackedProp_BufferTooSmall. Drivers may not - * return strings longer than k_unMaxPropertyStringSize. */ - virtual uint32_t GetStringTrackedDeviceProperty( ETrackedDeviceProperty prop, char *pchValue, uint32_t unBufferSize, ETrackedPropertyError *pError ) = 0; - }; -static const char *ITrackedDeviceServerDriver_Version = "ITrackedDeviceServerDriver_004"; +static const char *ITrackedDeviceServerDriver_Version = "ITrackedDeviceServerDriver_005"; } // ivrdisplaycomponent.h @@ -1745,73 +1789,21 @@ namespace vr class ITrackedDeviceServerDriver; struct TrackedDeviceDriverInfo_t; struct DriverPose_t; - -class IDriverLog -{ -public: - /** Writes a log message to the log file prefixed with the driver name */ - virtual void Log( const char *pchLogMessage ) = 0; -}; +typedef PropertyContainerHandle_t DriverHandle_t; /** This interface is provided by vrserver to allow the driver to notify * the system when something changes about a device. These changes must * not change the serial number or class of the device because those values * are permanently associated with the device's index. */ -class IServerDriverHost +class IVRDriverContext { public: - /** Notifies the server that a tracked device has been added. If this function returns true - * the server will call Activate on the device. If it returns false some kind of error - * has occurred and the device will not be activated. */ - virtual bool TrackedDeviceAdded( const char *pchDeviceSerialNumber ) = 0; - - /** Notifies the server that a tracked device's pose has been updated */ - virtual void TrackedDevicePoseUpdated( uint32_t unWhichDevice, const DriverPose_t & newPose ) = 0; + /** Returns the requested interface. If the interface was not available it will return NULL and fill + * out the error. */ + virtual void *GetGenericInterface( const char *pchInterfaceVersion, EVRInitError *peError = nullptr ) = 0; - /** Notifies the server that the property cache for the specified device should be invalidated */ - virtual void TrackedDevicePropertiesChanged( uint32_t unWhichDevice ) = 0; - - /** Notifies the server that vsync has occurred on the the display attached to the device. This is - * only permitted on devices of the HMD class. */ - virtual void VsyncEvent( double vsyncTimeOffsetSeconds ) = 0; - - /** notifies the server that the button was pressed */ - virtual void TrackedDeviceButtonPressed( uint32_t unWhichDevice, EVRButtonId eButtonId, double eventTimeOffset ) = 0; - - /** notifies the server that the button was unpressed */ - virtual void TrackedDeviceButtonUnpressed( uint32_t unWhichDevice, EVRButtonId eButtonId, double eventTimeOffset ) = 0; - - /** notifies the server that the button was pressed */ - virtual void TrackedDeviceButtonTouched( uint32_t unWhichDevice, EVRButtonId eButtonId, double eventTimeOffset ) = 0; - - /** notifies the server that the button was unpressed */ - virtual void TrackedDeviceButtonUntouched( uint32_t unWhichDevice, EVRButtonId eButtonId, double eventTimeOffset ) = 0; - - /** notifies the server than a controller axis changed */ - virtual void TrackedDeviceAxisUpdated( uint32_t unWhichDevice, uint32_t unWhichAxis, const VRControllerAxis_t & axisState ) = 0; - - /** Notifies the server that the MC image has been updated for the display attached to the device. This is - * only permitted on devices of the HMD class. */ - virtual void MCImageUpdated() = 0; - - /** always returns a pointer to a valid interface pointer of IVRSettings */ - virtual IVRSettings *GetSettings( const char *pchInterfaceVersion ) = 0; - - /** Notifies the server that the physical IPD adjustment has been moved on the HMD */ - virtual void PhysicalIpdSet( uint32_t unWhichDevice, float fPhysicalIpdMeters ) = 0; - - /** Notifies the server that the proximity sensor on the specified device */ - virtual void ProximitySensorState( uint32_t unWhichDevice, bool bProximitySensorTriggered ) = 0; - - /** Sends a vendor specific event (VREvent_VendorSpecific_Reserved_Start..VREvent_VendorSpecific_Reserved_End */ - virtual void VendorSpecificEvent( uint32_t unWhichDevice, vr::EVREventType eventType, const VREvent_Data_t & eventData, double eventTimeOffset ) = 0; - - /** Returns true if SteamVR is exiting */ - virtual bool IsExiting() = 0; - - /** Returns true and fills the event with the next event on the queue if there is one. If there are no events - * this method returns false. uncbVREvent should be the size in bytes of the VREvent_t struct */ - virtual bool PollNextEvent( VREvent_t *pEvent, uint32_t uncbVREvent ) = 0; + /** Returns the property container handle for this driver */ + virtual DriverHandle_t GetDriverHandle() = 0; }; @@ -1828,7 +1820,7 @@ class IServerTrackedDeviceProvider * config files. * pchDriverInstallDir - The absolute path of the root directory for the driver. */ - virtual EVRInitError Init( IDriverLog *pDriverLog, vr::IServerDriverHost *pDriverHost, const char *pchUserDriverConfigDir, const char *pchDriverInstallDir ) = 0; + virtual EVRInitError Init( IVRDriverContext *pDriverContext ) = 0; /** cleans up the driver right before it is unloaded */ virtual void Cleanup() = 0; @@ -1836,15 +1828,6 @@ class IServerTrackedDeviceProvider /** Returns the version of the ITrackedDeviceServerDriver interface used by this driver */ virtual const char * const *GetInterfaceVersions() = 0; - /** returns the number of HMDs that this driver manages that are physically connected. */ - virtual uint32_t GetTrackedDeviceCount() = 0; - - /** returns a single HMD */ - virtual ITrackedDeviceServerDriver *GetTrackedDeviceDriver( uint32_t unWhich ) = 0; - - /** returns a single HMD by ID */ - virtual ITrackedDeviceServerDriver* FindTrackedDeviceDriver( const char *pchId ) = 0; - /** Allows the driver do to some work in the main loop of the server. */ virtual void RunFrame() = 0; @@ -1865,104 +1848,497 @@ class IServerTrackedDeviceProvider }; -static const char *IServerTrackedDeviceProvider_Version = "IServerTrackedDeviceProvider_003"; +static const char *IServerTrackedDeviceProvider_Version = "IServerTrackedDeviceProvider_004"; -/** This interface is provided by vrclient to allow the driver call back and query various information */ -class IClientDriverHost + + +/** This interface must be implemented in each driver. It will be loaded in vrclient.dll */ +class IVRWatchdogProvider { public: - /** Returns the device class of a tracked device. If there has not been a device connected in this slot - * since the application started this function will return TrackedDevice_Invalid. For previous detected - * devices the function will return the previously observed device class. - * - * To determine which devices exist on the system, just loop from 0 to k_unMaxTrackedDeviceCount and check - * the device class. Every device with something other than TrackedDevice_Invalid is associated with an - * actual tracked device. */ - virtual ETrackedDeviceClass GetTrackedDeviceClass( vr::TrackedDeviceIndex_t unDeviceIndex ) = 0; + /** initializes the driver in watchdog mode. */ + virtual EVRInitError Init( IVRDriverContext *pDriverContext ) = 0; - /** Returns true if there is a device connected in this slot. */ - virtual bool IsTrackedDeviceConnected( vr::TrackedDeviceIndex_t unDeviceIndex ) = 0; + /** cleans up the driver right before it is unloaded */ + virtual void Cleanup() = 0; +}; + +static const char *IVRWatchdogProvider_Version = "IVRWatchdogProvider_001"; + +} +// ivrproperties.h +#include + +namespace vr +{ + + enum EPropertyWriteType + { + PropertyWrite_Set = 0, + PropertyWrite_Erase = 1, + PropertyWrite_SetError = 2 + }; + + struct PropertyWrite_t + { + ETrackedDeviceProperty prop; + EPropertyWriteType writeType; + ETrackedPropertyError eSetError; + void *pvBuffer; + uint32_t unBufferSize; + PropertyTypeTag_t unTag; + ETrackedPropertyError eError; + }; + + struct PropertyRead_t + { + ETrackedDeviceProperty prop; + void *pvBuffer; + uint32_t unBufferSize; + PropertyTypeTag_t unTag; + uint32_t unRequiredBufferSize; + ETrackedPropertyError eError; + }; + + +class IVRProperties +{ +public: - /** Returns a bool property. If the device index is not valid or the property is not a bool type this function will return false. */ - virtual bool GetBoolTrackedDeviceProperty( vr::TrackedDeviceIndex_t unDeviceIndex, ETrackedDeviceProperty prop, ETrackedPropertyError *pError = 0L ) = 0; + /** Reads a set of properties atomically. See the PropertyReadBatch_t struct for more information. */ + virtual ETrackedPropertyError ReadPropertyBatch( PropertyContainerHandle_t ulContainerHandle, PropertyRead_t *pBatch, uint32_t unBatchEntryCount ) = 0; - /** Returns a float property. If the device index is not valid or the property is not a float type this function will return 0. */ - virtual float GetFloatTrackedDeviceProperty( vr::TrackedDeviceIndex_t unDeviceIndex, ETrackedDeviceProperty prop, ETrackedPropertyError *pError = 0L ) = 0; + /** Writes a set of properties atomically. See the PropertyWriteBatch_t struct for more information. */ + virtual ETrackedPropertyError WritePropertyBatch( PropertyContainerHandle_t ulContainerHandle, PropertyWrite_t *pBatch, uint32_t unBatchEntryCount ) = 0; - /** Returns an int property. If the device index is not valid or the property is not a int type this function will return 0. */ - virtual int32_t GetInt32TrackedDeviceProperty( vr::TrackedDeviceIndex_t unDeviceIndex, ETrackedDeviceProperty prop, ETrackedPropertyError *pError = 0L ) = 0; + /** returns a string that corresponds with the specified property error. The string will be the name + * of the error enum value for all valid error codes */ + virtual const char *GetPropErrorNameFromEnum( ETrackedPropertyError error ) = 0; - /** Returns a uint64 property. If the device index is not valid or the property is not a uint64 type this function will return 0. */ - virtual uint64_t GetUint64TrackedDeviceProperty( vr::TrackedDeviceIndex_t unDeviceIndex, ETrackedDeviceProperty prop, ETrackedPropertyError *pError = 0L ) = 0; + /** Returns a container handle given a tracked device index */ + virtual PropertyContainerHandle_t TrackedDeviceToPropertyContainer( TrackedDeviceIndex_t nDevice ) = 0; - /** Returns a string property. If the device index is not valid or the property is not a float type this function will +}; + +static const char * const IVRProperties_Version = "IVRProperties_001"; + +class CVRPropertyHelpers +{ +public: + CVRPropertyHelpers( IVRProperties * pProperties ) : m_pProperties( pProperties ) {} + + /** Returns a scaler property. If the device index is not valid or the property value type does not match, + * this function will return false. */ + bool GetBoolProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, ETrackedPropertyError *pError = 0L ); + float GetFloatProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, ETrackedPropertyError *pError = 0L ); + int32_t GetInt32Property( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, ETrackedPropertyError *pError = 0L ); + uint64_t GetUint64Property( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, ETrackedPropertyError *pError = 0L ); + + /** Returns a single typed property. If the device index is not valid or the property is not a string type this function will * return 0. Otherwise it returns the length of the number of bytes necessary to hold this string including the trailing - * null. Strings will generally fit in buffers of k_unTrackingStringSize characters. */ - virtual uint32_t GetStringTrackedDeviceProperty( vr::TrackedDeviceIndex_t unDeviceIndex, ETrackedDeviceProperty prop, char *pchValue, uint32_t unBufferSize, ETrackedPropertyError *pError = 0L ) = 0; + * null. Strings will always fit in buffers of k_unMaxPropertyStringSize characters. */ + uint32_t GetProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, VR_OUT_STRING() void *pvBuffer, uint32_t unBufferSize, PropertyTypeTag_t *punTag, ETrackedPropertyError *pError = 0L ); - /** always returns a pointer to a valid interface pointer of IVRSettings */ - virtual void *GetGenericInterface( const char *pchInterfaceVersion ) = 0; - /** Client drivers in watchdog mode should call this when they have received a signal from hardware that should - * cause SteamVR to start */ - virtual void WatchdogWakeUp() = 0; + /** Returns a string property. If the device index is not valid or the property is not a string type this function will + * return 0. Otherwise it returns the length of the number of bytes necessary to hold this string including the trailing + * null. Strings will always fit in buffers of k_unMaxPropertyStringSize characters. */ + uint32_t GetStringProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, VR_OUT_STRING() char *pchValue, uint32_t unBufferSize, ETrackedPropertyError *pError = 0L ); + + /** Returns a string property as a std::string. If the device index is not valid or the property is not a string type this function will + * return an empty string. */ + std::string GetStringProperty( vr::PropertyContainerHandle_t ulContainer, vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError *peError = nullptr ); + + /** Sets a scaler property. The new value will be returned on any subsequent call to get this property in any process. */ + ETrackedPropertyError SetBoolProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, bool bNewValue ); + ETrackedPropertyError SetFloatProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, float fNewValue ); + ETrackedPropertyError SetInt32Property( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, int32_t nNewValue ); + ETrackedPropertyError SetUint64Property( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, uint64_t ulNewValue ); + + /** Sets a string property. The new value will be returned on any subsequent call to get this property in any process. */ + ETrackedPropertyError SetStringProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, const char *pchNewValue ); + + /** Sets a single typed property. The new value will be returned on any subsequent call to get this property in any process. */ + ETrackedPropertyError SetProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, void *pvNewValue, uint32_t unNewValueSize, PropertyTypeTag_t unTag ); + + /** Sets the error return value for a property. This value will be returned on all subsequent requests to get the property */ + ETrackedPropertyError SetPropertyError( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, ETrackedPropertyError eError ); + + /** Clears any value or error set for the property. */ + ETrackedPropertyError EraseProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop ); + + /* Turns a device index into a property container handle. */ + PropertyContainerHandle_t TrackedDeviceToPropertyContainer( TrackedDeviceIndex_t nDevice ) { return m_pProperties->TrackedDeviceToPropertyContainer( nDevice ); } + +private: + template + T GetPropertyHelper( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, ETrackedPropertyError *pError, T bDefault, PropertyTypeTag_t unTypeTag ); + + IVRProperties *m_pProperties; }; -/** Defines the mode that the client driver should start in. */ -enum EClientDriverMode +inline uint32_t CVRPropertyHelpers::GetProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, VR_OUT_STRING() void *pvBuffer, uint32_t unBufferSize, PropertyTypeTag_t *punTag, ETrackedPropertyError *pError ) +{ + PropertyRead_t batch; + batch.prop = prop; + batch.pvBuffer = pvBuffer; + batch.unBufferSize = unBufferSize; + + m_pProperties->ReadPropertyBatch( ulContainerHandle, &batch, 1 ); + + if ( pError ) + { + *pError = batch.eError; + } + + if ( punTag ) + { + *punTag = batch.unTag; + } + + return batch.unRequiredBufferSize; +} + + +/** Sets a single typed property. The new value will be returned on any subsequent call to get this property in any process. */ +inline ETrackedPropertyError CVRPropertyHelpers::SetProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, void *pvNewValue, uint32_t unNewValueSize, PropertyTypeTag_t unTag ) +{ + PropertyWrite_t batch; + batch.writeType = PropertyWrite_Set; + batch.prop = prop; + batch.pvBuffer = pvNewValue; + batch.unBufferSize = unNewValueSize; + batch.unTag = unTag; + + m_pProperties->WritePropertyBatch( ulContainerHandle, &batch, 1 ); + + return batch.eError; +} + + +/** Returns a string property. If the device index is not valid or the property is not a string type this function will +* return 0. Otherwise it returns the length of the number of bytes necessary to hold this string including the trailing +* null. Strings will always fit in buffers of k_unMaxPropertyStringSize characters. */ +inline uint32_t CVRPropertyHelpers::GetStringProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, VR_OUT_STRING() char *pchValue, uint32_t unBufferSize, ETrackedPropertyError *pError ) +{ + PropertyTypeTag_t unTag; + ETrackedPropertyError error; + uint32_t unRequiredSize = GetProperty( ulContainerHandle, prop, pchValue, unBufferSize, &unTag, &error ); + if ( unTag != k_unStringPropertyTag && error == TrackedProp_Success ) + { + error = TrackedProp_WrongDataType; + } + + if ( pError ) + { + *pError = error; + } + + if ( error != TrackedProp_Success ) + { + if ( pchValue && unBufferSize ) + { + *pchValue = '\0'; + } + } + + return unRequiredSize; +} + + +/** Returns a string property as a std::string. If the device index is not valid or the property is not a string type this function will +* return an empty string. */ +inline std::string CVRPropertyHelpers::GetStringProperty( vr::PropertyContainerHandle_t ulContainer, vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError *peError ) { - ClientDriverMode_Normal = 0, - ClientDriverMode_Watchdog = 1, // client should return VRInitError_Init_LowPowerWatchdogNotSupported if it can't support this mode + char buf[1024]; + vr::ETrackedPropertyError err; + uint32_t unRequiredBufferLen = GetStringProperty( ulContainer, prop, buf, sizeof(buf), &err ); + + std::string sResult; + + if ( err == TrackedProp_Success ) + { + sResult = buf; + } + else if ( err == TrackedProp_BufferTooSmall ) + { + char *pchBuffer = new char[unRequiredBufferLen]; + unRequiredBufferLen = GetStringProperty( ulContainer, prop, pchBuffer, unRequiredBufferLen, &err ); + sResult = pchBuffer; + delete[] pchBuffer; + } + + if ( peError ) + { + *peError = err; + } + + return sResult; +} + + +/** Sets a string property. The new value will be returned on any subsequent call to get this property in any process. */ +inline ETrackedPropertyError CVRPropertyHelpers::SetStringProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, const char *pchNewValue ) +{ + if ( !pchNewValue ) + return TrackedProp_InvalidOperation; + + // this is strlen without the dependency on string.h + const char *pchCurr = pchNewValue; + while ( *pchCurr ) + { + pchCurr++; + } + + return SetProperty( ulContainerHandle, prop, (void *)pchNewValue, (uint32_t)(pchCurr - pchNewValue) + 1, k_unStringPropertyTag ); +} + + +template +inline T CVRPropertyHelpers::GetPropertyHelper( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, ETrackedPropertyError *pError, T bDefault, PropertyTypeTag_t unTypeTag ) +{ + T bValue; + ETrackedPropertyError eError; + PropertyTypeTag_t unReadTag; + GetProperty( ulContainerHandle, prop, &bValue, sizeof( bValue ), &unReadTag, &eError ); + if ( unReadTag != unTypeTag && eError == TrackedProp_Success ) + { + eError = TrackedProp_WrongDataType; + }; + + if ( pError ) + *pError = eError; + if ( eError != TrackedProp_Success ) + { + return bDefault; + } + else + { + return bValue; + } +} + + +inline bool CVRPropertyHelpers::GetBoolProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, ETrackedPropertyError *pError ) +{ + return GetPropertyHelper( ulContainerHandle, prop, pError, false, k_unBoolPropertyTag ); +} + + +inline float CVRPropertyHelpers::GetFloatProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, ETrackedPropertyError *pError ) +{ + return GetPropertyHelper( ulContainerHandle, prop, pError, 0.f, k_unFloatPropertyTag ); +} + +inline int32_t CVRPropertyHelpers::GetInt32Property( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, ETrackedPropertyError *pError ) +{ + return GetPropertyHelper( ulContainerHandle, prop, pError, 0, k_unInt32PropertyTag ); +} + +inline uint64_t CVRPropertyHelpers::GetUint64Property( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, ETrackedPropertyError *pError ) +{ + return GetPropertyHelper( ulContainerHandle, prop, pError, 0, k_unUint64PropertyTag ); +} + +inline ETrackedPropertyError CVRPropertyHelpers::SetBoolProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, bool bNewValue ) +{ + return SetProperty( ulContainerHandle, prop, &bNewValue, sizeof( bNewValue ), k_unBoolPropertyTag ); +} + +inline ETrackedPropertyError CVRPropertyHelpers::SetFloatProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, float fNewValue ) +{ + return SetProperty( ulContainerHandle, prop, &fNewValue, sizeof( fNewValue ), k_unFloatPropertyTag ); +} + +inline ETrackedPropertyError CVRPropertyHelpers::SetInt32Property( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, int32_t nNewValue ) +{ + return SetProperty( ulContainerHandle, prop, &nNewValue, sizeof( nNewValue ), k_unInt32PropertyTag ); +} + +inline ETrackedPropertyError CVRPropertyHelpers::SetUint64Property( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, uint64_t ulNewValue ) +{ + return SetProperty( ulContainerHandle, prop, &ulNewValue, sizeof( ulNewValue ), k_unUint64PropertyTag ); +} + +/** Sets the error return value for a property. This value will be returned on all subsequent requests to get the property */ +inline ETrackedPropertyError CVRPropertyHelpers::SetPropertyError( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, ETrackedPropertyError eError ) +{ + PropertyWrite_t batch; + batch.writeType = PropertyWrite_SetError; + batch.prop = prop; + batch.eSetError = eError; + + m_pProperties->WritePropertyBatch( ulContainerHandle, &batch, 1 ); + + return batch.eError; +} + +/** Clears any value or error set for the property. */ +inline ETrackedPropertyError CVRPropertyHelpers::EraseProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop ) +{ + PropertyWrite_t batch; + batch.writeType = PropertyWrite_Erase; + batch.prop = prop; + + m_pProperties->WritePropertyBatch( ulContainerHandle, &batch, 1 ); + + return batch.eError; + +} + +} + + +// ivrdriverlog.h +namespace vr +{ + +class IVRDriverLog +{ +public: + /** Writes a log message to the log file prefixed with the driver name */ + virtual void Log( const char *pchLogMessage ) = 0; }; -/** This interface must be implemented in each driver. It will be loaded in vrclient.dll */ -class IClientTrackedDeviceProvider +static const char *IVRDriverLog_Version = "IVRDriverLog_001"; + +} +// ivrserverdriverhost.h +namespace vr +{ + +class ITrackedDeviceServerDriver; +struct TrackedDeviceDriverInfo_t; +struct DriverPose_t; + +/** This interface is provided by vrserver to allow the driver to notify +* the system when something changes about a device. These changes must +* not change the serial number or class of the device because those values +* are permanently associated with the device's index. */ +class IVRServerDriverHost { public: - /** initializes the driver. This will be called before any other methods are called, - * except BIsHmdPresent(). BIsHmdPresent is called outside of the Init/Cleanup pair. - * If Init returns anything other than VRInitError_None the driver DLL will be unloaded. - * - * pDriverHost will never be NULL, and will always be a pointer to a IClientDriverHost interface - * - * pchUserDriverConfigDir - The absolute path of the directory where the driver should store user - * config files. - * pchDriverInstallDir - The absolute path of the root directory for the driver. - */ - virtual EVRInitError Init( EClientDriverMode eDriverMode, IDriverLog *pDriverLog, vr::IClientDriverHost *pDriverHost, const char *pchUserDriverConfigDir, const char *pchDriverInstallDir ) = 0; + /** Notifies the server that a tracked device has been added. If this function returns true + * the server will call Activate on the device. If it returns false some kind of error + * has occurred and the device will not be activated. */ + virtual bool TrackedDeviceAdded( const char *pchDeviceSerialNumber, ETrackedDeviceClass eDeviceClass, ITrackedDeviceServerDriver *pDriver ) = 0; - /** cleans up the driver right before it is unloaded */ - virtual void Cleanup() = 0; + /** Notifies the server that a tracked device's pose has been updated */ + virtual void TrackedDevicePoseUpdated( uint32_t unWhichDevice, const DriverPose_t & newPose, uint32_t unPoseStructSize ) = 0; - /** Called when the client needs to inform an application if an HMD is attached that uses - * this driver. This method should be as lightweight as possible and should have no side effects - * such as hooking process functions or leaving resources loaded. Init will not be called before - * this method and Cleanup will not be called after it. - */ - virtual bool BIsHmdPresent( const char *pchUserConfigDir ) = 0; + /** Notifies the server that vsync has occurred on the the display attached to the device. This is + * only permitted on devices of the HMD class. */ + virtual void VsyncEvent( double vsyncTimeOffsetSeconds ) = 0; - /** called when the client inits an HMD to let the client driver know which one is in use */ - virtual EVRInitError SetDisplayId( const char *pchDisplayId ) = 0; + /** notifies the server that the button was pressed */ + virtual void TrackedDeviceButtonPressed( uint32_t unWhichDevice, EVRButtonId eButtonId, double eventTimeOffset ) = 0; - /** Returns the stencil mesh information for the current HMD. If this HMD does not have a stencil mesh the vertex data and count will be - * NULL and 0 respectively. This mesh is meant to be rendered into the stencil buffer (or into the depth buffer setting nearz) before rendering - * each eye's view. The pixels covered by this mesh will never be seen by the user after the lens distortion is applied and based on visibility to the panels. - * This will improve perf by letting the GPU early-reject pixels the user will never see before running the pixel shader. - * NOTE: Render this mesh with backface culling disabled since the winding order of the vertices can be different per-HMD or per-eye. - */ - virtual HiddenAreaMesh_t GetHiddenAreaMesh( EVREye eEye, EHiddenAreaMeshType type ) = 0; + /** notifies the server that the button was unpressed */ + virtual void TrackedDeviceButtonUnpressed( uint32_t unWhichDevice, EVRButtonId eButtonId, double eventTimeOffset ) = 0; + + /** notifies the server that the button was pressed */ + virtual void TrackedDeviceButtonTouched( uint32_t unWhichDevice, EVRButtonId eButtonId, double eventTimeOffset ) = 0; + + /** notifies the server that the button was unpressed */ + virtual void TrackedDeviceButtonUntouched( uint32_t unWhichDevice, EVRButtonId eButtonId, double eventTimeOffset ) = 0; + + /** notifies the server than a controller axis changed */ + virtual void TrackedDeviceAxisUpdated( uint32_t unWhichDevice, uint32_t unWhichAxis, const VRControllerAxis_t & axisState ) = 0; + + /** Notifies the server that the proximity sensor on the specified device */ + virtual void ProximitySensorState( uint32_t unWhichDevice, bool bProximitySensorTriggered ) = 0; + + /** Sends a vendor specific event (VREvent_VendorSpecific_Reserved_Start..VREvent_VendorSpecific_Reserved_End */ + virtual void VendorSpecificEvent( uint32_t unWhichDevice, vr::EVREventType eventType, const VREvent_Data_t & eventData, double eventTimeOffset ) = 0; + + /** Returns true if SteamVR is exiting */ + virtual bool IsExiting() = 0; + + /** Returns true and fills the event with the next event on the queue if there is one. If there are no events + * this method returns false. uncbVREvent should be the size in bytes of the VREvent_t struct */ + virtual bool PollNextEvent( VREvent_t *pEvent, uint32_t uncbVREvent ) = 0; +}; + +static const char *IVRServerDriverHost_Version = "IVRServerDriverHost_004"; + +} +// ivrhiddenarea.h +namespace vr +{ + +class CVRHiddenAreaHelpers +{ +public: + CVRHiddenAreaHelpers( IVRProperties *pProperties ) : m_pProperties( pProperties ) {} + + /** Stores a hidden area mesh in a property */ + ETrackedPropertyError SetHiddenArea( EVREye eEye, EHiddenAreaMeshType type, HmdVector2_t *pVerts, uint32_t unVertCount ); + + /** retrieves a hidden area mesh from a property. Returns the vert count read out of the property. */ + uint32_t GetHiddenArea( EVREye eEye, EHiddenAreaMeshType type, HmdVector2_t *pVerts, uint32_t unVertCount, ETrackedPropertyError *peError ); + +private: + ETrackedDeviceProperty GetPropertyEnum( EVREye eEye, EHiddenAreaMeshType type ) + { + return (ETrackedDeviceProperty)(Prop_DisplayHiddenArea_Binary_Start + ((int)type * 2) + (int)eEye); + } - /** Get the MC image for the current HMD. - * Returns the size in bytes of the buffer required to hold the specified resource. */ - virtual uint32_t GetMCImage( uint32_t *pImgWidth, uint32_t *pImgHeight, uint32_t *pChannels, void *pDataBuffer, uint32_t unBufferLen ) = 0; + IVRProperties *m_pProperties; }; -static const char *IClientTrackedDeviceProvider_Version = "IClientTrackedDeviceProvider_005"; + +inline ETrackedPropertyError CVRHiddenAreaHelpers::SetHiddenArea( EVREye eEye, EHiddenAreaMeshType type, HmdVector2_t *pVerts, uint32_t unVertCount ) +{ + ETrackedDeviceProperty prop = GetPropertyEnum( eEye, type ); + CVRPropertyHelpers propHelpers( m_pProperties ); + return propHelpers.SetProperty( propHelpers.TrackedDeviceToPropertyContainer( k_unTrackedDeviceIndex_Hmd ), prop, pVerts, sizeof( HmdVector2_t ) * unVertCount, k_unHiddenAreaPropertyTag ); +} + + +inline uint32_t CVRHiddenAreaHelpers::GetHiddenArea( EVREye eEye, EHiddenAreaMeshType type, HmdVector2_t *pVerts, uint32_t unVertCount, ETrackedPropertyError *peError ) +{ + ETrackedDeviceProperty prop = GetPropertyEnum( eEye, type ); + CVRPropertyHelpers propHelpers( m_pProperties ); + ETrackedPropertyError propError; + PropertyTypeTag_t unTag; + uint32_t unBytesNeeded = propHelpers.GetProperty( propHelpers.TrackedDeviceToPropertyContainer( k_unTrackedDeviceIndex_Hmd ), prop, pVerts, sizeof( HmdVector2_t )*unVertCount, &unTag, &propError ); + if ( propError == TrackedProp_Success && unTag != k_unHiddenAreaPropertyTag ) + { + propError = TrackedProp_WrongDataType; + unBytesNeeded = 0; + } + + if ( peError ) + { + *peError = propError; + } + + return unBytesNeeded / sizeof( HmdVector2_t ); +} } +// ivrwatchdoghost.h +namespace vr +{ + +/** This interface is provided by vrclient to allow the driver to make everything wake up */ +class IVRWatchdogHost +{ +public: + /** Client drivers in watchdog mode should call this when they have received a signal from hardware that should + * cause SteamVR to start */ + virtual void WatchdogWakeUp() = 0; +}; + +static const char *IVRWatchdogHost_Version = "IVRWatchdogHost_001"; + +}; + + + @@ -1978,9 +2354,185 @@ namespace vr IVRControllerComponent_Version, IVRCameraComponent_Version, IServerTrackedDeviceProvider_Version, - IClientTrackedDeviceProvider_Version, + IVRWatchdogProvider_Version, nullptr }; + + inline IVRDriverContext *&VRDriverContext() + { + static IVRDriverContext *pHost; + return pHost; + } + + class COpenVRDriverContext + { + public: + COpenVRDriverContext() : m_propertyHelpers(nullptr), m_hiddenAreaHelpers(nullptr) { Clear(); } + void Clear(); + + EVRInitError InitServer(); + EVRInitError InitWatchdog(); + + IVRSettings *VRSettings() + { + if ( m_pVRSettings == nullptr ) + { + EVRInitError eError; + m_pVRSettings = (IVRSettings *)VRDriverContext()->GetGenericInterface( IVRSettings_Version, &eError ); + } + return m_pVRSettings; + } + + IVRProperties *VRPropertiesRaw() + { + if ( m_pVRProperties == nullptr ) + { + EVRInitError eError; + m_pVRProperties = (IVRProperties *)VRDriverContext()->GetGenericInterface( IVRProperties_Version, &eError ); + m_propertyHelpers = CVRPropertyHelpers( m_pVRProperties ); + m_hiddenAreaHelpers = CVRHiddenAreaHelpers( m_pVRProperties ); + } + return m_pVRProperties; + } + + CVRPropertyHelpers *VRProperties() + { + VRPropertiesRaw(); + return &m_propertyHelpers; + } + + CVRHiddenAreaHelpers *VRHiddenArea() + { + VRPropertiesRaw(); + return &m_hiddenAreaHelpers; + } + + IVRServerDriverHost *VRServerDriverHost() + { + if ( m_pVRServerDriverHost == nullptr ) + { + EVRInitError eError; + m_pVRServerDriverHost = (IVRServerDriverHost *)VRDriverContext()->GetGenericInterface( IVRServerDriverHost_Version, &eError ); + } + return m_pVRServerDriverHost; + } + + IVRWatchdogHost *VRWatchdogHost() + { + if ( m_pVRWatchdogHost == nullptr ) + { + EVRInitError eError; + m_pVRWatchdogHost = (IVRWatchdogHost *)VRDriverContext()->GetGenericInterface( IVRWatchdogHost_Version, &eError ); + } + return m_pVRWatchdogHost; + } + + IVRDriverLog *VRDriverLog() + { + if ( m_pVRDriverLog == nullptr ) + { + EVRInitError eError; + m_pVRDriverLog = (IVRDriverLog *)VRDriverContext()->GetGenericInterface( IVRDriverLog_Version, &eError ); + } + return m_pVRDriverLog; + } + + DriverHandle_t VR_CALLTYPE VRDriverHandle() + { + return VRDriverContext()->GetDriverHandle(); + } + + private: + IVRSettings *m_pVRSettings; + IVRProperties *m_pVRProperties; + CVRPropertyHelpers m_propertyHelpers; + CVRHiddenAreaHelpers m_hiddenAreaHelpers; + IVRServerDriverHost *m_pVRServerDriverHost; + IVRWatchdogHost *m_pVRWatchdogHost; + IVRDriverLog *m_pVRDriverLog; + }; + + inline COpenVRDriverContext &OpenVRInternal_ModuleServerDriverContext() + { + static void *ctx[sizeof( COpenVRDriverContext ) / sizeof( void * )]; + return *(COpenVRDriverContext *)ctx; // bypass zero-init constructor + } + + inline IVRSettings *VR_CALLTYPE VRSettings() { return OpenVRInternal_ModuleServerDriverContext().VRSettings(); } + inline IVRProperties *VR_CALLTYPE VRPropertiesRaw() { return OpenVRInternal_ModuleServerDriverContext().VRPropertiesRaw(); } + inline CVRPropertyHelpers *VR_CALLTYPE VRProperties() { return OpenVRInternal_ModuleServerDriverContext().VRProperties(); } + inline CVRHiddenAreaHelpers *VR_CALLTYPE VRHiddenArea() { return OpenVRInternal_ModuleServerDriverContext().VRHiddenArea(); } + inline IVRDriverLog *VR_CALLTYPE VRDriverLog() { return OpenVRInternal_ModuleServerDriverContext().VRDriverLog(); } + inline IVRServerDriverHost *VR_CALLTYPE VRServerDriverHost() { return OpenVRInternal_ModuleServerDriverContext().VRServerDriverHost(); } + inline IVRWatchdogHost *VR_CALLTYPE VRWatchdogHost() { return OpenVRInternal_ModuleServerDriverContext().VRWatchdogHost(); } + inline DriverHandle_t VR_CALLTYPE VRDriverHandle() { return OpenVRInternal_ModuleServerDriverContext().VRDriverHandle(); } + inline void COpenVRDriverContext::Clear() + { + m_pVRSettings = nullptr; + m_pVRProperties = nullptr; + m_pVRServerDriverHost = nullptr; + m_pVRDriverLog = nullptr; + m_pVRWatchdogHost = nullptr; + } + + inline EVRInitError COpenVRDriverContext::InitServer() + { + Clear(); + if ( !VRServerDriverHost() + || !VRSettings() + || !VRProperties() + || !VRDriverLog() ) + return VRInitError_Init_InterfaceNotFound; + return VRInitError_None; + } + + inline EVRInitError COpenVRDriverContext::InitWatchdog() + { + Clear(); + if ( !VRWatchdogHost() + || !VRSettings() + || !VRDriverLog() ) + return VRInitError_Init_InterfaceNotFound; + return VRInitError_None; + } + + inline EVRInitError InitServerDriverContext( IVRDriverContext *pContext ) + { + VRDriverContext() = pContext; + return OpenVRInternal_ModuleServerDriverContext().InitServer(); + } + + inline EVRInitError InitWatchdogDriverContext( IVRDriverContext *pContext ) + { + VRDriverContext() = pContext; + return OpenVRInternal_ModuleServerDriverContext().InitWatchdog(); + } + + inline void CleanupDriverContext() + { + VRDriverContext() = nullptr; + OpenVRInternal_ModuleServerDriverContext().Clear(); + } + + #define VR_INIT_SERVER_DRIVER_CONTEXT( pContext ) \ + { \ + vr::EVRInitError eError = vr::InitServerDriverContext( pContext ); \ + if( eError != vr::VRInitError_None ) \ + return eError; \ + } + + #define VR_CLEANUP_SERVER_DRIVER_CONTEXT() \ + vr::CleanupDriverContext(); + + #define VR_INIT_WATCHDOG_DRIVER_CONTEXT( pContext ) \ + { \ + vr::EVRInitError eError = vr::InitWatchdogDriverContext( pContext ); \ + if( eError != vr::VRInitError_None ) \ + return eError; \ + } + + #define VR_CLEANUP_WATCHDOG_DRIVER_CONTEXT() \ + vr::CleanupDriverContext(); } // End diff --git a/lib/linux64/libopenvr_api.so b/lib/linux64/libopenvr_api.so index 46470254..48e40452 100755 Binary files a/lib/linux64/libopenvr_api.so and b/lib/linux64/libopenvr_api.so differ diff --git a/lib/win32/openvr_api.lib b/lib/win32/openvr_api.lib index 1521479a..705736ed 100644 Binary files a/lib/win32/openvr_api.lib and b/lib/win32/openvr_api.lib differ diff --git a/lib/win64/openvr_api.lib b/lib/win64/openvr_api.lib index fc16c949..33c8bbd2 100644 Binary files a/lib/win64/openvr_api.lib and b/lib/win64/openvr_api.lib differ diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 3f50eb43..6ec41688 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -15,21 +15,22 @@ if(NOT PLATFORM) endif() message(STATUS "Compilation set for ${PLATFORM}bits architectures.") +set(SDL_REQUIRED_LIBRARIES SDL2) + if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") - add_definitions(-DLINUX) + add_definitions(-DLINUX -DPOSIX) set(ARCH_TARGET linux64) if(${PLATFORM} MATCHES 32) message(WARNING "OpenVR x86 binaries not provided on GNU/Linux.") endif() elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - add_definitions(-DOSX) + set(CMAKE_MACOSX_RPATH 0) + add_definitions(-DOSX -DPOSIX) set(ARCH_TARGET osx32) - if(${PLATFORM} MATCHES 64) - message(WARNING "OpenVR x64 binaries not provided on OSX.") - endif() elseif(${CMAKE_SYSTEM_NAME} MATCHES "Windows") + set(SDL_REQUIRED_LIBRARIES ${SDL_REQUIRED_LIBRARIES} SDL2main) add_definitions(-D_WIN32) set(ARCH_TARGET win${PLATFORM}) @@ -50,7 +51,7 @@ set(SHARED_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/shared) # Check that the steamVR SDK is installed # (needed to prevent a segfault in OpenVR). if(CMAKE_HOST_UNIX) - find_file(OPENVRPATHS openvrpaths.vrpath PATHS $ENV{HOME}/.config/openvr) + find_file(OPENVRPATHS openvrpaths.vrpath PATHS $ENV{HOME}/.config/openvr "$ENV{HOME}/Library/Application Support/OpenVR/.openvr") if(${OPENVRPATHS} MATCHES OPENVRPATHS-NOTFOUND) message(FATAL_ERROR "${OPENVRPATHS} Please install SteamVR SDK to continue..") endif() @@ -74,7 +75,6 @@ endfunction() # ----------------------------------------------------------------------------- ## COMPILER DETECTION ## - if( (${CMAKE_CXX_COMPILER_ID} MATCHES "GNU") OR (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")) # Better to use the prebuilt GNU preprocessor define __GNUC__, @@ -90,12 +90,12 @@ if( (${CMAKE_CXX_COMPILER_ID} MATCHES "GNU") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -m32") endif() -elseif(${CMAKE_CXX_COMPILER_ID} MATCHES "MSVC") +elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Za") - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /w2 /DEBUG") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /W2 /DEBUG") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MP /INCREMENTAL:NO") else() - message(FATAL_ERROR "Unsupported compiler.") + message(FATAL_ERROR "Unsupported compiler '${CMAKE_CXX_COMPILER_ID}'") endif() # ----------------------------------------------------------------------------- @@ -124,19 +124,33 @@ else() endif() ## SDL 2 -foreach(lib SDL2 SDL2main) - find_library(${lib}_LIBRARY - NAMES - ${lib} - PATHS - ${THIRDPARTY_DIR}/sdl2-2.0.3/bin - PATH_SUFFIXES - linux32 - osx32 - ${WINDOWS_PATH_SUFFIXES} - ) - list(APPEND SDL2_LIBRARIES ${${lib}_LIBRARY}) -endforeach() +## osx32 and linux32 cmake can spot each others' .so and .a files, so keep them apart +if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + foreach(lib ${SDL_REQUIRED_LIBRARIES}) + find_library(${lib}_LIBRARY + NAMES + ${lib} + PATHS + ${THIRDPARTY_DIR}/sdl2-2.0.3/bin + PATH_SUFFIXES + osx32 + ) + list(APPEND SDL2_LIBRARIES ${${lib}_LIBRARY}) + endforeach() +else() + foreach(lib ${SDL_REQUIRED_LIBRARIES}) + find_library(${lib}_LIBRARY + NAMES + ${lib} + PATHS + ${THIRDPARTY_DIR}/sdl2-2.0.3/bin + PATH_SUFFIXES + linux${PLATFORM} + ${WINDOWS_PATH_SUFFIXES} + ) + list(APPEND SDL2_LIBRARIES ${${lib}_LIBRARY}) + endforeach() +endif() set(SDL2_INCLUDE_DIR ${THIRDPARTY_DIR}/sdl2-2.0.3/include) ## Qt 5 @@ -167,6 +181,8 @@ foreach(module Core Gui Widgets) list(APPEND QT_FLAGS "${Qt5${module}_EXECUTABLE_COMPILE_FLAGS}") list(APPEND QT_DEFINITIONS "${Qt5${module}_DEFINITIONS}") endforeach() +# Correct QT_FLAGS having semicolons, which break the compile step on POSIX +list(REMOVE_DUPLICATES QT_FLAGS) ## OpenVR API path find_library(OPENVR_LIBRARIES @@ -176,8 +192,8 @@ find_library(OPENVR_LIBRARIES ${CMAKE_CURRENT_SOURCE_DIR}/../bin ${CMAKE_CURRENT_SOURCE_DIR}/../lib PATH_SUFFIXES - linux64 osx32 + linux64 ${WINDOWS_PATH_SUFFIXES} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH @@ -210,4 +226,4 @@ add_subdirectory(hellovr_opengl) add_subdirectory(helloworldoverlay) add_subdirectory(tracked_camera_openvr_sample) -# ----------------------------------------------------------------------------- \ No newline at end of file +# ----------------------------------------------------------------------------- diff --git a/samples/bin/drivers/sample/driver.vrdrivermanifest b/samples/bin/drivers/sample/driver.vrdrivermanifest new file mode 100644 index 00000000..a550df96 --- /dev/null +++ b/samples/bin/drivers/sample/driver.vrdrivermanifest @@ -0,0 +1,11 @@ +{ + "alwaysActivate": false, + "name" : "sample", + "directory" : "", + "resourceOnly" : false, + + "hmd_presence" : + [ + "*.*" + ] +} diff --git a/samples/bin/drivers/sample/resources/icons/headset_sample_status_error.png b/samples/bin/drivers/sample/resources/icons/headset_sample_status_error.png new file mode 100644 index 00000000..c9401de2 Binary files /dev/null and b/samples/bin/drivers/sample/resources/icons/headset_sample_status_error.png differ diff --git a/samples/bin/drivers/sample/resources/icons/headset_sample_status_off.png b/samples/bin/drivers/sample/resources/icons/headset_sample_status_off.png new file mode 100644 index 00000000..22e884f8 Binary files /dev/null and b/samples/bin/drivers/sample/resources/icons/headset_sample_status_off.png differ diff --git a/samples/bin/drivers/sample/resources/icons/headset_sample_status_ready.png b/samples/bin/drivers/sample/resources/icons/headset_sample_status_ready.png new file mode 100644 index 00000000..5fe9fe20 Binary files /dev/null and b/samples/bin/drivers/sample/resources/icons/headset_sample_status_ready.png differ diff --git a/samples/bin/drivers/sample/resources/icons/headset_sample_status_ready_alert.png b/samples/bin/drivers/sample/resources/icons/headset_sample_status_ready_alert.png new file mode 100644 index 00000000..1da03a46 Binary files /dev/null and b/samples/bin/drivers/sample/resources/icons/headset_sample_status_ready_alert.png differ diff --git a/samples/bin/drivers/sample/resources/icons/headset_sample_status_ready_low.png b/samples/bin/drivers/sample/resources/icons/headset_sample_status_ready_low.png new file mode 100644 index 00000000..bbaf61d5 Binary files /dev/null and b/samples/bin/drivers/sample/resources/icons/headset_sample_status_ready_low.png differ diff --git a/samples/bin/drivers/sample/resources/icons/headset_sample_status_searching.gif b/samples/bin/drivers/sample/resources/icons/headset_sample_status_searching.gif new file mode 100644 index 00000000..85bb8134 Binary files /dev/null and b/samples/bin/drivers/sample/resources/icons/headset_sample_status_searching.gif differ diff --git a/samples/bin/drivers/sample/resources/icons/headset_sample_status_searching_alert.gif b/samples/bin/drivers/sample/resources/icons/headset_sample_status_searching_alert.gif new file mode 100644 index 00000000..7c23fae0 Binary files /dev/null and b/samples/bin/drivers/sample/resources/icons/headset_sample_status_searching_alert.gif differ diff --git a/samples/bin/drivers/sample/resources/icons/headset_sample_status_standby.png b/samples/bin/drivers/sample/resources/icons/headset_sample_status_standby.png new file mode 100644 index 00000000..ff9e4025 Binary files /dev/null and b/samples/bin/drivers/sample/resources/icons/headset_sample_status_standby.png differ diff --git a/samples/bin/drivers/sample/resources/settings/default.vrsettings b/samples/bin/drivers/sample/resources/settings/default.vrsettings new file mode 100644 index 00000000..369a316c --- /dev/null +++ b/samples/bin/drivers/sample/resources/settings/default.vrsettings @@ -0,0 +1,15 @@ +{ + "driver_sample" : { + "enable" : true, + "serialNumber" : "1234", + "modelNumber" : "SampleModel 1", + "windowX" : 20, + "windowY" : 20, + "windowWidth" : 800, + "windowHeight" : 600, + "renderWidth" : 400, + "renderHeight" : 300, + "secondsFromVsyncToPhotons" : 0.011, + "displayFrequency" : 0 + } +} diff --git a/samples/bin/linux64/libopenvr_api.so b/samples/bin/linux64/libopenvr_api.so index 3b4363fe..eafad11e 100644 Binary files a/samples/bin/linux64/libopenvr_api.so and b/samples/bin/linux64/libopenvr_api.so differ diff --git a/samples/bin/osx32/libopenvr_api.dylib b/samples/bin/osx32/libopenvr_api.dylib index 647ec3fa..b3da84f1 100644 Binary files a/samples/bin/osx32/libopenvr_api.dylib and b/samples/bin/osx32/libopenvr_api.dylib differ diff --git a/samples/bin/win32/openvr_api.dll b/samples/bin/win32/openvr_api.dll index 7aa2b993..83ead53b 100644 Binary files a/samples/bin/win32/openvr_api.dll and b/samples/bin/win32/openvr_api.dll differ diff --git a/samples/bin/win64/openvr_api.dll b/samples/bin/win64/openvr_api.dll index bbcccde5..5767d725 100644 Binary files a/samples/bin/win64/openvr_api.dll and b/samples/bin/win64/openvr_api.dll differ diff --git a/samples/driver_sample/driver_sample.cpp b/samples/driver_sample/driver_sample.cpp index 1c7290c5..b14f12ac 100644 --- a/samples/driver_sample/driver_sample.cpp +++ b/samples/driver_sample/driver_sample.cpp @@ -53,7 +53,6 @@ inline void HmdMatrix_SetIdentity( HmdMatrix34_t *pMatrix ) // keys for use with the settings API static const char * const k_pch_Sample_Section = "driver_sample"; -static const char * const k_pch_Sample_EnableSampleDriver_Bool = "enable"; static const char * const k_pch_Sample_SerialNumber_String = "serialNumber"; static const char * const k_pch_Sample_ModelNumber_String = "modelNumber"; static const char * const k_pch_Sample_WindowX_Int32 = "windowX"; @@ -69,35 +68,22 @@ static const char * const k_pch_Sample_DisplayFrequency_Float = "displayFrequenc // Purpose: //----------------------------------------------------------------------------- -class CClientDriver_Sample : public IClientTrackedDeviceProvider +class CWatchdogDriver_Sample : public IVRWatchdogProvider { public: - CClientDriver_Sample() - : m_bEnableNullDriver( false ) - , m_bInit( false ) + CWatchdogDriver_Sample() { - m_eDriverMode = ClientDriverMode_Normal; m_pWatchdogThread = nullptr; } - virtual EVRInitError Init( vr::EClientDriverMode eDriverMode, vr::IDriverLog *pDriverLog, vr::IClientDriverHost *pDriverHost, const char *pchUserDriverConfigDir, const char *pchDriverInstallDir ) ; + virtual EVRInitError Init( vr::IVRDriverContext *pDriverContext ) ; virtual void Cleanup() ; - virtual bool BIsHmdPresent( const char *pchUserDriverConfigDir ) ; - virtual EVRInitError SetDisplayId( const char *pchDisplayId ) { return VRInitError_None; } // Null doesn't care - virtual HiddenAreaMesh_t GetHiddenAreaMesh( EVREye eEye, EHiddenAreaMeshType type ); - virtual uint32_t GetMCImage( uint32_t *pImgWidth, uint32_t *pImgHeight, uint32_t *pChannels, void *pDataBuffer, uint32_t unBufferLen ) { return 0; } - void WatchdogWakeUp(); private: - vr::IClientDriverHost *m_pClientDriverHost; - - bool m_bEnableNullDriver; - bool m_bInit; - vr::EClientDriverMode m_eDriverMode; std::thread *m_pWatchdogThread; }; -CClientDriver_Sample g_clientDriverNull; +CWatchdogDriver_Sample g_watchdogDriverNull; bool g_bExiting = false; @@ -111,69 +97,38 @@ void WatchdogThreadFunction( ) if ( (0x01 & GetAsyncKeyState( 'Y' )) != 0 ) { // Y key was pressed. - g_clientDriverNull.WatchdogWakeUp(); + vr::VRWatchdogHost()->WatchdogWakeUp(); } std::this_thread::sleep_for( std::chrono::microseconds( 500 ) ); #else // for the other platforms, just send one every five seconds std::this_thread::sleep_for( std::chrono::seconds( 5 ) ); - g_clientDriverNull.WatchdogWakeUp(); + vr::VRWatchdogHost()->WatchdogWakeUp(); #endif } } -EVRInitError CClientDriver_Sample::Init( vr::EClientDriverMode eDriverMode, vr::IDriverLog *pDriverLog, vr::IClientDriverHost *pDriverHost, const char *pchUserDriverConfigDir, const char *pchDriverInstallDir ) +EVRInitError CWatchdogDriver_Sample::Init( vr::IVRDriverContext *pDriverContext ) { - m_pClientDriverHost = pDriverHost; - InitDriverLog( pDriverLog ); - - m_eDriverMode = eDriverMode; - - if ( !m_bInit ) - { - if ( m_pClientDriverHost ) - { - IVRSettings *pSettings = (IVRSettings *) m_pClientDriverHost->GetGenericInterface( IVRSettings_Version ); - - if ( !m_bEnableNullDriver && pSettings ) - { - m_bEnableNullDriver = pSettings->GetBool( k_pch_Sample_Section, k_pch_Sample_EnableSampleDriver_Bool); - } - } - m_bInit = true; - } + VR_INIT_WATCHDOG_DRIVER_CONTEXT( pDriverContext ); + InitDriverLog( vr::VRDriverLog() ); - if ( eDriverMode == ClientDriverMode_Watchdog ) + // Watchdog mode on Windows starts a thread that listens for the 'Y' key on the keyboard to + // be pressed. A real driver should wait for a system button event or something else from the + // the hardware that signals that the VR system should start up. + g_bExiting = false; + m_pWatchdogThread = new std::thread( WatchdogThreadFunction ); + if ( !m_pWatchdogThread ) { - if ( !m_bEnableNullDriver ) - { - return VRInitError_Init_LowPowerWatchdogNotSupported; - } - - // Watchdog mode on Windows starts a thread that listens for the 'Y' key on the keyboard to - // be pressed. A real driver should wait for a system button event or something else from the - // the hardware that signals that the VR system should start up. - g_bExiting = false; - m_pWatchdogThread = new std::thread( WatchdogThreadFunction ); - if ( !m_pWatchdogThread ) - { - DriverLog( "Unable to create watchdog thread\n"); - return VRInitError_Driver_Failed; - } + DriverLog( "Unable to create watchdog thread\n"); + return VRInitError_Driver_Failed; } return VRInitError_None; } -void CClientDriver_Sample::WatchdogWakeUp() -{ - if ( m_pClientDriverHost ) - m_pClientDriverHost->WatchdogWakeUp(); -} - - -void CClientDriver_Sample::Cleanup() +void CWatchdogDriver_Sample::Cleanup() { g_bExiting = true; if ( m_pWatchdogThread ) @@ -187,79 +142,35 @@ void CClientDriver_Sample::Cleanup() } -bool CClientDriver_Sample::BIsHmdPresent( const char *pchUserDriverConfigDir ) -{ - // optimistically return true. We'll have a chance to say whether there's actually an HMD later. - // This should do something quick like look for a USB VID/PID combination that makes it likely - // there's an HMD attached. - return true; -} - - -// ------------------------------------------------------------------------------------------ -// Purpose: Return a mesh that contains the hidden area for the current HMD -// ------------------------------------------------------------------------------------------ -HiddenAreaMesh_t CClientDriver_Sample::GetHiddenAreaMesh( EVREye eEye, EHiddenAreaMeshType type ) -{ - // Null doesn't do visible area meshes - vr::HiddenAreaMesh_t mesh; - mesh.pVertexData = NULL; - mesh.unTriangleCount = 0; - return mesh; -} - - //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- class CSampleDeviceDriver : public vr::ITrackedDeviceServerDriver, public vr::IVRDisplayComponent { public: - CSampleDeviceDriver( vr::IServerDriverHost *pDriverHost ) - : m_pServerDriverHost( pDriverHost ) - , m_unObjectId( vr::k_unTrackedDeviceIndexInvalid ) + CSampleDeviceDriver( ) { - IVRSettings *pSettings = m_pServerDriverHost ? m_pServerDriverHost->GetSettings( vr::IVRSettings_Version ) : NULL; + m_unObjectId = vr::k_unTrackedDeviceIndexInvalid; + m_ulPropertyContainer = vr::k_ulInvalidPropertyContainer; - if ( pSettings ) - { - DriverLog( "Using settings values\n" ); - m_flIPD = pSettings->GetFloat( k_pch_SteamVR_Section, k_pch_SteamVR_IPD_Float ); - - char buf[1024]; - pSettings->GetString( k_pch_Sample_Section, k_pch_Sample_SerialNumber_String, buf, sizeof(buf)); - m_sSerialNumber = buf; - - pSettings->GetString( k_pch_Sample_Section, k_pch_Sample_ModelNumber_String, buf, sizeof(buf)); - m_sSerialNumber = buf; - - m_nWindowX = pSettings->GetInt32( k_pch_Sample_Section, k_pch_Sample_WindowX_Int32); - m_nWindowY = pSettings->GetInt32( k_pch_Sample_Section, k_pch_Sample_WindowY_Int32); - m_nWindowWidth = pSettings->GetInt32( k_pch_Sample_Section, k_pch_Sample_WindowWidth_Int32); - m_nWindowHeight = pSettings->GetInt32( k_pch_Sample_Section, k_pch_Sample_WindowHeight_Int32); - m_nRenderWidth = pSettings->GetInt32( k_pch_Sample_Section, k_pch_Sample_RenderWidth_Int32); - m_nRenderHeight = pSettings->GetInt32( k_pch_Sample_Section, k_pch_Sample_RenderHeight_Int32); - m_flSecondsFromVsyncToPhotons = pSettings->GetFloat( k_pch_Sample_Section, k_pch_Sample_SecondsFromVsyncToPhotons_Float); - m_flDisplayFrequency = pSettings->GetFloat( k_pch_Sample_Section, k_pch_Sample_DisplayFrequency_Float); - } - else - { + DriverLog( "Using settings values\n" ); + m_flIPD = vr::VRSettings()->GetFloat( k_pch_SteamVR_Section, k_pch_SteamVR_IPD_Float ); - DriverLog( "Could not get settings API. Using default values\n" ); - m_flIPD = 0.065f; + char buf[1024]; + vr::VRSettings()->GetString( k_pch_Sample_Section, k_pch_Sample_SerialNumber_String, buf, sizeof( buf ) ); + m_sSerialNumber = buf; - m_sSerialNumber = "SAMPLE1234"; - m_sModelNumber = "ED209"; + vr::VRSettings()->GetString( k_pch_Sample_Section, k_pch_Sample_ModelNumber_String, buf, sizeof( buf ) ); + m_sSerialNumber = buf; - m_nWindowX = 0; - m_nWindowY = 0; - m_nWindowWidth = 1920; - m_nWindowHeight = 1080; - m_nRenderWidth = 1344; - m_nRenderHeight = 1512; - m_flSecondsFromVsyncToPhotons = 0.0; - m_flDisplayFrequency = 0.0; - } + m_nWindowX = vr::VRSettings()->GetInt32( k_pch_Sample_Section, k_pch_Sample_WindowX_Int32 ); + m_nWindowY = vr::VRSettings()->GetInt32( k_pch_Sample_Section, k_pch_Sample_WindowY_Int32 ); + m_nWindowWidth = vr::VRSettings()->GetInt32( k_pch_Sample_Section, k_pch_Sample_WindowWidth_Int32 ); + m_nWindowHeight = vr::VRSettings()->GetInt32( k_pch_Sample_Section, k_pch_Sample_WindowHeight_Int32 ); + m_nRenderWidth = vr::VRSettings()->GetInt32( k_pch_Sample_Section, k_pch_Sample_RenderWidth_Int32 ); + m_nRenderHeight = vr::VRSettings()->GetInt32( k_pch_Sample_Section, k_pch_Sample_RenderHeight_Int32 ); + m_flSecondsFromVsyncToPhotons = vr::VRSettings()->GetFloat( k_pch_Sample_Section, k_pch_Sample_SecondsFromVsyncToPhotons_Float ); + m_flDisplayFrequency = vr::VRSettings()->GetFloat( k_pch_Sample_Section, k_pch_Sample_DisplayFrequency_Float ); DriverLog( "driver_null: Serial Number: %s\n", m_sSerialNumber.c_str() ); DriverLog( "driver_null: Model Number: %s\n", m_sModelNumber.c_str() ); @@ -272,13 +183,39 @@ class CSampleDeviceDriver : public vr::ITrackedDeviceServerDriver, public vr::IV virtual ~CSampleDeviceDriver() { - m_pServerDriverHost = NULL; } - virtual EVRInitError Activate( uint32_t unObjectId ) + virtual EVRInitError Activate( vr::TrackedDeviceIndex_t unObjectId ) { m_unObjectId = unObjectId; + m_ulPropertyContainer = vr::VRProperties()->TrackedDeviceToPropertyContainer( m_unObjectId ); + + + vr::VRProperties()->SetStringProperty( m_ulPropertyContainer, Prop_ModelNumber_String, m_sModelNumber.c_str() ); + vr::VRProperties()->SetStringProperty( m_ulPropertyContainer, Prop_RenderModelName_String, m_sModelNumber.c_str() ); + vr::VRProperties()->SetFloatProperty( m_ulPropertyContainer, Prop_UserIpdMeters_Float, m_flIPD ); + vr::VRProperties()->SetFloatProperty( m_ulPropertyContainer, Prop_UserHeadToEyeDepthMeters_Float, 0.f ); + vr::VRProperties()->SetFloatProperty( m_ulPropertyContainer, Prop_DisplayFrequency_Float, m_flDisplayFrequency ); + vr::VRProperties()->SetFloatProperty( m_ulPropertyContainer, Prop_SecondsFromVsyncToPhotons_Float, m_flSecondsFromVsyncToPhotons ); + + // return a constant that's not 0 (invalid) or 1 (reserved for Oculus) + vr::VRProperties()->SetUint64Property( m_ulPropertyContainer, Prop_CurrentUniverseId_Uint64, 2 ); + + // avoid "not fullscreen" warnings from vrmonitor + vr::VRProperties()->SetBoolProperty( m_ulPropertyContainer, Prop_IsOnDesktop_Bool, false ); + + // Set icons for the HMD we're going to show + vr::VRProperties()->SetStringProperty( m_ulPropertyContainer, Prop_IconPathName_String, "icons" ); + vr::VRProperties()->SetStringProperty( m_ulPropertyContainer, vr::Prop_NamedIconPathDeviceOff_String, "{sample}headset_sample_status_off.png" ); + vr::VRProperties()->SetStringProperty( m_ulPropertyContainer, vr::Prop_NamedIconPathDeviceSearching_String, "{sample}headset_sample_status_searching.gif" ); + vr::VRProperties()->SetStringProperty( m_ulPropertyContainer, vr::Prop_NamedIconPathDeviceSearchingAlert_String, "{sample}headset_sample_status_searching_alert.gif" ); + vr::VRProperties()->SetStringProperty( m_ulPropertyContainer, vr::Prop_NamedIconPathDeviceReady_String, "{sample}headset_sample_status_ready.png" ); + vr::VRProperties()->SetStringProperty( m_ulPropertyContainer, vr::Prop_NamedIconPathDeviceReadyAlert_String, "{sample}headset_sample_status_ready_alert.png" ); + vr::VRProperties()->SetStringProperty( m_ulPropertyContainer, vr::Prop_NamedIconPathDeviceNotReady_String, "{sample}headset_sample_status_error.png" ); + vr::VRProperties()->SetStringProperty( m_ulPropertyContainer, vr::Prop_NamedIconPathDeviceStandby_String, "{sample}headset_sample_status_standby.png" ); + vr::VRProperties()->SetStringProperty( m_ulPropertyContainer, vr::Prop_NamedIconPathDeviceAlertLow_String, "{sample}headset_sample_status_ready_low.png" ); + return VRInitError_None; } @@ -387,140 +324,6 @@ class CSampleDeviceDriver : public vr::ITrackedDeviceServerDriver, public vr::IV return pose; } - virtual bool GetBoolTrackedDeviceProperty( vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError *pError ) - { - *pError = vr::TrackedProp_Success; - - switch ( prop ) - { - case vr::Prop_IsOnDesktop_Bool: - // avoid "not fullscreen" warnings from vrmonitor - return false; - } - - *pError = vr::TrackedProp_ValueNotProvidedByDevice; - return false; - } - - virtual float GetFloatTrackedDeviceProperty( vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError *pError ) - { - vr::ETrackedPropertyError error = vr::TrackedProp_ValueNotProvidedByDevice; - float fRetVal = 0; - switch ( prop ) - { - case vr::Prop_UserIpdMeters_Float: - fRetVal = m_flIPD; - error = TrackedProp_Success; - break; - - case vr::Prop_UserHeadToEyeDepthMeters_Float: - error = vr::TrackedProp_Success; - fRetVal = 0.f; - break; - - case vr::Prop_DisplayFrequency_Float: - error = vr::TrackedProp_Success; - fRetVal = m_flDisplayFrequency; - break; - - case vr::Prop_SecondsFromVsyncToPhotons_Float: - error = vr::TrackedProp_Success; - fRetVal = m_flSecondsFromVsyncToPhotons; - break; - - } - - if ( pError ) - { - *pError = error; - } - - return fRetVal; - } - - int32_t GetInt32TrackedDeviceProperty( vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError *pError ) - { - int32_t nRetVal = 0; - vr::ETrackedPropertyError error = vr::TrackedProp_UnknownProperty; - - switch ( prop ) - { - case vr::Prop_DeviceClass_Int32: - nRetVal = vr::TrackedDeviceClass_HMD; - error = vr::TrackedProp_Success; - break; - } - - if ( pError ) - { - *pError = error; - } - - return nRetVal; - } - - virtual uint64_t GetUint64TrackedDeviceProperty( vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError *pError ) - { - *pError = vr::TrackedProp_Success; - - switch ( prop ) - { - case vr::Prop_CurrentUniverseId_Uint64: - // return a constant that's not 0 (invalid) or 1 (reserved for Oculus) - return 2; - } - - *pError = vr::TrackedProp_ValueNotProvidedByDevice; - return 0; - } - - vr::HmdMatrix34_t GetMatrix34TrackedDeviceProperty( vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError *pError ) - { - *pError = vr::TrackedProp_ValueNotProvidedByDevice; - HmdMatrix34_t matIdentity; - HmdMatrix_SetIdentity( &matIdentity); - return matIdentity; - } - - virtual uint32_t GetStringTrackedDeviceProperty( vr::ETrackedDeviceProperty prop, char *pchValue, uint32_t unBufferSize, vr::ETrackedPropertyError *pError ) - { - std::string sValue= GetStringTrackedDeviceProperty( prop, pError ); - if ( *pError == vr::TrackedProp_Success ) - { - if ( sValue.size( ) + 1 > unBufferSize ) - { - *pError = vr::TrackedProp_BufferTooSmall; - } - else - { - strcpy_s( pchValue, unBufferSize, sValue.c_str() ); - } - return (uint32_t)sValue.size( ) + 1; - } - return 0; - } - - std::string GetStringTrackedDeviceProperty( vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError *pError ) - { - *pError = vr::TrackedProp_ValueNotProvidedByDevice; - std::string sRetVal; - - switch ( prop ) - { - case vr::Prop_ModelNumber_String: - sRetVal = m_sModelNumber; - *pError = vr::TrackedProp_Success; - break; - - case vr::Prop_SerialNumber_String: - sRetVal = m_sSerialNumber; - *pError = vr::TrackedProp_Success; - break; - } - - return sRetVal; - } - void RunFrame() { @@ -529,13 +332,15 @@ class CSampleDeviceDriver : public vr::ITrackedDeviceServerDriver, public vr::IV // driver blocks it for some periodic task. if ( m_unObjectId != vr::k_unTrackedDeviceIndexInvalid ) { - m_pServerDriverHost->TrackedDevicePoseUpdated( m_unObjectId, GetPose() ); + vr::VRServerDriverHost()->TrackedDevicePoseUpdated( m_unObjectId, GetPose(), sizeof( DriverPose_t ) ); } } + std::string GetSerialNumber() const { return m_sSerialNumber; } + private: - vr::IServerDriverHost *m_pServerDriverHost; - uint32_t m_unObjectId; + vr::TrackedDeviceIndex_t m_unObjectId; + vr::PropertyContainerHandle_t m_ulPropertyContainer; std::string m_sSerialNumber; std::string m_sModelNumber; @@ -563,12 +368,9 @@ class CServerDriver_Sample: public IServerTrackedDeviceProvider { } - virtual EVRInitError Init( IDriverLog *pDriverLog, vr::IServerDriverHost *pDriverHost, const char *pchUserDriverConfigDir, const char *pchDriverInstallDir ) ; + virtual EVRInitError Init( vr::IVRDriverContext *pDriverContext ) ; virtual void Cleanup() ; virtual const char * const *GetInterfaceVersions() { return vr::k_InterfaceVersions; } - virtual uint32_t GetTrackedDeviceCount(); - virtual ITrackedDeviceServerDriver *GetTrackedDeviceDriver( uint32_t unWhich ) ; - virtual ITrackedDeviceServerDriver* FindTrackedDeviceDriver( const char *pchId ) ; virtual void RunFrame() ; virtual bool ShouldBlockStandbyMode() { return false; } virtual void EnterStandby() {} @@ -583,18 +385,13 @@ class CServerDriver_Sample: public IServerTrackedDeviceProvider CServerDriver_Sample g_serverDriverNull; -EVRInitError CServerDriver_Sample::Init( IDriverLog *pDriverLog, vr::IServerDriverHost *pDriverHost, const char *pchUserDriverConfigDir, const char *pchDriverInstallDir ) +EVRInitError CServerDriver_Sample::Init( vr::IVRDriverContext *pDriverContext ) { - InitDriverLog( pDriverLog ); - - IVRSettings *pSettings = pDriverHost ? pDriverHost->GetSettings( vr::IVRSettings_Version ) : NULL; - - m_bEnableNullDriver = pSettings && pSettings->GetBool( k_pch_Sample_Section, k_pch_Sample_EnableSampleDriver_Bool ); - - if ( !m_bEnableNullDriver ) - return VRInitError_Init_HmdNotFound; + VR_INIT_SERVER_DRIVER_CONTEXT( pDriverContext ); + InitDriverLog( vr::VRDriverLog() ); - m_pNullHmdLatest = new CSampleDeviceDriver( pDriverHost); + m_pNullHmdLatest = new CSampleDeviceDriver(); + vr::VRServerDriverHost()->TrackedDeviceAdded( m_pNullHmdLatest->GetSerialNumber().c_str(), vr::TrackedDeviceClass_HMD, m_pNullHmdLatest ); return VRInitError_None; } @@ -606,27 +403,6 @@ void CServerDriver_Sample::Cleanup() } -uint32_t CServerDriver_Sample::GetTrackedDeviceCount() -{ - if ( m_bEnableNullDriver ) - return 1; - - return 0; -} - - -ITrackedDeviceServerDriver *CServerDriver_Sample::GetTrackedDeviceDriver( uint32_t unWhich ) -{ - return m_pNullHmdLatest; -} - - -ITrackedDeviceServerDriver* CServerDriver_Sample::FindTrackedDeviceDriver( const char *pchId ) -{ - return m_pNullHmdLatest; -} - - void CServerDriver_Sample::RunFrame() { if ( m_pNullHmdLatest ) @@ -644,9 +420,9 @@ HMD_DLL_EXPORT void *HmdDriverFactory( const char *pInterfaceName, int *pReturnC { return &g_serverDriverNull; } - if( 0 == strcmp( IClientTrackedDeviceProvider_Version, pInterfaceName ) ) + if( 0 == strcmp( IVRWatchdogProvider_Version, pInterfaceName ) ) { - return &g_clientDriverNull; + return &g_watchdogDriverNull; } if( pReturnCode ) diff --git a/samples/driver_sample/driverlog.cpp b/samples/driver_sample/driverlog.cpp index 88e8ffab..a635aac5 100644 --- a/samples/driver_sample/driverlog.cpp +++ b/samples/driver_sample/driverlog.cpp @@ -5,10 +5,10 @@ #include #include -static vr::IDriverLog * s_pLogFile = NULL; +static vr::IVRDriverLog * s_pLogFile = NULL; -bool InitDriverLog( vr::IDriverLog *pDriverLog ) +bool InitDriverLog( vr::IVRDriverLog *pDriverLog ) { if( s_pLogFile ) return false; @@ -59,21 +59,3 @@ void DebugDriverLog( const char *pMsgFormat, ... ) } -//----------------------------------------------------------------------------- -// Purpose: Helper to get a string from a tracked device property and turn it -// into a std::string -//----------------------------------------------------------------------------- -std::string GetTrackedDeviceString( vr::IClientDriverHost *pClientHost, vr::TrackedDeviceIndex_t unDevice, vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError *peError ) -{ - uint32_t unRequiredBufferLen = pClientHost->GetStringTrackedDeviceProperty( unDevice, prop, NULL, 0, peError ); - if( unRequiredBufferLen == 0 ) - return ""; - - char *pchBuffer = new char[ unRequiredBufferLen ]; - unRequiredBufferLen = pClientHost->GetStringTrackedDeviceProperty( unDevice, prop, pchBuffer, unRequiredBufferLen, peError ); - std::string sResult = pchBuffer; - delete [] pchBuffer; - return sResult; -} - - diff --git a/samples/driver_sample/driverlog.h b/samples/driver_sample/driverlog.h index 62ce8227..3249393d 100644 --- a/samples/driver_sample/driverlog.h +++ b/samples/driver_sample/driverlog.h @@ -17,13 +17,9 @@ extern void DriverLog( const char *pchFormat, ... ); extern void DebugDriverLog( const char *pchFormat, ... ); -extern bool InitDriverLog( vr::IDriverLog *pDriverLog ); +extern bool InitDriverLog( vr::IVRDriverLog *pDriverLog ); extern void CleanupDriverLog(); -/** Retrieves a string property from the IClientHost interface */ -std::string GetTrackedDeviceString( vr::IClientDriverHost *pClientHost, vr::TrackedDeviceIndex_t unDevice, vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError *peError = NULL ); - - -#endif // DRIVERLOG_H \ No newline at end of file +#endif // DRIVERLOG_H diff --git a/samples/hellovr_opengl/CMakeLists.txt b/samples/hellovr_opengl/CMakeLists.txt index 253030eb..a706ea2b 100644 --- a/samples/hellovr_opengl/CMakeLists.txt +++ b/samples/hellovr_opengl/CMakeLists.txt @@ -1,5 +1,14 @@ set(TARGET_NAME hellovr_opengl) +if(APPLE) + if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set_source_files_properties(../shared/pathtools.cpp hellovr_opengl_main.cpp PROPERTIES COMPILE_FLAGS "-x objective-c++") + find_library(FOUNDATION_FRAMEWORK Foundation) + mark_as_advanced(FOUNDATION_FRAMEWORK) + set(EXTRA_LIBS ${EXTRA_LIBS} ${FOUNDATION_FRAMEWORK}) + endif() +endif() + add_executable(${TARGET_NAME} ${SHARED_SRC_FILES} hellovr_opengl_main.cpp @@ -11,6 +20,7 @@ target_link_libraries(${TARGET_NAME} ${SDL2_LIBRARIES} ${OPENVR_LIBRARIES} ${CMAKE_DL_LIBS} + ${EXTRA_LIBS} ) setTargetOutputDirectory(${TARGET_NAME}) diff --git a/samples/hellovr_opengl/hellovr_opengl.vcxproj b/samples/hellovr_opengl/hellovr_opengl.vcxproj index 6af11c4e..8681565b 100644 --- a/samples/hellovr_opengl/hellovr_opengl.vcxproj +++ b/samples/hellovr_opengl/hellovr_opengl.vcxproj @@ -87,12 +87,14 @@ + + diff --git a/samples/hellovr_opengl/hellovr_opengl.vcxproj.filters b/samples/hellovr_opengl/hellovr_opengl.vcxproj.filters index e90ad349..a4f50072 100644 --- a/samples/hellovr_opengl/hellovr_opengl.vcxproj.filters +++ b/samples/hellovr_opengl/hellovr_opengl.vcxproj.filters @@ -33,6 +33,9 @@ Shared + + Shared + @@ -47,5 +50,8 @@ Shared + + Shared + \ No newline at end of file diff --git a/samples/hellovr_opengl/hellovr_opengl_main.cpp b/samples/hellovr_opengl/hellovr_opengl_main.cpp index 5dfc5ae9..bd78b4ce 100644 --- a/samples/hellovr_opengl/hellovr_opengl_main.cpp +++ b/samples/hellovr_opengl/hellovr_opengl_main.cpp @@ -3,7 +3,15 @@ #include #include #include +#if defined( OSX ) +#include +#include +#include +// Apple's version of glut.h #undef's APIENTRY, redefine it +#define APIENTRY +#else #include +#endif #include #include #include @@ -22,6 +30,10 @@ #define APIENTRY #endif +#ifndef _countof +#define _countof(x) (sizeof(x)/sizeof((x)[0])) +#endif + void ThreadSleep( unsigned long nMilliseconds ) { #if defined(_WIN32) @@ -691,9 +703,9 @@ void CMainApplication::RenderFrame() RenderStereoTargets(); RenderCompanionWindow(); - vr::Texture_t leftEyeTexture = {(void*)leftEyeDesc.m_nResolveTextureId, vr::TextureType_OpenGL, vr::ColorSpace_Gamma }; + vr::Texture_t leftEyeTexture = {(void*)(uintptr_t)leftEyeDesc.m_nResolveTextureId, vr::TextureType_OpenGL, vr::ColorSpace_Gamma }; vr::VRCompositor()->Submit(vr::Eye_Left, &leftEyeTexture ); - vr::Texture_t rightEyeTexture = {(void*)rightEyeDesc.m_nResolveTextureId, vr::TextureType_OpenGL, vr::ColorSpace_Gamma }; + vr::Texture_t rightEyeTexture = {(void*)(uintptr_t)rightEyeDesc.m_nResolveTextureId, vr::TextureType_OpenGL, vr::ColorSpace_Gamma }; vr::VRCompositor()->Submit(vr::Eye_Right, &rightEyeTexture ); } @@ -1183,7 +1195,7 @@ void CMainApplication::RenderControllerAxes() glBindBuffer( GL_ARRAY_BUFFER, m_glControllerVertBuffer ); GLuint stride = 2 * 3 * sizeof( float ); - GLuint offset = 0; + uintptr_t offset = 0; glEnableVertexAttribArray( 0 ); glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, stride, (const void *)offset); @@ -1458,7 +1470,7 @@ void CMainApplication::RenderCompanionWindow() glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); - glDrawElements( GL_TRIANGLES, m_uiCompanionWindowIndexSize/2, GL_UNSIGNED_SHORT, (const void *)(m_uiCompanionWindowIndexSize) ); + glDrawElements( GL_TRIANGLES, m_uiCompanionWindowIndexSize/2, GL_UNSIGNED_SHORT, (const void *)(uintptr_t)(m_uiCompanionWindowIndexSize) ); glBindVertexArray( 0 ); glUseProgram( 0 ); diff --git a/samples/helloworldoverlay/CMakeLists.txt b/samples/helloworldoverlay/CMakeLists.txt index c2f7b0e2..134bafd2 100644 --- a/samples/helloworldoverlay/CMakeLists.txt +++ b/samples/helloworldoverlay/CMakeLists.txt @@ -1,5 +1,14 @@ set(TARGET_NAME helloworldoverlay) +if(APPLE) + if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set_source_files_properties(../shared/pathtools.cpp PROPERTIES COMPILE_FLAGS "-x objective-c++") + find_library(FOUNDATION_FRAMEWORK Foundation) + mark_as_advanced(FOUNDATION_FRAMEWORK) + set(EXTRA_LIBS ${EXTRA_LIBS} ${FOUNDATION_FRAMEWORK}) + endif() +endif() + add_executable(${TARGET_NAME} ${SHARED_SRC_FILES} main.cpp @@ -18,6 +27,7 @@ target_link_libraries(${TARGET_NAME} ${QT_LIBRARIES} ${OPENVR_LIBRARIES} ${CMAKE_DL_LIBS} + ${EXTRA_LIBS} ) set_target_properties(${TARGET_NAME} diff --git a/samples/helloworldoverlay/openvroverlaycontroller.cpp b/samples/helloworldoverlay/openvroverlaycontroller.cpp index a691a4d1..edb80322 100644 --- a/samples/helloworldoverlay/openvroverlaycontroller.cpp +++ b/samples/helloworldoverlay/openvroverlaycontroller.cpp @@ -172,7 +172,7 @@ void COpenVROverlayController::OnSceneChanged( const QList& ) { // skip rendering if the overlay isn't visible if( !vr::VROverlay() || - !vr::VROverlay()->IsOverlayVisible( m_ulOverlayHandle ) && !vr::VROverlay()->IsOverlayVisible( m_ulOverlayThumbnailHandle ) ) + ( !vr::VROverlay()->IsOverlayVisible( m_ulOverlayHandle ) && !vr::VROverlay()->IsOverlayVisible( m_ulOverlayThumbnailHandle ) ) ) return; m_pOpenGLContext->makeCurrent( m_pOffscreenSurface ); @@ -188,7 +188,7 @@ void COpenVROverlayController::OnSceneChanged( const QList& ) GLuint unTexture = m_pFbo->texture(); if( unTexture != 0 ) { - vr::Texture_t texture = {(void*)unTexture, vr::TextureType_OpenGL, vr::ColorSpace_Auto }; + vr::Texture_t texture = {(void*)(uintptr_t)unTexture, vr::TextureType_OpenGL, vr::ColorSpace_Auto }; vr::VROverlay()->SetOverlayTexture( m_ulOverlayHandle, &texture ); } } diff --git a/samples/shared/compat.h b/samples/shared/compat.h index 0163b08f..154f8b07 100644 --- a/samples/shared/compat.h +++ b/samples/shared/compat.h @@ -15,6 +15,7 @@ #define vsprintf_s sprintf #define _stricmp strcmp #define stricmp strcmp +#define strnicmp strncasecmp #define strcpy_s(dst, n, src) int(strncpy(dst, src, n) != nullptr) #define fopen_s(fd, path, mode) int((*fd = fopen(path, mode)) != nullptr) #define _vsnprintf_s(buffer, size, fmt, ap) vsnprintf(buffer, size, fmt, ap) @@ -24,4 +25,4 @@ typedef int errno_t; #endif // _WIN32 -#endif // OPENVR_SAMPLES_SHARED_COMPAT_H_ \ No newline at end of file +#endif // OPENVR_SAMPLES_SHARED_COMPAT_H_ diff --git a/samples/shared/pathtools.cpp b/samples/shared/pathtools.cpp index d148a5d8..2ea35240 100644 --- a/samples/shared/pathtools.cpp +++ b/samples/shared/pathtools.cpp @@ -1,22 +1,27 @@ //========= Copyright Valve Corporation ============// +#include "compat.h" +#include "strtools.h" #include "pathtools.h" -//#include "hmdplatform_private.h" -//#include "vrcommon/strtools.h" #if defined( _WIN32) #include #include #include #include -#elif defined OSX -#include -#include -#include "osxfilebridge.h" -#define _S_IFDIR S_IFDIR // really from tier0/platform.h which we dont have yet -#define _MAX_PATH MAX_PATH // yet another form of _PATH define we use -#elif defined(LINUX) +#include + +#undef GetEnvironmentVariable +#else #include #include +#include +#include +#endif +#if defined OSX +#include +#include +#include +#define _S_IFDIR S_IFDIR // really from tier0/platform.h which we dont have yet #endif #include @@ -26,44 +31,54 @@ /** Returns the path (including filename) to the current executable */ std::string Path_GetExecutablePath() { - bool bSuccess = false; - char rchPath[ 1024 ]; - size_t nBuff = sizeof(rchPath); #if defined( _WIN32 ) - bSuccess = ::GetModuleFileNameA(NULL, rchPath, (DWORD)nBuff) > 0; -#elif defined OSX - uint32_t _nBuff = nBuff; - bSuccess = _NSGetExecutablePath(rchPath, &_nBuff) == 0; + wchar_t *pwchPath = new wchar_t[MAX_UNICODE_PATH]; + char *pchPath = new char[MAX_UNICODE_PATH_IN_UTF8]; + ::GetModuleFileNameW( NULL, pwchPath, MAX_UNICODE_PATH ); + WideCharToMultiByte( CP_UTF8, 0, pwchPath, -1, pchPath, MAX_UNICODE_PATH_IN_UTF8, NULL, NULL ); + delete[] pwchPath; + + std::string sPath = pchPath; + delete[] pchPath; + return sPath; +#elif defined( OSX ) + char rchPath[1024]; + uint32_t nBuff = sizeof( rchPath ); + bool bSuccess = _NSGetExecutablePath(rchPath, &nBuff) == 0; rchPath[nBuff-1] = '\0'; + if( bSuccess ) + return rchPath; + else + return ""; #elif defined LINUX + char rchPath[1024]; + size_t nBuff = sizeof( rchPath ); ssize_t nRead = readlink("/proc/self/exe", rchPath, nBuff-1 ); if ( nRead != -1 ) { rchPath[ nRead ] = 0; - bSuccess = true; + return rchPath; } else { - rchPath[ 0 ] = '\0'; + return ""; } #else AssertMsg( false, "Implement Plat_GetExecutablePath" ); + return ""; #endif - if( bSuccess ) - return rchPath; - else - return ""; } /** Returns the path of the current working directory */ std::string Path_GetWorkingDirectory() { std::string sPath; - char buf[ 1024 ]; #if defined( _WIN32 ) - sPath = _getcwd( buf, sizeof( buf ) ); + wchar_t buf[MAX_UNICODE_PATH]; + sPath = UTF16to8( _wgetcwd( buf, MAX_UNICODE_PATH ) ); #else + char buf[ 1024 ]; sPath = getcwd( buf, sizeof( buf ) ); #endif return sPath; @@ -74,37 +89,14 @@ bool Path_SetWorkingDirectory( const std::string & sPath ) { bool bSuccess; #if defined( _WIN32 ) - bSuccess = 0 == _chdir( sPath.c_str() ); + std::wstring wsPath = UTF8to16( sPath.c_str() ); + bSuccess = 0 == _wchdir( wsPath.c_str() ); #else bSuccess = 0 == chdir( sPath.c_str() ); #endif return bSuccess; } -std::string Path_GetModulePath() -{ -#if defined( _WIN32 ) - char path[32768]; - HMODULE hm = NULL; - - if (!GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, - (LPCSTR) &Path_GetModulePath, - &hm)) - { - int ret = GetLastError(); - fprintf(stderr, "GetModuleHandle returned %d\n", ret); - return ""; - } - GetModuleFileNameA(hm, path, sizeof(path)); - FreeLibrary( hm ); - return path; -#else - Dl_info dl_info; - dladdr((void *)Path_GetModulePath, &dl_info); - return dl_info.dli_fname; -#endif -} - /** Returns the specified path without its filename */ std::string Path_StripFilename( const std::string & sPath, char slash ) { @@ -151,17 +143,45 @@ std::string Path_StripExtension( const std::string & sPath ) return sPath; } +/** returns just extension of the provided filename (if any). */ +std::string Path_GetExtension( const std::string & sPath ) +{ + for ( std::string::const_reverse_iterator i = sPath.rbegin(); i != sPath.rend(); i++ ) + { + if ( *i == '.' ) + { + return std::string( i.base(), sPath.end() ); + } + + // if we find a slash there is no extension + if ( *i == '\\' || *i == '/' ) + break; + } + + // we didn't find an extension + return ""; +} bool Path_IsAbsolute( const std::string & sPath ) { if( sPath.empty() ) return false; - if( sPath.find( ':' ) != std::string::npos ) - return true; +#if defined( WIN32 ) + if ( sPath.size() < 3 ) // must be c:\x or \\x at least + return false; - if( sPath[0] == '\\' || sPath[0] == '/' ) + if ( sPath[1] == ':' ) // drive letter plus slash, but must test both slash cases + { + if ( sPath[2] == '\\' || sPath[2] == '/' ) + return true; + } + else if ( sPath[0] == '\\' && sPath[1] == '\\' ) // UNC path + return true; +#else + if( sPath[0] == '\\' || sPath[0] == '/' ) // any leading slash return true; +#endif return false; } @@ -223,6 +243,8 @@ std::string Path_Join( const std::string & first, const std::string & second, ch // only insert a slash if we don't already have one std::string::size_type nLen = first.length(); + if( !nLen ) + return second; #if defined(_WIN32) if( first.back() == '\\' || first.back() == '/' ) nLen--; @@ -257,6 +279,41 @@ std::string Path_Join( return Path_Join( Path_Join( Path_Join( Path_Join( first, second, slash ), third, slash ), fourth, slash ), fifth, slash ); } + +std::string Path_RemoveTrailingSlash( const std::string & sRawPath, char slash ) +{ + if ( slash == 0 ) + slash = Path_GetSlash(); + + std::string sPath = sRawPath; + std::string::size_type nCurrent = sRawPath.length(); + if ( nCurrent == 0 ) + return sPath; + + int nLastFound = -1; + nCurrent--; + while( nCurrent != 0 ) + { + if ( sRawPath[ nCurrent ] == slash ) + { + nLastFound = (int)nCurrent; + nCurrent--; + } + else + { + break; + } + } + + if ( nLastFound >= 0 ) + { + sPath.erase( nLastFound, std::string::npos ); + } + + return sPath; +} + + /** Removes redundant /.. elements in the path. Returns an empty path if the * specified path has a broken number of directories for its number of ..s */ std::string Path_Compact( const std::string & sRawPath, char slash ) @@ -336,17 +393,15 @@ std::string Path_Compact( const std::string & sRawPath, char slash ) return sPath; } -#define MAX_UNICODE_PATH 32768 -#define MAX_UNICODE_PATH_IN_UTF8 ( MAX_UNICODE_PATH * 4 ) /** Returns the path to the current DLL or exe */ -std::string GetThisModulePath() +std::string Path_GetThisModulePath() { // gets the path of vrclient.dll itself #ifdef WIN32 HMODULE hmodule = NULL; - ::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, reinterpret_cast(GetThisModulePath), &hmodule); + ::GetModuleHandleEx( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, reinterpret_cast(Path_GetThisModulePath), &hmodule ); wchar_t *pwchPath = new wchar_t[MAX_UNICODE_PATH]; char *pchPath = new char[ MAX_UNICODE_PATH_IN_UTF8 ]; @@ -361,7 +416,7 @@ std::string GetThisModulePath() #elif defined( OSX ) || defined( LINUX ) // get the addr of a function in vrclient.so and then ask the dlopen system about it Dl_info info; - dladdr( (void *)GetThisModulePath, &info ); + dladdr( (void *)Path_GetThisModulePath, &info ); return info.dli_fname; #endif @@ -379,19 +434,44 @@ bool Path_IsDirectory( const std::string & sPath ) sFixedPath.erase( sFixedPath.end() - 1, sFixedPath.end() ); // see if the specified path actually exists. + +#if defined(POSIX) struct stat buf; - if ( stat ( sFixedPath.c_str(), &buf ) == -1) + if ( stat( sFixedPath.c_str(), &buf ) == -1 ) { return false; } -#if defined(LINUX) +#if defined( LINUX ) || defined( OSX ) return S_ISDIR( buf.st_mode ); #else - return ( buf.st_mode & _S_IFDIR ) != 0; + return (buf.st_mode & _S_IFDIR) != 0; +#endif + +#else + struct _stat buf; + std::wstring wsFixedPath = UTF8to16( sFixedPath.c_str() ); + if ( _wstat( wsFixedPath.c_str(), &buf ) == -1 ) + { + return false; + } + + return (buf.st_mode & _S_IFDIR) != 0; #endif } +/** returns true if the specified path represents an app bundle */ +bool Path_IsAppBundle( const std::string & sPath ) +{ +#if defined(OSX) + NSBundle *bundle = [ NSBundle bundleWithPath: [ NSString stringWithUTF8String:sPath.c_str() ] ]; + bool bisAppBundle = ( nullptr != bundle ); + [ bundle release ]; + return bisAppBundle; +#else + return false; +#endif +} //----------------------------------------------------------------------------- // Purpose: returns true if the the path exists @@ -402,11 +482,20 @@ bool Path_Exists( const std::string & sPath ) if( sFixedPath.empty() ) return false; +#if defined( WIN32 ) + struct _stat buf; + std::wstring wsFixedPath = UTF8to16( sFixedPath.c_str() ); + if ( _wstat( wsFixedPath.c_str(), &buf ) == -1 ) + { + return false; + } +#else struct stat buf; if ( stat ( sFixedPath.c_str(), &buf ) == -1) { return false; } +#endif return true; } @@ -475,11 +564,9 @@ unsigned char * Path_ReadBinaryFile( const std::string &strFilename, int *pSize #if defined( POSIX ) f = fopen( strFilename.c_str(), "rb" ); #else - errno_t err = fopen_s(&f, strFilename.c_str(), "rb"); - if ( err != 0 ) - { - f = NULL; - } + std::wstring wstrFilename = UTF8to16( strFilename.c_str() ); + // the open operation needs to be sharable, therefore use of _wfsopen instead of _wfopen_s + f = _wfsopen( wstrFilename.c_str(), L"rb", _SH_DENYNO ); #endif unsigned char* buf = NULL; @@ -508,6 +595,68 @@ unsigned char * Path_ReadBinaryFile( const std::string &strFilename, int *pSize return buf; } +uint32_t Path_ReadBinaryFile( const std::string &strFilename, unsigned char *pBuffer, uint32_t unSize ) +{ + FILE *f; +#if defined( POSIX ) + f = fopen( strFilename.c_str(), "rb" ); +#else + std::wstring wstrFilename = UTF8to16( strFilename.c_str() ); + errno_t err = _wfopen_s( &f, wstrFilename.c_str(), L"rb" ); + if ( err != 0 ) + { + f = NULL; + } +#endif + + uint32_t unSizeToReturn = 0; + + if ( f != NULL ) + { + fseek( f, 0, SEEK_END ); + uint32_t size = (uint32_t)ftell( f ); + fseek( f, 0, SEEK_SET ); + + if ( size > unSize || !pBuffer ) + { + unSizeToReturn = (uint32_t)size; + } + else + { + if ( fread( pBuffer, size, 1, f ) == 1 ) + { + unSizeToReturn = (uint32_t)size; + } + } + + fclose( f ); + } + + return unSizeToReturn; +} + +bool Path_WriteBinaryFile(const std::string &strFilename, unsigned char *pData, unsigned nSize) +{ + FILE *f; +#if defined( POSIX ) + f = fopen(strFilename.c_str(), "wb"); +#else + std::wstring wstrFilename = UTF8to16( strFilename.c_str() ); + errno_t err = _wfopen_s( &f, wstrFilename.c_str(), L"wb" ); + if (err != 0) + { + f = NULL; + } +#endif + + size_t written = 0; + if (f != NULL) { + written = fwrite(pData, sizeof(unsigned char), nSize, f); + fclose(f); + } + + return written = nSize ? true : false; +} std::string Path_ReadTextFile( const std::string &strFilename ) { @@ -520,7 +669,7 @@ std::string Path_ReadTextFile( const std::string &strFilename ) return ""; // convert CRLF -> LF - int outsize = 1; + size_t outsize = 1; for (int i=1; i < size; i++) { if (buf[i] == '\n' && buf[i-1] == '\r') // CRLF @@ -529,7 +678,7 @@ std::string Path_ReadTextFile( const std::string &strFilename ) buf[outsize++] = buf[i]; // just copy } - std::string ret((char *)buf, (char *)(buf + outsize)); + std::string ret((char *)buf, outsize); delete[] buf; return ret; } @@ -541,7 +690,8 @@ bool Path_WriteStringToTextFile( const std::string &strFilename, const char *pch #if defined( POSIX ) f = fopen( strFilename.c_str(), "w" ); #else - errno_t err = fopen_s(&f, strFilename.c_str(), "w"); + std::wstring wstrFilename = UTF8to16( strFilename.c_str() ); + errno_t err = _wfopen_s( &f, wstrFilename.c_str(), L"w" ); if ( err != 0 ) { f = NULL; @@ -557,4 +707,113 @@ bool Path_WriteStringToTextFile( const std::string &strFilename, const char *pch } return ok; -} \ No newline at end of file +} + +bool Path_WriteStringToTextFileAtomic( const std::string &strFilename, const char *pchData ) +{ + std::string strTmpFilename = strFilename + ".tmp"; + + if ( !Path_WriteStringToTextFile( strTmpFilename, pchData ) ) + return false; + + // Platform specific atomic file replacement +#if defined( _WIN32 ) + std::wstring wsFilename = UTF8to16( strFilename.c_str() ); + std::wstring wsTmpFilename = UTF8to16( strTmpFilename.c_str() ); + if ( !::ReplaceFileW( wsFilename.c_str(), wsTmpFilename.c_str(), nullptr, 0, 0, 0 ) ) + { + // if we couldn't ReplaceFile, try a non-atomic write as a fallback + if ( !Path_WriteStringToTextFile( strFilename, pchData ) ) + return false; + } +#elif defined( POSIX ) + if ( rename( strTmpFilename.c_str(), strFilename.c_str() ) == -1 ) + return false; +#else +#error Do not know how to write atomic file +#endif + + return true; +} + + +#if defined(WIN32) +#define FILE_URL_PREFIX "file:///" +#else +#define FILE_URL_PREFIX "file://" +#endif + +// ---------------------------------------------------------------------------------------------------------------------------- +// Purpose: Turns a path to a file on disk into a URL (or just returns the value if it's already a URL) +// ---------------------------------------------------------------------------------------------------------------------------- +std::string Path_FilePathToUrl( const std::string & sRelativePath, const std::string & sBasePath ) +{ + if ( !strnicmp( sRelativePath.c_str(), "http://", 7 ) + || !strnicmp( sRelativePath.c_str(), "https://", 8 ) + || !strnicmp( sRelativePath.c_str(), "file://", 7 ) ) + { + return sRelativePath; + } + else + { + std::string sAbsolute = Path_MakeAbsolute( sRelativePath, sBasePath ); + if ( sAbsolute.empty() ) + return sAbsolute; + return std::string( FILE_URL_PREFIX ) + sAbsolute; + } +} + +// ----------------------------------------------------------------------------------------------------- +// Purpose: Strips off file:// off a URL and returns the path. For other kinds of URLs an empty string is returned +// ----------------------------------------------------------------------------------------------------- +std::string Path_UrlToFilePath( const std::string & sFileUrl ) +{ + if ( !strnicmp( sFileUrl.c_str(), FILE_URL_PREFIX, strlen( FILE_URL_PREFIX ) ) ) + { + return sFileUrl.c_str() + strlen( FILE_URL_PREFIX ); + } + else + { + return ""; + } +} + + +// ----------------------------------------------------------------------------------------------------- +// Purpose: Returns the root of the directory the system wants us to store user documents in +// ----------------------------------------------------------------------------------------------------- +std::string GetUserDocumentsPath() +{ +#if defined( WIN32 ) + WCHAR rwchPath[MAX_PATH]; + + if ( !SUCCEEDED( SHGetFolderPathW( NULL, CSIDL_MYDOCUMENTS | CSIDL_FLAG_CREATE, NULL, 0, rwchPath ) ) ) + { + return ""; + } + + // Convert the path to UTF-8 and store in the output + std::string sUserPath = UTF16to8( rwchPath ); + + return sUserPath; +#elif defined( OSX ) + @autoreleasepool { + NSArray *paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES ); + if ( [paths count] == 0 ) + { + return ""; + } + + return [[paths objectAtIndex:0] UTF8String]; + } +#elif defined( LINUX ) + // @todo: not solved/changed as part of OSX - still not real - just removed old class based steam cut and paste + const char *pchHome = getenv( "HOME" ); + if ( pchHome == NULL ) + { + return ""; + } + return pchHome; +#endif +} + diff --git a/samples/shared/pathtools.h b/samples/shared/pathtools.h index ad92b280..7c34a717 100644 --- a/samples/shared/pathtools.h +++ b/samples/shared/pathtools.h @@ -2,6 +2,7 @@ #pragma once #include +#include /** Returns the path (including filename) to the current executable */ std::string Path_GetExecutablePath(); @@ -13,7 +14,7 @@ std::string Path_GetWorkingDirectory(); bool Path_SetWorkingDirectory( const std::string & sPath ); /** returns the path (including filename) of the current shared lib or DLL */ -std::string Path_GetModulePath(); +std::string Path_GetThisModulePath(); /** Returns the specified path without its filename. * If slash is unspecified the native path separator of the current platform @@ -27,6 +28,9 @@ std::string Path_StripDirectory( const std::string & sPath, char slash = 0 ); * If there is a path the path is left intact. */ std::string Path_StripExtension( const std::string & sPath ); +/** returns just extension of the provided filename (if any). */ +std::string Path_GetExtension( const std::string & sPath ); + /** Returns true if the path is absolute */ bool Path_IsAbsolute( const std::string & sPath ); @@ -60,11 +64,14 @@ std::string Path_Join( * will be used. */ std::string Path_Compact( const std::string & sRawPath, char slash = 0 ); +//** Removed trailing slashes */ +std::string Path_RemoveTrailingSlash( const std::string & sRawPath, char slash = 0 ); + /** returns true if the specified path exists and is a directory */ bool Path_IsDirectory( const std::string & sPath ); -/** Returns the path to the current DLL or exe */ -std::string GetThisModulePath(); +/** returns true if the specified path represents an app bundle */ +bool Path_IsAppBundle( const std::string & sPath ); /** returns true if the the path exists */ bool Path_Exists( const std::string & sPath ); @@ -75,8 +82,28 @@ std::string Path_FindParentSubDirectoryRecursively( const std::string &strStartD /** Path operations to read or write text/binary files */ unsigned char * Path_ReadBinaryFile( const std::string &strFilename, int *pSize ); +uint32_t Path_ReadBinaryFile( const std::string &strFilename, unsigned char *pBuffer, uint32_t unSize ); +bool Path_WriteBinaryFile( const std::string &strFilename, unsigned char *pData, unsigned nSize ); std::string Path_ReadTextFile( const std::string &strFilename ); bool Path_WriteStringToTextFile( const std::string &strFilename, const char *pchData ); +bool Path_WriteStringToTextFileAtomic( const std::string &strFilename, const char *pchData ); + +/** Returns a file:// url for paths, or an http or https url if that's what was provided */ +std::string Path_FilePathToUrl( const std::string & sRelativePath, const std::string & sBasePath ); + +/** Strips off file:// off a URL and returns the path. For other kinds of URLs an empty string is returned */ +std::string Path_UrlToFilePath( const std::string & sFileUrl ); + +/** Returns the root of the directory the system wants us to store user documents in */ +std::string GetUserDocumentsPath(); + +#ifndef MAX_UNICODE_PATH + #define MAX_UNICODE_PATH 32767 +#endif + +#ifndef MAX_UNICODE_PATH_IN_UTF8 + #define MAX_UNICODE_PATH_IN_UTF8 (MAX_UNICODE_PATH * 4) +#endif //----------------------------------------------------------------------------- #if defined(WIN32) @@ -91,8 +118,12 @@ bool Path_WriteStringToTextFile( const std::string &strFilename, const char *pch #define PLATSUBDIR "osx32" #elif defined(LINUX) #define DYNAMIC_LIB_EXT ".so" +#if defined( LINUX32 ) #define PLATSUBDIR "linux32" #else +#define PLATSUBDIR "linux64" +#endif +#else #warning "Unknown platform for PLATSUBDIR" #define PLATSUBDIR "unknown_platform" #endif diff --git a/samples/shared/strtools.cpp b/samples/shared/strtools.cpp new file mode 100644 index 00000000..6166db48 --- /dev/null +++ b/samples/shared/strtools.cpp @@ -0,0 +1,437 @@ +//========= Copyright Valve Corporation ============// +#include "strtools.h" +#include +#include +#include + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool StringHasPrefix( const std::string & sString, const std::string & sPrefix ) +{ + return 0 == strnicmp( sString.c_str(), sPrefix.c_str(), sPrefix.length() ); +} + +bool StringHasPrefixCaseSensitive( const std::string & sString, const std::string & sPrefix ) +{ + return 0 == strncmp( sString.c_str(), sPrefix.c_str(), sPrefix.length() ); +} + + +bool StringHasSuffix( const std::string &sString, const std::string &sSuffix ) +{ + size_t cStrLen = sString.length(); + size_t cSuffixLen = sSuffix.length(); + + if ( cSuffixLen > cStrLen ) + return false; + + std::string sStringSuffix = sString.substr( cStrLen - cSuffixLen, cSuffixLen ); + + return 0 == stricmp( sStringSuffix.c_str(), sSuffix.c_str() ); +} + +bool StringHasSuffixCaseSensitive( const std::string &sString, const std::string &sSuffix ) +{ + size_t cStrLen = sString.length(); + size_t cSuffixLen = sSuffix.length(); + + if ( cSuffixLen > cStrLen ) + return false; + + std::string sStringSuffix = sString.substr( cStrLen - cSuffixLen, cSuffixLen ); + + return 0 == strncmp( sStringSuffix.c_str(), sSuffix.c_str(),cSuffixLen ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +std::string UTF16to8(const wchar_t * in) +{ + std::string out; + unsigned int codepoint = 0; + for ( ; in && *in != 0; ++in ) + { + if (*in >= 0xd800 && *in <= 0xdbff) + codepoint = ((*in - 0xd800) << 10) + 0x10000; + else + { + if (*in >= 0xdc00 && *in <= 0xdfff) + codepoint |= *in - 0xdc00; + else + codepoint = *in; + + if (codepoint <= 0x7f) + out.append(1, static_cast(codepoint)); + else if (codepoint <= 0x7ff) + { + out.append(1, static_cast(0xc0 | ((codepoint >> 6) & 0x1f))); + out.append(1, static_cast(0x80 | (codepoint & 0x3f))); + } + else if (codepoint <= 0xffff) + { + out.append(1, static_cast(0xe0 | ((codepoint >> 12) & 0x0f))); + out.append(1, static_cast(0x80 | ((codepoint >> 6) & 0x3f))); + out.append(1, static_cast(0x80 | (codepoint & 0x3f))); + } + else + { + out.append(1, static_cast(0xf0 | ((codepoint >> 18) & 0x07))); + out.append(1, static_cast(0x80 | ((codepoint >> 12) & 0x3f))); + out.append(1, static_cast(0x80 | ((codepoint >> 6) & 0x3f))); + out.append(1, static_cast(0x80 | (codepoint & 0x3f))); + } + codepoint = 0; + } + } + return out; +} + +std::wstring UTF8to16(const char * in) +{ + std::wstring out; + unsigned int codepoint = 0; + int following = 0; + for ( ; in && *in != 0; ++in ) + { + unsigned char ch = *in; + if (ch <= 0x7f) + { + codepoint = ch; + following = 0; + } + else if (ch <= 0xbf) + { + if (following > 0) + { + codepoint = (codepoint << 6) | (ch & 0x3f); + --following; + } + } + else if (ch <= 0xdf) + { + codepoint = ch & 0x1f; + following = 1; + } + else if (ch <= 0xef) + { + codepoint = ch & 0x0f; + following = 2; + } + else + { + codepoint = ch & 0x07; + following = 3; + } + if (following == 0) + { + if (codepoint > 0xffff) + { + out.append(1, static_cast(0xd800 + (codepoint >> 10))); + out.append(1, static_cast(0xdc00 + (codepoint & 0x03ff))); + } + else + out.append(1, static_cast(codepoint)); + codepoint = 0; + } + } + return out; +} + + +void strcpy_safe( char *pchBuffer, size_t unBufferSizeBytes, const char *pchSource ) +{ + pchBuffer[ unBufferSizeBytes - 1 ] = '\0'; + strncpy( pchBuffer, pchSource, unBufferSizeBytes - 1 ); +} + + +// -------------------------------------------------------------------- +// Purpose: converts a string to upper case +// -------------------------------------------------------------------- +std::string StringToUpper( const std::string & sString ) +{ + std::string sOut; + sOut.reserve( sString.size() + 1 ); + for( std::string::const_iterator i = sString.begin(); i != sString.end(); i++ ) + { + sOut.push_back( (char)toupper( *i ) ); + } + + return sOut; +} + + +// -------------------------------------------------------------------- +// Purpose: converts a string to lower case +// -------------------------------------------------------------------- +std::string StringToLower( const std::string & sString ) +{ + std::string sOut; + sOut.reserve( sString.size() + 1 ); + for( std::string::const_iterator i = sString.begin(); i != sString.end(); i++ ) + { + sOut.push_back( (char)tolower( *i ) ); + } + + return sOut; +} + + +uint32_t ReturnStdString( const std::string & sValue, char *pchBuffer, uint32_t unBufferLen ) +{ + uint32_t unLen = (uint32_t)sValue.length() + 1; + if( !pchBuffer || !unBufferLen ) + return unLen; + + if( unBufferLen < unLen ) + { + pchBuffer[0] = '\0'; + } + else + { + memcpy( pchBuffer, sValue.c_str(), unLen ); + } + + return unLen; +} + +void BufferToStdString( std::string & sDest, const char *pchBuffer, uint32_t unBufferLen ) +{ + sDest.resize( unBufferLen + 1 ); + memcpy( const_cast< char* >( sDest.c_str() ), pchBuffer, unBufferLen ); + const_cast< char* >( sDest.c_str() )[ unBufferLen ] = '\0'; +} + +/** Returns a std::string from a uint64_t */ +std::string Uint64ToString( uint64_t ulValue ) +{ + char buf[ 22 ]; +#if defined( _WIN32 ) + sprintf_s( buf, "%llu", ulValue ); +#else + snprintf( buf, sizeof( buf ), "%llu", (long long unsigned int ) ulValue ); +#endif + return buf; +} + + +/** returns a uint64_t from a string */ +uint64_t StringToUint64( const std::string & sValue ) +{ + return strtoull( sValue.c_str(), NULL, 0 ); +} + +//----------------------------------------------------------------------------- +// Purpose: Helper for converting a numeric value to a hex digit, value should be 0-15. +//----------------------------------------------------------------------------- +char cIntToHexDigit( int nValue ) +{ + //Assert( nValue >= 0 && nValue <= 15 ); + return "0123456789ABCDEF"[ nValue & 15 ]; +} + +//----------------------------------------------------------------------------- +// Purpose: Helper for converting a hex char value to numeric, return -1 if the char +// is not a valid hex digit. +//----------------------------------------------------------------------------- +int iHexCharToInt( char cValue ) +{ + int32_t iValue = cValue; + if ( (uint32_t)( iValue - '0' ) < 10 ) + return iValue - '0'; + + iValue |= 0x20; + if ( (uint32_t)( iValue - 'a' ) < 6 ) + return iValue - 'a' + 10; + + return -1; +} + +//----------------------------------------------------------------------------- +// Purpose: Internal implementation of encode, works in the strict RFC manner, or +// with spaces turned to + like HTML form encoding. +//----------------------------------------------------------------------------- +void V_URLEncodeInternal( char *pchDest, int nDestLen, const char *pchSource, int nSourceLen, bool bUsePlusForSpace ) +{ + //AssertMsg( nDestLen > 3*nSourceLen, "Target buffer for V_URLEncode should be 3x source length, plus one for terminating null\n" ); + + int iDestPos = 0; + for ( int i=0; i < nSourceLen; ++i ) + { + // worst case we need 3 additional chars + if( (iDestPos+3) > nDestLen ) + { + pchDest[0] = '\0'; +// AssertMsg( false, "Target buffer too short\n" ); + return; + } + + // We allow only a-z, A-Z, 0-9, period, underscore, and hyphen to pass through unescaped. + // These are the characters allowed by both the original RFC 1738 and the latest RFC 3986. + // Current specs also allow '~', but that is forbidden under original RFC 1738. + if ( !( pchSource[i] >= 'a' && pchSource[i] <= 'z' ) && !( pchSource[i] >= 'A' && pchSource[i] <= 'Z' ) && !(pchSource[i] >= '0' && pchSource[i] <= '9' ) + && pchSource[i] != '-' && pchSource[i] != '_' && pchSource[i] != '.' + ) + { + if ( bUsePlusForSpace && pchSource[i] == ' ' ) + { + pchDest[iDestPos++] = '+'; + } + else + { + pchDest[iDestPos++] = '%'; + uint8_t iValue = pchSource[i]; + if ( iValue == 0 ) + { + pchDest[iDestPos++] = '0'; + pchDest[iDestPos++] = '0'; + } + else + { + char cHexDigit1 = cIntToHexDigit( iValue % 16 ); + iValue /= 16; + char cHexDigit2 = cIntToHexDigit( iValue ); + pchDest[iDestPos++] = cHexDigit2; + pchDest[iDestPos++] = cHexDigit1; + } + } + } + else + { + pchDest[iDestPos++] = pchSource[i]; + } + } + + if( (iDestPos+1) > nDestLen ) + { + pchDest[0] = '\0'; + //AssertMsg( false, "Target buffer too short to terminate\n" ); + return; + } + + // Null terminate + pchDest[iDestPos++] = 0; +} + + +//----------------------------------------------------------------------------- +// Purpose: Internal implementation of decode, works in the strict RFC manner, or +// with spaces turned to + like HTML form encoding. +// +// Returns the amount of space used in the output buffer. +//----------------------------------------------------------------------------- +size_t V_URLDecodeInternal( char *pchDecodeDest, int nDecodeDestLen, const char *pchEncodedSource, int nEncodedSourceLen, bool bUsePlusForSpace ) +{ + if ( nDecodeDestLen < nEncodedSourceLen ) + { + //AssertMsg( false, "V_URLDecode needs a dest buffer at least as large as the source" ); + return 0; + } + + int iDestPos = 0; + for( int i=0; i < nEncodedSourceLen; ++i ) + { + if ( bUsePlusForSpace && pchEncodedSource[i] == '+' ) + { + pchDecodeDest[ iDestPos++ ] = ' '; + } + else if ( pchEncodedSource[i] == '%' ) + { + // Percent signifies an encoded value, look ahead for the hex code, convert to numeric, and use that + + // First make sure we have 2 more chars + if ( i < nEncodedSourceLen - 2 ) + { + char cHexDigit1 = pchEncodedSource[i+1]; + char cHexDigit2 = pchEncodedSource[i+2]; + + // Turn the chars into a hex value, if they are not valid, then we'll + // just place the % and the following two chars direct into the string, + // even though this really shouldn't happen, who knows what bad clients + // may do with encoding. + bool bValid = false; + int iValue = iHexCharToInt( cHexDigit1 ); + if ( iValue != -1 ) + { + iValue *= 16; + int iValue2 = iHexCharToInt( cHexDigit2 ); + if ( iValue2 != -1 ) + { + iValue += iValue2; + pchDecodeDest[ iDestPos++ ] = (char)iValue; + bValid = true; + } + } + + if ( !bValid ) + { + pchDecodeDest[ iDestPos++ ] = '%'; + pchDecodeDest[ iDestPos++ ] = cHexDigit1; + pchDecodeDest[ iDestPos++ ] = cHexDigit2; + } + } + + // Skip ahead + i += 2; + } + else + { + pchDecodeDest[ iDestPos++ ] = pchEncodedSource[i]; + } + } + + // We may not have extra room to NULL terminate, since this can be used on raw data, but if we do + // go ahead and do it as this can avoid bugs. + if ( iDestPos < nDecodeDestLen ) + { + pchDecodeDest[iDestPos] = 0; + } + + return (size_t)iDestPos; +} + +//----------------------------------------------------------------------------- +// Purpose: Encodes a string (or binary data) from URL encoding format, see rfc1738 section 2.2. +// This version of the call isn't a strict RFC implementation, but uses + for space as is +// the standard in HTML form encoding, despite it not being part of the RFC. +// +// Dest buffer should be at least as large as source buffer to guarantee room for decode. +//----------------------------------------------------------------------------- +void V_URLEncode( char *pchDest, int nDestLen, const char *pchSource, int nSourceLen ) +{ + return V_URLEncodeInternal( pchDest, nDestLen, pchSource, nSourceLen, true ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Decodes a string (or binary data) from URL encoding format, see rfc1738 section 2.2. +// This version of the call isn't a strict RFC implementation, but uses + for space as is +// the standard in HTML form encoding, despite it not being part of the RFC. +// +// Dest buffer should be at least as large as source buffer to guarantee room for decode. +// Dest buffer being the same as the source buffer (decode in-place) is explicitly allowed. +//----------------------------------------------------------------------------- +size_t V_URLDecode( char *pchDecodeDest, int nDecodeDestLen, const char *pchEncodedSource, int nEncodedSourceLen ) +{ + return V_URLDecodeInternal( pchDecodeDest, nDecodeDestLen, pchEncodedSource, nEncodedSourceLen, true ); +} + +//----------------------------------------------------------------------------- +void V_StripExtension( std::string &in ) +{ + // Find the last dot. If it's followed by a dot or a slash, then it's part of a + // directory specifier like ../../somedir/./blah. + std::string::size_type test = in.rfind( '.' ); + if ( test != std::string::npos ) + { + // This handles things like ".\blah" or "c:\my@email.com\abc\def\geh" + // Which would otherwise wind up with "" and "c:\my@email", respectively. + if ( in.rfind( '\\' ) < test && in.rfind( '/' ) < test ) + { + in.resize( test ); + } + } +} + diff --git a/samples/shared/strtools.h b/samples/shared/strtools.h new file mode 100644 index 00000000..b69ef15d --- /dev/null +++ b/samples/shared/strtools.h @@ -0,0 +1,130 @@ +//========= Copyright Valve Corporation ============// +#pragma once + +#include +#include +#include + +/** returns true if the string has the prefix */ +bool StringHasPrefix( const std::string & sString, const std::string & sPrefix ); +bool StringHasPrefixCaseSensitive( const std::string & sString, const std::string & sPrefix ); + +/** returns if the string has the suffix */ +bool StringHasSuffix( const std::string &sString, const std::string &sSuffix ); +bool StringHasSuffixCaseSensitive( const std::string &sString, const std::string &sSuffix ); + +/** converts a UTF-16 string to a UTF-8 string */ +std::string UTF16to8(const wchar_t * in); + +/** converts a UTF-8 string to a UTF-16 string */ +std::wstring UTF8to16(const char * in); +#define Utf16FromUtf8 UTF8to16 + +/** safely copy a string into a buffer */ +void strcpy_safe( char *pchBuffer, size_t unBufferSizeBytes, const char *pchSource ); +template< size_t bufferSize > +void strcpy_safe( char (& buffer) [ bufferSize ], const char *pchSource ) +{ + strcpy_safe( buffer, bufferSize, pchSource ); +} + + +/** converts a string to upper case */ +std::string StringToUpper( const std::string & sString ); + +/** converts a string to lower case */ +std::string StringToLower( const std::string & sString ); + +// we stricmp (from WIN) but it isn't POSIX - OSX/LINUX have strcasecmp so just inline bridge to it +#if defined( OSX ) || defined( LINUX ) +#include +inline int stricmp(const char *pStr1, const char *pStr2) { return strcasecmp(pStr1,pStr2); } +#ifndef _stricmp +#define _stricmp stricmp +#endif +inline int strnicmp( const char *pStr1, const char *pStr2, size_t unBufferLen ) { return strncasecmp( pStr1,pStr2, unBufferLen ); } +#define _strnicmp strnicmp + +#ifndef _vsnprintf_s +#define _vsnprintf_s vsnprintf +#endif + +#define _TRUNCATE ((size_t)-1) + +#endif + +#if defined( OSX ) +// behaviors ensure NULL-termination at least as well as _TRUNCATE does, but +// wcsncpy_s/strncpy_s can non-NULL-terminate, wcslcpy/strlcpy can not. +inline errno_t wcsncpy_s(wchar_t *strDest, size_t numberOfElements, const wchar_t *strSource, size_t count) +{ + return wcslcpy(strDest, strSource, numberOfElements); +} + +inline errno_t strncpy_s(char *strDest, size_t numberOfElements, const char *strSource, size_t count) +{ + return strlcpy(strDest, strSource, numberOfElements); +} + +#endif + +#if defined( LINUX ) +// this implementation does not return whether or not the destination was +// truncated, but that is straightforward to fix if anybody actually needs the +// return code. +#include "string.h" +inline void wcsncpy_s(wchar_t *strDest, size_t numberOfElements, const wchar_t *strSource, size_t count) +{ + wcsncpy(strDest, strSource, numberOfElements); + strDest[numberOfElements-1] = '\0'; +} + +inline void strncpy_s(char *strDest, size_t numberOfElements, const char *strSource, size_t count) +{ + strncpy(strDest, strSource, numberOfElements); + strDest[numberOfElements-1] = '\0'; +} + +#endif + +#if defined( _WIN32 ) && _MSC_VER < 1800 +inline uint64_t strtoull(const char *str, char **endptr, int base) { return _strtoui64( str, endptr, base ); } +#endif + +/* Handles copying a std::string into a buffer as would be provided in an API */ +uint32_t ReturnStdString( const std::string & sValue, char *pchBuffer, uint32_t unBufferLen ); + +/* Handles copying a buffer into an std::string and auto adds null terminator */ +void BufferToStdString( std::string & sDest, const char *pchBuffer, uint32_t unBufferLen ); + +/** Returns a std::string from a uint64_t */ +std::string Uint64ToString( uint64_t ulValue ); + +/** returns a uint64_t from a string */ +uint64_t StringToUint64( const std::string & sValue ); + +//----------------------------------------------------------------------------- +// Purpose: Encodes a string (or binary data) from URL encoding format, see rfc1738 section 2.2. +// This version of the call isn't a strict RFC implementation, but uses + for space as is +// the standard in HTML form encoding, despite it not being part of the RFC. +// +// Dest buffer should be at least as large as source buffer to guarantee room for decode. +//----------------------------------------------------------------------------- +void V_URLEncode( char *pchDest, int nDestLen, const char *pchSource, int nSourceLen ); + +//----------------------------------------------------------------------------- +// Purpose: Decodes a string (or binary data) from URL encoding format, see rfc1738 section 2.2. +// This version of the call isn't a strict RFC implementation, but uses + for space as is +// the standard in HTML form encoding, despite it not being part of the RFC. +// +// Dest buffer should be at least as large as source buffer to guarantee room for decode. +// Dest buffer being the same as the source buffer (decode in-place) is explicitly allowed. +//----------------------------------------------------------------------------- +size_t V_URLDecode( char *pchDecodeDest, int nDecodeDestLen, const char *pchEncodedSource, int nEncodedSourceLen ); + +//----------------------------------------------------------------------------- +// Purpose: strip extension from a path +//----------------------------------------------------------------------------- +void V_StripExtension( std::string &in ); + + diff --git a/samples/thirdparty/sdl2-2.0.3/bin/linux64/libSDL2-2.0.so.0 b/samples/thirdparty/sdl2-2.0.3/bin/linux64/libSDL2-2.0.so.0 new file mode 100755 index 00000000..80584b6a Binary files /dev/null and b/samples/thirdparty/sdl2-2.0.3/bin/linux64/libSDL2-2.0.so.0 differ diff --git a/samples/thirdparty/sdl2-2.0.3/bin/linux64/libSDL2-2.0.so.0.dbg b/samples/thirdparty/sdl2-2.0.3/bin/linux64/libSDL2-2.0.so.0.dbg new file mode 100755 index 00000000..c2f55994 Binary files /dev/null and b/samples/thirdparty/sdl2-2.0.3/bin/linux64/libSDL2-2.0.so.0.dbg differ diff --git a/samples/thirdparty/sdl2-2.0.3/bin/linux64/libSDL2.so b/samples/thirdparty/sdl2-2.0.3/bin/linux64/libSDL2.so new file mode 100644 index 00000000..80584b6a Binary files /dev/null and b/samples/thirdparty/sdl2-2.0.3/bin/linux64/libSDL2.so differ diff --git a/samples/thirdparty/sdl2-2.0.3/bin/linux64/libSDL2_static.a b/samples/thirdparty/sdl2-2.0.3/bin/linux64/libSDL2_static.a new file mode 100644 index 00000000..80ffbd89 Binary files /dev/null and b/samples/thirdparty/sdl2-2.0.3/bin/linux64/libSDL2_static.a differ diff --git a/samples/tracked_camera_openvr_sample/CMakeLists.txt b/samples/tracked_camera_openvr_sample/CMakeLists.txt index 15281a2a..2061e467 100644 --- a/samples/tracked_camera_openvr_sample/CMakeLists.txt +++ b/samples/tracked_camera_openvr_sample/CMakeLists.txt @@ -1,5 +1,14 @@ set(TARGET_NAME tracked_camera_openvr_sample) +if(APPLE) + if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set_source_files_properties(../shared/pathtools.cpp PROPERTIES COMPILE_FLAGS "-x objective-c++") + find_library(FOUNDATION_FRAMEWORK Foundation) + mark_as_advanced(FOUNDATION_FRAMEWORK) + set(EXTRA_LIBS ${EXTRA_LIBS} ${FOUNDATION_FRAMEWORK}) + endif() +endif() + add_executable(${TARGET_NAME} ${SHARED_SRC_FILES} main.cpp @@ -16,6 +25,7 @@ target_link_libraries(${TARGET_NAME} ${QT_LIBRARIES} ${OPENVR_LIBRARIES} ${CMAKE_DL_LIBS} + ${EXTRA_LIBS} ) set_target_properties(${TARGET_NAME} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 24f80c66..5ad5cfa0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,14 +1,74 @@ -cmake_minimum_required(VERSION 2.8) - +# Project name. project(openvr_api) -IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - add_definitions(-DOSX -DPOSIX) - set_source_files_properties(vrcommon/pathtools_public.cpp vrcommon/vrpathregistry_public.cpp PROPERTIES COMPILE_FLAGS "-x objective-c++") -ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") +set( LIBNAME "openvr_api" ) + +# Set some properies for specific files. +if(APPLE) + set(CMAKE_MACOSX_RPATH 0) + if(CMAKE_SYSTEM_NAME MATCHES "Darwin") + set_source_files_properties(vrcommon/pathtools_public.cpp vrcommon/vrpathregistry_public.cpp PROPERTIES COMPILE_FLAGS "-x objective-c++") + endif() + if(BUILD_SHARED) + find_library(FOUNDATION_FRAMEWORK Foundation) + mark_as_advanced(FOUNDATION_FRAMEWORK) + set(EXTRA_LIBS ${EXTRA_LIBS} ${FOUNDATION_FRAMEWORK}) + endif(BUILD_SHARED) +elseif(WIN32) + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + add_definitions( -DWIN64 ) + set( LIBNAME "openvr_api64" ) + endif() +endif() + +# Add include folders. +include_directories(${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/headers ${CMAKE_SOURCE_DIR}/src/vrcommon) + +if(USE_CUSTOM_LIBCXX) + link_directories( + ${LIBCXX_LIB_DIR} + ) +endif() + +# Set the source group and files. +set(CORE_FILES + openvr_api_public.cpp + jsoncpp.cpp +) +set(VRCOMMON_FILES + vrcommon/dirtools_public.cpp + vrcommon/envvartools_public.cpp + vrcommon/pathtools_public.cpp + vrcommon/sharedlibtools_public.cpp + vrcommon/hmderrors_public.cpp + vrcommon/vrpathregistry_public.cpp + vrcommon/strtools_public.cpp +) + +set(SOURCE_FILES + ${CORE_FILES} + ${VRCOMMON_FILES} +) + +source_group("Src" FILES + ${CORE_FILES} +) + +source_group("VRCommon" FILES + ${VRCOMMON_FILES} +) + +# Build the library. +if(BUILD_SHARED) + add_library(${LIBNAME} SHARED ${SOURCE_FILES}) +else() + add_library(${LIBNAME} STATIC ${SOURCE_FILES}) +endif() + +if(USE_CUSTOM_LIBCXX) + set(EXTRA_LIBS ${EXTRA_LIBS} c++ c++abi) +endif() -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") -include_directories(. ../headers) -add_library(openvr_api STATIC openvr_api_public.cpp jsoncpp.cpp vrcommon/dirtools_public.cpp vrcommon/envvartools_public.cpp vrcommon/pathtools_public.cpp vrcommon/sharedlibtools_public.cpp vrcommon/hmderrors_public.cpp vrcommon/vrpathregistry_public.cpp vrcommon/strtools_public.cpp vrcommon/vrpathregistry_public.cpp) +target_link_libraries(${LIBNAME} ${EXTRA_LIBS}) -install(TARGETS openvr_api DESTINATION lib) \ No newline at end of file +install(TARGETS ${LIBNAME} DESTINATION lib) diff --git a/src/openvr_api_public.cpp b/src/openvr_api_public.cpp index b7d06435..3e303dde 100644 --- a/src/openvr_api_public.cpp +++ b/src/openvr_api_public.cpp @@ -2,11 +2,11 @@ #define VR_API_EXPORT 1 #include "openvr.h" #include "ivrclientcore.h" -#include "vrcommon/pathtools.h" -#include "vrcommon/sharedlibtools.h" -#include "vrcommon/envvartools.h" -#include "vrcommon/hmderrors.h" -#include "vrcommon/vrpathregistry.h" +#include "pathtools_public.h" +#include "sharedlibtools_public.h" +#include "envvartools_public.h" +#include "hmderrors_public.h" +#include "vrpathregistry_public.h" using vr::EVRInitError; using vr::IVRSystem; @@ -30,6 +30,8 @@ uint32_t VR_GetInitToken() } EVRInitError VR_LoadHmdSystemInternal(); +void CleanupInternalInterfaces(); + uint32_t VR_InitInternal( EVRInitError *peError, vr::EVRApplicationType eApplicationType ) { @@ -78,6 +80,10 @@ void VR_ShutdownInternal() g_pVRModule = NULL; } +#if !defined( VR_API_PUBLIC ) + CleanupInternalInterfaces(); +#endif + ++g_nVRToken; } @@ -85,7 +91,7 @@ EVRInitError VR_LoadHmdSystemInternal() { std::string sRuntimePath, sConfigPath, sLogPath; - bool bReadPathRegistry = CVRPathRegistry::GetPaths( &sRuntimePath, &sConfigPath, &sLogPath, NULL, NULL ); + bool bReadPathRegistry = CVRPathRegistry_Public::GetPaths( &sRuntimePath, &sConfigPath, &sLogPath, NULL, NULL ); if( !bReadPathRegistry ) { return vr::VRInitError_Init_PathRegistryNotFound; @@ -203,7 +209,7 @@ bool VR_IsRuntimeInstalled() // otherwise we need to do a bit more work std::string sRuntimePath, sConfigPath, sLogPath; - bool bReadPathRegistry = CVRPathRegistry::GetPaths( &sRuntimePath, &sConfigPath, &sLogPath, NULL, NULL ); + bool bReadPathRegistry = CVRPathRegistry_Public::GetPaths( &sRuntimePath, &sConfigPath, &sLogPath, NULL, NULL ); if( !bReadPathRegistry ) { return false; @@ -229,7 +235,7 @@ const char *VR_RuntimePath() static std::string sRuntimePath; std::string sConfigPath, sLogPath; - bool bReadPathRegistry = CVRPathRegistry::GetPaths( &sRuntimePath, &sConfigPath, &sLogPath, NULL, NULL ); + bool bReadPathRegistry = CVRPathRegistry_Public::GetPaths( &sRuntimePath, &sConfigPath, &sLogPath, NULL, NULL ); if ( !bReadPathRegistry ) { return nullptr; diff --git a/src/vrcommon/dirtools_public.cpp b/src/vrcommon/dirtools_public.cpp index 287832ab..e5cfc02e 100644 --- a/src/vrcommon/dirtools_public.cpp +++ b/src/vrcommon/dirtools_public.cpp @@ -1,9 +1,10 @@ //========= Copyright Valve Corporation ============// -#include "dirtools.h" -#include "strtools.h" -#include "pathtools.h" +#include "dirtools_public.h" +#include "strtools_public.h" +#include "pathtools_public.h" #include +#include #ifdef _WIN32 #include "windows.h" diff --git a/src/vrcommon/dirtools.h b/src/vrcommon/dirtools_public.h similarity index 100% rename from src/vrcommon/dirtools.h rename to src/vrcommon/dirtools_public.h diff --git a/src/vrcommon/envvartools_public.cpp b/src/vrcommon/envvartools_public.cpp index 231dee45..bb050d68 100644 --- a/src/vrcommon/envvartools_public.cpp +++ b/src/vrcommon/envvartools_public.cpp @@ -1,5 +1,5 @@ //========= Copyright Valve Corporation ============// -#include "envvartools.h" +#include "envvartools_public.h" #include #if defined(_WIN32) diff --git a/src/vrcommon/envvartools.h b/src/vrcommon/envvartools_public.h similarity index 100% rename from src/vrcommon/envvartools.h rename to src/vrcommon/envvartools_public.h diff --git a/src/vrcommon/hmderrors_public.cpp b/src/vrcommon/hmderrors_public.cpp index f2409fe4..5d9ecbcb 100644 --- a/src/vrcommon/hmderrors_public.cpp +++ b/src/vrcommon/hmderrors_public.cpp @@ -1,5 +1,6 @@ //========= Copyright Valve Corporation ============// -#include "hmderrors.h" +#include "openvr.h" +#include "hmderrors_public.h" #include #include diff --git a/src/vrcommon/hmderrors.h b/src/vrcommon/hmderrors_public.h similarity index 90% rename from src/vrcommon/hmderrors.h rename to src/vrcommon/hmderrors_public.h index 4bce5e34..ccd6c8a9 100644 --- a/src/vrcommon/hmderrors.h +++ b/src/vrcommon/hmderrors_public.h @@ -1,7 +1,5 @@ //========= Copyright Valve Corporation ============// #pragma once -#include "openvr.h" - const char *GetEnglishStringForHmdError( vr::EVRInitError eError ); const char *GetIDForVRInitError( vr::EVRInitError eError ); diff --git a/src/vrcommon/pathtools_public.cpp b/src/vrcommon/pathtools_public.cpp index f132c2e1..6413c343 100644 --- a/src/vrcommon/pathtools_public.cpp +++ b/src/vrcommon/pathtools_public.cpp @@ -1,6 +1,6 @@ //========= Copyright Valve Corporation ============// -#include "strtools.h" -#include "pathtools.h" +#include "strtools_public.h" +#include "pathtools_public.h" #if defined( _WIN32) #include @@ -14,6 +14,7 @@ #include #include #include +#include #endif #if defined OSX #include @@ -667,7 +668,7 @@ std::string Path_ReadTextFile( const std::string &strFilename ) return ""; // convert CRLF -> LF - int outsize = 1; + size_t outsize = 1; for (int i=1; i < size; i++) { if (buf[i] == '\n' && buf[i-1] == '\r') // CRLF @@ -676,7 +677,7 @@ std::string Path_ReadTextFile( const std::string &strFilename ) buf[outsize++] = buf[i]; // just copy } - std::string ret((char *)buf, (char *)(buf + outsize)); + std::string ret((char *)buf, outsize); delete[] buf; return ret; } diff --git a/src/vrcommon/pathtools.h b/src/vrcommon/pathtools_public.h similarity index 100% rename from src/vrcommon/pathtools.h rename to src/vrcommon/pathtools_public.h diff --git a/src/vrcommon/sharedlibtools_public.cpp b/src/vrcommon/sharedlibtools_public.cpp index 99eb1505..9c0661ef 100644 --- a/src/vrcommon/sharedlibtools_public.cpp +++ b/src/vrcommon/sharedlibtools_public.cpp @@ -1,5 +1,5 @@ //========= Copyright Valve Corporation ============// -#include "sharedlibtools.h" +#include "sharedlibtools_public.h" #include #if defined(_WIN32) diff --git a/src/vrcommon/sharedlibtools.h b/src/vrcommon/sharedlibtools_public.h similarity index 100% rename from src/vrcommon/sharedlibtools.h rename to src/vrcommon/sharedlibtools_public.h diff --git a/src/vrcommon/strtools_public.cpp b/src/vrcommon/strtools_public.cpp index 6166db48..9ab60d90 100644 --- a/src/vrcommon/strtools_public.cpp +++ b/src/vrcommon/strtools_public.cpp @@ -1,5 +1,5 @@ //========= Copyright Valve Corporation ============// -#include "strtools.h" +#include "strtools_public.h" #include #include #include diff --git a/src/vrcommon/strtools.h b/src/vrcommon/strtools_public.h similarity index 100% rename from src/vrcommon/strtools.h rename to src/vrcommon/strtools_public.h diff --git a/src/vrcommon/vrpathregistry_public.cpp b/src/vrcommon/vrpathregistry_public.cpp index 5f171fa7..cf61c866 100644 --- a/src/vrcommon/vrpathregistry_public.cpp +++ b/src/vrcommon/vrpathregistry_public.cpp @@ -1,11 +1,11 @@ //========= Copyright Valve Corporation ============// -#include "vrpathregistry.h" +#include "vrpathregistry_public.h" #include "json/json.h" -#include "pathtools.h" -#include "envvartools.h" -#include "strtools.h" -#include "dirtools.h" +#include "pathtools_public.h" +#include "envvartools_public.h" +#include "strtools_public.h" +#include "dirtools_public.h" #if defined( WIN32 ) #include @@ -95,11 +95,10 @@ static std::string GetAppSettingsPath() } - // --------------------------------------------------------------------------- // Purpose: Constructor // --------------------------------------------------------------------------- -CVRPathRegistry::CVRPathRegistry() +CVRPathRegistry_Public::CVRPathRegistry_Public() { } @@ -107,7 +106,7 @@ CVRPathRegistry::CVRPathRegistry() // --------------------------------------------------------------------------- // Purpose: Computes the registry filename // --------------------------------------------------------------------------- -std::string CVRPathRegistry::GetOpenVRConfigPath() +std::string CVRPathRegistry_Public::GetOpenVRConfigPath() { std::string sConfigPath = GetAppSettingsPath(); if( sConfigPath.empty() ) @@ -129,7 +128,7 @@ std::string CVRPathRegistry::GetOpenVRConfigPath() //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -std::string CVRPathRegistry::GetVRPathRegistryFilename() +std::string CVRPathRegistry_Public::GetVRPathRegistryFilename() { std::string sPath = GetOpenVRConfigPath(); if ( sPath.empty() ) @@ -188,7 +187,7 @@ static void StringListToJson( const std::vector< std::string > & vecHistory, Jso //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -bool CVRPathRegistry::ToJsonString( std::string &sJsonString ) +bool CVRPathRegistry_Public::ToJsonString( std::string &sJsonString ) { std::string sRegPath = GetVRPathRegistryFilename(); if( sRegPath.empty() ) @@ -207,7 +206,7 @@ bool CVRPathRegistry::ToJsonString( std::string &sJsonString ) // --------------------------------------------------------------------------- // Purpose: Loads the config file from its well known location // --------------------------------------------------------------------------- -bool CVRPathRegistry::BLoadFromFile() +bool CVRPathRegistry_Public::BLoadFromFile() { std::string sRegPath = GetVRPathRegistryFilename(); if( sRegPath.empty() ) @@ -247,7 +246,7 @@ bool CVRPathRegistry::BLoadFromFile() // --------------------------------------------------------------------------- // Purpose: Saves the config file to its well known location // --------------------------------------------------------------------------- -bool CVRPathRegistry::BSaveToFile() const +bool CVRPathRegistry_Public::BSaveToFile() const { #if defined( DASHBOARD_BUILD_MODE ) return false; @@ -257,6 +256,10 @@ bool CVRPathRegistry::BSaveToFile() const return false; Json::Value root; + + root[ "version" ] = 1; + root[ "jsonid" ] = "vrpathreg"; + StringListToJson( m_vecRuntimePath, root, "runtime" ); StringListToJson( m_vecConfigPath, root, "config" ); StringListToJson( m_vecLogPath, root, "log" ); @@ -287,7 +290,7 @@ bool CVRPathRegistry::BSaveToFile() const // --------------------------------------------------------------------------- // Purpose: Returns the current runtime path or NULL if no path is configured. // --------------------------------------------------------------------------- -std::string CVRPathRegistry::GetRuntimePath() const +std::string CVRPathRegistry_Public::GetRuntimePath() const { if( m_vecRuntimePath.empty() ) return ""; @@ -299,7 +302,7 @@ std::string CVRPathRegistry::GetRuntimePath() const // --------------------------------------------------------------------------- // Purpose: Returns the current config path or NULL if no path is configured. // --------------------------------------------------------------------------- -std::string CVRPathRegistry::GetConfigPath() const +std::string CVRPathRegistry_Public::GetConfigPath() const { if( m_vecConfigPath.empty() ) return ""; @@ -311,7 +314,7 @@ std::string CVRPathRegistry::GetConfigPath() const // --------------------------------------------------------------------------- // Purpose: Returns the current log path or NULL if no path is configured. // --------------------------------------------------------------------------- -std::string CVRPathRegistry::GetLogPath() const +std::string CVRPathRegistry_Public::GetLogPath() const { if( m_vecLogPath.empty() ) return ""; @@ -325,9 +328,9 @@ std::string CVRPathRegistry::GetLogPath() const // Purpose: Returns paths using the path registry and the provided override // values. Pass NULL for any paths you don't care about. // --------------------------------------------------------------------------- -bool CVRPathRegistry::GetPaths( std::string *psRuntimePath, std::string *psConfigPath, std::string *psLogPath, const char *pchConfigPathOverride, const char *pchLogPathOverride, std::vector *pvecExternalDrivers ) +bool CVRPathRegistry_Public::GetPaths( std::string *psRuntimePath, std::string *psConfigPath, std::string *psLogPath, const char *pchConfigPathOverride, const char *pchLogPathOverride, std::vector *pvecExternalDrivers ) { - CVRPathRegistry pathReg; + CVRPathRegistry_Public pathReg; bool bLoadedRegistry = pathReg.BLoadFromFile(); int nCountEnvironmentVariables = 0; diff --git a/src/vrcommon/vrpathregistry.h b/src/vrcommon/vrpathregistry_public.h similarity index 95% rename from src/vrcommon/vrpathregistry.h rename to src/vrcommon/vrpathregistry_public.h index 80ebeb76..4838a107 100644 --- a/src/vrcommon/vrpathregistry.h +++ b/src/vrcommon/vrpathregistry_public.h @@ -9,14 +9,14 @@ static const char *k_pchRuntimeOverrideVar = "VR_OVERRIDE"; static const char *k_pchConfigOverrideVar = "VR_CONFIG_PATH"; static const char *k_pchLogOverrideVar = "VR_LOG_PATH"; -class CVRPathRegistry +class CVRPathRegistry_Public { public: static std::string GetVRPathRegistryFilename(); static std::string GetOpenVRConfigPath(); public: - CVRPathRegistry(); + CVRPathRegistry_Public(); /** Returns paths using the path registry and the provided override values. Pass NULL for any paths you don't care about. * Returns false if the path registry could not be read. Valid paths might still be returned based on environment variables. */ @@ -32,8 +32,7 @@ class CVRPathRegistry std::string GetConfigPath() const; std::string GetLogPath() const; - -private: +protected: typedef std::vector< std::string > StringVector_t; // index 0 is the current setting