blob: c8ed8aee5317278fcf592513c94797e74ef3a301 [file] [log] [blame]
[email protected]6d980bc2012-09-10 19:28:451// Copyright (c) 2012 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 "chromeos/display/output_configurator.h"
6
[email protected]06b20fe2013-11-13 19:18:387#include <cmath>
[email protected]acb217ed2013-04-09 21:52:368#include <cstdarg>
9#include <map>
[email protected]6d980bc2012-09-10 19:28:4510#include <string>
[email protected]acb217ed2013-04-09 21:52:3611#include <vector>
[email protected]6d980bc2012-09-10 19:28:4512
[email protected]acb217ed2013-04-09 21:52:3613#include "base/basictypes.h"
14#include "base/compiler_specific.h"
[email protected]f129d2502013-07-17 22:45:5015#include "base/message_loop/message_loop.h"
[email protected]afa339d72013-06-11 06:32:5116#include "base/strings/stringprintf.h"
[email protected]6d980bc2012-09-10 19:28:4517#include "testing/gtest/include/gtest/gtest.h"
18
19namespace chromeos {
20
[email protected]acb217ed2013-04-09 21:52:3621namespace {
22
23// Strings returned by TestDelegate::GetActionsAndClear() to describe various
24// actions that were performed.
25const char kInitXRandR[] = "init";
26const char kUpdateXRandR[] = "update";
27const char kGrab[] = "grab";
28const char kUngrab[] = "ungrab";
29const char kSync[] = "sync";
30const char kForceDPMS[] = "dpms";
31const char kProjectingOn[] = "projecting";
32const char kProjectingOff[] = "not_projecting";
33
34// String returned by TestDelegate::GetActionsAndClear() if no actions were
35// requested.
36const char kNoActions[] = "";
37
38// Returns a string describing a TestDelegate::SetBackgroundColor() call.
39std::string GetBackgroundAction(uint32 color_argb) {
40 return base::StringPrintf("background(0x%x)", color_argb);
41}
42
[email protected]6eebb90b2013-09-17 18:30:2743// Returns a string describing a TestDelegate::AddOutputMode() call.
44std::string GetAddOutputModeAction(RROutput output, RRMode mode) {
45 return base::StringPrintf("add_mode(output=%lu,mode=%lu)", output, mode);
46}
47
[email protected]acb217ed2013-04-09 21:52:3648// Returns a string describing a TestDelegate::ConfigureCrtc() call.
49std::string GetCrtcAction(RRCrtc crtc,
50 int x,
51 int y,
52 RRMode mode,
53 RROutput output) {
54 return base::StringPrintf("crtc(crtc=%lu,x=%d,y=%d,mode=%lu,output=%lu)",
55 crtc, x, y, mode, output);
56}
57
58// Returns a string describing a TestDelegate::CreateFramebuffer() call.
59std::string GetFramebufferAction(int width,
60 int height,
61 RRCrtc crtc1,
62 RRCrtc crtc2) {
63 return base::StringPrintf(
64 "framebuffer(width=%d,height=%d,crtc1=%lu,crtc2=%lu)",
65 width, height, crtc1, crtc2);
66}
67
68// Returns a string describing a TestDelegate::ConfigureCTM() call.
69std::string GetCTMAction(
70 int device_id,
71 const OutputConfigurator::CoordinateTransformation& ctm) {
72 return base::StringPrintf("ctm(id=%d,transform=(%f,%f,%f,%f))", device_id,
73 ctm.x_scale, ctm.x_offset, ctm.y_scale, ctm.y_offset);
74}
75
[email protected]a9318842013-10-02 07:21:1376// Returns a string describing a TestDelegate::SetHDCPState() call.
77std::string GetSetHDCPStateAction(RROutput id, HDCPState state) {
78 return base::StringPrintf("set_hdcp(id=%lu,state=%d)", id, state);
79}
80
[email protected]acb217ed2013-04-09 21:52:3681// Joins a sequence of strings describing actions (e.g. kScreenDim) such
82// that they can be compared against a string returned by
83// TestDelegate::GetActionsAndClear(). The list of actions must be
84// terminated by a NULL pointer.
85std::string JoinActions(const char* action, ...) {
86 std::string actions;
87
88 va_list arg_list;
89 va_start(arg_list, action);
90 while (action) {
91 if (!actions.empty())
92 actions += ",";
93 actions += action;
94 action = va_arg(arg_list, const char*);
95 }
96 va_end(arg_list);
97 return actions;
98}
99
100class TestDelegate : public OutputConfigurator::Delegate {
101 public:
102 static const int kXRandREventBase = 10;
103
[email protected]a9318842013-10-02 07:21:13104 TestDelegate()
[email protected]63da7fb2014-01-10 00:35:31105 : max_configurable_pixels_(0),
[email protected]a9318842013-10-02 07:21:13106 hdcp_state_(HDCP_STATE_UNDESIRED) {}
[email protected]acb217ed2013-04-09 21:52:36107 virtual ~TestDelegate() {}
108
[email protected]edc1c802013-08-14 03:55:04109 const std::vector<OutputConfigurator::OutputSnapshot>& outputs() const {
110 return outputs_;
111 }
[email protected]acb217ed2013-04-09 21:52:36112 void set_outputs(
113 const std::vector<OutputConfigurator::OutputSnapshot>& outputs) {
114 outputs_ = outputs;
115 }
116
[email protected]63da7fb2014-01-10 00:35:31117 void set_max_configurable_pixels(int pixels) {
118 max_configurable_pixels_ = pixels;
[email protected]edc1c802013-08-14 03:55:04119 }
120
[email protected]a9318842013-10-02 07:21:13121 void set_hdcp_state(HDCPState state) { hdcp_state_ = state; }
122
[email protected]acb217ed2013-04-09 21:52:36123 // Returns a comma-separated string describing the actions that were
124 // requested since the previous call to GetActionsAndClear() (i.e.
125 // results are non-repeatable).
126 std::string GetActionsAndClear() {
127 std::string actions = actions_;
128 actions_.clear();
129 return actions;
130 }
131
[email protected]06b20fe2013-11-13 19:18:38132 const OutputConfigurator::CoordinateTransformation& get_ctm(
133 int touch_device_id) {
134 return ctms_[touch_device_id];
135 }
136
[email protected]acb217ed2013-04-09 21:52:36137 // OutputConfigurator::Delegate overrides:
[email protected]acb217ed2013-04-09 21:52:36138 virtual void InitXRandRExtension(int* event_base) OVERRIDE {
139 AppendAction(kInitXRandR);
140 *event_base = kXRandREventBase;
141 }
142 virtual void UpdateXRandRConfiguration(
143 const base::NativeEvent& event) OVERRIDE { AppendAction(kUpdateXRandR); }
144 virtual void GrabServer() OVERRIDE { AppendAction(kGrab); }
145 virtual void UngrabServer() OVERRIDE { AppendAction(kUngrab); }
146 virtual void SyncWithServer() OVERRIDE { AppendAction(kSync); }
147 virtual void SetBackgroundColor(uint32 color_argb) OVERRIDE {
148 AppendAction(GetBackgroundAction(color_argb));
149 }
150 virtual void ForceDPMSOn() OVERRIDE { AppendAction(kForceDPMS); }
[email protected]6eebb90b2013-09-17 18:30:27151 virtual std::vector<OutputConfigurator::OutputSnapshot> GetOutputs()
152 OVERRIDE {
[email protected]acb217ed2013-04-09 21:52:36153 return outputs_;
154 }
[email protected]6eebb90b2013-09-17 18:30:27155 virtual void AddOutputMode(RROutput output, RRMode mode) OVERRIDE {
156 AppendAction(GetAddOutputModeAction(output, mode));
157 }
[email protected]dd807f42013-08-09 01:53:30158 virtual bool ConfigureCrtc(RRCrtc crtc,
159 RRMode mode,
160 RROutput output,
161 int x,
162 int y) OVERRIDE {
163 AppendAction(GetCrtcAction(crtc, x, y, mode, output));
[email protected]63da7fb2014-01-10 00:35:31164
165 if (max_configurable_pixels_ == 0)
166 return true;
167
168 OutputConfigurator::OutputSnapshot* snapshot = GetOutputFromId(output);
169 if (!snapshot)
170 return false;
171
172 const OutputConfigurator::ModeInfo* mode_info =
173 OutputConfigurator::GetModeInfo(*snapshot, mode);
174 if (!mode_info)
175 return false;
176
177 return mode_info->width * mode_info->height <= max_configurable_pixels_;
178
[email protected]acb217ed2013-04-09 21:52:36179 }
180 virtual void CreateFrameBuffer(
181 int width,
182 int height,
[email protected]dd807f42013-08-09 01:53:30183 const std::vector<OutputConfigurator::OutputSnapshot>& outputs) OVERRIDE {
[email protected]42091902013-05-02 02:24:12184 AppendAction(
185 GetFramebufferAction(width,
186 height,
[email protected]dd807f42013-08-09 01:53:30187 outputs.size() >= 1 ? outputs[0].crtc : 0,
188 outputs.size() >= 2 ? outputs[1].crtc : 0));
[email protected]acb217ed2013-04-09 21:52:36189 }
190 virtual void ConfigureCTM(
191 int touch_device_id,
192 const OutputConfigurator::CoordinateTransformation& ctm) OVERRIDE {
193 AppendAction(GetCTMAction(touch_device_id, ctm));
[email protected]06b20fe2013-11-13 19:18:38194 ctms_[touch_device_id] = ctm;
[email protected]acb217ed2013-04-09 21:52:36195 }
196 virtual void SendProjectingStateToPowerManager(bool projecting) OVERRIDE {
197 AppendAction(projecting ? kProjectingOn : kProjectingOff);
198 }
199
[email protected]a1ab6d82013-09-28 13:49:54200 virtual bool GetHDCPState(RROutput id, HDCPState* state) OVERRIDE {
[email protected]a9318842013-10-02 07:21:13201 *state = hdcp_state_;
[email protected]a1ab6d82013-09-28 13:49:54202 return true;
203 }
204
205 virtual bool SetHDCPState(RROutput id, HDCPState state) OVERRIDE {
[email protected]a9318842013-10-02 07:21:13206 AppendAction(GetSetHDCPStateAction(id, state));
[email protected]a1ab6d82013-09-28 13:49:54207 return true;
208 }
209
[email protected]acb217ed2013-04-09 21:52:36210 private:
211 struct ModeDetails {
212 ModeDetails() : width(0), height(0), interlaced(false) {}
213 ModeDetails(int width, int height, bool interlaced)
214 : width(width),
215 height(height),
216 interlaced(interlaced) {}
217
218 int width;
219 int height;
220 bool interlaced;
221 };
222
223 void AppendAction(const std::string& action) {
224 if (!actions_.empty())
225 actions_ += ",";
226 actions_ += action;
227 }
228
[email protected]63da7fb2014-01-10 00:35:31229 OutputConfigurator::OutputSnapshot* GetOutputFromId(RROutput output_id) {
230 for (unsigned int i = 0; i < outputs_.size(); i++) {
231 if (outputs_[i].output == output_id)
232 return &outputs_[i];
233 }
234 return NULL;
235 }
236
[email protected]acb217ed2013-04-09 21:52:36237 std::map<RRMode, ModeDetails> modes_;
238
[email protected]06b20fe2013-11-13 19:18:38239 // Most-recently-configured transformation matrices, keyed by touch device ID.
240 std::map<int, OutputConfigurator::CoordinateTransformation> ctms_;
241
[email protected]acb217ed2013-04-09 21:52:36242 // Outputs to be returned by GetOutputs().
243 std::vector<OutputConfigurator::OutputSnapshot> outputs_;
244
245 std::string actions_;
246
[email protected]63da7fb2014-01-10 00:35:31247 // |max_configurable_pixels_| represents the maximum number of pixels that
248 // ConfigureCrtc will support. Tests can use this to force ConfigureCrtc
249 // to fail if attempting to set a resolution that is higher than what
250 // a device might support under a given circumstance.
251 // A value of 0 means that no limit is enforced and ConfigureCrtc will
252 // return success regardless of the resolution.
253 int max_configurable_pixels_;
[email protected]edc1c802013-08-14 03:55:04254
[email protected]a9318842013-10-02 07:21:13255 // Result value of GetHDCPState().
256 HDCPState hdcp_state_;
257
[email protected]acb217ed2013-04-09 21:52:36258 DISALLOW_COPY_AND_ASSIGN(TestDelegate);
259};
260
[email protected]0b1b283b2013-08-17 13:32:18261class TestObserver : public OutputConfigurator::Observer {
262 public:
263 explicit TestObserver(OutputConfigurator* configurator)
264 : configurator_(configurator) {
265 Reset();
266 configurator_->AddObserver(this);
267 }
268 virtual ~TestObserver() {
269 configurator_->RemoveObserver(this);
270 }
271
272 int num_changes() const { return num_changes_; }
273 int num_failures() const { return num_failures_; }
[email protected]6eebb90b2013-09-17 18:30:27274 const std::vector<OutputConfigurator::OutputSnapshot>& latest_outputs()
275 const {
[email protected]0b1b283b2013-08-17 13:32:18276 return latest_outputs_;
277 }
278 OutputState latest_failed_state() const { return latest_failed_state_; }
279
280 void Reset() {
281 num_changes_ = 0;
282 num_failures_ = 0;
283 latest_outputs_.clear();
284 latest_failed_state_ = STATE_INVALID;
285 }
286
287 // OutputConfigurator::Observer overrides:
288 virtual void OnDisplayModeChanged(
289 const std::vector<OutputConfigurator::OutputSnapshot>& outputs) OVERRIDE {
290 num_changes_++;
291 latest_outputs_ = outputs;
292 }
293
294 virtual void OnDisplayModeChangeFailed(OutputState failed_new_state)
295 OVERRIDE {
296 num_failures_++;
297 latest_failed_state_ = failed_new_state;
298 }
299
300 private:
301 OutputConfigurator* configurator_; // Not owned.
302
303 // Number of times that OnDisplayMode*() has been called.
304 int num_changes_;
305 int num_failures_;
306
307 // Parameters most recently passed to OnDisplayMode*().
308 std::vector<OutputConfigurator::OutputSnapshot> latest_outputs_;
309 OutputState latest_failed_state_;
310
311 DISALLOW_COPY_AND_ASSIGN(TestObserver);
312};
313
[email protected]acb217ed2013-04-09 21:52:36314class TestStateController : public OutputConfigurator::StateController {
315 public:
316 TestStateController() : state_(STATE_DUAL_EXTENDED) {}
[email protected]42091902013-05-02 02:24:12317 virtual ~TestStateController() {}
[email protected]acb217ed2013-04-09 21:52:36318
319 void set_state(OutputState state) { state_ = state; }
320
321 // OutputConfigurator::StateController overrides:
[email protected]2c8a0aa72013-05-16 06:24:48322 virtual OutputState GetStateForDisplayIds(
323 const std::vector<int64>& outputs) const OVERRIDE { return state_; }
[email protected]a5792d32013-08-01 11:18:21324 virtual bool GetResolutionForDisplayId(
325 int64 display_id,
326 int *width,
327 int *height) const OVERRIDE {
328 return false;
329 }
[email protected]acb217ed2013-04-09 21:52:36330
331 private:
332 OutputState state_;
333
334 DISALLOW_COPY_AND_ASSIGN(TestStateController);
335};
336
[email protected]c1f30dc2013-05-22 17:27:45337class TestMirroringController
338 : public OutputConfigurator::SoftwareMirroringController {
339 public:
340 TestMirroringController() : software_mirroring_enabled_(false) {}
341 virtual ~TestMirroringController() {}
342
343 virtual void SetSoftwareMirroring(bool enabled) OVERRIDE {
344 software_mirroring_enabled_ = enabled;
345 }
346
347 bool software_mirroring_enabled() const {
348 return software_mirroring_enabled_;
349 }
350
351 private:
352 bool software_mirroring_enabled_;
353
354 DISALLOW_COPY_AND_ASSIGN(TestMirroringController);
355};
356
[email protected]acb217ed2013-04-09 21:52:36357class OutputConfiguratorTest : public testing::Test {
358 public:
[email protected]6eebb90b2013-09-17 18:30:27359 // Predefined modes that can be used by outputs.
360 static const RRMode kSmallModeId;
361 static const int kSmallModeWidth;
362 static const int kSmallModeHeight;
363
364 static const RRMode kBigModeId;
365 static const int kBigModeWidth;
366 static const int kBigModeHeight;
367
[email protected]acb217ed2013-04-09 21:52:36368 OutputConfiguratorTest()
[email protected]0b1b283b2013-08-17 13:32:18369 : observer_(&configurator_),
370 test_api_(&configurator_, TestDelegate::kXRandREventBase) {}
[email protected]acb217ed2013-04-09 21:52:36371 virtual ~OutputConfiguratorTest() {}
372
373 virtual void SetUp() OVERRIDE {
374 delegate_ = new TestDelegate();
375 configurator_.SetDelegateForTesting(
376 scoped_ptr<OutputConfigurator::Delegate>(delegate_));
377 configurator_.set_state_controller(&state_controller_);
[email protected]c1f30dc2013-05-22 17:27:45378 configurator_.set_mirroring_controller(&mirroring_controller_);
[email protected]acb217ed2013-04-09 21:52:36379
[email protected]5d99ee62013-08-16 19:56:47380 OutputConfigurator::ModeInfo small_mode_info;
381 small_mode_info.width = kSmallModeWidth;
382 small_mode_info.height = kSmallModeHeight;
383
384 OutputConfigurator::ModeInfo big_mode_info;
385 big_mode_info.width = kBigModeWidth;
386 big_mode_info.height = kBigModeHeight;
387
[email protected]acb217ed2013-04-09 21:52:36388 OutputConfigurator::OutputSnapshot* o = &outputs_[0];
389 o->output = 1;
390 o->crtc = 10;
391 o->current_mode = kSmallModeId;
392 o->native_mode = kSmallModeId;
[email protected]acb217ed2013-04-09 21:52:36393 o->is_internal = true;
[email protected]a9318842013-10-02 07:21:13394 o->type = OUTPUT_TYPE_INTERNAL;
[email protected]acb217ed2013-04-09 21:52:36395 o->is_aspect_preserving_scaling = true;
[email protected]5d99ee62013-08-16 19:56:47396 o->mode_infos[kSmallModeId] = small_mode_info;
[email protected]2c8a0aa72013-05-16 06:24:48397 o->has_display_id = true;
[email protected]67e6a682013-10-31 10:00:41398 o->display_id = 123;
[email protected]6eebb90b2013-09-17 18:30:27399 o->index = 0;
[email protected]acb217ed2013-04-09 21:52:36400
401 o = &outputs_[1];
402 o->output = 2;
403 o->crtc = 11;
404 o->current_mode = kBigModeId;
405 o->native_mode = kBigModeId;
[email protected]acb217ed2013-04-09 21:52:36406 o->is_internal = false;
[email protected]a9318842013-10-02 07:21:13407 o->type = OUTPUT_TYPE_HDMI;
[email protected]acb217ed2013-04-09 21:52:36408 o->is_aspect_preserving_scaling = true;
[email protected]5d99ee62013-08-16 19:56:47409 o->mode_infos[kSmallModeId] = small_mode_info;
410 o->mode_infos[kBigModeId] = big_mode_info;
[email protected]2c8a0aa72013-05-16 06:24:48411 o->has_display_id = true;
[email protected]67e6a682013-10-31 10:00:41412 o->display_id = 456;
[email protected]6eebb90b2013-09-17 18:30:27413 o->index = 1;
[email protected]acb217ed2013-04-09 21:52:36414
[email protected]edc1c802013-08-14 03:55:04415 UpdateOutputs(2, false);
[email protected]acb217ed2013-04-09 21:52:36416 }
417
418 protected:
[email protected]acb217ed2013-04-09 21:52:36419 // Configures |delegate_| to return the first |num_outputs| entries from
[email protected]edc1c802013-08-14 03:55:04420 // |outputs_|. If |send_events| is true, also sends screen-change and
421 // output-change events to |configurator_| and triggers the configure
422 // timeout if one was scheduled.
423 void UpdateOutputs(size_t num_outputs, bool send_events) {
[email protected]acb217ed2013-04-09 21:52:36424 ASSERT_LE(num_outputs, arraysize(outputs_));
425 std::vector<OutputConfigurator::OutputSnapshot> outputs;
426 for (size_t i = 0; i < num_outputs; ++i)
427 outputs.push_back(outputs_[i]);
428 delegate_->set_outputs(outputs);
[email protected]edc1c802013-08-14 03:55:04429
430 if (send_events) {
431 test_api_.SendScreenChangeEvent();
432 for (size_t i = 0; i < arraysize(outputs_); ++i) {
433 const OutputConfigurator::OutputSnapshot output = outputs_[i];
434 bool connected = i < num_outputs;
435 test_api_.SendOutputChangeEvent(
436 output.output, output.crtc, output.current_mode, connected);
437 }
438 test_api_.TriggerConfigureTimeout();
439 }
[email protected]acb217ed2013-04-09 21:52:36440 }
441
442 // Initializes |configurator_| with a single internal display.
[email protected]edc1c802013-08-14 03:55:04443 void InitWithSingleOutput() {
444 UpdateOutputs(1, false);
[email protected]acb217ed2013-04-09 21:52:36445 EXPECT_EQ(kNoActions, delegate_->GetActionsAndClear());
[email protected]d30dac82013-07-31 16:17:30446 configurator_.Init(false);
447 EXPECT_EQ(kNoActions, delegate_->GetActionsAndClear());
448 configurator_.Start(0);
[email protected]acb217ed2013-04-09 21:52:36449 EXPECT_EQ(JoinActions(kGrab, kInitXRandR,
450 GetFramebufferAction(kSmallModeWidth,
451 kSmallModeHeight, outputs_[0].crtc, 0).c_str(),
452 GetCrtcAction(outputs_[0].crtc, 0, 0, kSmallModeId,
453 outputs_[0].output).c_str(),
454 kForceDPMS, kUngrab, kProjectingOff, NULL),
455 delegate_->GetActionsAndClear());
456 }
457
458 base::MessageLoop message_loop_;
459 TestStateController state_controller_;
[email protected]c1f30dc2013-05-22 17:27:45460 TestMirroringController mirroring_controller_;
[email protected]acb217ed2013-04-09 21:52:36461 OutputConfigurator configurator_;
[email protected]0b1b283b2013-08-17 13:32:18462 TestObserver observer_;
[email protected]acb217ed2013-04-09 21:52:36463 TestDelegate* delegate_; // not owned
464 OutputConfigurator::TestApi test_api_;
465
466 OutputConfigurator::OutputSnapshot outputs_[2];
467
468 private:
469 DISALLOW_COPY_AND_ASSIGN(OutputConfiguratorTest);
470};
471
[email protected]6eebb90b2013-09-17 18:30:27472const RRMode OutputConfiguratorTest::kSmallModeId = 20;
473const int OutputConfiguratorTest::kSmallModeWidth = 1366;
474const int OutputConfiguratorTest::kSmallModeHeight = 768;
475
476const RRMode OutputConfiguratorTest::kBigModeId = 21;
477const int OutputConfiguratorTest::kBigModeWidth = 2560;
478const int OutputConfiguratorTest::kBigModeHeight = 1600;
479
[email protected]acb217ed2013-04-09 21:52:36480} // namespace
[email protected]6d980bc2012-09-10 19:28:45481
[email protected]6eebb90b2013-09-17 18:30:27482TEST_F(OutputConfiguratorTest, FindOutputModeMatchingSize) {
483 OutputConfigurator::OutputSnapshot output;
484
485 // Fields are width, height, interlaced, refresh rate.
486 output.mode_infos[11] = OutputConfigurator::ModeInfo(1920, 1200, false, 60.0);
487 // Different rates.
488 output.mode_infos[12] = OutputConfigurator::ModeInfo(1920, 1080, false, 30.0);
489 output.mode_infos[13] = OutputConfigurator::ModeInfo(1920, 1080, false, 50.0);
490 output.mode_infos[14] = OutputConfigurator::ModeInfo(1920, 1080, false, 40.0);
491 output.mode_infos[15] = OutputConfigurator::ModeInfo(1920, 1080, false, 0.0);
492 // Interlaced vs non-interlaced.
493 output.mode_infos[16] = OutputConfigurator::ModeInfo(1280, 720, true, 60.0);
494 output.mode_infos[17] = OutputConfigurator::ModeInfo(1280, 720, false, 40.0);
495 // Interlaced only.
496 output.mode_infos[18] = OutputConfigurator::ModeInfo(1024, 768, true, 0.0);
497 output.mode_infos[19] = OutputConfigurator::ModeInfo(1024, 768, true, 40.0);
498 output.mode_infos[20] = OutputConfigurator::ModeInfo(1024, 768, true, 60.0);
499 // Mixed.
500 output.mode_infos[21] = OutputConfigurator::ModeInfo(1024, 600, true, 60.0);
501 output.mode_infos[22] = OutputConfigurator::ModeInfo(1024, 600, false, 40.0);
502 output.mode_infos[23] = OutputConfigurator::ModeInfo(1024, 600, false, 50.0);
503 // Just one interlaced mode.
504 output.mode_infos[24] = OutputConfigurator::ModeInfo(640, 480, true, 60.0);
505 // Refresh rate not available.
506 output.mode_infos[25] = OutputConfigurator::ModeInfo(320, 200, false, 0.0);
507
508 EXPECT_EQ(11u, OutputConfigurator::FindOutputModeMatchingSize(output,
509 1920, 1200));
510
511 // Should pick highest refresh rate.
512 EXPECT_EQ(13u, OutputConfigurator::FindOutputModeMatchingSize(output,
513 1920, 1080));
514
515 // Should pick non-interlaced mode.
516 EXPECT_EQ(17u, OutputConfigurator::FindOutputModeMatchingSize(output,
517 1280, 720));
518
519 // Interlaced only. Should pick one with the highest refresh rate in
520 // interlaced mode.
521 EXPECT_EQ(20u, OutputConfigurator::FindOutputModeMatchingSize(output,
522 1024, 768));
523
524 // Mixed: Should pick one with the highest refresh rate in
525 // interlaced mode.
526 EXPECT_EQ(23u, OutputConfigurator::FindOutputModeMatchingSize(output,
527 1024, 600));
528
529 // Just one interlaced mode.
530 EXPECT_EQ(24u, OutputConfigurator::FindOutputModeMatchingSize(output,
531 640, 480));
532
533 // Refresh rate not available.
534 EXPECT_EQ(25u, OutputConfigurator::FindOutputModeMatchingSize(output,
535 320, 200));
536
537 // No mode found.
538 EXPECT_EQ(0u, OutputConfigurator::FindOutputModeMatchingSize(output,
539 1440, 900));
540}
541
[email protected]acb217ed2013-04-09 21:52:36542TEST_F(OutputConfiguratorTest, ConnectSecondOutput) {
543 InitWithSingleOutput();
544
545 // Connect a second output and check that the configurator enters
546 // extended mode.
[email protected]0b1b283b2013-08-17 13:32:18547 observer_.Reset();
[email protected]edc1c802013-08-14 03:55:04548 state_controller_.set_state(STATE_DUAL_EXTENDED);
549 UpdateOutputs(2, true);
[email protected]acb217ed2013-04-09 21:52:36550 const int kDualHeight =
551 kSmallModeHeight + OutputConfigurator::kVerticalGap + kBigModeHeight;
[email protected]acb217ed2013-04-09 21:52:36552 EXPECT_EQ(JoinActions(kUpdateXRandR, kGrab,
553 GetFramebufferAction(kBigModeWidth, kDualHeight,
554 outputs_[0].crtc, outputs_[1].crtc).c_str(),
555 GetCrtcAction(outputs_[0].crtc, 0, 0, kSmallModeId,
556 outputs_[0].output).c_str(),
557 GetCrtcAction(outputs_[1].crtc, 0,
558 kSmallModeHeight + OutputConfigurator::kVerticalGap,
559 kBigModeId, outputs_[1].output).c_str(),
560 kUngrab, kProjectingOn, NULL),
561 delegate_->GetActionsAndClear());
[email protected]c1f30dc2013-05-22 17:27:45562 EXPECT_FALSE(mirroring_controller_.software_mirroring_enabled());
[email protected]0b1b283b2013-08-17 13:32:18563 EXPECT_EQ(1, observer_.num_changes());
[email protected]acb217ed2013-04-09 21:52:36564
[email protected]0b1b283b2013-08-17 13:32:18565 observer_.Reset();
[email protected]acb217ed2013-04-09 21:52:36566 EXPECT_TRUE(configurator_.SetDisplayMode(STATE_DUAL_MIRROR));
567 EXPECT_EQ(JoinActions(kGrab,
568 GetFramebufferAction(kSmallModeWidth, kSmallModeHeight,
569 outputs_[0].crtc, outputs_[1].crtc).c_str(),
570 GetCrtcAction(outputs_[0].crtc, 0, 0, kSmallModeId,
571 outputs_[0].output).c_str(),
572 GetCrtcAction(outputs_[1].crtc, 0, 0, kSmallModeId,
573 outputs_[1].output).c_str(),
574 kUngrab, NULL),
575 delegate_->GetActionsAndClear());
[email protected]c1f30dc2013-05-22 17:27:45576 EXPECT_FALSE(mirroring_controller_.software_mirroring_enabled());
[email protected]0b1b283b2013-08-17 13:32:18577 EXPECT_EQ(1, observer_.num_changes());
[email protected]acb217ed2013-04-09 21:52:36578
579 // Disconnect the second output.
[email protected]0b1b283b2013-08-17 13:32:18580 observer_.Reset();
[email protected]edc1c802013-08-14 03:55:04581 UpdateOutputs(1, true);
[email protected]acb217ed2013-04-09 21:52:36582 EXPECT_EQ(JoinActions(kUpdateXRandR, kGrab,
583 GetFramebufferAction(kSmallModeWidth, kSmallModeHeight,
584 outputs_[0].crtc, 0).c_str(),
585 GetCrtcAction(outputs_[0].crtc, 0, 0, kSmallModeId,
586 outputs_[0].output).c_str(),
587 kUngrab, kProjectingOff, NULL),
588 delegate_->GetActionsAndClear());
[email protected]c1f30dc2013-05-22 17:27:45589 EXPECT_FALSE(mirroring_controller_.software_mirroring_enabled());
[email protected]0b1b283b2013-08-17 13:32:18590 EXPECT_EQ(1, observer_.num_changes());
[email protected]c1f30dc2013-05-22 17:27:45591
[email protected]6eebb90b2013-09-17 18:30:27592 // Get rid of shared modes to force software mirroring.
593 outputs_[1].mode_infos.erase(kSmallModeId);
[email protected]c1f30dc2013-05-22 17:27:45594 state_controller_.set_state(STATE_DUAL_EXTENDED);
[email protected]edc1c802013-08-14 03:55:04595 UpdateOutputs(2, true);
[email protected]c1f30dc2013-05-22 17:27:45596 EXPECT_EQ(JoinActions(kUpdateXRandR, kGrab,
597 GetFramebufferAction(kBigModeWidth, kDualHeight,
598 outputs_[0].crtc, outputs_[1].crtc).c_str(),
599 GetCrtcAction(outputs_[0].crtc, 0, 0, kSmallModeId,
600 outputs_[0].output).c_str(),
601 GetCrtcAction(outputs_[1].crtc, 0,
602 kSmallModeHeight + OutputConfigurator::kVerticalGap,
603 kBigModeId, outputs_[1].output).c_str(),
604 kUngrab, kProjectingOn, NULL),
605 delegate_->GetActionsAndClear());
606 EXPECT_FALSE(mirroring_controller_.software_mirroring_enabled());
607
[email protected]0b1b283b2013-08-17 13:32:18608 observer_.Reset();
[email protected]c1f30dc2013-05-22 17:27:45609 EXPECT_TRUE(configurator_.SetDisplayMode(STATE_DUAL_MIRROR));
[email protected]0b1b283b2013-08-17 13:32:18610 EXPECT_EQ(JoinActions(kGrab, kUngrab, NULL), delegate_->GetActionsAndClear());
[email protected]c1f30dc2013-05-22 17:27:45611 EXPECT_EQ(STATE_DUAL_EXTENDED, configurator_.output_state());
612 EXPECT_TRUE(mirroring_controller_.software_mirroring_enabled());
[email protected]0b1b283b2013-08-17 13:32:18613 EXPECT_EQ(1, observer_.num_changes());
[email protected]c1f30dc2013-05-22 17:27:45614
[email protected]0b1b283b2013-08-17 13:32:18615 // Setting STATE_DUAL_MIRROR should try to reconfigure.
616 observer_.Reset();
[email protected]57bed4d2013-06-08 20:54:18617 EXPECT_TRUE(configurator_.SetDisplayMode(STATE_DUAL_EXTENDED));
618 EXPECT_EQ(JoinActions(NULL), delegate_->GetActionsAndClear());
619 EXPECT_FALSE(mirroring_controller_.software_mirroring_enabled());
[email protected]0b1b283b2013-08-17 13:32:18620 EXPECT_EQ(1, observer_.num_changes());
[email protected]57bed4d2013-06-08 20:54:18621
622 // Set back to software mirror mode.
[email protected]0b1b283b2013-08-17 13:32:18623 observer_.Reset();
[email protected]57bed4d2013-06-08 20:54:18624 EXPECT_TRUE(configurator_.SetDisplayMode(STATE_DUAL_MIRROR));
625 EXPECT_EQ(JoinActions(kGrab, kUngrab, NULL),
626 delegate_->GetActionsAndClear());
627 EXPECT_EQ(STATE_DUAL_EXTENDED, configurator_.output_state());
628 EXPECT_TRUE(mirroring_controller_.software_mirroring_enabled());
[email protected]0b1b283b2013-08-17 13:32:18629 EXPECT_EQ(1, observer_.num_changes());
[email protected]57bed4d2013-06-08 20:54:18630
[email protected]c1f30dc2013-05-22 17:27:45631 // Disconnect the second output.
[email protected]0b1b283b2013-08-17 13:32:18632 observer_.Reset();
[email protected]edc1c802013-08-14 03:55:04633 UpdateOutputs(1, true);
[email protected]c1f30dc2013-05-22 17:27:45634 EXPECT_EQ(JoinActions(kUpdateXRandR, kGrab,
635 GetFramebufferAction(kSmallModeWidth, kSmallModeHeight,
636 outputs_[0].crtc, 0).c_str(),
637 GetCrtcAction(outputs_[0].crtc, 0, 0, kSmallModeId,
638 outputs_[0].output).c_str(),
639 kUngrab, kProjectingOff, NULL),
640 delegate_->GetActionsAndClear());
641 EXPECT_FALSE(mirroring_controller_.software_mirroring_enabled());
[email protected]0b1b283b2013-08-17 13:32:18642 EXPECT_EQ(1, observer_.num_changes());
[email protected]acb217ed2013-04-09 21:52:36643}
644
645TEST_F(OutputConfiguratorTest, SetDisplayPower) {
646 InitWithSingleOutput();
647
[email protected]acb217ed2013-04-09 21:52:36648 state_controller_.set_state(STATE_DUAL_MIRROR);
[email protected]0b1b283b2013-08-17 13:32:18649 observer_.Reset();
[email protected]edc1c802013-08-14 03:55:04650 UpdateOutputs(2, true);
[email protected]acb217ed2013-04-09 21:52:36651 EXPECT_EQ(JoinActions(kUpdateXRandR, kGrab,
652 GetFramebufferAction(kSmallModeWidth, kSmallModeHeight,
653 outputs_[0].crtc, outputs_[1].crtc).c_str(),
654 GetCrtcAction(outputs_[0].crtc, 0, 0, kSmallModeId,
655 outputs_[0].output).c_str(),
656 GetCrtcAction(outputs_[1].crtc, 0, 0, kSmallModeId,
657 outputs_[1].output).c_str(),
658 kUngrab, kProjectingOn, NULL),
659 delegate_->GetActionsAndClear());
[email protected]c1f30dc2013-05-22 17:27:45660 EXPECT_FALSE(mirroring_controller_.software_mirroring_enabled());
[email protected]0b1b283b2013-08-17 13:32:18661 EXPECT_EQ(1, observer_.num_changes());
[email protected]acb217ed2013-04-09 21:52:36662
663 // Turning off the internal display should switch the external display to
664 // its native mode.
[email protected]0b1b283b2013-08-17 13:32:18665 observer_.Reset();
[email protected]acb217ed2013-04-09 21:52:36666 configurator_.SetDisplayPower(DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON,
667 OutputConfigurator::kSetDisplayPowerNoFlags);
668 EXPECT_EQ(JoinActions(kGrab,
669 GetFramebufferAction(kBigModeWidth, kBigModeHeight,
670 outputs_[0].crtc, outputs_[1].crtc).c_str(),
671 GetCrtcAction(outputs_[0].crtc, 0, 0, 0,
672 outputs_[0].output).c_str(),
673 GetCrtcAction(outputs_[1].crtc, 0, 0, kBigModeId,
674 outputs_[1].output).c_str(),
675 kForceDPMS, kUngrab, NULL),
676 delegate_->GetActionsAndClear());
[email protected]c1f30dc2013-05-22 17:27:45677 EXPECT_EQ(STATE_SINGLE, configurator_.output_state());
[email protected]0b1b283b2013-08-17 13:32:18678 EXPECT_EQ(1, observer_.num_changes());
[email protected]acb217ed2013-04-09 21:52:36679
680 // When all displays are turned off, the framebuffer should switch back
681 // to the mirrored size.
[email protected]0b1b283b2013-08-17 13:32:18682 observer_.Reset();
[email protected]acb217ed2013-04-09 21:52:36683 configurator_.SetDisplayPower(DISPLAY_POWER_ALL_OFF,
684 OutputConfigurator::kSetDisplayPowerNoFlags);
685 EXPECT_EQ(JoinActions(kGrab,
686 GetFramebufferAction(kSmallModeWidth, kSmallModeHeight,
687 outputs_[0].crtc, outputs_[1].crtc).c_str(),
688 GetCrtcAction(outputs_[0].crtc, 0, 0, 0,
689 outputs_[0].output).c_str(),
690 GetCrtcAction(outputs_[1].crtc, 0, 0, 0,
691 outputs_[1].output).c_str(),
692 kUngrab, NULL),
693 delegate_->GetActionsAndClear());
[email protected]c1f30dc2013-05-22 17:27:45694 EXPECT_EQ(STATE_DUAL_MIRROR, configurator_.output_state());
695 EXPECT_FALSE(mirroring_controller_.software_mirroring_enabled());
[email protected]0b1b283b2013-08-17 13:32:18696 EXPECT_EQ(1, observer_.num_changes());
[email protected]acb217ed2013-04-09 21:52:36697
698 // Turn all displays on and check that mirroring is still used.
[email protected]0b1b283b2013-08-17 13:32:18699 observer_.Reset();
[email protected]acb217ed2013-04-09 21:52:36700 configurator_.SetDisplayPower(DISPLAY_POWER_ALL_ON,
701 OutputConfigurator::kSetDisplayPowerNoFlags);
702 EXPECT_EQ(JoinActions(kGrab,
703 GetFramebufferAction(kSmallModeWidth, kSmallModeHeight,
704 outputs_[0].crtc, outputs_[1].crtc).c_str(),
705 GetCrtcAction(outputs_[0].crtc, 0, 0, kSmallModeId,
706 outputs_[0].output).c_str(),
707 GetCrtcAction(outputs_[1].crtc, 0, 0, kSmallModeId,
708 outputs_[1].output).c_str(),
709 kForceDPMS, kUngrab, NULL),
710 delegate_->GetActionsAndClear());
[email protected]c1f30dc2013-05-22 17:27:45711 EXPECT_EQ(STATE_DUAL_MIRROR, configurator_.output_state());
712 EXPECT_FALSE(mirroring_controller_.software_mirroring_enabled());
[email protected]0b1b283b2013-08-17 13:32:18713 EXPECT_EQ(1, observer_.num_changes());
[email protected]c1f30dc2013-05-22 17:27:45714
[email protected]6eebb90b2013-09-17 18:30:27715 // Get rid of shared modes to force software mirroring.
716 outputs_[1].mode_infos.erase(kSmallModeId);
[email protected]edc1c802013-08-14 03:55:04717 state_controller_.set_state(STATE_DUAL_MIRROR);
[email protected]0b1b283b2013-08-17 13:32:18718 observer_.Reset();
[email protected]edc1c802013-08-14 03:55:04719 UpdateOutputs(2, true);
[email protected]c1f30dc2013-05-22 17:27:45720 const int kDualHeight =
721 kSmallModeHeight + OutputConfigurator::kVerticalGap + kBigModeHeight;
[email protected]c1f30dc2013-05-22 17:27:45722 EXPECT_EQ(JoinActions(kUpdateXRandR, kGrab,
723 GetFramebufferAction(kBigModeWidth, kDualHeight,
724 outputs_[0].crtc, outputs_[1].crtc).c_str(),
725 GetCrtcAction(outputs_[0].crtc, 0, 0, kSmallModeId,
726 outputs_[0].output).c_str(),
727 GetCrtcAction(outputs_[1].crtc, 0,
728 kSmallModeHeight + OutputConfigurator::kVerticalGap,
729 kBigModeId, outputs_[1].output).c_str(),
730 kUngrab, kProjectingOn, NULL),
731 delegate_->GetActionsAndClear());
732 EXPECT_EQ(STATE_DUAL_EXTENDED, configurator_.output_state());
733 EXPECT_TRUE(mirroring_controller_.software_mirroring_enabled());
[email protected]0b1b283b2013-08-17 13:32:18734 EXPECT_EQ(1, observer_.num_changes());
[email protected]c1f30dc2013-05-22 17:27:45735
736 // Turning off the internal display should switch the external display to
737 // its native mode.
[email protected]0b1b283b2013-08-17 13:32:18738 observer_.Reset();
[email protected]c1f30dc2013-05-22 17:27:45739 configurator_.SetDisplayPower(DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON,
740 OutputConfigurator::kSetDisplayPowerNoFlags);
741 EXPECT_EQ(JoinActions(kGrab,
742 GetFramebufferAction(kBigModeWidth, kBigModeHeight,
743 outputs_[0].crtc, outputs_[1].crtc).c_str(),
744 GetCrtcAction(outputs_[0].crtc, 0, 0, 0,
745 outputs_[0].output).c_str(),
746 GetCrtcAction(outputs_[1].crtc, 0, 0, kBigModeId,
747 outputs_[1].output).c_str(),
748 kForceDPMS, kUngrab, NULL),
749 delegate_->GetActionsAndClear());
750 EXPECT_EQ(STATE_SINGLE, configurator_.output_state());
751 EXPECT_FALSE(mirroring_controller_.software_mirroring_enabled());
[email protected]0b1b283b2013-08-17 13:32:18752 EXPECT_EQ(1, observer_.num_changes());
[email protected]c1f30dc2013-05-22 17:27:45753
754 // When all displays are turned off, the framebuffer should switch back
755 // to the extended + software mirroring.
[email protected]0b1b283b2013-08-17 13:32:18756 observer_.Reset();
[email protected]c1f30dc2013-05-22 17:27:45757 configurator_.SetDisplayPower(DISPLAY_POWER_ALL_OFF,
758 OutputConfigurator::kSetDisplayPowerNoFlags);
759 EXPECT_EQ(JoinActions(kGrab,
760 GetFramebufferAction(kBigModeWidth, kDualHeight,
761 outputs_[0].crtc, outputs_[1].crtc).c_str(),
762 GetCrtcAction(outputs_[0].crtc, 0, 0, 0,
763 outputs_[0].output).c_str(),
764 GetCrtcAction(outputs_[1].crtc, 0,
765 kSmallModeHeight + OutputConfigurator::kVerticalGap,
766 0, outputs_[1].output).c_str(),
767 kUngrab, NULL),
768 delegate_->GetActionsAndClear());
769 EXPECT_EQ(STATE_DUAL_EXTENDED, configurator_.output_state());
770 EXPECT_TRUE(mirroring_controller_.software_mirroring_enabled());
[email protected]0b1b283b2013-08-17 13:32:18771 EXPECT_EQ(1, observer_.num_changes());
[email protected]c1f30dc2013-05-22 17:27:45772
773 // Turn all displays on and check that mirroring is still used.
[email protected]0b1b283b2013-08-17 13:32:18774 observer_.Reset();
[email protected]c1f30dc2013-05-22 17:27:45775 configurator_.SetDisplayPower(DISPLAY_POWER_ALL_ON,
776 OutputConfigurator::kSetDisplayPowerNoFlags);
777 EXPECT_EQ(JoinActions(kGrab,
778 GetFramebufferAction(kBigModeWidth, kDualHeight,
779 outputs_[0].crtc, outputs_[1].crtc).c_str(),
780 GetCrtcAction(outputs_[0].crtc, 0, 0, kSmallModeId,
781 outputs_[0].output).c_str(),
782 GetCrtcAction(outputs_[1].crtc, 0,
783 kSmallModeHeight + OutputConfigurator::kVerticalGap,
784 kBigModeId, outputs_[1].output).c_str(),
785 kForceDPMS, kUngrab, NULL),
786 delegate_->GetActionsAndClear());
787 EXPECT_EQ(STATE_DUAL_EXTENDED, configurator_.output_state());
788 EXPECT_TRUE(mirroring_controller_.software_mirroring_enabled());
[email protected]0b1b283b2013-08-17 13:32:18789 EXPECT_EQ(1, observer_.num_changes());
[email protected]acb217ed2013-04-09 21:52:36790}
791
792TEST_F(OutputConfiguratorTest, SuspendAndResume) {
793 InitWithSingleOutput();
794
795 // No preparation is needed before suspending when the display is already
796 // on. The configurator should still reprobe on resume in case a display
797 // was connected while suspended.
798 configurator_.SuspendDisplays();
799 EXPECT_EQ(kNoActions, delegate_->GetActionsAndClear());
800 configurator_.ResumeDisplays();
801 EXPECT_EQ(JoinActions(kGrab,
802 GetFramebufferAction(kSmallModeWidth, kSmallModeHeight,
803 outputs_[0].crtc, 0).c_str(),
804 GetCrtcAction(outputs_[0].crtc, 0, 0, kSmallModeId,
805 outputs_[0].output).c_str(),
806 kForceDPMS, kUngrab, NULL),
807 delegate_->GetActionsAndClear());
808
809 // Now turn the display off before suspending and check that the
810 // configurator turns it back on and syncs with the server.
811 configurator_.SetDisplayPower(DISPLAY_POWER_ALL_OFF,
812 OutputConfigurator::kSetDisplayPowerNoFlags);
813 EXPECT_EQ(JoinActions(kGrab,
814 GetFramebufferAction(kSmallModeWidth, kSmallModeHeight,
815 outputs_[0].crtc, 0).c_str(),
816 GetCrtcAction(outputs_[0].crtc, 0, 0, 0,
817 outputs_[0].output).c_str(),
818 kUngrab, NULL),
819 delegate_->GetActionsAndClear());
820
821 configurator_.SuspendDisplays();
822 EXPECT_EQ(JoinActions(kGrab,
823 GetFramebufferAction(kSmallModeWidth, kSmallModeHeight,
824 outputs_[0].crtc, 0).c_str(),
825 GetCrtcAction(outputs_[0].crtc, 0, 0, kSmallModeId,
826 outputs_[0].output).c_str(),
827 kForceDPMS, kUngrab, kSync, NULL),
828 delegate_->GetActionsAndClear());
829
830 configurator_.ResumeDisplays();
831 EXPECT_EQ(JoinActions(kGrab,
832 GetFramebufferAction(kSmallModeWidth, kSmallModeHeight,
833 outputs_[0].crtc, 0).c_str(),
834 GetCrtcAction(outputs_[0].crtc, 0, 0, kSmallModeId,
835 outputs_[0].output).c_str(),
836 kForceDPMS, kUngrab, NULL),
837 delegate_->GetActionsAndClear());
838
839 // If a second, external display is connected, the displays shouldn't be
840 // powered back on before suspending.
[email protected]acb217ed2013-04-09 21:52:36841 state_controller_.set_state(STATE_DUAL_MIRROR);
[email protected]edc1c802013-08-14 03:55:04842 UpdateOutputs(2, true);
[email protected]acb217ed2013-04-09 21:52:36843 EXPECT_EQ(JoinActions(kUpdateXRandR, kGrab,
844 GetFramebufferAction(kSmallModeWidth, kSmallModeHeight,
845 outputs_[0].crtc, outputs_[1].crtc).c_str(),
846 GetCrtcAction(outputs_[0].crtc, 0, 0, kSmallModeId,
847 outputs_[0].output).c_str(),
848 GetCrtcAction(outputs_[1].crtc, 0, 0, kSmallModeId,
849 outputs_[1].output).c_str(),
850 kUngrab, kProjectingOn, NULL),
851 delegate_->GetActionsAndClear());
852
853 configurator_.SetDisplayPower(DISPLAY_POWER_ALL_OFF,
854 OutputConfigurator::kSetDisplayPowerNoFlags);
855 EXPECT_EQ(JoinActions(kGrab,
856 GetFramebufferAction(kSmallModeWidth, kSmallModeHeight,
857 outputs_[0].crtc, outputs_[1].crtc).c_str(),
858 GetCrtcAction(outputs_[0].crtc, 0, 0, 0,
859 outputs_[0].output).c_str(),
860 GetCrtcAction(outputs_[1].crtc, 0, 0, 0,
861 outputs_[1].output).c_str(),
862 kUngrab, NULL),
863 delegate_->GetActionsAndClear());
864
865 configurator_.SuspendDisplays();
866 EXPECT_EQ(JoinActions(kGrab, kUngrab, kSync, NULL),
867 delegate_->GetActionsAndClear());
868
[email protected]edc1c802013-08-14 03:55:04869 // If a display is disconnected while suspended, the configurator should
[email protected]acb217ed2013-04-09 21:52:36870 // pick up the change.
[email protected]edc1c802013-08-14 03:55:04871 UpdateOutputs(1, false);
[email protected]acb217ed2013-04-09 21:52:36872 configurator_.ResumeDisplays();
873 EXPECT_EQ(JoinActions(kGrab,
874 GetFramebufferAction(kSmallModeWidth, kSmallModeHeight,
875 outputs_[0].crtc, 0).c_str(),
876 GetCrtcAction(outputs_[0].crtc, 0, 0, 0,
877 outputs_[0].output).c_str(),
878 kUngrab, NULL),
879 delegate_->GetActionsAndClear());
880}
881
882TEST_F(OutputConfiguratorTest, Headless) {
[email protected]edc1c802013-08-14 03:55:04883 UpdateOutputs(0, false);
[email protected]acb217ed2013-04-09 21:52:36884 EXPECT_EQ(kNoActions, delegate_->GetActionsAndClear());
[email protected]d30dac82013-07-31 16:17:30885 configurator_.Init(false);
886 EXPECT_EQ(kNoActions, delegate_->GetActionsAndClear());
887 configurator_.Start(0);
[email protected]acb217ed2013-04-09 21:52:36888 EXPECT_EQ(JoinActions(kGrab, kInitXRandR, kForceDPMS, kUngrab,
889 kProjectingOff, NULL),
890 delegate_->GetActionsAndClear());
891
892 // Not much should happen when the display power state is changed while
893 // no displays are connected.
894 configurator_.SetDisplayPower(DISPLAY_POWER_ALL_OFF,
895 OutputConfigurator::kSetDisplayPowerNoFlags);
896 EXPECT_EQ(JoinActions(kGrab, kUngrab, NULL), delegate_->GetActionsAndClear());
897 configurator_.SetDisplayPower(DISPLAY_POWER_ALL_ON,
898 OutputConfigurator::kSetDisplayPowerNoFlags);
899 EXPECT_EQ(JoinActions(kGrab, kForceDPMS, kUngrab, NULL),
900 delegate_->GetActionsAndClear());
901
902 // Connect an external display and check that it's configured correctly.
[email protected]5d99ee62013-08-16 19:56:47903 outputs_[0] = outputs_[1];
[email protected]edc1c802013-08-14 03:55:04904 UpdateOutputs(1, true);
[email protected]acb217ed2013-04-09 21:52:36905 EXPECT_EQ(JoinActions(kUpdateXRandR, kGrab,
906 GetFramebufferAction(kBigModeWidth, kBigModeHeight,
907 outputs_[0].crtc, 0).c_str(),
908 GetCrtcAction(outputs_[0].crtc, 0, 0, kBigModeId,
909 outputs_[0].output).c_str(),
910 kUngrab, kProjectingOff, NULL),
911 delegate_->GetActionsAndClear());
912}
913
914TEST_F(OutputConfiguratorTest, StartWithTwoOutputs) {
[email protected]edc1c802013-08-14 03:55:04915 UpdateOutputs(2, false);
[email protected]acb217ed2013-04-09 21:52:36916 EXPECT_EQ(kNoActions, delegate_->GetActionsAndClear());
[email protected]d30dac82013-07-31 16:17:30917 configurator_.Init(false);
918 EXPECT_EQ(kNoActions, delegate_->GetActionsAndClear());
[email protected]acb217ed2013-04-09 21:52:36919
920 state_controller_.set_state(STATE_DUAL_MIRROR);
[email protected]d30dac82013-07-31 16:17:30921 configurator_.Start(0);
[email protected]acb217ed2013-04-09 21:52:36922 EXPECT_EQ(JoinActions(kGrab, kInitXRandR,
923 GetFramebufferAction(kSmallModeWidth, kSmallModeHeight,
924 outputs_[0].crtc, outputs_[1].crtc).c_str(),
925 GetCrtcAction(outputs_[0].crtc, 0, 0, kSmallModeId,
926 outputs_[0].output).c_str(),
927 GetCrtcAction(outputs_[1].crtc, 0, 0, kSmallModeId,
928 outputs_[1].output).c_str(),
929 kForceDPMS, kUngrab, kProjectingOn, NULL),
930 delegate_->GetActionsAndClear());
931}
932
933TEST_F(OutputConfiguratorTest, InvalidOutputStates) {
[email protected]edc1c802013-08-14 03:55:04934 UpdateOutputs(0, false);
[email protected]acb217ed2013-04-09 21:52:36935 EXPECT_EQ(kNoActions, delegate_->GetActionsAndClear());
[email protected]d30dac82013-07-31 16:17:30936 configurator_.Init(false);
937 configurator_.Start(0);
[email protected]0b1b283b2013-08-17 13:32:18938 observer_.Reset();
[email protected]acb217ed2013-04-09 21:52:36939 EXPECT_TRUE(configurator_.SetDisplayMode(STATE_HEADLESS));
940 EXPECT_FALSE(configurator_.SetDisplayMode(STATE_SINGLE));
941 EXPECT_FALSE(configurator_.SetDisplayMode(STATE_DUAL_MIRROR));
942 EXPECT_FALSE(configurator_.SetDisplayMode(STATE_DUAL_EXTENDED));
[email protected]0b1b283b2013-08-17 13:32:18943 EXPECT_EQ(1, observer_.num_changes());
944 EXPECT_EQ(3, observer_.num_failures());
[email protected]acb217ed2013-04-09 21:52:36945
[email protected]edc1c802013-08-14 03:55:04946 UpdateOutputs(1, true);
[email protected]0b1b283b2013-08-17 13:32:18947 observer_.Reset();
[email protected]acb217ed2013-04-09 21:52:36948 EXPECT_FALSE(configurator_.SetDisplayMode(STATE_HEADLESS));
949 EXPECT_TRUE(configurator_.SetDisplayMode(STATE_SINGLE));
950 EXPECT_FALSE(configurator_.SetDisplayMode(STATE_DUAL_MIRROR));
951 EXPECT_FALSE(configurator_.SetDisplayMode(STATE_DUAL_EXTENDED));
[email protected]0b1b283b2013-08-17 13:32:18952 EXPECT_EQ(1, observer_.num_changes());
953 EXPECT_EQ(3, observer_.num_failures());
[email protected]acb217ed2013-04-09 21:52:36954
[email protected]acb217ed2013-04-09 21:52:36955 state_controller_.set_state(STATE_DUAL_EXTENDED);
[email protected]edc1c802013-08-14 03:55:04956 UpdateOutputs(2, true);
[email protected]0b1b283b2013-08-17 13:32:18957 observer_.Reset();
[email protected]acb217ed2013-04-09 21:52:36958 EXPECT_FALSE(configurator_.SetDisplayMode(STATE_HEADLESS));
959 EXPECT_FALSE(configurator_.SetDisplayMode(STATE_SINGLE));
960 EXPECT_TRUE(configurator_.SetDisplayMode(STATE_DUAL_MIRROR));
961 EXPECT_TRUE(configurator_.SetDisplayMode(STATE_DUAL_EXTENDED));
[email protected]0b1b283b2013-08-17 13:32:18962 EXPECT_EQ(2, observer_.num_changes());
963 EXPECT_EQ(2, observer_.num_failures());
[email protected]acb217ed2013-04-09 21:52:36964}
965
[email protected]edc1c802013-08-14 03:55:04966TEST_F(OutputConfiguratorTest, GetOutputStateForDisplaysWithoutId) {
[email protected]2c8a0aa72013-05-16 06:24:48967 outputs_[0].has_display_id = false;
[email protected]edc1c802013-08-14 03:55:04968 UpdateOutputs(2, false);
[email protected]d30dac82013-07-31 16:17:30969 configurator_.Init(false);
[email protected]2c8a0aa72013-05-16 06:24:48970 state_controller_.set_state(STATE_DUAL_MIRROR);
[email protected]edc1c802013-08-14 03:55:04971 configurator_.Start(0);
[email protected]2c8a0aa72013-05-16 06:24:48972 EXPECT_EQ(STATE_DUAL_EXTENDED, configurator_.output_state());
[email protected]edc1c802013-08-14 03:55:04973}
[email protected]2c8a0aa72013-05-16 06:24:48974
[email protected]edc1c802013-08-14 03:55:04975TEST_F(OutputConfiguratorTest, GetOutputStateForDisplaysWithId) {
[email protected]2c8a0aa72013-05-16 06:24:48976 outputs_[0].has_display_id = true;
[email protected]edc1c802013-08-14 03:55:04977 UpdateOutputs(2, false);
978 configurator_.Init(false);
979 state_controller_.set_state(STATE_DUAL_MIRROR);
980 configurator_.Start(0);
[email protected]2c8a0aa72013-05-16 06:24:48981 EXPECT_EQ(STATE_DUAL_MIRROR, configurator_.output_state());
982}
983
[email protected]edc1c802013-08-14 03:55:04984TEST_F(OutputConfiguratorTest, AvoidUnnecessaryProbes) {
985 InitWithSingleOutput();
986
987 // X sends several events just after the configurator starts. Check that
988 // the output change events don't trigger an additional probe, which can
989 // block the UI thread.
990 test_api_.SendScreenChangeEvent();
991 EXPECT_EQ(kUpdateXRandR, delegate_->GetActionsAndClear());
992
993 test_api_.SendOutputChangeEvent(
994 outputs_[0].output, outputs_[0].crtc, outputs_[0].current_mode, true);
995 test_api_.SendOutputChangeEvent(
996 outputs_[1].output, outputs_[1].crtc, outputs_[1].current_mode, false);
997 EXPECT_FALSE(test_api_.TriggerConfigureTimeout());
998 EXPECT_EQ(kNoActions, delegate_->GetActionsAndClear());
999
1000 // Send an event stating that the second output is connected and check
1001 // that it gets updated.
1002 state_controller_.set_state(STATE_DUAL_MIRROR);
1003 UpdateOutputs(2, false);
1004 test_api_.SendOutputChangeEvent(
1005 outputs_[1].output, outputs_[1].crtc, outputs_[1].current_mode, true);
1006 EXPECT_TRUE(test_api_.TriggerConfigureTimeout());
1007 EXPECT_EQ(JoinActions(kGrab,
1008 GetFramebufferAction(kSmallModeWidth, kSmallModeHeight,
1009 outputs_[0].crtc, outputs_[1].crtc).c_str(),
1010 GetCrtcAction(outputs_[0].crtc, 0, 0, kSmallModeId,
1011 outputs_[0].output).c_str(),
1012 GetCrtcAction(outputs_[1].crtc, 0, 0, kSmallModeId,
1013 outputs_[1].output).c_str(),
1014 kUngrab, kProjectingOn, NULL),
1015 delegate_->GetActionsAndClear());
1016
1017 // An event about the second output changing modes should trigger another
1018 // reconfigure.
1019 test_api_.SendOutputChangeEvent(
1020 outputs_[1].output, outputs_[1].crtc, outputs_[1].native_mode, true);
1021 EXPECT_TRUE(test_api_.TriggerConfigureTimeout());
1022 EXPECT_EQ(JoinActions(kGrab,
1023 GetFramebufferAction(kSmallModeWidth, kSmallModeHeight,
1024 outputs_[0].crtc, outputs_[1].crtc).c_str(),
1025 GetCrtcAction(outputs_[0].crtc, 0, 0, kSmallModeId,
1026 outputs_[0].output).c_str(),
1027 GetCrtcAction(outputs_[1].crtc, 0, 0, kSmallModeId,
1028 outputs_[1].output).c_str(),
1029 kUngrab, kProjectingOn, NULL),
1030 delegate_->GetActionsAndClear());
1031
1032 // Disconnect the second output.
1033 UpdateOutputs(1, true);
1034 EXPECT_EQ(JoinActions(kUpdateXRandR, kGrab,
1035 GetFramebufferAction(kSmallModeWidth, kSmallModeHeight,
1036 outputs_[0].crtc, 0).c_str(),
1037 GetCrtcAction(outputs_[0].crtc, 0, 0, kSmallModeId,
1038 outputs_[0].output).c_str(),
1039 kUngrab, kProjectingOff, NULL),
1040 delegate_->GetActionsAndClear());
1041
1042 // An additional event about the second output being disconnected should
1043 // be ignored.
1044 test_api_.SendOutputChangeEvent(
1045 outputs_[1].output, outputs_[1].crtc, outputs_[1].current_mode, false);
1046 EXPECT_FALSE(test_api_.TriggerConfigureTimeout());
1047 EXPECT_EQ(kNoActions, delegate_->GetActionsAndClear());
1048
[email protected]63da7fb2014-01-10 00:35:311049 // Lower the limit for which the delegate will succeed, which should result
1050 // in the second output sticking with its native mode.
1051 delegate_->set_max_configurable_pixels(1);
[email protected]edc1c802013-08-14 03:55:041052 UpdateOutputs(2, true);
1053 EXPECT_EQ(JoinActions(kUpdateXRandR, kGrab,
1054 GetFramebufferAction(kSmallModeWidth, kSmallModeHeight,
1055 outputs_[0].crtc, outputs_[1].crtc).c_str(),
1056 GetCrtcAction(outputs_[0].crtc, 0, 0, kSmallModeId,
1057 outputs_[0].output).c_str(),
1058 GetCrtcAction(outputs_[1].crtc, 0, 0, kSmallModeId,
1059 outputs_[1].output).c_str(),
[email protected]63da7fb2014-01-10 00:35:311060 GetFramebufferAction(kBigModeWidth,
1061 kSmallModeHeight + kBigModeHeight +
1062 OutputConfigurator::kVerticalGap,
1063 outputs_[0].crtc, outputs_[1].crtc).c_str(),
1064 GetCrtcAction(outputs_[0].crtc, 0, 0, kSmallModeId,
1065 outputs_[0].output).c_str(),
1066 GetCrtcAction(outputs_[1].crtc, 0, kSmallModeHeight +
1067 OutputConfigurator::kVerticalGap, kBigModeId,
1068 outputs_[1].output).c_str(),
1069 GetCrtcAction(outputs_[1].crtc, 0, kSmallModeHeight +
1070 OutputConfigurator::kVerticalGap, kSmallModeId,
1071 outputs_[1].output).c_str(),
[email protected]edc1c802013-08-14 03:55:041072 kUngrab, kProjectingOn, NULL),
1073 delegate_->GetActionsAndClear());
1074
[email protected]63da7fb2014-01-10 00:35:311075 // A change event reporting a mode change on the second output should
[email protected]edc1c802013-08-14 03:55:041076 // trigger another reconfigure.
[email protected]63da7fb2014-01-10 00:35:311077 delegate_->set_max_configurable_pixels(0);
[email protected]edc1c802013-08-14 03:55:041078 test_api_.SendOutputChangeEvent(
1079 outputs_[1].output, outputs_[1].crtc, outputs_[1].mirror_mode, true);
1080 EXPECT_TRUE(test_api_.TriggerConfigureTimeout());
1081 EXPECT_EQ(JoinActions(kGrab,
1082 GetFramebufferAction(kSmallModeWidth, kSmallModeHeight,
1083 outputs_[0].crtc, outputs_[1].crtc).c_str(),
1084 GetCrtcAction(outputs_[0].crtc, 0, 0, kSmallModeId,
1085 outputs_[0].output).c_str(),
1086 GetCrtcAction(outputs_[1].crtc, 0, 0, kSmallModeId,
1087 outputs_[1].output).c_str(),
1088 kUngrab, kProjectingOn, NULL),
1089 delegate_->GetActionsAndClear());
1090}
1091
[email protected]3d1df542013-09-24 04:26:221092TEST_F(OutputConfiguratorTest, UpdateCachedOutputsEvenAfterFailure) {
1093 InitWithSingleOutput();
1094 const std::vector<OutputConfigurator::OutputSnapshot>* cached =
1095 &test_api_.cached_outputs();
1096 ASSERT_EQ(static_cast<size_t>(1), cached->size());
1097 EXPECT_EQ(outputs_[0].current_mode, (*cached)[0].current_mode);
1098
1099 // After connecting a second output, check that it shows up in
1100 // |cached_outputs_| even if an invalid state is requested.
1101 state_controller_.set_state(STATE_SINGLE);
1102 UpdateOutputs(2, true);
1103 cached = &test_api_.cached_outputs();
1104 ASSERT_EQ(static_cast<size_t>(2), cached->size());
1105 EXPECT_EQ(outputs_[0].current_mode, (*cached)[0].current_mode);
1106 EXPECT_EQ(outputs_[1].current_mode, (*cached)[1].current_mode);
1107}
1108
[email protected]6eebb90b2013-09-17 18:30:271109TEST_F(OutputConfiguratorTest, PanelFitting) {
1110 // Configure the internal display to support only the big mode and the
1111 // external display to support only the small mode.
1112 outputs_[0].current_mode = kBigModeId;
1113 outputs_[0].native_mode = kBigModeId;
1114 outputs_[0].mode_infos.clear();
1115 outputs_[0].mode_infos[kBigModeId] = OutputConfigurator::ModeInfo(
1116 kBigModeWidth, kBigModeHeight, false, 60.0);
1117
1118 outputs_[1].current_mode = kSmallModeId;
1119 outputs_[1].native_mode = kSmallModeId;
1120 outputs_[1].mode_infos.clear();
1121 outputs_[1].mode_infos[kSmallModeId] = OutputConfigurator::ModeInfo(
1122 kSmallModeWidth, kSmallModeHeight, false, 60.0);
1123
1124 // The small mode should be added to the internal output when requesting
1125 // mirrored mode.
1126 UpdateOutputs(2, false);
1127 state_controller_.set_state(STATE_DUAL_MIRROR);
1128 configurator_.Init(true /* is_panel_fitting_enabled */);
1129 configurator_.Start(0);
1130 EXPECT_EQ(STATE_DUAL_MIRROR, configurator_.output_state());
1131 EXPECT_EQ(JoinActions(kGrab, kInitXRandR,
1132 GetAddOutputModeAction(
1133 outputs_[0].output, kSmallModeId).c_str(),
1134 GetFramebufferAction(kSmallModeWidth, kSmallModeHeight,
1135 outputs_[0].crtc, outputs_[1].crtc).c_str(),
1136 GetCrtcAction(outputs_[0].crtc, 0, 0, kSmallModeId,
1137 outputs_[0].output).c_str(),
1138 GetCrtcAction(outputs_[1].crtc, 0, 0, kSmallModeId,
1139 outputs_[1].output).c_str(),
1140 kForceDPMS, kUngrab, kProjectingOn, NULL),
1141 delegate_->GetActionsAndClear());
1142
1143 // Both outputs should be using the small mode.
1144 ASSERT_EQ(1, observer_.num_changes());
1145 ASSERT_EQ(static_cast<size_t>(2), observer_.latest_outputs().size());
1146 EXPECT_EQ(kSmallModeId, observer_.latest_outputs()[0].mirror_mode);
1147 EXPECT_EQ(kSmallModeId, observer_.latest_outputs()[0].current_mode);
1148 EXPECT_EQ(kSmallModeId, observer_.latest_outputs()[1].mirror_mode);
1149 EXPECT_EQ(kSmallModeId, observer_.latest_outputs()[1].current_mode);
1150
1151 // Also check that the newly-added small mode is present in the internal
1152 // snapshot that was passed to the observer (http://crbug.com/289159).
1153 const OutputConfigurator::ModeInfo* info = OutputConfigurator::GetModeInfo(
1154 observer_.latest_outputs()[0], kSmallModeId);
1155 ASSERT_TRUE(info);
1156 EXPECT_EQ(kSmallModeWidth, info->width);
1157 EXPECT_EQ(kSmallModeHeight, info->height);
1158}
1159
[email protected]a9318842013-10-02 07:21:131160TEST_F(OutputConfiguratorTest, OutputProtection) {
1161 configurator_.Init(false);
1162 configurator_.Start(0);
1163 EXPECT_NE(kNoActions, delegate_->GetActionsAndClear());
1164
1165 OutputConfigurator::OutputProtectionClientId id =
1166 configurator_.RegisterOutputProtectionClient();
1167 EXPECT_NE(0u, id);
1168
1169 // One output.
1170 UpdateOutputs(1, true);
1171 EXPECT_NE(kNoActions, delegate_->GetActionsAndClear());
1172 uint32_t link_mask = 0;
1173 uint32_t protection_mask = 0;
[email protected]67e6a682013-10-31 10:00:411174 EXPECT_TRUE(configurator_.QueryOutputProtectionStatus(id,
1175 outputs_[0].display_id,
1176 &link_mask,
[email protected]a9318842013-10-02 07:21:131177 &protection_mask));
1178 EXPECT_EQ(static_cast<uint32_t>(OUTPUT_TYPE_INTERNAL), link_mask);
1179 EXPECT_EQ(static_cast<uint32_t>(OUTPUT_PROTECTION_METHOD_NONE),
1180 protection_mask);
1181 EXPECT_EQ(kNoActions, delegate_->GetActionsAndClear());
1182
1183 // Two outputs.
1184 UpdateOutputs(2, true);
1185 EXPECT_NE(kNoActions, delegate_->GetActionsAndClear());
[email protected]67e6a682013-10-31 10:00:411186 EXPECT_TRUE(configurator_.QueryOutputProtectionStatus(id,
1187 outputs_[1].display_id,
1188 &link_mask,
[email protected]a9318842013-10-02 07:21:131189 &protection_mask));
[email protected]67e6a682013-10-31 10:00:411190 EXPECT_EQ(static_cast<uint32_t>(OUTPUT_TYPE_HDMI),
[email protected]a9318842013-10-02 07:21:131191 link_mask);
1192 EXPECT_EQ(static_cast<uint32_t>(OUTPUT_PROTECTION_METHOD_NONE),
1193 protection_mask);
1194 EXPECT_EQ(kNoActions, delegate_->GetActionsAndClear());
1195
1196 EXPECT_TRUE(
[email protected]67e6a682013-10-31 10:00:411197 configurator_.EnableOutputProtection(id,
1198 outputs_[1].display_id,
1199 OUTPUT_PROTECTION_METHOD_HDCP));
[email protected]a9318842013-10-02 07:21:131200 EXPECT_EQ(GetSetHDCPStateAction(outputs_[1].output, HDCP_STATE_DESIRED),
1201 delegate_->GetActionsAndClear());
1202
1203 // Enable protection.
1204 delegate_->set_hdcp_state(HDCP_STATE_ENABLED);
[email protected]67e6a682013-10-31 10:00:411205 EXPECT_TRUE(configurator_.QueryOutputProtectionStatus(id,
1206 outputs_[1].display_id,
1207 &link_mask,
[email protected]a9318842013-10-02 07:21:131208 &protection_mask));
[email protected]67e6a682013-10-31 10:00:411209 EXPECT_EQ(static_cast<uint32_t>(OUTPUT_TYPE_HDMI), link_mask);
[email protected]a9318842013-10-02 07:21:131210 EXPECT_EQ(static_cast<uint32_t>(OUTPUT_PROTECTION_METHOD_HDCP),
1211 protection_mask);
1212 EXPECT_EQ(kNoActions, delegate_->GetActionsAndClear());
[email protected]67e6a682013-10-31 10:00:411213
1214 // Protections should be disabled after unregister.
1215 configurator_.UnregisterOutputProtectionClient(id);
1216 EXPECT_EQ(GetSetHDCPStateAction(outputs_[1].output, HDCP_STATE_UNDESIRED),
1217 delegate_->GetActionsAndClear());
[email protected]a9318842013-10-02 07:21:131218}
1219
1220TEST_F(OutputConfiguratorTest, OutputProtectionTwoClients) {
1221 OutputConfigurator::OutputProtectionClientId client1 =
1222 configurator_.RegisterOutputProtectionClient();
1223 OutputConfigurator::OutputProtectionClientId client2 =
1224 configurator_.RegisterOutputProtectionClient();
1225 EXPECT_NE(client1, client2);
1226
1227 configurator_.Init(false);
1228 configurator_.Start(0);
1229 UpdateOutputs(2, true);
1230 EXPECT_NE(kNoActions, delegate_->GetActionsAndClear());
1231
1232 // Clients never know state enableness for methods that they didn't request.
1233 EXPECT_TRUE(
1234 configurator_.EnableOutputProtection(client1,
[email protected]67e6a682013-10-31 10:00:411235 outputs_[1].display_id,
[email protected]a9318842013-10-02 07:21:131236 OUTPUT_PROTECTION_METHOD_HDCP));
1237 EXPECT_EQ(GetSetHDCPStateAction(outputs_[1].output,
1238 HDCP_STATE_DESIRED).c_str(),
1239 delegate_->GetActionsAndClear());
1240 delegate_->set_hdcp_state(HDCP_STATE_ENABLED);
1241
1242 uint32_t link_mask = 0;
1243 uint32_t protection_mask = 0;
[email protected]67e6a682013-10-31 10:00:411244 EXPECT_TRUE(configurator_.QueryOutputProtectionStatus(client1,
1245 outputs_[1].display_id,
1246 &link_mask,
[email protected]a9318842013-10-02 07:21:131247 &protection_mask));
[email protected]67e6a682013-10-31 10:00:411248 EXPECT_EQ(static_cast<uint32_t>(OUTPUT_TYPE_HDMI), link_mask);
[email protected]a9318842013-10-02 07:21:131249 EXPECT_EQ(OUTPUT_PROTECTION_METHOD_HDCP, protection_mask);
1250
[email protected]67e6a682013-10-31 10:00:411251 EXPECT_TRUE(configurator_.QueryOutputProtectionStatus(client2,
1252 outputs_[1].display_id,
1253 &link_mask,
[email protected]a9318842013-10-02 07:21:131254 &protection_mask));
[email protected]67e6a682013-10-31 10:00:411255 EXPECT_EQ(static_cast<uint32_t>(OUTPUT_TYPE_HDMI), link_mask);
[email protected]a9318842013-10-02 07:21:131256 EXPECT_EQ(OUTPUT_PROTECTION_METHOD_NONE, protection_mask);
1257
1258 // Protections will be disabled only if no more clients request them.
1259 EXPECT_TRUE(
1260 configurator_.EnableOutputProtection(client2,
[email protected]67e6a682013-10-31 10:00:411261 outputs_[1].display_id,
[email protected]a9318842013-10-02 07:21:131262 OUTPUT_PROTECTION_METHOD_NONE));
1263 EXPECT_EQ(GetSetHDCPStateAction(outputs_[1].output,
1264 HDCP_STATE_DESIRED).c_str(),
1265 delegate_->GetActionsAndClear());
1266 EXPECT_TRUE(
1267 configurator_.EnableOutputProtection(client1,
[email protected]67e6a682013-10-31 10:00:411268 outputs_[1].display_id,
[email protected]a9318842013-10-02 07:21:131269 OUTPUT_PROTECTION_METHOD_NONE));
1270 EXPECT_EQ(GetSetHDCPStateAction(outputs_[1].output,
1271 HDCP_STATE_UNDESIRED).c_str(),
1272 delegate_->GetActionsAndClear());
1273}
1274
[email protected]06b20fe2013-11-13 19:18:381275TEST_F(OutputConfiguratorTest, CTMForMultiScreens) {
1276 outputs_[0].touch_device_id = 1;
1277 outputs_[1].touch_device_id = 2;
1278
1279 UpdateOutputs(2, false);
1280 configurator_.Init(false);
1281 state_controller_.set_state(STATE_DUAL_EXTENDED);
1282 configurator_.Start(0);
1283
1284 const int kDualHeight =
1285 kSmallModeHeight + OutputConfigurator::kVerticalGap + kBigModeHeight;
1286 const int kDualWidth = kBigModeWidth;
1287
1288 OutputConfigurator::CoordinateTransformation ctm1 = delegate_->get_ctm(1);
1289 OutputConfigurator::CoordinateTransformation ctm2 = delegate_->get_ctm(2);
1290
1291 EXPECT_EQ(kSmallModeHeight - 1, round((kDualHeight - 1) * ctm1.y_scale));
1292 EXPECT_EQ(0, round((kDualHeight - 1) * ctm1.y_offset));
1293
1294 EXPECT_EQ(kBigModeHeight - 1, round((kDualHeight - 1) * ctm2.y_scale));
1295 EXPECT_EQ(kSmallModeHeight + OutputConfigurator::kVerticalGap,
1296 round((kDualHeight - 1) * ctm2.y_offset));
1297
1298 EXPECT_EQ(kSmallModeWidth - 1, round((kDualWidth - 1) * ctm1.x_scale));
1299 EXPECT_EQ(0, round((kDualWidth - 1) * ctm1.x_offset));
1300
1301 EXPECT_EQ(kBigModeWidth - 1, round((kDualWidth - 1) * ctm2.x_scale));
1302 EXPECT_EQ(0, round((kDualWidth - 1) * ctm2.x_offset));
1303}
1304
[email protected]63da7fb2014-01-10 00:35:311305TEST_F(OutputConfiguratorTest, HandleConfigureCrtcFailure) {
1306 InitWithSingleOutput();
1307
1308 // kFirstMode represents the first mode in the list and
1309 // also the mode that we are requesting the output_configurator
1310 // to choose. The test will be setup so that this mode will fail
1311 // and it will have to choose the next best option.
1312 const int kFirstMode = 11;
1313
1314 // Give the mode_info lists a few reasonable modes.
1315 for (unsigned int i = 0; i < arraysize(outputs_); i++) {
1316 outputs_[i].mode_infos.clear();
1317
1318 int current_mode = kFirstMode;
1319 outputs_[i].mode_infos[current_mode++] = OutputConfigurator::ModeInfo(
1320 2560, 1600, false, 60.0);
1321 outputs_[i].mode_infos[current_mode++] = OutputConfigurator::ModeInfo(
1322 1024, 768, false, 60.0);
1323 outputs_[i].mode_infos[current_mode++] = OutputConfigurator::ModeInfo(
1324 1280, 720, false, 60.0);
1325 outputs_[i].mode_infos[current_mode++] = OutputConfigurator::ModeInfo(
1326 1920, 1080, false, 60.0);
1327 outputs_[i].mode_infos[current_mode++] = OutputConfigurator::ModeInfo(
1328 1920, 1080, false, 40.0);
1329
1330 outputs_[i].current_mode = kFirstMode;
1331 outputs_[i].native_mode = kFirstMode;
1332 }
1333
1334 configurator_.Init(false);
1335
1336 // First test simply fails in STATE_SINGLE mode. This is probably
1337 // unrealistic but the want to make sure any assumptions don't
1338 // creep in.
1339 delegate_->set_max_configurable_pixels(
1340 outputs_[0].mode_infos[kFirstMode + 2].width *
1341 outputs_[0].mode_infos[kFirstMode + 2].height);
1342 state_controller_.set_state(STATE_SINGLE);
1343 UpdateOutputs(1, true);
1344
1345 EXPECT_EQ(JoinActions(kUpdateXRandR, kGrab,
1346 GetFramebufferAction(2560, 1600,
1347 outputs_[0].crtc, 0).c_str(),
1348 GetCrtcAction(outputs_[0].crtc, 0, 0, kFirstMode,
1349 outputs_[0].output).c_str(),
1350 GetCrtcAction(outputs_[0].crtc, 0, 0, kFirstMode + 3,
1351 outputs_[0].output).c_str(),
1352 GetCrtcAction(outputs_[0].crtc, 0, 0, kFirstMode + 2,
1353 outputs_[0].output).c_str(),
1354 kUngrab, kProjectingOff, NULL),
1355 delegate_->GetActionsAndClear());
1356
1357 // This test should attempt to configure a mirror mode that will not succeed
1358 // and should end up in extended mode.
1359 delegate_->set_max_configurable_pixels(
1360 outputs_[0].mode_infos[kFirstMode + 3].width *
1361 outputs_[0].mode_infos[kFirstMode + 3].height);
1362 state_controller_.set_state(STATE_DUAL_MIRROR);
1363 UpdateOutputs(2, true);
1364
1365 EXPECT_EQ(JoinActions(kUpdateXRandR, kGrab,
1366 GetFramebufferAction(
1367 outputs_[0].mode_infos[kFirstMode].width,
1368 outputs_[0].mode_infos[kFirstMode].height,
1369 outputs_[0].crtc,
1370 outputs_[1].crtc).c_str(),
1371 GetCrtcAction(outputs_[0].crtc,
1372 0, 0, kFirstMode, outputs_[0].output).c_str(),
1373 // First mode tried is expected to fail and it will
1374 // retry wil the 4th mode in the list.
1375 GetCrtcAction(outputs_[0].crtc, 0, 0, kFirstMode + 3,
1376 outputs_[0].output).c_str(),
1377 // Then attempt to configure crtc1 with the first mode.
1378 GetCrtcAction(outputs_[1].crtc, 0, 0, kFirstMode,
1379 outputs_[1].output).c_str(),
1380 GetCrtcAction(outputs_[1].crtc, 0, 0, kFirstMode + 3,
1381 outputs_[1].output).c_str(),
1382 // Since it was requested to go into mirror mode
1383 // and the configured modes were different, it
1384 // should now try and setup a valid configurable
1385 // extended mode.
1386 GetFramebufferAction(
1387 outputs_[0].mode_infos[kFirstMode].width,
1388 outputs_[0].mode_infos[kFirstMode].height +
1389 outputs_[1].mode_infos[kFirstMode].height +
1390 OutputConfigurator::kVerticalGap,
1391 outputs_[0].crtc, outputs_[1].crtc).c_str(),
1392 GetCrtcAction(outputs_[0].crtc, 0, 0, kFirstMode,
1393 outputs_[0].output).c_str(),
1394 GetCrtcAction(outputs_[0].crtc, 0, 0, kFirstMode + 3,
1395 outputs_[0].output).c_str(),
1396 GetCrtcAction(outputs_[1].crtc, 0,
1397 outputs_[1].mode_infos[kFirstMode].height +
1398 OutputConfigurator::kVerticalGap, kFirstMode,
1399 outputs_[1].output).c_str(),
1400 GetCrtcAction(outputs_[1].crtc, 0,
1401 outputs_[1].mode_infos[kFirstMode].height +
1402 OutputConfigurator::kVerticalGap, kFirstMode + 3,
1403 outputs_[1].output).c_str(),
1404 kUngrab, kProjectingOn, NULL),
1405 delegate_->GetActionsAndClear());
1406
1407}
1408
[email protected]6d980bc2012-09-10 19:28:451409} // namespace chromeos