Updated WinLibrary to latest version

This corrects some errors with the WinLibrary and how it handles cloned displays.

Also removed the 0.5 second delay between the end of the NVIDIALibrary call, and the start of the WinLibrary one, because they do not appear to be needed based on the NVIDIALibrary testing we've been doing with NVIDIAInfo.

Also corrected some log entries and comments.
This commit is contained in:
Terry MacDonald 2021-12-11 00:15:49 +13:00
parent a7ef20677d
commit 9416ac3346
2 changed files with 115 additions and 34 deletions

View File

@ -664,8 +664,8 @@ namespace DisplayMagicianShared
{ {
SharedLogger.logger.Trace($"ProfileRepository/SetActive: The NVIDIA display settings within profile {Name} were successfully applied."); SharedLogger.logger.Trace($"ProfileRepository/SetActive: The NVIDIA display settings within profile {Name} were successfully applied.");
SharedLogger.logger.Trace($"ProfileRepository/SetActive: Waiting 0.5 seconds to let the NVIDIA display change take place before setting the Windows CCD display settings"); /*SharedLogger.logger.Trace($"ProfileRepository/SetActive: Waiting 0.5 seconds to let the NVIDIA display change take place before setting the Windows CCD display settings");
System.Threading.Thread.Sleep(500); System.Threading.Thread.Sleep(500);*/
// Lets update the screens so Windows knows whats happening // Lets update the screens so Windows knows whats happening
// NVIDIA makes such large changes to the available screens in windows, we need to do this. // NVIDIA makes such large changes to the available screens in windows, we need to do this.
@ -730,16 +730,16 @@ namespace DisplayMagicianShared
{ {
SharedLogger.logger.Trace($"ProfileRepository/SetActive: The AMD display settings within profile {Name} were successfully applied."); SharedLogger.logger.Trace($"ProfileRepository/SetActive: The AMD display settings within profile {Name} were successfully applied.");
SharedLogger.logger.Trace($"ProfileRepository/SetActive: Waiting 0.5 seconds to let the AMD display change take place before setting the Windows CCD display settings"); /*SharedLogger.logger.Trace($"ProfileRepository/SetActive: Waiting 0.5 seconds to let the AMD display change take place before setting the Windows CCD display settings");
System.Threading.Thread.Sleep(500); System.Threading.Thread.Sleep(500);
*/
// Lets update the screens so Windows knows whats happening // Lets update the screens so Windows knows whats happening
// NVIDIA makes such large changes to the available screens in windows, we need to do this. // AMD makes such large changes to the available screens in windows, we need to do this.
winLibrary.UpdateActiveConfig(); winLibrary.UpdateActiveConfig();
// Then let's try to also apply the windows changes // Then let's try to also apply the windows changes
// Note: we are unable to check if the Windows CCD display config is possible, as it won't match if either the current display config is a Mosaic config, // Note: we are unable to check if the Windows CCD display config is possible, as it won't match if either the current display config is an Eyefinity config,
// or if the display config we want to change to is a Mosaic config. So we just have to assume that it will work! // or if the display config we want to change to is an Eyefinity config. So we just have to assume that it will work!
bool itWorkedforWindows = winLibrary.SetActiveConfig(_windowsDisplayConfig); bool itWorkedforWindows = winLibrary.SetActiveConfig(_windowsDisplayConfig);
if (itWorkedforWindows) if (itWorkedforWindows)
{ {

View File

@ -359,28 +359,41 @@ namespace DisplayMagicianShared.Windows
// Next, extract the UID entries for the displays as that's what the Path IDs are normally supposed to be // Next, extract the UID entries for the displays as that's what the Path IDs are normally supposed to be
// This is how we know the actual target id's ofd the monitors currently connected // This is how we know the actual target id's ofd the monitors currently connected
Regex rx = new Regex(@"UID(?<uid>\d+)#", RegexOptions.Compiled | RegexOptions.IgnoreCase); Regex rx = new Regex(@"UID(?<uid>\d+)#", RegexOptions.Compiled | RegexOptions.IgnoreCase);
HashSet<uint> physicalTargetIdsToFind = new HashSet<uint>(); HashSet<uint> physicalTargetIdsAvailable = new HashSet<uint>();
foreach (string displayIdentifier in windowsDisplayConfig.DisplayIdentifiers) foreach (string displayIdentifier in windowsDisplayConfig.DisplayIdentifiers)
{ {
MatchCollection mc = rx.Matches(displayIdentifier); MatchCollection mc = rx.Matches(displayIdentifier);
if (mc.Count > 0) if (mc.Count > 0)
{ {
physicalTargetIdsToFind.Add(UInt32.Parse(mc[0].Groups["uid"].Value)); physicalTargetIdsAvailable.Add(UInt32.Parse(mc[0].Groups["uid"].Value));
} }
} }
// Now cycle through the paths and grab the HDR state information // Now cycle through the paths and grab the HDR state information
// and map the adapter name to adapter id // and map the adapter name to adapter id
HashSet<uint> targetIdsToChange = new HashSet<uint>(); List<uint> targetPathIdsToChange = new List<uint>();
List<uint> targetModeIdsToChange = new List<uint>();
List<uint> targetIdsFound = new List<uint>();
List<uint> replacementIds = new List<uint>();
bool isClonedProfile = false;
var hdrInfos = new ADVANCED_HDR_INFO_PER_PATH[pathCount]; var hdrInfos = new ADVANCED_HDR_INFO_PER_PATH[pathCount];
int hdrInfoCount = 0; int hdrInfoCount = 0;
for (int i = 0; i < paths.Length; i++) for (int i = 0; i < paths.Length; i++)
{ {
bool gotSourceDeviceName = false;
bool gotAdapterName = false;
bool gotAdvancedColorInfo = false;
bool gotSdrWhiteLevel = false;
// Figure out if this path has a physical targetId, and if it doesn't store it // Figure out if this path has a physical targetId, and if it doesn't store it
if (!physicalTargetIdsToFind.Contains(paths[i].TargetInfo.Id)) if (physicalTargetIdsAvailable.Contains(paths[i].TargetInfo.Id))
{
targetIdsFound.Add(paths[i].TargetInfo.Id);
}
else
{ {
// Add to the list of physical path target ids we need to patch later // Add to the list of physical path target ids we need to patch later
targetIdsToChange.Add(paths[i].TargetInfo.Id); targetPathIdsToChange.Add(paths[i].TargetInfo.Id);
} }
// Track if this display is a cloned path // Track if this display is a cloned path
@ -394,12 +407,14 @@ namespace DisplayMagicianShared.Windows
err = CCDImport.DisplayConfigGetDeviceInfo(ref sourceInfo); err = CCDImport.DisplayConfigGetDeviceInfo(ref sourceInfo);
if (err == WIN32STATUS.ERROR_SUCCESS) if (err == WIN32STATUS.ERROR_SUCCESS)
{ {
gotSourceDeviceName = true;
// Store it for later // Store it for later
if (windowsDisplayConfig.DisplaySources.ContainsKey(sourceInfo.ViewGdiDeviceName)) if (windowsDisplayConfig.DisplaySources.ContainsKey(sourceInfo.ViewGdiDeviceName))
{ {
// We already have at least one display using this source, so we need to add the other cloned display to the existing list // We already have at least one display using this source, so we need to add the other cloned display to the existing list
windowsDisplayConfig.DisplaySources[sourceInfo.ViewGdiDeviceName].Add(paths[i].SourceInfo.Id); windowsDisplayConfig.DisplaySources[sourceInfo.ViewGdiDeviceName].Add(paths[i].SourceInfo.Id);
isClonedPath = true; isClonedPath = true;
isClonedProfile = true;
windowsDisplayConfig.IsCloned = true; windowsDisplayConfig.IsCloned = true;
} }
else else
@ -440,6 +455,7 @@ namespace DisplayMagicianShared.Windows
err = CCDImport.DisplayConfigGetDeviceInfo(ref adapterInfo); err = CCDImport.DisplayConfigGetDeviceInfo(ref adapterInfo);
if (err == WIN32STATUS.ERROR_SUCCESS) if (err == WIN32STATUS.ERROR_SUCCESS)
{ {
gotAdapterName = true;
// Store it for later // Store it for later
windowsDisplayConfig.DisplayAdapters.Add(paths[i].TargetInfo.AdapterId.Value, adapterInfo.AdapterDevicePath); windowsDisplayConfig.DisplayAdapters.Add(paths[i].TargetInfo.AdapterId.Value, adapterInfo.AdapterDevicePath);
SharedLogger.logger.Trace($"WinLibrary/GetWindowsDisplayConfig: Found adapter name {adapterInfo.AdapterDevicePath} for adapter {paths[i].TargetInfo.AdapterId.Value}."); SharedLogger.logger.Trace($"WinLibrary/GetWindowsDisplayConfig: Found adapter name {adapterInfo.AdapterDevicePath} for adapter {paths[i].TargetInfo.AdapterId.Value}.");
@ -460,6 +476,7 @@ namespace DisplayMagicianShared.Windows
err = CCDImport.DisplayConfigGetDeviceInfo(ref colorInfo); err = CCDImport.DisplayConfigGetDeviceInfo(ref colorInfo);
if (err == WIN32STATUS.ERROR_SUCCESS) if (err == WIN32STATUS.ERROR_SUCCESS)
{ {
gotAdvancedColorInfo = true;
SharedLogger.logger.Trace($"WinLibrary/GetWindowsDisplayConfig: Found color info for display {paths[i].TargetInfo.Id}."); SharedLogger.logger.Trace($"WinLibrary/GetWindowsDisplayConfig: Found color info for display {paths[i].TargetInfo.Id}.");
if (colorInfo.AdvancedColorSupported) if (colorInfo.AdvancedColorSupported)
{ {
@ -484,7 +501,7 @@ namespace DisplayMagicianShared.Windows
} }
// get SDR white levels // get SDR white levels
SharedLogger.logger.Trace($"WinLibrary/GetWindowsDisplayConfig: Attempting to get SDR white levels for adapter {paths[i].TargetInfo.AdapterId.Value}."); SharedLogger.logger.Trace($"WinLibrary/GetWindowsDisplayConfig: Attempting to get SDR white levels for display {paths[i].TargetInfo.Id}.");
var whiteLevelInfo = new DISPLAYCONFIG_SDR_WHITE_LEVEL(); var whiteLevelInfo = new DISPLAYCONFIG_SDR_WHITE_LEVEL();
whiteLevelInfo.Header.Type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_GET_SDR_WHITE_LEVEL; whiteLevelInfo.Header.Type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_GET_SDR_WHITE_LEVEL;
whiteLevelInfo.Header.Size = (uint)Marshal.SizeOf<DISPLAYCONFIG_SDR_WHITE_LEVEL>(); whiteLevelInfo.Header.Size = (uint)Marshal.SizeOf<DISPLAYCONFIG_SDR_WHITE_LEVEL>();
@ -493,6 +510,7 @@ namespace DisplayMagicianShared.Windows
err = CCDImport.DisplayConfigGetDeviceInfo(ref whiteLevelInfo); err = CCDImport.DisplayConfigGetDeviceInfo(ref whiteLevelInfo);
if (err == WIN32STATUS.ERROR_SUCCESS) if (err == WIN32STATUS.ERROR_SUCCESS)
{ {
gotSdrWhiteLevel = true;
SharedLogger.logger.Trace($"WinLibrary/GetWindowsDisplayConfig: Found SDR White levels for display {paths[i].TargetInfo.Id}."); SharedLogger.logger.Trace($"WinLibrary/GetWindowsDisplayConfig: Found SDR White levels for display {paths[i].TargetInfo.Id}.");
} }
else else
@ -503,39 +521,103 @@ namespace DisplayMagicianShared.Windows
hdrInfos[hdrInfoCount] = new ADVANCED_HDR_INFO_PER_PATH(); hdrInfos[hdrInfoCount] = new ADVANCED_HDR_INFO_PER_PATH();
hdrInfos[hdrInfoCount].AdapterId = paths[i].TargetInfo.AdapterId; hdrInfos[hdrInfoCount].AdapterId = paths[i].TargetInfo.AdapterId;
hdrInfos[hdrInfoCount].Id = paths[i].TargetInfo.Id; hdrInfos[hdrInfoCount].Id = paths[i].TargetInfo.Id;
hdrInfos[hdrInfoCount].AdvancedColorInfo = colorInfo; if (gotAdvancedColorInfo)
hdrInfos[hdrInfoCount].SDRWhiteLevel = whiteLevelInfo; {
hdrInfos[hdrInfoCount].AdvancedColorInfo = colorInfo;
}
if (gotSdrWhiteLevel)
{
hdrInfos[hdrInfoCount].SDRWhiteLevel = whiteLevelInfo;
}
hdrInfoCount++; hdrInfoCount++;
} }
// Now we need to figure out the maps between the cloned ID and the real physical target id
// the Advanced color info structure actually holds this information! So lets mine it.
Dictionary<uint, uint> targetIdMap = new Dictionary<uint, uint>();
foreach (var hdrInfo in hdrInfos)
{
targetIdMap[hdrInfo.Id] = hdrInfo.AdvancedColorInfo.Header.Id;
}
// Now we need to go through the list of paths again and patch the 'cloned' displays with a real display ID so the config works // Go through the list of physicalTargetIdsAvailable
for (int i = 0; i < paths.Length; i++) // ignore the ones that were found
// if one was not found, then
// go through the modes
// patch the target
if (isClonedProfile)
{ {
if (targetIdsToChange.Contains(paths[i].TargetInfo.Id)) // Figure out which available displays are unused (in path priority order)
foreach (var physicalTargetId in physicalTargetIdsAvailable)
{ {
// Patch the cloned ids with a real working one! if (!targetIdsFound.Contains(physicalTargetId))
paths[i].TargetInfo.Id = targetIdMap[paths[i].TargetInfo.Id]; {
// this is a candidate physical target id to use as a replacement
replacementIds.Add(physicalTargetId);
}
}
// Now go through and figure out a mapping of old target id to new replacement id
Dictionary<uint, uint> targetIdMap = new Dictionary<uint, uint>();
for (int i = 0; i < targetPathIdsToChange.Count; i++)
{
uint targetPathId = targetPathIdsToChange[i];
if (i < replacementIds.Count)
{
targetIdMap[targetPathId] = replacementIds[i];
}
}
// Now we need to go through the list of paths again and patch the 'cloned' displays with a real display ID so the config works
for (int i = 0; i < paths.Length; i++)
{
if (targetIdMap.ContainsKey(paths[i].TargetInfo.Id))
{
// Patch the cloned ids with a real working one!
paths[i].TargetInfo.Id = targetIdMap[paths[i].TargetInfo.Id];
}
}
// And then we need to go through the list of modes again and patch the 'cloned' displays with a real display ID so the display layout is right in cloned displays
for (int i = 0; i < modes.Length; i++)
{
// We only change the ids that match in InfoType for target displays
if (modes[i].InfoType == DISPLAYCONFIG_MODE_INFO_TYPE.DISPLAYCONFIG_MODE_INFO_TYPE_TARGET && targetIdMap.ContainsKey(modes[i].Id))
{
// Patch the cloned ids with a real working one!
modes[i].Id = targetIdMap[modes[i].Id];
}
} }
} }
// And then we need to go through the list of modes again and patch the 'cloned' displays with a real display ID so the display layout is right in cloned displays
for (int i = 0; i < modes.Length; i++) /*if (hdrInfos.Length > 0)
{ {
// We only change the ids that match in InfoType for target displays // If the screen
if (modes[i].InfoType == DISPLAYCONFIG_MODE_INFO_TYPE.DISPLAYCONFIG_MODE_INFO_TYPE_TARGET && targetIdsToChange.Contains(modes[i].Id)) foreach (var hdrInfo in hdrInfos)
{ {
// Patch the cloned ids with a real working one! targetIdMap[hdrInfo.Id] = hdrInfo.SDRWhiteLevel.Header.Id;
modes[i].Id = targetIdMap[modes[i].Id]; }
// Now we need to go through the list of paths again and patch the 'cloned' displays with a real display ID so the config works
for (int i = 0; i < paths.Length; i++)
{
if (targetIdsToChange.Contains(paths[i].TargetInfo.Id))
{
// Patch the cloned ids with a real working one!
paths[i].TargetInfo.Id = targetIdMap[paths[i].TargetInfo.Id];
}
}
// And then we need to go through the list of modes again and patch the 'cloned' displays with a real display ID so the display layout is right in cloned displays
for (int i = 0; i < modes.Length; i++)
{
// We only change the ids that match in InfoType for target displays
if (modes[i].InfoType == DISPLAYCONFIG_MODE_INFO_TYPE.DISPLAYCONFIG_MODE_INFO_TYPE_TARGET && targetIdsToChange.Contains(modes[i].Id))
{
// Patch the cloned ids with a real working one!
modes[i].Id = targetIdMap[modes[i].Id];
}
} }
} }
else
{
SharedLogger.logger.Warn($"WinLibrary/GetWindowsDisplayConfig: WARNING - There weren't any HDR Info objects created, so we have none to parse!");
}*/
// Store the active paths and modes in our display config object // Store the active paths and modes in our display config object
windowsDisplayConfig.DisplayConfigPaths = paths; windowsDisplayConfig.DisplayConfigPaths = paths;
@ -689,7 +771,6 @@ namespace DisplayMagicianShared.Windows
return DisplaySources; return DisplaySources;
} }
private LUID AdapterValueToLUID(ulong adapterValue) private LUID AdapterValueToLUID(ulong adapterValue)
{ {
LUID luid = new LUID(); LUID luid = new LUID();