From a5792d34938e1fd07110930477a67b42758cf86a Mon Sep 17 00:00:00 2001 From: "oshima@chromium.org" Date: Thu, 1 Aug 2013 11:18:21 +0000 Subject: Add ability to set resolution on external display * OutputConfigurator gets selected resolution via StateController::GetResolutionForDisplay * It only shows one selection per one resolution. Non interlaced takes precedence and best refresh rate is chosen. * Resolution list is added to DisplayInfo. UI can use this to present options to users. * Created separate display_util_x11 for utility functions that depends on xrandr. BUG=230733 TEST=covered by tests. more to come. manual test should be possible after UI is added. (crbug.com/266097) Review URL: https://chromiumcodereview.appspot.com/21297003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@214997 0039d316-1c4b-4281-b951-d872f2087c98 --- ash/ash.gyp | 4 +- ash/display/display_change_observer_x11.cc | 69 +++++--------- ash/display/display_change_observer_x11.h | 9 +- .../display_change_observer_x11_unittest.cc | 31 ------ ash/display/display_info.cc | 19 ++++ ash/display/display_info.h | 27 +++++- ash/display/display_manager.cc | 28 +++++- ash/display/display_manager.h | 13 ++- ash/display/display_util_x11.cc | 97 +++++++++++++++++++ ash/display/display_util_x11.h | 36 +++++++ ash/display/display_util_x11_unittest.cc | 104 +++++++++++++++++++++ 11 files changed, 351 insertions(+), 86 deletions(-) delete mode 100644 ash/display/display_change_observer_x11_unittest.cc create mode 100644 ash/display/display_util_x11.cc create mode 100644 ash/display/display_util_x11.h create mode 100644 ash/display/display_util_x11_unittest.cc (limited to 'ash') diff --git a/ash/ash.gyp b/ash/ash.gyp index 5c9d6ee..29a3c38 100644 --- a/ash/ash.gyp +++ b/ash/ash.gyp @@ -98,6 +98,8 @@ 'display/display_manager.cc', 'display/display_manager.h', 'display/display_pref_util.h', + 'display/display_util_x11.cc', + 'display/display_util_x11.h', 'display/event_transformation_handler.cc', 'display/event_transformation_handler.h', 'display/mirror_window_controller.cc', @@ -791,7 +793,7 @@ }], ['use_x11==1', { 'sources': [ - 'display/display_change_observer_x11_unittest.cc' + 'display/display_util_x11_unittest.cc' ], }], ['chromeos!=1', { diff --git a/ash/display/display_change_observer_x11.cc b/ash/display/display_change_observer_x11.cc index 8fa1730..860a5ea 100644 --- a/ash/display/display_change_observer_x11.cc +++ b/ash/display/display_change_observer_x11.cc @@ -15,6 +15,7 @@ #include "ash/display/display_info.h" #include "ash/display/display_layout_store.h" #include "ash/display/display_manager.h" +#include "ash/display/display_util_x11.h" #include "ash/shell.h" #include "base/command_line.h" #include "base/message_loop/message_pump_aurax11.h" @@ -26,40 +27,15 @@ namespace ash { namespace internal { - namespace { // The DPI threshold to detect high density screen. // Higher DPI than this will use device_scale_factor=2. -// Note: This value has to be kept in sync with the mouse/touchpad driver -// which controls mouse pointer acceleration. If you need to update this value, -// please update the bug (crosbug.com/31628) first and make sure that the -// driver will use the same value. -// This value also has to be kept in sync with the value in -// chromeos/display/output_configurator.cc. See crbug.com/130188 const unsigned int kHighDensityDPIThreshold = 160; // 1 inch in mm. const float kInchInMm = 25.4f; -XRRModeInfo* FindMode(XRRScreenResources* screen_resources, XID current_mode) { - for (int m = 0; m < screen_resources->nmode; m++) { - XRRModeInfo *mode = &screen_resources->modes[m]; - if (mode->id == current_mode) - return mode; - } - return NULL; -} - -// A list of bogus sizes in mm that X detects and should be ignored. -// See crbug.com/136533. -const unsigned long kInvalidDisplaySizeList[][2] = { - {40, 30}, - {50, 40}, - {160, 90}, - {160, 100}, -}; - int64 GetDisplayId(XID output, size_t output_index) { int64 display_id; if (chromeos::GetDisplayId(output, output_index, &display_id)) @@ -69,24 +45,6 @@ int64 GetDisplayId(XID output, size_t output_index) { } // namespace -bool ShouldIgnoreSize(unsigned long mm_width, unsigned long mm_height) { - // Ignore if the reported display is smaller than minimum size. - if (mm_width <= kInvalidDisplaySizeList[0][0] || - mm_height <= kInvalidDisplaySizeList[0][1]) { - LOG(WARNING) << "Smaller than minimum display size"; - return true; - } - for (unsigned long i = 1 ; i < arraysize(kInvalidDisplaySizeList); ++i) { - const unsigned long* size = kInvalidDisplaySizeList[i]; - if (mm_width == size[0] && mm_height == size[1]) { - LOG(WARNING) << "Black listed display size detected:" - << size[0] << "x" << size[1]; - return true; - } - } - return false; -} - DisplayChangeObserverX11::DisplayChangeObserverX11() : xdisplay_(base::MessagePumpAuraX11::GetDefaultXDisplay()), x_root_window_(DefaultRootWindow(xdisplay_)), @@ -116,6 +74,21 @@ chromeos::OutputState DisplayChangeObserverX11::GetStateForDisplayIds( chromeos::STATE_DUAL_MIRROR : chromeos::STATE_DUAL_EXTENDED; } +bool DisplayChangeObserverX11::GetResolutionForDisplayId(int64 display_id, + int* width, + int* height) const { + + gfx::Size resolution; + if (!Shell::GetInstance()->display_manager()-> + GetSelectedResolutionForDisplayId(display_id, &resolution)) { + return false; + } + + *width = resolution.width(); + *height = resolution.height(); + return true; +} + void DisplayChangeObserverX11::OnDisplayModeChanged() { XRRScreenResources* screen_resources = XRRGetScreenResources(xdisplay_, x_root_window_); @@ -151,13 +124,14 @@ void DisplayChangeObserverX11::OnDisplayModeChanged() { XRRFreeOutputInfo(output_info); continue; } - XRRCrtcInfo* crtc_info = crtc_info_map[output_info->crtc]; + const XRRCrtcInfo* crtc_info = crtc_info_map[output_info->crtc]; if (!crtc_info) { LOG(WARNING) << "Crtc not found for output: output_index=" << output_index; continue; } - XRRModeInfo* mode = FindMode(screen_resources, crtc_info->mode); + const XRRModeInfo* mode = + chromeos::FindModeInfo(screen_resources, crtc_info->mode); if (!mode) { LOG(WARNING) << "Could not find a mode for the output: output_index=" << output_index; @@ -173,6 +147,10 @@ void DisplayChangeObserverX11::OnDisplayModeChanged() { gfx::Rect display_bounds( crtc_info->x, crtc_info->y, mode->width, mode->height); + std::vector resolutions; + if (!is_internal) + resolutions = GetResolutionList(screen_resources, output_info); + XRRFreeOutputInfo(output_info); std::string name = is_internal ? @@ -195,6 +173,7 @@ void DisplayChangeObserverX11::OnDisplayModeChanged() { displays.back().set_device_scale_factor(device_scale_factor); displays.back().SetBounds(display_bounds); displays.back().set_native(true); + displays.back().set_resolutions(resolutions); } // Free all allocated resources. diff --git a/ash/display/display_change_observer_x11.h b/ash/display/display_change_observer_x11.h index 3d13e0d..6781151 100644 --- a/ash/display/display_change_observer_x11.h +++ b/ash/display/display_change_observer_x11.h @@ -31,6 +31,9 @@ class DisplayChangeObserverX11 // chromeos::OutputConfigurator::StateController overrides: virtual chromeos::OutputState GetStateForDisplayIds( const std::vector& outputs) const OVERRIDE; + virtual bool GetResolutionForDisplayId(int64 display_id, + int* width, + int* height) const OVERRIDE; // Overriden from chromeos::OutputConfigurator::Observer: virtual void OnDisplayModeChanged() OVERRIDE; @@ -48,12 +51,6 @@ class DisplayChangeObserverX11 DISALLOW_COPY_AND_ASSIGN(DisplayChangeObserverX11); }; -// Returns true if the size info in the output_info isn't valid -// and should be ignored. This is exposed for testing. -// |mm_width| and |mm_height| are given in millimeters. -ASH_EXPORT bool ShouldIgnoreSize(unsigned long mm_width, - unsigned long mm_height); - } // namespace internal } // namespace ash diff --git a/ash/display/display_change_observer_x11_unittest.cc b/ash/display/display_change_observer_x11_unittest.cc deleted file mode 100644 index 8f81297..0000000 --- a/ash/display/display_change_observer_x11_unittest.cc +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ash/display/display_change_observer_x11.h" - -// Undefine X's macros used in gtest. -#undef Bool -#undef None - -#include "testing/gtest/include/gtest/gtest.h" - -typedef testing::Test DisplayChangeObserverX11Test; - -namespace ash { -namespace internal { - -TEST_F(DisplayChangeObserverX11Test, TestBlackListedDisplay) { - EXPECT_TRUE(ShouldIgnoreSize(10, 10)); - EXPECT_TRUE(ShouldIgnoreSize(40, 30)); - EXPECT_TRUE(ShouldIgnoreSize(50, 40)); - EXPECT_TRUE(ShouldIgnoreSize(160, 90)); - EXPECT_TRUE(ShouldIgnoreSize(160, 100)); - - EXPECT_FALSE(ShouldIgnoreSize(50, 60)); - EXPECT_FALSE(ShouldIgnoreSize(100, 70)); - EXPECT_FALSE(ShouldIgnoreSize(272, 181)); -} - -} // namespace internal -} // namespace ash diff --git a/ash/display/display_info.cc b/ash/display/display_info.cc index d886a59..8f71e6d 100644 --- a/ash/display/display_info.cc +++ b/ash/display/display_info.cc @@ -22,6 +22,11 @@ namespace ash { namespace internal { +Resolution::Resolution(const gfx::Size& size, bool interlaced) + : size(size), + interlaced(interlaced) { +} + // satic DisplayInfo DisplayInfo::CreateFromSpec(const std::string& spec) { return CreateFromSpecWithID(spec, gfx::Display::kInvalidDisplayID); @@ -148,6 +153,7 @@ void DisplayInfo::Copy(const DisplayInfo& native_info) { bounds_in_pixel_ = native_info.bounds_in_pixel_; size_in_pixel_ = native_info.size_in_pixel_; device_scale_factor_ = native_info.device_scale_factor_; + resolutions_ = native_info.resolutions_; // Copy overscan_insets_in_dip_ if it's not empty. This is for test // cases which use "/o" annotation which sets the overscan inset @@ -214,5 +220,18 @@ std::string DisplayInfo::ToString() const { ui_scale_); } +std::string DisplayInfo::ToFullString() const { + std::string resolutions_str; + std::vector::const_iterator iter = resolutions_.begin(); + for (; iter != resolutions_.end(); ++iter) { + if (!resolutions_str.empty()) + resolutions_str += ","; + resolutions_str += iter->size.ToString(); + if (iter->interlaced) + resolutions_str += "(i)"; + } + return ToString() + ", resolutions=" + resolutions_str; +} + } // namespace internal } // namespace ash diff --git a/ash/display/display_info.h b/ash/display/display_info.h index a679a73..899dd15 100644 --- a/ash/display/display_info.h +++ b/ash/display/display_info.h @@ -6,6 +6,7 @@ #define ASH_DISPLAY_DISPLAY_INFO_H_ #include +#include #include "ash/ash_export.h" #include "base/gtest_prod_util.h" @@ -16,6 +17,15 @@ namespace ash { namespace internal { +// A struct that represents the display's resolution and +// interlaced info. +struct ASH_EXPORT Resolution { + Resolution(const gfx::Size& size, bool interlaced); + + gfx::Size size; + bool interlaced; +}; + // DisplayInfo contains metadata for each display. This is used to // create |gfx::Display| as well as to maintain extra infomation // to manage displays in ash environment. @@ -114,9 +124,21 @@ class ASH_EXPORT DisplayInfo { void set_native(bool native) { native_ = native; } bool native() const { return native_; } - // Returns a string representation of the DisplayInfo; + const std::vector& resolutions() const { + return resolutions_; + } + void set_resolutions(std::vector& resolution) { + resolutions_.swap(resolution); + } + + // Returns a string representation of the DisplayInfo + // excluding resolutions. std::string ToString() const; + // Returns a string representation of the DisplayInfo + // including resolutions. + std::string ToFullString() const; + private: int64 id_; std::string name_; @@ -134,6 +156,9 @@ class ASH_EXPORT DisplayInfo { // True if this comes from native platform (DisplayChangeObserverX11). bool native_; + + // The list of resolutions supported by this display. + std::vector resolutions_; }; } // namespace internal diff --git a/ash/display/display_manager.cc b/ash/display/display_manager.cc index 48fb914..5943f99 100644 --- a/ash/display/display_manager.cc +++ b/ash/display/display_manager.cc @@ -321,11 +321,24 @@ void DisplayManager::SetDisplayUIScale(int64 display_id, UpdateDisplays(display_info_list); } +void DisplayManager::SetDisplayResolution(int64 display_id, + const gfx::Size& resolution) { + DCHECK_NE(gfx::Display::InternalDisplayId(), display_id); + if (gfx::Display::InternalDisplayId() == display_id) + return; + resolutions_[display_id] = resolution; +#if defined(OS_CHROMEOS) && defined(USE_X11) + if (base::chromeos::IsRunningOnChromeOS()) + Shell::GetInstance()->output_configurator()->ScheduleConfigureOutputs(); +#endif +} + void DisplayManager::RegisterDisplayProperty( int64 display_id, gfx::Display::Rotation rotation, float ui_scale, - const gfx::Insets* overscan_insets) { + const gfx::Insets* overscan_insets, + const gfx::Size& resolution_in_pixels) { if (display_info_.find(display_id) == display_info_.end()) { display_info_[display_id] = DisplayInfo(display_id, std::string(""), false); @@ -337,6 +350,19 @@ void DisplayManager::RegisterDisplayProperty( display_info_[display_id].set_ui_scale(ui_scale); if (overscan_insets) display_info_[display_id].SetOverscanInsets(*overscan_insets); + if (!resolution_in_pixels.IsEmpty()) + resolutions_[display_id] = resolution_in_pixels; +} + +bool DisplayManager::GetSelectedResolutionForDisplayId( + int64 id, + gfx::Size* resolution_out) const { + std::map::const_iterator iter = + resolutions_.find(id); + if (iter == resolutions_.end()) + return false; + *resolution_out = iter->second; + return true; } bool DisplayManager::IsDisplayRotationEnabled() const { diff --git a/ash/display/display_manager.h b/ash/display/display_manager.h index bfecbdc..24303e1 100644 --- a/ash/display/display_manager.h +++ b/ash/display/display_manager.h @@ -130,12 +130,20 @@ class ASH_EXPORT DisplayManager // Sets the display's ui scale. void SetDisplayUIScale(int64 display_id, float ui_scale); + // Sets the display's resolution. + void SetDisplayResolution(int64 display_id, const gfx::Size& resolution); + // Register per display properties. |overscan_insets| is NULL if // the display has no custom overscan insets. void RegisterDisplayProperty(int64 display_id, gfx::Display::Rotation rotation, float ui_scale, - const gfx::Insets* overscan_insets); + const gfx::Insets* overscan_insets, + const gfx::Size& resolution_in_pixels); + + // Returns the display's selected resolution. + bool GetSelectedResolutionForDisplayId(int64 display_id, + gfx::Size* resolution_out) const; // Tells if display rotation/ui scaling features are enabled. bool IsDisplayRotationEnabled() const; @@ -270,6 +278,9 @@ private: // The mapping from the display ID to its internal data. std::map display_info_; + // Selected resolutions for displays. Key is the displays' ID. + std::map resolutions_; + // When set to true, the host window's resize event updates // the display's size. This is set to true when running on // desktop environment (for debugging) so that resizing the host diff --git a/ash/display/display_util_x11.cc b/ash/display/display_util_x11.cc new file mode 100644 index 0000000..e662ce2 --- /dev/null +++ b/ash/display/display_util_x11.cc @@ -0,0 +1,97 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/display/display_util_x11.h" + +#include +#include +#include + +#include "ash/display/display_info.h" +#include "base/logging.h" +#include "chromeos/display/output_util.h" + +namespace ash { +namespace internal { +namespace { + +// A list of bogus sizes in mm that X detects that should be ignored. +// See crbug.com/136533. The first element maintains the minimum +// size required to be valid size. +const unsigned long kInvalidDisplaySizeList[][2] = { + {40, 30}, + {50, 40}, + {160, 90}, + {160, 100}, +}; + +// Resolution list are sorted by the area in pixels and the larger +// one comes first. +struct ResolutionSorter { + bool operator()(const Resolution& a, const Resolution& b) { + return a.size.width() * a.size.height() > b.size.width() * b.size.height(); + } +}; + +} // namespace + +bool ShouldIgnoreSize(unsigned long mm_width, unsigned long mm_height) { + // Ignore if the reported display is smaller than minimum size. + if (mm_width <= kInvalidDisplaySizeList[0][0] || + mm_height <= kInvalidDisplaySizeList[0][1]) { + LOG(WARNING) << "Smaller than minimum display size"; + return true; + } + for (unsigned long i = 1 ; i < arraysize(kInvalidDisplaySizeList); ++i) { + const unsigned long* size = kInvalidDisplaySizeList[i]; + if (mm_width == size[0] && mm_height == size[1]) { + LOG(WARNING) << "Black listed display size detected:" + << size[0] << "x" << size[1]; + return true; + } + } + return false; +} + +std::vector GetResolutionList( + XRRScreenResources* screen_resources, + XRROutputInfo* output_info) { + typedef std::map, Resolution> ResolutionMap; + + ResolutionMap resolution_map; + + for (int i = 0; i < output_info->nmode; i++) { + RRMode mode = output_info->modes[i]; + const XRRModeInfo* info = chromeos::FindModeInfo(screen_resources, mode); + DCHECK(info); + // Just ignore bad entry on Release build. + if (!info) + continue; + ResolutionMap::key_type size = std::make_pair(info->width, info->height); + bool interlaced = (info->modeFlags & RR_Interlace) != 0; + + ResolutionMap::iterator iter = resolution_map.find(size); + + // Add new resolution if it's new size or override interlaced mode. + if (iter == resolution_map.end()) { + resolution_map.insert(ResolutionMap::value_type( + size, + Resolution(gfx::Size(info->width, info->height), interlaced))); + } else if (iter->second.interlaced && !interlaced) { + iter->second.interlaced = false; + } + } + + std::vector resolution_list; + for (ResolutionMap::const_iterator iter = resolution_map.begin(); + iter != resolution_map.end(); + ++iter) { + resolution_list.push_back(iter->second); + } + std::sort(resolution_list.begin(), resolution_list.end(), ResolutionSorter()); + return resolution_list; +} + +} // namespace internal +} // namespace ash diff --git a/ash/display/display_util_x11.h b/ash/display/display_util_x11.h new file mode 100644 index 0000000..6647688 --- /dev/null +++ b/ash/display/display_util_x11.h @@ -0,0 +1,36 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_DISPLAY_DISPLAY_UTIL_X11_H_ +#define ASH_DISPLAY_DISPLAY_UTIL_X11_H_ + +#include + +#include "ash/ash_export.h" +#include "ash/display/display_info.h" + +struct _XRRScreenResources; +typedef _XRRScreenResources XRRScreenResources; +struct _XRROutputInfo; +typedef _XRROutputInfo XRROutputInfo; + +namespace ash { +namespace internal { +struct Resolution; + +// Returns true if the size info in the output_info isn't valid +// and should be ignored. This is exposed for testing. +// |mm_width| and |mm_height| are given in millimeters. +ASH_EXPORT bool ShouldIgnoreSize(unsigned long mm_width, + unsigned long mm_height); + +// Returns the resolution list. +ASH_EXPORT std::vector GetResolutionList( + XRRScreenResources* screen_resources, + XRROutputInfo* output_info); + +} // namespace internal +} // namespace ash + +#endif // ASH_DISPLAY_DISPLAY_UTIL_X11_H_ diff --git a/ash/display/display_util_x11_unittest.cc b/ash/display/display_util_x11_unittest.cc new file mode 100644 index 0000000..f534a28 --- /dev/null +++ b/ash/display/display_util_x11_unittest.cc @@ -0,0 +1,104 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/display/display_util_x11.h" + +#include + +// Undefine X's macros used in gtest. +#undef Bool +#undef None + +#include "chromeos/display/output_util.h" +#include "testing/gtest/include/gtest/gtest.h" + +typedef testing::Test DisplayUtilX11Test; + +namespace ash { +namespace internal { + +TEST_F(DisplayUtilX11Test, TestBlackListedDisplay) { + EXPECT_TRUE(ShouldIgnoreSize(10, 10)); + EXPECT_TRUE(ShouldIgnoreSize(40, 30)); + EXPECT_TRUE(ShouldIgnoreSize(50, 40)); + EXPECT_TRUE(ShouldIgnoreSize(160, 90)); + EXPECT_TRUE(ShouldIgnoreSize(160, 100)); + + EXPECT_FALSE(ShouldIgnoreSize(50, 60)); + EXPECT_FALSE(ShouldIgnoreSize(100, 70)); + EXPECT_FALSE(ShouldIgnoreSize(272, 181)); +} + +TEST_F(DisplayUtilX11Test, GetResolutionList) { + XRRScreenResources resources = {0}; + RROutput outputs[] = {1}; + resources.noutput = arraysize(outputs); + resources.outputs = outputs; + XRRModeInfo modes[] = { + // id, width, height, interlaced, refresh rate + chromeos::test::CreateModeInfo(11, 1920, 1200, false, 60.0f), + + // different rates + chromeos::test::CreateModeInfo(12, 1920, 1080, false, 30.0f), + chromeos::test::CreateModeInfo(13, 1920, 1080, false, 50.0f), + chromeos::test::CreateModeInfo(14, 1920, 1080, false, 40.0f), + + // interlace vs non interlace + chromeos::test::CreateModeInfo(15, 1280, 720, true, 60.0f), + chromeos::test::CreateModeInfo(16, 1280, 720, false, 40.0f), + + // interlace only + chromeos::test::CreateModeInfo(17, 1024, 768, true, 40.0f), + chromeos::test::CreateModeInfo(18, 1024, 768, true, 60.0f), + + // mixed + chromeos::test::CreateModeInfo(19, 1024, 600, true, 60.0f), + chromeos::test::CreateModeInfo(20, 1024, 600, false, 40.0f), + chromeos::test::CreateModeInfo(21, 1024, 600, false, 50.0f), + + // just one interlaced mode + chromeos::test::CreateModeInfo(22, 640, 480, true, 60.0f), + }; + resources.nmode = arraysize(modes); + resources.modes = modes; + + XRROutputInfo output_info = {0}; + RRMode output_modes[] = { + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22 + }; + output_info.nmode = arraysize(output_modes); + output_info.modes = output_modes; + + std::vector resolutions = + GetResolutionList(&resources, &output_info); + EXPECT_EQ(6u, resolutions.size()); + EXPECT_EQ("1920x1200", resolutions[0].size.ToString()); + EXPECT_FALSE(resolutions[0].interlaced); + + EXPECT_EQ("1920x1080", resolutions[1].size.ToString()); + EXPECT_FALSE(resolutions[1].interlaced); + + EXPECT_EQ("1280x720", resolutions[2].size.ToString()); + EXPECT_FALSE(resolutions[2].interlaced); + + EXPECT_EQ("1024x768", resolutions[3].size.ToString()); + EXPECT_TRUE(resolutions[3].interlaced); + + EXPECT_EQ("1024x600", resolutions[4].size.ToString()); + EXPECT_FALSE(resolutions[4].interlaced); + + EXPECT_EQ("640x480", resolutions[5].size.ToString()); + EXPECT_TRUE(resolutions[5].interlaced); + + // Empty output shouldn't crash. + RRMode empty_output_modes[] = {}; + output_info.nmode = 0; + output_info.modes = empty_output_modes; + + resolutions = GetResolutionList(&resources, &output_info); + EXPECT_EQ(0u, resolutions.size()); +} + +} // namespace internal +} // namespace ash -- cgit v1.1