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]