Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / ui / display / chromeos / output_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/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