diff --git a/DisplayMagician/DisplayMagician.csproj b/DisplayMagician/DisplayMagician.csproj index df2f162..e60086b 100644 --- a/DisplayMagician/DisplayMagician.csproj +++ b/DisplayMagician/DisplayMagician.csproj @@ -175,7 +175,6 @@ StartProgramControl.cs - @@ -315,9 +314,6 @@ 1.0.3-rc - - 1.3.0.13 - 1.6.0.4 diff --git a/DisplayMagician/DisplayRepresentation.cs b/DisplayMagician/DisplayRepresentation.cs deleted file mode 100644 index 85c7df2..0000000 --- a/DisplayMagician/DisplayRepresentation.cs +++ /dev/null @@ -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 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(); - - /*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); - } - } -} \ No newline at end of file diff --git a/DisplayMagician/Program.cs b/DisplayMagician/Program.cs index 61a2ffa..ba559bf 100644 --- a/DisplayMagician/Program.cs +++ b/DisplayMagician/Program.cs @@ -594,7 +594,7 @@ namespace DisplayMagician { 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 (profile.Driver.Equals("AMD")) + if (profile.VideoMode.Equals("AMD")) { // Now lets prepare a task to apply the profile in a separate thread diff --git a/DisplayMagician/UIForms/DisplayProfileForm.cs b/DisplayMagician/UIForms/DisplayProfileForm.cs index 5307740..0edc6bf 100644 --- a/DisplayMagician/UIForms/DisplayProfileForm.cs +++ b/DisplayMagician/UIForms/DisplayProfileForm.cs @@ -260,7 +260,7 @@ namespace DisplayMagician.UIForms lbl_profile_shown.Text = _selectedProfile.Name; // 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); } diff --git a/DisplayMagicianShared/AMD/AMDLibrary.cs b/DisplayMagicianShared/AMD/AMDLibrary.cs index 4b73b28..4464597 100644 --- a/DisplayMagicianShared/AMD/AMDLibrary.cs +++ b/DisplayMagicianShared/AMD/AMDLibrary.cs @@ -43,6 +43,7 @@ namespace DisplayMagicianShared.AMD public struct AMD_DISPLAY_CONFIG : IEquatable { public List AdapterConfigs; + public List DisplayIdentifiers; public bool Equals(AMD_DISPLAY_CONFIG other) => 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) { - /*// Get the all possible windows display configs - AMD_DISPLAY_CONFIG allWindowsDisplayConfig = GetAMDDisplayConfig(QDC.QDC_ALL_PATHS); + // We want to check the AMD profile can be used now + 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"); - // Firstly check that the Adapter Names are still currently available (i.e. the adapter hasn't been replaced). - foreach (string savedAdapterName in displayConfig.displayAdapters.Values) + // check what the currently available displays are (include the ones not active) + List currentAllIds = GetAllConnectedDisplayIdentifiers(); + + // 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 - // 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!"); + SharedLogger.logger.Trace($"AMDLibrary/IsPossibleConfig: Success! The AMD display configuration is possible to be used now"); return true; } 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 true; + } + } public List GetCurrentDisplayIdentifiers() diff --git a/DisplayMagicianShared/AMD/AMDProfileItem.cs b/DisplayMagicianShared/AMD/AMDProfileItem.cs index ca9ff0a..77ed95f 100644 --- a/DisplayMagicianShared/AMD/AMDProfileItem.cs +++ b/DisplayMagicianShared/AMD/AMDProfileItem.cs @@ -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; } @@ -183,7 +183,8 @@ namespace DisplayMagicianShared.AMD public override bool IsValid() { - if (ProfileIcon is ProfileIcon && + if (AMDLibrary.GetLibrary().IsValidConfig(_amdDisplayConfig) && + ProfileIcon is ProfileIcon && System.IO.File.Exists(SavedProfileIconCacheFilename) && ProfileBitmap is Bitmap && ProfileTightestBitmap is Bitmap && @@ -286,34 +287,55 @@ namespace DisplayMagicianShared.AMD // Now we create the screens structure from the AMD profile information _screens = new List(); - 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.Library = "AMD"; - screen.Name = display.DisplayName; - screen.DisplayConnector = display.DisplayConnector; - screen.ScreenX = mode.XPos; - screen.ScreenY = mode.YPos; - screen.ScreenWidth = mode.XRes; - screen.ScreenHeight = mode.YRes; + screen.Name = targetId.ToString(); + //screen.DisplayConnector = displayMode.DisplayConnector; + screen.ScreenX = displayMode.SourceMode.Position.X; + screen.ScreenY = displayMode.SourceMode.Position.Y; + screen.ScreenWidth = (int)displayMode.SourceMode.Width; + screen.ScreenHeight = (int)displayMode.SourceMode.Height; // If we're at the 0,0 coordinate then we're the primary monitor if (screen.ScreenX == 0 && screen.ScreenY == 0) { screen.IsPrimary = true; } + } + } + foreach (ADVANCED_HDR_INFO_PER_PATH hdrInfo in _windowsDisplayConfig.DisplayHDRStates) + { + // Find the matching HDR information + if (hdrInfo.Id == targetId) + { // HDR information - if (display.HDRSupported) + if (hdrInfo.AdvancedColorInfo.AdvancedColorSupported) { screen.HDRSupported = true; - if (display.HDREnabled) + if (hdrInfo.AdvancedColorInfo.AdvancedColorEnabled) { screen.HDREnabled = true; } @@ -321,40 +343,38 @@ namespace DisplayMagicianShared.AMD { screen.HDREnabled = false; } - + } else { screen.HDRSupported = 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; } @@ -382,190 +402,29 @@ namespace DisplayMagicianShared.AMD if (this.GetType() != other.GetType()) 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)) return false; - // If the WindowsDisplayConfig's equal each other + // If Windows Display Config is different then return false. if (!WindowsDisplayConfig.Equals(other.WindowsDisplayConfig)) return false; - // Check if the profile identifiers are not the same, then return false - int foundDICount = 0; - 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 - { - - 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)) + // If Display Identifiers are different then return false. + if (!ProfileDisplayIdentifiers.SequenceEqual(other.ProfileDisplayIdentifiers)) return false; + // Otherwise if all the tests work, then we're good! return true; } - // Modified the GetHashCode to compare the displayidentifier - public int GetHashCode(AMDProfileItem profile) + public override int GetHashCode() { - - // 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 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(); + // Calculate the hash code for the product. + return (AMDDisplayConfig, WindowsDisplayConfig, ProfileDisplayIdentifiers).GetHashCode(); } + } + } \ No newline at end of file diff --git a/DisplayMagicianShared/NVIDIA/NVIDIAProfileItem.cs b/DisplayMagicianShared/NVIDIA/NVIDIAProfileItem.cs index ad3d150..afcc9c4 100644 --- a/DisplayMagicianShared/NVIDIA/NVIDIAProfileItem.cs +++ b/DisplayMagicianShared/NVIDIA/NVIDIAProfileItem.cs @@ -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; } @@ -175,7 +175,7 @@ namespace DisplayMagicianShared.NVIDIA public override bool IsValid() { - if (Paths != null && + if (NVIDIALibrary.GetLibrary().IsValidConfig(_nvidiaDisplayConfig) && ProfileIcon is ProfileIcon && System.IO.File.Exists(SavedProfileIconCacheFilename) && ProfileBitmap is Bitmap && @@ -268,38 +268,58 @@ namespace DisplayMagicianShared.NVIDIA public override List GetScreenPositions() { - // Now we create the screens structure from the AMD profile information _screens = new List(); - 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.Library = "AMD"; - screen.Name = display.DisplayName; - screen.DisplayConnector = display.DisplayConnector; - screen.ScreenX = mode.XPos; - screen.ScreenY = mode.YPos; - screen.ScreenWidth = mode.XRes; - screen.ScreenHeight = mode.YRes; + screen.Name = targetId.ToString(); + //screen.DisplayConnector = displayMode.DisplayConnector; + screen.ScreenX = displayMode.SourceMode.Position.X; + screen.ScreenY = displayMode.SourceMode.Position.Y; + screen.ScreenWidth = (int)displayMode.SourceMode.Width; + screen.ScreenHeight = (int)displayMode.SourceMode.Height; // If we're at the 0,0 coordinate then we're the primary monitor if (screen.ScreenX == 0 && screen.ScreenY == 0) { screen.IsPrimary = true; } + } + } + foreach (ADVANCED_HDR_INFO_PER_PATH hdrInfo in _windowsDisplayConfig.DisplayHDRStates) + { + // Find the matching HDR information + if (hdrInfo.Id == targetId) + { // HDR information - if (display.HDRSupported) + if (hdrInfo.AdvancedColorInfo.AdvancedColorSupported) { screen.HDRSupported = true; - if (display.HDREnabled) + if (hdrInfo.AdvancedColorInfo.AdvancedColorEnabled) { screen.HDREnabled = true; } @@ -315,32 +335,26 @@ namespace DisplayMagicianShared.NVIDIA 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; } @@ -376,226 +390,23 @@ namespace DisplayMagicianShared.NVIDIA if (!WindowsDisplayConfig.Equals(other.WindowsDisplayConfig)) return false; - // Check if the profile identifiers are not the same, then return false - int foundDICount = 0; - foreach (string profileDI in ProfileDisplayIdentifiers) - { - - if (other.ProfileDisplayIdentifiers.Contains(profileDI)) - { - foundDICount++; - continue; - } - - } - - if (foundDICount != other.ProfileDisplayIdentifiers.Count) + // If Display Identifiers are different then return false. + if (!ProfileDisplayIdentifiers.SequenceEqual(other.ProfileDisplayIdentifiers)) 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 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; + // Otherwise if all the tests work, then we're good! + return true; } // 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 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. - 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 - { - // 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(); - - } - } } \ No newline at end of file diff --git a/DisplayMagicianShared/ProfileIcon.cs b/DisplayMagicianShared/ProfileIcon.cs index c067836..ead8b1e 100644 --- a/DisplayMagicianShared/ProfileIcon.cs +++ b/DisplayMagicianShared/ProfileIcon.cs @@ -5,9 +5,6 @@ using System.Drawing.Drawing2D; using System.Drawing.IconLib; using System.Drawing.Imaging; using System.Linq; -using System.Windows.Forms; -using DisplayMagicianShared.Topology; -//using static DisplayMagicianShared.ProfileItem; namespace DisplayMagicianShared { diff --git a/DisplayMagicianShared/ProfileItem.cs b/DisplayMagicianShared/ProfileItem.cs index 1d51441..39fa86b 100644 --- a/DisplayMagicianShared/ProfileItem.cs +++ b/DisplayMagicianShared/ProfileItem.cs @@ -181,7 +181,7 @@ namespace DisplayMagicianShared } } - public virtual string Driver { get; } = "Unknown"; + public virtual string VideoMode { get; } = "Unknown"; public Keys Hotkey { get diff --git a/DisplayMagicianShared/UserControls/DisplayView.cs b/DisplayMagicianShared/UserControls/DisplayView.cs index f3fdc66..7deb8d5 100644 --- a/DisplayMagicianShared/UserControls/DisplayView.cs +++ b/DisplayMagicianShared/UserControls/DisplayView.cs @@ -1,7 +1,6 @@ using System; using System.Drawing; using System.Windows.Forms; -using DisplayMagicianShared.Topology; namespace DisplayMagicianShared.UserControls { diff --git a/DisplayMagicianShared/Windows/WinProfileItem.cs b/DisplayMagicianShared/Windows/WinProfileItem.cs index c200068..c1c44a1 100644 --- a/DisplayMagicianShared/Windows/WinProfileItem.cs +++ b/DisplayMagicianShared/Windows/WinProfileItem.cs @@ -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; }