Index: chromeos/display/output_configurator_unittest.cc |
diff --git a/chromeos/display/output_configurator_unittest.cc b/chromeos/display/output_configurator_unittest.cc |
index 658e1baa7c92b5c43be5bb78ecfa9c2f3eb6b82e..ad3211ee5a7cde7ad434b0725061cf442c6d7c12 100644 |
--- a/chromeos/display/output_configurator_unittest.cc |
+++ b/chromeos/display/output_configurator_unittest.cc |
@@ -39,6 +39,11 @@ std::string GetBackgroundAction(uint32 color_argb) { |
return base::StringPrintf("background(0x%x)", color_argb); |
} |
+// Returns a string describing a TestDelegate::AddOutputMode() call. |
+std::string GetAddOutputModeAction(RROutput output, RRMode mode) { |
+ return base::StringPrintf("add_mode(output=%lu,mode=%lu)", output, mode); |
+} |
+ |
// Returns a string describing a TestDelegate::ConfigureCrtc() call. |
std::string GetCrtcAction(RRCrtc crtc, |
int x, |
@@ -115,7 +120,6 @@ class TestDelegate : public OutputConfigurator::Delegate { |
} |
// OutputConfigurator::Delegate overrides: |
- virtual void SetPanelFittingEnabled(bool enabled) OVERRIDE {} |
virtual void InitXRandRExtension(int* event_base) OVERRIDE { |
AppendAction(kInitXRandR); |
*event_base = kXRandREventBase; |
@@ -129,10 +133,13 @@ class TestDelegate : public OutputConfigurator::Delegate { |
AppendAction(GetBackgroundAction(color_argb)); |
} |
virtual void ForceDPMSOn() OVERRIDE { AppendAction(kForceDPMS); } |
- virtual std::vector<OutputConfigurator::OutputSnapshot> GetOutputs( |
- const OutputConfigurator::StateController* controller) OVERRIDE { |
+ virtual std::vector<OutputConfigurator::OutputSnapshot> GetOutputs() |
+ OVERRIDE { |
return outputs_; |
} |
+ virtual void AddOutputMode(RROutput output, RRMode mode) OVERRIDE { |
+ AppendAction(GetAddOutputModeAction(output, mode)); |
+ } |
virtual bool ConfigureCrtc(RRCrtc crtc, |
RRMode mode, |
RROutput output, |
@@ -205,7 +212,8 @@ class TestObserver : public OutputConfigurator::Observer { |
int num_changes() const { return num_changes_; } |
int num_failures() const { return num_failures_; } |
- std::vector<OutputConfigurator::OutputSnapshot> latest_outputs() const { |
+ const std::vector<OutputConfigurator::OutputSnapshot>& latest_outputs() |
+ const { |
return latest_outputs_; |
} |
OutputState latest_failed_state() const { return latest_failed_state_; } |
@@ -289,6 +297,15 @@ class TestMirroringController |
class OutputConfiguratorTest : public testing::Test { |
public: |
+ // Predefined modes that can be used by outputs. |
+ static const RRMode kSmallModeId; |
+ static const int kSmallModeWidth; |
+ static const int kSmallModeHeight; |
+ |
+ static const RRMode kBigModeId; |
+ static const int kBigModeWidth; |
+ static const int kBigModeHeight; |
+ |
OutputConfiguratorTest() |
: observer_(&configurator_), |
test_api_(&configurator_, TestDelegate::kXRandREventBase) {} |
@@ -314,49 +331,28 @@ class OutputConfiguratorTest : public testing::Test { |
o->crtc = 10; |
o->current_mode = kSmallModeId; |
o->native_mode = kSmallModeId; |
- o->selected_mode = kSmallModeId; |
- o->mirror_mode = kSmallModeId; |
- o->x = 0; |
- o->y = 0; |
o->is_internal = true; |
o->is_aspect_preserving_scaling = true; |
o->mode_infos[kSmallModeId] = small_mode_info; |
- o->touch_device_id = 0; |
o->has_display_id = true; |
+ o->index = 0; |
o = &outputs_[1]; |
o->output = 2; |
o->crtc = 11; |
o->current_mode = kBigModeId; |
o->native_mode = kBigModeId; |
- o->selected_mode = kBigModeId; |
- o->mirror_mode = kSmallModeId; |
- o->x = 0; |
- o->y = 0; |
o->is_internal = false; |
o->is_aspect_preserving_scaling = true; |
o->mode_infos[kSmallModeId] = small_mode_info; |
o->mode_infos[kBigModeId] = big_mode_info; |
- o->touch_device_id = 0; |
o->has_display_id = true; |
+ o->index = 1; |
UpdateOutputs(2, false); |
} |
- void DisableNativeMirroring() { |
- outputs_[0].mirror_mode = outputs_[1].mirror_mode = 0L; |
- } |
- |
protected: |
- // Predefined modes that can be used by outputs. |
- static const int kSmallModeId = 20; |
- static const int kSmallModeWidth = 1366; |
- static const int kSmallModeHeight = 768; |
- |
- static const int kBigModeId = 21; |
- static const int kBigModeWidth = 2560; |
- static const int kBigModeHeight = 1600; |
- |
// Configures |delegate_| to return the first |num_outputs| entries from |
// |outputs_|. If |send_events| is true, also sends screen-change and |
// output-change events to |configurator_| and triggers the configure |
@@ -410,8 +406,76 @@ class OutputConfiguratorTest : public testing::Test { |
DISALLOW_COPY_AND_ASSIGN(OutputConfiguratorTest); |
}; |
+const RRMode OutputConfiguratorTest::kSmallModeId = 20; |
+const int OutputConfiguratorTest::kSmallModeWidth = 1366; |
+const int OutputConfiguratorTest::kSmallModeHeight = 768; |
+ |
+const RRMode OutputConfiguratorTest::kBigModeId = 21; |
+const int OutputConfiguratorTest::kBigModeWidth = 2560; |
+const int OutputConfiguratorTest::kBigModeHeight = 1600; |
+ |
} // namespace |
+TEST_F(OutputConfiguratorTest, FindOutputModeMatchingSize) { |
+ OutputConfigurator::OutputSnapshot output; |
+ |
+ // Fields are width, height, interlaced, refresh rate. |
+ output.mode_infos[11] = OutputConfigurator::ModeInfo(1920, 1200, false, 60.0); |
+ // Different rates. |
+ output.mode_infos[12] = OutputConfigurator::ModeInfo(1920, 1080, false, 30.0); |
+ output.mode_infos[13] = OutputConfigurator::ModeInfo(1920, 1080, false, 50.0); |
+ output.mode_infos[14] = OutputConfigurator::ModeInfo(1920, 1080, false, 40.0); |
+ output.mode_infos[15] = OutputConfigurator::ModeInfo(1920, 1080, false, 0.0); |
+ // Interlaced vs non-interlaced. |
+ output.mode_infos[16] = OutputConfigurator::ModeInfo(1280, 720, true, 60.0); |
+ output.mode_infos[17] = OutputConfigurator::ModeInfo(1280, 720, false, 40.0); |
+ // Interlaced only. |
+ output.mode_infos[18] = OutputConfigurator::ModeInfo(1024, 768, true, 0.0); |
+ output.mode_infos[19] = OutputConfigurator::ModeInfo(1024, 768, true, 40.0); |
+ output.mode_infos[20] = OutputConfigurator::ModeInfo(1024, 768, true, 60.0); |
+ // Mixed. |
+ output.mode_infos[21] = OutputConfigurator::ModeInfo(1024, 600, true, 60.0); |
+ output.mode_infos[22] = OutputConfigurator::ModeInfo(1024, 600, false, 40.0); |
+ output.mode_infos[23] = OutputConfigurator::ModeInfo(1024, 600, false, 50.0); |
+ // Just one interlaced mode. |
+ output.mode_infos[24] = OutputConfigurator::ModeInfo(640, 480, true, 60.0); |
+ // Refresh rate not available. |
+ output.mode_infos[25] = OutputConfigurator::ModeInfo(320, 200, false, 0.0); |
+ |
+ EXPECT_EQ(11u, OutputConfigurator::FindOutputModeMatchingSize(output, |
+ 1920, 1200)); |
+ |
+ // Should pick highest refresh rate. |
+ EXPECT_EQ(13u, OutputConfigurator::FindOutputModeMatchingSize(output, |
+ 1920, 1080)); |
+ |
+ // Should pick non-interlaced mode. |
+ EXPECT_EQ(17u, OutputConfigurator::FindOutputModeMatchingSize(output, |
+ 1280, 720)); |
+ |
+ // Interlaced only. Should pick one with the highest refresh rate in |
+ // interlaced mode. |
+ EXPECT_EQ(20u, OutputConfigurator::FindOutputModeMatchingSize(output, |
+ 1024, 768)); |
+ |
+ // Mixed: Should pick one with the highest refresh rate in |
+ // interlaced mode. |
+ EXPECT_EQ(23u, OutputConfigurator::FindOutputModeMatchingSize(output, |
+ 1024, 600)); |
+ |
+ // Just one interlaced mode. |
+ EXPECT_EQ(24u, OutputConfigurator::FindOutputModeMatchingSize(output, |
+ 640, 480)); |
+ |
+ // Refresh rate not available. |
+ EXPECT_EQ(25u, OutputConfigurator::FindOutputModeMatchingSize(output, |
+ 320, 200)); |
+ |
+ // No mode found. |
+ EXPECT_EQ(0u, OutputConfigurator::FindOutputModeMatchingSize(output, |
+ 1440, 900)); |
+} |
+ |
TEST_F(OutputConfiguratorTest, ConnectSecondOutput) { |
InitWithSingleOutput(); |
@@ -462,8 +526,8 @@ TEST_F(OutputConfiguratorTest, ConnectSecondOutput) { |
EXPECT_FALSE(mirroring_controller_.software_mirroring_enabled()); |
EXPECT_EQ(1, observer_.num_changes()); |
- // Software Mirroring |
- DisableNativeMirroring(); |
+ // Get rid of shared modes to force software mirroring. |
+ outputs_[1].mode_infos.erase(kSmallModeId); |
state_controller_.set_state(STATE_DUAL_EXTENDED); |
UpdateOutputs(2, true); |
EXPECT_EQ(JoinActions(kUpdateXRandR, kGrab, |
@@ -585,8 +649,8 @@ TEST_F(OutputConfiguratorTest, SetDisplayPower) { |
EXPECT_FALSE(mirroring_controller_.software_mirroring_enabled()); |
EXPECT_EQ(1, observer_.num_changes()); |
- // Software Mirroring |
- DisableNativeMirroring(); |
+ // Get rid of shared modes to force software mirroring. |
+ outputs_[1].mode_infos.erase(kSmallModeId); |
state_controller_.set_state(STATE_DUAL_MIRROR); |
observer_.Reset(); |
UpdateOutputs(2, true); |
@@ -950,4 +1014,55 @@ TEST_F(OutputConfiguratorTest, AvoidUnnecessaryProbes) { |
delegate_->GetActionsAndClear()); |
} |
+TEST_F(OutputConfiguratorTest, PanelFitting) { |
+ // Configure the internal display to support only the big mode and the |
+ // external display to support only the small mode. |
+ outputs_[0].current_mode = kBigModeId; |
+ outputs_[0].native_mode = kBigModeId; |
+ outputs_[0].mode_infos.clear(); |
+ outputs_[0].mode_infos[kBigModeId] = OutputConfigurator::ModeInfo( |
+ kBigModeWidth, kBigModeHeight, false, 60.0); |
+ |
+ outputs_[1].current_mode = kSmallModeId; |
+ outputs_[1].native_mode = kSmallModeId; |
+ outputs_[1].mode_infos.clear(); |
+ outputs_[1].mode_infos[kSmallModeId] = OutputConfigurator::ModeInfo( |
+ kSmallModeWidth, kSmallModeHeight, false, 60.0); |
+ |
+ // The small mode should be added to the internal output when requesting |
+ // mirrored mode. |
+ UpdateOutputs(2, false); |
+ state_controller_.set_state(STATE_DUAL_MIRROR); |
+ configurator_.Init(true /* is_panel_fitting_enabled */); |
+ configurator_.Start(0); |
+ EXPECT_EQ(STATE_DUAL_MIRROR, configurator_.output_state()); |
+ EXPECT_EQ(JoinActions(kGrab, kInitXRandR, |
+ GetAddOutputModeAction( |
+ outputs_[0].output, kSmallModeId).c_str(), |
+ GetFramebufferAction(kSmallModeWidth, kSmallModeHeight, |
+ outputs_[0].crtc, outputs_[1].crtc).c_str(), |
+ GetCrtcAction(outputs_[0].crtc, 0, 0, kSmallModeId, |
+ outputs_[0].output).c_str(), |
+ GetCrtcAction(outputs_[1].crtc, 0, 0, kSmallModeId, |
+ outputs_[1].output).c_str(), |
+ kForceDPMS, kUngrab, kProjectingOn, NULL), |
+ delegate_->GetActionsAndClear()); |
+ |
+ // Both outputs should be using the small mode. |
+ ASSERT_EQ(1, observer_.num_changes()); |
+ ASSERT_EQ(static_cast<size_t>(2), observer_.latest_outputs().size()); |
+ EXPECT_EQ(kSmallModeId, observer_.latest_outputs()[0].mirror_mode); |
+ EXPECT_EQ(kSmallModeId, observer_.latest_outputs()[0].current_mode); |
+ EXPECT_EQ(kSmallModeId, observer_.latest_outputs()[1].mirror_mode); |
+ EXPECT_EQ(kSmallModeId, observer_.latest_outputs()[1].current_mode); |
+ |
+ // Also check that the newly-added small mode is present in the internal |
+ // snapshot that was passed to the observer (http://crbug.com/289159). |
+ const OutputConfigurator::ModeInfo* info = OutputConfigurator::GetModeInfo( |
+ observer_.latest_outputs()[0], kSmallModeId); |
+ ASSERT_TRUE(info); |
+ EXPECT_EQ(kSmallModeWidth, info->width); |
+ EXPECT_EQ(kSmallModeHeight, info->height); |
+} |
+ |
} // namespace chromeos |