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

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

Issue 801493002: Update DisplayConfigurator to use the asynchronous tasks (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@async-refactor4
Patch Set: Fix comment Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/display/chromeos/display_configurator.h" 5 #include "ui/display/chromeos/display_configurator.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/command_line.h" 8 #include "base/command_line.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/sys_info.h" 10 #include "base/sys_info.h"
11 #include "base/time/time.h" 11 #include "base/time/time.h"
12 #include "ui/display/chromeos/display_util.h" 12 #include "ui/display/chromeos/display_util.h"
13 #include "ui/display/chromeos/update_display_configuration_task.h"
13 #include "ui/display/display_switches.h" 14 #include "ui/display/display_switches.h"
14 #include "ui/display/types/display_mode.h" 15 #include "ui/display/types/display_mode.h"
15 #include "ui/display/types/display_snapshot.h" 16 #include "ui/display/types/display_snapshot.h"
16 #include "ui/display/types/native_display_delegate.h" 17 #include "ui/display/types/native_display_delegate.h"
17 18
18 namespace ui { 19 namespace ui {
19 20
20 namespace { 21 namespace {
21 22
22 typedef std::vector<const DisplayMode*> DisplayModeList; 23 typedef std::vector<const DisplayMode*> DisplayModeList;
(...skipping 24 matching lines...) Expand all
47 bool DisplayConfigurator::TestApi::TriggerConfigureTimeout() { 48 bool DisplayConfigurator::TestApi::TriggerConfigureTimeout() {
48 if (configurator_->configure_timer_.IsRunning()) { 49 if (configurator_->configure_timer_.IsRunning()) {
49 configurator_->configure_timer_.user_task().Run(); 50 configurator_->configure_timer_.user_task().Run();
50 configurator_->configure_timer_.Stop(); 51 configurator_->configure_timer_.Stop();
51 return true; 52 return true;
52 } else { 53 } else {
53 return false; 54 return false;
54 } 55 }
55 } 56 }
56 57
58 ////////////////////////////////////////////////////////////////////////////////
59 // DisplayConfigurator::DisplayLayoutManagerImpl implementation
60
61 class DisplayConfigurator::DisplayLayoutManagerImpl
62 : public DisplayLayoutManager {
63 public:
64 DisplayLayoutManagerImpl(DisplayConfigurator* configurator);
65 ~DisplayLayoutManagerImpl() override;
66
67 // DisplayConfigurator::DisplayLayoutManager:
68 SoftwareMirroringController* GetSoftwareMirroringController() const override;
69 StateController* GetStateController() const override;
70 MultipleDisplayState GetDisplayState() const override;
71 chromeos::DisplayPowerState GetPowerState() const override;
72 std::vector<DisplayState> ParseDisplays(
73 const std::vector<DisplaySnapshot*>& displays) const override;
74 bool GetDisplayLayout(const std::vector<DisplayState>& displays,
75 MultipleDisplayState new_display_state,
76 chromeos::DisplayPowerState new_power_state,
77 std::vector<DisplayConfigureRequest>* requests,
78 gfx::Size* framebuffer_size) const override;
79
80 private:
81 // Helper method for ParseDisplays() that initializes the passed-in
82 // displays' |mirror_mode| fields by looking for a mode in |internal_display|
83 // and |external_display| having the same resolution. Returns false if a
84 // shared mode wasn't found or created.
85 //
86 // |try_panel_fitting| allows creating a panel-fitting mode for
87 // |internal_display| instead of only searching for a matching mode (note that
88 // it may lead to a crash if |internal_display| is not capable of panel
89 // fitting).
90 //
91 // |preserve_aspect| limits the search/creation only to the modes having the
92 // native aspect ratio of |external_display|.
93 bool FindMirrorMode(DisplayState* internal_display,
94 DisplayState* external_display,
95 bool try_panel_fitting,
96 bool preserve_aspect) const;
97
98 DisplayConfigurator* configurator_; // Not owned.
99
100 DISALLOW_COPY_AND_ASSIGN(DisplayLayoutManagerImpl);
101 };
102
103 DisplayConfigurator::DisplayLayoutManagerImpl::DisplayLayoutManagerImpl(
104 DisplayConfigurator* configurator)
105 : configurator_(configurator) {
106 }
107
108 DisplayConfigurator::DisplayLayoutManagerImpl::~DisplayLayoutManagerImpl() {
109 }
110
111 DisplayConfigurator::SoftwareMirroringController*
112 DisplayConfigurator::DisplayLayoutManagerImpl::GetSoftwareMirroringController()
113 const {
114 return configurator_->mirroring_controller_;
115 }
116
117 DisplayConfigurator::StateController*
118 DisplayConfigurator::DisplayLayoutManagerImpl::GetStateController() const {
119 return configurator_->state_controller_;
120 }
121
122 MultipleDisplayState
123 DisplayConfigurator::DisplayLayoutManagerImpl::GetDisplayState() const {
124 return configurator_->current_display_state_;
125 }
126
127 chromeos::DisplayPowerState
128 DisplayConfigurator::DisplayLayoutManagerImpl::GetPowerState() const {
129 return configurator_->current_power_state_;
130 }
131
132 std::vector<DisplayConfigurator::DisplayState>
133 DisplayConfigurator::DisplayLayoutManagerImpl::ParseDisplays(
134 const std::vector<DisplaySnapshot*>& snapshots) const {
135 std::vector<DisplayState> cached_displays;
136 for (auto snapshot : snapshots) {
137 DisplayState display_state;
138 display_state.display = snapshot;
139 cached_displays.push_back(display_state);
140 }
141
142 // Set |selected_mode| fields.
143 for (size_t i = 0; i < cached_displays.size(); ++i) {
144 DisplayState* display_state = &cached_displays[i];
145 gfx::Size size;
146 if (GetStateController() &&
147 GetStateController()->GetResolutionForDisplayId(
148 display_state->display->display_id(), &size)) {
149 display_state->selected_mode =
150 FindDisplayModeMatchingSize(*display_state->display, size);
151 }
152
153 // Fall back to native mode.
154 if (!display_state->selected_mode)
155 display_state->selected_mode = display_state->display->native_mode();
156 }
157
158 // Set |mirror_mode| fields.
159 if (cached_displays.size() == 2) {
160 bool one_is_internal =
161 cached_displays[0].display->type() == DISPLAY_CONNECTION_TYPE_INTERNAL;
162 bool two_is_internal =
163 cached_displays[1].display->type() == DISPLAY_CONNECTION_TYPE_INTERNAL;
164 int internal_displays =
165 (one_is_internal ? 1 : 0) + (two_is_internal ? 1 : 0);
166 DCHECK_LT(internal_displays, 2);
167 LOG_IF(WARNING, internal_displays >= 2)
168 << "At least two internal displays detected.";
169
170 bool can_mirror = false;
171 for (int attempt = 0; !can_mirror && attempt < 2; ++attempt) {
172 // Try preserving external display's aspect ratio on the first attempt.
173 // If that fails, fall back to the highest matching resolution.
174 bool preserve_aspect = attempt == 0;
175
176 if (internal_displays == 1) {
177 can_mirror = FindMirrorMode(&cached_displays[one_is_internal ? 0 : 1],
178 &cached_displays[one_is_internal ? 1 : 0],
179 configurator_->is_panel_fitting_enabled_,
180 preserve_aspect);
181 } else { // if (internal_displays == 0)
182 // No panel fitting for external displays, so fall back to exact match.
183 can_mirror = FindMirrorMode(&cached_displays[0], &cached_displays[1],
184 false, preserve_aspect);
185 if (!can_mirror && preserve_aspect) {
186 // FindMirrorMode() will try to preserve aspect ratio of what it
187 // thinks is external display, so if it didn't succeed with one, maybe
188 // it will succeed with the other. This way we will have the correct
189 // aspect ratio on at least one of them.
190 can_mirror = FindMirrorMode(&cached_displays[1], &cached_displays[0],
191 false, preserve_aspect);
192 }
193 }
194 }
195 }
196
197 return cached_displays;
198 }
199
200 bool DisplayConfigurator::DisplayLayoutManagerImpl::GetDisplayLayout(
201 const std::vector<DisplayState>& displays,
202 MultipleDisplayState new_display_state,
203 chromeos::DisplayPowerState new_power_state,
204 std::vector<DisplayConfigureRequest>* requests,
205 gfx::Size* framebuffer_size) const {
206 std::vector<bool> display_power;
207 int num_on_displays =
208 GetDisplayPower(displays, new_power_state, &display_power);
209 VLOG(1) << "EnterState: display="
210 << MultipleDisplayStateToString(new_display_state)
211 << " power=" << DisplayPowerStateToString(new_power_state);
212
213 // Framebuffer dimensions.
214 gfx::Size size;
215
216 for (size_t i = 0; i < displays.size(); ++i) {
217 requests->push_back(DisplayConfigureRequest(
218 displays[i].display, displays[i].display->current_mode(),
219 gfx::Point()));
220 }
221
222 switch (new_display_state) {
223 case MULTIPLE_DISPLAY_STATE_INVALID:
224 NOTREACHED() << "Ignoring request to enter invalid state with "
225 << displays.size() << " connected display(s)";
226 return false;
227 case MULTIPLE_DISPLAY_STATE_HEADLESS:
228 if (displays.size() != 0) {
229 LOG(WARNING) << "Ignoring request to enter headless mode with "
230 << displays.size() << " connected display(s)";
231 return false;
232 }
233 break;
234 case MULTIPLE_DISPLAY_STATE_SINGLE: {
235 // If there are multiple displays connected, only one should be turned on.
236 if (displays.size() != 1 && num_on_displays != 1) {
237 LOG(WARNING) << "Ignoring request to enter single mode with "
238 << displays.size() << " connected displays and "
239 << num_on_displays << " turned on";
240 return false;
241 }
242
243 for (size_t i = 0; i < displays.size(); ++i) {
244 const DisplayConfigurator::DisplayState* state = &displays[i];
245 (*requests)[i].mode = display_power[i] ? state->selected_mode : NULL;
246
247 if (display_power[i] || displays.size() == 1) {
248 const DisplayMode* mode_info = state->selected_mode;
249 if (!mode_info) {
250 LOG(WARNING) << "No selected mode when configuring display: "
251 << state->display->ToString();
252 return false;
253 }
254 if (mode_info->size() == gfx::Size(1024, 768)) {
255 VLOG(1) << "Potentially misdetecting display(1024x768):"
256 << " displays size=" << displays.size()
257 << ", num_on_displays=" << num_on_displays
258 << ", current size:" << size.width() << "x" << size.height()
259 << ", i=" << i << ", display=" << state->display->ToString()
260 << ", display_mode=" << mode_info->ToString();
261 }
262 size = mode_info->size();
263 }
264 }
265 break;
266 }
267 case MULTIPLE_DISPLAY_STATE_DUAL_MIRROR: {
268 if (displays.size() != 2 ||
269 (num_on_displays != 0 && num_on_displays != 2)) {
270 LOG(WARNING) << "Ignoring request to enter mirrored mode with "
271 << displays.size() << " connected display(s) and "
272 << num_on_displays << " turned on";
273 return false;
274 }
275
276 const DisplayMode* mode_info = displays[0].mirror_mode;
277 if (!mode_info) {
278 LOG(WARNING) << "No mirror mode when configuring display: "
279 << displays[0].display->ToString();
280 return false;
281 }
282 size = mode_info->size();
283
284 for (size_t i = 0; i < displays.size(); ++i) {
285 const DisplayConfigurator::DisplayState* state = &displays[i];
286 (*requests)[i].mode = display_power[i] ? state->mirror_mode : NULL;
287 }
288 break;
289 }
290 case MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED:
291 case MULTIPLE_DISPLAY_STATE_MULTI_EXTENDED: {
292 if ((new_display_state == MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED &&
293 displays.size() != 2) ||
294 (new_display_state == MULTIPLE_DISPLAY_STATE_MULTI_EXTENDED &&
295 displays.size() <= 2) ||
296 (num_on_displays != 0 &&
297 num_on_displays != static_cast<int>(displays.size()))) {
298 LOG(WARNING) << "Ignoring request to enter extended mode with "
299 << displays.size() << " connected display(s) and "
300 << num_on_displays << " turned on";
301 return false;
302 }
303
304 for (size_t i = 0; i < displays.size(); ++i) {
305 const DisplayConfigurator::DisplayState* state = &displays[i];
306 (*requests)[i].origin.set_y(size.height() ? size.height() + kVerticalGap
307 : 0);
308 (*requests)[i].mode = display_power[i] ? state->selected_mode : NULL;
309
310 // Retain the full screen size even if all displays are off so the
311 // same desktop configuration can be restored when the displays are
312 // turned back on.
313 const DisplayMode* mode_info = displays[i].selected_mode;
314 if (!mode_info) {
315 LOG(WARNING) << "No selected mode when configuring display: "
316 << state->display->ToString();
317 return false;
318 }
319
320 size.set_width(std::max<int>(size.width(), mode_info->size().width()));
321 size.set_height(size.height() + (size.height() ? kVerticalGap : 0) +
322 mode_info->size().height());
323 }
324 break;
325 }
326 }
327
328 *framebuffer_size = size;
329 return true;
330 }
331
332 bool DisplayConfigurator::DisplayLayoutManagerImpl::FindMirrorMode(
333 DisplayState* internal_display,
334 DisplayState* external_display,
335 bool try_panel_fitting,
336 bool preserve_aspect) const {
337 const DisplayMode* internal_native_info =
338 internal_display->display->native_mode();
339 const DisplayMode* external_native_info =
340 external_display->display->native_mode();
341 if (!internal_native_info || !external_native_info)
342 return false;
343
344 // Check if some external display resolution can be mirrored on internal.
345 // Prefer the modes in the order they're present in DisplaySnapshot, assuming
346 // this is the order in which they look better on the monitor.
347 for (DisplayModeList::const_iterator external_it =
348 external_display->display->modes().begin();
349 external_it != external_display->display->modes().end(); ++external_it) {
350 const DisplayMode& external_info = **external_it;
351 bool is_native_aspect_ratio =
352 external_native_info->size().width() * external_info.size().height() ==
353 external_native_info->size().height() * external_info.size().width();
354 if (preserve_aspect && !is_native_aspect_ratio)
355 continue; // Allow only aspect ratio preserving modes for mirroring.
356
357 // Try finding an exact match.
358 for (DisplayModeList::const_iterator internal_it =
359 internal_display->display->modes().begin();
360 internal_it != internal_display->display->modes().end();
361 ++internal_it) {
362 const DisplayMode& internal_info = **internal_it;
363 if (internal_info.size().width() == external_info.size().width() &&
364 internal_info.size().height() == external_info.size().height() &&
365 internal_info.is_interlaced() == external_info.is_interlaced()) {
366 internal_display->mirror_mode = *internal_it;
367 external_display->mirror_mode = *external_it;
368 return true; // Mirror mode found.
369 }
370 }
371
372 // Try to create a matching internal display mode by panel fitting.
373 if (try_panel_fitting) {
374 // We can downscale by 1.125, and upscale indefinitely. Downscaling looks
375 // ugly, so, can fit == can upscale. Also, internal panels don't support
376 // fitting interlaced modes.
377 bool can_fit = internal_native_info->size().width() >=
378 external_info.size().width() &&
379 internal_native_info->size().height() >=
380 external_info.size().height() &&
381 !external_info.is_interlaced();
382 if (can_fit) {
383 configurator_->native_display_delegate_->AddMode(
384 *internal_display->display, *external_it);
385 internal_display->display->add_mode(*external_it);
386 internal_display->mirror_mode = *external_it;
387 external_display->mirror_mode = *external_it;
388 return true; // Mirror mode created.
389 }
390 }
391 }
392
393 return false;
394 }
395
396 ////////////////////////////////////////////////////////////////////////////////
397 // DisplayConfigurator implementation
398
57 // static 399 // static
58 const DisplayMode* DisplayConfigurator::FindDisplayModeMatchingSize( 400 const DisplayMode* DisplayConfigurator::FindDisplayModeMatchingSize(
59 const DisplaySnapshot& display, 401 const DisplaySnapshot& display,
60 const gfx::Size& size) { 402 const gfx::Size& size) {
61 const DisplayMode* best_mode = NULL; 403 const DisplayMode* best_mode = NULL;
62 for (DisplayModeList::const_iterator it = display.modes().begin(); 404 for (DisplayModeList::const_iterator it = display.modes().begin();
63 it != display.modes().end(); 405 it != display.modes().end();
64 ++it) { 406 ++it) {
65 const DisplayMode* mode = *it; 407 const DisplayMode* mode = *it;
66 408
(...skipping 28 matching lines...) Expand all
95 } 437 }
96 438
97 return best_mode; 439 return best_mode;
98 } 440 }
99 441
100 DisplayConfigurator::DisplayConfigurator() 442 DisplayConfigurator::DisplayConfigurator()
101 : state_controller_(NULL), 443 : state_controller_(NULL),
102 mirroring_controller_(NULL), 444 mirroring_controller_(NULL),
103 is_panel_fitting_enabled_(false), 445 is_panel_fitting_enabled_(false),
104 configure_display_(base::SysInfo::IsRunningOnChromeOS()), 446 configure_display_(base::SysInfo::IsRunningOnChromeOS()),
105 display_state_(MULTIPLE_DISPLAY_STATE_INVALID), 447 current_display_state_(MULTIPLE_DISPLAY_STATE_INVALID),
448 current_power_state_(chromeos::DISPLAY_POWER_ALL_ON),
449 requested_display_state_(MULTIPLE_DISPLAY_STATE_INVALID),
106 requested_power_state_(chromeos::DISPLAY_POWER_ALL_ON), 450 requested_power_state_(chromeos::DISPLAY_POWER_ALL_ON),
107 current_power_state_(chromeos::DISPLAY_POWER_ALL_ON), 451 requested_power_state_change_(false),
452 requested_power_flags_(kSetDisplayPowerNoFlags),
453 force_configure_(false),
108 next_display_protection_client_id_(1), 454 next_display_protection_client_id_(1),
109 display_externally_controlled_(false) { 455 display_externally_controlled_(false),
456 layout_manager_(new DisplayLayoutManagerImpl(this)),
457 weak_ptr_factory_(this) {
110 } 458 }
111 459
112 DisplayConfigurator::~DisplayConfigurator() { 460 DisplayConfigurator::~DisplayConfigurator() {
113 if (native_display_delegate_) 461 if (native_display_delegate_)
114 native_display_delegate_->RemoveObserver(this); 462 native_display_delegate_->RemoveObserver(this);
115 } 463 }
116 464
117 void DisplayConfigurator::SetDelegateForTesting( 465 void DisplayConfigurator::SetDelegateForTesting(
118 scoped_ptr<NativeDisplayDelegate> display_delegate) { 466 scoped_ptr<NativeDisplayDelegate> display_delegate) {
119 DCHECK(!native_display_delegate_); 467 DCHECK(!native_display_delegate_);
120 468
121 native_display_delegate_ = display_delegate.Pass(); 469 native_display_delegate_ = display_delegate.Pass();
122 configure_display_ = true; 470 configure_display_ = true;
123 } 471 }
124 472
125 void DisplayConfigurator::SetInitialDisplayPower( 473 void DisplayConfigurator::SetInitialDisplayPower(
126 chromeos::DisplayPowerState power_state) { 474 chromeos::DisplayPowerState power_state) {
127 DCHECK_EQ(display_state_, MULTIPLE_DISPLAY_STATE_INVALID); 475 DCHECK_EQ(current_display_state_, MULTIPLE_DISPLAY_STATE_INVALID);
128 requested_power_state_ = current_power_state_ = power_state; 476 requested_power_state_ = current_power_state_ = power_state;
129 } 477 }
130 478
131 void DisplayConfigurator::Init(bool is_panel_fitting_enabled) { 479 void DisplayConfigurator::Init(bool is_panel_fitting_enabled) {
132 is_panel_fitting_enabled_ = is_panel_fitting_enabled; 480 is_panel_fitting_enabled_ = is_panel_fitting_enabled;
133 if (!configure_display_ || display_externally_controlled_) 481 if (!configure_display_ || display_externally_controlled_)
134 return; 482 return;
135 483
136 // If the delegate is already initialized don't update it (For example, tests 484 // If the delegate is already initialized don't update it (For example, tests
137 // set their own delegates). 485 // set their own delegates).
(...skipping 28 matching lines...) Expand all
166 514
167 display_externally_controlled_ = true; 515 display_externally_controlled_ = true;
168 native_display_delegate_->RelinquishDisplayControl(); 516 native_display_delegate_->RelinquishDisplayControl();
169 } 517 }
170 518
171 void DisplayConfigurator::ForceInitialConfigure( 519 void DisplayConfigurator::ForceInitialConfigure(
172 uint32_t background_color_argb) { 520 uint32_t background_color_argb) {
173 if (!configure_display_ || display_externally_controlled_) 521 if (!configure_display_ || display_externally_controlled_)
174 return; 522 return;
175 523
176 native_display_delegate_->GrabServer();
177 native_display_delegate_->Initialize(); 524 native_display_delegate_->Initialize();
178 525
179 UpdateCachedDisplays(); 526 // ForceInitialConfigure should be the first configuration so there shouldn't
180 if (cached_displays_.size() > 1 && background_color_argb) 527 // be anything scheduled.
181 native_display_delegate_->SetBackgroundColor(background_color_argb); 528 DCHECK(!configuration_task_);
182 const MultipleDisplayState new_state = ChooseDisplayState(
183 requested_power_state_);
184 const bool success = EnterStateOrFallBackToSoftwareMirroring(
185 new_state, requested_power_state_);
186 529
187 // Force the DPMS on chrome startup as the driver doesn't always detect 530 configuration_task_.reset(new UpdateDisplayConfigurationTask(
188 // that all displays are on when signing out. 531 native_display_delegate_.get(), layout_manager_.get(),
189 native_display_delegate_->ForceDPMSOn(); 532 requested_display_state_, requested_power_state_,
190 native_display_delegate_->UngrabServer(); 533 kSetDisplayPowerForceProbe, background_color_argb, true,
191 NotifyObservers(success, new_state); 534 base::Bind(&DisplayConfigurator::OnConfigured,
535 weak_ptr_factory_.GetWeakPtr())));
536 configuration_task_->Run();
192 } 537 }
193 538
194 bool DisplayConfigurator::IsMirroring() const { 539 bool DisplayConfigurator::IsMirroring() const {
195 return display_state_ == MULTIPLE_DISPLAY_STATE_DUAL_MIRROR || 540 return current_display_state_ == MULTIPLE_DISPLAY_STATE_DUAL_MIRROR ||
196 (mirroring_controller_ && 541 (mirroring_controller_ &&
197 mirroring_controller_->SoftwareMirroringEnabled()); 542 mirroring_controller_->SoftwareMirroringEnabled());
198 } 543 }
199 544
200 bool DisplayConfigurator::ApplyProtections(const ContentProtections& requests) { 545 bool DisplayConfigurator::ApplyProtections(const ContentProtections& requests) {
201 for (DisplayStateList::const_iterator it = cached_displays_.begin(); 546 for (DisplayStateList::const_iterator it = cached_displays_.begin();
202 it != cached_displays_.end(); 547 it != cached_displays_.end();
203 ++it) { 548 ++it) {
204 uint32_t all_desired = 0; 549 uint32_t all_desired = 0;
205 550
206 // In mirror mode, protection request of all displays need to be fulfilled. 551 // In mirror mode, protection request of all displays need to be fulfilled.
207 // In non-mirror mode, only request of client's display needs to be 552 // In non-mirror mode, only request of client's display needs to be
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
409 } 754 }
410 } 755 }
411 756
412 return false; 757 return false;
413 } 758 }
414 759
415 void DisplayConfigurator::PrepareForExit() { 760 void DisplayConfigurator::PrepareForExit() {
416 configure_display_ = false; 761 configure_display_ = false;
417 } 762 }
418 763
419 bool DisplayConfigurator::SetDisplayPower( 764 void DisplayConfigurator::SetDisplayPower(
420 chromeos::DisplayPowerState power_state, 765 chromeos::DisplayPowerState power_state,
421 int flags) { 766 int flags) {
422 if (!configure_display_ || display_externally_controlled_) 767 if (!configure_display_ || display_externally_controlled_)
423 return false; 768 return;
424 769
425 VLOG(1) << "SetDisplayPower: power_state=" 770 VLOG(1) << "SetDisplayPower: power_state="
426 << DisplayPowerStateToString(power_state) << " flags=" << flags 771 << DisplayPowerStateToString(power_state) << " flags=" << flags
427 << ", configure timer=" 772 << ", configure timer="
428 << (configure_timer_.IsRunning() ? "Running" : "Stopped"); 773 << (configure_timer_.IsRunning() ? "Running" : "Stopped");
429 if (power_state == current_power_state_ && 774 if (power_state == requested_power_state_ &&
430 !(flags & kSetDisplayPowerForceProbe)) 775 !(flags & kSetDisplayPowerForceProbe))
431 return true; 776 return;
432 777
433 native_display_delegate_->GrabServer(); 778 requested_power_state_ = power_state;
434 UpdateCachedDisplays(); 779 requested_power_state_change_ = true;
780 requested_power_flags_ = flags;
435 781
436 const MultipleDisplayState new_state = ChooseDisplayState(power_state); 782 RunPendingConfiguration();
437 bool attempted_change = false;
438 bool success = false;
439
440 bool only_if_single_internal_display =
441 flags & kSetDisplayPowerOnlyIfSingleInternalDisplay;
442 bool single_internal_display =
443 cached_displays_.size() == 1 &&
444 cached_displays_[0].display->type() == DISPLAY_CONNECTION_TYPE_INTERNAL;
445 if (single_internal_display || !only_if_single_internal_display) {
446 success = EnterStateOrFallBackToSoftwareMirroring(new_state, power_state);
447 attempted_change = true;
448
449 // Force the DPMS on since the driver doesn't always detect that it
450 // should turn on. This is needed when coming back from idle suspend.
451 if (success && power_state != chromeos::DISPLAY_POWER_ALL_OFF)
452 native_display_delegate_->ForceDPMSOn();
453 }
454
455 native_display_delegate_->UngrabServer();
456 if (attempted_change)
457 NotifyObservers(success, new_state);
458 return success;
459 } 783 }
460 784
461 bool DisplayConfigurator::SetDisplayMode(MultipleDisplayState new_state) { 785 void DisplayConfigurator::SetDisplayMode(MultipleDisplayState new_state) {
462 if (!configure_display_ || display_externally_controlled_) 786 if (!configure_display_ || display_externally_controlled_)
463 return false; 787 return;
464 788
465 VLOG(1) << "SetDisplayMode: state=" 789 VLOG(1) << "SetDisplayMode: state="
466 << MultipleDisplayStateToString(new_state); 790 << MultipleDisplayStateToString(new_state);
467 if (display_state_ == new_state) { 791 if (current_display_state_ == new_state) {
468 // Cancel software mirroring if the state is moving from 792 // Cancel software mirroring if the state is moving from
469 // MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED to 793 // MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED to
470 // MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED. 794 // MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED.
471 if (mirroring_controller_ && 795 if (mirroring_controller_ &&
472 new_state == MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED) 796 new_state == MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED)
473 mirroring_controller_->SetSoftwareMirroring(false); 797 mirroring_controller_->SetSoftwareMirroring(false);
474 NotifyObservers(true, new_state); 798 NotifyObservers(true, new_state);
475 return true; 799 return;
476 } 800 }
477 801
478 native_display_delegate_->GrabServer(); 802 requested_display_state_ = new_state;
479 UpdateCachedDisplays();
480 const bool success = EnterStateOrFallBackToSoftwareMirroring(
481 new_state, requested_power_state_);
482 native_display_delegate_->UngrabServer();
483 803
484 NotifyObservers(success, new_state); 804 RunPendingConfiguration();
485 return success;
486 } 805 }
487 806
488 void DisplayConfigurator::OnConfigurationChanged() { 807 void DisplayConfigurator::OnConfigurationChanged() {
489 // Configure displays with |kConfigureDelayMs| delay, 808 // Configure displays with |kConfigureDelayMs| delay,
490 // so that time-consuming ConfigureDisplays() won't be called multiple times. 809 // so that time-consuming ConfigureDisplays() won't be called multiple times.
491 if (configure_timer_.IsRunning()) { 810 if (configure_timer_.IsRunning()) {
492 // Note: when the timer is running it is possible that a different task 811 // Note: when the timer is running it is possible that a different task
493 // (RestoreRequestedPowerStateAfterResume()) is scheduled. In these cases, 812 // (RestoreRequestedPowerStateAfterResume()) is scheduled. In these cases,
494 // prefer the already scheduled task to ConfigureDisplays() since 813 // prefer the already scheduled task to ConfigureDisplays() since
495 // ConfigureDisplays() performs only basic configuration while 814 // ConfigureDisplays() performs only basic configuration while
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
531 } 850 }
532 851
533 void DisplayConfigurator::ResumeDisplays() { 852 void DisplayConfigurator::ResumeDisplays() {
534 configure_timer_.Start( 853 configure_timer_.Start(
535 FROM_HERE, 854 FROM_HERE,
536 base::TimeDelta::FromMilliseconds(kResumeDelayMs), 855 base::TimeDelta::FromMilliseconds(kResumeDelayMs),
537 base::Bind(&DisplayConfigurator::RestoreRequestedPowerStateAfterResume, 856 base::Bind(&DisplayConfigurator::RestoreRequestedPowerStateAfterResume,
538 base::Unretained(this))); 857 base::Unretained(this)));
539 } 858 }
540 859
541 void DisplayConfigurator::UpdateCachedDisplays() {
542 std::vector<DisplaySnapshot*> snapshots =
543 native_display_delegate_->GetDisplays();
544
545 cached_displays_.clear();
546 for (size_t i = 0; i < snapshots.size(); ++i) {
547 DisplayState display_state;
548 display_state.display = snapshots[i];
549 cached_displays_.push_back(display_state);
550 }
551
552 // Set |selected_mode| fields.
553 for (size_t i = 0; i < cached_displays_.size(); ++i) {
554 DisplayState* display_state = &cached_displays_[i];
555 gfx::Size size;
556 if (state_controller_ &&
557 state_controller_->GetResolutionForDisplayId(
558 display_state->display->display_id(), &size)) {
559 display_state->selected_mode =
560 FindDisplayModeMatchingSize(*display_state->display, size);
561 }
562
563 // Fall back to native mode.
564 if (!display_state->selected_mode)
565 display_state->selected_mode = display_state->display->native_mode();
566 }
567
568 // Set |mirror_mode| fields.
569 if (cached_displays_.size() == 2) {
570 bool one_is_internal =
571 cached_displays_[0].display->type() == DISPLAY_CONNECTION_TYPE_INTERNAL;
572 bool two_is_internal =
573 cached_displays_[1].display->type() == DISPLAY_CONNECTION_TYPE_INTERNAL;
574 int internal_displays =
575 (one_is_internal ? 1 : 0) + (two_is_internal ? 1 : 0);
576 DCHECK_LT(internal_displays, 2);
577 LOG_IF(WARNING, internal_displays == 2)
578 << "Two internal displays detected.";
579
580 bool can_mirror = false;
581 for (int attempt = 0; !can_mirror && attempt < 2; ++attempt) {
582 // Try preserving external display's aspect ratio on the first attempt.
583 // If that fails, fall back to the highest matching resolution.
584 bool preserve_aspect = attempt == 0;
585
586 if (internal_displays == 1) {
587 if (one_is_internal) {
588 can_mirror = FindMirrorMode(&cached_displays_[0],
589 &cached_displays_[1],
590 is_panel_fitting_enabled_,
591 preserve_aspect);
592 } else {
593 DCHECK(two_is_internal);
594 can_mirror = FindMirrorMode(&cached_displays_[1],
595 &cached_displays_[0],
596 is_panel_fitting_enabled_,
597 preserve_aspect);
598 }
599 } else { // if (internal_displays == 0)
600 // No panel fitting for external displays, so fall back to exact match.
601 can_mirror = FindMirrorMode(
602 &cached_displays_[0], &cached_displays_[1], false, preserve_aspect);
603 if (!can_mirror && preserve_aspect) {
604 // FindMirrorMode() will try to preserve aspect ratio of what it
605 // thinks is external display, so if it didn't succeed with one, maybe
606 // it will succeed with the other. This way we will have the correct
607 // aspect ratio on at least one of them.
608 can_mirror = FindMirrorMode(&cached_displays_[1],
609 &cached_displays_[0],
610 false,
611 preserve_aspect);
612 }
613 }
614 }
615 }
616 }
617
618 bool DisplayConfigurator::FindMirrorMode(DisplayState* internal_display,
619 DisplayState* external_display,
620 bool try_panel_fitting,
621 bool preserve_aspect) {
622 const DisplayMode* internal_native_info =
623 internal_display->display->native_mode();
624 const DisplayMode* external_native_info =
625 external_display->display->native_mode();
626 if (!internal_native_info || !external_native_info)
627 return false;
628
629 // Check if some external display resolution can be mirrored on internal.
630 // Prefer the modes in the order they're present in DisplaySnapshot, assuming
631 // this is the order in which they look better on the monitor.
632 for (DisplayModeList::const_iterator external_it =
633 external_display->display->modes().begin();
634 external_it != external_display->display->modes().end();
635 ++external_it) {
636 const DisplayMode& external_info = **external_it;
637 bool is_native_aspect_ratio =
638 external_native_info->size().width() * external_info.size().height() ==
639 external_native_info->size().height() * external_info.size().width();
640 if (preserve_aspect && !is_native_aspect_ratio)
641 continue; // Allow only aspect ratio preserving modes for mirroring.
642
643 // Try finding an exact match.
644 for (DisplayModeList::const_iterator internal_it =
645 internal_display->display->modes().begin();
646 internal_it != internal_display->display->modes().end();
647 ++internal_it) {
648 const DisplayMode& internal_info = **internal_it;
649 if (internal_info.size().width() == external_info.size().width() &&
650 internal_info.size().height() == external_info.size().height() &&
651 internal_info.is_interlaced() == external_info.is_interlaced()) {
652 internal_display->mirror_mode = *internal_it;
653 external_display->mirror_mode = *external_it;
654 return true; // Mirror mode found.
655 }
656 }
657
658 // Try to create a matching internal display mode by panel fitting.
659 if (try_panel_fitting) {
660 // We can downscale by 1.125, and upscale indefinitely. Downscaling looks
661 // ugly, so, can fit == can upscale. Also, internal panels don't support
662 // fitting interlaced modes.
663 bool can_fit = internal_native_info->size().width() >=
664 external_info.size().width() &&
665 internal_native_info->size().height() >=
666 external_info.size().height() &&
667 !external_info.is_interlaced();
668 if (can_fit) {
669 native_display_delegate_->AddMode(*internal_display->display,
670 *external_it);
671 internal_display->display->add_mode(*external_it);
672 internal_display->mirror_mode = *external_it;
673 external_display->mirror_mode = *external_it;
674 return true; // Mirror mode created.
675 }
676 }
677 }
678
679 return false;
680 }
681
682 void DisplayConfigurator::ConfigureDisplays() { 860 void DisplayConfigurator::ConfigureDisplays() {
683 if (!configure_display_ || display_externally_controlled_) 861 if (!configure_display_ || display_externally_controlled_)
684 return; 862 return;
685 863
686 native_display_delegate_->GrabServer(); 864 force_configure_ = true;
687 UpdateCachedDisplays(); 865 RunPendingConfiguration();
688 const MultipleDisplayState new_state = ChooseDisplayState( 866 }
689 requested_power_state_);
690 const bool success = EnterStateOrFallBackToSoftwareMirroring(
691 new_state, requested_power_state_);
692 native_display_delegate_->UngrabServer();
693 867
694 NotifyObservers(success, new_state); 868 void DisplayConfigurator::RunPendingConfiguration() {
869 // Configuration task is currently running. Do not start a second
870 // configuration.
871 if (configuration_task_)
872 return;
873
874 if (!ShouldRunConfigurationTask()) {
875 LOG(ERROR) << "Called RunPendingConfiguration without any changes"
876 " requested";
877 return;
878 }
879
880 configuration_task_.reset(new UpdateDisplayConfigurationTask(
881 native_display_delegate_.get(), layout_manager_.get(),
882 requested_display_state_, requested_power_state_, requested_power_flags_,
883 0, force_configure_, base::Bind(&DisplayConfigurator::OnConfigured,
884 weak_ptr_factory_.GetWeakPtr())));
885
886 // Reset the flags before running the task; otherwise it may end up scheduling
887 // another configuration.
888 force_configure_ = false;
889 requested_power_flags_ = kSetDisplayPowerNoFlags;
890 requested_power_state_change_ = false;
891 requested_display_state_ = MULTIPLE_DISPLAY_STATE_INVALID;
892
893 configuration_task_->Run();
894 }
895
896 void DisplayConfigurator::OnConfigured(
897 bool success,
898 const std::vector<DisplayState>& displays,
899 const gfx::Size& framebuffer_size,
900 MultipleDisplayState new_display_state,
901 chromeos::DisplayPowerState new_power_state) {
902 VLOG(1) << "OnConfigured: success=" << success << " new_display_state="
903 << MultipleDisplayStateToString(new_display_state)
904 << " new_power_state=" << DisplayPowerStateToString(new_power_state);
905
906 cached_displays_ = displays;
907 if (success) {
908 current_display_state_ = new_display_state;
909 current_power_state_ = new_power_state;
910 framebuffer_size_ = framebuffer_size;
911 // If the requested power state hasn't changed then make sure that value
912 // gets updated as well since the last requested value may have been
913 // dependent on certain conditions (ie: if only the internal monitor was
914 // present).
915 if (!requested_power_state_change_)
916 requested_power_state_ = new_power_state;
917 }
918
919 configuration_task_.reset();
920 NotifyObservers(success, new_display_state);
921
922 if (success && !configure_timer_.IsRunning() &&
923 ShouldRunConfigurationTask()) {
924 configure_timer_.Start(FROM_HERE,
925 base::TimeDelta::FromMilliseconds(kConfigureDelayMs),
926 this, &DisplayConfigurator::RunPendingConfiguration);
927 }
928 }
929
930 bool DisplayConfigurator::ShouldRunConfigurationTask() const {
931 if (force_configure_)
932 return true;
933
934 // Schedule if there is a request to change the display state.
935 if (requested_display_state_ != current_display_state_ &&
936 requested_display_state_ != MULTIPLE_DISPLAY_STATE_INVALID)
937 return true;
938
939 // Schedule if there is a request to change the power state.
940 if (requested_power_state_change_)
941 return true;
942
943 return false;
695 } 944 }
696 945
697 void DisplayConfigurator::RestoreRequestedPowerStateAfterResume() { 946 void DisplayConfigurator::RestoreRequestedPowerStateAfterResume() {
698 // Force probing to ensure that we pick up any changes that were made while 947 // Force probing to ensure that we pick up any changes that were made while
699 // the system was suspended. 948 // the system was suspended.
700 SetDisplayPower(requested_power_state_, kSetDisplayPowerForceProbe); 949 SetDisplayPower(requested_power_state_, kSetDisplayPowerForceProbe);
701 } 950 }
702 951
703 void DisplayConfigurator::NotifyObservers( 952 void DisplayConfigurator::NotifyObservers(
704 bool success, 953 bool success,
705 MultipleDisplayState attempted_state) { 954 MultipleDisplayState attempted_state) {
706 if (success) { 955 if (success) {
707 FOR_EACH_OBSERVER( 956 FOR_EACH_OBSERVER(
708 Observer, observers_, OnDisplayModeChanged(cached_displays_)); 957 Observer, observers_, OnDisplayModeChanged(cached_displays_));
709 } else { 958 } else {
710 FOR_EACH_OBSERVER( 959 FOR_EACH_OBSERVER(
711 Observer, observers_, OnDisplayModeChangeFailed(attempted_state)); 960 Observer, observers_, OnDisplayModeChangeFailed(attempted_state));
712 } 961 }
713 } 962 }
714 963
715 bool DisplayConfigurator::EnterStateOrFallBackToSoftwareMirroring(
716 MultipleDisplayState display_state,
717 chromeos::DisplayPowerState power_state) {
718 bool success = EnterState(display_state, power_state);
719 if (mirroring_controller_) {
720 bool enable_software_mirroring = false;
721 if (!success && display_state == MULTIPLE_DISPLAY_STATE_DUAL_MIRROR) {
722 if (display_state_ != MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED ||
723 current_power_state_ != power_state)
724 EnterState(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED, power_state);
725 enable_software_mirroring = success =
726 display_state_ == MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED;
727 }
728 mirroring_controller_->SetSoftwareMirroring(enable_software_mirroring);
729 }
730 return success;
731 }
732
733 bool DisplayConfigurator::EnterState(MultipleDisplayState display_state,
734 chromeos::DisplayPowerState power_state) {
735 std::vector<bool> display_power;
736 int num_on_displays =
737 GetDisplayPower(cached_displays_, power_state, &display_power);
738 VLOG(1) << "EnterState: display="
739 << MultipleDisplayStateToString(display_state)
740 << " power=" << DisplayPowerStateToString(power_state);
741
742 // Save the requested state so we'll try to use it next time even if we fail.
743 requested_power_state_ = power_state;
744
745 // Framebuffer dimensions.
746 gfx::Size size;
747
748 std::vector<gfx::Point> new_origins(cached_displays_.size(), gfx::Point());
749 std::vector<const DisplayMode*> new_mode;
750 for (size_t i = 0; i < cached_displays_.size(); ++i)
751 new_mode.push_back(cached_displays_[i].display->current_mode());
752
753 switch (display_state) {
754 case MULTIPLE_DISPLAY_STATE_INVALID:
755 NOTREACHED() << "Ignoring request to enter invalid state with "
756 << cached_displays_.size() << " connected display(s)";
757 return false;
758 case MULTIPLE_DISPLAY_STATE_HEADLESS:
759 if (cached_displays_.size() != 0) {
760 LOG(WARNING) << "Ignoring request to enter headless mode with "
761 << cached_displays_.size() << " connected display(s)";
762 return false;
763 }
764 break;
765 case MULTIPLE_DISPLAY_STATE_SINGLE: {
766 // If there are multiple displays connected, only one should be turned on.
767 if (cached_displays_.size() != 1 && num_on_displays != 1) {
768 LOG(WARNING) << "Ignoring request to enter single mode with "
769 << cached_displays_.size() << " connected displays and "
770 << num_on_displays << " turned on";
771 return false;
772 }
773
774 for (size_t i = 0; i < cached_displays_.size(); ++i) {
775 DisplayState* state = &cached_displays_[i];
776 new_mode[i] = display_power[i] ? state->selected_mode : NULL;
777
778 if (display_power[i] || cached_displays_.size() == 1) {
779 const DisplayMode* mode_info = state->selected_mode;
780 if (!mode_info) {
781 LOG(WARNING) << "No selected mode when configuring display: "
782 << state->display->ToString();
783 return false;
784 }
785 if (mode_info->size() == gfx::Size(1024, 768)) {
786 VLOG(1) << "Potentially misdetecting display(1024x768):"
787 << " displays size=" << cached_displays_.size()
788 << ", num_on_displays=" << num_on_displays
789 << ", current size:" << size.width() << "x" << size.height()
790 << ", i=" << i << ", display=" << state->display->ToString()
791 << ", display_mode=" << mode_info->ToString();
792 }
793 size = mode_info->size();
794 }
795 }
796 break;
797 }
798 case MULTIPLE_DISPLAY_STATE_DUAL_MIRROR: {
799 if (cached_displays_.size() != 2 ||
800 (num_on_displays != 0 && num_on_displays != 2)) {
801 LOG(WARNING) << "Ignoring request to enter mirrored mode with "
802 << cached_displays_.size() << " connected display(s) and "
803 << num_on_displays << " turned on";
804 return false;
805 }
806
807 const DisplayMode* mode_info = cached_displays_[0].mirror_mode;
808 if (!mode_info) {
809 LOG(WARNING) << "No mirror mode when configuring display: "
810 << cached_displays_[0].display->ToString();
811 return false;
812 }
813 size = mode_info->size();
814
815 for (size_t i = 0; i < cached_displays_.size(); ++i) {
816 DisplayState* state = &cached_displays_[i];
817 new_mode[i] = display_power[i] ? state->mirror_mode : NULL;
818 }
819 break;
820 }
821 case MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED:
822 case MULTIPLE_DISPLAY_STATE_MULTI_EXTENDED: {
823 if ((display_state == MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED &&
824 cached_displays_.size() != 2) ||
825 (display_state == MULTIPLE_DISPLAY_STATE_MULTI_EXTENDED &&
826 cached_displays_.size() <= 2) ||
827 (num_on_displays != 0 &&
828 num_on_displays != static_cast<int>(cached_displays_.size()))) {
829 LOG(WARNING) << "Ignoring request to enter extended mode with "
830 << cached_displays_.size() << " connected display(s) and "
831 << num_on_displays << " turned on";
832 return false;
833 }
834
835 for (size_t i = 0; i < cached_displays_.size(); ++i) {
836 DisplayState* state = &cached_displays_[i];
837 new_origins[i].set_y(size.height() ? size.height() + kVerticalGap : 0);
838 new_mode[i] = display_power[i] ? state->selected_mode : NULL;
839
840 // Retain the full screen size even if all displays are off so the
841 // same desktop configuration can be restored when the displays are
842 // turned back on.
843 const DisplayMode* mode_info = cached_displays_[i].selected_mode;
844 if (!mode_info) {
845 LOG(WARNING) << "No selected mode when configuring display: "
846 << state->display->ToString();
847 return false;
848 }
849
850 size.set_width(std::max<int>(size.width(), mode_info->size().width()));
851 size.set_height(size.height() + (size.height() ? kVerticalGap : 0) +
852 mode_info->size().height());
853 }
854 break;
855 }
856 }
857
858 // Finally, apply the desired changes.
859 bool all_succeeded = true;
860 if (!cached_displays_.empty()) {
861 native_display_delegate_->CreateFrameBuffer(size);
862 for (size_t i = 0; i < cached_displays_.size(); ++i) {
863 const DisplayState& state = cached_displays_[i];
864 bool configure_succeeded = false;
865
866 while (true) {
867 if (native_display_delegate_->Configure(
868 *state.display, new_mode[i], new_origins[i])) {
869 state.display->set_current_mode(new_mode[i]);
870 state.display->set_origin(new_origins[i]);
871
872 configure_succeeded = true;
873 break;
874 }
875
876 const DisplayMode* mode_info = new_mode[i];
877 if (!mode_info)
878 break;
879
880 // Find the mode with the next-best resolution and see if that can
881 // be set.
882 int best_mode_pixels = 0;
883
884 int current_mode_pixels = mode_info->size().GetArea();
885 for (DisplayModeList::const_iterator it =
886 state.display->modes().begin();
887 it != state.display->modes().end();
888 it++) {
889 int pixel_count = (*it)->size().GetArea();
890 if ((pixel_count < current_mode_pixels) &&
891 (pixel_count > best_mode_pixels)) {
892 new_mode[i] = *it;
893 best_mode_pixels = pixel_count;
894 }
895 }
896
897 if (best_mode_pixels == 0)
898 break;
899 }
900
901 if (!configure_succeeded)
902 all_succeeded = false;
903
904 // If we are trying to set mirror mode and one of the modesets fails,
905 // then the two monitors will be mis-matched. In this case, return
906 // false to let the observers be aware.
907 if (display_state == MULTIPLE_DISPLAY_STATE_DUAL_MIRROR &&
908 display_power[i] &&
909 state.display->current_mode() != state.mirror_mode)
910 all_succeeded = false;
911 }
912 }
913
914 if (all_succeeded) {
915 display_state_ = display_state;
916 current_power_state_ = power_state;
917 framebuffer_size_ = size;
918 }
919 return all_succeeded;
920 }
921
922 MultipleDisplayState DisplayConfigurator::ChooseDisplayState(
923 chromeos::DisplayPowerState power_state) const {
924 int num_on_displays = GetDisplayPower(cached_displays_, power_state, NULL);
925 switch (cached_displays_.size()) {
926 case 0:
927 return MULTIPLE_DISPLAY_STATE_HEADLESS;
928 case 1:
929 return MULTIPLE_DISPLAY_STATE_SINGLE;
930 default: {
931 if (num_on_displays == 1) {
932 // If only one display is currently turned on, return the "single"
933 // state so that its native mode will be used.
934 return MULTIPLE_DISPLAY_STATE_SINGLE;
935 } if (num_on_displays >= 3) {
936 return MULTIPLE_DISPLAY_STATE_MULTI_EXTENDED;
937 } else if (cached_displays_.size() == 2) {
938 if (!state_controller_)
939 return MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED;
940 // With either both displays on or both displays off, use one of the
941 // dual modes.
942 std::vector<int64_t> display_ids;
943 for (size_t i = 0; i < cached_displays_.size(); ++i)
944 display_ids.push_back(cached_displays_[i].display->display_id());
945
946 return state_controller_->GetStateForDisplayIds(display_ids);
947 }
948 NOTREACHED();
949 }
950 }
951 return MULTIPLE_DISPLAY_STATE_INVALID;
952 }
953
954 } // namespace ui 964 } // namespace ui
OLDNEW
« no previous file with comments | « ui/display/chromeos/display_configurator.h ('k') | ui/display/chromeos/display_configurator_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698