diff --git a/DisplayMagicianShared/NVIDIA/NVAPI.cs b/DisplayMagicianShared/NVIDIA/NVAPI.cs
index fd5650f..006c733 100644
--- a/DisplayMagicianShared/NVIDIA/NVAPI.cs
+++ b/DisplayMagicianShared/NVIDIA/NVAPI.cs
@@ -2146,6 +2146,7 @@ namespace DisplayMagicianShared.NVIDIA
public const UInt32 NV_MOSAIC_TOPO_MAX = (UInt32)NV_MOSAIC_TOPO.TOPO_MAX;
public const UInt32 NVAPI_MAX_MOSAIC_DISPLAY_ROWS = 8;
public const UInt32 NVAPI_MAX_MOSAIC_DISPLAY_COLUMNS = 8;
+ public const UInt32 NVAPI_MAX_MOSAIC_TOPOS = 16;
public const UInt32 NVAPI_GENERIC_STRING_MAX = 4096;
public const UInt32 NVAPI_LONG_STRING_MAX = 256;
public const UInt32 NVAPI_SHORT_STRING_MAX = 64;
@@ -2343,6 +2344,8 @@ namespace DisplayMagicianShared.NVIDIA
GetDelegate(NvId_Mosaic_GetCurrentTopo, out Mosaic_GetCurrentTopoInternal);
GetDelegate(NvId_Mosaic_GetTopoGroup, out Mosaic_GetTopoGroupInternal);
GetDelegate(NvId_Mosaic_GetSupportedTopoInfo, out Mosaic_GetSupportedTopoInfoInternal);
+ GetDelegate(NvId_Mosaic_EnumDisplayModes, out Mosaic_EnumDisplayModesInternal);
+ GetDelegate(NvId_Mosaic_EnumDisplayModes, out Mosaic_EnumDisplayModesInternalNull); // The null version of the submission
GetDelegate(NvId_Mosaic_EnumDisplayGrids, out Mosaic_EnumDisplayGridsInternal);
GetDelegate(NvId_Mosaic_EnumDisplayGrids, out Mosaic_EnumDisplayGridsInternalNull); // The null version of the submission
GetDelegate(NvId_Mosaic_SetDisplayGrids, out Mosaic_SetDisplayGridsInternal);
@@ -3629,6 +3632,113 @@ namespace DisplayMagicianShared.NVIDIA
return status;
}
+ // NVAPI_INTERFACE NvAPI_Mosaic_EnumDisplayModes ( __in NV_MOSAIC_GRID_TOPO * pGridTopology, __inout_ecount_part_opt*,*pDisplayCount NV_MOSAIC_DISPLAY_SETTING * pDisplaySettings,
+ // __inout NvU32 * pDisplayCount )
+ // NvAPIMosaic_EnumDisplayModes
+ private delegate NVAPI_STATUS Mosaic_EnumDisplayModesDelegate(
+ [In] NV_MOSAIC_GRID_TOPO_V2 gridTopology,
+ [In][Out] IntPtr displaySettingsBuffer,
+ [In][Out] ref UInt32 displayCount);
+ private static readonly Mosaic_EnumDisplayModesDelegate Mosaic_EnumDisplayModesInternal;
+
+ ///
+ /// Determines the set of available display modes for a given grid topology.
+ /// If displaySettings is NULL, then displayCount will receive the total number of modes that are available.
+ /// If displaySettings is not NULL, then displayCount should point to the number of elements in the pDisplaySettings array. On return, it will contain the number of modes that were actually returned
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static NVAPI_STATUS NvAPI_Mosaic_EnumDisplayModes(NV_MOSAIC_GRID_TOPO_V2 gridTopology, ref NV_MOSAIC_DISPLAY_SETTING_V2[] displaySettings, ref UInt32 displayCount)
+ {
+ NVAPI_STATUS status;
+
+ // Build a managed structure for us to use as a data source for another object that the unmanaged NVAPI C library can use
+ displaySettings = new NV_MOSAIC_DISPLAY_SETTING_V2[displayCount];
+ // Initialize unmanged memory to hold the unmanaged array of structs
+ IntPtr displaySettingsBuffer = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(NV_MOSAIC_DISPLAY_SETTING_V2)) * (int)displayCount);
+ // Also set another memory pointer to the same place so that we can do the memory copying item by item
+ // as we have to do it ourselves (there isn't an easy to use Marshal equivalent)
+ IntPtr currentDisplaySettingsBuffer = displaySettingsBuffer;
+ // Go through the array and copy things from managed code to unmanaged code
+ for (Int32 x = 0; x < (Int32)displayCount; x++)
+ {
+ // Set up the basic structure
+ displaySettings[x].Version = NVImport.NV_MOSAIC_DISPLAY_SETTING_V2_VER;
+
+ // Marshal a single gridtopology into unmanaged code ready for sending to the unmanaged NVAPI function
+ Marshal.StructureToPtr(displaySettings[x], currentDisplaySettingsBuffer, false);
+ // advance the buffer forwards to the next object
+ currentDisplaySettingsBuffer = (IntPtr)((long)currentDisplaySettingsBuffer + Marshal.SizeOf(displaySettings[x]));
+ }
+
+
+ if (Mosaic_EnumDisplayModesInternal != null)
+ {
+ // Use the unmanaged buffer in the unmanaged C call
+ status = Mosaic_EnumDisplayModesInternal(gridTopology, displaySettingsBuffer, ref displayCount);
+
+ if (status == NVAPI_STATUS.NVAPI_OK)
+ {
+ // If everything worked, then copy the data back from the unmanaged array into the managed array
+ // So that we can use it in C# land
+ // Reset the memory pointer we're using for tracking where we are back to the start of the unmanaged memory buffer
+ currentDisplaySettingsBuffer = displaySettingsBuffer;
+ // Create a managed array to store the received information within
+ displaySettings = new NV_MOSAIC_DISPLAY_SETTING_V2[displayCount];
+ // Go through the memory buffer item by item and copy the items into the managed array
+ for (int i = 0; i < displayCount; i++)
+ {
+ // build a structure in the array slot
+ displaySettings[i] = new NV_MOSAIC_DISPLAY_SETTING_V2();
+ // fill the array slot structure NV_MOSAIC_DISPLAY_SETTING_V2 the data from the buffer
+ displaySettings[i] = (NV_MOSAIC_DISPLAY_SETTING_V2)Marshal.PtrToStructure(currentDisplaySettingsBuffer, typeof(NV_MOSAIC_DISPLAY_SETTING_V2));
+ // destroy the bit of memory we no longer need
+ Marshal.DestroyStructure(currentDisplaySettingsBuffer, typeof(NV_MOSAIC_DISPLAY_SETTING_V2));
+ // advance the buffer forwards to the next object
+ currentDisplaySettingsBuffer = (IntPtr)((long)currentDisplaySettingsBuffer + Marshal.SizeOf(displaySettings[i]));
+ }
+ }
+ }
+ else
+ {
+ status = NVAPI_STATUS.NVAPI_FUNCTION_NOT_FOUND;
+ }
+
+ Marshal.FreeCoTaskMem(displaySettingsBuffer);
+
+ return status;
+ }
+
+ // NVAPI_INTERFACE NvAPI_Mosaic_EnumDisplayModes(__inout_ecount_part_opt*,* pGridCount NV_MOSAIC_GRID_TOPO* pGridTopologies,__inout NvU32 * pGridCount)
+ // NvAPIMosaic_EnumDisplayModes
+ private delegate NVAPI_STATUS Mosaic_EnumDisplayModesDelegateNull(
+ [In] NV_MOSAIC_GRID_TOPO_V2 gridTopology,
+ [In][Out] IntPtr displaySettingsBuffer,
+ [In][Out] ref UInt32 displayCount);
+ private static readonly Mosaic_EnumDisplayModesDelegateNull Mosaic_EnumDisplayModesInternalNull;
+
+ ///
+ /// Determines the set of available display modes for a given grid topology.
+ /// If displaySettings is NULL, then displayCount will receive the total number of modes that are available.
+ /// If displaySettings is not NULL, then displayCount should point to the number of elements in the pDisplaySettings array. On return, it will contain the number of modes that were actually returned
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static NVAPI_STATUS NvAPI_Mosaic_EnumDisplayModes(NV_MOSAIC_GRID_TOPO_V2 gridTopology, ref UInt32 displayCount)
+ {
+ NVAPI_STATUS status;
+ IntPtr displaySettings = IntPtr.Zero;
+
+ if (Mosaic_EnumDisplayModesInternalNull != null) { status = Mosaic_EnumDisplayModesInternalNull(gridTopology, displaySettings, ref displayCount); }
+ else { status = NVAPI_STATUS.NVAPI_FUNCTION_NOT_FOUND; }
+
+ return status;
+ }
+
// NVAPI_INTERFACE NvAPI_Mosaic_EnumDisplayGrids(__inout_ecount_part_opt*,* pGridCount NV_MOSAIC_GRID_TOPO* pGridTopologies,__inout NvU32 * pGridCount)
// NvAPIMosaic_EnumDisplayGrids
private delegate NVAPI_STATUS Mosaic_EnumDisplayGridsDelegate(
@@ -3752,8 +3862,9 @@ namespace DisplayMagicianShared.NVIDIA
///
///
///
- public static NVAPI_STATUS NvAPI_Mosaic_ValidateDisplayGrids(NV_MOSAIC_SETDISPLAYTOPO_FLAGS setTopoFlags, ref NV_MOSAIC_GRID_TOPO_V2[] gridTopologies, ref NV_MOSAIC_DISPLAY_TOPO_STATUS_V1[] topoStatuses, UInt32 gridCount)
+ public static NVAPI_STATUS NvAPI_Mosaic_ValidateDisplayGrids(NV_MOSAIC_SETDISPLAYTOPO_FLAGS setTopoFlags, NV_MOSAIC_GRID_TOPO_V2[] gridTopologies, ref NV_MOSAIC_DISPLAY_TOPO_STATUS_V1[] topoStatuses, UInt32 gridCount)
{
+ // Warning! - This function still has some errors with it. It errors with an NVAPI_INCOMPATIBLE_STRUCT_VERSION error. Still needs troubleshooting.
NVAPI_STATUS status;
// Initialize unmanged memory to hold the unmanaged array of structs
IntPtr gridTopologiesBuffer = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(NV_MOSAIC_GRID_TOPO_V2)) * (int)gridCount);
@@ -3763,13 +3874,6 @@ namespace DisplayMagicianShared.NVIDIA
// Go through the array and copy things from managed code to unmanaged code
for (Int32 x = 0; x < (Int32)gridCount; x++)
{
- for (Int32 y = 0; y < gridTopologies[x].DisplayCount; y++)
- {
- gridTopologies[x].Displays[y].Version = NVImport.NV_MOSAIC_GRID_TOPO_DISPLAY_V2_VER;
- }
- gridTopologies[x].DisplaySettings.Version = NVImport.NV_MOSAIC_DISPLAY_SETTING_V1_VER;
- gridTopologies[x].Version = NVImport.NV_MOSAIC_GRID_TOPO_V2_VER;
-
// Marshal a single gridtopology into unmanaged code ready for sending to the unmanaged NVAPI function
Marshal.StructureToPtr(gridTopologies[x], currentGridTopologiesBuffer, false);
// advance the buffer forwards to the next object
@@ -4008,8 +4112,8 @@ namespace DisplayMagicianShared.NVIDIA
// NVAPI_INTERFACE NvAPI_Mosaic_SetCurrentTopo ( NV_MOSAIC_TOPO_BRIEF * pTopoBrief, NV_MOSAIC_DISPLAY_SETTING* pDisplaySetting, NvS32 overlapX, NvS32 overlapY, NvU32 enable)
// NvAPI_Mosaic_SetCurrentTopo
private delegate NVAPI_STATUS Mosaic_SetCurrentTopoDelegate(
- [In] ref NV_MOSAIC_TOPO_BRIEF topoBrief,
- [In] ref NV_MOSAIC_DISPLAY_SETTING_V2 displaySetting,
+ [In] NV_MOSAIC_TOPO_BRIEF topoBrief,
+ [In] NV_MOSAIC_DISPLAY_SETTING_V2 displaySetting,
[In] Int32 overlapX,
[In] Int32 overlapY,
[In] UInt32 enable);
@@ -4025,15 +4129,15 @@ namespace DisplayMagicianShared.NVIDIA
///
///
///
- public static NVAPI_STATUS NvAPI_Mosaic_SetCurrentTopo(ref NV_MOSAIC_TOPO_BRIEF topoBrief, ref NV_MOSAIC_DISPLAY_SETTING_V2 displaySetting, Int32 overlapX, Int32 overlapY, UInt32 enable)
+ public static NVAPI_STATUS NvAPI_Mosaic_SetCurrentTopo(NV_MOSAIC_TOPO_BRIEF topoBrief, NV_MOSAIC_DISPLAY_SETTING_V2 displaySetting, Int32 overlapX, Int32 overlapY, UInt32 enable)
{
NVAPI_STATUS status;
- topoBrief.Version = NVImport.NV_MOSAIC_TOPO_BRIEF_VER;
- displaySetting.Version = NVImport.NV_MOSAIC_DISPLAY_SETTING_V2_VER;
+ //topoBrief.Version = NVImport.NV_MOSAIC_TOPO_BRIEF_VER;
+ //displaySetting.Version = NVImport.NV_MOSAIC_DISPLAY_SETTING_V2_VER;
// Set enable to false within the version as we want to enable it now
// This is needed as the saved display topology object was made when the topology was enabled :)
//topoBrief.Enabled = 0;
- if (Mosaic_SetCurrentTopoInternal != null) { status = Mosaic_SetCurrentTopoInternal(ref topoBrief, ref displaySetting, overlapX, overlapY, enable); }
+ if (Mosaic_SetCurrentTopoInternal != null) { status = Mosaic_SetCurrentTopoInternal(topoBrief, displaySetting, overlapX, overlapY, enable); }
else { status = NVAPI_STATUS.NVAPI_FUNCTION_NOT_FOUND; }
return status;
diff --git a/DisplayMagicianShared/NVIDIA/NVIDIALibrary.cs b/DisplayMagicianShared/NVIDIA/NVIDIALibrary.cs
index 8a5d627..56e21aa 100644
--- a/DisplayMagicianShared/NVIDIA/NVIDIALibrary.cs
+++ b/DisplayMagicianShared/NVIDIA/NVIDIALibrary.cs
@@ -354,12 +354,59 @@ namespace DisplayMagicianShared.NVIDIA
}
}
+ // Get current Supported Mosaic Topology info (check whether Mosaic is on)
+ NV_MOSAIC_SUPPORTED_TOPO_INFO_V2 mosaicSupportedTopoInfo = new NV_MOSAIC_SUPPORTED_TOPO_INFO_V2();
+ NVStatus = NVImport.NvAPI_Mosaic_GetSupportedTopoInfo(ref mosaicSupportedTopoInfo, NV_MOSAIC_TOPO_TYPE.ALL);
+ if (NVStatus == NVAPI_STATUS.NVAPI_OK)
+ {
+ SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: NvAPI_Mosaic_GetSupportedTopoInfo returned OK.");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_NOT_SUPPORTED)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: Mosaic is not supported with the existing hardware. NvAPI_Mosaic_GetSupportedTopoInfo() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_INVALID_ARGUMENT)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: One or more argumentss passed in are invalid. NvAPI_Mosaic_GetSupportedTopoInfo() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_API_NOT_INITIALIZED)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: The NvAPI API needs to be initialized first. NvAPI_Mosaic_GetSupportedTopoInfo() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_NO_IMPLEMENTATION)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: This entry point not available in this NVIDIA Driver. NvAPI_Mosaic_GetSupportedTopoInfo() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_INCOMPATIBLE_STRUCT_VERSION)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: The version of the structure passed in is not supported by this driver. NvAPI_Mosaic_GetSupportedTopoInfo() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_ERROR)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: A miscellaneous error occurred. NvAPI_Mosaic_GetSupportedTopoInfo() returned error code {NVStatus}");
+ }
+ else
+ {
+ SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: Some non standard error occurred while getting Mosaic Topology! NvAPI_Mosaic_GetSupportedTopoInfo() returned error code {NVStatus}");
+ }
+
+ if (mosaicSupportedTopoInfo != null && mosaicSupportedTopoInfo.TopoBriefsCount > 0)
+ {
+ int numValidTopos = mosaicSupportedTopoInfo.TopoBriefs.Count(tb => tb.IsPossible == 1);
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: There are {numValidTopos} valid Mosaic Topologies available with this display layout.");
+ }
+ else
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: There are no valid Mosaic Topologies available with this display layout.");
+ }
+
+
// Get current Mosaic Topology settings in brief (check whether Mosaic is on)
NV_MOSAIC_TOPO_BRIEF mosaicTopoBrief = new NV_MOSAIC_TOPO_BRIEF();
- NV_MOSAIC_DISPLAY_SETTING_V2 mosaicDisplaySettings = new NV_MOSAIC_DISPLAY_SETTING_V2();
+ NV_MOSAIC_DISPLAY_SETTING_V2 mosaicDisplaySetting = new NV_MOSAIC_DISPLAY_SETTING_V2();
int mosaicOverlapX = 0;
int mosaicOverlapY = 0;
- NVStatus = NVImport.NvAPI_Mosaic_GetCurrentTopo(ref mosaicTopoBrief, ref mosaicDisplaySettings, out mosaicOverlapX, out mosaicOverlapY);
+ NVStatus = NVImport.NvAPI_Mosaic_GetCurrentTopo(ref mosaicTopoBrief, ref mosaicDisplaySetting, out mosaicOverlapX, out mosaicOverlapY);
if (NVStatus == NVAPI_STATUS.NVAPI_OK)
{
SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: NvAPI_Mosaic_GetCurrentTopo returned OK.");
@@ -389,52 +436,93 @@ namespace DisplayMagicianShared.NVIDIA
SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: Some non standard error occurred while getting Mosaic Topology! NvAPI_Mosaic_GetCurrentTopo() returned error code {NVStatus}");
}
+ // Get more Mosaic Topology detailed settings
+ NV_MOSAIC_TOPO_GROUP mosaicTopoGroup = new NV_MOSAIC_TOPO_GROUP();
+ NVStatus = NVImport.NvAPI_Mosaic_GetTopoGroup(ref mosaicTopoBrief, ref mosaicTopoGroup);
+ if (NVStatus == NVAPI_STATUS.NVAPI_OK)
+ {
+ SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: NvAPI_Mosaic_GetTopoGroup returned OK.");
+ if (mosaicTopoBrief.IsPossible == 1)
+ {
+ SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: The current Mosaic Topology of {mosaicTopoBrief.Topo} is possible to use");
+ }
+ else
+ {
+ SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: The current Mosaic Topology of {mosaicTopoBrief.Topo} is NOT possible to use");
+ }
+ if (mosaicTopoGroup.Count > 0)
+ {
+ int m = 1;
+ foreach (var mosaicTopoDetail in mosaicTopoGroup.Topos)
+ {
+
+ if (mosaicTopoDetail.TopologyValid)
+ {
+ SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: The returned Mosaic Topology Group #{m} is VALID.");
+ }
+ else
+ {
+ SharedLogger.logger.Error($"NVIDIALibrary/GetNVIDIADisplayConfig: The returned Mosaic Topology Group #{m} is NOT VALID and cannot be used.");
+ }
+ if (mosaicTopoDetail.TopologyMissingGPU)
+ {
+ SharedLogger.logger.Error($"NVIDIALibrary/GetNVIDIADisplayConfig: The returned Mosaic Topology Group #{m} is MISSING THE GPU it was created with.");
+ }
+ if (mosaicTopoDetail.TopologyMissingDisplay)
+ {
+ SharedLogger.logger.Error($"NVIDIALibrary/GetNVIDIADisplayConfig: The returned Mosaic Topology Group #{m} is MISSING ONE OR MORE DISPLAYS it was created with.");
+ }
+ if (mosaicTopoDetail.TopologyMixedDisplayTypes)
+ {
+ SharedLogger.logger.Error($"NVIDIALibrary/GetNVIDIADisplayConfig: The returned Mosaic Topology Group #{m} is USING MIXED DISPLAY TYPES and NVIDIA don't support that at present.");
+ }
+ }
+ }
+ else
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: The returned Mosaic Topology Group doesn't have any returned Topo Groups. We expect there should be at least one if the Mosaic display layout is configured correctly.");
+ }
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_NOT_SUPPORTED)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: Mosaic is not supported with the existing hardware. NvAPI_Mosaic_GetTopoGroup() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_INVALID_ARGUMENT)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: One or more arguments passed in are invalid. NvAPI_Mosaic_GetTopoGroup() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_API_NOT_INITIALIZED)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: The NvAPI API needs to be initialized first. NvAPI_Mosaic_GetTopoGroup() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_NO_IMPLEMENTATION)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: This entry point not available in this NVIDIA Driver. NvAPI_Mosaic_GetTopoGroup() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_INCOMPATIBLE_STRUCT_VERSION)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: The version of the structure passed in is not supported by this driver. NvAPI_Mosaic_GetTopoGroup() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_ERROR)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: A miscellaneous error occurred. NvAPI_Mosaic_GetTopoGroup() returned error code {NVStatus}");
+ }
+ else
+ {
+ SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: Some non standard error occurred while getting Mosaic Topology! NvAPI_Mosaic_GetTopoGroup() returned error code {NVStatus}");
+ }
+
// Check if there is a topology and that Mosaic is enabled
if (mosaicTopoBrief.Topo != NV_MOSAIC_TOPO.TOPO_NONE && mosaicTopoBrief.Enabled == 1)
{
// Mosaic is enabled!
SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: NVIDIA Mosaic is enabled.");
myDisplayConfig.MosaicConfig.MosaicTopologyBrief = mosaicTopoBrief;
- myDisplayConfig.MosaicConfig.MosaicDisplaySettings = mosaicDisplaySettings;
+ myDisplayConfig.MosaicConfig.MosaicDisplaySettings = mosaicDisplaySetting;
myDisplayConfig.MosaicConfig.OverlapX = mosaicOverlapX;
myDisplayConfig.MosaicConfig.OverlapY = mosaicOverlapY;
myDisplayConfig.MosaicConfig.IsMosaicEnabled = true;
- // Get more Mosaic Topology detailed settings
- NV_MOSAIC_TOPO_GROUP mosaicTopoGroup = new NV_MOSAIC_TOPO_GROUP();
- NVStatus = NVImport.NvAPI_Mosaic_GetTopoGroup(ref mosaicTopoBrief, ref mosaicTopoGroup);
- if (NVStatus == NVAPI_STATUS.NVAPI_OK)
- {
- SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: NvAPI_Mosaic_GetTopoGroup returned OK.");
- }
- else if (NVStatus == NVAPI_STATUS.NVAPI_NOT_SUPPORTED)
- {
- SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: Mosaic is not supported with the existing hardware. NvAPI_Mosaic_GetTopoGroup() returned error code {NVStatus}");
- }
- else if (NVStatus == NVAPI_STATUS.NVAPI_INVALID_ARGUMENT)
- {
- SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: One or more argumentss passed in are invalid. NvAPI_Mosaic_GetTopoGroup() returned error code {NVStatus}");
- }
- else if (NVStatus == NVAPI_STATUS.NVAPI_API_NOT_INITIALIZED)
- {
- SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: The NvAPI API needs to be initialized first. NvAPI_Mosaic_GetTopoGroup() returned error code {NVStatus}");
- }
- else if (NVStatus == NVAPI_STATUS.NVAPI_NO_IMPLEMENTATION)
- {
- SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: This entry point not available in this NVIDIA Driver. NvAPI_Mosaic_GetTopoGroup() returned error code {NVStatus}");
- }
- else if (NVStatus == NVAPI_STATUS.NVAPI_INCOMPATIBLE_STRUCT_VERSION)
- {
- SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: The version of the structure passed in is not supported by this driver. NvAPI_Mosaic_GetTopoGroup() returned error code {NVStatus}");
- }
- else if (NVStatus == NVAPI_STATUS.NVAPI_ERROR)
- {
- SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: A miscellaneous error occurred. NvAPI_Mosaic_GetTopoGroup() returned error code {NVStatus}");
- }
- else
- {
- SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: Some non standard error occurred while getting Mosaic Topology! NvAPI_Mosaic_GetTopoGroup() returned error code {NVStatus}");
- }
// Figure out how many Mosaic Grid topoligies there are
uint mosaicGridCount = 0;
@@ -521,6 +609,47 @@ namespace DisplayMagicianShared.NVIDIA
// Save the viewports to the List
allViewports.Add(viewports);
+ // Figure out how many Mosaic Display topologies there are
+ UInt32 mosaicDisplayModesCount = 0;
+ NVStatus = NVImport.NvAPI_Mosaic_EnumDisplayModes(gridTopo, ref mosaicDisplayModesCount);
+ if (NVStatus == NVAPI_STATUS.NVAPI_OK)
+ {
+ SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: NvAPI_Mosaic_EnumDisplayModes returned OK.");
+ }
+
+ // Get Current Mosaic Display Topology settings using the Grid topologies numbers we got before
+ //NV_MOSAIC_TOPO myGridTopo = gridTopo;
+ NV_MOSAIC_DISPLAY_SETTING_V2[] mosaicDisplaySettings = new NV_MOSAIC_DISPLAY_SETTING_V2[mosaicDisplayModesCount];
+ NVStatus = NVImport.NvAPI_Mosaic_EnumDisplayModes(gridTopo, ref mosaicDisplaySettings, ref mosaicDisplayModesCount);
+ if (NVStatus == NVAPI_STATUS.NVAPI_OK)
+ {
+ SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: NvAPI_Mosaic_EnumDisplayModes returned OK.");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_NOT_SUPPORTED)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: Mosaic is not supported with the existing hardware. NvAPI_Mosaic_EnumDisplayModes() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_INVALID_ARGUMENT)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: One or more argumentss passed in are invalid. NvAPI_Mosaic_EnumDisplayModes() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_API_NOT_INITIALIZED)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: The NvAPI API needs to be initialized first. NvAPI_Mosaic_EnumDisplayModes() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_NO_IMPLEMENTATION)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: This entry point not available in this NVIDIA Driver. NvAPI_Mosaic_EnumDisplayModes() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_ERROR)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: A miscellaneous error occurred. NvAPI_Mosaic_EnumDisplayModes() returned error code {NVStatus}");
+ }
+ else
+ {
+ SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: Some non standard error occurred while getting Mosaic Topology Display Settings! NvAPI_Mosaic_EnumDisplayModes() returned error code {NVStatus}");
+ }
+
}
myDisplayConfig.MosaicConfig.MosaicViewports = allViewports;
@@ -1477,8 +1606,105 @@ namespace DisplayMagicianShared.NVIDIA
}
else
{
- // We need to change to a Mosaic profile, so we need to apply the new Mosaic Topology
- NV_MOSAIC_SETDISPLAYTOPO_FLAGS setTopoFlags = NV_MOSAIC_SETDISPLAYTOPO_FLAGS.NONE;
+ /*// We need to change to a Mosaic profile, so we need to apply the new Mosaic Topology
+ SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfig: Mosaic current config is different as the one we want, so applying the Mosaic config now");
+ // If we get here then the display is valid, so now we actually apply the new Mosaic Topology
+ NVStatus = NVImport.NvAPI_Mosaic_SetCurrentTopo(displayConfig.MosaicConfig.MosaicTopologyBrief, displayConfig.MosaicConfig.MosaicDisplaySettings, displayConfig.MosaicConfig.OverlapX, displayConfig.MosaicConfig.OverlapY, 0);
+ if (NVStatus == NVAPI_STATUS.NVAPI_OK)
+ {
+ SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfig: NvAPI_Mosaic_SetCurrentTopo returned OK.");
+ SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfig: Waiting 0.5 second to let the Mosaic display change take place before continuing");
+ System.Threading.Thread.Sleep(500);
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_NO_ACTIVE_SLI_TOPOLOGY)
+ {
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: No matching GPU topologies could be found. NvAPI_Mosaic_SetCurrentTopo() returned error code {NVStatus}");
+ return false;
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_TOPO_NOT_POSSIBLE)
+ {
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: The topology passed in is not currently possible. NvAPI_Mosaic_SetCurrentTopo() returned error code {NVStatus}");
+ return false;
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_INVALID_ARGUMENT)
+ {
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: One or more argumentss passed in are invalid. NvAPI_Mosaic_SetCurrentTopo() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_API_NOT_INITIALIZED)
+ {
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: The NvAPI API needs to be initialized first. NvAPI_Mosaic_SetCurrentTopo() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_NO_IMPLEMENTATION)
+ {
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: This entry point not available in this NVIDIA Driver. NvAPI_Mosaic_SetCurrentTopo() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_INCOMPATIBLE_STRUCT_VERSION)
+ {
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: The version of the structure passed in is not compatible with this entrypoint. NvAPI_Mosaic_SetCurrentTopo() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_MODE_CHANGE_FAILED)
+ {
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: There was an error changing the display mode. NvAPI_Mosaic_SetCurrentTopo() returned error code {NVStatus}");
+ return false;
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_ERROR)
+ {
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: A miscellaneous error occurred. NvAPI_Mosaic_SetCurrentTopo() returned error code {NVStatus}");
+ }
+ else
+ {
+ SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfig: Some non standard error occurred while getting Mosaic Display Grids! NvAPI_Mosaic_SetCurrentTopo() returned error code {NVStatus}");
+ }
+
+ // Turn on the selected Mosaic
+ uint enable = 1;
+ NVStatus = NVImport.NvAPI_Mosaic_EnableCurrentTopo(enable);
+ if (NVStatus == NVAPI_STATUS.NVAPI_OK)
+ {
+ SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfig: NvAPI_Mosaic_EnableCurrentTopo returned OK. Previously set Mosiac config re-enabled.");
+ SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfig: Waiting 0.5 second to let the Mosaic display change take place before continuing");
+ System.Threading.Thread.Sleep(500);
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_NOT_SUPPORTED)
+ {
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: Mosaic is not supported with the existing hardware. NvAPI_Mosaic_EnableCurrentTopo() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_TOPO_NOT_POSSIBLE)
+ {
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: The topology passed in is not currently possible. NvAPI_Mosaic_EnableCurrentTopo() returned error code {NVStatus}");
+ return false;
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_INVALID_ARGUMENT)
+ {
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: One or more argumentss passed in are invalid. NvAPI_Mosaic_EnableCurrentTopo() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_API_NOT_INITIALIZED)
+ {
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: The NvAPI API needs to be initialized first. NvAPI_Mosaic_EnableCurrentTopo() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_NO_IMPLEMENTATION)
+ {
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: This entry point not available in this NVIDIA Driver. NvAPI_Mosaic_EnableCurrentTopo() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_INCOMPATIBLE_STRUCT_VERSION)
+ {
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: The version of the structure passed in is not compatible with this entrypoint. NvAPI_Mosaic_EnableCurrentTopo() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_MODE_CHANGE_FAILED)
+ {
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: There was an error disabling the display mode. NvAPI_Mosaic_EnableCurrentTopo() returned error code {NVStatus}");
+ return false;
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_ERROR)
+ {
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: A miscellaneous error occurred. NvAPI_Mosaic_EnableCurrentTopo() returned error code {NVStatus}");
+ }
+ else
+ {
+ SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfig: Some non standard error occurred while getting Mosaic Topology! NvAPI_Mosaic_EnableCurrentTopo() returned error code {NVStatus}");
+ }*/
+
+ NV_MOSAIC_SETDISPLAYTOPO_FLAGS setTopoFlags = NV_MOSAIC_SETDISPLAYTOPO_FLAGS.MAXIMIZE_PERFORMANCE;
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfig: Mosaic current config is different as the one we want, so applying the Mosaic config now");
// If we get here then the display is valid, so now we actually apply the new Mosaic Topology
@@ -1536,52 +1762,199 @@ namespace DisplayMagicianShared.NVIDIA
// We are on a Mosaic profile now, and we need to change to a non-Mosaic profile
// We need to disable the Mosaic Topology
- // Turn off Mosaic
- uint enable = 0;
- NVStatus = NVImport.NvAPI_Mosaic_EnableCurrentTopo(enable);
+ NV_MOSAIC_SETDISPLAYTOPO_FLAGS setTopoFlags = NV_MOSAIC_SETDISPLAYTOPO_FLAGS.ALLOW_INVALID;
+
+ SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfig: Mosaic config that is currently set is no longer needed. Removing Mosaic config.");
+ NV_MOSAIC_GRID_TOPO_V2[] individualScreensTopology = CreateSingleScreenMosaicTopology();
+
+ // WARNING - Validation is disabled at present. This is mostly because there are errors in my NvAPI_Mosaic_ValidateDisplayGrids,
+ // but also because the config is coming from the NVIDIA Control Panel which will already do it's own validation checks.
+ /*// Firstly try to see if the oneScreenTopology is a valid config
+ SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfig: Checking if the 1x1 DisplayGrid we chose is valid for the NvAPI_Mosaic_SetDisplayGrids mosaic layout.");
+ NV_MOSAIC_DISPLAY_TOPO_STATUS_V1[] individualScreensStatuses = new NV_MOSAIC_DISPLAY_TOPO_STATUS_V1[(UInt32)individualScreensTopology.Length];
+ NVStatus = NVImport.NvAPI_Mosaic_ValidateDisplayGrids(setTopoFlags, individualScreensTopology, ref individualScreensStatuses, (UInt32)individualScreensTopology.Length);
if (NVStatus == NVAPI_STATUS.NVAPI_OK)
{
- SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfig: NvAPI_Mosaic_EnableCurrentTopo returned OK. Previously set Mosiac config re-enabled.");
+ SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfig: NvAPI_Mosaic_ValidateDisplayGrids returned OK.");
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfig: Waiting 0.5 second to let the Mosaic display change take place before continuing");
System.Threading.Thread.Sleep(500);
}
- else if (NVStatus == NVAPI_STATUS.NVAPI_NOT_SUPPORTED)
+ else if (NVStatus == NVAPI_STATUS.NVAPI_NO_ACTIVE_SLI_TOPOLOGY)
{
- SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: Mosaic is not supported with the existing hardware. NvAPI_Mosaic_EnableCurrentTopo() returned error code {NVStatus}");
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: No matching GPU topologies could be found. NvAPI_Mosaic_ValidateDisplayGrids() returned error code {NVStatus}");
+ return false;
}
else if (NVStatus == NVAPI_STATUS.NVAPI_TOPO_NOT_POSSIBLE)
{
- SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: The topology passed in is not currently possible. NvAPI_Mosaic_EnableCurrentTopo() returned error code {NVStatus}");
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: The topology passed in is not currently possible. NvAPI_Mosaic_ValidateDisplayGrids() returned error code {NVStatus}");
+ return false;
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_INVALID_DISPLAY_ID)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/SetActiveConfig: The Display ID of the first display is not currently possible to use. NvAPI_Mosaic_ValidateDisplayGrids() returned error code {NVStatus}. Trying again with the next display.");
return false;
}
else if (NVStatus == NVAPI_STATUS.NVAPI_INVALID_ARGUMENT)
{
- SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: One or more argumentss passed in are invalid. NvAPI_Mosaic_EnableCurrentTopo() returned error code {NVStatus}");
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: One or more arguments passed in are invalid. NvAPI_Mosaic_ValidateDisplayGrids() returned error code {NVStatus}");
+ return false;
}
else if (NVStatus == NVAPI_STATUS.NVAPI_API_NOT_INITIALIZED)
{
- SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: The NvAPI API needs to be initialized first. NvAPI_Mosaic_EnableCurrentTopo() returned error code {NVStatus}");
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: The NvAPI API needs to be initialized first. NvAPI_Mosaic_ValidateDisplayGrids() returned error code {NVStatus}");
+ return false;
}
else if (NVStatus == NVAPI_STATUS.NVAPI_NO_IMPLEMENTATION)
{
- SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: This entry point not available in this NVIDIA Driver. NvAPI_Mosaic_EnableCurrentTopo() returned error code {NVStatus}");
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: This entry point not available in this NVIDIA Driver. NvAPI_Mosaic_ValidateDisplayGrids() returned error code {NVStatus}");
+ return false;
}
else if (NVStatus == NVAPI_STATUS.NVAPI_INCOMPATIBLE_STRUCT_VERSION)
{
- SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: The version of the structure passed in is not compatible with this entrypoint. NvAPI_Mosaic_EnableCurrentTopo() returned error code {NVStatus}");
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: The version of the structure passed in is not compatible with this entrypoint. NvAPI_Mosaic_ValidateDisplayGrids() returned error code {NVStatus}");
+ return false;
}
else if (NVStatus == NVAPI_STATUS.NVAPI_MODE_CHANGE_FAILED)
{
- SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: There was an error disabling the display mode. NvAPI_Mosaic_EnableCurrentTopo() returned error code {NVStatus}");
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: There was an error changing the display mode. NvAPI_Mosaic_ValidateDisplayGrids() returned error code {NVStatus}");
return false;
}
else if (NVStatus == NVAPI_STATUS.NVAPI_ERROR)
{
- SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: A miscellaneous error occurred. NvAPI_Mosaic_EnableCurrentTopo() returned error code {NVStatus}");
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: A miscellaneous error occurred. NvAPI_Mosaic_ValidateDisplayGrids() returned error code {NVStatus}");
+ return false;
}
else
{
- SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfig: Some non standard error occurred while getting Mosaic Topology! NvAPI_Mosaic_EnableCurrentTopo() returned error code {NVStatus}");
+ SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfig: Some non standard error occurred while getting Mosaic Display Grids! NvAPI_Mosaic_ValidateDisplayGrids() returned error code {NVStatus}");
+ return false;
+ }*/
+
+
+ // If we get here then the display is valid, so now we actually apply the new Mosaic Topology
+ SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfig: Trying to set a 1x1 DisplayGrid for the NvAPI_Mosaic_SetDisplayGrids mosaic layout.");
+ NVStatus = NVImport.NvAPI_Mosaic_SetDisplayGrids(individualScreensTopology, (UInt32)individualScreensTopology.Length, setTopoFlags);
+ if (NVStatus == NVAPI_STATUS.NVAPI_OK)
+ {
+ SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfig: NvAPI_Mosaic_SetDisplayGrids returned OK.");
+ SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfig: Waiting 0.5 second to let the Mosaic display change take place before continuing");
+ System.Threading.Thread.Sleep(500);
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_NO_ACTIVE_SLI_TOPOLOGY)
+ {
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: No matching GPU topologies could be found. NvAPI_Mosaic_SetDisplayGrids() returned error code {NVStatus}");
+ return false;
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_TOPO_NOT_POSSIBLE)
+ {
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: The topology passed in is not currently possible. NvAPI_Mosaic_SetDisplayGrids() returned error code {NVStatus}");
+ return false;
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_INVALID_DISPLAY_ID)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/SetActiveConfig: The Display ID of the first display is not currently possible to use. NvAPI_Mosaic_SetDisplayGrids() returned error code {NVStatus}. Trying again with the next display.");
+ return false;
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_INVALID_ARGUMENT)
+ {
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: One or more arguments passed in are invalid. NvAPI_Mosaic_SetDisplayGrids() returned error code {NVStatus}");
+ return false;
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_API_NOT_INITIALIZED)
+ {
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: The NvAPI API needs to be initialized first. NvAPI_Mosaic_SetDisplayGrids() returned error code {NVStatus}");
+ return false;
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_NO_IMPLEMENTATION)
+ {
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: This entry point not available in this NVIDIA Driver. NvAPI_Mosaic_SetDisplayGrids() returned error code {NVStatus}");
+ return false;
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_INCOMPATIBLE_STRUCT_VERSION)
+ {
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: The version of the structure passed in is not compatible with this entrypoint. NvAPI_Mosaic_SetDisplayGrids() returned error code {NVStatus}");
+ return false;
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_MODE_CHANGE_FAILED)
+ {
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: There was an error changing the display mode. NvAPI_Mosaic_SetDisplayGrids() returned error code {NVStatus}");
+ return false;
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_ERROR)
+ {
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: A miscellaneous error occurred. NvAPI_Mosaic_SetDisplayGrids() returned error code {NVStatus}");
+ return false;
+ }
+ else
+ {
+ // If we get here, we may have an error, or it may have worked successfully! So we need to check again :(
+ SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfig: Some non standard error occurred while getting Mosaic Display Grids! NvAPI_Mosaic_SetDisplayGrids() returned error code {NVStatus}");
+ return false;
+ }
+
+ // If we get here, it may or it may not have worked successfully! So we need to check again :(
+ // We don't want to do a full ceck, so we do a quick check instead.
+ if (MosaicIsOn())
+ {
+ // If the Mosaic is still on, then the last mosaic disable failed, so we need to then try turning it off this using NvAPI_Mosaic_EnableCurrentTopo(0)
+ SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfig: Previous attempt to turn off Mosaic. Now trying to use NvAPI_Mosaic_EnableCurrentTopo to disable Mosaic instead.");
+ uint enable = 0;
+ NVStatus = NVImport.NvAPI_Mosaic_EnableCurrentTopo(enable);
+ if (NVStatus == NVAPI_STATUS.NVAPI_OK)
+ {
+ SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfig: NvAPI_Mosaic_EnableCurrentTopo returned OK. Previously set Mosiac config now disabled");
+ SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfig: Waiting 0.5 second to let the Mosaic display change take place before continuing");
+ System.Threading.Thread.Sleep(500);
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_NOT_SUPPORTED)
+ {
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: Mosaic is not supported with the existing hardware. NvAPI_Mosaic_EnableCurrentTopo() returned error code {NVStatus}");
+ return false;
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_TOPO_NOT_POSSIBLE)
+ {
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: The topology passed in is not currently possible. NvAPI_Mosaic_EnableCurrentTopo() returned error code {NVStatus}");
+ return false;
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_INVALID_ARGUMENT)
+ {
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: One or more argumentss passed in are invalid. NvAPI_Mosaic_EnableCurrentTopo() returned error code {NVStatus}");
+ return false;
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_API_NOT_INITIALIZED)
+ {
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: The NvAPI API needs to be initialized first. NvAPI_Mosaic_EnableCurrentTopo() returned error code {NVStatus}");
+ return false;
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_NO_IMPLEMENTATION)
+ {
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: This entry point not available in this NVIDIA Driver. NvAPI_Mosaic_EnableCurrentTopo() returned error code {NVStatus}");
+ return false;
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_INCOMPATIBLE_STRUCT_VERSION)
+ {
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: The version of the structure passed in is not compatible with this entrypoint. NvAPI_Mosaic_EnableCurrentTopo() returned error code {NVStatus}");
+ return false;
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_MODE_CHANGE_FAILED)
+ {
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: There was an error disabling the display mode. NvAPI_Mosaic_EnableCurrentTopo() returned error code {NVStatus}");
+ return false;
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_ERROR)
+ {
+ SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: A miscellaneous error occurred. NvAPI_Mosaic_EnableCurrentTopo() returned error code {NVStatus}");
+ return false;
+ }
+ else
+ {
+ SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfig: Some non standard error occurred while getting Mosaic Topology! NvAPI_Mosaic_EnableCurrentTopo() returned error code {NVStatus}");
+ return false;
+ }
+ }
+ else
+ {
+ SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfig: Mosaic successfully disabled using NvAPI_Mosaic_SetDisplayGrids method.");
}
}
else if (!displayConfig.MosaicConfig.IsMosaicEnabled && !ActiveDisplayConfig.MosaicConfig.IsMosaicEnabled)
@@ -2066,6 +2439,68 @@ namespace DisplayMagicianShared.NVIDIA
}
}*/
+ public static bool MosaicIsOn()
+ {
+ PhysicalGpuHandle[] physicalGpus = new PhysicalGpuHandle[NVImport.NVAPI_MAX_PHYSICAL_GPUS];
+ uint physicalGpuCount = 0;
+ NVAPI_STATUS NVStatus = NVImport.NvAPI_EnumPhysicalGPUs(ref physicalGpus, out physicalGpuCount);
+ if (NVStatus == NVAPI_STATUS.NVAPI_OK)
+ {
+ SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: NvAPI_EnumPhysicalGPUs returned {physicalGpuCount} Physical GPUs");
+ }
+ else
+ {
+ SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: Error getting physical GPU count. NvAPI_EnumPhysicalGPUs() returned error code {NVStatus}");
+ }
+
+ // Go through the Physical GPUs one by one
+ for (uint physicalGpuIndex = 0; physicalGpuIndex < physicalGpuCount; physicalGpuIndex++)
+ {
+ // Get current Mosaic Topology settings in brief (check whether Mosaic is on)
+ NV_MOSAIC_TOPO_BRIEF mosaicTopoBrief = new NV_MOSAIC_TOPO_BRIEF();
+ NV_MOSAIC_DISPLAY_SETTING_V2 mosaicDisplaySetting = new NV_MOSAIC_DISPLAY_SETTING_V2();
+ int mosaicOverlapX = 0;
+ int mosaicOverlapY = 0;
+ NVStatus = NVImport.NvAPI_Mosaic_GetCurrentTopo(ref mosaicTopoBrief, ref mosaicDisplaySetting, out mosaicOverlapX, out mosaicOverlapY);
+ if (NVStatus == NVAPI_STATUS.NVAPI_OK)
+ {
+ SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: NvAPI_Mosaic_GetCurrentTopo returned OK.");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_NOT_SUPPORTED)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: Mosaic is not supported with the existing hardware. NvAPI_Mosaic_GetCurrentTopo() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_INVALID_ARGUMENT)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: One or more argumentss passed in are invalid. NvAPI_Mosaic_GetCurrentTopo() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_API_NOT_INITIALIZED)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: The NvAPI API needs to be initialized first. NvAPI_Mosaic_GetCurrentTopo() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_NO_IMPLEMENTATION)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: This entry point not available in this NVIDIA Driver. NvAPI_Mosaic_GetCurrentTopo() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_ERROR)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: A miscellaneous error occurred. NvAPI_Mosaic_GetCurrentTopo() returned error code {NVStatus}");
+ }
+ else
+ {
+ SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: Some non standard error occurred while getting Mosaic Topology! NvAPI_Mosaic_GetCurrentTopo() returned error code {NVStatus}");
+ }
+
+ // Check if there is a topology and that Mosaic is enabled
+ if (mosaicTopoBrief.Topo != NV_MOSAIC_TOPO.TOPO_NONE && mosaicTopoBrief.Enabled == 1)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
public List GetCurrentDisplayIdentifiers()
{
SharedLogger.logger.Trace($"NVIDIALibrary/GetCurrentDisplayIdentifiers: Getting the current display identifiers for the displays in use now");
@@ -2453,6 +2888,171 @@ namespace DisplayMagicianShared.NVIDIA
return displayIdentifiers;
}
+
+ public static NV_MOSAIC_GRID_TOPO_V2[] CreateSingleScreenMosaicTopology()
+ {
+ /*// Get current Mosaic Topology settings in brief (check whether Mosaic is on)
+ NV_MOSAIC_TOPO_BRIEF mosaicTopoBrief = new NV_MOSAIC_TOPO_BRIEF();
+ NV_MOSAIC_DISPLAY_SETTING_V2 mosaicDisplaySetting = new NV_MOSAIC_DISPLAY_SETTING_V2();
+ int mosaicOverlapX = 0;
+ int mosaicOverlapY = 0;
+ NVAPI_STATUS NVStatus = NVImport.NvAPI_Mosaic_GetCurrentTopo(ref mosaicTopoBrief, ref mosaicDisplaySetting, out mosaicOverlapX, out mosaicOverlapY);
+ if (NVStatus == NVAPI_STATUS.NVAPI_OK)
+ {
+ SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: NvAPI_Mosaic_GetCurrentTopo returned OK.");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_NOT_SUPPORTED)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: Mosaic is not supported with the existing hardware. NvAPI_Mosaic_GetCurrentTopo() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_INVALID_ARGUMENT)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: One or more argumentss passed in are invalid. NvAPI_Mosaic_GetCurrentTopo() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_API_NOT_INITIALIZED)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: The NvAPI API needs to be initialized first. NvAPI_Mosaic_GetCurrentTopo() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_NO_IMPLEMENTATION)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: This entry point not available in this NVIDIA Driver. NvAPI_Mosaic_GetCurrentTopo() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_ERROR)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: A miscellaneous error occurred. NvAPI_Mosaic_GetCurrentTopo() returned error code {NVStatus}");
+ }
+ else
+ {
+ SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: Some non standard error occurred while getting Mosaic Topology! NvAPI_Mosaic_GetCurrentTopo() returned error code {NVStatus}");
+ }*/
+
+ // Figure out how many Mosaic Grid topoligies there are
+ uint mosaicGridCount = 0;
+ NVAPI_STATUS NVStatus = NVImport.NvAPI_Mosaic_EnumDisplayGrids(ref mosaicGridCount);
+ if (NVStatus == NVAPI_STATUS.NVAPI_OK)
+ {
+ SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: NvAPI_Mosaic_GetCurrentTopo returned OK.");
+ }
+
+ // Get Current Mosaic Grid settings using the Grid topologies fnumbers we got before
+ NV_MOSAIC_GRID_TOPO_V2[] mosaicGridTopos = new NV_MOSAIC_GRID_TOPO_V2[mosaicGridCount];
+ NVStatus = NVImport.NvAPI_Mosaic_EnumDisplayGrids(ref mosaicGridTopos, ref mosaicGridCount);
+ if (NVStatus == NVAPI_STATUS.NVAPI_OK)
+ {
+ SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: NvAPI_Mosaic_EnumDisplayGrids returned OK.");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_NOT_SUPPORTED)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: Mosaic is not supported with the existing hardware. NvAPI_Mosaic_EnumDisplayGrids() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_INVALID_ARGUMENT)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: One or more argumentss passed in are invalid. NvAPI_Mosaic_EnumDisplayGrids() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_API_NOT_INITIALIZED)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: The NvAPI API needs to be initialized first. NvAPI_Mosaic_EnumDisplayGrids() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_NO_IMPLEMENTATION)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: This entry point not available in this NVIDIA Driver. NvAPI_Mosaic_EnumDisplayGrids() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_ERROR)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: A miscellaneous error occurred. NvAPI_Mosaic_EnumDisplayGrids() returned error code {NVStatus}");
+ }
+ else
+ {
+ SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: Some non standard error occurred while getting Mosaic Topology! NvAPI_Mosaic_EnumDisplayGrids() returned error code {NVStatus}");
+ }
+
+ // Sum up all the screens we have
+ //int totalScreenCount = mosaicGridTopos.Select(tp => tp.Displays).Sum(d => d.Count());
+ List screensToReturn = new List();
+
+ foreach (NV_MOSAIC_GRID_TOPO_V2 gridTopo in mosaicGridTopos)
+ {
+ // Figure out how many Mosaic Display topologies there are
+ UInt32 mosaicDisplayModesCount = 0;
+ NVStatus = NVImport.NvAPI_Mosaic_EnumDisplayModes(gridTopo, ref mosaicDisplayModesCount);
+ if (NVStatus == NVAPI_STATUS.NVAPI_OK)
+ {
+ SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: NvAPI_Mosaic_EnumDisplayModes returned OK.");
+ }
+
+ // Get Current Mosaic Display Topology settings using the Grid topologies numbers we got before
+ //NV_MOSAIC_TOPO myGridTopo = gridTopo;
+ NV_MOSAIC_DISPLAY_SETTING_V2[] mosaicDisplaySettings = new NV_MOSAIC_DISPLAY_SETTING_V2[mosaicDisplayModesCount];
+ NVStatus = NVImport.NvAPI_Mosaic_EnumDisplayModes(gridTopo, ref mosaicDisplaySettings, ref mosaicDisplayModesCount);
+ if (NVStatus == NVAPI_STATUS.NVAPI_OK)
+ {
+ SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: NvAPI_Mosaic_EnumDisplayModes returned OK.");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_NOT_SUPPORTED)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: Mosaic is not supported with the existing hardware. NvAPI_Mosaic_EnumDisplayModes() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_INVALID_ARGUMENT)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: One or more argumentss passed in are invalid. NvAPI_Mosaic_EnumDisplayModes() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_API_NOT_INITIALIZED)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: The NvAPI API needs to be initialized first. NvAPI_Mosaic_EnumDisplayModes() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_NO_IMPLEMENTATION)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: This entry point not available in this NVIDIA Driver. NvAPI_Mosaic_EnumDisplayModes() returned error code {NVStatus}");
+ }
+ else if (NVStatus == NVAPI_STATUS.NVAPI_ERROR)
+ {
+ SharedLogger.logger.Warn($"NVIDIALibrary/GetNVIDIADisplayConfig: A miscellaneous error occurred. NvAPI_Mosaic_EnumDisplayModes() returned error code {NVStatus}");
+ }
+ else
+ {
+ SharedLogger.logger.Trace($"NVIDIALibrary/GetNVIDIADisplayConfig: Some non standard error occurred while getting Mosaic Topology Display Settings! NvAPI_Mosaic_EnumDisplayModes() returned error code {NVStatus}");
+ }
+
+ for (int displayIndexToUse = 0; displayIndexToUse < gridTopo.DisplayCount; displayIndexToUse++)
+ {
+ NV_MOSAIC_GRID_TOPO_V2 thisScreen = new NV_MOSAIC_GRID_TOPO_V2();
+ thisScreen.Version = NVImport.NV_MOSAIC_GRID_TOPO_V2_VER;
+ thisScreen.Rows = 1;
+ thisScreen.Columns = 1;
+ thisScreen.DisplayCount = 1;
+ thisScreen.Flags = 0;
+ thisScreen.Displays = new NV_MOSAIC_GRID_TOPO_DISPLAY_V2[NVImport.NV_MOSAIC_MAX_DISPLAYS];
+ thisScreen.Displays[0].Version = NVImport.NV_MOSAIC_GRID_TOPO_DISPLAY_V2_VER;
+ thisScreen.Displays[0].DisplayId = gridTopo.Displays[displayIndexToUse].DisplayId;
+ thisScreen.Displays[0].CloneGroup = gridTopo.Displays[displayIndexToUse].CloneGroup;
+ thisScreen.Displays[0].OverlapX = gridTopo.Displays[displayIndexToUse].OverlapX;
+ thisScreen.Displays[0].OverlapY = gridTopo.Displays[displayIndexToUse].OverlapY;
+ thisScreen.Displays[0].PixelShiftType = gridTopo.Displays[displayIndexToUse].PixelShiftType;
+ thisScreen.Displays[0].Rotation = gridTopo.Displays[displayIndexToUse].Rotation;
+ thisScreen.DisplaySettings = new NV_MOSAIC_DISPLAY_SETTING_V1();
+ thisScreen.DisplaySettings.Version = gridTopo.DisplaySettings.Version;
+ thisScreen.DisplaySettings.Bpp = gridTopo.DisplaySettings.Bpp;
+ thisScreen.DisplaySettings.Freq = gridTopo.DisplaySettings.Freq;
+ thisScreen.DisplaySettings.Height = gridTopo.DisplaySettings.Height;
+ thisScreen.DisplaySettings.Width = gridTopo.DisplaySettings.Width;
+ screensToReturn.Add(thisScreen);
+ }
+
+ }
+ /*
+
+
+ // Selected the best display settings to use
+ NV_MOSAIC_DISPLAY_SETTING_V2 bestSetting = mosaicDisplaySettings.OrderByDescending(
+ settings => (long)settings.Width *
+ settings.Height *
+ settings.Bpp *
+ settings.Freq).First();
+ */
+
+ return screensToReturn.ToArray();
+ }
+
public static bool ListOfArraysEqual(List a1, List a2)
{
if (a1.Count == a2.Count)
diff --git a/DisplayMagicianShared/Windows/TaskBarSettings.cs b/DisplayMagicianShared/Windows/TaskBarSettings.cs
index 0f24050..9b2965b 100644
--- a/DisplayMagicianShared/Windows/TaskBarSettings.cs
+++ b/DisplayMagicianShared/Windows/TaskBarSettings.cs
@@ -11,7 +11,7 @@ using Microsoft.Win32;
namespace DisplayMagicianShared.Windows
{
public class TaskBarSettings
- {
+ {
private const string AdvancedSettingsAddress =
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced";
@@ -68,7 +68,7 @@ namespace DisplayMagicianShared.Windows
{
try
{
-
+
var value = key.GetValue(valueName, null,
RegistryValueOptions.DoNotExpandEnvironmentNames);
@@ -134,4 +134,4 @@ namespace DisplayMagicianShared.Windows
return true;
}
}
-}
+}
\ No newline at end of file
diff --git a/DisplayMagicianShared/Windows/TaskBarStuckRectangle.cs b/DisplayMagicianShared/Windows/TaskBarStuckRectangle.cs
index 3dcd0e4..87197b7 100644
--- a/DisplayMagicianShared/Windows/TaskBarStuckRectangle.cs
+++ b/DisplayMagicianShared/Windows/TaskBarStuckRectangle.cs
@@ -89,7 +89,7 @@ namespace DisplayMagicianShared.Windows
public string DevicePath { get; set; }
- public bool MainScreen{ get; set; }
+ public bool MainScreen { get; set; }
[JsonIgnore]
public UInt32 DPI
@@ -262,7 +262,7 @@ namespace DisplayMagicianShared.Windows
=> Version == other.Version &&
MainScreen == other.MainScreen &&
DevicePath == other.DevicePath &&
- Xor(Binary,other.Binary);
+ Xor(Binary, other.Binary);
public override int GetHashCode()
@@ -334,8 +334,8 @@ namespace DisplayMagicianShared.Windows
version = -1;
}
}
-
- if (version >= 2)
+
+ if (version >= 2)
{
// Grab the main screen taskbar placement
try
@@ -383,7 +383,6 @@ namespace DisplayMagicianShared.Windows
{
foreach (string displayId in displayIdentifiers)
{
- TaskBarStuckRectangle tbStuckRect;
// e.g. "WINAPI|\\\\?\\PCI#VEN_10DE&DEV_2482&SUBSYS_408E1458&REV_A1#4&2283f625&0&0019#{5b45201d-f2f2-4f3b-85bb-30ff1f953599}|DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DVI|54074|4318|\\\\?\\DISPLAY#NVS10DE#5&2b46c695&0&UID185344#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}|NV Surround"
string[] winapiLine = displayId.Split('|');
string pattern = @"DISPLAY\#(.*)\#\{";
@@ -485,4 +484,4 @@ namespace DisplayMagicianShared.Windows
return true;
}
}
-}
+}
\ No newline at end of file
diff --git a/DisplayMagicianShared/Windows/WinLibrary.cs b/DisplayMagicianShared/Windows/WinLibrary.cs
index 27bdbd6..5060e7e 100644
--- a/DisplayMagicianShared/Windows/WinLibrary.cs
+++ b/DisplayMagicianShared/Windows/WinLibrary.cs
@@ -167,7 +167,7 @@ namespace DisplayMagicianShared.Windows
myDefaultConfig.DisplayConfigPaths = new DISPLAYCONFIG_PATH_INFO[0];
myDefaultConfig.DisplayHDRStates = new List();
myDefaultConfig.DisplayIdentifiers = new List();
- myDefaultConfig.DisplaySources = new Dictionary>();
+ myDefaultConfig.DisplaySources = new Dictionary>();
myDefaultConfig.GdiDisplaySettings = new Dictionary();
myDefaultConfig.TaskBarLayout = new List();
myDefaultConfig.TaskBarSettings = new TaskBarSettings();
@@ -387,8 +387,8 @@ namespace DisplayMagicianShared.Windows
bool isClonedProfile = false;
for (int i = 0; i < paths.Length; i++)
{
- bool gotSourceDeviceName = false;
- bool gotAdapterName = false;
+ //bool gotSourceDeviceName = false;
+ //bool gotAdapterName = false;
bool gotAdvancedColorInfo = false;
bool gotSdrWhiteLevel = false;
@@ -414,7 +414,7 @@ namespace DisplayMagicianShared.Windows
err = CCDImport.DisplayConfigGetDeviceInfo(ref sourceInfo);
if (err == WIN32STATUS.ERROR_SUCCESS)
{
- gotSourceDeviceName = true;
+ //gotSourceDeviceName = true;
// Store it for later
if (windowsDisplayConfig.DisplaySources.ContainsKey(sourceInfo.ViewGdiDeviceName))
{
@@ -462,7 +462,7 @@ namespace DisplayMagicianShared.Windows
err = CCDImport.DisplayConfigGetDeviceInfo(ref adapterInfo);
if (err == WIN32STATUS.ERROR_SUCCESS)
{
- gotAdapterName = true;
+ //gotAdapterName = true;
// Store it for later
windowsDisplayConfig.DisplayAdapters.Add(paths[i].TargetInfo.AdapterId.Value, adapterInfo.AdapterDevicePath);
SharedLogger.logger.Trace($"WinLibrary/GetWindowsDisplayConfig: Found adapter name {adapterInfo.AdapterDevicePath} for adapter {paths[i].TargetInfo.AdapterId.Value}.");
@@ -476,7 +476,7 @@ namespace DisplayMagicianShared.Windows
{
// We already have the adapter name
SharedLogger.logger.Trace($"WinLibrary/GetWindowsDisplayConfig: We already have the adapter name {windowsDisplayConfig.DisplayAdapters[paths[i].TargetInfo.AdapterId.Value]} for adapter {paths[i].TargetInfo.AdapterId.Value} so skipping storing it.");
- gotAdapterName = true;
+ //gotAdapterName = true;
}
// Get advanced color info
@@ -603,7 +603,7 @@ namespace DisplayMagicianShared.Windows
// We use the information we already got from the display identifiers
SharedLogger.logger.Trace($"WinLibrary/GetWindowsDisplayConfig: Attempting to get the Windows Taskbar layout.");
List taskBarStuckRectangles = TaskBarStuckRectangle.GetCurrent(windowsDisplayConfig.DisplayIdentifiers);
-
+
// Now we try to get the taskbar settings too
SharedLogger.logger.Trace($"WinLibrary/GetWindowsDisplayConfig: Attempting to get the Windows Taskbar settings.");
TaskBarSettings taskBarSettings = TaskBarSettings.GetCurrent();
@@ -1075,7 +1075,7 @@ namespace DisplayMagicianShared.Windows
public bool SetActiveConfig(WINDOWS_DISPLAY_CONFIG displayConfig)
{
- bool needToRestartExplorer = false;
+ //bool needToRestartExplorer = false;
// Get the all possible windows display configs
SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: Generating a list of all the current display configs");
@@ -1333,10 +1333,10 @@ namespace DisplayMagicianShared.Windows
{
SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: Display {displayDeviceKey} is not currently in use, so cannot set it!");
}
-
+
}
-
+
// Now set the taskbar position for each screen
if (displayConfig.TaskBarLayout.Count > 0)
{
@@ -1367,7 +1367,7 @@ namespace DisplayMagicianShared.Windows
if (displayConfig.TaskBarSettings.Apply())
{
SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: Set the taskbar settings successfully!");
- needToRestartExplorer = true;
+ //needToRestartExplorer = true;
}
else
{
@@ -1908,66 +1908,6 @@ namespace DisplayMagicianShared.Windows
}
}
- public static bool RestartExplorer()
- {
- try
- {
- RestartManagerSession restartManager = new RestartManagerSession();
- FileInfo explorerFileInfo = new FileInfo(@"C:\Windows\explorer.exe");
- restartManager.RegisterProcessFile(explorerFileInfo);
- restartManager.Shutdown(RestartManagerSession.ShutdownType.ForceShutdown);
- restartManager.Restart();
- restartManager.Dispose();
- return true;
- }
- catch (Win32Exception ex)
- {
- if (ex.ErrorCode == 776)
- {
- SharedLogger.logger.Error(ex, $"WinLibrary/RestartExplorer: RestartManager was unable to restart Windows Explorer. ERROR_REQUEST_OUT_OF_SEQUENCE (779): This error value is returned if the RmRestart function is called with a valid session handle before calling the RmShutdown function.");
- }
- else if (ex.ErrorCode == 352)
- {
- SharedLogger.logger.Error(ex, $"WinLibrary/RestartExplorer: RestartManager was unable to restart Windows Explorer. ERROR_FAIL_RESTART (352): One or more applications could not be restarted.");
- }
- else if (ex.ErrorCode == 121)
- {
- SharedLogger.logger.Error(ex, $"WinLibrary/RestartExplorer: RestartManager was unable to restart Windows Explorer. ERROR_SEM_TIMEOUT (121): A Restart Manager function could not obtain a registry write mutex in the allotted time. A system restart is recommended because further use of the Restart Manager is likely to fail.");
- }
- else if (ex.ErrorCode == 1223)
- {
- SharedLogger.logger.Error(ex, $"WinLibrary/RestartExplorer: RestartManager was unable to restart Windows Explorer. ERROR_CANCELLED (1223): This error value is returned by the RmRestart function when the request to cancel an operation is successful.");
- }
- else if (ex.ErrorCode == 160)
- {
- SharedLogger.logger.Error(ex, $"WinLibrary/RestartExplorer: RestartManager was unable to restart Windows Explorer. ERROR_BAD_ARGUMENTS (160): One or more arguments are not correct. This error value is returned by the Restart Manager function if a NULL pointer or 0 is passed in a parameter that requires a non-null and non-zero value.");
- }
- else if (ex.ErrorCode == 29)
- {
- SharedLogger.logger.Error(ex, $"WinLibrary/RestartExplorer: RestartManager was unable to restart Windows Explorer. ERROR_WRITE_FAULT (29): An operation was unable to read or write to the registry.");
- }
- else if (ex.ErrorCode == 14)
- {
- SharedLogger.logger.Error(ex, $"WinLibrary/RestartExplorer: RestartManager was unable to restart Windows Explorer. ERROR_OUTOFMEMORY (14): A Restart Manager operation could not complete because not enough memory was available.");
- }
- else if (ex.ErrorCode == 6)
- {
- SharedLogger.logger.Error(ex, $"WinLibrary/RestartExplorer: RestartManager was unable to restart Windows Explorer. ERROR_INVALID_HANDLE (6): No Restart Manager session exists for the handle supplied.");
- }
- else
- {
- SharedLogger.logger.Error(ex, $"WinLibrary/RestartExplorer: RestartManager was unable to restart Windows Explorer. ErrorCode = {ex.ErrorCode}.");
- }
- return false;
- }
- catch (Exception ex)
- {
- SharedLogger.logger.Error(ex, $"WinLibrary/RestartExplorer: General exception when trying to restart Windows Explorer!");
- return false;
- }
-
- }
-
}
[global::System.Serializable]