Commit 013aeeae authored by Nick Czajka's avatar Nick Czajka Committed by Commit Bot

Fix resolution menu not appearing for HDMI monitors

Duplicate modes were causing lookups in modeToParentModeMap_ to fail,
resulting in undefined pref values and errors at the display menu level.

This change ensures that all modes have an entry in
modeToParentModeMap_.

It also introduces a preference for native or selected modes when
de-duplicating equivalent modes.

Bug: 1127398
Change-Id: I7be8f1e34b31e1a1e7f3b106519c5ce529f568c7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2406716
Commit-Queue: Nick Czajka <czajka@google.com>
Reviewed-by: default avatarZentaro Kavanagh <zentaro@chromium.org>
Reviewed-by: default avatarBailey Berro <baileyberro@chromium.org>
Cr-Commit-Position: refs/heads/master@{#809097}
parent bcb580f0
...@@ -573,6 +573,15 @@ cr.define('settings.display', function() { ...@@ -573,6 +573,15 @@ cr.define('settings.display', function() {
modes.get(mode.width).set(mode.height, new Map()); modes.get(mode.width).set(mode.height, new Map());
} }
// Prefer the first native mode we find, for consistency.
if (modes.get(mode.width).get(mode.height).has(mode.refreshRate)) {
const existingModeIndex =
modes.get(mode.width).get(mode.height).get(mode.refreshRate);
const existingMode = selectedDisplay.modes[existingModeIndex];
if (existingMode.isNative || !mode.isNative) {
continue;
}
}
modes.get(mode.width).get(mode.height).set(mode.refreshRate, i); modes.get(mode.width).get(mode.height).set(mode.refreshRate, i);
} }
return modes; return modes;
...@@ -612,8 +621,8 @@ cr.define('settings.display', function() { ...@@ -612,8 +621,8 @@ cr.define('settings.display', function() {
// (resolution) is the default and therefore the "parent" mode. // (resolution) is the default and therefore the "parent" mode.
const height = heightArr[j]; const height = heightArr[j];
const refreshRates = heightsMap.get(height); const refreshRates = heightsMap.get(height);
const parentModeIndex = this.getParentModeIndex_(refreshRates);
this.addResolution_(width, height, refreshRates); this.addResolution_(parentModeIndex, width, height);
// For each of the refresh rates at a given resolution, add an entry // For each of the refresh rates at a given resolution, add an entry
// to |parentModeToRefreshRateMap_|. This allows us to retrieve a // to |parentModeToRefreshRateMap_|. This allows us to retrieve a
...@@ -621,7 +630,6 @@ cr.define('settings.display', function() { ...@@ -621,7 +630,6 @@ cr.define('settings.display', function() {
// parentModeIndex. // parentModeIndex.
const refreshRatesArr = Array.from(refreshRates.keys()); const refreshRatesArr = Array.from(refreshRates.keys());
for (let k = 0; k < refreshRatesArr.length; k++) { for (let k = 0; k < refreshRatesArr.length; k++) {
const parentModeIndex = Array.from(refreshRates.values())[0];
const rate = refreshRatesArr[k]; const rate = refreshRatesArr[k];
const modeIndex = refreshRates.get(rate); const modeIndex = refreshRates.get(rate);
const isInterlaced = selectedDisplay.modes[modeIndex].isInterlaced; const isInterlaced = selectedDisplay.modes[modeIndex].isInterlaced;
...@@ -632,25 +640,44 @@ cr.define('settings.display', function() { ...@@ -632,25 +640,44 @@ cr.define('settings.display', function() {
} }
} }
// Construct mode->parentMode map so we can get parent modes later.
for (let i = 0; i < selectedDisplay.modes.length; i++) {
const mode = selectedDisplay.modes[i];
const parentModeIndex =
this.getParentModeIndex_(modes.get(mode.width).get(mode.height));
this.modeToParentModeMap_.set(i, parentModeIndex);
}
assert(this.modeToParentModeMap_.size == selectedDisplay.modes.length);
// Use the new sort order. // Use the new sort order.
this.sortResolutionList_(); this.sortResolutionList_();
}, },
/**
* Picks the appropriate parent mode from a refresh rate -> mode index map.
* Currently this chooses the mode with the highest refresh rate.
* @param {Map<number,number>} refreshRates each possible refresh rate
* mapped to the corresponding mode index.
* @private
*/
getParentModeIndex_(refreshRates) {
const maxRefreshRate = Math.max(...refreshRates.keys());
return refreshRates.get(maxRefreshRate);
},
/** /**
* Adds a an entry in |displayModeList_| for the resolution represented by * Adds a an entry in |displayModeList_| for the resolution represented by
* |width| and |height| and possible |refreshRates|. * |width| and |height| and possible |refreshRates|.
* @param {number} parentModeIndex
* @param {number} width * @param {number} width
* @param {number} height * @param {number} height
* @param {Map<number,number>} refreshRates each possible refresh rate for
* the resolution mapped to the corresponding modeIndex.
* @private * @private
*/ */
addResolution_(width, height, refreshRates) { addResolution_(parentModeIndex, width, height) {
assert(this.listAllDisplayModes_); assert(this.listAllDisplayModes_);
const parentModeIndex = Array.from(refreshRates.values())[0];
// Add an entry in the outer map for |parentModeIndex|. The inner // Add an entry in the outer map for |parentModeIndex|. The inner
// array (the value at |parentModeIndex) will be populated with all // array (the value at |parentModeIndex|) will be populated with all
// possible refresh rates for the given resolution. // possible refresh rates for the given resolution.
this.parentModeToRefreshRateMap_.set(parentModeIndex, new Array()); this.parentModeToRefreshRateMap_.set(parentModeIndex, new Array());
...@@ -676,9 +703,6 @@ cr.define('settings.display', function() { ...@@ -676,9 +703,6 @@ cr.define('settings.display', function() {
*/ */
addRefreshRate_(parentModeIndex, modeIndex, rate, isInterlaced) { addRefreshRate_(parentModeIndex, modeIndex, rate, isInterlaced) {
assert(this.listAllDisplayModes_); assert(this.listAllDisplayModes_);
// Maintain a mapping from a given |modeIndex| back to the
// corresponding |parentModeIndex|.
this.modeToParentModeMap_.set(modeIndex, parentModeIndex);
// Truncate at two decimal places for display. If the refresh rate // Truncate at two decimal places for display. If the refresh rate
// is a whole number, remove the mantissa. // is a whole number, remove the mantissa.
......
...@@ -494,6 +494,25 @@ cr.define('device_page_tests', function() { ...@@ -494,6 +494,25 @@ cr.define('device_page_tests', function() {
height: 2000, height: 2000,
refreshRate: 75, refreshRate: 75,
}, },
// Include 3 copies of 3000x2000 mode to emulate duplicated modes
// reported by some monitors. Only one is marked 'isNative'.
{
deviceScaleFactor: 1.0,
widthInNativePixels: 3000,
heightInNativePixels: 2000,
width: 3000,
height: 2000,
refreshRate: 100,
},
{
isNative: true,
deviceScaleFactor: 1.0,
widthInNativePixels: 3000,
heightInNativePixels: 2000,
width: 3000,
height: 2000,
refreshRate: 100,
},
{ {
deviceScaleFactor: 1.0, deviceScaleFactor: 1.0,
widthInNativePixels: 3000, widthInNativePixels: 3000,
...@@ -954,12 +973,14 @@ cr.define('device_page_tests', function() { ...@@ -954,12 +973,14 @@ cr.define('device_page_tests', function() {
// Verify the display modes are parsed correctly. // Verify the display modes are parsed correctly.
// 5 total modes, 2 parent modes. // 5 total modes, 2 parent modes.
expectEquals(5, displayPage.modeToParentModeMap_.size); expectEquals(7, displayPage.modeToParentModeMap_.size);
expectEquals(0, displayPage.modeToParentModeMap_.get(0)); expectEquals(0, displayPage.modeToParentModeMap_.get(0));
expectEquals(0, displayPage.modeToParentModeMap_.get(1)); expectEquals(0, displayPage.modeToParentModeMap_.get(1));
expectEquals(2, displayPage.modeToParentModeMap_.get(2)); expectEquals(5, displayPage.modeToParentModeMap_.get(2));
expectEquals(2, displayPage.modeToParentModeMap_.get(3)); expectEquals(5, displayPage.modeToParentModeMap_.get(3));
expectEquals(2, displayPage.modeToParentModeMap_.get(4)); expectEquals(5, displayPage.modeToParentModeMap_.get(4));
expectEquals(5, displayPage.modeToParentModeMap_.get(5));
expectEquals(5, displayPage.modeToParentModeMap_.get(6));
// Two resolution options, one for each parent mode. // Two resolution options, one for each parent mode.
expectEquals(2, displayPage.refreshRateList_.length); expectEquals(2, displayPage.refreshRateList_.length);
...@@ -969,7 +990,7 @@ cr.define('device_page_tests', function() { ...@@ -969,7 +990,7 @@ cr.define('device_page_tests', function() {
expectEquals( expectEquals(
2, displayPage.parentModeToRefreshRateMap_.get(0).length); 2, displayPage.parentModeToRefreshRateMap_.get(0).length);
expectEquals( expectEquals(
3, displayPage.parentModeToRefreshRateMap_.get(2).length); 3, displayPage.parentModeToRefreshRateMap_.get(5).length);
// Ambient EQ never shown on non-internal display regardless of // Ambient EQ never shown on non-internal display regardless of
// whether it is enabled. // whether it is enabled.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment