## IServerTrackedDeviceProvider

An `IServerTrackedDeviceProvider` is an interface that is implemented by a driver and its methods are called by the
runtime when the state of the runtime changes. It **must** be a global, single instance and exist for the duration
of the runtime session.

An `IServerTrackedDeviceProvider` **can** interact
with [IVRServerDriverHost](#IVRServerDriverHost), an interface
implemented by the runtime that provides useful methods to retrieve and update state from the runtime.

`IServerTrackedDeviceProvider` **does not** implement any devices itself, but **should**
initialize a [ITrackedDeviceServerDriver](#ITrackedDeviceServerDriver) for each device it wants to add to the
runtime.

See [IVRServerDriverHost](#IVRServerDriverHost) for how to add a device to the runtime.

<br/>

```c++
virtual EVRInitError Init( IVRDriverContext *pDriverContext ) = 0;
```

`Init` is called before any other methods of the class are called. `Init` **may** choose to initialize device drivers,
and **must** return `VRInitError_None` if the call is successful.

Returning anything else than `VRInitError_None` **will** cause the driver and shared library to be unloaded
from `vrserver.exe`.

The implementation of `IServerTrackedDeviceProvider` **should** keep resource usage to a minimum before `Init` is
called.

* `IVRDriverContext *pDriverContext` - Contains pointers to interfaces implemented by the runtime. The
  macro `VR_INIT_SERVER_DRIVER_CONTEXT` provided in the OpenVR API **can** be used to initialize this context.

The implementation of `IServerTrackedDeviceProvider` **must not** call any methods in the runtime (such as
in [IVRServerDriverHost](#IVRServerDriverHost)) until `Init` has been called and the server driver context has been
initialized. See example at the end of the section.

<br/>

```c++
virtual void Cleanup() = 0;
```

`Cleanup` is called right before the driver is unloaded.

`Cleanup` **should** release any resources
that `IServerTrackedDeviceProvider` or child `ITrackedDeviceServerDriver` have acquired throughout the session.

<br/>

```c++
virtual const char * const *GetInterfaceVersions() = 0;
```

`GetInterfaceVersions` **must** return a pointer to an array of strings that represent the versions of interfaces used
in this driver.

The helper variable `k_InterfaceVersions` in the OpenVR API **should** be returned directly from this method.
This variable contains versions of the interfaces you are compiling your driver against.

    IVRSettings_Version
    ITrackedDeviceServerDriver_Version
    IVRDisplayComponent_Version
    IVRDriverDirectModeComponent_Version
    IVRCameraComponent_Version
    IServerTrackedDeviceProvider_Version
    IVRWatchdogProvider_Version
    IVRVirtualDisplay_Version
    IVRDriverManager_Version
    IVRResources_Version
    IVRCompositorPluginProvider_Version

<br/>

```c++
virtual void RunFrame() = 0;
```

`RunFrame` is called *directly* in the main loop of `vrserver.exe`. As a result, it **should not** perform calls that
might block. It is called on every frame.

It is strongly recommended for a driver to use their own thread for performing work that might need to be done at a
regular interval.

A driver **should** (and perhaps only) poll for events using `RunFrame`. See [events](#events).

<br/>

```c++
virtual bool ShouldBlockStandbyMode() = 0;
```

`ShouldBlockStandbyMode` is deprecated, and will never be called in newer versions of SteamVR. Drivers **must**
implement
this function (because it is pure virtual), but the return value has no effect on behavior.

<br/>

```c++
virtual void EnterStandby() = 0;
```

`EnterStandby` is called when the whole system is entering standby mode.

This is after a user-configured time after which the system becomes inactive (HMD not being worn, controllers off or not
used, etc.).

The driver **should** switch itself into whatever sort of low-power state it has.

<br/>

```c++
virtual void LeaveStandby() = 0;
```

`LeaveStandby` is called when the whole system is leaving Standby mode. The driver **should** switch itself back to full
operation.

### Example

```c++
class MyDeviceProvider : public IServerTrackedDeviceProvider
{
public:
    virtual EVRInitError Init( vr::IVRDriverContext *pDriverContext )
    {
        VR_INIT_SERVER_DRIVER_CONTEXT( pDriverContext );

        m_pMyHmdDevice = new MyHmdDeviceDriver();
        m_pMyControllerDevice = new MyControllerDriver();

        //see IVRServerDriverHost - notify the runtime that our driver wishes to add two devices to the session
        vr::VRServerDriverHost()->TrackedDeviceAdded( "MyHMD1", vr::TrackedDeviceClass_HMD, m_pMyHmdDevice );
        vr::VRServerDriverHost()->TrackedDeviceAdded( "MyController1", vr::TrackedDeviceClass_Controller, m_pMyControllerDevice );

        return VRInitError_None;
    }

    virtual void Cleanup() 
    {
        delete m_pMyHmdDevice;
        m_pMyHmdDevice = NULL;
        delete m_pMyControllerDevice;
        m_pMyControllerDevice = NULL;
    }

    virtual const char * const *GetInterfaceVersions() { return vr::k_InterfaceVersions; }
    virtual void MyRunFrame() {}
    virtual bool ShouldBlockStandbyMode()  { return false; } //never called.
    virtual void EnterStandby()  {}
    virtual void LeaveStandby()  {}

private:
    MyHmdDeviceDriver *m_pMyHmdDevice = nullptr;
    MyControllerDriver *m_pMyControllerDevice = nullptr;
};
```

## ITrackedDeviceServerDriver

`ITrackedDeviceServerDriver` represents a singular device in the *driver*.

<br/>

```c++
virtual EVRInitError Activate( uint32_t unObjectId ) = 0;
```

`Activate` is called after the driver makes a call to `IVRServerDriverHost::TrackedDeviceAdded`.

Resource usage should be kept to a minimum until this method has been called by the runtime.

Devices **should not** make any calls to the runtime until `Activate()` has been called.

* `uint32_t unObjectId` - The device's id. This is unique across SteamVR and is used to get and update various state and
  properties relating to the device, such as [poses](#Poses) and [properties](#device-properties).

<br/>

```c++
virtual void Deactivate() = 0;
```

`Deactivate` is called when the device is needed to be deactivated, either from SteamVR closing or the system switching
between HMDs, if this device class represents the currently active HMD.

The device  **should** free whatever resources it has acquired when this method is called by the runtime.

Any valid calls the device can make to various runtime-implemented interfaces are guaranteed to be valid
until `Deactivate` is called. The device **must not** call any of these interfaces after the device has returned from
this method, as they are not guaranteed to be valid past this point.

`IServerTrackedDeviceProvider::Cleanup` **will** be called after this method has been called on each device currently
added to the runtime.

<br/>

```c++
virtual void EnterStandby() = 0;
```

`EnterStandby` is called when the device should enter standby mode. This occurs when the user requests the device to
be turned off, when the system is entering standby mode, or when the system shuts down.

The device should switch into a lower power state or turn off.

<br/>

```c++
virtual void *GetComponent( const char *pchComponentNameAndVersion ) = 0;
```

`GetComponent` is called on activation and the device **should** return whatever components it has for device-specific
functionality. If the component requested does not exist on the device, the device **must** return NULL from this
method.

* `const char *pchComponentNameAndVersion` - The component name and version to match against. The possible options are
  kept as strings in the OpenVR header. The name and versions of the interfaces you are currently targeting (the ones
  you are implementing) and can return from this method are listed below:
    * `IVRDisplayComponent` - A generic display component on a single tracked device. If drivers do not need to access
      the display directly or are not a virtual display, use this.
    * `IVRDriverDirectModeComponent` - This component is used for drivers that implement direct mode entirely on their
      own without allowing the VR Compositor to own the window/device.
    * `IVRCameraComponent` - Represents camera one or more cameras on the device

See [Device Components](#Device-Components) for more information on device components.

```c++
virtual void *GetComponent(const char *pchComponentNameAndVersion) override {
  if (!_stricmp(pchComponentNameAndVersion, vr::IVRVirtualDisplay_Version)) {
    return &m_myVirtualDisplay;
  }
        
  if (!_stricmp(pchComponentNameAndVersion, vr::IVRCameraComponent_Version)) {
    return &m_myCameraComponent;
  }
  
  return nullptr;
}
```

<br/>

```c++
virtual void DebugRequest( const char *pchRequest, char *pchResponseBuffer, uint32_t unResponseBufferSize ) = 0;
```

`DebugRequest` is called when the application requests a debug action from the device. The device **should** respond to
the
request in the buffer provided.

What is sent from the application to the device is up to the application and device to handle, as is the response.

* `const char *pchRequest` - The request string. The device **should** respond to the request in the buffer provided.
* `char *pchResponseBuffer` - The buffer to write the response to.
* `uint32_t unResponseBufferSize` - The size of the buffer provided.

<br/>

```c++
virtual DriverPose_t GetPose() = 0;
```

This method is deprecated and is not called by the runtime. The device **must** implement this method, but the return
value has no effect on behavior.

### Device Components

HMDs have a variety of different ways of interacting with the runtime. They may choose to have their own compositor, let
the runtime submit frames directly to the device on their behalf, or need ways to access the final composited
backbuffer.

OpenVR provides a set of display "component" interfaces that can be used to implement these different behaviors.

The options are:

* `IVRDisplayComponent` - Recommended. The driver will provide information about the display to the runtime on
  initialization, such as distortion and the runtime will then own the display and submit the frames directly to it.
    * This takes advantage of "direct mode" (not to be confused with `IVRDriverDirectModeComponent`) which allows the
      runtime to skip the windowing system level and work directly on the display level.
* `IVRDriverDirectModeComponent` - Only recommended if the driver is doing its own compositing, or if it is impossible
  to provide distortion data. Image texture handoff in driver direct mode happens before compositing and allows the
  driver to own the display.
* `IVRVirtualDisplay` - Only recommended if you can provide your distortion data, but for some reason cannot provide the
  output, such as transmitting the frames wirelessly. Provides the driver with a final composited backbuffer intended
  for the headset's display.
* `IVRCameraComponent` - The device implements a camera.

See [ITrackedDeviceServerDriver](#ITrackedDeviceServerDriver) for more information and how to implement
the `GetComponent` method.

#### IVRDisplayComponent

`IVRDisplayComponent` is a component that represents a display on a device which the runtime calls to get information
about the display.

The runtime will then submit composited frames to the display by directly interacting with it.

<br/>

```c++
virtual void GetWindowBounds( int32_t *pnX, int32_t *pnY, uint32_t *pnWidth, uint32_t *pnHeight ) = 0;
```

`GetWindowBounds` is called by the runtime when the VR display is in extended mode (i.e. a part of the desktop), which
SteamVR determines by calling `IsDisplayOnDesktop`. The function **should** provide the size and position that the
window needs to be on the desktop, such that it fills the extended display.

* `int32_t *pnX` - The number of pixels from the left of the window to the place to where you want rendered.
* `int32_t *pnY` - The number of pixels from the top of the window to the place to where you want rendered.
* `uint32_t *pnWidth` - The width of the window in pixels.
* `uint32_t *pnHeight` - The height of the window in pixels.

<br/>

```c++
virtual bool IsDisplayOnDesktop() = 0;
```

`IsDisplayOnDesktop` is called by the runtime to determine if the window is extending the desktop.

HMDs **should not** use this extended mode (returning `true` from this function) and instead make a direct-mode HMD.
See [IVRDriverDirectModeComponent](#IVRDriverDirectModeComponent) for more information on direct-mode HMDs.

<br/>

```c++
virtual bool IsDisplayRealDisplay() = 0;
```

`IsDisplayRealDisplay` is called by the runtime to determine if the display is a real display.

Virtual devices **should** return `false` here, to prevent the runtime trying to directly interact with a display that
doesn't actually exist.

<br/>

```c++
virtual void GetRecommendedRenderTargetSize( uint32_t *pnWidth, uint32_t *pnHeight ) = 0;
```

`GetRecommendedRenderTargetSize` is called by the runtime to get the suggested size for the intermediate render target
that the distortion pulls from.

The values the driver specifies in this method set the value of the resolution in SteamVR settings (to 100%). The values
the driver specifies in this method are not guaranteed to be used, if the user has set a different resolution in SteamVR
settings, or the application picks a different resolution.

The resolution you specify **should** result in 1:1 pixels with the display at the center of projection after the
distortion function is applied to maximise the detail in the center of the display, where the user looks the most.

* `uint32_t *pnWidth` - The width of the render target in pixels.
* `uint32_t *pnHeight` - The height of the render target in pixels.

```c++ 
virtual void GetEyeOutputViewport( EVREye eEye, uint32_t *pnX, uint32_t *pnY, uint32_t *pnWidth, uint32_t *pnHeight ) = 0;
```

`GetEyeOutputViewport` is called by the runtime to get the viewport in the frame buffer to draw the output of the
distortion into.

* `EVREye eEye` - The eye to get the viewport for. The possible options are:
    * `Eye_Left` - The left eye.
    * `Eye_Right` - The right eye.
* `uint32_t *pnX` - The number of pixels from the left of the window to left edge of the viewport. Typically, each eye
  will have half of the window width as its viewport.
* `uint32_t *pnY` - The number of pixels from the top of the window to top edge of the viewport.
* `uint32_t *pnWidth` - The width of the viewport in pixels.
* `uint32_t *pnHeight` - The height of the viewport in pixels.

```c++
virtual void GetEyeOutputViewport( EVREye eEye, uint32_t *pnX, uint32_t *pnY, uint32_t *pnWidth, uint32_t *pnHeight ) 
{
    *pnY = 0;
    *pnWidth = m_nWindowWidth / 2;
    *pnHeight = m_nWindowHeight;

    if ( eEye == Eye_Left )
    {
        *pnX = 0;
    }
    else
    {
        *pnX = m_nWindowWidth / 2;
    }
}
```

<br/>

```c++
virtual void GetProjectionRaw( EVREye eEye, float *pfLeft, float *pfRight, float *pfTop, float *pfBottom ) = 0;
```

`GetProjectionRaw` is called by the runtime to get the raw values from the distortion that are used to build your own
projection matrix in case your application is doing something fancy like infinite Z.

The values represent the tangents of the half-angles from the center view axis.

Note that “bottom” and “top” are backwards. “Bottom” is the tan angle from the center of projection to the top (+Y) edge
of the display, and “top” is the center of projection to the bottom (-Y) edge of the display.

* `EVREye eEye` - The eye to get the projection for. The possible options are:
    * `Eye_Left` - The left eye.
    * `Eye_Right` - The right eye.
* `float *pfLeft` - The tangent of the angle between the center view axis and the left clipping plane (-X).
* `float *pfRight` - The tangent of the angle between the center view axis and the right clipping plane (+X).
* `float *pfTop` - The tangent of the angle between the center view axis and the **bottom** clipping plane (-Y).
* `float *pfBottom` - The tangent of the angle between the center view axis and the **top** clipping plane (+Y).

For example, an HMD with a 90 degree field of view would return the following values:

```c++
void GetProjectionRaw( EVREye eEye, float *pfLeft, float *pfRight, float *pfTop, float *pfBottom ) 
{
    // 45 degrees is the angle between the forward vector and each side
    // so the values would be the tangent of 45 degrees (which is 1 or tan(45))
    *pfLeft = -1.0f;
    *pfRight = 1.0f;
    *pfTop = -1.0f;
    *pfBottom = 1.0f;
}
```

<br/>

```c++
virtual DistortionCoordinates_t ComputeDistortion( EVREye eEye, float fU, float fV ) = 0;
```

`ComputeDistortion` is called by the runtime and is used to generate the post-distortion UV coordinates for each color
channel. UVs range from 0 to 1 and go from 0,0 in the upper left corner of the source render target to 1,1 in the lower
right and covers a single eye.

* `EVREye eEye` - The eye to get the distortion for. The possible options are:
    * `Eye_Left` - The left eye.
    * `Eye_Right` - The right eye.
* `float fU` - The current U coordinate.
* `float fV` - The current V coordinate.

```c++
virtual bool ComputeInverseDistortion( HmdVector2_t *pResult, EVREye eEye, uint32_t unChannel, float fU, float fV ) = 0;
```
`ComputeInverseDistortion` is called by the runtime to get the result of the inverse distortion function for the specified eye,
channel and uv.

Drivers **may** return false from this method to indicate that the runtime should infer an estimate from
the result returned by `IVRDisplayComponent::ComputeDistortion`.

Returning true from method indicates to the runtime that it should not try to estimate the inverse, and instead use the
values provided by the driver.

* `HmdVector2_t *pResult` - Driver should write into this with the result for the specified UV.
* `EVREye eEye` - The eye to get the distortion for. The possible options are:
    * `Eye_Left` - The left eye.
    * `Eye_Right` - The right eye.
* `uint32_t unChannel` - Which channel is requested. 0 for red, 1 for blue, 2 for green.
* `float fU` - The current U coordinate.
* `float fV` - The current V coordinate.

#### IVRDriverDirectModeComponent

`IVRDriverDirectModeComponent` is used for drivers that implement direct mode entirely on their own without allowing the
VR Compositor to own the window, and for a driver's own compositor to interface with the runtime.

This is useful for drivers that might want to implement their own compositor.

Drivers **should** implement `IVRDisplayComponent` and let the compositor own the device, unless they need to have this
control over the display.

<br />

```c++
virtual void CreateSwapTextureSet( uint32_t unPid, const SwapTextureSetDesc_t *pSwapTextureSetDesc, SwapTextureSet_t *pOutSwapTextureSet ) {}
```

`CreateSwapTextureSet` is called to allocate textures for applications to render into.

One of these per eye will be passed back to `SubmitLayer` for each frame.

* `uint32_t unPid` - pid of the client process creating the texture.
* `const SwapTextureSetDesc_t *pSwapTextureSetDesc` - description of the texture.
    * `uint32_t nWidth` - Width of the texture.
    * `uint32_t nHeight` - Height of the texture.
    * `uint32_t nFormat` - Format of the texture. In `DXGI_FORMAT`.
    * `uint32_t nSampleCount` - Number of samples per pixel.
* `SwapTextureSet_t *pOutSwapTextureSet` - Your allocated textures
    * `vr::SharedTextureHandle_t rSharedTextureHandles[ 3 ]` - _Shared_ handles to the textures
    * `uint32_t VRSwapTextureFlag` - Flags for the texture.
        * `VRSwapTextureFlag_Shared_NTHandle` - Specify that the shared texture resource was created with
          the `SHARED_NTHANDLE` option (Windows)

```c++
void CreateSwapTextureSet( uint32_t unPid, const SwapTextureSetDesc_t *pSwapTextureSetDesc, SwapTextureSet_t *pOutSwapTextureSet ) {
    D3D11_TEXTURE2D_DESC desc = {};
    desc.ArraySize = 1;
    desc.Width = pSwapTextureSetDesc->unWidth;
    desc.Height = pSwapTextureSetDesc->unHeight;
    desc.MipLevels = 1;
    desc.SampleDesc.Count = 1;
    desc.SampleDesc.Quality = 0;
    desc.Format = (DXGI_FORMAT)pSwapTextureSetDesc->unFormat;
    desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
    desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
    
    for(int i = 0; i < 3; i++) {
        HRESULT hresult = myD3DDevice->CreateTexture2D(&desc, nullptr, &pOutSwapTextureSet->rSharedTextureHandles[i]);
        
        IDXGIResource* pResource = nullptr;
        hresult = pOutSwapTextureSet->rSharedTextureHandles[i]->QueryInterface(__uuidof(IDXGIResource), (void**)&pResource);
        
        HANDLE hSharedHandle = nullptr;
        hresult = pResource->GetSharedHandle(&hSharedHandle);
        pResource->Release();
        
        pOutSwapTextureSet->rSharedTextureHandles[i] = (vr::SharedTextureHandle_t)hSharedHandle;
    }
}
```

<br />

```c++
virtual void DestroySwapTextureSet( vr::SharedTextureHandle_t sharedTextureHandle ) {};
```

`DestroySwapTextureSet` should destroy textures created using CreateSwapTextureSet.

Only one of the set's handles needs to be used to destroy the entire set.

* `vr::SharedTextureHandle_t sharedTextureHandle` - Handle to destroy.

<br />

```c++
virtual void DestroyAllSwapTextureSets( uint32_t unPid ) {}
```

`DestroyAllSwapTextureSets` should destroy all textures for the given process.

* `uint32_t unPid` - pid of the process to destroy the textures from.

<br />

```c++
virtual void GetNextSwapTextureSetIndex( vr::SharedTextureHandle_t sharedTextureHandles[ 2 ], uint32_t( *pIndices )[ 2 ] ) {}
```

`GetNextSwapTextureSetIndex` is called after `Present` returns, and is used to get the next index to use for rendering.

* `vr::SharedTextureHandle_t sharedTextureHandles[ 2 ]` - handles to the textures of each eye. Textures **must** have
  been created using `CreateSwapTextureSet`.
* `uint32_t( *pIndices )[ 2 ]` - Your result for the index to use for each eye.

<br />

```c++
virtual void SubmitLayer( const SubmitLayerPerEye_t( &perEye )[ 2 ] ) {}
```

`SubmitLayer` is called once per layer to draw for this frame.

* `const SubmitLayerPerEye_t( &perEye )[ 2 ]` - The layer to draw per eye.
    * `vr::SharedTextureHandle_t sharedTextureHandle` - Handle to the texture to draw. Textures **must** have been
      created using `CreateSwapTextureSet`.
    * `vr::SharedTextureHandle_t hDepthTexture` - Depth texture. Not always provided.
    * `vr::VRTextureBounds_t bounds` - Valid region and depth of provided texture.
    * `vr::HmdMatrix44_t mProjection` - The projection matrix used to render the depth buffer.
    * `vr::HmdMatrix34_t mHmdPose` - Hmd pose that was used to render this layer.

<br />

```c++
virtual void Present( vr::SharedTextureHandle_t syncTexture ) {}
```

`Present` is called to submit the queued layers for display.

```c++
void Present(vr::SharedTextureHandle_t syncTexture) {
  // Open sync texture only when it changes.
  if (m_syncTexture != syncTexture) {
      m_syncTexture = syncTexture;
      SAFE_RELEASE( m_pSyncTexture );
      if (m_syncTexture) {
          m_pD3D11Device->OpenSharedResource( ( HANDLE )m_syncTexture, __uuidof( ID3D11Texture2D ), ( void ** )&m_pSyncTexture );
      }
  }
  
  IDXGIKeyedMutex *pSyncMutex = NULL;
  if (m_pSyncTexture != NULL && SUCCEEDED(m_pSyncTexture->QueryInterface(__uuidof(IDXGIKeyedMutex), (void **)&pSyncMutex))) {
      pSyncMutex->AcquireSync(0, 10);
  }

  //...
  
  if (pSyncMutex) {
      pSyncMutex->ReleaseSync( 0 );
      pSyncMutex->Release();
  }
}
```

<br />

```c++
virtual void PostPresent( const Throttling_t *pThrottling ) {}
```

`PostPresent` is an optional method for a driver to implement, and is called after `Present` returns and after the
compositor is aware the driver has acquired the sync texture to allow the driver to take more time until vsync after
they've successfully acquired the sync texture in `Present`.

* `const Throttling_t *pThrottling` - Throttling information set by the user
    * `uint32_t nFramesToThrottle` - Set from the settings key `k_pch_SteamVR_FramesToThrottle_Int32` under an app key.
    * `uint32_t  nAdditionalFramesToPredict` - Set from the settings key `k_pch_SteamVR_AdditionalFramesToPredict_Int32`
      under an app key.

<br/>

```c++
virtual void GetFrameTiming( DriverDirectMode_FrameTiming *pFrameTiming ) {}
```

`GetFrameTiming` is an optional method for a driver to implement and is called to get additional frame timing stats from
the driver.

* `DriverDirectMode_FrameTiming *pFrameTiming` - Frame timing data provided by the driver
    * `uint32_t nSize` - Size of the struct
    * `uint32_t nNumFramePresents` - Number of times the frame was presented
    * `uint32_t nNumMisPresented` - Number of times the frame was presented on a vsync other than it was predicted to
    * `uint32_t nNumDroppedFrames` - Number of times previous frame was scanned out (i.e. compositor missed vsync).
    * `uint32_t m_nReprojectionFlags` - Flags for reprojection information.
        * `VRCompositor_ReprojectionMotion_Enabled` - Motion smoothing is enabled in the UI for the currently running
          application
        * `VRCompositor_ReprojectionMotion_ForcedOn` - Motion smoothing is forced on in the UI for the currently running
          application
        * `VRCompositor_ReprojectionMotion_AppThrottled` - Application is requesting throttling
          via `ForceInterleavedReprojectionOn`.

#### IVRVirtualDisplay

Used for drivers that implement a virtual display and need to access the final composited backbuffer image without
transmitting to a real display, such as for transmitting wirelessly.

From the perspective of the runtime, the compositor is interfacing with a virtual, rather than actual, display. This
makes it a critical piece of the render pipeline, and drivers **must** get the timing correct in order to continue
providing a proper experience to the user.

As `IVRVirtualDisplay` is expected to be implemented as a _device component_, it **must** implement
a [ITrackedDeviceServerDriver](#itrackeddeviceserverdriver).

The following properties **must** be set for the device to have a virtual display component:

* It is added to the runtime as a `vr::TrackedDeviceClass_DisplayRedirect` device class. (see below).
* `redirectsDisplay` is set to `true` in [driver.vrdrivermanifest](#drivervrdrivermanifest).

```c++
  vr::VRServerDriverHost()->TrackedDeviceAdded("my_serial_ABC123", vr::TrackedDeviceClass_DisplayRedirect, &myVirtualDisplayDevice);
```

<br />

```c++
virtual void Present( const PresentInfo_t *pPresentInfo, uint32_t unPresentInfoSize ) = 0;
```

`Present` is called once per frame after all rendering has been submitted to the GPU and provides the final backbuffer
to display.

`Present` **should** avoid any blocking calls on any operations such as reading the texture, and instead queue these
commands to return as soon as possible. `WaitForPresent` is provided for calling the blocking operations.

* `const PresentInfo_t *pPresentInfo` - Contains information about backbuffer.
    * `SharedTextureHandle_t backbufferTextureHandle` - Handle to the backbuffer texture.
    * `EVSync vsync` - Vsync information
        * `VSync_None` - No vsync
        * `VSync_WaitRender` - Block following render work until vsync occurs.
        * `VSync_NoWaitRender` - Do not block following render work, allowing work to get started early.
    * `uint64_t nFrameId` - Frame ID of the current frame.
    * `double flVSyncTimeInSeconds` - Time in seconds when vsync occurred.
* `uint32_t unPresentInfoSize` - Size of the current `PresentInfo_t` struct.

<br />

```c++
virtual void WaitForPresent() = 0;
```

`WaitForPresent` is called to allow the driver to perform blocking calls on operations that might have been queued
in `Present`.

<br />

```c++
virtual bool GetTimeSinceLastVsync( float *pfSecondsSinceLastVsync, uint64_t *pulFrameCounter ) = 0;
```

`GetTimeSinceLastVsync` is called to provide timing data for synchronizing with the display.

`GetTimeSinceLastVsync` is called after `WaitForPresent` returns. It **should** return the time, in seconds, since the
last _virtual_ vsync event.

* `float *pfSecondsSinceLastVsync` - The time, in seconds, since the last _virtual_ vsync event. This is the offset from
  the physical device timing by the additional latency introduced by the virtual driver, specified by the driver in
  the `vr::Prop_SecondsFromVsyncToPhotons_Float` property.
* `uint64_t *pulFrameCounter` - Current frame count. This is a monotonically increasing value and **should** reflect the
  virtual vsync count, rather than the number of frames presented in order for the runtime to detect dropped frames.

<br />

See this repository for an example `IVRVirtualDisplay` implementation: https://github.com/ValveSoftware/virtual_display.