mirror of
https://github.com/terrymacdonald/DisplayMagician.git
synced 2024-08-30 18:32:20 +00:00
[WIP] Almost ready to test new libs
This commit is contained in:
parent
bd89993770
commit
998293621e
@ -175,7 +175,6 @@
|
|||||||
<DependentUpon>StartProgramControl.cs</DependentUpon>
|
<DependentUpon>StartProgramControl.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Validators.cs" />
|
<Compile Include="Validators.cs" />
|
||||||
<Compile Include="DisplayRepresentation.cs" />
|
|
||||||
<Compile Include="InterProcess\IPCClient.cs" />
|
<Compile Include="InterProcess\IPCClient.cs" />
|
||||||
<Compile Include="InterProcess\InstanceStatus.cs" />
|
<Compile Include="InterProcess\InstanceStatus.cs" />
|
||||||
<Compile Include="InterProcess\IService.cs" />
|
<Compile Include="InterProcess\IService.cs" />
|
||||||
@ -315,9 +314,6 @@
|
|||||||
<PackageReference Include="WinCopies.IconExtractor">
|
<PackageReference Include="WinCopies.IconExtractor">
|
||||||
<Version>1.0.3-rc</Version>
|
<Version>1.0.3-rc</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="WindowsDisplayAPI">
|
|
||||||
<Version>1.3.0.13</Version>
|
|
||||||
</PackageReference>
|
|
||||||
<PackageReference Include="WinFormAnimation">
|
<PackageReference Include="WinFormAnimation">
|
||||||
<Version>1.6.0.4</Version>
|
<Version>1.6.0.4</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
@ -1,140 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Drawing;
|
|
||||||
using System.Linq;
|
|
||||||
using DisplayMagicianShared;
|
|
||||||
using DisplayMagicianShared.Topology;
|
|
||||||
|
|
||||||
namespace DisplayMagician
|
|
||||||
{
|
|
||||||
internal class DisplayRepresentation
|
|
||||||
{
|
|
||||||
public DisplayRepresentation(Display display)
|
|
||||||
{
|
|
||||||
Name = display.DeviceName;
|
|
||||||
Path = display.DevicePath;
|
|
||||||
var index = Path.IndexOf("{", StringComparison.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
if (index > 0)
|
|
||||||
{
|
|
||||||
Path = Path.Substring(0, index).TrimEnd('#');
|
|
||||||
}
|
|
||||||
|
|
||||||
IsAvailable = display.IsAvailable;
|
|
||||||
|
|
||||||
if (IsAvailable)
|
|
||||||
{
|
|
||||||
PossibleSettings = GetDisplay()?.GetPossibleSettings()?.ToArray() ?? new DisplayPossibleSetting[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public DisplayRepresentation(PathTarget display)
|
|
||||||
{
|
|
||||||
Name = display.DisplayName;
|
|
||||||
Path = display.DevicePath;
|
|
||||||
IsAvailable = GetDisplay()?.IsAvailable ?? false;
|
|
||||||
|
|
||||||
if (IsAvailable)
|
|
||||||
{
|
|
||||||
PossibleSettings = GetDisplay()?.GetPossibleSettings()?.ToArray() ?? new DisplayPossibleSetting[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsAvailable { get; }
|
|
||||||
public string Name { get; }
|
|
||||||
public string Path { get; }
|
|
||||||
|
|
||||||
public DisplayPossibleSetting[] PossibleSettings { get; }
|
|
||||||
|
|
||||||
public static IEnumerable<DisplayRepresentation> GetDisplays(ProfileItem profile = null)
|
|
||||||
{
|
|
||||||
//var displays =
|
|
||||||
// Display.GetDisplays()
|
|
||||||
// .Select(display => new DisplayRepresentation(display))
|
|
||||||
// .OrderByDescending(representation => representation.IsAvailable)
|
|
||||||
// .GroupBy(representation => representation.Path)
|
|
||||||
// .Select(grouping => grouping.First()).ToList();
|
|
||||||
var displays = new List<DisplayRepresentation>();
|
|
||||||
|
|
||||||
/*if (profile != null)
|
|
||||||
{
|
|
||||||
foreach (var target in profile.Paths.SelectMany(path => path.TargetDisplays))
|
|
||||||
{
|
|
||||||
if (displays.All(display => display.Path != target.DevicePath))
|
|
||||||
{
|
|
||||||
displays.Add(new DisplayRepresentation(target));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
return displays;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Display GetDisplay()
|
|
||||||
{
|
|
||||||
return Display.GetDisplays().FirstOrDefault(display => display.DevicePath.StartsWith(Path));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*public Path GetPathSource(ProfileItem profile)
|
|
||||||
{
|
|
||||||
return profile.Paths.FirstOrDefault(path => path.TargetDisplays.Any(target => target.DevicePath == Path));
|
|
||||||
}
|
|
||||||
|
|
||||||
public PathTarget GetPathTarget(ProfileItem profile)
|
|
||||||
{
|
|
||||||
return profile.Paths.SelectMany(path => path.TargetDisplays).FirstOrDefault(target => target.DevicePath == Path);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
public PathDisplayTarget GetTargetInfo()
|
|
||||||
{
|
|
||||||
return
|
|
||||||
PathDisplayTarget.GetDisplayTargets()
|
|
||||||
.Where(target => target.DevicePath.StartsWith(Path))
|
|
||||||
.OrderByDescending(target => target.IsAvailable)
|
|
||||||
.FirstOrDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Bitmap ToBitmap(Size size, ProfileItem profile = null)
|
|
||||||
{
|
|
||||||
var targetInfo = GetTargetInfo();
|
|
||||||
var resolution = Size.Empty;
|
|
||||||
|
|
||||||
/*if (targetInfo != null && targetInfo.IsAvailable)
|
|
||||||
{
|
|
||||||
resolution = targetInfo.PreferredResolution;
|
|
||||||
}
|
|
||||||
else if (profile != null)
|
|
||||||
{
|
|
||||||
var targetPath = GetPathSource(profile);
|
|
||||||
|
|
||||||
if (targetPath != null)
|
|
||||||
{
|
|
||||||
resolution = targetPath.Resolution;
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
var p = new ProfileItem();
|
|
||||||
/*var p = new ProfileItem {Paths = new Path[1]};
|
|
||||||
|
|
||||||
p.Paths[0] = new Path
|
|
||||||
{
|
|
||||||
Resolution = resolution,
|
|
||||||
Position = new Point(),
|
|
||||||
TargetDisplays = new PathTarget[1]
|
|
||||||
};
|
|
||||||
p.Paths[0].TargetDisplays[0] = new PathTarget {DevicePath = Path};
|
|
||||||
|
|
||||||
if (profile != null)
|
|
||||||
{
|
|
||||||
var targetPath = GetPathTarget(profile);
|
|
||||||
|
|
||||||
if (targetPath != null)
|
|
||||||
{
|
|
||||||
p.Paths[0].TargetDisplays[0].SurroundTopology = targetPath.SurroundTopology;
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
return new ProfileIcon(p).ToBitmap(size.Width, size.Height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -594,7 +594,7 @@ namespace DisplayMagician {
|
|||||||
ApplyingProfileForm timeoutForm = new ApplyingProfileForm(null, 3, $"Changing to '{profile.Name}' Profile", "Press ESC to cancel", Color.Orange, true);
|
ApplyingProfileForm timeoutForm = new ApplyingProfileForm(null, 3, $"Changing to '{profile.Name}' Profile", "Press ESC to cancel", Color.Orange, true);
|
||||||
|
|
||||||
// If this is an AMD profile, then we need to set it up as such
|
// If this is an AMD profile, then we need to set it up as such
|
||||||
if (profile.Driver.Equals("AMD"))
|
if (profile.VideoMode.Equals("AMD"))
|
||||||
{
|
{
|
||||||
|
|
||||||
// Now lets prepare a task to apply the profile in a separate thread
|
// Now lets prepare a task to apply the profile in a separate thread
|
||||||
|
@ -260,7 +260,7 @@ namespace DisplayMagician.UIForms
|
|||||||
lbl_profile_shown.Text = _selectedProfile.Name;
|
lbl_profile_shown.Text = _selectedProfile.Name;
|
||||||
|
|
||||||
// And show the logo for the driver
|
// And show the logo for the driver
|
||||||
if (_selectedProfile.Driver == "AMD")
|
if (_selectedProfile.VideoMode == "AMD")
|
||||||
{
|
{
|
||||||
pbLogo.Image = PickBitmapBasedOnBgColour(BackColor, Properties.Resources.amdblack, Properties.Resources.amdwhite);
|
pbLogo.Image = PickBitmapBasedOnBgColour(BackColor, Properties.Resources.amdblack, Properties.Resources.amdwhite);
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,7 @@ namespace DisplayMagicianShared.AMD
|
|||||||
public struct AMD_DISPLAY_CONFIG : IEquatable<AMD_DISPLAY_CONFIG>
|
public struct AMD_DISPLAY_CONFIG : IEquatable<AMD_DISPLAY_CONFIG>
|
||||||
{
|
{
|
||||||
public List<AMD_ADAPTER_CONFIG> AdapterConfigs;
|
public List<AMD_ADAPTER_CONFIG> AdapterConfigs;
|
||||||
|
public List<string> DisplayIdentifiers;
|
||||||
|
|
||||||
public bool Equals(AMD_DISPLAY_CONFIG other)
|
public bool Equals(AMD_DISPLAY_CONFIG other)
|
||||||
=> AdapterConfigs.SequenceEqual(other.AdapterConfigs);
|
=> AdapterConfigs.SequenceEqual(other.AdapterConfigs);
|
||||||
@ -1054,45 +1055,232 @@ namespace DisplayMagicianShared.AMD
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsValidConfig(AMD_DISPLAY_CONFIG displayConfig)
|
||||||
|
{
|
||||||
|
// We want to check the NVIDIA Surround (Mosaic) config is valid
|
||||||
|
SharedLogger.logger.Trace($"NVIDIALibrary/IsValidConfig: Testing whether the display configuration is valid");
|
||||||
|
//
|
||||||
|
return true;
|
||||||
|
|
||||||
|
//if (displayConfig.MosaicConfig.IsMosaicEnabled)
|
||||||
|
//{
|
||||||
|
|
||||||
|
// ===================================================================================================================================
|
||||||
|
// Important! ValidateDisplayGrids does not work at the moment. It errors when supplied with a Grid Topology that works in SetDisplaGrids
|
||||||
|
// We therefore cannot use ValidateDisplayGrids to actually validate the config before it's use. We instead need to rely on SetDisplaGrids reporting an
|
||||||
|
// error if it is unable to apply the requested configuration. While this works fine, it's not optimal.
|
||||||
|
// TODO: Test ValidateDisplayGrids in a future NVIDIA driver release to see if they fixed it.
|
||||||
|
// ===================================================================================================================================
|
||||||
|
//return true;
|
||||||
|
|
||||||
|
/*// 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];
|
||||||
|
NV_MOSAIC_GRID_TOPO_V1[] mosaicGridTopos = new NV_MOSAIC_GRID_TOPO_V1[mosaicGridCount];
|
||||||
|
NVStatus = NVImport.NvAPI_Mosaic_EnumDisplayGrids(ref mosaicGridTopos, ref mosaicGridCount);
|
||||||
|
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}");
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*NV_MOSAIC_SETDISPLAYTOPO_FLAGS setTopoFlags = NV_MOSAIC_SETDISPLAYTOPO_FLAGS.NONE;
|
||||||
|
bool topoValid = false;
|
||||||
|
NV_MOSAIC_DISPLAY_TOPO_STATUS_V1[] topoStatuses = new NV_MOSAIC_DISPLAY_TOPO_STATUS_V1[displayConfig.MosaicConfig.MosaicGridCount];
|
||||||
|
NVAPI_STATUS NVStatus = NVImport.NvAPI_Mosaic_ValidateDisplayGrids(setTopoFlags, ref displayConfig.MosaicConfig.MosaicGridTopos, ref topoStatuses, displayConfig.MosaicConfig.MosaicGridCount);
|
||||||
|
//NV_MOSAIC_DISPLAY_TOPO_STATUS_V1[] topoStatuses = new NV_MOSAIC_DISPLAY_TOPO_STATUS_V1[mosaicGridCount];
|
||||||
|
//NVStatus = NVImport.NvAPI_Mosaic_ValidateDisplayGrids(setTopoFlags, ref mosaicGridTopos, ref topoStatuses, mosaicGridCount);
|
||||||
|
if (NVStatus == NVAPI_STATUS.NVAPI_OK)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfig: NvAPI_Mosaic_GetCurrentTopo returned OK.");
|
||||||
|
|
||||||
|
for (int i = 0; i < topoStatuses.Length; i++)
|
||||||
|
{
|
||||||
|
// If there is an error then we need to log it!
|
||||||
|
// And make it not be used
|
||||||
|
if (topoStatuses[i].ErrorFlags == NV_MOSAIC_DISPLAYCAPS_PROBLEM_FLAGS.OK)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfig: Congratulations! No error flags for GridTopology #{i}");
|
||||||
|
topoValid = true;
|
||||||
|
}
|
||||||
|
else if (topoStatuses[i].ErrorFlags == NV_MOSAIC_DISPLAYCAPS_PROBLEM_FLAGS.DISPLAY_ON_INVALID_GPU)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: Error with the GridTopology #{i}: Display is on an invalid GPU");
|
||||||
|
}
|
||||||
|
else if (topoStatuses[i].ErrorFlags == NV_MOSAIC_DISPLAYCAPS_PROBLEM_FLAGS.DISPLAY_ON_WRONG_CONNECTOR)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: Error with the GridTopology #{i}: Display is on the wrong connection. It was on a different connection when the display profile was saved.");
|
||||||
|
}
|
||||||
|
else if (topoStatuses[i].ErrorFlags == NV_MOSAIC_DISPLAYCAPS_PROBLEM_FLAGS.ECC_ENABLED)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: Error with the GridTopology #{i}: ECC has been enabled, and Mosaic/Surround doesn't work with ECC");
|
||||||
|
}
|
||||||
|
else if (topoStatuses[i].ErrorFlags == NV_MOSAIC_DISPLAYCAPS_PROBLEM_FLAGS.GPU_TOPOLOGY_NOT_SUPPORTED)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: Error with the GridTopology #{i}: This GPU topology is not supported.");
|
||||||
|
}
|
||||||
|
else if (topoStatuses[i].ErrorFlags == NV_MOSAIC_DISPLAYCAPS_PROBLEM_FLAGS.MISMATCHED_OUTPUT_TYPE)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: Error with the GridTopology #{i}: The output type has changed for the display. The display was connected through another output type when the display profile was saved.");
|
||||||
|
}
|
||||||
|
else if (topoStatuses[i].ErrorFlags == NV_MOSAIC_DISPLAYCAPS_PROBLEM_FLAGS.NOT_SUPPORTED)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: Error with the GridTopology #{i}: This Grid Topology is not supported on this video card.");
|
||||||
|
}
|
||||||
|
else if (topoStatuses[i].ErrorFlags == NV_MOSAIC_DISPLAYCAPS_PROBLEM_FLAGS.NO_COMMON_TIMINGS)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: Error with the GridTopology #{i}: Couldn't find common timings that suit all the displays in this Grid Topology.");
|
||||||
|
}
|
||||||
|
else if (topoStatuses[i].ErrorFlags == NV_MOSAIC_DISPLAYCAPS_PROBLEM_FLAGS.NO_DISPLAY_CONNECTED)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: Error with the GridTopology #{i}: No display connected.");
|
||||||
|
}
|
||||||
|
else if (topoStatuses[i].ErrorFlags == NV_MOSAIC_DISPLAYCAPS_PROBLEM_FLAGS.NO_EDID_AVAILABLE)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: Error with the GridTopology #{i}: Your display didn't provide any information when we attempted to query it. Your display either doesn't support support EDID querying or has it a fault. ");
|
||||||
|
}
|
||||||
|
else if (topoStatuses[i].ErrorFlags == NV_MOSAIC_DISPLAYCAPS_PROBLEM_FLAGS.NO_GPU_TOPOLOGY)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: Error with the GridTopology #{i}: There is no GPU topology provided.");
|
||||||
|
}
|
||||||
|
else if (topoStatuses[i].ErrorFlags == NV_MOSAIC_DISPLAYCAPS_PROBLEM_FLAGS.NO_SLI_BRIDGE)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Error($"NVIDIALibrary/SetActiveConfig: Error with the GridTopology #{i}: There is no SLI bridge, and there was one when the display profile was created.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// And now we also check to see if there are any warnings we also need to log
|
||||||
|
if (topoStatuses[i].WarningFlags == NV_MOSAIC_DISPLAYTOPO_WARNING_FLAGS.NONE)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfig: Congratulations! No warning flags for GridTopology #{i}");
|
||||||
|
}
|
||||||
|
else if (topoStatuses[i].WarningFlags == NV_MOSAIC_DISPLAYTOPO_WARNING_FLAGS.DISPLAY_POSITION)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Warn($"NVIDIALibrary/SetActiveConfig: Warning for the GridTopology #{i}: The display position has changed, and this may affect your display view.");
|
||||||
|
}
|
||||||
|
else if (topoStatuses[i].WarningFlags == NV_MOSAIC_DISPLAYTOPO_WARNING_FLAGS.DRIVER_RELOAD_REQUIRED)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Warn($"NVIDIALibrary/SetActiveConfig: Warning for the GridTopology #{i}: Your computer needs to be restarted before your NVIDIA device driver can use this Grid Topology.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (NVStatus == NVAPI_STATUS.NVAPI_NOT_SUPPORTED)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Warn($"NVIDIALibrary/SetActiveConfig: Mosaic is not supported with the existing hardware. NvAPI_Mosaic_ValidateDisplayGrids() returned error code {NVStatus}");
|
||||||
|
}
|
||||||
|
else if (NVStatus == NVAPI_STATUS.NVAPI_NO_ACTIVE_SLI_TOPOLOGY)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Warn($"NVIDIALibrary/SetActiveConfig: No matching GPU topologies could be found. NvAPI_Mosaic_ValidateDisplayGrids() returned error code {NVStatus}");
|
||||||
|
}
|
||||||
|
else if (NVStatus == NVAPI_STATUS.NVAPI_TOPO_NOT_POSSIBLE)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Warn($"NVIDIALibrary/SetActiveConfig: The topology passed in is not currently possible. NvAPI_Mosaic_ValidateDisplayGrids() returned error code {NVStatus}");
|
||||||
|
}
|
||||||
|
else if (NVStatus == NVAPI_STATUS.NVAPI_INVALID_ARGUMENT)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Warn($"NVIDIALibrary/SetActiveConfig: One or more argumentss passed in are invalid. NvAPI_Mosaic_ValidateDisplayGrids() returned error code {NVStatus}");
|
||||||
|
}
|
||||||
|
else if (NVStatus == NVAPI_STATUS.NVAPI_API_NOT_INITIALIZED)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Warn($"NVIDIALibrary/SetActiveConfig: The NvAPI API needs to be initialized first. NvAPI_Mosaic_ValidateDisplayGrids() returned error code {NVStatus}");
|
||||||
|
}
|
||||||
|
else if (NVStatus == NVAPI_STATUS.NVAPI_NO_IMPLEMENTATION)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Warn($"NVIDIALibrary/SetActiveConfig: This entry point not available in this NVIDIA Driver. NvAPI_Mosaic_ValidateDisplayGrids() returned error code {NVStatus}");
|
||||||
|
}
|
||||||
|
else if (NVStatus == NVAPI_STATUS.NVAPI_INCOMPATIBLE_STRUCT_VERSION)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Warn($"NVIDIALibrary/SetActiveConfig: The version of the structure passed in is not compatible with this entrypoint. NvAPI_Mosaic_ValidateDisplayGrids() returned error code {NVStatus}");
|
||||||
|
}
|
||||||
|
else if (NVStatus == NVAPI_STATUS.NVAPI_MODE_CHANGE_FAILED)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Warn($"NVIDIALibrary/SetActiveConfig: There was an error changing the display mode. NvAPI_Mosaic_ValidateDisplayGrids() returned error code {NVStatus}");
|
||||||
|
}
|
||||||
|
else if (NVStatus == NVAPI_STATUS.NVAPI_ERROR)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Warn($"NVIDIALibrary/SetActiveConfig: A miscellaneous error occurred. NvAPI_Mosaic_ValidateDisplayGrids() returned error code {NVStatus}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfig: Some non standard error occurred while getting Mosaic Topology! NvAPI_Mosaic_ValidateDisplayGrids() returned error code {NVStatus}");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Cancel the screen change if there was an error with anything above this.
|
||||||
|
if (topoValid)
|
||||||
|
{
|
||||||
|
// If there was an issue then we need to return false
|
||||||
|
// to indicate that the display profile can't be applied
|
||||||
|
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfig: The display settings are valid.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If there was an issue then we need to return false
|
||||||
|
// to indicate that the display profile can't be applied
|
||||||
|
SharedLogger.logger.Trace($"NVIDIALibrary/SetActiveConfig: There was an error when validating the requested grid topology that prevents us from using the display settings provided. THe display setttings are NOT valid.");
|
||||||
|
return false;
|
||||||
|
}*/
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
//{
|
||||||
|
// Its not a Mosaic topology, so we just let it pass, as it's windows settings that matter.
|
||||||
|
//return true;
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
public bool IsPossibleConfig(AMD_DISPLAY_CONFIG displayConfig)
|
public bool IsPossibleConfig(AMD_DISPLAY_CONFIG displayConfig)
|
||||||
{
|
{
|
||||||
/*// Get the all possible windows display configs
|
// We want to check the AMD profile can be used now
|
||||||
AMD_DISPLAY_CONFIG allWindowsDisplayConfig = GetAMDDisplayConfig(QDC.QDC_ALL_PATHS);
|
SharedLogger.logger.Trace($"AMDLibrary/IsPossibleConfig: Testing whether the AMD display configuration is possible to be used now");
|
||||||
|
|
||||||
SharedLogger.logger.Trace("AMDLibrary/PatchAdapterIDs: Going through the list of adapters we stored in the config to make sure they still exist");
|
// check what the currently available displays are (include the ones not active)
|
||||||
// Firstly check that the Adapter Names are still currently available (i.e. the adapter hasn't been replaced).
|
List<string> currentAllIds = GetAllConnectedDisplayIdentifiers();
|
||||||
foreach (string savedAdapterName in displayConfig.displayAdapters.Values)
|
|
||||||
|
// CHeck that we have all the displayConfig DisplayIdentifiers we need available now
|
||||||
|
if (displayConfig.DisplayIdentifiers.All(value => currentAllIds.Contains(value)))
|
||||||
|
//if (currentAllIds.Intersect(displayConfig.DisplayIdentifiers).Count() == displayConfig.DisplayIdentifiers.Count)
|
||||||
{
|
{
|
||||||
// If there is even one of the saved adapters that has changed, then it's no longer possible
|
SharedLogger.logger.Trace($"AMDLibrary/IsPossibleConfig: Success! The AMD display configuration is possible to be used now");
|
||||||
// to use this display config!
|
|
||||||
if (!allWindowsDisplayConfig.displayAdapters.Values.Contains(savedAdapterName))
|
|
||||||
{
|
|
||||||
SharedLogger.logger.Error($"AMDLibrary/PatchAdapterIDs: ERROR - Saved adapter {savedAdapterName} is not available right now! This display configuration won't work!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SharedLogger.logger.Trace($"AMDLibrary/PatchAdapterIDs: All teh adapters that the display configuration uses are still avilable to use now!");
|
|
||||||
|
|
||||||
// Now we go through the Paths to update the LUIDs as per Soroush's suggestion
|
|
||||||
SharedLogger.logger.Trace($"AMDLibrary/IsPossibleConfig: Attemptong to patch the saved display configuration's adapter IDs so that it will still work (these change at each boot)");
|
|
||||||
PatchAdapterIDs(ref displayConfig, allWindowsDisplayConfig.displayAdapters);
|
|
||||||
|
|
||||||
SharedLogger.logger.Trace($"AMDLibrary/IsPossibleConfig: Testing whether the display configuration is valid ");
|
|
||||||
// Test whether a specified display configuration is supported on the computer
|
|
||||||
uint myPathsCount = (uint)displayConfig.displayConfigPaths.Length;
|
|
||||||
uint myModesCount = (uint)displayConfig.displayConfigModes.Length;
|
|
||||||
WIN32STATUS err = CCDImport.SetDisplayConfig(myPathsCount, displayConfig.displayConfigPaths, myModesCount, displayConfig.displayConfigModes, SDC.DISPLAYMAGICIAN_VALIDATE);
|
|
||||||
if (err == WIN32STATUS.ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
SharedLogger.logger.Trace($"AMDLibrary/IsPossibleConfig: SetDisplayConfig validated that the display configuration is valid and can be used!");
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SharedLogger.logger.Trace($"AMDLibrary/IsPossibleConfig: SetDisplayConfig confirmed that the display configuration is invalid and cannot be used!");
|
SharedLogger.logger.Trace($"AMDLibrary/IsPossibleConfig: Uh oh! The AMD display configuration is possible cannot be used now");
|
||||||
return false;
|
return false;
|
||||||
}*/
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<string> GetCurrentDisplayIdentifiers()
|
public List<string> GetCurrentDisplayIdentifiers()
|
||||||
|
@ -63,7 +63,7 @@ namespace DisplayMagicianShared.AMD
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Driver { get; } = "AMD";
|
public override string VideoMode { get; } = "AMD";
|
||||||
|
|
||||||
public override string Name { get; set; }
|
public override string Name { get; set; }
|
||||||
|
|
||||||
@ -183,7 +183,8 @@ namespace DisplayMagicianShared.AMD
|
|||||||
public override bool IsValid()
|
public override bool IsValid()
|
||||||
{
|
{
|
||||||
|
|
||||||
if (ProfileIcon is ProfileIcon &&
|
if (AMDLibrary.GetLibrary().IsValidConfig(_amdDisplayConfig) &&
|
||||||
|
ProfileIcon is ProfileIcon &&
|
||||||
System.IO.File.Exists(SavedProfileIconCacheFilename) &&
|
System.IO.File.Exists(SavedProfileIconCacheFilename) &&
|
||||||
ProfileBitmap is Bitmap &&
|
ProfileBitmap is Bitmap &&
|
||||||
ProfileTightestBitmap is Bitmap &&
|
ProfileTightestBitmap is Bitmap &&
|
||||||
@ -286,34 +287,55 @@ namespace DisplayMagicianShared.AMD
|
|||||||
// Now we create the screens structure from the AMD profile information
|
// Now we create the screens structure from the AMD profile information
|
||||||
_screens = new List<ScreenPosition>();
|
_screens = new List<ScreenPosition>();
|
||||||
|
|
||||||
if ( _amdDisplayConfig.AdapterConfigs.Count > 0)
|
int pathCount = _windowsDisplayConfig.DisplayConfigPaths.Length;
|
||||||
|
// First of all we need to figure out how many display paths we have.
|
||||||
|
if (pathCount < 1)
|
||||||
{
|
{
|
||||||
foreach ( var adapter in _amdDisplayConfig.AdapterConfigs)
|
// Return an empty screen if we have no Display Config Paths to use!
|
||||||
|
return _screens;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var path in _windowsDisplayConfig.DisplayConfigPaths)
|
||||||
|
{
|
||||||
|
// For each path we go through and get the relevant info we need.
|
||||||
|
if (_windowsDisplayConfig.DisplayConfigPaths.Length > 0)
|
||||||
{
|
{
|
||||||
foreach (var display in adapter)
|
// Set some basics about the screen
|
||||||
|
ScreenPosition screen = new ScreenPosition();
|
||||||
|
screen.Library = "NVIDIA";
|
||||||
|
|
||||||
|
UInt32 targetId = path.TargetInfo.Id;
|
||||||
|
|
||||||
|
foreach (DISPLAYCONFIG_MODE_INFO displayMode in _windowsDisplayConfig.DisplayConfigModes)
|
||||||
{
|
{
|
||||||
foreach (var mode in display.DisplayModes)
|
// Find the matching Display Config Source Mode
|
||||||
|
if (displayMode.InfoType != DISPLAYCONFIG_MODE_INFO_TYPE.DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE && displayMode.Id == targetId)
|
||||||
{
|
{
|
||||||
ScreenPosition screen = new ScreenPosition();
|
screen.Name = targetId.ToString();
|
||||||
screen.Library = "AMD";
|
//screen.DisplayConnector = displayMode.DisplayConnector;
|
||||||
screen.Name = display.DisplayName;
|
screen.ScreenX = displayMode.SourceMode.Position.X;
|
||||||
screen.DisplayConnector = display.DisplayConnector;
|
screen.ScreenY = displayMode.SourceMode.Position.Y;
|
||||||
screen.ScreenX = mode.XPos;
|
screen.ScreenWidth = (int)displayMode.SourceMode.Width;
|
||||||
screen.ScreenY = mode.YPos;
|
screen.ScreenHeight = (int)displayMode.SourceMode.Height;
|
||||||
screen.ScreenWidth = mode.XRes;
|
|
||||||
screen.ScreenHeight = mode.YRes;
|
|
||||||
|
|
||||||
// If we're at the 0,0 coordinate then we're the primary monitor
|
// If we're at the 0,0 coordinate then we're the primary monitor
|
||||||
if (screen.ScreenX == 0 && screen.ScreenY == 0)
|
if (screen.ScreenX == 0 && screen.ScreenY == 0)
|
||||||
{
|
{
|
||||||
screen.IsPrimary = true;
|
screen.IsPrimary = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (ADVANCED_HDR_INFO_PER_PATH hdrInfo in _windowsDisplayConfig.DisplayHDRStates)
|
||||||
|
{
|
||||||
|
// Find the matching HDR information
|
||||||
|
if (hdrInfo.Id == targetId)
|
||||||
|
{
|
||||||
// HDR information
|
// HDR information
|
||||||
if (display.HDRSupported)
|
if (hdrInfo.AdvancedColorInfo.AdvancedColorSupported)
|
||||||
{
|
{
|
||||||
screen.HDRSupported = true;
|
screen.HDRSupported = true;
|
||||||
if (display.HDREnabled)
|
if (hdrInfo.AdvancedColorInfo.AdvancedColorEnabled)
|
||||||
{
|
{
|
||||||
screen.HDREnabled = true;
|
screen.HDREnabled = true;
|
||||||
}
|
}
|
||||||
@ -321,40 +343,38 @@ namespace DisplayMagicianShared.AMD
|
|||||||
{
|
{
|
||||||
screen.HDREnabled = false;
|
screen.HDREnabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
screen.HDRSupported = false;
|
screen.HDRSupported = false;
|
||||||
screen.HDREnabled = false;
|
screen.HDREnabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spanned screen options
|
|
||||||
if (display.IsEyefinity)
|
|
||||||
{
|
|
||||||
screen.IsSpanned = true;
|
|
||||||
screen.Colour = Color.FromArgb(200, 237, 28, 36); // represents AMD Red
|
|
||||||
screen.SpannedName = "AMD Eyefinity";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
screen.IsSpanned = false;
|
|
||||||
screen.Colour = Color.FromArgb(255, 195, 195, 195); // represents normal screen colour
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Figure out features
|
|
||||||
|
|
||||||
//ATI.ADL.ADL.ConvertDisplayModeFlags(mode.ModeValue);
|
|
||||||
|
|
||||||
//screen.Features = mode.ModeValue;
|
|
||||||
|
|
||||||
_screens.Add(screen);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Now we need to check for Spanned screens
|
||||||
|
/*if (_amdDisplayConfig)
|
||||||
|
{
|
||||||
|
screen.IsSpanned = true;
|
||||||
|
screen.Colour = Color.FromArgb(118, 185, 0); // represents NVIDIA Green
|
||||||
|
screen.SpannedName = "NVIDIA Surround/Mosaic";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
screen.IsSpanned = false;
|
||||||
|
screen.Colour = Color.FromArgb(195, 195, 195); // represents normal screen colour
|
||||||
|
}*/
|
||||||
|
|
||||||
|
screen.IsSpanned = false;
|
||||||
|
screen.Colour = Color.FromArgb(195, 195, 195); // represents normal screen colour
|
||||||
|
|
||||||
|
_screens.Add(screen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return _screens;
|
return _screens;
|
||||||
}
|
}
|
||||||
@ -382,190 +402,29 @@ namespace DisplayMagicianShared.AMD
|
|||||||
if (this.GetType() != other.GetType())
|
if (this.GetType() != other.GetType())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// If the AMDDisplayConfig's do not equal each other
|
// If AMD Display Config is different then return false.
|
||||||
if (!AMDDisplayConfig.Equals(other.AMDDisplayConfig))
|
if (!AMDDisplayConfig.Equals(other.AMDDisplayConfig))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// If the WindowsDisplayConfig's equal each other
|
// If Windows Display Config is different then return false.
|
||||||
if (!WindowsDisplayConfig.Equals(other.WindowsDisplayConfig))
|
if (!WindowsDisplayConfig.Equals(other.WindowsDisplayConfig))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Check if the profile identifiers are not the same, then return false
|
// If Display Identifiers are different then return false.
|
||||||
int foundDICount = 0;
|
if (!ProfileDisplayIdentifiers.SequenceEqual(other.ProfileDisplayIdentifiers))
|
||||||
foreach (string profileDI in ProfileDisplayIdentifiers)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (other.ProfileDisplayIdentifiers.Contains(profileDI))
|
|
||||||
{
|
|
||||||
foundDICount++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (foundDICount != other.ProfileDisplayIdentifiers.Count)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
foundDICount = 0;
|
|
||||||
foreach (string profileDI in other.ProfileDisplayIdentifiers)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (ProfileDisplayIdentifiers.Contains(profileDI))
|
|
||||||
{
|
|
||||||
foundDICount++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (foundDICount != ProfileDisplayIdentifiers.Count)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Check whether the profiles' properties are equal
|
|
||||||
// We need to exclude the name as the name is solely for saving to disk
|
|
||||||
// and displaying to the user.
|
|
||||||
// Two profiles are equal only when they have the same viewport data
|
|
||||||
// The data may be in different orders each run, so we need to compare them one by one
|
|
||||||
|
|
||||||
int foundPathsCount = 0;
|
|
||||||
int foundOtherPathsCount = 0;
|
|
||||||
|
|
||||||
// TODO: Make this work in AMD land
|
|
||||||
/*foreach (Topology.Path profilePath in Paths)
|
|
||||||
{
|
|
||||||
if (other.Paths.Contains(profilePath))
|
|
||||||
{
|
|
||||||
foundPathsCount++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
foreach (Topology.Path otherPath in other.Paths)
|
|
||||||
{
|
|
||||||
if (Paths.Contains(otherPath))
|
|
||||||
{
|
|
||||||
foundOtherPathsCount++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
|
|
||||||
if (foundPathsCount == foundOtherPathsCount)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If Equals() returns true for this object compared to another
|
|
||||||
// then GetHashCode() must return the same value for these objects.
|
|
||||||
/*public override int GetHashCode()
|
|
||||||
{
|
|
||||||
|
|
||||||
// Get hash code for the Viewports field if it is not null.
|
|
||||||
int hashPaths = Paths == null ? 0 : Paths.GetHashCode();
|
|
||||||
|
|
||||||
//Calculate the hash code for the product.
|
|
||||||
return hashPaths;
|
|
||||||
|
|
||||||
}*/
|
|
||||||
public override int GetHashCode()
|
|
||||||
{
|
|
||||||
|
|
||||||
// Get hash code for the ProfileDisplayIdentifiers field if it is not null.
|
|
||||||
int hashIds = ProfileDisplayIdentifiers == null ? 0 : ProfileDisplayIdentifiers.GetHashCode();
|
|
||||||
|
|
||||||
// Get AMD Profile Data too
|
|
||||||
int hashProfileAMDData = AMDDisplayConfig.GetHashCode();
|
|
||||||
|
|
||||||
// Get AMD Profile Data too
|
|
||||||
int hashProfileWindowsData = WindowsDisplayConfig.GetHashCode();
|
|
||||||
|
|
||||||
// Calculate the hash code for the product.
|
|
||||||
return (hashIds, hashProfileAMDData, hashProfileWindowsData).GetHashCode();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return (Name ?? Language.UN_TITLED_PROFILE);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Custom Equality comparer for the Profile class
|
|
||||||
// Allows us to use 'Contains'
|
|
||||||
class AMDProfileComparer : IEqualityComparer<AMDProfileItem>
|
|
||||||
{
|
|
||||||
|
|
||||||
public bool Equals(AMDProfileItem x, AMDProfileItem y)
|
|
||||||
{
|
|
||||||
|
|
||||||
//Check whether the compared objects reference the same data.
|
|
||||||
if (Object.ReferenceEquals(x, y)) return true;
|
|
||||||
|
|
||||||
//Check whether any of the compared objects is null.
|
|
||||||
if (x is null || y is null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Check if the profile identifiers are not the same, then return false
|
|
||||||
int foundDICount = 0;
|
|
||||||
foreach (string profileDI in x.ProfileDisplayIdentifiers)
|
|
||||||
{
|
|
||||||
if (y.ProfileDisplayIdentifiers.Contains(profileDI))
|
|
||||||
{
|
|
||||||
foundDICount++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
if (foundDICount != x.ProfileDisplayIdentifiers.Count)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
foundDICount = 0;
|
|
||||||
foreach (string profileDI in y.ProfileDisplayIdentifiers)
|
|
||||||
{
|
|
||||||
if (x.ProfileDisplayIdentifiers.Contains(profileDI))
|
|
||||||
{
|
|
||||||
foundDICount++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
if (foundDICount != y.ProfileDisplayIdentifiers.Count)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
|
|
||||||
// Now we need to check the AMD Display Configs themselves
|
|
||||||
if (!x.AMDDisplayConfig.Equals(y.AMDDisplayConfig))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Now we need to check the AMD Display Configs themselves
|
|
||||||
if (!x.WindowsDisplayConfig.Equals(y.WindowsDisplayConfig))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// Otherwise if all the tests work, then we're good!
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Modified the GetHashCode to compare the displayidentifier
|
public override int GetHashCode()
|
||||||
public int GetHashCode(AMDProfileItem profile)
|
|
||||||
{
|
{
|
||||||
|
// Calculate the hash code for the product.
|
||||||
// Check whether the object is null
|
return (AMDDisplayConfig, WindowsDisplayConfig, ProfileDisplayIdentifiers).GetHashCode();
|
||||||
if (profile is null) return 0;
|
|
||||||
|
|
||||||
// Get hash code for the ProfileDisplayIdentifiers field if it is not null.
|
|
||||||
int hashIds = profile.ProfileDisplayIdentifiers == null ? 0 : profile.ProfileDisplayIdentifiers.GetHashCode();
|
|
||||||
|
|
||||||
// Get hash code for the AMD Display Config
|
|
||||||
int hashProfileAMDData = profile.AMDDisplayConfig.GetHashCode();
|
|
||||||
|
|
||||||
// Get hash code for the Windows Display Config
|
|
||||||
int hashProfileWinData = profile.WindowsDisplayConfig.GetHashCode();
|
|
||||||
|
|
||||||
//Calculate the hash code for the product.
|
|
||||||
return (hashIds, hashProfileAMDData, hashProfileWinData).GetHashCode();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -64,7 +64,7 @@ namespace DisplayMagicianShared.NVIDIA
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Driver { get; } = "NVIDIA";
|
public override string VideoMode { get; } = "NVIDIA";
|
||||||
|
|
||||||
public override string Name { get; set; }
|
public override string Name { get; set; }
|
||||||
|
|
||||||
@ -175,7 +175,7 @@ namespace DisplayMagicianShared.NVIDIA
|
|||||||
public override bool IsValid()
|
public override bool IsValid()
|
||||||
{
|
{
|
||||||
|
|
||||||
if (Paths != null &&
|
if (NVIDIALibrary.GetLibrary().IsValidConfig(_nvidiaDisplayConfig) &&
|
||||||
ProfileIcon is ProfileIcon &&
|
ProfileIcon is ProfileIcon &&
|
||||||
System.IO.File.Exists(SavedProfileIconCacheFilename) &&
|
System.IO.File.Exists(SavedProfileIconCacheFilename) &&
|
||||||
ProfileBitmap is Bitmap &&
|
ProfileBitmap is Bitmap &&
|
||||||
@ -268,38 +268,58 @@ namespace DisplayMagicianShared.NVIDIA
|
|||||||
|
|
||||||
public override List<ScreenPosition> GetScreenPositions()
|
public override List<ScreenPosition> GetScreenPositions()
|
||||||
{
|
{
|
||||||
|
|
||||||
// Now we create the screens structure from the AMD profile information
|
// Now we create the screens structure from the AMD profile information
|
||||||
_screens = new List<ScreenPosition>();
|
_screens = new List<ScreenPosition>();
|
||||||
|
|
||||||
if (_displayConfig.Count > 0)
|
int pathCount = _windowsDisplayConfig.DisplayConfigPaths.Length;
|
||||||
|
// First of all we need to figure out how many display paths we have.
|
||||||
|
if (pathCount < 1)
|
||||||
{
|
{
|
||||||
foreach (var adapter in _displayConfig.AdapterConfigs)
|
// Return an empty screen if we have no Display Config Paths to use!
|
||||||
|
return _screens;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var path in _windowsDisplayConfig.DisplayConfigPaths)
|
||||||
|
{
|
||||||
|
// For each path we go through and get the relevant info we need.
|
||||||
|
if (_windowsDisplayConfig.DisplayConfigPaths.Length > 0)
|
||||||
{
|
{
|
||||||
foreach (var display in adapter.Displays)
|
// Set some basics about the screen
|
||||||
|
ScreenPosition screen = new ScreenPosition();
|
||||||
|
screen.Library = "NVIDIA";
|
||||||
|
|
||||||
|
UInt32 targetId = path.TargetInfo.Id;
|
||||||
|
|
||||||
|
foreach (DISPLAYCONFIG_MODE_INFO displayMode in _windowsDisplayConfig.DisplayConfigModes)
|
||||||
{
|
{
|
||||||
foreach (var mode in display.DisplayModes)
|
// Find the matching Display Config Source Mode
|
||||||
|
if (displayMode.InfoType != DISPLAYCONFIG_MODE_INFO_TYPE.DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE && displayMode.Id == targetId)
|
||||||
{
|
{
|
||||||
ScreenPosition screen = new ScreenPosition();
|
screen.Name = targetId.ToString();
|
||||||
screen.Library = "AMD";
|
//screen.DisplayConnector = displayMode.DisplayConnector;
|
||||||
screen.Name = display.DisplayName;
|
screen.ScreenX = displayMode.SourceMode.Position.X;
|
||||||
screen.DisplayConnector = display.DisplayConnector;
|
screen.ScreenY = displayMode.SourceMode.Position.Y;
|
||||||
screen.ScreenX = mode.XPos;
|
screen.ScreenWidth = (int)displayMode.SourceMode.Width;
|
||||||
screen.ScreenY = mode.YPos;
|
screen.ScreenHeight = (int)displayMode.SourceMode.Height;
|
||||||
screen.ScreenWidth = mode.XRes;
|
|
||||||
screen.ScreenHeight = mode.YRes;
|
|
||||||
|
|
||||||
// If we're at the 0,0 coordinate then we're the primary monitor
|
// If we're at the 0,0 coordinate then we're the primary monitor
|
||||||
if (screen.ScreenX == 0 && screen.ScreenY == 0)
|
if (screen.ScreenX == 0 && screen.ScreenY == 0)
|
||||||
{
|
{
|
||||||
screen.IsPrimary = true;
|
screen.IsPrimary = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (ADVANCED_HDR_INFO_PER_PATH hdrInfo in _windowsDisplayConfig.DisplayHDRStates)
|
||||||
|
{
|
||||||
|
// Find the matching HDR information
|
||||||
|
if (hdrInfo.Id == targetId)
|
||||||
|
{
|
||||||
// HDR information
|
// HDR information
|
||||||
if (display.HDRSupported)
|
if (hdrInfo.AdvancedColorInfo.AdvancedColorSupported)
|
||||||
{
|
{
|
||||||
screen.HDRSupported = true;
|
screen.HDRSupported = true;
|
||||||
if (display.HDREnabled)
|
if (hdrInfo.AdvancedColorInfo.AdvancedColorEnabled)
|
||||||
{
|
{
|
||||||
screen.HDREnabled = true;
|
screen.HDREnabled = true;
|
||||||
}
|
}
|
||||||
@ -315,32 +335,26 @@ namespace DisplayMagicianShared.NVIDIA
|
|||||||
screen.HDREnabled = false;
|
screen.HDREnabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spanned screen options
|
|
||||||
if (display.IsEyefinity)
|
|
||||||
{
|
|
||||||
screen.IsSpanned = true;
|
|
||||||
screen.Colour = Color.FromArgb(200, 237, 28, 36); // represents AMD Red
|
|
||||||
screen.SpannedName = "AMD Eyefinity";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
screen.IsSpanned = false;
|
|
||||||
screen.Colour = Color.FromArgb(255, 195, 195, 195); // represents normal screen colour
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Figure out features
|
|
||||||
|
|
||||||
//ATI.ADL.ADL.ConvertDisplayModeFlags(mode.ModeValue);
|
|
||||||
|
|
||||||
//screen.Features = mode.ModeValue;
|
|
||||||
|
|
||||||
_screens.Add(screen);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
// Now we need to check for Spanned screens
|
||||||
|
if (_nvidiaDisplayConfig.MosaicConfig.IsMosaicEnabled)
|
||||||
|
{
|
||||||
|
screen.IsSpanned = true;
|
||||||
|
screen.Colour = Color.FromArgb(118, 185, 0); // represents NVIDIA Green
|
||||||
|
screen.SpannedName = "NVIDIA Surround/Mosaic";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
screen.IsSpanned = false;
|
||||||
|
screen.Colour = Color.FromArgb(195, 195, 195); // represents normal screen colour
|
||||||
|
}
|
||||||
|
|
||||||
|
_screens.Add(screen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return _screens;
|
return _screens;
|
||||||
}
|
}
|
||||||
@ -376,226 +390,23 @@ namespace DisplayMagicianShared.NVIDIA
|
|||||||
if (!WindowsDisplayConfig.Equals(other.WindowsDisplayConfig))
|
if (!WindowsDisplayConfig.Equals(other.WindowsDisplayConfig))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Check if the profile identifiers are not the same, then return false
|
// If Display Identifiers are different then return false.
|
||||||
int foundDICount = 0;
|
if (!ProfileDisplayIdentifiers.SequenceEqual(other.ProfileDisplayIdentifiers))
|
||||||
foreach (string profileDI in ProfileDisplayIdentifiers)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (other.ProfileDisplayIdentifiers.Contains(profileDI))
|
|
||||||
{
|
|
||||||
foundDICount++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (foundDICount != other.ProfileDisplayIdentifiers.Count)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
foundDICount = 0;
|
// Otherwise if all the tests work, then we're good!
|
||||||
foreach (string profileDI in other.ProfileDisplayIdentifiers)
|
return true;
|
||||||
{
|
|
||||||
|
|
||||||
if (ProfileDisplayIdentifiers.Contains(profileDI))
|
|
||||||
{
|
|
||||||
foundDICount++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (foundDICount != ProfileDisplayIdentifiers.Count)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Check whether the profiles' properties are equal
|
|
||||||
// We need to exclude the name as the name is solely for saving to disk
|
|
||||||
// and displaying to the user.
|
|
||||||
// Two profiles are equal only when they have the same viewport data
|
|
||||||
// The data may be in different orders each run, so we need to compare them one by one
|
|
||||||
|
|
||||||
int foundPathsCount = 0;
|
|
||||||
int foundOtherPathsCount = 0;
|
|
||||||
|
|
||||||
// TODO: Make this work in NVIDIA land
|
|
||||||
foreach (Topology.Path profilePath in Paths)
|
|
||||||
{
|
|
||||||
if (other.Paths.Contains(profilePath))
|
|
||||||
{
|
|
||||||
foundPathsCount++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
foreach (Topology.Path otherPath in other.Paths)
|
|
||||||
{
|
|
||||||
if (Paths.Contains(otherPath))
|
|
||||||
{
|
|
||||||
foundOtherPathsCount++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (foundPathsCount == foundOtherPathsCount)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If Equals() returns true for this object compared to another
|
// If Equals() returns true for this object compared to another
|
||||||
// then GetHashCode() must return the same value for these objects.
|
// then GetHashCode() must return the same value for these objects.
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
{
|
{
|
||||||
|
|
||||||
// Get hash code for the ProfileDisplayIdentifiers field if it is not null.
|
|
||||||
int hashIds = ProfileDisplayIdentifiers == null ? 0 : ProfileDisplayIdentifiers.GetHashCode();
|
|
||||||
|
|
||||||
// Get ProfileData too
|
|
||||||
int hashProfileData = Paths == null ? 0 : Paths.GetHashCode();
|
|
||||||
|
|
||||||
// Calculate the hash code for the product.
|
// Calculate the hash code for the product.
|
||||||
return (hashIds, hashProfileData).GetHashCode();
|
return (NVIDIADisplayConfig, WindowsDisplayConfig, ProfileDisplayIdentifiers).GetHashCode();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return (Name ?? Language.UN_TITLED_PROFILE);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Custom Equality comparer for the Profile class
|
|
||||||
// Allows us to use 'Contains'
|
|
||||||
class NVIDIAProfileComparer : IEqualityComparer<NVIDIAProfileItem>
|
|
||||||
{
|
|
||||||
// Products are equal if their names and product numbers are equal.
|
|
||||||
/*public bool Equals(NVIDIAProfileItem x, NVIDIAProfileItem y)
|
|
||||||
{
|
|
||||||
|
|
||||||
//Check whether the compared objects reference the same data.
|
|
||||||
if (Object.ReferenceEquals(x, y)) return true;
|
|
||||||
|
|
||||||
//Check whether any of the compared objects is null.
|
|
||||||
if (x is null || y is null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Check whether the profiles' properties are equal
|
|
||||||
// We need to exclude the name as the name is solely for saving to disk
|
|
||||||
// and displaying to the user.
|
|
||||||
// Two profiles are equal only when they have the same viewport data
|
|
||||||
if (x.Paths.SequenceEqual(y.Paths))
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
public bool Equals(NVIDIAProfileItem x, NVIDIAProfileItem y)
|
|
||||||
{
|
|
||||||
|
|
||||||
//Check whether the compared objects reference the same data.
|
|
||||||
if (Object.ReferenceEquals(x, y)) return true;
|
|
||||||
|
|
||||||
//Check whether any of the compared objects is null.
|
|
||||||
if (x is null || y is null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (x.Paths.Length != y.Paths.Length)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Check if the profile identifiers are not the same, then return false
|
|
||||||
int foundDICount = 0;
|
|
||||||
foreach (string profileDI in x.ProfileDisplayIdentifiers)
|
|
||||||
{
|
|
||||||
if (y.ProfileDisplayIdentifiers.Contains(profileDI))
|
|
||||||
{
|
|
||||||
foundDICount++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
if (foundDICount != x.ProfileDisplayIdentifiers.Count)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
foundDICount = 0;
|
|
||||||
foreach (string profileDI in y.ProfileDisplayIdentifiers)
|
|
||||||
{
|
|
||||||
if (x.ProfileDisplayIdentifiers.Contains(profileDI))
|
|
||||||
{
|
|
||||||
foundDICount++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
if (foundDICount != y.ProfileDisplayIdentifiers.Count)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
|
|
||||||
// Check whether the profiles' properties are equal
|
|
||||||
// We need to exclude the name as the name is solely for saving to disk
|
|
||||||
// and displaying to the user.
|
|
||||||
// Two profiles are equal only when they have the same viewport data
|
|
||||||
int foundPathsCount = 0;
|
|
||||||
int foundOtherPathsCount = 0;
|
|
||||||
|
|
||||||
// TODO: Fix this so it finds compares ProfileData
|
|
||||||
foreach (Topology.Path profilePath in x.Paths)
|
|
||||||
{
|
|
||||||
if (y.Paths.Contains(profilePath))
|
|
||||||
{
|
|
||||||
foundPathsCount++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
foreach (Topology.Path otherPath in y.Paths)
|
|
||||||
{
|
|
||||||
if (x.Paths.Contains(otherPath))
|
|
||||||
{
|
|
||||||
foundOtherPathsCount++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (foundPathsCount == foundOtherPathsCount)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If Equals() returns true for a pair of objects
|
|
||||||
// then GetHashCode() must return the same value for these objects.
|
|
||||||
/*public int GetHashCode(NVIDIAProfileItem profile)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Check whether the object is null
|
|
||||||
if (profile is null) return 0;
|
|
||||||
|
|
||||||
// Get hash code for the Viewports field if it is not null.
|
|
||||||
int hashPaths = profile.Paths == null ? 0 : profile.Paths.GetHashCode();
|
|
||||||
|
|
||||||
//Calculate the hash code for the product.
|
|
||||||
return hashPaths;
|
|
||||||
|
|
||||||
}*/
|
|
||||||
// Modified the GetHashCode to compare the displayidentifier
|
|
||||||
public int GetHashCode(NVIDIAProfileItem profile)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Check whether the object is null
|
|
||||||
if (profile is null) return 0;
|
|
||||||
|
|
||||||
// Get hash code for the ProfileDisplayIdentifiers field if it is not null.
|
|
||||||
int hashIds = profile.ProfileDisplayIdentifiers == null ? 0 : profile.ProfileDisplayIdentifiers.GetHashCode();
|
|
||||||
|
|
||||||
// Get hash code for the Paths
|
|
||||||
int hashPaths = profile.Paths == null ? 0 : profile.Paths.GetHashCode();
|
|
||||||
|
|
||||||
//Calculate the hash code for the product.
|
|
||||||
return (hashIds, hashPaths).GetHashCode();
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -5,9 +5,6 @@ using System.Drawing.Drawing2D;
|
|||||||
using System.Drawing.IconLib;
|
using System.Drawing.IconLib;
|
||||||
using System.Drawing.Imaging;
|
using System.Drawing.Imaging;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Windows.Forms;
|
|
||||||
using DisplayMagicianShared.Topology;
|
|
||||||
//using static DisplayMagicianShared.ProfileItem;
|
|
||||||
|
|
||||||
namespace DisplayMagicianShared
|
namespace DisplayMagicianShared
|
||||||
{
|
{
|
||||||
|
@ -181,7 +181,7 @@ namespace DisplayMagicianShared
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual string Driver { get; } = "Unknown";
|
public virtual string VideoMode { get; } = "Unknown";
|
||||||
|
|
||||||
public Keys Hotkey {
|
public Keys Hotkey {
|
||||||
get
|
get
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using DisplayMagicianShared.Topology;
|
|
||||||
|
|
||||||
namespace DisplayMagicianShared.UserControls
|
namespace DisplayMagicianShared.UserControls
|
||||||
{
|
{
|
||||||
|
@ -100,7 +100,7 @@ namespace DisplayMagicianShared.Windows
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Driver { get; } = "AMD";
|
public override string VideoMode { get; } = "AMD";
|
||||||
|
|
||||||
public override string Name { get; set; }
|
public override string Name { get; set; }
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user