1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ui/display/chromeos/display_configurator.h"
15 #include "base/compiler_specific.h"
16 #include "base/format_macros.h"
17 #include "base/memory/scoped_vector.h"
18 #include "base/message_loop/message_loop.h"
19 #include "base/strings/stringprintf.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 #include "ui/display/chromeos/test/test_display_snapshot.h"
22 #include "ui/display/types/chromeos/display_mode.h"
23 #include "ui/display/types/chromeos/native_display_delegate.h"
29 // Strings returned by TestNativeDisplayDelegate::GetActionsAndClear() to
30 // describe various actions that were performed.
31 const char kInitXRandR[] = "init";
32 const char kGrab[] = "grab";
33 const char kUngrab[] = "ungrab";
34 const char kSync[] = "sync";
35 const char kForceDPMS[] = "dpms";
37 // String returned by TestNativeDisplayDelegate::GetActionsAndClear() if no
38 // actions were requested.
39 const char kNoActions[] = "";
41 std::string DisplaySnapshotToString(const DisplaySnapshot& output) {
42 return base::StringPrintf("id=%" PRId64, output.display_id());
45 // Returns a string describing a TestNativeDisplayDelegate::SetBackgroundColor()
47 std::string GetBackgroundAction(uint32_t color_argb) {
48 return base::StringPrintf("background(0x%x)", color_argb);
51 // Returns a string describing a TestNativeDisplayDelegate::AddOutputMode()
53 std::string GetAddOutputModeAction(const DisplaySnapshot& output,
54 const DisplayMode* mode) {
55 return base::StringPrintf("add_mode(output=%" PRId64 ",mode=%s)",
57 mode->ToString().c_str());
60 // Returns a string describing a TestNativeDisplayDelegate::Configure()
62 std::string GetCrtcAction(const DisplaySnapshot& output,
63 const DisplayMode* mode,
64 const gfx::Point& origin) {
65 return base::StringPrintf("crtc(display=[%s],x=%d,y=%d,mode=[%s])",
66 DisplaySnapshotToString(output).c_str(),
69 mode ? mode->ToString().c_str() : "NULL");
72 // Returns a string describing a TestNativeDisplayDelegate::CreateFramebuffer()
74 std::string GetFramebufferAction(const gfx::Size& size,
75 const DisplaySnapshot* out1,
76 const DisplaySnapshot* out2) {
77 return base::StringPrintf(
78 "framebuffer(width=%d,height=%d,display1=%s,display2=%s)",
81 out1 ? DisplaySnapshotToString(*out1).c_str() : "NULL",
82 out2 ? DisplaySnapshotToString(*out2).c_str() : "NULL");
85 // Returns a string describing a TestNativeDisplayDelegate::ConfigureCTM() call.
86 std::string GetCTMAction(
88 const DisplayConfigurator::CoordinateTransformation& ctm) {
89 return base::StringPrintf("ctm(id=%d,transform=(%f,%f,%f,%f))",
97 // Returns a string describing a TestNativeDisplayDelegate::SetHDCPState() call.
98 std::string GetSetHDCPStateAction(const DisplaySnapshot& output,
100 return base::StringPrintf(
101 "set_hdcp(id=%" PRId64 ",state=%d)", output.display_id(), state);
104 // Joins a sequence of strings describing actions (e.g. kScreenDim) such
105 // that they can be compared against a string returned by
106 // ActionLogger::GetActionsAndClear(). The list of actions must be
107 // terminated by a NULL pointer.
108 std::string JoinActions(const char* action, ...) {
112 va_start(arg_list, action);
114 if (!actions.empty())
117 action = va_arg(arg_list, const char*);
127 void AppendAction(const std::string& action) {
128 if (!actions_.empty())
133 // Returns a comma-separated string describing the actions that were
134 // requested since the previous call to GetActionsAndClear() (i.e.
135 // results are non-repeatable).
136 std::string GetActionsAndClear() {
137 std::string actions = actions_;
143 std::string actions_;
145 DISALLOW_COPY_AND_ASSIGN(ActionLogger);
148 class TestTouchscreenDelegate
149 : public DisplayConfigurator::TouchscreenDelegate {
151 // Ownership of |log| remains with the caller.
152 explicit TestTouchscreenDelegate(ActionLogger* log)
154 configure_touchscreens_(false) {}
155 virtual ~TestTouchscreenDelegate() {}
157 const DisplayConfigurator::CoordinateTransformation& GetCTM(
158 int touch_device_id) {
159 return ctms_[touch_device_id];
162 void set_configure_touchscreens(bool state) {
163 configure_touchscreens_ = state;
166 // DisplayConfigurator::TouchscreenDelegate implementation:
167 virtual void AssociateTouchscreens(
168 DisplayConfigurator::DisplayStateList* outputs) OVERRIDE {
169 if (configure_touchscreens_) {
170 for (size_t i = 0; i < outputs->size(); ++i)
171 (*outputs)[i].touch_device_id = i + 1;
174 virtual void ConfigureCTM(
176 const DisplayConfigurator::CoordinateTransformation& ctm) OVERRIDE {
177 log_->AppendAction(GetCTMAction(touch_device_id, ctm));
178 ctms_[touch_device_id] = ctm;
182 ActionLogger* log_; // Not owned.
184 bool configure_touchscreens_;
186 // Most-recently-configured transformation matrices, keyed by touch device ID.
187 std::map<int, DisplayConfigurator::CoordinateTransformation> ctms_;
189 DISALLOW_COPY_AND_ASSIGN(TestTouchscreenDelegate);
192 class TestNativeDisplayDelegate : public NativeDisplayDelegate {
194 // Ownership of |log| remains with the caller.
195 explicit TestNativeDisplayDelegate(ActionLogger* log)
196 : max_configurable_pixels_(0),
197 hdcp_state_(HDCP_STATE_UNDESIRED),
199 virtual ~TestNativeDisplayDelegate() {}
201 const std::vector<DisplaySnapshot*>& outputs() const { return outputs_; }
202 void set_outputs(const std::vector<DisplaySnapshot*>& outputs) {
206 void set_max_configurable_pixels(int pixels) {
207 max_configurable_pixels_ = pixels;
210 void set_hdcp_state(HDCPState state) { hdcp_state_ = state; }
212 // DisplayConfigurator::Delegate overrides:
213 virtual void Initialize() OVERRIDE { log_->AppendAction(kInitXRandR); }
214 virtual void GrabServer() OVERRIDE { log_->AppendAction(kGrab); }
215 virtual void UngrabServer() OVERRIDE { log_->AppendAction(kUngrab); }
216 virtual void SyncWithServer() OVERRIDE { log_->AppendAction(kSync); }
217 virtual void SetBackgroundColor(uint32_t color_argb) OVERRIDE {
218 log_->AppendAction(GetBackgroundAction(color_argb));
220 virtual void ForceDPMSOn() OVERRIDE { log_->AppendAction(kForceDPMS); }
221 virtual std::vector<DisplaySnapshot*> GetDisplays() OVERRIDE {
224 virtual void AddMode(const DisplaySnapshot& output,
225 const DisplayMode* mode) OVERRIDE {
226 log_->AppendAction(GetAddOutputModeAction(output, mode));
228 virtual bool Configure(const DisplaySnapshot& output,
229 const DisplayMode* mode,
230 const gfx::Point& origin) OVERRIDE {
231 log_->AppendAction(GetCrtcAction(output, mode, origin));
233 if (max_configurable_pixels_ == 0)
239 return mode->size().GetArea() <= max_configurable_pixels_;
241 virtual void CreateFrameBuffer(const gfx::Size& size) OVERRIDE {
243 GetFramebufferAction(size,
244 outputs_.size() >= 1 ? outputs_[0] : NULL,
245 outputs_.size() >= 2 ? outputs_[1] : NULL));
247 virtual bool GetHDCPState(const DisplaySnapshot& output,
248 HDCPState* state) OVERRIDE {
249 *state = hdcp_state_;
253 virtual bool SetHDCPState(const DisplaySnapshot& output,
254 HDCPState state) OVERRIDE {
255 log_->AppendAction(GetSetHDCPStateAction(output, state));
259 virtual std::vector<ui::ColorCalibrationProfile>
260 GetAvailableColorCalibrationProfiles(const DisplaySnapshot& output) OVERRIDE {
261 return std::vector<ui::ColorCalibrationProfile>();
264 virtual bool SetColorCalibrationProfile(
265 const DisplaySnapshot& output,
266 ui::ColorCalibrationProfile new_profile) OVERRIDE {
270 virtual void AddObserver(NativeDisplayObserver* observer) OVERRIDE {}
272 virtual void RemoveObserver(NativeDisplayObserver* observer) OVERRIDE {}
275 // Outputs to be returned by GetDisplays().
276 std::vector<DisplaySnapshot*> outputs_;
278 // |max_configurable_pixels_| represents the maximum number of pixels that
279 // Configure will support. Tests can use this to force Configure
280 // to fail if attempting to set a resolution that is higher than what
281 // a device might support under a given circumstance.
282 // A value of 0 means that no limit is enforced and Configure will
283 // return success regardless of the resolution.
284 int max_configurable_pixels_;
286 // Result value of GetHDCPState().
287 HDCPState hdcp_state_;
289 ActionLogger* log_; // Not owned.
291 DISALLOW_COPY_AND_ASSIGN(TestNativeDisplayDelegate);
294 class TestObserver : public DisplayConfigurator::Observer {
296 explicit TestObserver(DisplayConfigurator* configurator)
297 : configurator_(configurator) {
299 configurator_->AddObserver(this);
301 virtual ~TestObserver() { configurator_->RemoveObserver(this); }
303 int num_changes() const { return num_changes_; }
304 int num_failures() const { return num_failures_; }
305 const DisplayConfigurator::DisplayStateList& latest_outputs() const {
306 return latest_outputs_;
308 MultipleDisplayState latest_failed_state() const {
309 return latest_failed_state_;
315 latest_outputs_.clear();
316 latest_failed_state_ = MULTIPLE_DISPLAY_STATE_INVALID;
319 // DisplayConfigurator::Observer overrides:
320 virtual void OnDisplayModeChanged(
321 const DisplayConfigurator::DisplayStateList& outputs) OVERRIDE {
323 latest_outputs_ = outputs;
326 virtual void OnDisplayModeChangeFailed(MultipleDisplayState failed_new_state)
329 latest_failed_state_ = failed_new_state;
333 DisplayConfigurator* configurator_; // Not owned.
335 // Number of times that OnDisplayMode*() has been called.
339 // Parameters most recently passed to OnDisplayMode*().
340 DisplayConfigurator::DisplayStateList latest_outputs_;
341 MultipleDisplayState latest_failed_state_;
343 DISALLOW_COPY_AND_ASSIGN(TestObserver);
346 class TestStateController : public DisplayConfigurator::StateController {
348 TestStateController() : state_(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED) {}
349 virtual ~TestStateController() {}
351 void set_state(MultipleDisplayState state) { state_ = state; }
353 // DisplayConfigurator::StateController overrides:
354 virtual MultipleDisplayState GetStateForDisplayIds(
355 const std::vector<int64_t>& outputs) const OVERRIDE {
358 virtual bool GetResolutionForDisplayId(int64_t display_id,
359 gfx::Size* size) const OVERRIDE {
364 MultipleDisplayState state_;
366 DISALLOW_COPY_AND_ASSIGN(TestStateController);
369 class TestMirroringController
370 : public DisplayConfigurator::SoftwareMirroringController {
372 TestMirroringController() : software_mirroring_enabled_(false) {}
373 virtual ~TestMirroringController() {}
375 virtual void SetSoftwareMirroring(bool enabled) OVERRIDE {
376 software_mirroring_enabled_ = enabled;
379 bool software_mirroring_enabled() const {
380 return software_mirroring_enabled_;
384 bool software_mirroring_enabled_;
386 DISALLOW_COPY_AND_ASSIGN(TestMirroringController);
389 class DisplayConfiguratorTest : public testing::Test {
391 DisplayConfiguratorTest()
392 : small_mode_(gfx::Size(1366, 768), false, 60.0f),
393 big_mode_(gfx::Size(2560, 1600), false, 60.0f),
394 observer_(&configurator_),
395 test_api_(&configurator_) {}
396 virtual ~DisplayConfiguratorTest() {}
398 virtual void SetUp() OVERRIDE {
399 log_.reset(new ActionLogger());
401 native_display_delegate_ = new TestNativeDisplayDelegate(log_.get());
402 touchscreen_delegate_ = new TestTouchscreenDelegate(log_.get());
403 configurator_.SetDelegatesForTesting(
404 scoped_ptr<NativeDisplayDelegate>(native_display_delegate_),
405 scoped_ptr<DisplayConfigurator::TouchscreenDelegate>(
406 touchscreen_delegate_));
408 configurator_.set_state_controller(&state_controller_);
409 configurator_.set_mirroring_controller(&mirroring_controller_);
411 std::vector<const DisplayMode*> modes;
412 modes.push_back(&small_mode_);
414 TestDisplaySnapshot* o = &outputs_[0];
415 o->set_current_mode(&small_mode_);
416 o->set_native_mode(&small_mode_);
418 o->set_type(DISPLAY_CONNECTION_TYPE_INTERNAL);
419 o->set_is_aspect_preserving_scaling(true);
420 o->set_display_id(123);
421 o->set_has_proper_display_id(true);
424 o->set_current_mode(&big_mode_);
425 o->set_native_mode(&big_mode_);
426 modes.push_back(&big_mode_);
428 o->set_type(DISPLAY_CONNECTION_TYPE_HDMI);
429 o->set_is_aspect_preserving_scaling(true);
430 o->set_display_id(456);
431 o->set_has_proper_display_id(true);
433 UpdateOutputs(2, false);
436 // Predefined modes that can be used by outputs.
437 const DisplayMode small_mode_;
438 const DisplayMode big_mode_;
441 // Configures |native_display_delegate_| to return the first |num_outputs|
443 // |outputs_|. If |send_events| is true, also sends screen-change and
444 // output-change events to |configurator_| and triggers the configure
445 // timeout if one was scheduled.
446 void UpdateOutputs(size_t num_outputs, bool send_events) {
447 ASSERT_LE(num_outputs, arraysize(outputs_));
448 std::vector<DisplaySnapshot*> outputs;
449 for (size_t i = 0; i < num_outputs; ++i)
450 outputs.push_back(&outputs_[i]);
451 native_display_delegate_->set_outputs(outputs);
454 configurator_.OnConfigurationChanged();
455 test_api_.TriggerConfigureTimeout();
459 // Initializes |configurator_| with a single internal display.
460 void InitWithSingleOutput() {
461 UpdateOutputs(1, false);
462 EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
463 configurator_.Init(false);
464 EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
465 configurator_.ForceInitialConfigure(0);
470 GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL)
472 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
476 log_->GetActionsAndClear());
479 base::MessageLoop message_loop_;
480 TestStateController state_controller_;
481 TestMirroringController mirroring_controller_;
482 DisplayConfigurator configurator_;
483 TestObserver observer_;
484 scoped_ptr<ActionLogger> log_;
485 TestNativeDisplayDelegate* native_display_delegate_; // not owned
486 TestTouchscreenDelegate* touchscreen_delegate_; // not owned
487 DisplayConfigurator::TestApi test_api_;
489 TestDisplaySnapshot outputs_[2];
492 DISALLOW_COPY_AND_ASSIGN(DisplayConfiguratorTest);
497 TEST_F(DisplayConfiguratorTest, FindDisplayModeMatchingSize) {
498 ScopedVector<const DisplayMode> modes;
500 // Fields are width, height, interlaced, refresh rate.
501 modes.push_back(new DisplayMode(gfx::Size(1920, 1200), false, 60.0));
503 modes.push_back(new DisplayMode(gfx::Size(1920, 1080), false, 30.0));
504 modes.push_back(new DisplayMode(gfx::Size(1920, 1080), false, 50.0));
505 modes.push_back(new DisplayMode(gfx::Size(1920, 1080), false, 40.0));
506 modes.push_back(new DisplayMode(gfx::Size(1920, 1080), false, 0.0));
507 // Interlaced vs non-interlaced.
508 modes.push_back(new DisplayMode(gfx::Size(1280, 720), true, 60.0));
509 modes.push_back(new DisplayMode(gfx::Size(1280, 720), false, 40.0));
511 modes.push_back(new DisplayMode(gfx::Size(1024, 768), true, 0.0));
512 modes.push_back(new DisplayMode(gfx::Size(1024, 768), true, 40.0));
513 modes.push_back(new DisplayMode(gfx::Size(1024, 768), true, 60.0));
515 modes.push_back(new DisplayMode(gfx::Size(1024, 600), true, 60.0));
516 modes.push_back(new DisplayMode(gfx::Size(1024, 600), false, 40.0));
517 modes.push_back(new DisplayMode(gfx::Size(1024, 600), false, 50.0));
518 // Just one interlaced mode.
519 modes.push_back(new DisplayMode(gfx::Size(640, 480), true, 60.0));
520 // Refresh rate not available.
521 modes.push_back(new DisplayMode(gfx::Size(320, 200), false, 0.0));
523 TestDisplaySnapshot output;
524 output.set_modes(modes.get());
527 DisplayConfigurator::FindDisplayModeMatchingSize(
528 output, gfx::Size(1920, 1200)));
530 // Should pick highest refresh rate.
532 DisplayConfigurator::FindDisplayModeMatchingSize(
533 output, gfx::Size(1920, 1080)));
535 // Should pick non-interlaced mode.
537 DisplayConfigurator::FindDisplayModeMatchingSize(
538 output, gfx::Size(1280, 720)));
540 // Interlaced only. Should pick one with the highest refresh rate in
543 DisplayConfigurator::FindDisplayModeMatchingSize(
544 output, gfx::Size(1024, 768)));
546 // Mixed: Should pick one with the highest refresh rate in
549 DisplayConfigurator::FindDisplayModeMatchingSize(
550 output, gfx::Size(1024, 600)));
552 // Just one interlaced mode.
554 DisplayConfigurator::FindDisplayModeMatchingSize(
555 output, gfx::Size(640, 480)));
557 // Refresh rate not available.
559 DisplayConfigurator::FindDisplayModeMatchingSize(
560 output, gfx::Size(320, 200)));
564 DisplayConfigurator::FindDisplayModeMatchingSize(
565 output, gfx::Size(1440, 900)));
568 TEST_F(DisplayConfiguratorTest, ConnectSecondOutput) {
569 InitWithSingleOutput();
571 // Connect a second output and check that the configurator enters
574 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED);
575 UpdateOutputs(2, true);
576 const int kDualHeight = small_mode_.size().height() +
577 DisplayConfigurator::kVerticalGap +
578 big_mode_.size().height();
582 GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
584 &outputs_[1]).c_str(),
585 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
586 GetCrtcAction(outputs_[1],
589 small_mode_.size().height() +
590 DisplayConfigurator::kVerticalGap))
594 log_->GetActionsAndClear());
595 EXPECT_FALSE(mirroring_controller_.software_mirroring_enabled());
596 EXPECT_EQ(1, observer_.num_changes());
599 EXPECT_TRUE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR));
603 GetFramebufferAction(small_mode_.size(), &outputs_[0], &outputs_[1])
605 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
606 GetCrtcAction(outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
609 log_->GetActionsAndClear());
610 EXPECT_FALSE(mirroring_controller_.software_mirroring_enabled());
611 EXPECT_EQ(1, observer_.num_changes());
613 // Disconnect the second output.
615 UpdateOutputs(1, true);
619 GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL).c_str(),
620 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
623 log_->GetActionsAndClear());
624 EXPECT_FALSE(mirroring_controller_.software_mirroring_enabled());
625 EXPECT_EQ(1, observer_.num_changes());
627 // Get rid of shared modes to force software mirroring.
628 outputs_[1].set_modes(std::vector<const DisplayMode*>(1, &big_mode_));
629 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED);
630 UpdateOutputs(2, true);
634 GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
636 &outputs_[1]).c_str(),
637 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
638 GetCrtcAction(outputs_[1],
641 small_mode_.size().height() +
642 DisplayConfigurator::kVerticalGap))
646 log_->GetActionsAndClear());
647 EXPECT_FALSE(mirroring_controller_.software_mirroring_enabled());
650 EXPECT_TRUE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR));
651 EXPECT_EQ(JoinActions(kGrab, kUngrab, NULL), log_->GetActionsAndClear());
652 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
653 configurator_.display_state());
654 EXPECT_TRUE(mirroring_controller_.software_mirroring_enabled());
655 EXPECT_EQ(1, observer_.num_changes());
657 // Setting MULTIPLE_DISPLAY_STATE_DUAL_MIRROR should try to reconfigure.
660 configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED));
661 EXPECT_EQ(JoinActions(NULL), log_->GetActionsAndClear());
662 EXPECT_FALSE(mirroring_controller_.software_mirroring_enabled());
663 EXPECT_EQ(1, observer_.num_changes());
665 // Set back to software mirror mode.
667 EXPECT_TRUE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR));
668 EXPECT_EQ(JoinActions(kGrab, kUngrab, NULL), log_->GetActionsAndClear());
669 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
670 configurator_.display_state());
671 EXPECT_TRUE(mirroring_controller_.software_mirroring_enabled());
672 EXPECT_EQ(1, observer_.num_changes());
674 // Disconnect the second output.
676 UpdateOutputs(1, true);
680 GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL).c_str(),
681 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
684 log_->GetActionsAndClear());
685 EXPECT_FALSE(mirroring_controller_.software_mirroring_enabled());
686 EXPECT_EQ(1, observer_.num_changes());
689 TEST_F(DisplayConfiguratorTest, SetDisplayPower) {
690 InitWithSingleOutput();
692 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
694 UpdateOutputs(2, true);
698 GetFramebufferAction(small_mode_.size(), &outputs_[0], &outputs_[1])
700 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
701 GetCrtcAction(outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
704 log_->GetActionsAndClear());
705 EXPECT_FALSE(mirroring_controller_.software_mirroring_enabled());
706 EXPECT_EQ(1, observer_.num_changes());
708 // Turning off the internal display should switch the external display to
711 configurator_.SetDisplayPower(
712 chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON,
713 DisplayConfigurator::kSetDisplayPowerNoFlags);
717 GetFramebufferAction(big_mode_.size(), &outputs_[0], &outputs_[1])
719 GetCrtcAction(outputs_[0], NULL, gfx::Point(0, 0)).c_str(),
720 GetCrtcAction(outputs_[1], &big_mode_, gfx::Point(0, 0)).c_str(),
724 log_->GetActionsAndClear());
725 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_SINGLE, configurator_.display_state());
726 EXPECT_EQ(1, observer_.num_changes());
728 // When all displays are turned off, the framebuffer should switch back
729 // to the mirrored size.
731 configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF,
732 DisplayConfigurator::kSetDisplayPowerNoFlags);
735 GetFramebufferAction(
736 small_mode_.size(), &outputs_[0], &outputs_[1]).c_str(),
737 GetCrtcAction(outputs_[0], NULL, gfx::Point(0, 0)).c_str(),
738 GetCrtcAction(outputs_[1], NULL, gfx::Point(0, 0)).c_str(),
741 log_->GetActionsAndClear());
742 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, configurator_.display_state());
743 EXPECT_FALSE(mirroring_controller_.software_mirroring_enabled());
744 EXPECT_EQ(1, observer_.num_changes());
746 // Turn all displays on and check that mirroring is still used.
748 configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON,
749 DisplayConfigurator::kSetDisplayPowerNoFlags);
753 GetFramebufferAction(small_mode_.size(), &outputs_[0], &outputs_[1])
755 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
756 GetCrtcAction(outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
760 log_->GetActionsAndClear());
761 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, configurator_.display_state());
762 EXPECT_FALSE(mirroring_controller_.software_mirroring_enabled());
763 EXPECT_EQ(1, observer_.num_changes());
765 // Get rid of shared modes to force software mirroring.
766 outputs_[1].set_modes(std::vector<const DisplayMode*>(1, &big_mode_));
767 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
769 UpdateOutputs(2, true);
770 const int kDualHeight = small_mode_.size().height() +
771 DisplayConfigurator::kVerticalGap +
772 big_mode_.size().height();
776 GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
778 &outputs_[1]).c_str(),
779 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
780 GetCrtcAction(outputs_[1],
783 small_mode_.size().height() +
784 DisplayConfigurator::kVerticalGap))
788 log_->GetActionsAndClear());
789 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
790 configurator_.display_state());
791 EXPECT_TRUE(mirroring_controller_.software_mirroring_enabled());
792 EXPECT_EQ(1, observer_.num_changes());
794 // Turning off the internal display should switch the external display to
797 configurator_.SetDisplayPower(
798 chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON,
799 DisplayConfigurator::kSetDisplayPowerNoFlags);
803 GetFramebufferAction(big_mode_.size(), &outputs_[0], &outputs_[1])
805 GetCrtcAction(outputs_[0], NULL, gfx::Point(0, 0)).c_str(),
806 GetCrtcAction(outputs_[1], &big_mode_, gfx::Point(0, 0)).c_str(),
810 log_->GetActionsAndClear());
811 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_SINGLE, configurator_.display_state());
812 EXPECT_FALSE(mirroring_controller_.software_mirroring_enabled());
813 EXPECT_EQ(1, observer_.num_changes());
815 // When all displays are turned off, the framebuffer should switch back
816 // to the extended + software mirroring.
818 configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF,
819 DisplayConfigurator::kSetDisplayPowerNoFlags);
823 GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
825 &outputs_[1]).c_str(),
826 GetCrtcAction(outputs_[0], NULL, gfx::Point(0, 0)).c_str(),
827 GetCrtcAction(outputs_[1],
830 small_mode_.size().height() +
831 DisplayConfigurator::kVerticalGap))
835 log_->GetActionsAndClear());
836 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
837 configurator_.display_state());
838 EXPECT_TRUE(mirroring_controller_.software_mirroring_enabled());
839 EXPECT_EQ(1, observer_.num_changes());
841 // Turn all displays on and check that mirroring is still used.
843 configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON,
844 DisplayConfigurator::kSetDisplayPowerNoFlags);
848 GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
850 &outputs_[1]).c_str(),
851 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
852 GetCrtcAction(outputs_[1],
855 small_mode_.size().height() +
856 DisplayConfigurator::kVerticalGap))
861 log_->GetActionsAndClear());
862 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
863 configurator_.display_state());
864 EXPECT_TRUE(mirroring_controller_.software_mirroring_enabled());
865 EXPECT_EQ(1, observer_.num_changes());
868 TEST_F(DisplayConfiguratorTest, SuspendAndResume) {
869 InitWithSingleOutput();
871 // No preparation is needed before suspending when the display is already
872 // on. The configurator should still reprobe on resume in case a display
873 // was connected while suspended.
874 configurator_.SuspendDisplays();
875 EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
876 configurator_.ResumeDisplays();
880 GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL).c_str(),
881 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
885 log_->GetActionsAndClear());
887 // Now turn the display off before suspending and check that the
888 // configurator turns it back on and syncs with the server.
889 configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF,
890 DisplayConfigurator::kSetDisplayPowerNoFlags);
894 GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL).c_str(),
895 GetCrtcAction(outputs_[0], NULL, gfx::Point(0, 0)).c_str(),
898 log_->GetActionsAndClear());
900 configurator_.SuspendDisplays();
904 GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL).c_str(),
905 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
910 log_->GetActionsAndClear());
912 configurator_.ResumeDisplays();
916 GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL).c_str(),
917 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
921 log_->GetActionsAndClear());
923 // If a second, external display is connected, the displays shouldn't be
924 // powered back on before suspending.
925 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
926 UpdateOutputs(2, true);
930 GetFramebufferAction(small_mode_.size(), &outputs_[0], &outputs_[1])
932 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
933 GetCrtcAction(outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
936 log_->GetActionsAndClear());
938 configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF,
939 DisplayConfigurator::kSetDisplayPowerNoFlags);
942 GetFramebufferAction(
943 small_mode_.size(), &outputs_[0], &outputs_[1]).c_str(),
944 GetCrtcAction(outputs_[0], NULL, gfx::Point(0, 0)).c_str(),
945 GetCrtcAction(outputs_[1], NULL, gfx::Point(0, 0)).c_str(),
948 log_->GetActionsAndClear());
950 configurator_.SuspendDisplays();
951 EXPECT_EQ(JoinActions(kGrab, kUngrab, kSync, NULL),
952 log_->GetActionsAndClear());
954 // If a display is disconnected while suspended, the configurator should
955 // pick up the change.
956 UpdateOutputs(1, false);
957 configurator_.ResumeDisplays();
961 GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL).c_str(),
962 GetCrtcAction(outputs_[0], NULL, gfx::Point(0, 0)).c_str(),
965 log_->GetActionsAndClear());
968 TEST_F(DisplayConfiguratorTest, Headless) {
969 UpdateOutputs(0, false);
970 EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
971 configurator_.Init(false);
972 EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
973 configurator_.ForceInitialConfigure(0);
974 EXPECT_EQ(JoinActions(kGrab, kInitXRandR, kForceDPMS, kUngrab, NULL),
975 log_->GetActionsAndClear());
977 // Not much should happen when the display power state is changed while
978 // no displays are connected.
979 configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF,
980 DisplayConfigurator::kSetDisplayPowerNoFlags);
981 EXPECT_EQ(JoinActions(kGrab, kUngrab, NULL), log_->GetActionsAndClear());
982 configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON,
983 DisplayConfigurator::kSetDisplayPowerNoFlags);
984 EXPECT_EQ(JoinActions(kGrab, kForceDPMS, kUngrab, NULL),
985 log_->GetActionsAndClear());
987 // Connect an external display and check that it's configured correctly.
988 outputs_[0].set_current_mode(outputs_[1].current_mode());
989 outputs_[0].set_native_mode(outputs_[1].native_mode());
990 outputs_[0].set_modes(outputs_[1].modes());
991 outputs_[0].set_type(outputs_[1].type());
993 UpdateOutputs(1, true);
997 GetFramebufferAction(big_mode_.size(), &outputs_[0], NULL).c_str(),
998 GetCrtcAction(outputs_[0], &big_mode_, gfx::Point(0, 0)).c_str(),
1001 log_->GetActionsAndClear());
1004 TEST_F(DisplayConfiguratorTest, StartWithTwoOutputs) {
1005 UpdateOutputs(2, false);
1006 EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
1007 configurator_.Init(false);
1008 EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
1010 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
1011 configurator_.ForceInitialConfigure(0);
1016 GetFramebufferAction(small_mode_.size(), &outputs_[0], &outputs_[1])
1018 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
1019 GetCrtcAction(outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
1023 log_->GetActionsAndClear());
1026 TEST_F(DisplayConfiguratorTest, InvalidMultipleDisplayStates) {
1027 UpdateOutputs(0, false);
1028 EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
1029 configurator_.Init(false);
1030 configurator_.ForceInitialConfigure(0);
1032 EXPECT_TRUE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_HEADLESS));
1033 EXPECT_FALSE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_SINGLE));
1035 configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR));
1037 configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED));
1038 EXPECT_EQ(1, observer_.num_changes());
1039 EXPECT_EQ(3, observer_.num_failures());
1041 UpdateOutputs(1, true);
1043 EXPECT_FALSE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_HEADLESS));
1044 EXPECT_TRUE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_SINGLE));
1046 configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR));
1048 configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED));
1049 EXPECT_EQ(1, observer_.num_changes());
1050 EXPECT_EQ(3, observer_.num_failures());
1052 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED);
1053 UpdateOutputs(2, true);
1055 EXPECT_FALSE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_HEADLESS));
1056 EXPECT_FALSE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_SINGLE));
1057 EXPECT_TRUE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR));
1059 configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED));
1060 EXPECT_EQ(2, observer_.num_changes());
1061 EXPECT_EQ(2, observer_.num_failures());
1064 TEST_F(DisplayConfiguratorTest, GetMultipleDisplayStateForDisplaysWithoutId) {
1065 outputs_[0].set_has_proper_display_id(false);
1066 UpdateOutputs(2, false);
1067 configurator_.Init(false);
1068 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
1069 configurator_.ForceInitialConfigure(0);
1070 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
1071 configurator_.display_state());
1074 TEST_F(DisplayConfiguratorTest, GetMultipleDisplayStateForDisplaysWithId) {
1075 outputs_[0].set_has_proper_display_id(true);
1076 UpdateOutputs(2, false);
1077 configurator_.Init(false);
1078 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
1079 configurator_.ForceInitialConfigure(0);
1080 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, configurator_.display_state());
1083 TEST_F(DisplayConfiguratorTest, UpdateCachedOutputsEvenAfterFailure) {
1084 InitWithSingleOutput();
1085 const DisplayConfigurator::DisplayStateList* cached =
1086 &configurator_.cached_displays();
1087 ASSERT_EQ(static_cast<size_t>(1), cached->size());
1088 EXPECT_EQ(outputs_[0].current_mode(), (*cached)[0].display->current_mode());
1090 // After connecting a second output, check that it shows up in
1091 // |cached_displays_| even if an invalid state is requested.
1092 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_SINGLE);
1093 UpdateOutputs(2, true);
1094 cached = &configurator_.cached_displays();
1095 ASSERT_EQ(static_cast<size_t>(2), cached->size());
1096 EXPECT_EQ(outputs_[0].current_mode(), (*cached)[0].display->current_mode());
1097 EXPECT_EQ(outputs_[1].current_mode(), (*cached)[1].display->current_mode());
1100 TEST_F(DisplayConfiguratorTest, PanelFitting) {
1101 // Configure the internal display to support only the big mode and the
1102 // external display to support only the small mode.
1103 outputs_[0].set_current_mode(&big_mode_);
1104 outputs_[0].set_native_mode(&big_mode_);
1105 outputs_[0].set_modes(std::vector<const DisplayMode*>(1, &big_mode_));
1107 outputs_[1].set_current_mode(&small_mode_);
1108 outputs_[1].set_native_mode(&small_mode_);
1109 outputs_[1].set_modes(std::vector<const DisplayMode*>(1, &small_mode_));
1111 // The small mode should be added to the internal output when requesting
1113 UpdateOutputs(2, false);
1114 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
1115 configurator_.Init(true /* is_panel_fitting_enabled */);
1116 configurator_.ForceInitialConfigure(0);
1117 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, configurator_.display_state());
1122 GetAddOutputModeAction(outputs_[0], &small_mode_).c_str(),
1123 GetFramebufferAction(small_mode_.size(), &outputs_[0], &outputs_[1])
1125 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
1126 GetCrtcAction(outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
1130 log_->GetActionsAndClear());
1132 // Both outputs should be using the small mode.
1133 ASSERT_EQ(1, observer_.num_changes());
1134 ASSERT_EQ(static_cast<size_t>(2), observer_.latest_outputs().size());
1135 EXPECT_EQ(&small_mode_, observer_.latest_outputs()[0].mirror_mode);
1136 EXPECT_EQ(&small_mode_,
1137 observer_.latest_outputs()[0].display->current_mode());
1138 EXPECT_EQ(&small_mode_, observer_.latest_outputs()[1].mirror_mode);
1139 EXPECT_EQ(&small_mode_,
1140 observer_.latest_outputs()[1].display->current_mode());
1142 // Also check that the newly-added small mode is present in the internal
1143 // snapshot that was passed to the observer (http://crbug.com/289159).
1144 const DisplayConfigurator::DisplayState& state =
1145 observer_.latest_outputs()[0];
1146 ASSERT_NE(state.display->modes().end(),
1147 std::find(state.display->modes().begin(),
1148 state.display->modes().end(),
1152 TEST_F(DisplayConfiguratorTest, ContentProtection) {
1153 configurator_.Init(false);
1154 configurator_.ForceInitialConfigure(0);
1155 EXPECT_NE(kNoActions, log_->GetActionsAndClear());
1157 DisplayConfigurator::ContentProtectionClientId id =
1158 configurator_.RegisterContentProtectionClient();
1162 UpdateOutputs(1, true);
1163 EXPECT_NE(kNoActions, log_->GetActionsAndClear());
1164 uint32_t link_mask = 0;
1165 uint32_t protection_mask = 0;
1166 EXPECT_TRUE(configurator_.QueryContentProtectionStatus(
1167 id, outputs_[0].display_id(), &link_mask, &protection_mask));
1168 EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_INTERNAL), link_mask);
1169 EXPECT_EQ(static_cast<uint32_t>(CONTENT_PROTECTION_METHOD_NONE),
1171 EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
1174 UpdateOutputs(2, true);
1175 EXPECT_NE(kNoActions, log_->GetActionsAndClear());
1176 EXPECT_TRUE(configurator_.QueryContentProtectionStatus(
1177 id, outputs_[1].display_id(), &link_mask, &protection_mask));
1178 EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_HDMI), link_mask);
1179 EXPECT_EQ(static_cast<uint32_t>(CONTENT_PROTECTION_METHOD_NONE),
1181 EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
1183 EXPECT_TRUE(configurator_.EnableContentProtection(
1184 id, outputs_[1].display_id(), CONTENT_PROTECTION_METHOD_HDCP));
1185 EXPECT_EQ(GetSetHDCPStateAction(outputs_[1], HDCP_STATE_DESIRED),
1186 log_->GetActionsAndClear());
1188 // Enable protection.
1189 native_display_delegate_->set_hdcp_state(HDCP_STATE_ENABLED);
1190 EXPECT_TRUE(configurator_.QueryContentProtectionStatus(
1191 id, outputs_[1].display_id(), &link_mask, &protection_mask));
1192 EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_HDMI), link_mask);
1193 EXPECT_EQ(static_cast<uint32_t>(CONTENT_PROTECTION_METHOD_HDCP),
1195 EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
1197 // Protections should be disabled after unregister.
1198 configurator_.UnregisterContentProtectionClient(id);
1199 EXPECT_EQ(GetSetHDCPStateAction(outputs_[1], HDCP_STATE_UNDESIRED),
1200 log_->GetActionsAndClear());
1203 TEST_F(DisplayConfiguratorTest, ContentProtectionTwoClients) {
1204 DisplayConfigurator::ContentProtectionClientId client1 =
1205 configurator_.RegisterContentProtectionClient();
1206 DisplayConfigurator::ContentProtectionClientId client2 =
1207 configurator_.RegisterContentProtectionClient();
1208 EXPECT_NE(client1, client2);
1210 configurator_.Init(false);
1211 configurator_.ForceInitialConfigure(0);
1212 UpdateOutputs(2, true);
1213 EXPECT_NE(kNoActions, log_->GetActionsAndClear());
1215 // Clients never know state enableness for methods that they didn't request.
1216 EXPECT_TRUE(configurator_.EnableContentProtection(
1217 client1, outputs_[1].display_id(), CONTENT_PROTECTION_METHOD_HDCP));
1218 EXPECT_EQ(GetSetHDCPStateAction(outputs_[1], HDCP_STATE_DESIRED).c_str(),
1219 log_->GetActionsAndClear());
1220 native_display_delegate_->set_hdcp_state(HDCP_STATE_ENABLED);
1222 uint32_t link_mask = 0;
1223 uint32_t protection_mask = 0;
1224 EXPECT_TRUE(configurator_.QueryContentProtectionStatus(
1225 client1, outputs_[1].display_id(), &link_mask, &protection_mask));
1226 EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_HDMI), link_mask);
1227 EXPECT_EQ(CONTENT_PROTECTION_METHOD_HDCP, protection_mask);
1229 EXPECT_TRUE(configurator_.QueryContentProtectionStatus(
1230 client2, outputs_[1].display_id(), &link_mask, &protection_mask));
1231 EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_HDMI), link_mask);
1232 EXPECT_EQ(CONTENT_PROTECTION_METHOD_NONE, protection_mask);
1234 // Protections will be disabled only if no more clients request them.
1235 EXPECT_TRUE(configurator_.EnableContentProtection(
1236 client2, outputs_[1].display_id(), CONTENT_PROTECTION_METHOD_NONE));
1237 EXPECT_EQ(GetSetHDCPStateAction(outputs_[1], HDCP_STATE_DESIRED).c_str(),
1238 log_->GetActionsAndClear());
1239 EXPECT_TRUE(configurator_.EnableContentProtection(
1240 client1, outputs_[1].display_id(), CONTENT_PROTECTION_METHOD_NONE));
1241 EXPECT_EQ(GetSetHDCPStateAction(outputs_[1], HDCP_STATE_UNDESIRED).c_str(),
1242 log_->GetActionsAndClear());
1245 TEST_F(DisplayConfiguratorTest, CTMForMultiScreens) {
1246 touchscreen_delegate_->set_configure_touchscreens(true);
1247 UpdateOutputs(2, false);
1248 configurator_.Init(false);
1249 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED);
1250 configurator_.ForceInitialConfigure(0);
1252 const int kDualHeight = small_mode_.size().height() +
1253 DisplayConfigurator::kVerticalGap +
1254 big_mode_.size().height();
1255 const int kDualWidth = big_mode_.size().width();
1257 DisplayConfigurator::CoordinateTransformation ctm1 =
1258 touchscreen_delegate_->GetCTM(1);
1259 DisplayConfigurator::CoordinateTransformation ctm2 =
1260 touchscreen_delegate_->GetCTM(2);
1262 EXPECT_EQ(small_mode_.size().height() - 1,
1263 round((kDualHeight - 1) * ctm1.y_scale));
1264 EXPECT_EQ(0, round((kDualHeight - 1) * ctm1.y_offset));
1266 EXPECT_EQ(big_mode_.size().height() - 1,
1267 round((kDualHeight - 1) * ctm2.y_scale));
1268 EXPECT_EQ(small_mode_.size().height() + DisplayConfigurator::kVerticalGap,
1269 round((kDualHeight - 1) * ctm2.y_offset));
1271 EXPECT_EQ(small_mode_.size().width() - 1,
1272 round((kDualWidth - 1) * ctm1.x_scale));
1273 EXPECT_EQ(0, round((kDualWidth - 1) * ctm1.x_offset));
1275 EXPECT_EQ(big_mode_.size().width() - 1,
1276 round((kDualWidth - 1) * ctm2.x_scale));
1277 EXPECT_EQ(0, round((kDualWidth - 1) * ctm2.x_offset));
1280 TEST_F(DisplayConfiguratorTest, HandleConfigureCrtcFailure) {
1281 InitWithSingleOutput();
1283 ScopedVector<const DisplayMode> modes;
1284 // The first mode is the mode we are requesting DisplayConfigurator to choose.
1285 // The test will be setup so that this mode will fail and it will have to
1286 // choose the next best option.
1287 modes.push_back(new DisplayMode(gfx::Size(2560, 1600), false, 60.0));
1288 modes.push_back(new DisplayMode(gfx::Size(1024, 768), false, 60.0));
1289 modes.push_back(new DisplayMode(gfx::Size(1280, 720), false, 60.0));
1290 modes.push_back(new DisplayMode(gfx::Size(1920, 1080), false, 60.0));
1291 modes.push_back(new DisplayMode(gfx::Size(1920, 1080), false, 40.0));
1293 for (unsigned int i = 0; i < arraysize(outputs_); i++) {
1294 outputs_[i].set_modes(modes.get());
1295 outputs_[i].set_current_mode(modes[0]);
1296 outputs_[i].set_native_mode(modes[0]);
1299 configurator_.Init(false);
1301 // First test simply fails in MULTIPLE_DISPLAY_STATE_SINGLE mode. This is
1302 // probably unrealistic but we want to make sure any assumptions don't creep
1304 native_display_delegate_->set_max_configurable_pixels(
1305 modes[2]->size().GetArea());
1306 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_SINGLE);
1307 UpdateOutputs(1, true);
1312 GetFramebufferAction(big_mode_.size(), &outputs_[0], NULL).c_str(),
1313 GetCrtcAction(outputs_[0], modes[0], gfx::Point(0, 0)).c_str(),
1314 GetCrtcAction(outputs_[0], modes[3], gfx::Point(0, 0)).c_str(),
1315 GetCrtcAction(outputs_[0], modes[2], gfx::Point(0, 0)).c_str(),
1318 log_->GetActionsAndClear());
1320 // This test should attempt to configure a mirror mode that will not succeed
1321 // and should end up in extended mode.
1322 native_display_delegate_->set_max_configurable_pixels(
1323 modes[3]->size().GetArea());
1324 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
1325 UpdateOutputs(2, true);
1330 GetFramebufferAction(modes[0]->size(), &outputs_[0], &outputs_[1])
1332 GetCrtcAction(outputs_[0], modes[0], gfx::Point(0, 0)).c_str(),
1333 // First mode tried is expected to fail and it will
1334 // retry wil the 4th mode in the list.
1335 GetCrtcAction(outputs_[0], modes[3], gfx::Point(0, 0)).c_str(),
1336 // Then attempt to configure crtc1 with the first mode.
1337 GetCrtcAction(outputs_[1], modes[0], gfx::Point(0, 0)).c_str(),
1338 GetCrtcAction(outputs_[1], modes[3], gfx::Point(0, 0)).c_str(),
1339 // Since it was requested to go into mirror mode
1340 // and the configured modes were different, it
1341 // should now try and setup a valid configurable
1343 GetFramebufferAction(
1344 gfx::Size(modes[0]->size().width(),
1345 modes[0]->size().height() + modes[0]->size().height() +
1346 DisplayConfigurator::kVerticalGap),
1348 &outputs_[1]).c_str(),
1349 GetCrtcAction(outputs_[0], modes[0], gfx::Point(0, 0)).c_str(),
1350 GetCrtcAction(outputs_[0], modes[3], gfx::Point(0, 0)).c_str(),
1351 GetCrtcAction(outputs_[1],
1354 modes[0]->size().height() +
1355 DisplayConfigurator::kVerticalGap))
1357 GetCrtcAction(outputs_[1],
1360 modes[0]->size().height() +
1361 DisplayConfigurator::kVerticalGap))
1365 log_->GetActionsAndClear());