Chromium Code Reviews| Index: chromeos/display/output_configurator_unittest.cc |
| diff --git a/chromeos/display/output_configurator_unittest.cc b/chromeos/display/output_configurator_unittest.cc |
| index 571df38f6cd4b3906e95f62bcbc506ea001d615b..8f4feda9f4f7bb2eff595b261650eedc129b919d 100644 |
| --- a/chromeos/display/output_configurator_unittest.cc |
| +++ b/chromeos/display/output_configurator_unittest.cc |
| @@ -102,7 +102,7 @@ class TestDelegate : public OutputConfigurator::Delegate { |
| static const int kXRandREventBase = 10; |
| TestDelegate() |
| - : configure_crtc_result_(true), |
| + : max_configurable_pixels_(0), |
| hdcp_state_(HDCP_STATE_UNDESIRED) {} |
| virtual ~TestDelegate() {} |
| @@ -114,8 +114,8 @@ class TestDelegate : public OutputConfigurator::Delegate { |
| outputs_ = outputs; |
| } |
| - void set_configure_crtc_result(bool result) { |
| - configure_crtc_result_ = result; |
| + void set_max_configurable_pixels(int pixels) { |
| + max_configurable_pixels_ = pixels; |
| } |
| void set_hdcp_state(HDCPState state) { hdcp_state_ = state; } |
| @@ -161,7 +161,23 @@ class TestDelegate : public OutputConfigurator::Delegate { |
| int x, |
| int y) OVERRIDE { |
| AppendAction(GetCrtcAction(crtc, x, y, mode, output)); |
| - return configure_crtc_result_; |
| + |
| + if (max_configurable_pixels_ == 0) |
| + return true; |
| + |
| + OutputConfigurator::OutputSnapshot* snapshot = GetOutputFromId(output); |
| + |
|
Daniel Erat
2014/01/09 00:40:34
nit: remove this blank line
|
| + if (!snapshot) |
| + return false; |
| + |
| + const OutputConfigurator::ModeInfo* mode_info = |
| + OutputConfigurator::GetModeInfo(*snapshot, mode); |
| + |
|
Daniel Erat
2014/01/09 00:40:34
nit: remove this blank line
|
| + if (!mode_info) |
| + return false; |
| + |
| + return mode_info->width * mode_info->height <= max_configurable_pixels_; |
| + |
| } |
| virtual void CreateFrameBuffer( |
| int width, |
| @@ -212,6 +228,14 @@ class TestDelegate : public OutputConfigurator::Delegate { |
| actions_ += action; |
| } |
| + OutputConfigurator::OutputSnapshot* GetOutputFromId(RROutput output_id) { |
| + for (unsigned int i = 0; i < outputs_.size(); i++) { |
| + if (outputs_[i].output == output_id) |
| + return &outputs_[i]; |
| + } |
| + return NULL; |
| + } |
| + |
| std::map<RRMode, ModeDetails> modes_; |
| // Most-recently-configured transformation matrices, keyed by touch device ID. |
| @@ -222,8 +246,13 @@ class TestDelegate : public OutputConfigurator::Delegate { |
| std::string actions_; |
| - // Return value returned by ConfigureCrtc(). |
| - bool configure_crtc_result_; |
| + // |max_configurable_pixels_| represents the maximum number of pixels that |
| + // ConfigureCrtc will support. Tests can use this to force ConfigureCrtc |
| + // to fail if attempting to set a resolution that is higher than what |
| + // a device might support under a given circumstance. |
| + // A value of 0 means that no limit is enforced and ConfigureCrtc will |
| + // return success regardless of the resolution. |
| + int max_configurable_pixels_; |
| // Result value of GetHDCPState(). |
| HDCPState hdcp_state_; |
| @@ -1019,9 +1048,9 @@ TEST_F(OutputConfiguratorTest, AvoidUnnecessaryProbes) { |
| EXPECT_FALSE(test_api_.TriggerConfigureTimeout()); |
| EXPECT_EQ(kNoActions, delegate_->GetActionsAndClear()); |
| - // Tell the delegate to report failure, which should result in the |
| - // second output sticking with its native mode. |
| - delegate_->set_configure_crtc_result(false); |
| + // Lower the limit for which the delegate will succeed, which should result |
| + // in the second output sticking with its native mode. |
| + delegate_->set_max_configurable_pixels(1); |
| UpdateOutputs(2, true); |
| EXPECT_EQ(JoinActions(kUpdateXRandR, kGrab, |
| GetFramebufferAction(kSmallModeWidth, kSmallModeHeight, |
| @@ -1030,12 +1059,24 @@ TEST_F(OutputConfiguratorTest, AvoidUnnecessaryProbes) { |
| outputs_[0].output).c_str(), |
| GetCrtcAction(outputs_[1].crtc, 0, 0, kSmallModeId, |
| outputs_[1].output).c_str(), |
| + GetFramebufferAction(kBigModeWidth, |
| + kSmallModeHeight + kBigModeHeight + |
| + OutputConfigurator::kVerticalGap, |
| + 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, kSmallModeHeight + |
| + OutputConfigurator::kVerticalGap, kBigModeId, |
| + outputs_[1].output).c_str(), |
| + GetCrtcAction(outputs_[1].crtc, 0, kSmallModeHeight + |
| + OutputConfigurator::kVerticalGap, kSmallModeId, |
| + outputs_[1].output).c_str(), |
| kUngrab, kProjectingOn, NULL), |
| delegate_->GetActionsAndClear()); |
| - // An change event reporting a mode change on the second output should |
| + // A change event reporting a mode change on the second output should |
| // trigger another reconfigure. |
| - delegate_->set_configure_crtc_result(true); |
| + delegate_->set_max_configurable_pixels(0); |
| test_api_.SendOutputChangeEvent( |
| outputs_[1].output, outputs_[1].crtc, outputs_[1].mirror_mode, true); |
| EXPECT_TRUE(test_api_.TriggerConfigureTimeout()); |
| @@ -1263,4 +1304,109 @@ TEST_F(OutputConfiguratorTest, CTMForMultiScreens) { |
| EXPECT_EQ(0, round((kDualWidth - 1) * ctm2.x_offset)); |
| } |
| +TEST_F(OutputConfiguratorTest, HandleConfigureCrtcFailure) { |
| + InitWithSingleOutput(); |
| + |
| + // kFirstMode represents the first mode in the list and |
| + // also the mode that we are requesting the output_configurator |
| + // to choose. The test will be setup so that this mode will fail |
| + // and it will have to choose the next best option. |
| + const int kFirstMode = 11; |
| + int current_mode = kFirstMode; |
|
Daniel Erat
2014/01/09 00:40:34
nit: move this definition down to the place where
|
| + |
| + // Give the mode_info lists a few reasonable modes. |
| + for (int i = 0; i < 2; i++) { |
| + outputs_[i].mode_infos.clear(); |
| + |
| + current_mode = kFirstMode; |
| + outputs_[i].mode_infos[current_mode++] = OutputConfigurator::ModeInfo( |
| + 2560, 1600, false, 60.0); |
| + outputs_[i].mode_infos[current_mode++] = OutputConfigurator::ModeInfo( |
| + 1024, 768, false, 60.0); |
| + outputs_[i].mode_infos[current_mode++] = OutputConfigurator::ModeInfo( |
| + 1280, 720, false, 60.0); |
| + outputs_[i].mode_infos[current_mode++] = OutputConfigurator::ModeInfo( |
| + 1920, 1080, false, 60.0); |
| + outputs_[i].mode_infos[current_mode++] = OutputConfigurator::ModeInfo( |
| + 1920, 1080, false, 40.0); |
| + |
| + outputs_[i].current_mode = kFirstMode; |
| + outputs_[i].native_mode = kFirstMode; |
| + } |
| + |
| + configurator_.Init(false); |
| + |
| + // First test simply fails in STATE_SINGLE mode. This is probably |
| + // unrealistic but the want to make sure any assumptions don't |
| + // creep in. |
| + delegate_->set_max_configurable_pixels( |
| + outputs_[0].mode_infos[kFirstMode + 2].width * |
| + outputs_[0].mode_infos[kFirstMode + 2].height); |
| + state_controller_.set_state(STATE_SINGLE); |
| + UpdateOutputs(1, true); |
| + |
| + EXPECT_EQ(JoinActions(kUpdateXRandR, kGrab, |
| + GetFramebufferAction(2560, 1600, |
| + outputs_[0].crtc, 0).c_str(), |
| + GetCrtcAction(outputs_[0].crtc, 0, 0, kFirstMode, |
| + outputs_[0].output).c_str(), |
| + GetCrtcAction(outputs_[0].crtc, 0, 0, kFirstMode + 3, |
| + outputs_[0].output).c_str(), |
| + GetCrtcAction(outputs_[0].crtc, 0, 0, kFirstMode + 2, |
| + outputs_[0].output).c_str(), |
| + kUngrab, kProjectingOff, NULL), |
| + delegate_->GetActionsAndClear()); |
| + |
| + // This test should attempt to configure a mirror mode that will not succeed |
| + // and should end up in extended mode. |
| + delegate_->set_max_configurable_pixels( |
| + outputs_[0].mode_infos[kFirstMode + 3].width * |
| + outputs_[0].mode_infos[kFirstMode + 3].height); |
| + state_controller_.set_state(STATE_DUAL_MIRROR); |
| + UpdateOutputs(2, true); |
| + |
| + EXPECT_EQ(JoinActions(kUpdateXRandR, kGrab, |
| + GetFramebufferAction( |
| + outputs_[0].mode_infos[kFirstMode].width, |
| + outputs_[0].mode_infos[kFirstMode].height, |
| + outputs_[0].crtc, |
| + outputs_[1].crtc).c_str(), |
| + GetCrtcAction(outputs_[0].crtc, |
| + 0, 0, kFirstMode, outputs_[0].output).c_str(), |
| + // First mode tried is expected to fail and it will |
| + // retry wil the 4th mode in the list. |
| + GetCrtcAction(outputs_[0].crtc, 0, 0, kFirstMode + 3, |
| + outputs_[0].output).c_str(), |
| + // Then attempt to configure crtc1 with the first mode. |
| + GetCrtcAction(outputs_[1].crtc, 0, 0, kFirstMode, |
| + outputs_[1].output).c_str(), |
| + GetCrtcAction(outputs_[1].crtc, 0, 0, kFirstMode + 3, |
| + outputs_[1].output).c_str(), |
| + // Since it was requested to go into mirror mode |
| + // and the configured modes were different, it |
| + // should now try and setup a valid configurable |
| + // extended mode. |
| + GetFramebufferAction( |
| + outputs_[0].mode_infos[kFirstMode].width, |
| + outputs_[0].mode_infos[kFirstMode].height + |
| + outputs_[1].mode_infos[kFirstMode].height + |
| + OutputConfigurator::kVerticalGap, |
| + outputs_[0].crtc, outputs_[1].crtc).c_str(), |
| + GetCrtcAction(outputs_[0].crtc, 0, 0, kFirstMode, |
| + outputs_[0].output).c_str(), |
| + GetCrtcAction(outputs_[0].crtc, 0, 0, kFirstMode + 3, |
| + outputs_[0].output).c_str(), |
| + GetCrtcAction(outputs_[1].crtc, 0, |
| + outputs_[1].mode_infos[kFirstMode].height + |
| + OutputConfigurator::kVerticalGap, kFirstMode, |
| + outputs_[1].output).c_str(), |
| + GetCrtcAction(outputs_[1].crtc, 0, |
| + outputs_[1].mode_infos[kFirstMode].height + |
| + OutputConfigurator::kVerticalGap, kFirstMode + 3, |
| + outputs_[1].output).c_str(), |
| + kUngrab, kProjectingOn, NULL), |
| + delegate_->GetActionsAndClear()); |
| + |
| +} |
| + |
| } // namespace chromeos |