Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / ui / display / chromeos / display_configurator_unittest.cc
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::ConfigureCTM() call.
86 std::string GetCTMAction(
87     int device_id,
88     const DisplayConfigurator::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
149     : public DisplayConfigurator::TouchscreenDelegate {
150  public:
151   // Ownership of |log| remains with the caller.
152   explicit TestTouchscreenDelegate(ActionLogger* log)
153       : log_(log),
154         configure_touchscreens_(false) {}
155   virtual ~TestTouchscreenDelegate() {}
156
157   const DisplayConfigurator::CoordinateTransformation& GetCTM(
158       int touch_device_id) {
159     return ctms_[touch_device_id];
160   }
161
162   void set_configure_touchscreens(bool state) {
163     configure_touchscreens_ = state;
164   }
165
166   // DisplayConfigurator::TouchscreenDelegate implementation:
167   virtual void AssociateTouchscreens(
168       DisplayConfigurator::DisplayStateList* outputs) OVERRIDE {
169     if (configure_touchscreens_) {
170       for (size_t i = 0; i < outputs->size(); ++i)
171         (*outputs)[i].touch_device_id = i + 1;
172     }
173   }
174   virtual void ConfigureCTM(
175       int touch_device_id,
176       const DisplayConfigurator::CoordinateTransformation& ctm) OVERRIDE {
177     log_->AppendAction(GetCTMAction(touch_device_id, ctm));
178     ctms_[touch_device_id] = ctm;
179   }
180
181  private:
182   ActionLogger* log_;  // Not owned.
183
184   bool configure_touchscreens_;
185
186   // Most-recently-configured transformation matrices, keyed by touch device ID.
187   std::map<int, DisplayConfigurator::CoordinateTransformation> ctms_;
188
189   DISALLOW_COPY_AND_ASSIGN(TestTouchscreenDelegate);
190 };
191
192 class TestNativeDisplayDelegate : public NativeDisplayDelegate {
193  public:
194   // Ownership of |log| remains with the caller.
195   explicit TestNativeDisplayDelegate(ActionLogger* log)
196       : max_configurable_pixels_(0),
197         hdcp_state_(HDCP_STATE_UNDESIRED),
198         log_(log) {}
199   virtual ~TestNativeDisplayDelegate() {}
200
201   const std::vector<DisplaySnapshot*>& outputs() const { return outputs_; }
202   void set_outputs(const std::vector<DisplaySnapshot*>& outputs) {
203     outputs_ = outputs;
204   }
205
206   void set_max_configurable_pixels(int pixels) {
207     max_configurable_pixels_ = pixels;
208   }
209
210   void set_hdcp_state(HDCPState state) { hdcp_state_ = state; }
211
212   // DisplayConfigurator::Delegate overrides:
213   virtual void Initialize() OVERRIDE { log_->AppendAction(kInitXRandR); }
214   virtual void GrabServer() OVERRIDE { log_->AppendAction(kGrab); }
215   virtual void UngrabServer() OVERRIDE { log_->AppendAction(kUngrab); }
216   virtual void SyncWithServer() OVERRIDE { log_->AppendAction(kSync); }
217   virtual void SetBackgroundColor(uint32_t color_argb) OVERRIDE {
218     log_->AppendAction(GetBackgroundAction(color_argb));
219   }
220   virtual void ForceDPMSOn() OVERRIDE { log_->AppendAction(kForceDPMS); }
221   virtual std::vector<DisplaySnapshot*> GetDisplays() OVERRIDE {
222     return outputs_;
223   }
224   virtual void AddMode(const DisplaySnapshot& output,
225                        const DisplayMode* mode) OVERRIDE {
226     log_->AppendAction(GetAddOutputModeAction(output, mode));
227   }
228   virtual bool Configure(const DisplaySnapshot& output,
229                          const DisplayMode* mode,
230                          const gfx::Point& origin) OVERRIDE {
231     log_->AppendAction(GetCrtcAction(output, mode, origin));
232
233     if (max_configurable_pixels_ == 0)
234       return true;
235
236     if (!mode)
237       return false;
238
239     return mode->size().GetArea() <= max_configurable_pixels_;
240   }
241   virtual void CreateFrameBuffer(const gfx::Size& size) OVERRIDE {
242     log_->AppendAction(
243         GetFramebufferAction(size,
244                              outputs_.size() >= 1 ? outputs_[0] : NULL,
245                              outputs_.size() >= 2 ? outputs_[1] : NULL));
246   }
247   virtual bool GetHDCPState(const DisplaySnapshot& output,
248                             HDCPState* state) OVERRIDE {
249     *state = hdcp_state_;
250     return true;
251   }
252
253   virtual bool SetHDCPState(const DisplaySnapshot& output,
254                             HDCPState state) OVERRIDE {
255     log_->AppendAction(GetSetHDCPStateAction(output, state));
256     return true;
257   }
258
259   virtual std::vector<ui::ColorCalibrationProfile>
260   GetAvailableColorCalibrationProfiles(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 GetDisplays().
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 DisplayConfigurator::Observer {
295  public:
296   explicit TestObserver(DisplayConfigurator* 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 DisplayConfigurator::DisplayStateList& latest_outputs() const {
306     return latest_outputs_;
307   }
308   MultipleDisplayState latest_failed_state() const {
309     return latest_failed_state_;
310   }
311
312   void Reset() {
313     num_changes_ = 0;
314     num_failures_ = 0;
315     latest_outputs_.clear();
316     latest_failed_state_ = MULTIPLE_DISPLAY_STATE_INVALID;
317   }
318
319   // DisplayConfigurator::Observer overrides:
320   virtual void OnDisplayModeChanged(
321       const DisplayConfigurator::DisplayStateList& outputs) OVERRIDE {
322     num_changes_++;
323     latest_outputs_ = outputs;
324   }
325
326   virtual void OnDisplayModeChangeFailed(MultipleDisplayState failed_new_state)
327       OVERRIDE {
328     num_failures_++;
329     latest_failed_state_ = failed_new_state;
330   }
331
332  private:
333   DisplayConfigurator* configurator_;  // Not owned.
334
335   // Number of times that OnDisplayMode*() has been called.
336   int num_changes_;
337   int num_failures_;
338
339   // Parameters most recently passed to OnDisplayMode*().
340   DisplayConfigurator::DisplayStateList latest_outputs_;
341   MultipleDisplayState latest_failed_state_;
342
343   DISALLOW_COPY_AND_ASSIGN(TestObserver);
344 };
345
346 class TestStateController : public DisplayConfigurator::StateController {
347  public:
348   TestStateController() : state_(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED) {}
349   virtual ~TestStateController() {}
350
351   void set_state(MultipleDisplayState state) { state_ = state; }
352
353   // DisplayConfigurator::StateController overrides:
354   virtual MultipleDisplayState GetStateForDisplayIds(
355       const std::vector<int64_t>& outputs) const OVERRIDE {
356     return state_;
357   }
358   virtual bool GetResolutionForDisplayId(int64_t display_id,
359                                          gfx::Size* size) const OVERRIDE {
360     return false;
361   }
362
363  private:
364   MultipleDisplayState state_;
365
366   DISALLOW_COPY_AND_ASSIGN(TestStateController);
367 };
368
369 class TestMirroringController
370     : public DisplayConfigurator::SoftwareMirroringController {
371  public:
372   TestMirroringController() : software_mirroring_enabled_(false) {}
373   virtual ~TestMirroringController() {}
374
375   virtual void SetSoftwareMirroring(bool enabled) OVERRIDE {
376     software_mirroring_enabled_ = enabled;
377   }
378
379   bool software_mirroring_enabled() const {
380     return software_mirroring_enabled_;
381   }
382
383  private:
384   bool software_mirroring_enabled_;
385
386   DISALLOW_COPY_AND_ASSIGN(TestMirroringController);
387 };
388
389 class DisplayConfiguratorTest : public testing::Test {
390  public:
391   DisplayConfiguratorTest()
392       : small_mode_(gfx::Size(1366, 768), false, 60.0f),
393         big_mode_(gfx::Size(2560, 1600), false, 60.0f),
394         observer_(&configurator_),
395         test_api_(&configurator_) {}
396   virtual ~DisplayConfiguratorTest() {}
397
398   virtual void SetUp() OVERRIDE {
399     log_.reset(new ActionLogger());
400
401     native_display_delegate_ = new TestNativeDisplayDelegate(log_.get());
402     touchscreen_delegate_ = new TestTouchscreenDelegate(log_.get());
403     configurator_.SetDelegatesForTesting(
404         scoped_ptr<NativeDisplayDelegate>(native_display_delegate_),
405         scoped_ptr<DisplayConfigurator::TouchscreenDelegate>(
406             touchscreen_delegate_));
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(DISPLAY_CONNECTION_TYPE_INTERNAL);
419     o->set_is_aspect_preserving_scaling(true);
420     o->set_display_id(123);
421     o->set_has_proper_display_id(true);
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(DISPLAY_CONNECTION_TYPE_HDMI);
429     o->set_is_aspect_preserving_scaling(true);
430     o->set_display_id(456);
431     o->set_has_proper_display_id(true);
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   DisplayConfigurator configurator_;
483   TestObserver observer_;
484   scoped_ptr<ActionLogger> log_;
485   TestNativeDisplayDelegate* native_display_delegate_;  // not owned
486   TestTouchscreenDelegate* touchscreen_delegate_;       // not owned
487   DisplayConfigurator::TestApi test_api_;
488
489   TestDisplaySnapshot outputs_[2];
490
491  private:
492   DISALLOW_COPY_AND_ASSIGN(DisplayConfiguratorTest);
493 };
494
495 }  // namespace
496
497 TEST_F(DisplayConfiguratorTest, 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             DisplayConfigurator::FindDisplayModeMatchingSize(
528                 output, gfx::Size(1920, 1200)));
529
530   // Should pick highest refresh rate.
531   EXPECT_EQ(modes[2],
532             DisplayConfigurator::FindDisplayModeMatchingSize(
533                 output, gfx::Size(1920, 1080)));
534
535   // Should pick non-interlaced mode.
536   EXPECT_EQ(modes[6],
537             DisplayConfigurator::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             DisplayConfigurator::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             DisplayConfigurator::FindDisplayModeMatchingSize(
550                 output, gfx::Size(1024, 600)));
551
552   // Just one interlaced mode.
553   EXPECT_EQ(modes[13],
554             DisplayConfigurator::FindDisplayModeMatchingSize(
555                 output, gfx::Size(640, 480)));
556
557   // Refresh rate not available.
558   EXPECT_EQ(modes[14],
559             DisplayConfigurator::FindDisplayModeMatchingSize(
560                 output, gfx::Size(320, 200)));
561
562   // No mode found.
563   EXPECT_EQ(NULL,
564             DisplayConfigurator::FindDisplayModeMatchingSize(
565                 output, gfx::Size(1440, 900)));
566 }
567
568 TEST_F(DisplayConfiguratorTest, 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(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED);
575   UpdateOutputs(2, true);
576   const int kDualHeight = small_mode_.size().height() +
577                           DisplayConfigurator::kVerticalGap +
578                           big_mode_.size().height();
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                                        DisplayConfigurator::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(MULTIPLE_DISPLAY_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(MULTIPLE_DISPLAY_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                                        DisplayConfigurator::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(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR));
651   EXPECT_EQ(JoinActions(kGrab, kUngrab, NULL), log_->GetActionsAndClear());
652   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
653             configurator_.display_state());
654   EXPECT_TRUE(mirroring_controller_.software_mirroring_enabled());
655   EXPECT_EQ(1, observer_.num_changes());
656
657   // Setting MULTIPLE_DISPLAY_STATE_DUAL_MIRROR should try to reconfigure.
658   observer_.Reset();
659   EXPECT_TRUE(
660       configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED));
661   EXPECT_EQ(JoinActions(NULL), log_->GetActionsAndClear());
662   EXPECT_FALSE(mirroring_controller_.software_mirroring_enabled());
663   EXPECT_EQ(1, observer_.num_changes());
664
665   // Set back to software mirror mode.
666   observer_.Reset();
667   EXPECT_TRUE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR));
668   EXPECT_EQ(JoinActions(kGrab, kUngrab, NULL), log_->GetActionsAndClear());
669   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
670             configurator_.display_state());
671   EXPECT_TRUE(mirroring_controller_.software_mirroring_enabled());
672   EXPECT_EQ(1, observer_.num_changes());
673
674   // Disconnect the second output.
675   observer_.Reset();
676   UpdateOutputs(1, true);
677   EXPECT_EQ(
678       JoinActions(
679           kGrab,
680           GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL).c_str(),
681           GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
682           kUngrab,
683           NULL),
684       log_->GetActionsAndClear());
685   EXPECT_FALSE(mirroring_controller_.software_mirroring_enabled());
686   EXPECT_EQ(1, observer_.num_changes());
687 }
688
689 TEST_F(DisplayConfiguratorTest, SetDisplayPower) {
690   InitWithSingleOutput();
691
692   state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
693   observer_.Reset();
694   UpdateOutputs(2, true);
695   EXPECT_EQ(
696       JoinActions(
697           kGrab,
698           GetFramebufferAction(small_mode_.size(), &outputs_[0], &outputs_[1])
699               .c_str(),
700           GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
701           GetCrtcAction(outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
702           kUngrab,
703           NULL),
704       log_->GetActionsAndClear());
705   EXPECT_FALSE(mirroring_controller_.software_mirroring_enabled());
706   EXPECT_EQ(1, observer_.num_changes());
707
708   // Turning off the internal display should switch the external display to
709   // its native mode.
710   observer_.Reset();
711   configurator_.SetDisplayPower(
712       chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON,
713       DisplayConfigurator::kSetDisplayPowerNoFlags);
714   EXPECT_EQ(
715       JoinActions(
716           kGrab,
717           GetFramebufferAction(big_mode_.size(), &outputs_[0], &outputs_[1])
718               .c_str(),
719           GetCrtcAction(outputs_[0], NULL, gfx::Point(0, 0)).c_str(),
720           GetCrtcAction(outputs_[1], &big_mode_, gfx::Point(0, 0)).c_str(),
721           kForceDPMS,
722           kUngrab,
723           NULL),
724       log_->GetActionsAndClear());
725   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_SINGLE, configurator_.display_state());
726   EXPECT_EQ(1, observer_.num_changes());
727
728   // When all displays are turned off, the framebuffer should switch back
729   // to the mirrored size.
730   observer_.Reset();
731   configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF,
732                                 DisplayConfigurator::kSetDisplayPowerNoFlags);
733   EXPECT_EQ(
734       JoinActions(kGrab,
735                   GetFramebufferAction(
736                       small_mode_.size(), &outputs_[0], &outputs_[1]).c_str(),
737                   GetCrtcAction(outputs_[0], NULL, gfx::Point(0, 0)).c_str(),
738                   GetCrtcAction(outputs_[1], NULL, gfx::Point(0, 0)).c_str(),
739                   kUngrab,
740                   NULL),
741       log_->GetActionsAndClear());
742   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, configurator_.display_state());
743   EXPECT_FALSE(mirroring_controller_.software_mirroring_enabled());
744   EXPECT_EQ(1, observer_.num_changes());
745
746   // Turn all displays on and check that mirroring is still used.
747   observer_.Reset();
748   configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON,
749                                 DisplayConfigurator::kSetDisplayPowerNoFlags);
750   EXPECT_EQ(
751       JoinActions(
752           kGrab,
753           GetFramebufferAction(small_mode_.size(), &outputs_[0], &outputs_[1])
754               .c_str(),
755           GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
756           GetCrtcAction(outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
757           kForceDPMS,
758           kUngrab,
759           NULL),
760       log_->GetActionsAndClear());
761   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, configurator_.display_state());
762   EXPECT_FALSE(mirroring_controller_.software_mirroring_enabled());
763   EXPECT_EQ(1, observer_.num_changes());
764
765   // Get rid of shared modes to force software mirroring.
766   outputs_[1].set_modes(std::vector<const DisplayMode*>(1, &big_mode_));
767   state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
768   observer_.Reset();
769   UpdateOutputs(2, true);
770   const int kDualHeight = small_mode_.size().height() +
771                           DisplayConfigurator::kVerticalGap +
772                           big_mode_.size().height();
773   EXPECT_EQ(
774       JoinActions(
775           kGrab,
776           GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
777                                &outputs_[0],
778                                &outputs_[1]).c_str(),
779           GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
780           GetCrtcAction(outputs_[1],
781                         &big_mode_,
782                         gfx::Point(0,
783                                    small_mode_.size().height() +
784                                        DisplayConfigurator::kVerticalGap))
785               .c_str(),
786           kUngrab,
787           NULL),
788       log_->GetActionsAndClear());
789   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
790             configurator_.display_state());
791   EXPECT_TRUE(mirroring_controller_.software_mirroring_enabled());
792   EXPECT_EQ(1, observer_.num_changes());
793
794   // Turning off the internal display should switch the external display to
795   // its native mode.
796   observer_.Reset();
797   configurator_.SetDisplayPower(
798       chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON,
799       DisplayConfigurator::kSetDisplayPowerNoFlags);
800   EXPECT_EQ(
801       JoinActions(
802           kGrab,
803           GetFramebufferAction(big_mode_.size(), &outputs_[0], &outputs_[1])
804               .c_str(),
805           GetCrtcAction(outputs_[0], NULL, gfx::Point(0, 0)).c_str(),
806           GetCrtcAction(outputs_[1], &big_mode_, gfx::Point(0, 0)).c_str(),
807           kForceDPMS,
808           kUngrab,
809           NULL),
810       log_->GetActionsAndClear());
811   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_SINGLE, configurator_.display_state());
812   EXPECT_FALSE(mirroring_controller_.software_mirroring_enabled());
813   EXPECT_EQ(1, observer_.num_changes());
814
815   // When all displays are turned off, the framebuffer should switch back
816   // to the extended + software mirroring.
817   observer_.Reset();
818   configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF,
819                                 DisplayConfigurator::kSetDisplayPowerNoFlags);
820   EXPECT_EQ(
821       JoinActions(
822           kGrab,
823           GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
824                                &outputs_[0],
825                                &outputs_[1]).c_str(),
826           GetCrtcAction(outputs_[0], NULL, gfx::Point(0, 0)).c_str(),
827           GetCrtcAction(outputs_[1],
828                         NULL,
829                         gfx::Point(0,
830                                    small_mode_.size().height() +
831                                        DisplayConfigurator::kVerticalGap))
832               .c_str(),
833           kUngrab,
834           NULL),
835       log_->GetActionsAndClear());
836   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
837             configurator_.display_state());
838   EXPECT_TRUE(mirroring_controller_.software_mirroring_enabled());
839   EXPECT_EQ(1, observer_.num_changes());
840
841   // Turn all displays on and check that mirroring is still used.
842   observer_.Reset();
843   configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON,
844                                 DisplayConfigurator::kSetDisplayPowerNoFlags);
845   EXPECT_EQ(
846       JoinActions(
847           kGrab,
848           GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
849                                &outputs_[0],
850                                &outputs_[1]).c_str(),
851           GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
852           GetCrtcAction(outputs_[1],
853                         &big_mode_,
854                         gfx::Point(0,
855                                    small_mode_.size().height() +
856                                        DisplayConfigurator::kVerticalGap))
857               .c_str(),
858           kForceDPMS,
859           kUngrab,
860           NULL),
861       log_->GetActionsAndClear());
862   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
863             configurator_.display_state());
864   EXPECT_TRUE(mirroring_controller_.software_mirroring_enabled());
865   EXPECT_EQ(1, observer_.num_changes());
866 }
867
868 TEST_F(DisplayConfiguratorTest, SuspendAndResume) {
869   InitWithSingleOutput();
870
871   // No preparation is needed before suspending when the display is already
872   // on.  The configurator should still reprobe on resume in case a display
873   // was connected while suspended.
874   configurator_.SuspendDisplays();
875   EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
876   configurator_.ResumeDisplays();
877   EXPECT_EQ(
878       JoinActions(
879           kGrab,
880           GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL).c_str(),
881           GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
882           kForceDPMS,
883           kUngrab,
884           NULL),
885       log_->GetActionsAndClear());
886
887   // Now turn the display off before suspending and check that the
888   // configurator turns it back on and syncs with the server.
889   configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF,
890                                 DisplayConfigurator::kSetDisplayPowerNoFlags);
891   EXPECT_EQ(
892       JoinActions(
893           kGrab,
894           GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL).c_str(),
895           GetCrtcAction(outputs_[0], NULL, gfx::Point(0, 0)).c_str(),
896           kUngrab,
897           NULL),
898       log_->GetActionsAndClear());
899
900   configurator_.SuspendDisplays();
901   EXPECT_EQ(
902       JoinActions(
903           kGrab,
904           GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL).c_str(),
905           GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
906           kForceDPMS,
907           kUngrab,
908           kSync,
909           NULL),
910       log_->GetActionsAndClear());
911
912   configurator_.ResumeDisplays();
913   EXPECT_EQ(
914       JoinActions(
915           kGrab,
916           GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL).c_str(),
917           GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
918           kForceDPMS,
919           kUngrab,
920           NULL),
921       log_->GetActionsAndClear());
922
923   // If a second, external display is connected, the displays shouldn't be
924   // powered back on before suspending.
925   state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
926   UpdateOutputs(2, true);
927   EXPECT_EQ(
928       JoinActions(
929           kGrab,
930           GetFramebufferAction(small_mode_.size(), &outputs_[0], &outputs_[1])
931               .c_str(),
932           GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
933           GetCrtcAction(outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
934           kUngrab,
935           NULL),
936       log_->GetActionsAndClear());
937
938   configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF,
939                                 DisplayConfigurator::kSetDisplayPowerNoFlags);
940   EXPECT_EQ(
941       JoinActions(kGrab,
942                   GetFramebufferAction(
943                       small_mode_.size(), &outputs_[0], &outputs_[1]).c_str(),
944                   GetCrtcAction(outputs_[0], NULL, gfx::Point(0, 0)).c_str(),
945                   GetCrtcAction(outputs_[1], NULL, gfx::Point(0, 0)).c_str(),
946                   kUngrab,
947                   NULL),
948       log_->GetActionsAndClear());
949
950   configurator_.SuspendDisplays();
951   EXPECT_EQ(JoinActions(kGrab, kUngrab, kSync, NULL),
952             log_->GetActionsAndClear());
953
954   // If a display is disconnected while suspended, the configurator should
955   // pick up the change.
956   UpdateOutputs(1, false);
957   configurator_.ResumeDisplays();
958   EXPECT_EQ(
959       JoinActions(
960           kGrab,
961           GetFramebufferAction(small_mode_.size(), &outputs_[0], NULL).c_str(),
962           GetCrtcAction(outputs_[0], NULL, gfx::Point(0, 0)).c_str(),
963           kUngrab,
964           NULL),
965       log_->GetActionsAndClear());
966 }
967
968 TEST_F(DisplayConfiguratorTest, Headless) {
969   UpdateOutputs(0, false);
970   EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
971   configurator_.Init(false);
972   EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
973   configurator_.ForceInitialConfigure(0);
974   EXPECT_EQ(JoinActions(kGrab, kInitXRandR, kForceDPMS, kUngrab, NULL),
975             log_->GetActionsAndClear());
976
977   // Not much should happen when the display power state is changed while
978   // no displays are connected.
979   configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_OFF,
980                                 DisplayConfigurator::kSetDisplayPowerNoFlags);
981   EXPECT_EQ(JoinActions(kGrab, kUngrab, NULL), log_->GetActionsAndClear());
982   configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON,
983                                 DisplayConfigurator::kSetDisplayPowerNoFlags);
984   EXPECT_EQ(JoinActions(kGrab, kForceDPMS, kUngrab, NULL),
985             log_->GetActionsAndClear());
986
987   // Connect an external display and check that it's configured correctly.
988   outputs_[0].set_current_mode(outputs_[1].current_mode());
989   outputs_[0].set_native_mode(outputs_[1].native_mode());
990   outputs_[0].set_modes(outputs_[1].modes());
991   outputs_[0].set_type(outputs_[1].type());
992
993   UpdateOutputs(1, true);
994   EXPECT_EQ(
995       JoinActions(
996           kGrab,
997           GetFramebufferAction(big_mode_.size(), &outputs_[0], NULL).c_str(),
998           GetCrtcAction(outputs_[0], &big_mode_, gfx::Point(0, 0)).c_str(),
999           kUngrab,
1000           NULL),
1001       log_->GetActionsAndClear());
1002 }
1003
1004 TEST_F(DisplayConfiguratorTest, StartWithTwoOutputs) {
1005   UpdateOutputs(2, false);
1006   EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
1007   configurator_.Init(false);
1008   EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
1009
1010   state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
1011   configurator_.ForceInitialConfigure(0);
1012   EXPECT_EQ(
1013       JoinActions(
1014           kGrab,
1015           kInitXRandR,
1016           GetFramebufferAction(small_mode_.size(), &outputs_[0], &outputs_[1])
1017               .c_str(),
1018           GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
1019           GetCrtcAction(outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
1020           kForceDPMS,
1021           kUngrab,
1022           NULL),
1023       log_->GetActionsAndClear());
1024 }
1025
1026 TEST_F(DisplayConfiguratorTest, InvalidMultipleDisplayStates) {
1027   UpdateOutputs(0, false);
1028   EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
1029   configurator_.Init(false);
1030   configurator_.ForceInitialConfigure(0);
1031   observer_.Reset();
1032   EXPECT_TRUE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_HEADLESS));
1033   EXPECT_FALSE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_SINGLE));
1034   EXPECT_FALSE(
1035       configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR));
1036   EXPECT_FALSE(
1037       configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED));
1038   EXPECT_EQ(1, observer_.num_changes());
1039   EXPECT_EQ(3, observer_.num_failures());
1040
1041   UpdateOutputs(1, true);
1042   observer_.Reset();
1043   EXPECT_FALSE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_HEADLESS));
1044   EXPECT_TRUE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_SINGLE));
1045   EXPECT_FALSE(
1046       configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR));
1047   EXPECT_FALSE(
1048       configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED));
1049   EXPECT_EQ(1, observer_.num_changes());
1050   EXPECT_EQ(3, observer_.num_failures());
1051
1052   state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED);
1053   UpdateOutputs(2, true);
1054   observer_.Reset();
1055   EXPECT_FALSE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_HEADLESS));
1056   EXPECT_FALSE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_SINGLE));
1057   EXPECT_TRUE(configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR));
1058   EXPECT_TRUE(
1059       configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED));
1060   EXPECT_EQ(2, observer_.num_changes());
1061   EXPECT_EQ(2, observer_.num_failures());
1062 }
1063
1064 TEST_F(DisplayConfiguratorTest, GetMultipleDisplayStateForDisplaysWithoutId) {
1065   outputs_[0].set_has_proper_display_id(false);
1066   UpdateOutputs(2, false);
1067   configurator_.Init(false);
1068   state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
1069   configurator_.ForceInitialConfigure(0);
1070   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
1071             configurator_.display_state());
1072 }
1073
1074 TEST_F(DisplayConfiguratorTest, GetMultipleDisplayStateForDisplaysWithId) {
1075   outputs_[0].set_has_proper_display_id(true);
1076   UpdateOutputs(2, false);
1077   configurator_.Init(false);
1078   state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
1079   configurator_.ForceInitialConfigure(0);
1080   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, configurator_.display_state());
1081 }
1082
1083 TEST_F(DisplayConfiguratorTest, UpdateCachedOutputsEvenAfterFailure) {
1084   InitWithSingleOutput();
1085   const DisplayConfigurator::DisplayStateList* cached =
1086       &configurator_.cached_displays();
1087   ASSERT_EQ(static_cast<size_t>(1), cached->size());
1088   EXPECT_EQ(outputs_[0].current_mode(), (*cached)[0].display->current_mode());
1089
1090   // After connecting a second output, check that it shows up in
1091   // |cached_displays_| even if an invalid state is requested.
1092   state_controller_.set_state(MULTIPLE_DISPLAY_STATE_SINGLE);
1093   UpdateOutputs(2, true);
1094   cached = &configurator_.cached_displays();
1095   ASSERT_EQ(static_cast<size_t>(2), cached->size());
1096   EXPECT_EQ(outputs_[0].current_mode(), (*cached)[0].display->current_mode());
1097   EXPECT_EQ(outputs_[1].current_mode(), (*cached)[1].display->current_mode());
1098 }
1099
1100 TEST_F(DisplayConfiguratorTest, PanelFitting) {
1101   // Configure the internal display to support only the big mode and the
1102   // external display to support only the small mode.
1103   outputs_[0].set_current_mode(&big_mode_);
1104   outputs_[0].set_native_mode(&big_mode_);
1105   outputs_[0].set_modes(std::vector<const DisplayMode*>(1, &big_mode_));
1106
1107   outputs_[1].set_current_mode(&small_mode_);
1108   outputs_[1].set_native_mode(&small_mode_);
1109   outputs_[1].set_modes(std::vector<const DisplayMode*>(1, &small_mode_));
1110
1111   // The small mode should be added to the internal output when requesting
1112   // mirrored mode.
1113   UpdateOutputs(2, false);
1114   state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
1115   configurator_.Init(true /* is_panel_fitting_enabled */);
1116   configurator_.ForceInitialConfigure(0);
1117   EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, configurator_.display_state());
1118   EXPECT_EQ(
1119       JoinActions(
1120           kGrab,
1121           kInitXRandR,
1122           GetAddOutputModeAction(outputs_[0], &small_mode_).c_str(),
1123           GetFramebufferAction(small_mode_.size(), &outputs_[0], &outputs_[1])
1124               .c_str(),
1125           GetCrtcAction(outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
1126           GetCrtcAction(outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
1127           kForceDPMS,
1128           kUngrab,
1129           NULL),
1130       log_->GetActionsAndClear());
1131
1132   // Both outputs should be using the small mode.
1133   ASSERT_EQ(1, observer_.num_changes());
1134   ASSERT_EQ(static_cast<size_t>(2), observer_.latest_outputs().size());
1135   EXPECT_EQ(&small_mode_, observer_.latest_outputs()[0].mirror_mode);
1136   EXPECT_EQ(&small_mode_,
1137             observer_.latest_outputs()[0].display->current_mode());
1138   EXPECT_EQ(&small_mode_, observer_.latest_outputs()[1].mirror_mode);
1139   EXPECT_EQ(&small_mode_,
1140             observer_.latest_outputs()[1].display->current_mode());
1141
1142   // Also check that the newly-added small mode is present in the internal
1143   // snapshot that was passed to the observer (http://crbug.com/289159).
1144   const DisplayConfigurator::DisplayState& state =
1145       observer_.latest_outputs()[0];
1146   ASSERT_NE(state.display->modes().end(),
1147             std::find(state.display->modes().begin(),
1148                       state.display->modes().end(),
1149                       &small_mode_));
1150 }
1151
1152 TEST_F(DisplayConfiguratorTest, ContentProtection) {
1153   configurator_.Init(false);
1154   configurator_.ForceInitialConfigure(0);
1155   EXPECT_NE(kNoActions, log_->GetActionsAndClear());
1156
1157   DisplayConfigurator::ContentProtectionClientId id =
1158       configurator_.RegisterContentProtectionClient();
1159   EXPECT_NE(0u, id);
1160
1161   // One output.
1162   UpdateOutputs(1, true);
1163   EXPECT_NE(kNoActions, log_->GetActionsAndClear());
1164   uint32_t link_mask = 0;
1165   uint32_t protection_mask = 0;
1166   EXPECT_TRUE(configurator_.QueryContentProtectionStatus(
1167       id, outputs_[0].display_id(), &link_mask, &protection_mask));
1168   EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_INTERNAL), link_mask);
1169   EXPECT_EQ(static_cast<uint32_t>(CONTENT_PROTECTION_METHOD_NONE),
1170             protection_mask);
1171   EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
1172
1173   // Two outputs.
1174   UpdateOutputs(2, true);
1175   EXPECT_NE(kNoActions, log_->GetActionsAndClear());
1176   EXPECT_TRUE(configurator_.QueryContentProtectionStatus(
1177       id, outputs_[1].display_id(), &link_mask, &protection_mask));
1178   EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_HDMI), link_mask);
1179   EXPECT_EQ(static_cast<uint32_t>(CONTENT_PROTECTION_METHOD_NONE),
1180             protection_mask);
1181   EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
1182
1183   EXPECT_TRUE(configurator_.EnableContentProtection(
1184       id, outputs_[1].display_id(), CONTENT_PROTECTION_METHOD_HDCP));
1185   EXPECT_EQ(GetSetHDCPStateAction(outputs_[1], HDCP_STATE_DESIRED),
1186             log_->GetActionsAndClear());
1187
1188   // Enable protection.
1189   native_display_delegate_->set_hdcp_state(HDCP_STATE_ENABLED);
1190   EXPECT_TRUE(configurator_.QueryContentProtectionStatus(
1191       id, outputs_[1].display_id(), &link_mask, &protection_mask));
1192   EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_HDMI), link_mask);
1193   EXPECT_EQ(static_cast<uint32_t>(CONTENT_PROTECTION_METHOD_HDCP),
1194             protection_mask);
1195   EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
1196
1197   // Protections should be disabled after unregister.
1198   configurator_.UnregisterContentProtectionClient(id);
1199   EXPECT_EQ(GetSetHDCPStateAction(outputs_[1], HDCP_STATE_UNDESIRED),
1200             log_->GetActionsAndClear());
1201 }
1202
1203 TEST_F(DisplayConfiguratorTest, ContentProtectionTwoClients) {
1204   DisplayConfigurator::ContentProtectionClientId client1 =
1205       configurator_.RegisterContentProtectionClient();
1206   DisplayConfigurator::ContentProtectionClientId client2 =
1207       configurator_.RegisterContentProtectionClient();
1208   EXPECT_NE(client1, client2);
1209
1210   configurator_.Init(false);
1211   configurator_.ForceInitialConfigure(0);
1212   UpdateOutputs(2, true);
1213   EXPECT_NE(kNoActions, log_->GetActionsAndClear());
1214
1215   // Clients never know state enableness for methods that they didn't request.
1216   EXPECT_TRUE(configurator_.EnableContentProtection(
1217       client1, outputs_[1].display_id(), CONTENT_PROTECTION_METHOD_HDCP));
1218   EXPECT_EQ(GetSetHDCPStateAction(outputs_[1], HDCP_STATE_DESIRED).c_str(),
1219             log_->GetActionsAndClear());
1220   native_display_delegate_->set_hdcp_state(HDCP_STATE_ENABLED);
1221
1222   uint32_t link_mask = 0;
1223   uint32_t protection_mask = 0;
1224   EXPECT_TRUE(configurator_.QueryContentProtectionStatus(
1225       client1, outputs_[1].display_id(), &link_mask, &protection_mask));
1226   EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_HDMI), link_mask);
1227   EXPECT_EQ(CONTENT_PROTECTION_METHOD_HDCP, protection_mask);
1228
1229   EXPECT_TRUE(configurator_.QueryContentProtectionStatus(
1230       client2, outputs_[1].display_id(), &link_mask, &protection_mask));
1231   EXPECT_EQ(static_cast<uint32_t>(DISPLAY_CONNECTION_TYPE_HDMI), link_mask);
1232   EXPECT_EQ(CONTENT_PROTECTION_METHOD_NONE, protection_mask);
1233
1234   // Protections will be disabled only if no more clients request them.
1235   EXPECT_TRUE(configurator_.EnableContentProtection(
1236       client2, outputs_[1].display_id(), CONTENT_PROTECTION_METHOD_NONE));
1237   EXPECT_EQ(GetSetHDCPStateAction(outputs_[1], HDCP_STATE_DESIRED).c_str(),
1238             log_->GetActionsAndClear());
1239   EXPECT_TRUE(configurator_.EnableContentProtection(
1240       client1, outputs_[1].display_id(), CONTENT_PROTECTION_METHOD_NONE));
1241   EXPECT_EQ(GetSetHDCPStateAction(outputs_[1], HDCP_STATE_UNDESIRED).c_str(),
1242             log_->GetActionsAndClear());
1243 }
1244
1245 TEST_F(DisplayConfiguratorTest, CTMForMultiScreens) {
1246   touchscreen_delegate_->set_configure_touchscreens(true);
1247   UpdateOutputs(2, false);
1248   configurator_.Init(false);
1249   state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED);
1250   configurator_.ForceInitialConfigure(0);
1251
1252   const int kDualHeight = small_mode_.size().height() +
1253                           DisplayConfigurator::kVerticalGap +
1254                           big_mode_.size().height();
1255   const int kDualWidth = big_mode_.size().width();
1256
1257   DisplayConfigurator::CoordinateTransformation ctm1 =
1258       touchscreen_delegate_->GetCTM(1);
1259   DisplayConfigurator::CoordinateTransformation ctm2 =
1260       touchscreen_delegate_->GetCTM(2);
1261
1262   EXPECT_EQ(small_mode_.size().height() - 1,
1263             round((kDualHeight - 1) * ctm1.y_scale));
1264   EXPECT_EQ(0, round((kDualHeight - 1) * ctm1.y_offset));
1265
1266   EXPECT_EQ(big_mode_.size().height() - 1,
1267             round((kDualHeight - 1) * ctm2.y_scale));
1268   EXPECT_EQ(small_mode_.size().height() + DisplayConfigurator::kVerticalGap,
1269             round((kDualHeight - 1) * ctm2.y_offset));
1270
1271   EXPECT_EQ(small_mode_.size().width() - 1,
1272             round((kDualWidth - 1) * ctm1.x_scale));
1273   EXPECT_EQ(0, round((kDualWidth - 1) * ctm1.x_offset));
1274
1275   EXPECT_EQ(big_mode_.size().width() - 1,
1276             round((kDualWidth - 1) * ctm2.x_scale));
1277   EXPECT_EQ(0, round((kDualWidth - 1) * ctm2.x_offset));
1278 }
1279
1280 TEST_F(DisplayConfiguratorTest, HandleConfigureCrtcFailure) {
1281   InitWithSingleOutput();
1282
1283   ScopedVector<const DisplayMode> modes;
1284   // The first mode is the mode we are requesting DisplayConfigurator to choose.
1285   // The test will be setup so that this mode will fail and it will have to
1286   // choose the next best option.
1287   modes.push_back(new DisplayMode(gfx::Size(2560, 1600), false, 60.0));
1288   modes.push_back(new DisplayMode(gfx::Size(1024, 768), false, 60.0));
1289   modes.push_back(new DisplayMode(gfx::Size(1280, 720), false, 60.0));
1290   modes.push_back(new DisplayMode(gfx::Size(1920, 1080), false, 60.0));
1291   modes.push_back(new DisplayMode(gfx::Size(1920, 1080), false, 40.0));
1292
1293   for (unsigned int i = 0; i < arraysize(outputs_); i++) {
1294     outputs_[i].set_modes(modes.get());
1295     outputs_[i].set_current_mode(modes[0]);
1296     outputs_[i].set_native_mode(modes[0]);
1297   }
1298
1299   configurator_.Init(false);
1300
1301   // First test simply fails in MULTIPLE_DISPLAY_STATE_SINGLE mode. This is
1302   // probably unrealistic but we want to make sure any assumptions don't creep
1303   // in.
1304   native_display_delegate_->set_max_configurable_pixels(
1305       modes[2]->size().GetArea());
1306   state_controller_.set_state(MULTIPLE_DISPLAY_STATE_SINGLE);
1307   UpdateOutputs(1, true);
1308
1309   EXPECT_EQ(
1310       JoinActions(
1311           kGrab,
1312           GetFramebufferAction(big_mode_.size(), &outputs_[0], NULL).c_str(),
1313           GetCrtcAction(outputs_[0], modes[0], gfx::Point(0, 0)).c_str(),
1314           GetCrtcAction(outputs_[0], modes[3], gfx::Point(0, 0)).c_str(),
1315           GetCrtcAction(outputs_[0], modes[2], gfx::Point(0, 0)).c_str(),
1316           kUngrab,
1317           NULL),
1318       log_->GetActionsAndClear());
1319
1320   // This test should attempt to configure a mirror mode that will not succeed
1321   // and should end up in extended mode.
1322   native_display_delegate_->set_max_configurable_pixels(
1323       modes[3]->size().GetArea());
1324   state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
1325   UpdateOutputs(2, true);
1326
1327   EXPECT_EQ(
1328       JoinActions(
1329           kGrab,
1330           GetFramebufferAction(modes[0]->size(), &outputs_[0], &outputs_[1])
1331               .c_str(),
1332           GetCrtcAction(outputs_[0], modes[0], gfx::Point(0, 0)).c_str(),
1333           // First mode tried is expected to fail and it will
1334           // retry wil the 4th mode in the list.
1335           GetCrtcAction(outputs_[0], modes[3], gfx::Point(0, 0)).c_str(),
1336           // Then attempt to configure crtc1 with the first mode.
1337           GetCrtcAction(outputs_[1], modes[0], gfx::Point(0, 0)).c_str(),
1338           GetCrtcAction(outputs_[1], modes[3], gfx::Point(0, 0)).c_str(),
1339           // Since it was requested to go into mirror mode
1340           // and the configured modes were different, it
1341           // should now try and setup a valid configurable
1342           // extended mode.
1343           GetFramebufferAction(
1344               gfx::Size(modes[0]->size().width(),
1345                         modes[0]->size().height() + modes[0]->size().height() +
1346                             DisplayConfigurator::kVerticalGap),
1347               &outputs_[0],
1348               &outputs_[1]).c_str(),
1349           GetCrtcAction(outputs_[0], modes[0], gfx::Point(0, 0)).c_str(),
1350           GetCrtcAction(outputs_[0], modes[3], gfx::Point(0, 0)).c_str(),
1351           GetCrtcAction(outputs_[1],
1352                         modes[0],
1353                         gfx::Point(0,
1354                                    modes[0]->size().height() +
1355                                        DisplayConfigurator::kVerticalGap))
1356               .c_str(),
1357           GetCrtcAction(outputs_[1],
1358                         modes[3],
1359                         gfx::Point(0,
1360                                    modes[0]->size().height() +
1361                                        DisplayConfigurator::kVerticalGap))
1362               .c_str(),
1363           kUngrab,
1364           NULL),
1365       log_->GetActionsAndClear());
1366 }
1367
1368 }  // namespace ui