mirror of
https://github.com/terrymacdonald/DisplayMagician.git
synced 2024-08-30 18:32:20 +00:00
Initial NVIDIA, AMD and CCD Integration
Putting the current libraries into DisplaayMagician so I can work on the logic.
This commit is contained in:
parent
0123e061e0
commit
4d1f074f42
@ -42,26 +42,18 @@ namespace DisplayMagicianShared.AMD
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct AMD_DISPLAY_CONFIG : IEquatable<AMD_DISPLAY_CONFIG>
|
||||
{
|
||||
//public Dictionary<ulong, string> DisplayAdapters;
|
||||
public List<AMD_ADAPTER_CONFIG> AdapterConfigs;
|
||||
//public DISPLAYCONFIG_MODE_INFO[] DisplayConfigModes;
|
||||
//public ADVANCED_HDR_INFO_PER_PATH[] DisplayHDRStates;
|
||||
public WINDOWS_DISPLAY_CONFIG WindowsDisplayConfig;
|
||||
|
||||
public bool Equals(AMD_DISPLAY_CONFIG other)
|
||||
=> AdapterConfigs.SequenceEqual(other.AdapterConfigs) &&
|
||||
//DisplayConfigPaths.SequenceEqual(other.DisplayConfigPaths) &&
|
||||
//DisplayConfigModes.SequenceEqual(other.DisplayConfigModes) &&
|
||||
//DisplayHDRStates.SequenceEqual(other.DisplayHDRStates) &&
|
||||
WindowsDisplayConfig.Equals(other.WindowsDisplayConfig);
|
||||
=> AdapterConfigs.SequenceEqual(other.AdapterConfigs);
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return (AdapterConfigs, WindowsDisplayConfig).GetHashCode();
|
||||
return (AdapterConfigs).GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
public class AMDLibrary : IDisposable
|
||||
class AMDLibrary : IDisposable
|
||||
{
|
||||
|
||||
// Static members are 'eagerly initialized', that is,
|
||||
@ -172,6 +164,15 @@ namespace DisplayMagicianShared.AMD
|
||||
}
|
||||
}
|
||||
|
||||
public List<string> PCIVendorIDs
|
||||
{
|
||||
get
|
||||
{
|
||||
// A list of all the matching PCI Vendor IDs are per https://www.pcilookup.com/?ven=amd&dev=&action=submit
|
||||
return new List<string>() { "1002" };
|
||||
}
|
||||
}
|
||||
|
||||
public static AMDLibrary GetLibrary()
|
||||
{
|
||||
return _instance;
|
||||
@ -556,10 +557,6 @@ namespace DisplayMagicianShared.AMD
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// We want to get the Windows CCD information and store it for later so that we record
|
||||
// display sizes, and screen positions and the like.
|
||||
myDisplayConfig.WindowsDisplayConfig = _winLibrary.GetActiveConfig();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
84
DisplayMagicianShared/NVIDIA/PInvokeDelegateFactory.cs
Normal file
84
DisplayMagicianShared/NVIDIA/PInvokeDelegateFactory.cs
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
Copyright (C) 2009-2012 Michael Möller <mmoeller@openhardwaremonitor.org>
|
||||
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace DisplayMagicianShared.NVIDIA
|
||||
{
|
||||
internal static class PInvokeDelegateFactory
|
||||
{
|
||||
|
||||
private static readonly ModuleBuilder moduleBuilder =
|
||||
AppDomain.CurrentDomain.DefineDynamicAssembly(
|
||||
new AssemblyName("PInvokeDelegateFactoryInternalAssembly"),
|
||||
AssemblyBuilderAccess.Run).DefineDynamicModule(
|
||||
"PInvokeDelegateFactoryInternalModule");
|
||||
|
||||
private static readonly IDictionary<KeyValuePair<DllImportAttribute, Type>, Type> wrapperTypes =
|
||||
new Dictionary<KeyValuePair<DllImportAttribute, Type>, Type>();
|
||||
|
||||
public static void CreateDelegate<T>(DllImportAttribute dllImportAttribute,
|
||||
out T newDelegate) where T : class
|
||||
{
|
||||
Type wrapperType;
|
||||
KeyValuePair<DllImportAttribute, Type> key = new KeyValuePair<DllImportAttribute, Type>(dllImportAttribute, typeof(T));
|
||||
|
||||
wrapperTypes.TryGetValue(key, out wrapperType);
|
||||
|
||||
if (wrapperType == null)
|
||||
{
|
||||
wrapperType = CreateWrapperType(typeof(T), dllImportAttribute);
|
||||
wrapperTypes.Add(key, wrapperType);
|
||||
}
|
||||
|
||||
newDelegate = Delegate.CreateDelegate(typeof(T), wrapperType,
|
||||
dllImportAttribute.EntryPoint) as T;
|
||||
}
|
||||
|
||||
|
||||
private static Type CreateWrapperType(Type delegateType,
|
||||
DllImportAttribute dllImportAttribute)
|
||||
{
|
||||
|
||||
TypeBuilder typeBuilder = moduleBuilder.DefineType(
|
||||
"PInvokeDelegateFactoryInternalWrapperType" + wrapperTypes.Count);
|
||||
|
||||
MethodInfo methodInfo = delegateType.GetMethod("Invoke");
|
||||
|
||||
ParameterInfo[] parameterInfos = methodInfo.GetParameters();
|
||||
int parameterCount = parameterInfos.GetLength(0);
|
||||
|
||||
Type[] parameterTypes = new Type[parameterCount];
|
||||
for (int i = 0; i < parameterCount; i++)
|
||||
parameterTypes[i] = parameterInfos[i].ParameterType;
|
||||
|
||||
MethodBuilder methodBuilder = typeBuilder.DefinePInvokeMethod(
|
||||
dllImportAttribute.EntryPoint, dllImportAttribute.Value,
|
||||
MethodAttributes.Public | MethodAttributes.Static |
|
||||
MethodAttributes.PinvokeImpl, CallingConventions.Standard,
|
||||
methodInfo.ReturnType, parameterTypes,
|
||||
dllImportAttribute.CallingConvention,
|
||||
dllImportAttribute.CharSet);
|
||||
|
||||
foreach (ParameterInfo parameterInfo in parameterInfos)
|
||||
methodBuilder.DefineParameter(parameterInfo.Position + 1,
|
||||
parameterInfo.Attributes, parameterInfo.Name);
|
||||
|
||||
if (dllImportAttribute.PreserveSig)
|
||||
methodBuilder.SetImplementationFlags(MethodImplAttributes.PreserveSig);
|
||||
|
||||
return typeBuilder.CreateType();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,96 +0,0 @@
|
||||
using NvAPIWrapper.Native.Display;
|
||||
using NvAPIWrapper.Native.Mosaic;
|
||||
|
||||
namespace DisplayMagicianShared.NVIDIA
|
||||
{
|
||||
internal static class SurroundHelper
|
||||
{
|
||||
public static PixelShift ToPixelShift(this PixelShiftType pixelShift)
|
||||
{
|
||||
switch (pixelShift)
|
||||
{
|
||||
case PixelShiftType.TopLeft2X2Pixels:
|
||||
|
||||
return PixelShift.TopLeft2X2Pixels;
|
||||
|
||||
case PixelShiftType.BottomRight2X2Pixels:
|
||||
|
||||
return PixelShift.BottomRight2X2Pixels;
|
||||
|
||||
default:
|
||||
|
||||
return PixelShift.NoPixelShift;
|
||||
}
|
||||
}
|
||||
|
||||
public static PixelShiftType ToPixelShiftType(this PixelShift pixelShift)
|
||||
{
|
||||
switch (pixelShift)
|
||||
{
|
||||
case PixelShift.TopLeft2X2Pixels:
|
||||
|
||||
return PixelShiftType.TopLeft2X2Pixels;
|
||||
|
||||
case PixelShift.BottomRight2X2Pixels:
|
||||
|
||||
return PixelShiftType.BottomRight2X2Pixels;
|
||||
|
||||
default:
|
||||
|
||||
return PixelShiftType.NoPixelShift;
|
||||
}
|
||||
}
|
||||
|
||||
public static Rotate ToRotate(this Rotation rotation)
|
||||
{
|
||||
switch (rotation)
|
||||
{
|
||||
case Rotation.Identity:
|
||||
|
||||
return Rotate.Degree0;
|
||||
|
||||
case Rotation.Rotate90:
|
||||
|
||||
return Rotate.Degree90;
|
||||
|
||||
case Rotation.Rotate180:
|
||||
|
||||
return Rotate.Degree180;
|
||||
|
||||
case Rotation.Rotate270:
|
||||
|
||||
return Rotate.Degree270;
|
||||
|
||||
default:
|
||||
|
||||
return Rotate.Ignored;
|
||||
}
|
||||
}
|
||||
|
||||
public static Rotation ToRotation(this Rotate rotation)
|
||||
{
|
||||
switch (rotation)
|
||||
{
|
||||
case Rotate.Degree0:
|
||||
|
||||
return Rotation.Identity;
|
||||
|
||||
case Rotate.Degree90:
|
||||
|
||||
return Rotation.Rotate90;
|
||||
|
||||
case Rotate.Degree180:
|
||||
|
||||
return Rotation.Rotate180;
|
||||
|
||||
case Rotate.Degree270:
|
||||
|
||||
return Rotation.Rotate270;
|
||||
|
||||
default:
|
||||
|
||||
return Rotation.Unknown;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,438 +0,0 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using WindowsDisplayAPI.DisplayConfig;
|
||||
using NvAPIWrapper.Mosaic;
|
||||
using NvAPIWrapper.Native.Interfaces.Mosaic;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DisplayMagicianShared.NVIDIA
|
||||
{
|
||||
public class SurroundTopology
|
||||
{
|
||||
public SurroundTopology(GridTopology topology)
|
||||
{
|
||||
Rows = topology.Rows;
|
||||
Columns = topology.Columns;
|
||||
Resolution = new Size(topology.Resolution.Width, topology.Resolution.Height);
|
||||
ColorDepth = topology.Resolution.ColorDepth;
|
||||
Frequency = topology.Frequency;
|
||||
Displays =
|
||||
topology.Displays.Where(
|
||||
display =>
|
||||
Resolution.Width > display.Overlap.HorizontalOverlap &&
|
||||
Resolution.Height > display.Overlap.VerticalOverlap)
|
||||
.Select(display => new SurroundTopologyDisplay(display))
|
||||
.ToArray();
|
||||
ApplyWithBezelCorrectedResolution = topology.ApplyWithBezelCorrectedResolution;
|
||||
ImmersiveGaming = topology.ImmersiveGaming;
|
||||
BaseMosaicPanoramic = topology.BaseMosaicPanoramic;
|
||||
DriverReloadAllowed = topology.DriverReloadAllowed;
|
||||
AcceleratePrimaryDisplay = topology.AcceleratePrimaryDisplay;
|
||||
}
|
||||
|
||||
public SurroundTopology()
|
||||
{
|
||||
}
|
||||
|
||||
public bool AcceleratePrimaryDisplay { get; set; }
|
||||
public bool ApplyWithBezelCorrectedResolution { get; set; }
|
||||
public bool BaseMosaicPanoramic { get; set; }
|
||||
public int ColorDepth { get; set; }
|
||||
public int Columns { get; set; }
|
||||
public SurroundTopologyDisplay[] Displays { get; set; }
|
||||
public bool DriverReloadAllowed { get; set; }
|
||||
public int Frequency { get; set; }
|
||||
public bool ImmersiveGaming { get; set; }
|
||||
public Size Resolution { get; set; }
|
||||
public int Rows { get; set; }
|
||||
|
||||
|
||||
// ReSharper disable once ExcessiveIndentation
|
||||
public static SurroundTopology FromPathTargetInfo(PathTargetInfo pathTargetInfo)
|
||||
{
|
||||
// We go through the code if only the path belongs to a NVIDIA virtual surround display
|
||||
// and is not null
|
||||
if (pathTargetInfo == null)
|
||||
{
|
||||
SharedLogger.logger.Trace($"SurroundTopology/FromPathTargetInfo: The PathTargetInfo object supplied was null, so we have to return null back.");
|
||||
return null;
|
||||
}
|
||||
|
||||
string EDIDManufactureCode = "";
|
||||
string friendlyName = "";
|
||||
bool devicePathContainsUID5120 = false;
|
||||
bool isNvidiaEDID = false;
|
||||
bool isNvidiaDeviceName = false;
|
||||
bool isNvidiaDevicePath = false;
|
||||
|
||||
try
|
||||
{
|
||||
EDIDManufactureCode = pathTargetInfo.DisplayTarget.EDIDManufactureCode;
|
||||
SharedLogger.logger.Trace($"SurroundTopology/FromPathTargetInfo: Grabbed EDIDManufactureCode of {EDIDManufactureCode}.");
|
||||
if (string.Equals(EDIDManufactureCode, "NVS", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
SharedLogger.logger.Trace($"SurroundTopology/FromPathTargetInfo: The EDIDManufactureCode of {EDIDManufactureCode} matches 'NVS', so this is an NVIDIA surround topology.");
|
||||
isNvidiaEDID = true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
SharedLogger.logger.Warn(ex, $"SurroundTopology/FromPathTargetInfo: Exception trying to access EDIDManufactureCode.");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
friendlyName = pathTargetInfo.DisplayTarget.FriendlyName;
|
||||
SharedLogger.logger.Trace($"SurroundTopology/FromPathTargetInfo: Grabbed Display FriendlyName of {friendlyName}.");
|
||||
if (string.Equals(friendlyName, "NV Surround", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
SharedLogger.logger.Trace($"SurroundTopology/FromPathTargetInfo: The Display FriendlyName of {friendlyName} matches 'NV Surround', so this is an NVIDIA surround topology.");
|
||||
isNvidiaDeviceName = true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
SharedLogger.logger.Warn(ex, $"SurroundTopology/FromPathTargetInfo: Exception trying to access friendlyName.");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
devicePathContainsUID5120 = pathTargetInfo.DisplayTarget.DevicePath.ToLower().Contains("&UID5120".ToLower());
|
||||
SharedLogger.logger.Trace($"SurroundTopology/FromPathTargetInfo: Testing if the Display DevicePath contains UID5120 = {devicePathContainsUID5120}.");
|
||||
if (devicePathContainsUID5120)
|
||||
{
|
||||
SharedLogger.logger.Trace($"SurroundTopology/FromPathTargetInfo: The Device Path contains UID5120, so this is an NVIDIA surround topology.");
|
||||
isNvidiaDevicePath = true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
SharedLogger.logger.Warn(ex, $"SurroundTopology/FromPathTargetInfo: Exception trying to access friendlyName.");
|
||||
}
|
||||
|
||||
// If the checks haven't passed, then we return null
|
||||
if (!isNvidiaEDID && !isNvidiaDeviceName && !isNvidiaDevicePath)
|
||||
{
|
||||
SharedLogger.logger.Warn($"SurroundTopology/FromPathTargetInfo: As far as we can tell, this isn't an NVIDIA Surround window, so we're returning null.");
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Get parent DisplayConfig PathInfo by checking display targets
|
||||
SharedLogger.logger.Trace($"SurroundTopology/FromPathTargetInfo: Get parent DisplayConfig PathInfo by checking display targets.");
|
||||
var correspondingWindowsPathInfo =
|
||||
PathInfo.GetActivePaths()
|
||||
.FirstOrDefault(
|
||||
info =>
|
||||
info.TargetsInfo.Any(
|
||||
targetInfo =>
|
||||
targetInfo.DisplayTarget == pathTargetInfo.DisplayTarget));
|
||||
|
||||
if (correspondingWindowsPathInfo != null)
|
||||
{
|
||||
// Get corresponding NvAPI PathInfo
|
||||
// If position is same, then the two paths are equal, after all position is whats important in path sources
|
||||
SharedLogger.logger.Trace($"SurroundTopology/FromPathTargetInfo: Get corresponding NvAPI PathInfo. If position is same, then the two paths are equal, after all position is whats important in path sources");
|
||||
var correspondingNvidiaPathInfo =
|
||||
NvAPIWrapper.Display.PathInfo.GetDisplaysConfig()
|
||||
.FirstOrDefault(
|
||||
info =>
|
||||
info.Position.X == correspondingWindowsPathInfo.Position.X &&
|
||||
info.Position.Y == correspondingWindowsPathInfo.Position.Y &&
|
||||
info.Resolution.Width == correspondingWindowsPathInfo.Resolution.Width &&
|
||||
info.Resolution.Height == correspondingWindowsPathInfo.Resolution.Height);
|
||||
|
||||
if (correspondingNvidiaPathInfo != null)
|
||||
{
|
||||
// Get corresponding NvAPI PathTargetInfo
|
||||
// We now assume that there is only one target for a NvAPI PathInfo, in an other word, for now, it is not possible to have a cloned surround display
|
||||
SharedLogger.logger.Trace($"SurroundTopology/FromPathTargetInfo: Get corresponding NvAPI PathTargetInfo. We now assume that there is only one target for a NvAPI PathInfo, in an other word, for now, it is not possible to have a cloned surround display");
|
||||
var correspondingNvidiaTargetInfo = correspondingNvidiaPathInfo.TargetsInfo.FirstOrDefault();
|
||||
|
||||
if (correspondingNvidiaTargetInfo != null)
|
||||
{
|
||||
// Get corresponding NvAPI Grid Topology
|
||||
// We also assume that the NVS monitor uses a similar display id to one of real physical monitors
|
||||
SharedLogger.logger.Trace($"SurroundTopology/FromPathTargetInfo: Get corresponding NvAPI Grid Topology. We also assume that the NVS monitor uses a similar display id to one of real physical monitors");
|
||||
var correspondingNvidiaTopology =
|
||||
GridTopology.GetGridTopologies()
|
||||
.FirstOrDefault(
|
||||
topology => topology.Displays.Any(display =>
|
||||
display.DisplayDevice == correspondingNvidiaTargetInfo.DisplayDevice));
|
||||
|
||||
if (correspondingNvidiaTopology != null)
|
||||
{
|
||||
SharedLogger.logger.Trace($"SurroundTopology/FromPathTargetInfo: Return the new NVIDIA Topology SurroundTopology object");
|
||||
return new SurroundTopology(correspondingNvidiaTopology);
|
||||
}
|
||||
else
|
||||
{
|
||||
SharedLogger.logger.Trace($"SurroundTopology/FromPathTargetInfo: The correspondingNvidiaTopology SurroundTopology object wa null, so nothing to return");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
SharedLogger.logger.Warn(ex, $"SurroundTopology/FromPathTargetInfo: Exception trying to get the Grid Topology from the NVIDIA driver.");
|
||||
}
|
||||
// if we get here, then we've failed to get the NVIDIA Grid Topology
|
||||
SharedLogger.logger.Warn($"SurroundTopology/FromPathTargetInfo: We've tried to get the Grid Topology from the NVIDIA driver but we can't!");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"SurroundTopology[{Rows}, {Columns}] ({Resolution.Width}, {Resolution.Height}) @ {Frequency}";
|
||||
}
|
||||
|
||||
// ReSharper disable once ExcessiveIndentation
|
||||
public GridTopology ToGridTopology()
|
||||
{
|
||||
var gridTopology = new GridTopology(Rows, Columns,
|
||||
Displays.Select(display => display.ToGridTopologyDisplay()).ToArray())
|
||||
{
|
||||
ApplyWithBezelCorrectedResolution = ApplyWithBezelCorrectedResolution,
|
||||
ImmersiveGaming = ImmersiveGaming,
|
||||
BaseMosaicPanoramic = BaseMosaicPanoramic,
|
||||
DriverReloadAllowed = DriverReloadAllowed,
|
||||
AcceleratePrimaryDisplay = AcceleratePrimaryDisplay
|
||||
};
|
||||
IDisplaySettings bestDisplaySettings = null;
|
||||
|
||||
foreach (var displaySetting in gridTopology.GetPossibleDisplaySettings())
|
||||
{
|
||||
if (displaySetting.Width == Resolution.Width &&
|
||||
displaySetting.Height == Resolution.Height)
|
||||
{
|
||||
if (displaySetting.BitsPerPixel == ColorDepth)
|
||||
{
|
||||
if (displaySetting.Frequency == Frequency)
|
||||
{
|
||||
bestDisplaySettings = displaySetting;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (bestDisplaySettings == null || displaySetting.Frequency > bestDisplaySettings.Frequency)
|
||||
{
|
||||
bestDisplaySettings = displaySetting;
|
||||
}
|
||||
}
|
||||
else if (bestDisplaySettings == null ||
|
||||
displaySetting.BitsPerPixel > bestDisplaySettings.BitsPerPixel)
|
||||
{
|
||||
bestDisplaySettings = displaySetting;
|
||||
}
|
||||
}
|
||||
else if (bestDisplaySettings == null ||
|
||||
displaySetting.Width * displaySetting.Height >
|
||||
bestDisplaySettings.Width * bestDisplaySettings.Height)
|
||||
{
|
||||
bestDisplaySettings = displaySetting;
|
||||
}
|
||||
}
|
||||
|
||||
if (bestDisplaySettings != null)
|
||||
{
|
||||
gridTopology.SetDisplaySettings(bestDisplaySettings);
|
||||
}
|
||||
|
||||
return gridTopology;
|
||||
}
|
||||
|
||||
// The public override for the Object.Equals
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return this.Equals(obj as SurroundTopology);
|
||||
}
|
||||
|
||||
// SurroundTopoligies are equal if their contents (except name) are equal
|
||||
public bool Equals(SurroundTopology other)
|
||||
{
|
||||
|
||||
// If parameter is null, return false.
|
||||
if (other is null)
|
||||
return false;
|
||||
|
||||
// Optimization for a common success case.
|
||||
if (Object.ReferenceEquals(this, other))
|
||||
return true;
|
||||
|
||||
// If run-time types are not exactly the same, return false.
|
||||
if (this.GetType() != other.GetType())
|
||||
return false;
|
||||
|
||||
// Check whether the Profile Viewport properties are equal
|
||||
// Two profiles are equal only when they have the same viewport data exactly
|
||||
if (AcceleratePrimaryDisplay.Equals(other.AcceleratePrimaryDisplay) &&
|
||||
ApplyWithBezelCorrectedResolution.Equals(other.ApplyWithBezelCorrectedResolution) &&
|
||||
BaseMosaicPanoramic.Equals(other.BaseMosaicPanoramic) &&
|
||||
ColorDepth.Equals(other.ColorDepth) &&
|
||||
Columns.Equals(other.Columns) &&
|
||||
Displays.Length.Equals(other.Displays.Length) &&
|
||||
DriverReloadAllowed.Equals(other.DriverReloadAllowed) &&
|
||||
Frequency.Equals(other.Frequency) &&
|
||||
ImmersiveGaming.Equals(other.ImmersiveGaming) &&
|
||||
Resolution.Equals(other.Resolution) &&
|
||||
Rows.Equals(other.Rows))
|
||||
{
|
||||
// If the above all match, then we need to check the Displays matche
|
||||
if (Displays == null && other.Displays == null)
|
||||
return true;
|
||||
else if (Displays != null && other.Displays == null)
|
||||
return false;
|
||||
else if (Displays == null && other.Displays != null)
|
||||
return false;
|
||||
else if (Displays.SequenceEqual(other.Displays))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
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 AcceleratePrimaryDisplay field if it is not null.
|
||||
int hashAcceleratePrimaryDisplay = AcceleratePrimaryDisplay.GetHashCode();
|
||||
|
||||
// Get hash code for the ApplyWithBezelCorrectedResolution field if it is not null.
|
||||
int hashApplyWithBezelCorrectedResolution = ApplyWithBezelCorrectedResolution.GetHashCode();
|
||||
|
||||
// Get hash code for the FrequencyInMillihertz field if it is not null.
|
||||
int hashBaseMosaicPanoramic = BaseMosaicPanoramic.GetHashCode();
|
||||
|
||||
// Get hash code for the FrequencyInMillihertz field if it is not null.
|
||||
int hashColorDepth = ColorDepth.GetHashCode();
|
||||
|
||||
// Get hash code for the FrequencyInMillihertz field if it is not null.
|
||||
int hashColumns = Columns.GetHashCode();
|
||||
|
||||
// Get hash code for the FrequencyInMillihertz field if it is not null.
|
||||
int hashDriverReloadAllowed = DriverReloadAllowed.GetHashCode();
|
||||
|
||||
// Get hash code for the FrequencyInMillihertz field if it is not null.
|
||||
int hashFrequency = Frequency.GetHashCode();
|
||||
|
||||
// Get hash code for the FrequencyInMillihertz field if it is not null.
|
||||
int hashImmersiveGaming = ImmersiveGaming.GetHashCode();
|
||||
|
||||
// Get hash code for the FrequencyInMillihertz field if it is not null.
|
||||
int hashResolution = Resolution.GetHashCode();
|
||||
|
||||
// Get hash code for the FrequencyInMillihertz field if it is not null.
|
||||
int hashRows = Rows.GetHashCode();
|
||||
|
||||
// Get hash code for the Displays field if it is not null.
|
||||
int hashDisplays = Displays.GetHashCode();
|
||||
|
||||
//Calculate the hash code for the product.
|
||||
return hashAcceleratePrimaryDisplay ^ hashApplyWithBezelCorrectedResolution ^ hashBaseMosaicPanoramic ^
|
||||
hashColorDepth ^ hashColumns ^ hashDriverReloadAllowed ^ hashFrequency ^ hashImmersiveGaming ^
|
||||
hashResolution ^ hashRows ^ hashDisplays;
|
||||
}
|
||||
}
|
||||
|
||||
// Custom comparer for the ProfileViewportTargetDisplay class
|
||||
class SurroundTopologyComparer : IEqualityComparer<SurroundTopology>
|
||||
{
|
||||
// Products are equal if their names and product numbers are equal.
|
||||
public bool Equals(SurroundTopology x, SurroundTopology 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 Profile Viewport properties are equal
|
||||
// Two profiles are equal only when they have the same viewport data exactly
|
||||
|
||||
if (x.AcceleratePrimaryDisplay.Equals(y.AcceleratePrimaryDisplay) &&
|
||||
x.ApplyWithBezelCorrectedResolution.Equals(y.ApplyWithBezelCorrectedResolution) &&
|
||||
x.BaseMosaicPanoramic.Equals(y.BaseMosaicPanoramic) &&
|
||||
x.ColorDepth.Equals(y.ColorDepth) &&
|
||||
x.Columns.Equals(y.Columns) &&
|
||||
x.Displays.Length.Equals(y.Displays.Length) &&
|
||||
x.DriverReloadAllowed.Equals(y.DriverReloadAllowed) &&
|
||||
x.Frequency.Equals(y.Frequency) &&
|
||||
x.ImmersiveGaming.Equals(y.ImmersiveGaming) &&
|
||||
x.Resolution.Equals(y.Resolution) &&
|
||||
x.Rows.Equals(y.Rows))
|
||||
{
|
||||
// If the above all match, then we need to check the Displays matche
|
||||
if (x.Displays == null && y.Displays == null)
|
||||
return true;
|
||||
else if (x.Displays != null && y.Displays == null)
|
||||
return false;
|
||||
else if (x.Displays == null && y.Displays != null)
|
||||
return false;
|
||||
else if (x.Displays.SequenceEqual(y.Displays))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
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(SurroundTopology surroundTopology)
|
||||
{
|
||||
// Check whether the object is null
|
||||
if (surroundTopology is null) return 0;
|
||||
|
||||
// Get hash code for the AcceleratePrimaryDisplay field if it is not null.
|
||||
int hashAcceleratePrimaryDisplay = surroundTopology.AcceleratePrimaryDisplay.GetHashCode();
|
||||
|
||||
// Get hash code for the ApplyWithBezelCorrectedResolution field if it is not null.
|
||||
int hashApplyWithBezelCorrectedResolution = surroundTopology.ApplyWithBezelCorrectedResolution.GetHashCode();
|
||||
|
||||
// Get hash code for the FrequencyInMillihertz field if it is not null.
|
||||
int hashBaseMosaicPanoramic = surroundTopology.BaseMosaicPanoramic.GetHashCode();
|
||||
|
||||
// Get hash code for the FrequencyInMillihertz field if it is not null.
|
||||
int hashColorDepth = surroundTopology.ColorDepth.GetHashCode();
|
||||
|
||||
// Get hash code for the FrequencyInMillihertz field if it is not null.
|
||||
int hashColumns = surroundTopology.Columns.GetHashCode();
|
||||
|
||||
// Get hash code for the FrequencyInMillihertz field if it is not null.
|
||||
int hashDriverReloadAllowed = surroundTopology.DriverReloadAllowed.GetHashCode();
|
||||
|
||||
// Get hash code for the FrequencyInMillihertz field if it is not null.
|
||||
int hashFrequency = surroundTopology.Frequency.GetHashCode();
|
||||
|
||||
// Get hash code for the FrequencyInMillihertz field if it is not null.
|
||||
int hashImmersiveGaming = surroundTopology.ImmersiveGaming.GetHashCode();
|
||||
|
||||
// Get hash code for the FrequencyInMillihertz field if it is not null.
|
||||
int hashResolution = surroundTopology.Resolution.GetHashCode();
|
||||
|
||||
// Get hash code for the FrequencyInMillihertz field if it is not null.
|
||||
int hashRows = surroundTopology.Rows.GetHashCode();
|
||||
|
||||
// Get hash code for the Displays field if it is not null.
|
||||
int hashDisplays = surroundTopology.Displays.GetHashCode();
|
||||
|
||||
//Calculate the hash code for the product.
|
||||
return hashAcceleratePrimaryDisplay ^ hashApplyWithBezelCorrectedResolution ^ hashBaseMosaicPanoramic ^
|
||||
hashColorDepth ^ hashColumns ^ hashDriverReloadAllowed ^ hashFrequency ^ hashImmersiveGaming ^
|
||||
hashResolution ^ hashRows ^ hashDisplays;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,179 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using EDIDParser;
|
||||
using EDIDParser.Descriptors;
|
||||
using EDIDParser.Enums;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using NvAPIWrapper.Mosaic;
|
||||
using NvAPIWrapper.Native.Exceptions;
|
||||
using DisplayMagicianShared;
|
||||
|
||||
namespace DisplayMagicianShared.NVIDIA
|
||||
{
|
||||
public class SurroundTopologyDisplay
|
||||
{
|
||||
|
||||
public SurroundTopologyDisplay(GridTopologyDisplay display)
|
||||
{
|
||||
DisplayId = display.DisplayDevice.DisplayId;
|
||||
Rotation = display.Rotation.ToRotation();
|
||||
Overlap = new Point(display.Overlap.HorizontalOverlap, display.Overlap.VerticalOverlap);
|
||||
PixelShift = display.PixelShiftType.ToPixelShift();
|
||||
|
||||
try
|
||||
{
|
||||
NvAPIWrapper.Native.GeneralApi.Initialize();
|
||||
//var phyGPU = display.DisplayDevice.PhysicalGPU;
|
||||
var bytes = display.DisplayDevice.PhysicalGPU.ReadEDIDData(display.DisplayDevice.Output);
|
||||
DisplayName = new EDID(bytes).Descriptors
|
||||
.Where(descriptor => descriptor is StringDescriptor)
|
||||
.Cast<StringDescriptor>()
|
||||
.FirstOrDefault(descriptor => descriptor.Type == StringDescriptorType.MonitorName)?.Value;
|
||||
}
|
||||
catch (NVIDIAApiException ex)
|
||||
{
|
||||
//Debug.WriteLine($"SurroundTopologyDisplay/NVIDIAApiException exception: {ex.Message}: {ex.StackTrace} - {ex.InnerException}");
|
||||
SharedLogger.logger.Debug(ex, $"SurroundTopologyDisplay/NVIDIAApiException: Accessing NvAPIWRapper ReadEDDIDData caused exception. Setting generic DisplayID instead");
|
||||
// If we hit here then we cannot find the DisplayName from the EDID Data from the GPU
|
||||
// So we just make one up using the DisplayID
|
||||
DisplayName = $"Display #{DisplayId}";
|
||||
}
|
||||
}
|
||||
|
||||
public SurroundTopologyDisplay()
|
||||
{
|
||||
}
|
||||
|
||||
public uint DisplayId { get; set; }
|
||||
|
||||
public string DisplayName { get; set; }
|
||||
|
||||
public Point Overlap { get; set; }
|
||||
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public PixelShift PixelShift { get; set; }
|
||||
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public Rotation Rotation { get; set; }
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return DisplayName ?? $"SurroundTopologyDisplay #{DisplayId}";
|
||||
}
|
||||
|
||||
public GridTopologyDisplay ToGridTopologyDisplay()
|
||||
{
|
||||
return new GridTopologyDisplay(DisplayId, new Overlap(Overlap.X, Overlap.Y), Rotation.ToRotate(), 0,
|
||||
PixelShift.ToPixelShiftType());
|
||||
}
|
||||
|
||||
// The public override for the Object.Equals
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return this.Equals(obj as SurroundTopologyDisplay);
|
||||
}
|
||||
|
||||
// SurroundTopologyDisplay are equal if their contents are equal
|
||||
public bool Equals(SurroundTopologyDisplay other)
|
||||
{
|
||||
|
||||
// If parameter is null, return false.
|
||||
if (Object.ReferenceEquals(other, null))
|
||||
return false;
|
||||
|
||||
// Optimization for a common success case.
|
||||
if (Object.ReferenceEquals(this, other))
|
||||
return true;
|
||||
|
||||
// If run-time types are not exactly the same, return false.
|
||||
if (this.GetType() != other.GetType())
|
||||
return false;
|
||||
|
||||
// Check whether the SurroundTopologyDisplay properties are equal
|
||||
// Two SurroundTopologyDisplay are equal only when they have the same data exactly
|
||||
if (DisplayId == other.DisplayId &&
|
||||
Overlap.Equals(other.Overlap) &&
|
||||
PixelShift == other.PixelShift &&
|
||||
Rotation == other.Rotation)
|
||||
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 DisplayId field if it is not null.
|
||||
int hashDisplayId = DisplayId.GetHashCode();
|
||||
|
||||
// Get hash code for the Overlap field if it is not null.
|
||||
int hashOverlap = Overlap.GetHashCode();
|
||||
|
||||
// Get hash code for the PixelShift field if it is not null.
|
||||
int hashPixelShift = PixelShift.GetHashCode();
|
||||
|
||||
// Get hash code for the Rotation field if it is not null.
|
||||
int hashRotation = Rotation.GetHashCode();
|
||||
|
||||
//Calculate the hash code for the product.
|
||||
return hashDisplayId ^ hashOverlap ^ hashPixelShift ^ hashRotation;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Custom comparer for the ProfileViewportTargetDisplay class
|
||||
class SurroundTopologyDisplayComparer : IEqualityComparer<SurroundTopologyDisplay>
|
||||
{
|
||||
// Products are equal if their names and product numbers are equal.
|
||||
public bool Equals(SurroundTopologyDisplay x, SurroundTopologyDisplay 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 (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
|
||||
return false;
|
||||
|
||||
// Check whether the SurroundTopologyDisplay properties are equal
|
||||
// Two SurroundTopologyDisplay are equal only when they have the same data exactly
|
||||
if (x.DisplayId == y.DisplayId &&
|
||||
x.Overlap.Equals(y.Overlap) &&
|
||||
x.PixelShift == y.PixelShift &&
|
||||
x.Rotation == y.Rotation)
|
||||
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(SurroundTopologyDisplay surroundTopologyDisplay)
|
||||
{
|
||||
// Check whether the object is null
|
||||
if (Object.ReferenceEquals(surroundTopologyDisplay, null)) return 0;
|
||||
|
||||
// Get hash code for the DisplayId field if it is not null.
|
||||
int hashDisplayId = surroundTopologyDisplay.DisplayId.GetHashCode();
|
||||
|
||||
// Get hash code for the Overlap field if it is not null.
|
||||
int hashOverlap = surroundTopologyDisplay.Overlap.GetHashCode();
|
||||
|
||||
// Get hash code for the PixelShift field if it is not null.
|
||||
int hashPixelShift = surroundTopologyDisplay.PixelShift.GetHashCode();
|
||||
|
||||
// Get hash code for the Rotation field if it is not null.
|
||||
int hashRotation = surroundTopologyDisplay.Rotation.GetHashCode();
|
||||
|
||||
//Calculate the hash code for the product.
|
||||
return hashDisplayId ^ hashOverlap ^ hashPixelShift ^ hashRotation;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -237,7 +237,7 @@ namespace DisplayMagicianShared.Windows
|
||||
PalN = 15,
|
||||
PalNc = 16,
|
||||
SecamB = 17,
|
||||
SecamD = 18,
|
||||
SecNVIDIA = 18,
|
||||
SecamG = 19,
|
||||
SecamH = 20,
|
||||
SecamK = 21,
|
||||
|
@ -6,6 +6,7 @@ using System.Text;
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
using DisplayMagicianShared;
|
||||
using System.ComponentModel;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace DisplayMagicianShared.Windows
|
||||
{
|
||||
@ -31,23 +32,24 @@ namespace DisplayMagicianShared.Windows
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct WINDOWS_DISPLAY_CONFIG : IEquatable<WINDOWS_DISPLAY_CONFIG>
|
||||
{
|
||||
public Dictionary<ulong, string> displayAdapters;
|
||||
public DISPLAYCONFIG_PATH_INFO[] displayConfigPaths;
|
||||
public DISPLAYCONFIG_MODE_INFO[] displayConfigModes;
|
||||
public ADVANCED_HDR_INFO_PER_PATH[] displayHDRStates;
|
||||
public Dictionary<ulong, string> DisplayAdapters;
|
||||
public DISPLAYCONFIG_PATH_INFO[] DisplayConfigPaths;
|
||||
public DISPLAYCONFIG_MODE_INFO[] DisplayConfigModes;
|
||||
public ADVANCED_HDR_INFO_PER_PATH[] DisplayHDRStates;
|
||||
public List<string> DisplayIdentifiers;
|
||||
|
||||
public bool Equals(WINDOWS_DISPLAY_CONFIG other)
|
||||
=> displayConfigPaths.SequenceEqual(other.displayConfigPaths) &&
|
||||
displayConfigModes.SequenceEqual(other.displayConfigModes) &&
|
||||
displayHDRStates.SequenceEqual(other.displayHDRStates);
|
||||
=> DisplayConfigPaths.SequenceEqual(other.DisplayConfigPaths) &&
|
||||
DisplayConfigModes.SequenceEqual(other.DisplayConfigModes) &&
|
||||
DisplayHDRStates.SequenceEqual(other.DisplayHDRStates);
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return (displayConfigPaths, displayConfigModes, displayHDRStates).GetHashCode();
|
||||
return (DisplayConfigPaths, DisplayConfigModes, DisplayHDRStates).GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
public class WinLibrary : IDisposable
|
||||
class WinLibrary : IDisposable
|
||||
{
|
||||
|
||||
// Static members are 'eagerly initialized', that is,
|
||||
@ -69,7 +71,6 @@ namespace DisplayMagicianShared.Windows
|
||||
{
|
||||
SharedLogger.logger.Trace("WinLibrary/WinLibrary: Intialising Windows CCD library interface");
|
||||
_initialised = true;
|
||||
SharedLogger.logger.Trace("WinLibrary/WinLibrary: ADL2 library was initialised successfully");
|
||||
|
||||
}
|
||||
|
||||
@ -119,7 +120,7 @@ namespace DisplayMagicianShared.Windows
|
||||
Dictionary<ulong, ulong> adapterOldToNewMap = new Dictionary<ulong, ulong>();
|
||||
|
||||
SharedLogger.logger.Trace("WinLibrary/PatchAdapterIDs: Going through the list of adapters we stored in the config to figure out the old adapterIDs");
|
||||
foreach (KeyValuePair<ulong, string> savedAdapter in savedDisplayConfig.displayAdapters)
|
||||
foreach (KeyValuePair<ulong, string> savedAdapter in savedDisplayConfig.DisplayAdapters)
|
||||
{
|
||||
foreach (KeyValuePair<ulong, string> currentAdapter in currentAdapterMap)
|
||||
{
|
||||
@ -136,73 +137,73 @@ namespace DisplayMagicianShared.Windows
|
||||
ulong newAdapterValue = 0;
|
||||
// Update the paths with the current adapter id
|
||||
SharedLogger.logger.Trace($"WinLibrary/PatchAdapterIDs: Going through the display config paths to update the adapter id");
|
||||
for (int i = 0; i < savedDisplayConfig.displayConfigPaths.Length; i++)
|
||||
for (int i = 0; i < savedDisplayConfig.DisplayConfigPaths.Length; i++)
|
||||
{
|
||||
// Change the Path SourceInfo and TargetInfo AdapterIDs
|
||||
if (adapterOldToNewMap.ContainsKey(savedDisplayConfig.displayConfigPaths[i].SourceInfo.AdapterId.Value))
|
||||
if (adapterOldToNewMap.ContainsKey(savedDisplayConfig.DisplayConfigPaths[i].SourceInfo.AdapterId.Value))
|
||||
{
|
||||
// We get here if there is a matching adapter
|
||||
newAdapterValue = adapterOldToNewMap[savedDisplayConfig.displayConfigPaths[i].SourceInfo.AdapterId.Value];
|
||||
savedDisplayConfig.displayConfigPaths[i].SourceInfo.AdapterId = AdapterValueToLUID(newAdapterValue);
|
||||
newAdapterValue = adapterOldToNewMap[savedDisplayConfig.displayConfigPaths[i].TargetInfo.AdapterId.Value];
|
||||
savedDisplayConfig.displayConfigPaths[i].TargetInfo.AdapterId = AdapterValueToLUID(newAdapterValue);
|
||||
newAdapterValue = adapterOldToNewMap[savedDisplayConfig.DisplayConfigPaths[i].SourceInfo.AdapterId.Value];
|
||||
savedDisplayConfig.DisplayConfigPaths[i].SourceInfo.AdapterId = AdapterValueToLUID(newAdapterValue);
|
||||
newAdapterValue = adapterOldToNewMap[savedDisplayConfig.DisplayConfigPaths[i].TargetInfo.AdapterId.Value];
|
||||
savedDisplayConfig.DisplayConfigPaths[i].TargetInfo.AdapterId = AdapterValueToLUID(newAdapterValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if there isn't a matching adapter, then we just pick the first current one and hope that works!
|
||||
// (it is highly likely to... its only if the user has multiple graphics cards with some weird config it may break)
|
||||
newAdapterValue = currentAdapterMap.First().Key;
|
||||
SharedLogger.logger.Warn($"WinLibrary/PatchAdapterIDs: Uh Oh. Adapter {savedDisplayConfig.displayConfigPaths[i].SourceInfo.AdapterId.Value} didn't have a current match! It's possible the adapter was swapped or disabled. Attempting to use adapter {newAdapterValue} instead.");
|
||||
savedDisplayConfig.displayConfigPaths[i].SourceInfo.AdapterId = AdapterValueToLUID(newAdapterValue);
|
||||
savedDisplayConfig.displayConfigPaths[i].TargetInfo.AdapterId = AdapterValueToLUID(newAdapterValue);
|
||||
SharedLogger.logger.Warn($"WinLibrary/PatchAdapterIDs: Uh Oh. Adapter {savedDisplayConfig.DisplayConfigPaths[i].SourceInfo.AdapterId.Value} didn't have a current match! It's possible the adapter was swapped or disabled. Attempting to use adapter {newAdapterValue} instead.");
|
||||
savedDisplayConfig.DisplayConfigPaths[i].SourceInfo.AdapterId = AdapterValueToLUID(newAdapterValue);
|
||||
savedDisplayConfig.DisplayConfigPaths[i].TargetInfo.AdapterId = AdapterValueToLUID(newAdapterValue);
|
||||
}
|
||||
}
|
||||
|
||||
SharedLogger.logger.Trace($"WinLibrary/PatchAdapterIDs: Going through the display config modes to update the adapter id");
|
||||
// Update the modes with the current adapter id
|
||||
for (int i = 0; i < savedDisplayConfig.displayConfigModes.Length; i++)
|
||||
for (int i = 0; i < savedDisplayConfig.DisplayConfigModes.Length; i++)
|
||||
{
|
||||
// Change the Mode AdapterID
|
||||
if (adapterOldToNewMap.ContainsKey(savedDisplayConfig.displayConfigModes[i].AdapterId.Value))
|
||||
if (adapterOldToNewMap.ContainsKey(savedDisplayConfig.DisplayConfigModes[i].AdapterId.Value))
|
||||
{
|
||||
// We get here if there is a matching adapter
|
||||
newAdapterValue = adapterOldToNewMap[savedDisplayConfig.displayConfigModes[i].AdapterId.Value];
|
||||
savedDisplayConfig.displayConfigModes[i].AdapterId = AdapterValueToLUID(newAdapterValue);
|
||||
newAdapterValue = adapterOldToNewMap[savedDisplayConfig.DisplayConfigModes[i].AdapterId.Value];
|
||||
savedDisplayConfig.DisplayConfigModes[i].AdapterId = AdapterValueToLUID(newAdapterValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if there isn't a matching adapter, then we just pick the first current one and hope that works!
|
||||
// (it is highly likely to... its only if the user has multiple graphics cards with some weird config it may break)
|
||||
newAdapterValue = currentAdapterMap.First().Key;
|
||||
SharedLogger.logger.Warn($"WinLibrary/PatchAdapterIDs: Uh Oh. Adapter {savedDisplayConfig.displayConfigModes[i].AdapterId.Value} didn't have a current match! It's possible the adapter was swapped or disabled. Attempting to use adapter {newAdapterValue} instead.");
|
||||
savedDisplayConfig.displayConfigModes[i].AdapterId = AdapterValueToLUID(newAdapterValue);
|
||||
SharedLogger.logger.Warn($"WinLibrary/PatchAdapterIDs: Uh Oh. Adapter {savedDisplayConfig.DisplayConfigModes[i].AdapterId.Value} didn't have a current match! It's possible the adapter was swapped or disabled. Attempting to use adapter {newAdapterValue} instead.");
|
||||
savedDisplayConfig.DisplayConfigModes[i].AdapterId = AdapterValueToLUID(newAdapterValue);
|
||||
}
|
||||
}
|
||||
|
||||
SharedLogger.logger.Trace($"WinLibrary/PatchAdapterIDs: Going through the display config HDR info to update the adapter id");
|
||||
// Update the HDRInfo with the current adapter id
|
||||
for (int i = 0; i < savedDisplayConfig.displayHDRStates.Length; i++)
|
||||
for (int i = 0; i < savedDisplayConfig.DisplayHDRStates.Length; i++)
|
||||
{
|
||||
// Change the Mode AdapterID
|
||||
if (adapterOldToNewMap.ContainsKey(savedDisplayConfig.displayHDRStates[i].AdapterId.Value))
|
||||
if (adapterOldToNewMap.ContainsKey(savedDisplayConfig.DisplayHDRStates[i].AdapterId.Value))
|
||||
{
|
||||
// We get here if there is a matching adapter
|
||||
newAdapterValue = adapterOldToNewMap[savedDisplayConfig.displayHDRStates[i].AdapterId.Value];
|
||||
savedDisplayConfig.displayHDRStates[i].AdapterId = AdapterValueToLUID(newAdapterValue);
|
||||
newAdapterValue = adapterOldToNewMap[savedDisplayConfig.displayHDRStates[i].AdvancedColorInfo.Header.AdapterId.Value];
|
||||
savedDisplayConfig.displayHDRStates[i].AdvancedColorInfo.Header.AdapterId = AdapterValueToLUID(newAdapterValue);
|
||||
newAdapterValue = adapterOldToNewMap[savedDisplayConfig.displayHDRStates[i].SDRWhiteLevel.Header.AdapterId.Value];
|
||||
savedDisplayConfig.displayHDRStates[i].SDRWhiteLevel.Header.AdapterId = AdapterValueToLUID(newAdapterValue);
|
||||
newAdapterValue = adapterOldToNewMap[savedDisplayConfig.DisplayHDRStates[i].AdapterId.Value];
|
||||
savedDisplayConfig.DisplayHDRStates[i].AdapterId = AdapterValueToLUID(newAdapterValue);
|
||||
newAdapterValue = adapterOldToNewMap[savedDisplayConfig.DisplayHDRStates[i].AdvancedColorInfo.Header.AdapterId.Value];
|
||||
savedDisplayConfig.DisplayHDRStates[i].AdvancedColorInfo.Header.AdapterId = AdapterValueToLUID(newAdapterValue);
|
||||
newAdapterValue = adapterOldToNewMap[savedDisplayConfig.DisplayHDRStates[i].SDRWhiteLevel.Header.AdapterId.Value];
|
||||
savedDisplayConfig.DisplayHDRStates[i].SDRWhiteLevel.Header.AdapterId = AdapterValueToLUID(newAdapterValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if there isn't a matching adapter, then we just pick the first current one and hope that works!
|
||||
// (it is highly likely to... its only if the user has multiple graphics cards with some weird config it may break)
|
||||
newAdapterValue = currentAdapterMap.First().Key;
|
||||
SharedLogger.logger.Warn($"WinLibrary/PatchAdapterIDs: Uh Oh. Adapter {savedDisplayConfig.displayHDRStates[i].AdapterId.Value} didn't have a current match! It's possible the adapter was swapped or disabled. Attempting to use adapter {newAdapterValue} instead.");
|
||||
savedDisplayConfig.displayHDRStates[i].AdapterId = AdapterValueToLUID(newAdapterValue);
|
||||
savedDisplayConfig.displayHDRStates[i].AdvancedColorInfo.Header.AdapterId = AdapterValueToLUID(newAdapterValue);
|
||||
savedDisplayConfig.displayHDRStates[i].SDRWhiteLevel.Header.AdapterId = AdapterValueToLUID(newAdapterValue);
|
||||
SharedLogger.logger.Warn($"WinLibrary/PatchAdapterIDs: Uh Oh. Adapter {savedDisplayConfig.DisplayHDRStates[i].AdapterId.Value} didn't have a current match! It's possible the adapter was swapped or disabled. Attempting to use adapter {newAdapterValue} instead.");
|
||||
savedDisplayConfig.DisplayHDRStates[i].AdapterId = AdapterValueToLUID(newAdapterValue);
|
||||
savedDisplayConfig.DisplayHDRStates[i].AdvancedColorInfo.Header.AdapterId = AdapterValueToLUID(newAdapterValue);
|
||||
savedDisplayConfig.DisplayHDRStates[i].SDRWhiteLevel.Header.AdapterId = AdapterValueToLUID(newAdapterValue);
|
||||
}
|
||||
}
|
||||
|
||||
@ -266,8 +267,8 @@ namespace DisplayMagicianShared.Windows
|
||||
|
||||
// Prepare the empty windows display config
|
||||
WINDOWS_DISPLAY_CONFIG windowsDisplayConfig = new WINDOWS_DISPLAY_CONFIG();
|
||||
windowsDisplayConfig.displayAdapters = new Dictionary<ulong, string>();
|
||||
windowsDisplayConfig.displayHDRStates = new ADVANCED_HDR_INFO_PER_PATH[pathCount];
|
||||
windowsDisplayConfig.DisplayAdapters = new Dictionary<ulong, string>();
|
||||
windowsDisplayConfig.DisplayHDRStates = new ADVANCED_HDR_INFO_PER_PATH[pathCount];
|
||||
|
||||
// Now cycle through the paths and grab the HDR state information
|
||||
// and map the adapter name to adapter id
|
||||
@ -277,7 +278,7 @@ namespace DisplayMagicianShared.Windows
|
||||
{
|
||||
// Get adapter ID for later
|
||||
SharedLogger.logger.Trace($"WinLibrary/GetWindowsDisplayConfig: Attempting to get adapter name for adapter {path.TargetInfo.AdapterId.Value}.");
|
||||
if (!windowsDisplayConfig.displayAdapters.ContainsKey(path.TargetInfo.AdapterId.Value))
|
||||
if (!windowsDisplayConfig.DisplayAdapters.ContainsKey(path.TargetInfo.AdapterId.Value))
|
||||
{
|
||||
var adapterInfo = new DISPLAYCONFIG_ADAPTER_NAME();
|
||||
adapterInfo.Header.Type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_GET_ADAPTER_NAME;
|
||||
@ -288,7 +289,7 @@ namespace DisplayMagicianShared.Windows
|
||||
if (err == WIN32STATUS.ERROR_SUCCESS)
|
||||
{
|
||||
// Store it for later
|
||||
windowsDisplayConfig.displayAdapters.Add(path.TargetInfo.AdapterId.Value, adapterInfo.AdapterDevicePath);
|
||||
windowsDisplayConfig.DisplayAdapters.Add(path.TargetInfo.AdapterId.Value, adapterInfo.AdapterDevicePath);
|
||||
SharedLogger.logger.Trace($"WinLibrary/GetWindowsDisplayConfig: Found adapter name {adapterInfo.AdapterDevicePath} for adapter {path.TargetInfo.AdapterId.Value}.");
|
||||
}
|
||||
else
|
||||
@ -356,9 +357,10 @@ namespace DisplayMagicianShared.Windows
|
||||
}
|
||||
|
||||
// Store the active paths and modes in our display config object
|
||||
windowsDisplayConfig.displayConfigPaths = paths;
|
||||
windowsDisplayConfig.displayConfigModes = modes;
|
||||
windowsDisplayConfig.displayHDRStates = hdrInfos;
|
||||
windowsDisplayConfig.DisplayConfigPaths = paths;
|
||||
windowsDisplayConfig.DisplayConfigModes = modes;
|
||||
windowsDisplayConfig.DisplayHDRStates = hdrInfos;
|
||||
windowsDisplayConfig.DisplayIdentifiers = GetCurrentDisplayIdentifiers();
|
||||
|
||||
return windowsDisplayConfig;
|
||||
}
|
||||
@ -375,7 +377,7 @@ namespace DisplayMagicianShared.Windows
|
||||
public string PrintActiveConfig()
|
||||
{
|
||||
string stringToReturn = "";
|
||||
|
||||
stringToReturn += $"****** WINDOWS CCD CONFIGURATION *******\n";
|
||||
// Get the size of the largest Active Paths and Modes arrays
|
||||
int pathCount = 0;
|
||||
int modeCount = 0;
|
||||
@ -639,13 +641,13 @@ namespace DisplayMagicianShared.Windows
|
||||
|
||||
// Now we go through the Paths to update the LUIDs as per Soroush's suggestion
|
||||
SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: Patching the adapter IDs to make the saved config valid");
|
||||
PatchAdapterIDs(ref displayConfig, allWindowsDisplayConfig.displayAdapters);
|
||||
PatchAdapterIDs(ref displayConfig, allWindowsDisplayConfig.DisplayAdapters);
|
||||
|
||||
SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: 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);
|
||||
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($"WinLibrary/SetActiveConfig: Successfully validated that the display configuration supplied would work!");
|
||||
@ -658,7 +660,7 @@ namespace DisplayMagicianShared.Windows
|
||||
|
||||
SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: Yay! The display configuration is valid! Attempting to set the Display Config now");
|
||||
// Now set the specified display configuration for this computer
|
||||
err = CCDImport.SetDisplayConfig(myPathsCount, displayConfig.displayConfigPaths, myModesCount, displayConfig.displayConfigModes, SDC.DISPLAYMAGICIAN_SET);
|
||||
err = CCDImport.SetDisplayConfig(myPathsCount, displayConfig.DisplayConfigPaths, myModesCount, displayConfig.DisplayConfigModes, SDC.DISPLAYMAGICIAN_SET);
|
||||
if (err == WIN32STATUS.ERROR_SUCCESS)
|
||||
{
|
||||
SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: Successfully set the display configuration to the settings supplied!");
|
||||
@ -671,7 +673,7 @@ namespace DisplayMagicianShared.Windows
|
||||
|
||||
SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: SUCCESS! The display configuration has been successfully applied");
|
||||
|
||||
foreach (ADVANCED_HDR_INFO_PER_PATH myHDRstate in displayConfig.displayHDRStates)
|
||||
foreach (ADVANCED_HDR_INFO_PER_PATH myHDRstate in displayConfig.DisplayHDRStates)
|
||||
{
|
||||
SharedLogger.logger.Trace($"Trying to get information whether HDR color is in use now on Display {myHDRstate.Id}.");
|
||||
// Get advanced HDR info
|
||||
@ -740,18 +742,18 @@ namespace DisplayMagicianShared.Windows
|
||||
|
||||
}
|
||||
|
||||
public bool IsPossibleConfig(WINDOWS_DISPLAY_CONFIG displayConfig)
|
||||
public bool IsValidConfig(WINDOWS_DISPLAY_CONFIG displayConfig)
|
||||
{
|
||||
// Get the all possible windows display configs
|
||||
// Get the current windows display configs
|
||||
WINDOWS_DISPLAY_CONFIG allWindowsDisplayConfig = GetWindowsDisplayConfig(QDC.QDC_ALL_PATHS);
|
||||
|
||||
SharedLogger.logger.Trace("WinLibrary/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)
|
||||
foreach (string savedAdapterName in displayConfig.DisplayAdapters.Values)
|
||||
{
|
||||
// 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))
|
||||
if (!allWindowsDisplayConfig.DisplayAdapters.Values.Contains(savedAdapterName))
|
||||
{
|
||||
SharedLogger.logger.Error($"WinLibrary/PatchAdapterIDs: ERROR - Saved adapter {savedAdapterName} is not available right now! This display configuration won't work!");
|
||||
return false;
|
||||
@ -761,13 +763,13 @@ namespace DisplayMagicianShared.Windows
|
||||
|
||||
// Now we go through the Paths to update the LUIDs as per Soroush's suggestion
|
||||
SharedLogger.logger.Trace($"WinLibrary/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);
|
||||
PatchAdapterIDs(ref displayConfig, allWindowsDisplayConfig.DisplayAdapters);
|
||||
|
||||
SharedLogger.logger.Trace($"WinLibrary/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);
|
||||
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($"WinLibrary/IsPossibleConfig: SetDisplayConfig validated that the display configuration is valid and can be used!");
|
||||
@ -781,6 +783,29 @@ namespace DisplayMagicianShared.Windows
|
||||
|
||||
}
|
||||
|
||||
public bool IsPossibleConfig(WINDOWS_DISPLAY_CONFIG displayConfig)
|
||||
{
|
||||
// We want to check the Windows Display profile can be used now
|
||||
SharedLogger.logger.Trace($"WinLibrary/IsPossibleConfig: Testing whether the Windows display configuration is possible to be used now");
|
||||
|
||||
// check what the currently available displays are (include the ones not active)
|
||||
List<string> currentAllIds = GetAllConnectedDisplayIdentifiers();
|
||||
|
||||
// CHeck that we have all the displayConfig DisplayIdentifiers we need available now
|
||||
//if (currentAllIds.Intersect(displayConfig.DisplayIdentifiers).Count() == displayConfig.DisplayIdentifiers.Count)
|
||||
if (displayConfig.DisplayIdentifiers.All(value => currentAllIds.Contains(value)))
|
||||
{
|
||||
SharedLogger.logger.Trace($"WinLibrary/IsPossibleConfig: Success! THe Windows display configuration is possible to be used now");
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
SharedLogger.logger.Trace($"WinLibrary/IsPossibleConfig: Uh oh! THe Windows display configuration is possible cannot be used now");
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public List<string> GetCurrentDisplayIdentifiers()
|
||||
{
|
||||
SharedLogger.logger.Error($"WinLibrary/GetCurrentDisplayIdentifiers: Getting the current display identifiers for the displays in use now");
|
||||
@ -803,7 +828,7 @@ namespace DisplayMagicianShared.Windows
|
||||
// Get the size of the largest Active Paths and Modes arrays
|
||||
int pathCount = 0;
|
||||
int modeCount = 0;
|
||||
WIN32STATUS err = CCDImport.GetDisplayConfigBufferSizes(QDC.QDC_ONLY_ACTIVE_PATHS, out pathCount, out modeCount);
|
||||
WIN32STATUS err = CCDImport.GetDisplayConfigBufferSizes(selector, out pathCount, out modeCount);
|
||||
if (err != WIN32STATUS.ERROR_SUCCESS)
|
||||
{
|
||||
SharedLogger.logger.Error($"WinLibrary/PrintActiveConfig: ERROR - GetDisplayConfigBufferSizes returned WIN32STATUS {err} when trying to get the maximum path and mode sizes");
|
||||
@ -813,14 +838,14 @@ namespace DisplayMagicianShared.Windows
|
||||
SharedLogger.logger.Trace($"WinLibrary/GetSomeDisplayIdentifiers: Getting the current Display Config path and mode arrays");
|
||||
var paths = new DISPLAYCONFIG_PATH_INFO[pathCount];
|
||||
var modes = new DISPLAYCONFIG_MODE_INFO[modeCount];
|
||||
err = CCDImport.QueryDisplayConfig(QDC.QDC_ONLY_ACTIVE_PATHS, ref pathCount, paths, ref modeCount, modes, IntPtr.Zero);
|
||||
err = CCDImport.QueryDisplayConfig(selector, ref pathCount, paths, ref modeCount, modes, IntPtr.Zero);
|
||||
if (err == WIN32STATUS.ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
SharedLogger.logger.Warn($"WinLibrary/GetSomeDisplayIdentifiers: The displays were modified between GetDisplayConfigBufferSizes and QueryDisplayConfig so we need to get the buffer sizes again.");
|
||||
SharedLogger.logger.Trace($"WinLibrary/GetSomeDisplayIdentifiers: Getting the size of the largest Active Paths and Modes arrays");
|
||||
// Screen changed in between GetDisplayConfigBufferSizes and QueryDisplayConfig, so we need to get buffer sizes again
|
||||
// as per https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-querydisplayconfig
|
||||
err = CCDImport.GetDisplayConfigBufferSizes(QDC.QDC_ONLY_ACTIVE_PATHS, out pathCount, out modeCount);
|
||||
err = CCDImport.GetDisplayConfigBufferSizes(selector, out pathCount, out modeCount);
|
||||
if (err != WIN32STATUS.ERROR_SUCCESS)
|
||||
{
|
||||
SharedLogger.logger.Error($"WinLibrary/GetSomeDisplayIdentifiers: ERROR - GetDisplayConfigBufferSizes returned WIN32STATUS {err} when trying to get the maximum path and mode sizes again");
|
||||
@ -829,7 +854,7 @@ namespace DisplayMagicianShared.Windows
|
||||
SharedLogger.logger.Trace($"WinLibrary/GetSomeDisplayIdentifiers: Getting the current Display Config path and mode arrays");
|
||||
paths = new DISPLAYCONFIG_PATH_INFO[pathCount];
|
||||
modes = new DISPLAYCONFIG_MODE_INFO[modeCount];
|
||||
err = CCDImport.QueryDisplayConfig(QDC.QDC_ONLY_ACTIVE_PATHS, ref pathCount, paths, ref modeCount, modes, IntPtr.Zero);
|
||||
err = CCDImport.QueryDisplayConfig(selector, ref pathCount, paths, ref modeCount, modes, IntPtr.Zero);
|
||||
if (err == WIN32STATUS.ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
SharedLogger.logger.Error($"WinLibrary/GetSomeDisplayIdentifiers: ERROR - The displays were still modified between GetDisplayConfigBufferSizes and QueryDisplayConfig, even though we tried twice. Something is wrong.");
|
||||
@ -971,6 +996,120 @@ namespace DisplayMagicianShared.Windows
|
||||
return displayIdentifiers;
|
||||
}
|
||||
|
||||
public List<string> GetCurrentPCIVideoCardVendors()
|
||||
{
|
||||
SharedLogger.logger.Error($"WinLibrary/GetCurrentPCIVideoCardVendors: Getting the current PCI vendor ids for the videocards reported to Windows");
|
||||
List<string> videoCardVendorIds = new List<string>();
|
||||
|
||||
|
||||
SharedLogger.logger.Trace($"WinLibrary/GetCurrentPCIVideoCardVendors: Testing whether the display configuration is valid (allowing tweaks).");
|
||||
// Get the size of the largest Active Paths and Modes arrays
|
||||
int pathCount = 0;
|
||||
int modeCount = 0;
|
||||
WIN32STATUS err = CCDImport.GetDisplayConfigBufferSizes(QDC.QDC_ONLY_ACTIVE_PATHS, out pathCount, out modeCount);
|
||||
if (err != WIN32STATUS.ERROR_SUCCESS)
|
||||
{
|
||||
SharedLogger.logger.Error($"WinLibrary/GetCurrentPCIVideoCardVendors: ERROR - GetDisplayConfigBufferSizes returned WIN32STATUS {err} when trying to get the maximum path and mode sizes");
|
||||
throw new WinLibraryException($"GetDisplayConfigBufferSizes returned WIN32STATUS {err} when trying to get the maximum path and mode sizes");
|
||||
}
|
||||
|
||||
SharedLogger.logger.Trace($"WinLibrary/GetSomeDisplayIdentifiers: Getting the current Display Config path and mode arrays");
|
||||
var paths = new DISPLAYCONFIG_PATH_INFO[pathCount];
|
||||
var modes = new DISPLAYCONFIG_MODE_INFO[modeCount];
|
||||
err = CCDImport.QueryDisplayConfig(QDC.QDC_ONLY_ACTIVE_PATHS, ref pathCount, paths, ref modeCount, modes, IntPtr.Zero);
|
||||
if (err == WIN32STATUS.ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
SharedLogger.logger.Warn($"WinLibrary/GetCurrentPCIVideoCardVendors: The displays were modified between GetDisplayConfigBufferSizes and QueryDisplayConfig so we need to get the buffer sizes again.");
|
||||
SharedLogger.logger.Trace($"WinLibrary/GetCurrentPCIVideoCardVendors: Getting the size of the largest Active Paths and Modes arrays");
|
||||
// Screen changed in between GetDisplayConfigBufferSizes and QueryDisplayConfig, so we need to get buffer sizes again
|
||||
// as per https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-querydisplayconfig
|
||||
err = CCDImport.GetDisplayConfigBufferSizes(QDC.QDC_ONLY_ACTIVE_PATHS, out pathCount, out modeCount);
|
||||
if (err != WIN32STATUS.ERROR_SUCCESS)
|
||||
{
|
||||
SharedLogger.logger.Error($"WinLibrary/GetCurrentPCIVideoCardVendors: ERROR - GetDisplayConfigBufferSizes returned WIN32STATUS {err} when trying to get the maximum path and mode sizes again");
|
||||
throw new WinLibraryException($"GetDisplayConfigBufferSizes returned WIN32STATUS {err} when trying to get the maximum path and mode sizes again");
|
||||
}
|
||||
SharedLogger.logger.Trace($"WinLibrary/GetSomeDisplayIdentifiers: Getting the current Display Config path and mode arrays");
|
||||
paths = new DISPLAYCONFIG_PATH_INFO[pathCount];
|
||||
modes = new DISPLAYCONFIG_MODE_INFO[modeCount];
|
||||
err = CCDImport.QueryDisplayConfig(QDC.QDC_ONLY_ACTIVE_PATHS, ref pathCount, paths, ref modeCount, modes, IntPtr.Zero);
|
||||
if (err == WIN32STATUS.ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
SharedLogger.logger.Error($"WinLibrary/GetCurrentPCIVideoCardVendors: ERROR - The displays were still modified between GetDisplayConfigBufferSizes and QueryDisplayConfig, even though we tried twice. Something is wrong.");
|
||||
throw new WinLibraryException($"The displays were still modified between GetDisplayConfigBufferSizes and QueryDisplayConfig, even though we tried twice. Something is wrong.");
|
||||
}
|
||||
else if (err != WIN32STATUS.ERROR_SUCCESS)
|
||||
{
|
||||
SharedLogger.logger.Error($"WinLibrary/GetCurrentPCIVideoCardVendors: ERROR - QueryDisplayConfig returned WIN32STATUS {err} when trying to query all available displays again");
|
||||
throw new WinLibraryException($"QueryDisplayConfig returned WIN32STATUS {err} when trying to query all available displays again.");
|
||||
}
|
||||
}
|
||||
else if (err != WIN32STATUS.ERROR_SUCCESS)
|
||||
{
|
||||
SharedLogger.logger.Error($"WinLibrary/GetCurrentPCIVideoCardVendors: ERROR - QueryDisplayConfig returned WIN32STATUS {err} when trying to query all available displays");
|
||||
throw new WinLibraryException($"QueryDisplayConfig returned WIN32STATUS {err} when trying to query all available displays.");
|
||||
}
|
||||
|
||||
foreach (var path in paths)
|
||||
{
|
||||
if (path.TargetInfo.TargetAvailable == false)
|
||||
{
|
||||
// We want to skip this one cause it's not valid
|
||||
SharedLogger.logger.Trace($"WinLibrary/GetCurrentPCIVideoCardVendors: Skipping path due to TargetAvailable not existing in display #{path.TargetInfo.Id}");
|
||||
continue;
|
||||
}
|
||||
|
||||
// get display adapter name
|
||||
var adapterInfo = new DISPLAYCONFIG_ADAPTER_NAME();
|
||||
adapterInfo.Header.Type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_GET_ADAPTER_NAME;
|
||||
adapterInfo.Header.Size = (uint)Marshal.SizeOf<DISPLAYCONFIG_ADAPTER_NAME>();
|
||||
adapterInfo.Header.AdapterId = path.TargetInfo.AdapterId;
|
||||
adapterInfo.Header.Id = path.TargetInfo.Id;
|
||||
err = CCDImport.DisplayConfigGetDeviceInfo(ref adapterInfo);
|
||||
if (err == WIN32STATUS.ERROR_SUCCESS)
|
||||
{
|
||||
SharedLogger.logger.Trace($"WinLibrary/GetCurrentPCIVideoCardVendors: Successfully got the display name info from {path.TargetInfo.Id}.");
|
||||
}
|
||||
else
|
||||
{
|
||||
SharedLogger.logger.Warn($"WinLibrary/GetCurrentPCIVideoCardVendors: WARNING - DisplayConfigGetDeviceInfo returned WIN32STATUS {err} when trying to get the target info for display #{path.TargetInfo.Id}");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// The AdapterDevicePath is something like "\\\\?\\PCI#VEN_10DE&DEV_2482&SUBSYS_408E1458&REV_A1#4&2283f625&0&0019#{5b45201d-f2f2-4f3b-85bb-30ff1f953599}"
|
||||
// We only want the vendor ID
|
||||
SharedLogger.logger.Trace($"WinLibrary/GetCurrentPCIVideoCardVendors: The AdapterDevicePath for this path is :{adapterInfo.AdapterDevicePath}");
|
||||
// Match against the vendor ID
|
||||
string pattern = @"VEN_([\d\w]{4})&";
|
||||
Match match = Regex.Match(adapterInfo.AdapterDevicePath, pattern);
|
||||
if (match.Success)
|
||||
{
|
||||
string VendorId = match.Groups[1].Value;
|
||||
SharedLogger.logger.Trace($"WinLibrary/GetCurrentPCIVideoCardVendors: The matched PCI Vendor ID is :{VendorId }");
|
||||
if (!videoCardVendorIds.Contains(VendorId))
|
||||
{
|
||||
videoCardVendorIds.Add(VendorId);
|
||||
SharedLogger.logger.Trace($"WinLibrary/GetCurrentPCIVideoCardVendors: Stored PCI vendor ID {VendorId} as we haven't already got it");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SharedLogger.logger.Trace($"WinLibrary/GetCurrentPCIVideoCardVendors: The PCI Vendor ID pattern wasn't matched so we didn't record a vendor ID.");
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
SharedLogger.logger.Warn(ex, $"WinLibrary/GetCurrentPCIVideoCardVendors: Exception getting PCI Vendor ID from Display Adapter {path.SourceInfo.AdapterId}.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return videoCardVendorIds;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[global::System.Serializable]
|
||||
|
Loading…
Reference in New Issue
Block a user