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);
}
}
}
}