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. 4 5 #include "ui/display/chromeos/display_configurator.h" 6 7 #include <stdint.h> 8 9 #include <cmath> 10 #include <cstdarg> 11 #include <map> 12 #include <string> 13 #include <vector> 14 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" 24 25 namespace ui { 26 27 namespace { 28 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"; 36 37 // String returned by TestNativeDisplayDelegate::GetActionsAndClear() if no 38 // actions were requested. 39 const char kNoActions[] = ""; 40 41 std::string DisplaySnapshotToString(const DisplaySnapshot& output) { 42 return base::StringPrintf("id=%" PRId64, output.display_id()); 43 } 44 45 // Returns a string describing a TestNativeDisplayDelegate::SetBackgroundColor() 46 // call. 47 std::string GetBackgroundAction(uint32_t color_argb) { 48 return base::StringPrintf("background(0x%x)", color_argb); 49 } 50 51 // Returns a string describing a TestNativeDisplayDelegate::AddOutputMode() 52 // call. 53 std::string GetAddOutputModeAction(const DisplaySnapshot& output, 54 const DisplayMode* mode) { 55 return base::StringPrintf("add_mode(output=%" PRId64 ",mode=%s)", 56 output.display_id(), 57 mode->ToString().c_str()); 58 } 59 60 // Returns a string describing a TestNativeDisplayDelegate::Configure() 61 // call. 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(), 67 origin.x(), 68 origin.y(), 69 mode ? mode->ToString().c_str() : "NULL"); 70 } 71 72 // Returns a string describing a TestNativeDisplayDelegate::CreateFramebuffer() 73 // call. 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)", 79 size.width(), 80 size.height(), 81 out1 ? DisplaySnapshotToString(*out1).c_str() : "NULL", 82 out2 ? DisplaySnapshotToString(*out2).c_str() : "NULL"); 83 } 84 85 // Returns a string describing a TestNativeDisplayDelegate::SetHDCPState() call. 86 std::string GetSetHDCPStateAction(const DisplaySnapshot& output, 87 HDCPState state) { 88 return base::StringPrintf( 89 "set_hdcp(id=%" PRId64 ",state=%d)", output.display_id(), state); 90 } 91 92 // Joins a sequence of strings describing actions (e.g. kScreenDim) such 93 // that they can be compared against a string returned by 94 // ActionLogger::GetActionsAndClear(). The list of actions must be 95 // terminated by a NULL pointer. 96 std::string JoinActions(const char* action, ...) { 97 std::string actions; 98 99 va_list arg_list; 100 va_start(arg_list, action); 101 while (action) { 102 if (!actions.empty()) 103 actions += ","; 104 actions += action; 105 action = va_arg(arg_list, const char*); 106 } 107 va_end(arg_list); 108 return actions; 109 } 110 111 class ActionLogger { 112 public: 113 ActionLogger() {} 114 115 void AppendAction(const std::string& action) { 116 if (!actions_.empty()) 117 actions_ += ","; 118 actions_ += action; 119 } 120 121 // Returns a comma-separated string describing the actions that were 122 // requested since the previous call to GetActionsAndClear() (i.e. 123 // results are non-repeatable). 124 std::string GetActionsAndClear() { 125 std::string actions = actions_; 126 actions_.clear(); 127 return actions; 128 } 129 130 private: 131 std::string actions_; 132 133 DISALLOW_COPY_AND_ASSIGN(ActionLogger); 134 }; 135 136 class TestTouchscreenDelegate 137 : public DisplayConfigurator::TouchscreenDelegate { 138 public: 139 // Ownership of |log| remains with the caller. 140 explicit TestTouchscreenDelegate(ActionLogger* log) 141 : log_(log), 142 configure_touchscreens_(false) {} 143 virtual ~TestTouchscreenDelegate() {} 144 145 void set_configure_touchscreens(bool state) { 146 configure_touchscreens_ = state; 147 } 148 149 // DisplayConfigurator::TouchscreenDelegate implementation: 150 virtual void AssociateTouchscreens( 151 DisplayConfigurator::DisplayStateList* outputs) OVERRIDE { 152 if (configure_touchscreens_) { 153 for (size_t i = 0; i < outputs->size(); ++i) 154 (*outputs)[i].touch_device_id = i + 1; 155 } 156 } 157 158 private: 159 ActionLogger* log_; // Not owned. 160 161 bool configure_touchscreens_; 162 163 DISALLOW_COPY_AND_ASSIGN(TestTouchscreenDelegate); 164 }; 165 166 class TestNativeDisplayDelegate : public NativeDisplayDelegate { 167 public: 168 // Ownership of |log| remains with the caller. 169 explicit TestNativeDisplayDelegate(ActionLogger* log) 170 : max_configurable_pixels_(0), 171 hdcp_state_(HDCP_STATE_UNDESIRED), 172 log_(log) {} 173 virtual ~TestNativeDisplayDelegate() {} 174 175 const std::vector<DisplaySnapshot*>& outputs() const { return outputs_; } 176 void set_outputs(const std::vector<DisplaySnapshot*>& outputs) { 177 outputs_ = outputs; 178 } 179 180 void set_max_configurable_pixels(int pixels) { 181 max_configurable_pixels_ = pixels; 182 } 183 184 void set_hdcp_state(HDCPState state) { hdcp_state_ = state; } 185 186 // DisplayConfigurator::Delegate overrides: 187 virtual void Initialize() OVERRIDE { log_->AppendAction(kInitXRandR); } 188 virtual void GrabServer() OVERRIDE { log_->AppendAction(kGrab); } 189 virtual void UngrabServer() OVERRIDE { log_->AppendAction(kUngrab); } 190 virtual void SyncWithServer() OVERRIDE { log_->AppendAction(kSync); } 191 virtual void SetBackgroundColor(uint32_t color_argb) OVERRIDE { 192 log_->AppendAction(GetBackgroundAction(color_argb)); 193 } 194 virtual void ForceDPMSOn() OVERRIDE { log_->AppendAction(kForceDPMS); } 195 virtual std::vector<DisplaySnapshot*> GetDisplays() OVERRIDE { 196 return outputs_; 197 } 198 virtual void AddMode(const DisplaySnapshot& output, 199 const DisplayMode* mode) OVERRIDE { 200 log_->AppendAction(GetAddOutputModeAction(output, mode)); 201 } 202 virtual bool Configure(const DisplaySnapshot& output, 203 const DisplayMode* mode, 204 const gfx::Point& origin) OVERRIDE { 205 log_->AppendAction(GetCrtcAction(output, mode, origin)); 206 207 if (max_configurable_pixels_ == 0) 208 return true; 209 210 if (!mode) 211 return false; 212 213 return mode->size().GetArea() <= max_configurable_pixels_; 214 } 215 virtual void CreateFrameBuffer(const gfx::Size& size) OVERRIDE { 216 log_->AppendAction( 217 GetFramebufferAction(size, 218 outputs_.size() >= 1 ? outputs_[0] : NULL, 219 outputs_.size() >= 2 ? outputs_[1] : NULL)); 220 } 221 virtual bool GetHDCPState(const DisplaySnapshot& output, 222 HDCPState* state) OVERRIDE { 223 *state = hdcp_state_; 224 return true; 225 } 226 227 virtual bool SetHDCPState(const DisplaySnapshot& output, 228 HDCPState state) OVERRIDE { 229 log_->AppendAction(GetSetHDCPStateAction(output, state)); 230 return true; 231 } 232 233 virtual std::vector<ui::ColorCalibrationProfile> 234 GetAvailableColorCalibrationProfiles(const DisplaySnapshot& output) OVERRIDE { 235 return std::vector<ui::ColorCalibrationProfile>(); 236 } 237 238 virtual bool SetColorCalibrationProfile( 239 const DisplaySnapshot& output, 240 ui::ColorCalibrationProfile new_profile) OVERRIDE { 241 return false; 242 } 243 244 virtual void AddObserver(NativeDisplayObserver* observer) OVERRIDE {} 245 246 virtual void RemoveObserver(NativeDisplayObserver* observer) OVERRIDE {} 247 248 private: 249 // Outputs to be returned by GetDisplays(). 250 std::vector<DisplaySnapshot*> outputs_; 251 252 // |max_configurable_pixels_| represents the maximum number of pixels that 253 // Configure will support. Tests can use this to force Configure 254 // to fail if attempting to set a resolution that is higher than what 255 // a device might support under a given circumstance. 256 // A value of 0 means that no limit is enforced and Configure will 257 // return success regardless of the resolution. 258 int max_configurable_pixels_; 259 260 // Result value of GetHDCPState(). 261 HDCPState hdcp_state_; 262 263 ActionLogger* log_; // Not owned. 264 265 DISALLOW_COPY_AND_ASSIGN(TestNativeDisplayDelegate); 266 }; 267 268 class TestObserver : public DisplayConfigurator::Observer { 269 public: 270 explicit TestObserver(DisplayConfigurator* configurator) 271 : configurator_(configurator) { 272 Reset(); 273 configurator_->AddObserver(this); 274 } 275 virtual ~TestObserver() { configurator_->RemoveObserver(this); } 276 277 int num_changes() const { return num_changes_; } 278 int num_failures() const { return num_failures_; } 279 const DisplayConfigurator::DisplayStateList& latest_outputs() const { 280 return latest_outputs_; 281 } 282 MultipleDisplayState latest_failed_state() const { 283 return latest_failed_state_; 284 } 285 286 void Reset() { 287 num_changes_ = 0; 288 num_failures_ = 0; 289 latest_outputs_.clear(); 290 latest_failed_state_ = MULTIPLE_DISPLAY_STATE_INVALID; 291 } 292 293 // DisplayConfigurator::Observer overrides: 294 virtual void OnDisplayModeChanged( 295 const DisplayConfigurator::DisplayStateList& outputs) OVERRIDE { 296 num_changes_++; 297 latest_outputs_ = outputs; 298 } 299 300 virtual void OnDisplayModeChangeFailed(MultipleDisplayState failed_new_state) 301 OVERRIDE { 302 num_failures_++; 303 latest_failed_state_ = failed_new_state; 304 } 305 306 private: 307 DisplayConfigurator* configurator_; // Not owned. 308 309 // Number of times that OnDisplayMode*() has been called. 310 int num_changes_; 311 int num_failures_; 312 313 // Parameters most recently passed to OnDisplayMode*(). 314 DisplayConfigurator::DisplayStateList latest_outputs_; 315 MultipleDisplayState latest_failed_state_; 316 317 DISALLOW_COPY_AND_ASSIGN(TestObserver); 318 }; 319 320 class TestStateController : public DisplayConfigurator::StateController { 321 public: 322 TestStateController() : state_(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED) {} 323 virtual ~TestStateController() {} 324 325 void set_state(MultipleDisplayState state) { state_ = state; } 326 327 // DisplayConfigurator::StateController overrides: 328 virtual MultipleDisplayState GetStateForDisplayIds( 329 const std::vector<int64_t>& outputs) const OVERRIDE { 330 return state_; 331 } 332 virtual bool GetResolutionForDisplayId(int64_t display_id, 333 gfx::Size* size) const OVERRIDE { 334 return false; 335 } 336 337 private: 338 MultipleDisplayState state_; 339 340 DISALLOW_COPY_AND_ASSIGN(TestStateController); 341 }; 342 343 class TestMirroringController 344 : public DisplayConfigurator::SoftwareMirroringController { 345 public: 346 TestMirroringController() : software_mirroring_enabled_(false) {} 347 virtual ~TestMirroringController() {} 348 349 virtual void SetSoftwareMirroring(bool enabled) OVERRIDE { 350 software_mirroring_enabled_ = enabled; 351 } 352 353 virtual bool SoftwareMirroringEnabled() const OVERRIDE { 354 return software_mirroring_enabled_; 355 } 356 357 private: 358 bool software_mirroring_enabled_; 359 360 DISALLOW_COPY_AND_ASSIGN(TestMirroringController); 361 }; 362 363 class DisplayConfiguratorTest : public testing::Test { 364 public: 365 DisplayConfiguratorTest() 366 : small_mode_(gfx::Size(1366, 768), false, 60.0f), 367 big_mode_(gfx::Size(2560, 1600), false, 60.0f), 368 observer_(&configurator_), 369 test_api_(&configurator_) {} 370 virtual ~DisplayConfiguratorTest() {} 371 372 virtual void SetUp() OVERRIDE { 373 log_.reset(new ActionLogger()); 374 375 native_display_delegate_ = new TestNativeDisplayDelegate(log_.get()); 376 touchscreen_delegate_ = new TestTouchscreenDelegate(log_.get()); 377 configurator_.SetDelegatesForTesting( 378 scoped_ptr<NativeDisplayDelegate>(native_display_delegate_), 379 scoped_ptr<DisplayConfigurator::TouchscreenDelegate>( 380 touchscreen_delegate_)); 381 382 configurator_.set_state_controller(&state_controller_); 383 configurator_.set_mirroring_controller(&mirroring_controller_); 384 385 std::vector<const DisplayMode*> modes; 386 modes.push_back(&small_mode_); 387 388 TestDisplaySnapshot* o = &outputs_[0]; 389 o->set_current_mode(&small_mode_); 390 o->set_native_mode(&small_mode_); 391 o->set_modes(modes); 392 o->set_type(DISPLAY_CONNECTION_TYPE_INTERNAL); 393 o->set_is_aspect_preserving_scaling(true); 394 o->set_display_id(123); 395 o->set_has_proper_display_id(true); 396 397 o = &outputs_[1]; 398 o->set_current_mode(&big_mode_); 399 o->set_native_mode(&big_mode_); 400 modes.push_back(&big_mode_); 401 o->set_modes(modes); 402 o->set_type(DISPLAY_CONNECTION_TYPE_HDMI); 403 o->set_is_aspect_preserving_scaling(true); 404 o->set_display_id(456); 405 o->set_has_proper_display_id(true); 406 407 UpdateOutputs(2, false); 408 } 409 410 // Predefined modes that can be used by outputs. 411 const DisplayMode small_mode_; 412 const DisplayMode big_mode_; 413 414 protected: 415 // Configures |native_display_delegate_| to return the first |num_outputs| 416 // entries from 417 // |outputs_|. If |send_events| is true, also sends screen-change and 418 // output-change events to |configurator_| and triggers the configure 419 // timeout if one was scheduled. 420 void UpdateOutputs(size_t num_outputs, bool send_events) { 421 ASSERT_LE(num_outputs, arraysize(outputs_)); 422 std::vector<DisplaySnapshot*> outputs; 423 for (size_t i = 0; i < num_outputs; ++i) 424 outputs.push_back(&outputs_[i]); 425 native_display_delegate_->set_outputs(outputs); 426 427 if (send_events) { 428 configurator_.OnConfigurationChanged(); 429 test_api_.TriggerConfigureTimeout(); 430 } 431 } 432 433 // Initializes |configurator_| with a single internal display. 434 void InitWithSingleOutput() { 435 UpdateOutputs(1, false); 436 EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); 437 configurator_.Init(false); 438 EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); 439 configurator_.ForceInitialConfigure(0); 440 EXPECT_EQ( 441 JoinActions( 442 kGrab, 443 kInitXRandR, 444 GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL) 445 .c_str(), 446 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), 447 kForceDPMS, 448 kUngrab, 449 NULL), 450 log_->GetActionsAndClear()); 451 } 452 453 base::MessageLoop message_loop_; 454 TestStateController state_controller_; 455 TestMirroringController mirroring_controller_; 456 DisplayConfigurator configurator_; 457 TestObserver observer_; 458 scoped_ptr<ActionLogger> log_; 459 TestNativeDisplayDelegate* native_display_delegate_; // not owned 460 TestTouchscreenDelegate* touchscreen_delegate_; // not owned 461 DisplayConfigurator::TestApi test_api_; 462 463 TestDisplaySnapshot outputs_[2]; 464 465 private: 466 DISALLOW_COPY_AND_ASSIGN(DisplayConfiguratorTest); 467 }; 468 469 } // namespace 470 471 TEST_F(DisplayConfiguratorTest, FindDisplayModeMatchingSize) { 472 ScopedVector<const DisplayMode> modes; 473 474 // Fields are width, height, interlaced, refresh rate. 475 modes.push_back(new DisplayMode(gfx::Size(1920, 1200), false, 60.0)); 476 // Different rates. 477 modes.push_back(new DisplayMode(gfx::Size(1920, 1080), false, 30.0)); 478 modes.push_back(new DisplayMode(gfx::Size(1920, 1080), false, 50.0)); 479 modes.push_back(new DisplayMode(gfx::Size(1920, 1080), false, 40.0)); 480 modes.push_back(new DisplayMode(gfx::Size(1920, 1080), false, 0.0)); 481 // Interlaced vs non-interlaced. 482 modes.push_back(new DisplayMode(gfx::Size(1280, 720), true, 60.0)); 483 modes.push_back(new DisplayMode(gfx::Size(1280, 720), false, 40.0)); 484 // Interlaced only. 485 modes.push_back(new DisplayMode(gfx::Size(1024, 768), true, 0.0)); 486 modes.push_back(new DisplayMode(gfx::Size(1024, 768), true, 40.0)); 487 modes.push_back(new DisplayMode(gfx::Size(1024, 768), true, 60.0)); 488 // Mixed. 489 modes.push_back(new DisplayMode(gfx::Size(1024, 600), true, 60.0)); 490 modes.push_back(new DisplayMode(gfx::Size(1024, 600), false, 40.0)); 491 modes.push_back(new DisplayMode(gfx::Size(1024, 600), false, 50.0)); 492 // Just one interlaced mode. 493 modes.push_back(new DisplayMode(gfx::Size(640, 480), true, 60.0)); 494 // Refresh rate not available. 495 modes.push_back(new DisplayMode(gfx::Size(320, 200), false, 0.0)); 496 497 TestDisplaySnapshot output; 498 output.set_modes(modes.get()); 499 500 EXPECT_EQ(modes[0], 501 DisplayConfigurator::FindDisplayModeMatchingSize( 502 output, gfx::Size(1920, 1200))); 503 504 // Should pick highest refresh rate. 505 EXPECT_EQ(modes[2], 506 DisplayConfigurator::FindDisplayModeMatchingSize( 507 output, gfx::Size(1920, 1080))); 508 509 // Should pick non-interlaced mode. 510 EXPECT_EQ(modes[6], 511 DisplayConfigurator::FindDisplayModeMatchingSize( 512 output, gfx::Size(1280, 720))); 513 514 // Interlaced only. Should pick one with the highest refresh rate in 515 // interlaced mode. 516 EXPECT_EQ(modes[9], 517 DisplayConfigurator::FindDisplayModeMatchingSize( 518 output, gfx::Size(1024, 768))); 519 520 // Mixed: Should pick one with the highest refresh rate in 521 // interlaced mode. 522 EXPECT_EQ(modes[12], 523 DisplayConfigurator::FindDisplayModeMatchingSize( 524 output, gfx::Size(1024, 600))); 525 526 // Just one interlaced mode. 527 EXPECT_EQ(modes[13], 528 DisplayConfigurator::FindDisplayModeMatchingSize( 529 output, gfx::Size(640, 480))); 530 531 // Refresh rate not available. 532 EXPECT_EQ(modes[14], 533 DisplayConfigurator::FindDisplayModeMatchingSize( 534 output, gfx::Size(320, 200))); 535 536 // No mode found. 537 EXPECT_EQ(NULL, 538 DisplayConfigurator::FindDisplayModeMatchingSize( 539 output, gfx::Size(1440, 900))); 540 } 541 542 TEST_F(DisplayConfiguratorTest, ConnectSecondOutput) { 543 InitWithSingleOutput(); 544 545 // Connect a second output and check that the configurator enters 546 // extended mode. 547 observer_.Reset(); 548 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED); 549 UpdateOutputs(2, true); 550 const int kDualHeight = small_mode_.size().height() + 551 DisplayConfigurator::kVerticalGap + 552 big_mode_.size().height(); 553 EXPECT_EQ( 554 JoinActions( 555 kGrab, 556 GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight), 557 &outputs_[0], 558 &outputs_[1]).c_str(), 559 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), 560 GetCrtcAction(outputs_[1], 561 &big_mode_, 562 gfx::Point(0, 563 small_mode_.size().height() + 564 DisplayConfigurator::kVerticalGap)) 565 .c_str(), 566 kUngrab, 567 NULL), 568 log_->GetActionsAndClear()); 569 EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled()); 570 EXPECT_EQ(1, observer_.num_changes()); 571 572 observer_.Reset(); 573 EXPECT_TRUE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR)); 574 EXPECT_EQ( 575 JoinActions( 576 kGrab, 577 GetFramebufferAction(small_mode_.size(), &outputs_[0], &outputs_[1]) 578 .c_str(), 579 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), 580 GetCrtcAction(outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(), 581 kUngrab, 582 NULL), 583 log_->GetActionsAndClear()); 584 EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled()); 585 EXPECT_EQ(1, observer_.num_changes()); 586 587 // Disconnect the second output. 588 observer_.Reset(); 589 UpdateOutputs(1, true); 590 EXPECT_EQ( 591 JoinActions( 592 kGrab, 593 GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL).c_str(), 594 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), 595 kUngrab, 596 NULL), 597 log_->GetActionsAndClear()); 598 EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled()); 599 EXPECT_EQ(1, observer_.num_changes()); 600 601 // Get rid of shared modes to force software mirroring. 602 outputs_[1].set_modes(std::vector<const DisplayMode*>(1, &big_mode_)); 603 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED); 604 UpdateOutputs(2, true); 605 EXPECT_EQ( 606 JoinActions( 607 kGrab, 608 GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight), 609 &outputs_[0], 610 &outputs_[1]).c_str(), 611 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), 612 GetCrtcAction(outputs_[1], 613 &big_mode_, 614 gfx::Point(0, 615 small_mode_.size().height() + 616 DisplayConfigurator::kVerticalGap)) 617 .c_str(), 618 kUngrab, 619 NULL), 620 log_->GetActionsAndClear()); 621 EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled()); 622 623 observer_.Reset(); 624 EXPECT_TRUE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR)); 625 EXPECT_EQ(JoinActions(kGrab, kUngrab, NULL), log_->GetActionsAndClear()); 626 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED, 627 configurator_.display_state()); 628 EXPECT_TRUE(mirroring_controller_.SoftwareMirroringEnabled()); 629 EXPECT_EQ(1, observer_.num_changes()); 630 631 // Setting MULTIPLE_DISPLAY_STATE_DUAL_MIRROR should try to reconfigure. 632 observer_.Reset(); 633 EXPECT_TRUE( 634 configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED)); 635 EXPECT_EQ(JoinActions(NULL), log_->GetActionsAndClear()); 636 EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled()); 637 EXPECT_EQ(1, observer_.num_changes()); 638 639 // Set back to software mirror mode. 640 observer_.Reset(); 641 EXPECT_TRUE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR)); 642 EXPECT_EQ(JoinActions(kGrab, kUngrab, NULL), log_->GetActionsAndClear()); 643 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED, 644 configurator_.display_state()); 645 EXPECT_TRUE(mirroring_controller_.SoftwareMirroringEnabled()); 646 EXPECT_EQ(1, observer_.num_changes()); 647 648 // Disconnect the second output. 649 observer_.Reset(); 650 UpdateOutputs(1, true); 651 EXPECT_EQ( 652 JoinActions( 653 kGrab, 654 GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL).c_str(), 655 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), 656 kUngrab, 657 NULL), 658 log_->GetActionsAndClear()); 659 EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled()); 660 EXPECT_EQ(1, observer_.num_changes()); 661 } 662 663 TEST_F(DisplayConfiguratorTest, SetDisplayPower) { 664 InitWithSingleOutput(); 665 666 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR); 667 observer_.Reset(); 668 UpdateOutputs(2, true); 669 EXPECT_EQ( 670 JoinActions( 671 kGrab, 672 GetFramebufferAction(small_mode_.size(), &outputs_[0], &outputs_[1]) 673 .c_str(), 674 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), 675 GetCrtcAction(outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(), 676 kUngrab, 677 NULL), 678 log_->GetActionsAndClear()); 679 EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled()); 680 EXPECT_EQ(1, observer_.num_changes()); 681 682 // Turning off the internal display should switch the external display to 683 // its native mode. 684 observer_.Reset(); 685 configurator_.SetDisplayPower( 686 chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON, 687 DisplayConfigurator::kSetDisplayPowerNoFlags); 688 EXPECT_EQ( 689 JoinActions( 690 kGrab, 691 GetFramebufferAction(big_mode_.size(), &outputs_[0], &outputs_[1]) 692 .c_str(), 693 GetCrtcAction(outputs_[0], NULL, gfx::Point(0, 0)).c_str(), 694 GetCrtcAction(outputs_[1], &big_mode_, gfx::Point(0, 0)).c_str(), 695 kForceDPMS, 696 kUngrab, 697 NULL), 698 log_->GetActionsAndClear()); 699 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_SINGLE, configurator_.display_state()); 700 EXPECT_EQ(1, observer_.num_changes()); 701 702 // When all displays are turned off, the framebuffer should switch back 703 // to the mirrored size. 704 observer_.Reset(); 705 configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF, 706 DisplayConfigurator::kSetDisplayPowerNoFlags); 707 EXPECT_EQ( 708 JoinActions(kGrab, 709 GetFramebufferAction( 710 small_mode_.size(), &outputs_[0], &outputs_[1]).c_str(), 711 GetCrtcAction(outputs_[0], NULL, gfx::Point(0, 0)).c_str(), 712 GetCrtcAction(outputs_[1], NULL, gfx::Point(0, 0)).c_str(), 713 kUngrab, 714 NULL), 715 log_->GetActionsAndClear()); 716 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, configurator_.display_state()); 717 EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled()); 718 EXPECT_EQ(1, observer_.num_changes()); 719 720 // Turn all displays on and check that mirroring is still used. 721 observer_.Reset(); 722 configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON, 723 DisplayConfigurator::kSetDisplayPowerNoFlags); 724 EXPECT_EQ( 725 JoinActions( 726 kGrab, 727 GetFramebufferAction(small_mode_.size(), &outputs_[0], &outputs_[1]) 728 .c_str(), 729 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), 730 GetCrtcAction(outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(), 731 kForceDPMS, 732 kUngrab, 733 NULL), 734 log_->GetActionsAndClear()); 735 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, configurator_.display_state()); 736 EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled()); 737 EXPECT_EQ(1, observer_.num_changes()); 738 739 // Get rid of shared modes to force software mirroring. 740 outputs_[1].set_modes(std::vector<const DisplayMode*>(1, &big_mode_)); 741 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR); 742 observer_.Reset(); 743 UpdateOutputs(2, true); 744 const int kDualHeight = small_mode_.size().height() + 745 DisplayConfigurator::kVerticalGap + 746 big_mode_.size().height(); 747 EXPECT_EQ( 748 JoinActions( 749 kGrab, 750 GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight), 751 &outputs_[0], 752 &outputs_[1]).c_str(), 753 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), 754 GetCrtcAction(outputs_[1], 755 &big_mode_, 756 gfx::Point(0, 757 small_mode_.size().height() + 758 DisplayConfigurator::kVerticalGap)) 759 .c_str(), 760 kUngrab, 761 NULL), 762 log_->GetActionsAndClear()); 763 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED, 764 configurator_.display_state()); 765 EXPECT_TRUE(mirroring_controller_.SoftwareMirroringEnabled()); 766 EXPECT_EQ(1, observer_.num_changes()); 767 768 // Turning off the internal display should switch the external display to 769 // its native mode. 770 observer_.Reset(); 771 configurator_.SetDisplayPower( 772 chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON, 773 DisplayConfigurator::kSetDisplayPowerNoFlags); 774 EXPECT_EQ( 775 JoinActions( 776 kGrab, 777 GetFramebufferAction(big_mode_.size(), &outputs_[0], &outputs_[1]) 778 .c_str(), 779 GetCrtcAction(outputs_[0], NULL, gfx::Point(0, 0)).c_str(), 780 GetCrtcAction(outputs_[1], &big_mode_, gfx::Point(0, 0)).c_str(), 781 kForceDPMS, 782 kUngrab, 783 NULL), 784 log_->GetActionsAndClear()); 785 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_SINGLE, configurator_.display_state()); 786 EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled()); 787 EXPECT_EQ(1, observer_.num_changes()); 788 789 // When all displays are turned off, the framebuffer should switch back 790 // to the extended + software mirroring. 791 observer_.Reset(); 792 configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF, 793 DisplayConfigurator::kSetDisplayPowerNoFlags); 794 EXPECT_EQ( 795 JoinActions( 796 kGrab, 797 GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight), 798 &outputs_[0], 799 &outputs_[1]).c_str(), 800 GetCrtcAction(outputs_[0], NULL, gfx::Point(0, 0)).c_str(), 801 GetCrtcAction(outputs_[1], 802 NULL, 803 gfx::Point(0, 804 small_mode_.size().height() + 805 DisplayConfigurator::kVerticalGap)) 806 .c_str(), 807 kUngrab, 808 NULL), 809 log_->GetActionsAndClear()); 810 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED, 811 configurator_.display_state()); 812 EXPECT_TRUE(mirroring_controller_.SoftwareMirroringEnabled()); 813 EXPECT_EQ(1, observer_.num_changes()); 814 815 // Turn all displays on and check that mirroring is still used. 816 observer_.Reset(); 817 configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON, 818 DisplayConfigurator::kSetDisplayPowerNoFlags); 819 EXPECT_EQ( 820 JoinActions( 821 kGrab, 822 GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight), 823 &outputs_[0], 824 &outputs_[1]).c_str(), 825 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), 826 GetCrtcAction(outputs_[1], 827 &big_mode_, 828 gfx::Point(0, 829 small_mode_.size().height() + 830 DisplayConfigurator::kVerticalGap)) 831 .c_str(), 832 kForceDPMS, 833 kUngrab, 834 NULL), 835 log_->GetActionsAndClear()); 836 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED, 837 configurator_.display_state()); 838 EXPECT_TRUE(mirroring_controller_.SoftwareMirroringEnabled()); 839 EXPECT_EQ(1, observer_.num_changes()); 840 } 841 842 TEST_F(DisplayConfiguratorTest, SuspendAndResume) { 843 InitWithSingleOutput(); 844 845 // No preparation is needed before suspending when the display is already 846 // on. The configurator should still reprobe on resume in case a display 847 // was connected while suspended. 848 configurator_.SuspendDisplays(); 849 EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); 850 configurator_.ResumeDisplays(); 851 EXPECT_EQ( 852 JoinActions( 853 kGrab, 854 GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL).c_str(), 855 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), 856 kForceDPMS, 857 kUngrab, 858 NULL), 859 log_->GetActionsAndClear()); 860 861 // Now turn the display off before suspending and check that the 862 // configurator turns it back on and syncs with the server. 863 configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF, 864 DisplayConfigurator::kSetDisplayPowerNoFlags); 865 EXPECT_EQ( 866 JoinActions( 867 kGrab, 868 GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL).c_str(), 869 GetCrtcAction(outputs_[0], NULL, gfx::Point(0, 0)).c_str(), 870 kUngrab, 871 NULL), 872 log_->GetActionsAndClear()); 873 874 configurator_.SuspendDisplays(); 875 EXPECT_EQ( 876 JoinActions( 877 kGrab, 878 GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL).c_str(), 879 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), 880 kForceDPMS, 881 kUngrab, 882 kSync, 883 NULL), 884 log_->GetActionsAndClear()); 885 886 configurator_.ResumeDisplays(); 887 EXPECT_EQ( 888 JoinActions( 889 kGrab, 890 GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL).c_str(), 891 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), 892 kForceDPMS, 893 kUngrab, 894 NULL), 895 log_->GetActionsAndClear()); 896 897 // If a second, external display is connected, the displays shouldn't be 898 // powered back on before suspending. 899 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR); 900 UpdateOutputs(2, true); 901 EXPECT_EQ( 902 JoinActions( 903 kGrab, 904 GetFramebufferAction(small_mode_.size(), &outputs_[0], &outputs_[1]) 905 .c_str(), 906 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), 907 GetCrtcAction(outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(), 908 kUngrab, 909 NULL), 910 log_->GetActionsAndClear()); 911 912 configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF, 913 DisplayConfigurator::kSetDisplayPowerNoFlags); 914 EXPECT_EQ( 915 JoinActions(kGrab, 916 GetFramebufferAction( 917 small_mode_.size(), &outputs_[0], &outputs_[1]).c_str(), 918 GetCrtcAction(outputs_[0], NULL, gfx::Point(0, 0)).c_str(), 919 GetCrtcAction(outputs_[1], NULL, gfx::Point(0, 0)).c_str(), 920 kUngrab, 921 NULL), 922 log_->GetActionsAndClear()); 923 924 configurator_.SuspendDisplays(); 925 EXPECT_EQ(JoinActions(kGrab, kUngrab, kSync, NULL), 926 log_->GetActionsAndClear()); 927 928 // If a display is disconnected while suspended, the configurator should 929 // pick up the change. 930 UpdateOutputs(1, false); 931 configurator_.ResumeDisplays(); 932 EXPECT_EQ( 933 JoinActions( 934 kGrab, 935 GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL).c_str(), 936 GetCrtcAction(outputs_[0], NULL, gfx::Point(0, 0)).c_str(), 937 kUngrab, 938 NULL), 939 log_->GetActionsAndClear()); 940 } 941 942 TEST_F(DisplayConfiguratorTest, Headless) { 943 UpdateOutputs(0, false); 944 EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); 945 configurator_.Init(false); 946 EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); 947 configurator_.ForceInitialConfigure(0); 948 EXPECT_EQ(JoinActions(kGrab, kInitXRandR, kForceDPMS, kUngrab, NULL), 949 log_->GetActionsAndClear()); 950 951 // Not much should happen when the display power state is changed while 952 // no displays are connected. 953 configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF, 954 DisplayConfigurator::kSetDisplayPowerNoFlags); 955 EXPECT_EQ(JoinActions(kGrab, kUngrab, NULL), log_->GetActionsAndClear()); 956 configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON, 957 DisplayConfigurator::kSetDisplayPowerNoFlags); 958 EXPECT_EQ(JoinActions(kGrab, kForceDPMS, kUngrab, NULL), 959 log_->GetActionsAndClear()); 960 961 // Connect an external display and check that it's configured correctly. 962 outputs_[0].set_current_mode(outputs_[1].current_mode()); 963 outputs_[0].set_native_mode(outputs_[1].native_mode()); 964 outputs_[0].set_modes(outputs_[1].modes()); 965 outputs_[0].set_type(outputs_[1].type()); 966 967 UpdateOutputs(1, true); 968 EXPECT_EQ( 969 JoinActions( 970 kGrab, 971 GetFramebufferAction(big_mode_.size(), &outputs_[0], NULL).c_str(), 972 GetCrtcAction(outputs_[0], &big_mode_, gfx::Point(0, 0)).c_str(), 973 kUngrab, 974 NULL), 975 log_->GetActionsAndClear()); 976 } 977 978 TEST_F(DisplayConfiguratorTest, StartWithTwoOutputs) { 979 UpdateOutputs(2, false); 980 EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); 981 configurator_.Init(false); 982 EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); 983 984 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR); 985 configurator_.ForceInitialConfigure(0); 986 EXPECT_EQ( 987 JoinActions( 988 kGrab, 989 kInitXRandR, 990 GetFramebufferAction(small_mode_.size(), &outputs_[0], &outputs_[1]) 991 .c_str(), 992 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), 993 GetCrtcAction(outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(), 994 kForceDPMS, 995 kUngrab, 996 NULL), 997 log_->GetActionsAndClear()); 998 } 999 1000 TEST_F(DisplayConfiguratorTest, InvalidMultipleDisplayStates) { 1001 UpdateOutputs(0, false); 1002 EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); 1003 configurator_.Init(false); 1004 configurator_.ForceInitialConfigure(0); 1005 observer_.Reset(); 1006 EXPECT_TRUE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_HEADLESS)); 1007 EXPECT_FALSE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_SINGLE)); 1008 EXPECT_FALSE( 1009 configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR)); 1010 EXPECT_FALSE( 1011 configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED)); 1012 EXPECT_EQ(1, observer_.num_changes()); 1013 EXPECT_EQ(3, observer_.num_failures()); 1014 1015 UpdateOutputs(1, true); 1016 observer_.Reset(); 1017 EXPECT_FALSE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_HEADLESS)); 1018 EXPECT_TRUE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_SINGLE)); 1019 EXPECT_FALSE( 1020 configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR)); 1021 EXPECT_FALSE( 1022 configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED)); 1023 EXPECT_EQ(1, observer_.num_changes()); 1024 EXPECT_EQ(3, observer_.num_failures()); 1025 1026 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED); 1027 UpdateOutputs(2, true); 1028 observer_.Reset(); 1029 EXPECT_FALSE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_HEADLESS)); 1030 EXPECT_FALSE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_SINGLE)); 1031 EXPECT_TRUE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR)); 1032 EXPECT_TRUE( 1033 configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED)); 1034 EXPECT_EQ(2, observer_.num_changes()); 1035 EXPECT_EQ(2, observer_.num_failures()); 1036 } 1037 1038 TEST_F(DisplayConfiguratorTest, GetMultipleDisplayStateForDisplaysWithoutId) { 1039 outputs_[0].set_has_proper_display_id(false); 1040 UpdateOutputs(2, false); 1041 configurator_.Init(false); 1042 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR); 1043 configurator_.ForceInitialConfigure(0); 1044 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED, 1045 configurator_.display_state()); 1046 } 1047 1048 TEST_F(DisplayConfiguratorTest, GetMultipleDisplayStateForDisplaysWithId) { 1049 outputs_[0].set_has_proper_display_id(true); 1050 UpdateOutputs(2, false); 1051 configurator_.Init(false); 1052 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR); 1053 configurator_.ForceInitialConfigure(0); 1054 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, configurator_.display_state()); 1055 } 1056 1057 TEST_F(DisplayConfiguratorTest, UpdateCachedOutputsEvenAfterFailure) { 1058 InitWithSingleOutput(); 1059 const DisplayConfigurator::DisplayStateList* cached = 1060 &configurator_.cached_displays(); 1061 ASSERT_EQ(static_cast<size_t>(1), cached->size()); 1062 EXPECT_EQ(outputs_[0].current_mode(), (*cached)[0].display->current_mode()); 1063 1064 // After connecting a second output, check that it shows up in 1065 // |cached_displays_| even if an invalid state is requested. 1066 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_SINGLE); 1067 UpdateOutputs(2, true); 1068 cached = &configurator_.cached_displays(); 1069 ASSERT_EQ(static_cast<size_t>(2), cached->size()); 1070 EXPECT_EQ(outputs_[0].current_mode(), (*cached)[0].display->current_mode()); 1071 EXPECT_EQ(outputs_[1].current_mode(), (*cached)[1].display->current_mode()); 1072 } 1073 1074 TEST_F(DisplayConfiguratorTest, PanelFitting) { 1075 // Configure the internal display to support only the big mode and the 1076 // external display to support only the small mode. 1077 outputs_[0].set_current_mode(&big_mode_); 1078 outputs_[0].set_native_mode(&big_mode_); 1079 outputs_[0].set_modes(std::vector<const DisplayMode*>(1, &big_mode_)); 1080 1081 outputs_[1].set_current_mode(&small_mode_); 1082 outputs_[1].set_native_mode(&small_mode_); 1083 outputs_[1].set_modes(std::vector<const DisplayMode*>(1, &small_mode_)); 1084 1085 // The small mode should be added to the internal output when requesting 1086 // mirrored mode. 1087 UpdateOutputs(2, false); 1088 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR); 1089 configurator_.Init(true /* is_panel_fitting_enabled */); 1090 configurator_.ForceInitialConfigure(0); 1091 EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, configurator_.display_state()); 1092 EXPECT_EQ( 1093 JoinActions( 1094 kGrab, 1095 kInitXRandR, 1096 GetAddOutputModeAction(outputs_[0], &small_mode_).c_str(), 1097 GetFramebufferAction(small_mode_.size(), &outputs_[0], &outputs_[1]) 1098 .c_str(), 1099 GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(), 1100 GetCrtcAction(outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(), 1101 kForceDPMS, 1102 kUngrab, 1103 NULL), 1104 log_->GetActionsAndClear()); 1105 1106 // Both outputs should be using the small mode. 1107 ASSERT_EQ(1, observer_.num_changes()); 1108 ASSERT_EQ(static_cast<size_t>(2), observer_.latest_outputs().size()); 1109 EXPECT_EQ(&small_mode_, observer_.latest_outputs()[0].mirror_mode); 1110 EXPECT_EQ(&small_mode_, 1111 observer_.latest_outputs()[0].display->current_mode()); 1112 EXPECT_EQ(&small_mode_, observer_.latest_outputs()[1].mirror_mode); 1113 EXPECT_EQ(&small_mode_, 1114 observer_.latest_outputs()[1].display->current_mode()); 1115 1116 // Also check that the newly-added small mode is present in the internal 1117 // snapshot that was passed to the observer (http://crbug.com/289159). 1118 const DisplayConfigurator::DisplayState& state = 1119 observer_.latest_outputs()[0]; 1120 ASSERT_NE(state.display->modes().end(), 1121 std::find(state.display->modes().begin(), 1122 state.display->modes().end(), 1123 &small_mode_)); 1124 } 1125 1126 TEST_F(DisplayConfiguratorTest, ContentProtection) { 1127 configurator_.Init(false); 1128 configurator_.ForceInitialConfigure(0); 1129 EXPECT_NE(kNoActions, log_->GetActionsAndClear()); 1130 1131 DisplayConfigurator::ContentProtectionClientId id = 1132 configurator_.RegisterContentProtectionClient(); 1133 EXPECT_NE(0u, id); 1134 1135 // One output. 1136 UpdateOutputs(1, true); 1137 EXPECT_NE(kNoActions, log_->GetActionsAndClear()); 1138 uint32_t link_mask = 0; 1139 uint32_t protection_mask = 0; 1140 EXPECT_TRUE(configurator_.QueryContentProtectionStatus( 1141 id, outputs_[0].display_id(), &link_mask, &protection_mask)); 1142 EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_INTERNAL), link_mask); 1143 EXPECT_EQ(static_cast<uint32_t>(CONTENT_PROTECTION_METHOD_NONE), 1144 protection_mask); 1145 EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); 1146 1147 // Two outputs. 1148 UpdateOutputs(2, true); 1149 EXPECT_NE(kNoActions, log_->GetActionsAndClear()); 1150 EXPECT_TRUE(configurator_.QueryContentProtectionStatus( 1151 id, outputs_[1].display_id(), &link_mask, &protection_mask)); 1152 EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_HDMI), link_mask); 1153 EXPECT_EQ(static_cast<uint32_t>(CONTENT_PROTECTION_METHOD_NONE), 1154 protection_mask); 1155 EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); 1156 1157 EXPECT_TRUE(configurator_.EnableContentProtection( 1158 id, outputs_[1].display_id(), CONTENT_PROTECTION_METHOD_HDCP)); 1159 EXPECT_EQ(GetSetHDCPStateAction(outputs_[1], HDCP_STATE_DESIRED), 1160 log_->GetActionsAndClear()); 1161 1162 // Enable protection. 1163 native_display_delegate_->set_hdcp_state(HDCP_STATE_ENABLED); 1164 EXPECT_TRUE(configurator_.QueryContentProtectionStatus( 1165 id, outputs_[1].display_id(), &link_mask, &protection_mask)); 1166 EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_HDMI), link_mask); 1167 EXPECT_EQ(static_cast<uint32_t>(CONTENT_PROTECTION_METHOD_HDCP), 1168 protection_mask); 1169 EXPECT_EQ(kNoActions, log_->GetActionsAndClear()); 1170 1171 // Protections should be disabled after unregister. 1172 configurator_.UnregisterContentProtectionClient(id); 1173 EXPECT_EQ(GetSetHDCPStateAction(outputs_[1], HDCP_STATE_UNDESIRED), 1174 log_->GetActionsAndClear()); 1175 } 1176 1177 TEST_F(DisplayConfiguratorTest, ContentProtectionTwoClients) { 1178 DisplayConfigurator::ContentProtectionClientId client1 = 1179 configurator_.RegisterContentProtectionClient(); 1180 DisplayConfigurator::ContentProtectionClientId client2 = 1181 configurator_.RegisterContentProtectionClient(); 1182 EXPECT_NE(client1, client2); 1183 1184 configurator_.Init(false); 1185 configurator_.ForceInitialConfigure(0); 1186 UpdateOutputs(2, true); 1187 EXPECT_NE(kNoActions, log_->GetActionsAndClear()); 1188 1189 // Clients never know state enableness for methods that they didn't request. 1190 EXPECT_TRUE(configurator_.EnableContentProtection( 1191 client1, outputs_[1].display_id(), CONTENT_PROTECTION_METHOD_HDCP)); 1192 EXPECT_EQ(GetSetHDCPStateAction(outputs_[1], HDCP_STATE_DESIRED).c_str(), 1193 log_->GetActionsAndClear()); 1194 native_display_delegate_->set_hdcp_state(HDCP_STATE_ENABLED); 1195 1196 uint32_t link_mask = 0; 1197 uint32_t protection_mask = 0; 1198 EXPECT_TRUE(configurator_.QueryContentProtectionStatus( 1199 client1, outputs_[1].display_id(), &link_mask, &protection_mask)); 1200 EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_HDMI), link_mask); 1201 EXPECT_EQ(CONTENT_PROTECTION_METHOD_HDCP, protection_mask); 1202 1203 EXPECT_TRUE(configurator_.QueryContentProtectionStatus( 1204 client2, outputs_[1].display_id(), &link_mask, &protection_mask)); 1205 EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_HDMI), link_mask); 1206 EXPECT_EQ(CONTENT_PROTECTION_METHOD_NONE, protection_mask); 1207 1208 // Protections will be disabled only if no more clients request them. 1209 EXPECT_TRUE(configurator_.EnableContentProtection( 1210 client2, outputs_[1].display_id(), CONTENT_PROTECTION_METHOD_NONE)); 1211 EXPECT_EQ(GetSetHDCPStateAction(outputs_[1], HDCP_STATE_DESIRED).c_str(), 1212 log_->GetActionsAndClear()); 1213 EXPECT_TRUE(configurator_.EnableContentProtection( 1214 client1, outputs_[1].display_id(), CONTENT_PROTECTION_METHOD_NONE)); 1215 EXPECT_EQ(GetSetHDCPStateAction(outputs_[1], HDCP_STATE_UNDESIRED).c_str(), 1216 log_->GetActionsAndClear()); 1217 } 1218 1219 TEST_F(DisplayConfiguratorTest, HandleConfigureCrtcFailure) { 1220 InitWithSingleOutput(); 1221 1222 ScopedVector<const DisplayMode> modes; 1223 // The first mode is the mode we are requesting DisplayConfigurator to choose. 1224 // The test will be setup so that this mode will fail and it will have to 1225 // choose the next best option. 1226 modes.push_back(new DisplayMode(gfx::Size(2560, 1600), false, 60.0)); 1227 modes.push_back(new DisplayMode(gfx::Size(1024, 768), false, 60.0)); 1228 modes.push_back(new DisplayMode(gfx::Size(1280, 720), false, 60.0)); 1229 modes.push_back(new DisplayMode(gfx::Size(1920, 1080), false, 60.0)); 1230 modes.push_back(new DisplayMode(gfx::Size(1920, 1080), false, 40.0)); 1231 1232 for (unsigned int i = 0; i < arraysize(outputs_); i++) { 1233 outputs_[i].set_modes(modes.get()); 1234 outputs_[i].set_current_mode(modes[0]); 1235 outputs_[i].set_native_mode(modes[0]); 1236 } 1237 1238 configurator_.Init(false); 1239 1240 // First test simply fails in MULTIPLE_DISPLAY_STATE_SINGLE mode. This is 1241 // probably unrealistic but we want to make sure any assumptions don't creep 1242 // in. 1243 native_display_delegate_->set_max_configurable_pixels( 1244 modes[2]->size().GetArea()); 1245 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_SINGLE); 1246 UpdateOutputs(1, true); 1247 1248 EXPECT_EQ( 1249 JoinActions( 1250 kGrab, 1251 GetFramebufferAction(big_mode_.size(), &outputs_[0], NULL).c_str(), 1252 GetCrtcAction(outputs_[0], modes[0], gfx::Point(0, 0)).c_str(), 1253 GetCrtcAction(outputs_[0], modes[3], gfx::Point(0, 0)).c_str(), 1254 GetCrtcAction(outputs_[0], modes[2], gfx::Point(0, 0)).c_str(), 1255 kUngrab, 1256 NULL), 1257 log_->GetActionsAndClear()); 1258 1259 // This test should attempt to configure a mirror mode that will not succeed 1260 // and should end up in extended mode. 1261 native_display_delegate_->set_max_configurable_pixels( 1262 modes[3]->size().GetArea()); 1263 state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR); 1264 UpdateOutputs(2, true); 1265 1266 EXPECT_EQ( 1267 JoinActions( 1268 kGrab, 1269 GetFramebufferAction(modes[0]->size(), &outputs_[0], &outputs_[1]) 1270 .c_str(), 1271 GetCrtcAction(outputs_[0], modes[0], gfx::Point(0, 0)).c_str(), 1272 // First mode tried is expected to fail and it will 1273 // retry wil the 4th mode in the list. 1274 GetCrtcAction(outputs_[0], modes[3], gfx::Point(0, 0)).c_str(), 1275 // Then attempt to configure crtc1 with the first mode. 1276 GetCrtcAction(outputs_[1], modes[0], gfx::Point(0, 0)).c_str(), 1277 GetCrtcAction(outputs_[1], modes[3], gfx::Point(0, 0)).c_str(), 1278 // Since it was requested to go into mirror mode 1279 // and the configured modes were different, it 1280 // should now try and setup a valid configurable 1281 // extended mode. 1282 GetFramebufferAction( 1283 gfx::Size(modes[0]->size().width(), 1284 modes[0]->size().height() + modes[0]->size().height() + 1285 DisplayConfigurator::kVerticalGap), 1286 &outputs_[0], 1287 &outputs_[1]).c_str(), 1288 GetCrtcAction(outputs_[0], modes[0], gfx::Point(0, 0)).c_str(), 1289 GetCrtcAction(outputs_[0], modes[3], gfx::Point(0, 0)).c_str(), 1290 GetCrtcAction(outputs_[1], 1291 modes[0], 1292 gfx::Point(0, 1293 modes[0]->size().height() + 1294 DisplayConfigurator::kVerticalGap)) 1295 .c_str(), 1296 GetCrtcAction(outputs_[1], 1297 modes[3], 1298 gfx::Point(0, 1299 modes[0]->size().height() + 1300 DisplayConfigurator::kVerticalGap)) 1301 .c_str(), 1302 kUngrab, 1303 NULL), 1304 log_->GetActionsAndClear()); 1305 } 1306 1307 } // namespace ui 1308