using System; using System.Runtime.InteropServices; using NvAPIWrapper.Native.Exceptions; using NvAPIWrapper.Native.General; using NvAPIWrapper.Native.Helpers; using NvAPIWrapper.Native.Helpers.Structures; using NvAPIWrapper.Native.Stereo; using NvAPIWrapper.Native.Stereo.Structures; namespace NvAPIWrapper.Native { /// /// Contains Stereo static functions /// // ReSharper disable once ClassTooBig public static class StereoApi { /// /// This API activates stereo for the device interface corresponding to the given stereo handle. /// Activating stereo is possible only if stereo was enabled previously in the registry. /// If stereo is not activated, then calls to functions that require that stereo is activated have no effect, /// and will return the appropriate error code. /// /// Stereo handle corresponding to the device interface. public static void ActivateStereo(StereoHandle handle) { var status = DelegateFactory.GetDelegate()( handle ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } } /// /// This API captures the current stereo image in JPEG stereo format with the given quality. /// Only the last capture call per flip will be effective. /// /// Stereo handle that corresponds to the device interface. /// Quality of the JPEG image to be captured. Integer value between 0 and 100. public static void CaptureJpegImage(StereoHandle handle, uint quality) { var status = DelegateFactory.GetDelegate()( handle, quality ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } } /// /// This API captures the current stereo image in PNG stereo format. /// Only the last capture call per flip will be effective. /// /// Stereo handle that corresponds to the device interface. public static void CapturePngImage(StereoHandle handle) { var status = DelegateFactory.GetDelegate()( handle ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } } /// /// Creates new configuration registry key for current application. /// If there is no configuration profile prior to the function call, /// this API tries to create a new configuration profile registry key /// for a given application and fill it with the default values. /// If an application already has a configuration profile registry key, the API does nothing. /// The name of the key is automatically set to the name of the executable that calls this function. /// Because of this, the executable should have a distinct and unique name. /// If the application is using only one version of DirectX, then the default profile type will be appropriate. /// If the application is using more than one version of DirectX from the same executable, /// it should use the appropriate profile type for each configuration profile. /// /// Type of profile the application wants to create. public static void CreateConfigurationProfileRegistryKey( StereoRegistryProfileType registryProfileType) { var status = DelegateFactory .GetDelegate()( registryProfileType ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } } /// /// This API creates a stereo handle that is used in subsequent calls related to a given device interface. /// This must be called before any other NvAPI_Stereo_ function for that handle. /// Multiple devices can be used at one time using multiple calls to this function (one per each device). /// HOW TO USE: After the Direct3D device is created, create the stereo handle. /// On call success: /// -# Use all other functions that have stereo handle as first parameter. /// -# After the device interface that corresponds to the the stereo handle is destroyed, /// the application should call NvAPI_DestroyStereoHandle() for that stereo handle. /// /// Pointer to IUnknown interface that is IDirect3DDevice9* in DX9, ID3D10Device*. /// Newly created stereo handle. // ReSharper disable once InconsistentNaming public static StereoHandle CreateHandleFromIUnknown(IntPtr d3dDevice) { var status = DelegateFactory.GetDelegate()( d3dDevice, out var stereoHandle ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } return stereoHandle; } // ReSharper disable once CommentTypo /// /// This API allows the user to create a mono or a stereo swap chain. /// NOTE: NvAPI_D3D1x_CreateSwapChain is a wrapper of the method IDXGIFactory::CreateSwapChain which /// additionally notifies the D3D driver of the mode in which the swap chain is to be /// created. /// /// /// Stereo handle that corresponds to the device interface. The device that will write 2D images to /// the swap chain. /// /// /// A pointer to the swap-chain description (DXGI_SWAP_CHAIN_DESC). This parameter /// cannot be NULL. /// /// The stereo mode fot the swap chain. /// A pointer to the swap chain created. public static IntPtr D3D1XCreateSwapChain( StereoHandle handle, IntPtr dxgiSwapChainDescription, StereoSwapChainMode swapChainMode) { var status = DelegateFactory.GetDelegate()( handle, dxgiSwapChainDescription, out var dxgiSwapChain, swapChainMode ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } return dxgiSwapChain; } /// /// This API allows the user to create a mono or a stereo swap chain. /// NOTE: NvAPI_D3D9_CreateSwapChain is a wrapper of the method IDirect3DDevice9::CreateAdditionalSwapChain which /// additionally notifies the D3D driver if the swap chain creation mode must be stereo or mono. /// /// Stereo handle that corresponds to the device interface. /// A pointer to the swap-chain description (DXGI). This parameter cannot be NULL. /// The stereo mode for the swap chain. /// A pointer to the swap chain created. public static IntPtr D3D9CreateSwapChain( StereoHandle handle, // ReSharper disable once InconsistentNaming IntPtr d3dPresentParameters, StereoSwapChainMode swapChainMode) { var status = DelegateFactory.GetDelegate()( handle, d3dPresentParameters, out var direct3DSwapChain9, swapChainMode ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } return direct3DSwapChain9; } /// /// This API deactivates stereo for the given device interface. /// If stereo is not activated, then calls to functions that require that stereo is activated have no effect, /// and will return the appropriate error code. /// /// Stereo handle that corresponds to the device interface. public static void DeactivateStereo(StereoHandle handle) { var status = DelegateFactory.GetDelegate()( handle ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } } /// /// This API decreases convergence for the given device interface (just like the Ctrl+F5 hot-key). /// /// Stereo handle that corresponds to the device interface. public static void DecreaseConvergence(StereoHandle handle) { var status = DelegateFactory.GetDelegate()( handle ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } } /// /// This API decreases separation for the given device interface (just like the Ctrl+F3 hot-key). /// /// Stereo handle that corresponds to the device interface. public static void DecreaseSeparation(StereoHandle handle) { var status = DelegateFactory.GetDelegate()( handle ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } } /// /// Removes configuration registry key for current application. /// If an application already has a configuration profile prior to this function call, /// the function attempts to remove the application's configuration profile registry key from the registry. /// If there is no configuration profile registry key prior to the function call, /// the function does nothing and does not report an error. /// /// Type of profile that the application wants to delete. public static void DeleteConfigurationProfileRegistryKey( StereoRegistryProfileType registryProfileType) { var status = DelegateFactory .GetDelegate()( registryProfileType ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } } /// /// This API removes the given value from the application's configuration profile registry key. /// If there is no such value, the function does nothing and does not report an error. /// /// The type of profile the application wants to access. /// ID of the value that is being deleted. public static void DeleteConfigurationProfileValue( StereoRegistryProfileType registryProfileType, StereoRegistryIdentification registryId) { var status = DelegateFactory.GetDelegate()( registryProfileType, registryId ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } } /// /// This API destroys the stereo handle created with one of the NvAPI_Stereo_CreateHandleFrom() functions. /// This should be called after the device corresponding to the handle has been destroyed. /// /// Stereo handle that is to be destroyed. public static void DestroyHandle(StereoHandle handle) { var status = DelegateFactory.GetDelegate()( handle ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } } /// /// This API disables stereo mode in the registry. /// Calls to this function affect the entire system. /// If stereo is not enabled, then calls to functions that require that stereo is enabled have no effect, /// and will return the appropriate error code. /// public static void DisableStereo() { var status = DelegateFactory.GetDelegate()(); if (status != Status.Ok) { throw new NVIDIAApiException(status); } } /// /// This APU enables stereo mode in the registry. /// Calls to this function affect the entire system. /// If stereo is not enabled, then calls to functions that require that stereo is enabled have no effect, /// and will return the appropriate error code. /// public static void EnableStereo() { var status = DelegateFactory.GetDelegate()(); if (status != Status.Ok) { throw new NVIDIAApiException(status); } } /// /// This API gets the current convergence value. /// /// Stereo handle that corresponds to the device interface. /// Current convergence value public static float GetConvergence(StereoHandle handle) { var status = DelegateFactory.GetDelegate()( handle, out var convergence ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } return convergence; } /// /// This API retrieves the current default stereo profile. /// /// Default stereo profile name. public static string GetDefaultProfile() { var stringCapacity = 256; var stringAddress = Marshal.AllocHGlobal(stringCapacity); try { var status = DelegateFactory.GetDelegate()( (uint) stringCapacity, stringAddress, out var stringSize ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } if (stringSize == 0) { return null; } return Marshal.PtrToStringAnsi(stringAddress, (int) stringSize); } finally { Marshal.FreeHGlobal(stringAddress); } } /// /// This API returns eye separation as a ratio of [between eye distance]/[physical screen width]. /// /// Stereo handle that corresponds to the device interface. /// Eye separation public static float GetEyeSeparation(StereoHandle handle) { var status = DelegateFactory.GetDelegate()( handle, out var eyeSeparation ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } return eyeSeparation; } /// /// This API gets the current frustum adjust mode value. /// /// Stereo handle that corresponds to the device interface. /// Current frustum value public static StereoFrustumAdjustMode GetFrustumAdjustMode(StereoHandle handle) { var status = DelegateFactory.GetDelegate()( handle, out var frustumAdjustMode ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } return frustumAdjustMode; } /// /// This API gets current separation value (in percents). /// /// Stereo handle that corresponds to the device interface. /// Current separation percentage public static float GetSeparation(StereoHandle handle) { var status = DelegateFactory.GetDelegate()( handle, out var separationPercentage ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } return separationPercentage; } /// /// This API checks what kind of stereo support is currently supported on a particular display. /// If the the display is prohibited from showing stereo (e.g. secondary in a multi-mon setup), we will /// return 0 for all stereo modes (full screen exclusive, automatic windowed, persistent windowed). /// Otherwise, we will check which stereo mode is supported. On 120Hz display, this will be what /// the user chooses in control panel. On HDMI 1.4 display, persistent windowed mode is always assumed to be /// supported. Note that this function does not check if the CURRENT RESOLUTION/REFRESH RATE can support /// stereo. For HDMI 1.4, it is the application's responsibility to change the resolution/refresh rate to one that is /// 3D compatible. For 120Hz, the driver will ALWAYS force 120Hz anyway. /// /// Monitor that app is going to run on /// An instance of structure. public static StereoCapabilitiesV1 GetStereoSupport(IntPtr monitorHandle) { var instance = typeof(StereoCapabilitiesV1).Instantiate(); using (var reference = ValueTypeReference.FromValueType(instance)) { var status = DelegateFactory.GetDelegate()( monitorHandle, reference ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } return reference.ToValueType(typeof(StereoCapabilitiesV1)); } } /// /// This API gets surface creation mode for this device interface. /// /// Stereo handle that corresponds to the device interface. /// The current creation mode for this device interface. public static StereoSurfaceCreateMode GetSurfaceCreationMode(StereoHandle handle) { var status = DelegateFactory.GetDelegate()( handle, out var surfaceCreateMode ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } return surfaceCreateMode; } /// /// This API increases convergence for given the device interface (just like the Ctrl+F6 hot-key). /// /// Stereo handle that corresponds to the device interface. public static void IncreaseConvergence(StereoHandle handle) { var status = DelegateFactory.GetDelegate()( handle ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } } /// /// This API increases separation for the given device interface (just like the Ctrl+F4 hot-key). /// /// Stereo handle that corresponds to the device interface. public static void IncreaseSeparation(StereoHandle handle) { var status = DelegateFactory.GetDelegate()( handle ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } } /// /// This API allows an application to enable stereo viewing, without the need of a GUID/Key pair /// This API cannot be used to enable stereo viewing on 3DTV. /// HOW TO USE: Call this function immediately after device creation, then follow with a reset. \n /// Very generically: /// Create Device->Create Stereo Handle->InitActivation->Reset Device /// /// Stereo handle corresponding to the device interface. /// Flags to enable or disable delayed activation. public static void InitActivation(StereoHandle handle, StereoActivationFlag activationFlag) { var status = DelegateFactory.GetDelegate()( handle, activationFlag ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } } /// /// This API checks if stereo is activated for the given device interface. /// /// Stereo handle that corresponds to the device interface. /// Address where result of the inquiry will be placed. public static bool IsStereoActivated(StereoHandle handle) { var status = DelegateFactory.GetDelegate()( handle, out var isStereoActive ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } return isStereoActive > 0; } /// /// This API checks if stereo mode is enabled in the registry. /// /// true if the stereo is enable; otherwise false public static bool IsStereoEnabled() { var status = DelegateFactory.GetDelegate()( out var isEnable ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } return isEnable > 0; } /// /// This API returns availability of windowed mode stereo /// /// true if windowed mode is supported; otherwise false public static bool IsWindowedModeSupported() { var status = DelegateFactory.GetDelegate()( out var supported ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } return supported > 0; } /// /// This API turns on/off reverse stereo blit. /// After reversed stereo blit control is turned on, blits from the stereo surface will /// produce the right-eye image in the left side of the destination surface and the left-eye /// image in the right side of the destination surface. /// In DirectX 9, the destination surface must be created as the render target, and StretchRect must be used. /// Conditions: /// - DstWidth == 2*SrcWidth /// - DstHeight == SrcHeight /// - Src surface is the stereo surface. /// - SrcRect must be {0,0,SrcWidth,SrcHeight} /// - DstRect must be {0,0,DstWidth,DstHeight} /// In DirectX 10, ResourceCopyRegion must be used. /// Conditions: /// - DstWidth == 2*SrcWidth /// - DstHeight == SrcHeight /// - dstX == 0, /// - dstY == 0, /// - dstZ == 0, /// - SrcBox: left=top=front==0; right==SrcWidth; bottom==SrcHeight; back==1; /// /// Stereo handle corresponding to the device interface. /// A boolean value to enable or disable blit control public static void ReverseStereoBlitControl(StereoHandle handle, bool turnOn) { var status = DelegateFactory.GetDelegate()( handle, (byte) (turnOn ? 1 : 0) ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } } /// /// This API sets the back buffer to left or right in Direct stereo mode. /// /// Stereo handle that corresponds to the device interface. /// Defines active eye in Direct stereo mode public static void SetActiveEye(StereoHandle handle, StereoActiveEye activeEye) { var status = DelegateFactory.GetDelegate()( handle, activeEye ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } } /// /// This API sets the given parameter value under the application's registry key. /// If the value does not exist under the application's registry key, the value will be created under the key. /// /// The type of profile the application wants to access. /// ID of the value that is being set. /// Value that is being set. public static void SetConfigurationProfileValue( StereoRegistryProfileType registryProfileType, StereoRegistryIdentification registryId, float value) { var status = DelegateFactory.GetDelegate()( registryProfileType, registryId, ref value ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } } /// /// This API sets the given parameter value under the application's registry key. /// If the value does not exist under the application's registry key, the value will be created under the key. /// /// The type of profile the application wants to access. /// ID of the value that is being set. /// Value that is being set. public static void SetConfigurationProfileValue( StereoRegistryProfileType registryProfileType, StereoRegistryIdentification registryId, int value) { var status = DelegateFactory.GetDelegate()( registryProfileType, registryId, ref value ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } } /// /// This API sets convergence to the given value. /// /// Stereo handle that corresponds to the device interface. /// New value for convergence. public static void SetConvergence(StereoHandle handle, float convergence) { var status = DelegateFactory.GetDelegate()( handle, convergence ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } } /// /// This API defines the stereo profile used by the driver in case the application has no associated profile. /// To take effect, this API must be called before D3D device is created. Calling once a device has been created will /// not affect the current device. /// /// Default profile name. public static void SetDefaultProfile(string profileName) { var status = DelegateFactory.GetDelegate()( profileName ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } } /// /// This API sets the 3D stereo driver mode: Direct or Automatic /// /// Defines the 3D stereo driver mode: Direct or Automatic public static void SetDriverMode(StereoDriverMode driverMode) { var status = DelegateFactory.GetDelegate()( driverMode ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } } /// /// This API sets the current frustum adjust mode value. /// /// Stereo handle that corresponds to the device interface. /// New value for frustum adjust mode. public static void SetFrustumAdjustMode( StereoHandle handle, StereoFrustumAdjustMode frustumAdjustMode) { var status = DelegateFactory.GetDelegate()( handle, frustumAdjustMode ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } } /// /// This API checks if the last draw call was stereoized. It is a very expensive to call and should be used for /// debugging purpose *only*. /// /// Stereo handle that corresponds to the device interface. /// true if the last draw was a stereo draw; otherwise false public static bool WasLastDrawStereoizedDebug(StereoHandle handle) { var status = DelegateFactory.GetDelegate()( handle, out var supported ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } return supported > 0; } // ReSharper disable CommentTypo /// /// This API is a Setup notification message that the stereo driver uses to notify the application /// when the user changes the stereo driver state. /// When the user changes the stereo state (Activated or Deactivated, separation or conversion) /// the stereo driver posts a defined message with the following parameters: /// lParam is the current conversion. (Actual conversion is *(float*)&lParam ) /// wParam == MAKEWPARAM(l, h) where /// - l == 0 if stereo is deactivated /// - l == 1 if stereo is deactivated /// - h is the current separation. (Actual separation is float(h*100.f/0xFFFF) /// Call this API with NULL hWnd to prohibit notification. /// /// Stereo handle corresponding to the device interface. /// /// Window handle that will be notified when the user changes the stereo driver state. Actual /// handle must be cast to an . /// /// MessageID of the message that will be posted to window public static void SetNotificationMessage( StereoHandle handle, ulong windowsHandle, ulong messageId) { var status = DelegateFactory.GetDelegate()( handle, windowsHandle, messageId ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } } /// /// This API sets separation to given percentage. /// /// Stereo handle that corresponds to the device interface. /// New value for separation percentage. public static void SetSeparation(StereoHandle handle, float separationPercentage) { var status = DelegateFactory.GetDelegate()( handle, separationPercentage ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } } /// /// This API sets surface creation mode for this device interface. /// /// Stereo handle that corresponds to the device interface. /// New surface creation mode for this device interface. public static void SetSurfaceCreationMode( StereoHandle handle, StereoSurfaceCreateMode surfaceCreateMode) { var status = DelegateFactory.GetDelegate()( handle, surfaceCreateMode ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } } /// /// This API allows an application to trigger creation of a stereo desktop, /// in case the creation was stopped on application launch. /// /// Stereo handle that corresponds to the device interface. public static void TriggerActivation(StereoHandle handle) { var status = DelegateFactory.GetDelegate()( handle ); if (status != Status.Ok) { throw new NVIDIAApiException(status); } } } }