Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(14)

Side by Side Diff: ui/display/chromeos/output_configurator_unittest.cc

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

Powered by Google App Engine
This is Rietveld 408576698