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

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

Issue 187073002: Refactoring display configuration state to allow generic state objects (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebased Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/output_configurator.h" 5 #include "ui/display/chromeos/output_configurator.h"
6 6
7 #include <X11/Xlib.h>
8 #include <X11/extensions/Xrandr.h>
9
10 #include "base/bind.h" 7 #include "base/bind.h"
11 #include "base/logging.h" 8 #include "base/logging.h"
12 #include "base/strings/string_number_conversions.h" 9 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/stringprintf.h" 10 #include "base/strings/stringprintf.h"
14 #include "base/sys_info.h" 11 #include "base/sys_info.h"
15 #include "base/time/time.h" 12 #include "base/time/time.h"
16 #include "ui/display/chromeos/x11/display_util.h" 13 #include "ui/display/chromeos/display_mode.h"
14 #include "ui/display/chromeos/display_snapshot.h"
17 #include "ui/display/chromeos/x11/native_display_delegate_x11.h" 15 #include "ui/display/chromeos/x11/native_display_delegate_x11.h"
18 #include "ui/display/chromeos/x11/touchscreen_delegate_x11.h" 16 #include "ui/display/chromeos/x11/touchscreen_delegate_x11.h"
19 17
20 namespace ui { 18 namespace ui {
21 19
22 namespace { 20 namespace {
23 21
22 typedef std::vector<const DisplayMode*> DisplayModeList;
23
24 // The delay to perform configuration after RRNotify. See the comment 24 // The delay to perform configuration after RRNotify. See the comment
25 // in |Dispatch()|. 25 // in |Dispatch()|.
26 const int64 kConfigureDelayMs = 500; 26 const int64 kConfigureDelayMs = 500;
27 27
28 // Returns a string describing |state|. 28 // Returns a string describing |state|.
29 std::string DisplayPowerStateToString(chromeos::DisplayPowerState state) { 29 std::string DisplayPowerStateToString(chromeos::DisplayPowerState state) {
30 switch (state) { 30 switch (state) {
31 case chromeos::DISPLAY_POWER_ALL_ON: 31 case chromeos::DISPLAY_POWER_ALL_ON:
32 return "ALL_ON"; 32 return "ALL_ON";
33 case chromeos::DISPLAY_POWER_ALL_OFF: 33 case chromeos::DISPLAY_POWER_ALL_OFF:
(...skipping 18 matching lines...) Expand all
52 return "SINGLE"; 52 return "SINGLE";
53 case OUTPUT_STATE_DUAL_MIRROR: 53 case OUTPUT_STATE_DUAL_MIRROR:
54 return "DUAL_MIRROR"; 54 return "DUAL_MIRROR";
55 case OUTPUT_STATE_DUAL_EXTENDED: 55 case OUTPUT_STATE_DUAL_EXTENDED:
56 return "DUAL_EXTENDED"; 56 return "DUAL_EXTENDED";
57 } 57 }
58 NOTREACHED() << "Unknown state " << state; 58 NOTREACHED() << "Unknown state " << state;
59 return "INVALID"; 59 return "INVALID";
60 } 60 }
61 61
62 // Returns a string representation of OutputSnapshot. 62 // Returns a string representation of DisplayMode.
63 std::string OutputSnapshotToString( 63 // TODO(dnicoara) Move this to DisplayMode.
64 const OutputConfigurator::OutputSnapshot* output) { 64 std::string DisplayModeToString(const DisplayMode* mode) {
65 return base::StringPrintf(
66 "[type=%d, output=%ld, crtc=%ld, mode=%ld, dim=%dx%d]",
67 output->type,
68 output->output,
69 output->crtc,
70 output->current_mode,
71 static_cast<int>(output->width_mm),
72 static_cast<int>(output->height_mm));
73 }
74
75 // Returns a string representation of ModeInfo.
76 std::string ModeInfoToString(const OutputConfigurator::ModeInfo* mode) {
77 return base::StringPrintf("[%dx%d %srate=%f]", 65 return base::StringPrintf("[%dx%d %srate=%f]",
78 mode->width, 66 mode->size().width(),
79 mode->height, 67 mode->size().height(),
80 mode->interlaced ? "interlaced " : "", 68 mode->is_interlaced() ? "interlaced " : "",
81 mode->refresh_rate); 69 mode->refresh_rate());
82 } 70 }
83 71
84 // Returns the number of outputs in |outputs| that should be turned on, per 72 // Returns the number of outputs in |outputs| that should be turned on, per
85 // |state|. If |output_power| is non-NULL, it is updated to contain the 73 // |state|. If |output_power| is non-NULL, it is updated to contain the
86 // on/off state of each corresponding entry in |outputs|. 74 // on/off state of each corresponding entry in |outputs|.
87 int GetOutputPower( 75 int GetOutputPower(const std::vector<OutputConfigurator::DisplayState>& outputs,
88 const std::vector<OutputConfigurator::OutputSnapshot>& outputs, 76 chromeos::DisplayPowerState state,
89 chromeos::DisplayPowerState state, 77 std::vector<bool>* output_power) {
90 std::vector<bool>* output_power) {
91 int num_on_outputs = 0; 78 int num_on_outputs = 0;
92 if (output_power) 79 if (output_power)
93 output_power->resize(outputs.size()); 80 output_power->resize(outputs.size());
94 81
95 for (size_t i = 0; i < outputs.size(); ++i) { 82 for (size_t i = 0; i < outputs.size(); ++i) {
96 bool internal = outputs[i].type == OUTPUT_TYPE_INTERNAL; 83 bool internal = outputs[i].display->type() == OUTPUT_TYPE_INTERNAL;
97 bool on = 84 bool on =
98 state == chromeos::DISPLAY_POWER_ALL_ON || 85 state == chromeos::DISPLAY_POWER_ALL_ON ||
99 (state == chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON && 86 (state == chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON &&
100 !internal) || 87 !internal) ||
101 (state == chromeos::DISPLAY_POWER_INTERNAL_ON_EXTERNAL_OFF && internal); 88 (state == chromeos::DISPLAY_POWER_INTERNAL_ON_EXTERNAL_OFF && internal);
102 if (output_power) 89 if (output_power)
103 (*output_power)[i] = on; 90 (*output_power)[i] = on;
104 if (on) 91 if (on)
105 num_on_outputs++; 92 num_on_outputs++;
106 } 93 }
107 return num_on_outputs; 94 return num_on_outputs;
108 } 95 }
109 96
110 } // namespace 97 } // namespace
111 98
112 OutputConfigurator::ModeInfo::ModeInfo()
113 : width(0),
114 height(0),
115 interlaced(false),
116 refresh_rate(0.0) {}
117
118 OutputConfigurator::ModeInfo::ModeInfo(int width,
119 int height,
120 bool interlaced,
121 float refresh_rate)
122 : width(width),
123 height(height),
124 interlaced(interlaced),
125 refresh_rate(refresh_rate) {}
126
127 OutputConfigurator::CoordinateTransformation::CoordinateTransformation() 99 OutputConfigurator::CoordinateTransformation::CoordinateTransformation()
128 : x_scale(1.0), 100 : x_scale(1.0),
129 x_offset(0.0), 101 x_offset(0.0),
130 y_scale(1.0), 102 y_scale(1.0),
131 y_offset(0.0) {} 103 y_offset(0.0) {}
132 104
133 OutputConfigurator::OutputSnapshot::OutputSnapshot() 105 OutputConfigurator::DisplayState::DisplayState()
134 : output(None), 106 : display(NULL),
135 crtc(None),
136 current_mode(None),
137 native_mode(None),
138 mirror_mode(None),
139 selected_mode(None),
140 x(0),
141 y(0),
142 width_mm(0),
143 height_mm(0),
144 is_aspect_preserving_scaling(false),
145 type(OUTPUT_TYPE_UNKNOWN),
146 touch_device_id(0), 107 touch_device_id(0),
147 display_id(0), 108 selected_mode(NULL),
148 has_display_id(false), 109 mirror_mode(NULL) {}
149 index(0) {}
150
151 OutputConfigurator::OutputSnapshot::~OutputSnapshot() {}
152 110
153 bool OutputConfigurator::TestApi::TriggerConfigureTimeout() { 111 bool OutputConfigurator::TestApi::TriggerConfigureTimeout() {
154 if (configurator_->configure_timer_.get() && 112 if (configurator_->configure_timer_.get() &&
155 configurator_->configure_timer_->IsRunning()) { 113 configurator_->configure_timer_->IsRunning()) {
156 configurator_->configure_timer_.reset(); 114 configurator_->configure_timer_.reset();
157 configurator_->ConfigureOutputs(); 115 configurator_->ConfigureOutputs();
158 return true; 116 return true;
159 } else { 117 } else {
160 return false; 118 return false;
161 } 119 }
162 } 120 }
163 121
164 // static 122 // static
165 const OutputConfigurator::ModeInfo* OutputConfigurator::GetModeInfo( 123 const DisplayMode* OutputConfigurator::FindDisplayModeMatchingSize(
166 const OutputSnapshot& output, 124 const DisplaySnapshot& output,
167 RRMode mode) { 125 const gfx::Size& size) {
168 if (mode == None) 126 const DisplayMode* best_mode = NULL;
169 return NULL; 127 for (DisplayModeList::const_iterator it = output.modes().begin();
128 it != output.modes().end();
129 ++it) {
130 const DisplayMode* mode = *it;
170 131
171 ModeInfoMap::const_iterator it = output.mode_infos.find(mode); 132 if (mode->size() != size)
172 if (it == output.mode_infos.end()) { 133 continue;
173 LOG(WARNING) << "Unable to find info about mode " << mode << " for output " 134
174 << output.output; 135 if (!best_mode) {
175 return NULL; 136 best_mode = mode;
137 continue;
138 }
139
140 if (mode->is_interlaced()) {
141 if (!best_mode->is_interlaced())
142 continue;
143 } else {
144 // Reset the best rate if the non interlaced is
145 // found the first time.
146 if (best_mode->is_interlaced()) {
147 best_mode = mode;
148 continue;
149 }
150 }
151 if (mode->refresh_rate() < best_mode->refresh_rate())
152 continue;
153
154 best_mode = mode;
176 } 155 }
177 return &it->second;
178 }
179 156
180 // static 157 return best_mode;
181 RRMode OutputConfigurator::FindOutputModeMatchingSize(
182 const OutputSnapshot& output,
183 int width,
184 int height) {
185 RRMode found = None;
186 float best_rate = 0;
187 bool non_interlaced_found = false;
188 for (ModeInfoMap::const_iterator it = output.mode_infos.begin();
189 it != output.mode_infos.end();
190 ++it) {
191 RRMode mode = it->first;
192 const ModeInfo& info = it->second;
193
194 if (info.width == width && info.height == height) {
195 if (info.interlaced) {
196 if (non_interlaced_found)
197 continue;
198 } else {
199 // Reset the best rate if the non interlaced is
200 // found the first time.
201 if (!non_interlaced_found)
202 best_rate = info.refresh_rate;
203 non_interlaced_found = true;
204 }
205 if (info.refresh_rate < best_rate)
206 continue;
207
208 found = mode;
209 best_rate = info.refresh_rate;
210 }
211 }
212 return found;
213 } 158 }
214 159
215 OutputConfigurator::OutputConfigurator() 160 OutputConfigurator::OutputConfigurator()
216 : state_controller_(NULL), 161 : state_controller_(NULL),
217 mirroring_controller_(NULL), 162 mirroring_controller_(NULL),
218 is_panel_fitting_enabled_(false), 163 is_panel_fitting_enabled_(false),
219 configure_display_(base::SysInfo::IsRunningOnChromeOS()), 164 configure_display_(base::SysInfo::IsRunningOnChromeOS()),
220 output_state_(OUTPUT_STATE_INVALID), 165 output_state_(OUTPUT_STATE_INVALID),
221 power_state_(chromeos::DISPLAY_POWER_ALL_ON), 166 power_state_(chromeos::DISPLAY_POWER_ALL_ON),
222 next_output_protection_client_id_(1) {} 167 next_output_protection_client_id_(1) {}
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 EnterStateOrFallBackToSoftwareMirroring(new_state, power_state_); 222 EnterStateOrFallBackToSoftwareMirroring(new_state, power_state_);
278 223
279 // Force the DPMS on chrome startup as the driver doesn't always detect 224 // Force the DPMS on chrome startup as the driver doesn't always detect
280 // that all displays are on when signing out. 225 // that all displays are on when signing out.
281 native_display_delegate_->ForceDPMSOn(); 226 native_display_delegate_->ForceDPMSOn();
282 native_display_delegate_->UngrabServer(); 227 native_display_delegate_->UngrabServer();
283 NotifyObservers(success, new_state); 228 NotifyObservers(success, new_state);
284 } 229 }
285 230
286 bool OutputConfigurator::ApplyProtections(const DisplayProtections& requests) { 231 bool OutputConfigurator::ApplyProtections(const DisplayProtections& requests) {
287 for (std::vector<OutputSnapshot>::const_iterator it = cached_outputs_.begin(); 232 for (DisplayStateList::const_iterator it = cached_outputs_.begin();
288 it != cached_outputs_.end(); 233 it != cached_outputs_.end();
289 ++it) { 234 ++it) {
290 uint32_t all_desired = 0; 235 uint32_t all_desired = 0;
291 DisplayProtections::const_iterator request_it = 236 DisplayProtections::const_iterator request_it =
292 requests.find(it->display_id); 237 requests.find(it->display->display_id());
293 if (request_it != requests.end()) 238 if (request_it != requests.end())
294 all_desired = request_it->second; 239 all_desired = request_it->second;
295 switch (it->type) { 240 switch (it->display->type()) {
296 case OUTPUT_TYPE_UNKNOWN: 241 case OUTPUT_TYPE_UNKNOWN:
297 return false; 242 return false;
298 // DisplayPort, DVI, and HDMI all support HDCP. 243 // DisplayPort, DVI, and HDMI all support HDCP.
299 case OUTPUT_TYPE_DISPLAYPORT: 244 case OUTPUT_TYPE_DISPLAYPORT:
300 case OUTPUT_TYPE_DVI: 245 case OUTPUT_TYPE_DVI:
301 case OUTPUT_TYPE_HDMI: { 246 case OUTPUT_TYPE_HDMI: {
302 HDCPState new_desired_state = 247 HDCPState new_desired_state =
303 (all_desired & OUTPUT_PROTECTION_METHOD_HDCP) ? 248 (all_desired & OUTPUT_PROTECTION_METHOD_HDCP) ?
304 HDCP_STATE_DESIRED : HDCP_STATE_UNDESIRED; 249 HDCP_STATE_DESIRED : HDCP_STATE_UNDESIRED;
305 if (!native_display_delegate_->SetHDCPState(*it, new_desired_state)) 250 if (!native_display_delegate_->SetHDCPState(*it->display,
251 new_desired_state))
306 return false; 252 return false;
307 break; 253 break;
308 } 254 }
309 case OUTPUT_TYPE_INTERNAL: 255 case OUTPUT_TYPE_INTERNAL:
310 case OUTPUT_TYPE_VGA: 256 case OUTPUT_TYPE_VGA:
311 case OUTPUT_TYPE_NETWORK: 257 case OUTPUT_TYPE_NETWORK:
312 // No protections for these types. Do nothing. 258 // No protections for these types. Do nothing.
313 break; 259 break;
314 case OUTPUT_TYPE_NONE: 260 case OUTPUT_TYPE_NONE:
315 NOTREACHED(); 261 NOTREACHED();
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
351 OutputProtectionClientId client_id, 297 OutputProtectionClientId client_id,
352 int64 display_id, 298 int64 display_id,
353 uint32_t* link_mask, 299 uint32_t* link_mask,
354 uint32_t* protection_mask) { 300 uint32_t* protection_mask) {
355 if (!configure_display_) 301 if (!configure_display_)
356 return false; 302 return false;
357 303
358 uint32_t enabled = 0; 304 uint32_t enabled = 0;
359 uint32_t unfulfilled = 0; 305 uint32_t unfulfilled = 0;
360 *link_mask = 0; 306 *link_mask = 0;
361 for (std::vector<OutputSnapshot>::const_iterator it = cached_outputs_.begin(); 307 for (DisplayStateList::const_iterator it = cached_outputs_.begin();
362 it != cached_outputs_.end(); 308 it != cached_outputs_.end();
363 ++it) { 309 ++it) {
364 if (it->display_id != display_id) 310 if (it->display->display_id() != display_id)
365 continue; 311 continue;
366 *link_mask |= it->type; 312 *link_mask |= it->display->type();
367 switch (it->type) { 313 switch (it->display->type()) {
368 case OUTPUT_TYPE_UNKNOWN: 314 case OUTPUT_TYPE_UNKNOWN:
369 return false; 315 return false;
370 // DisplayPort, DVI, and HDMI all support HDCP. 316 // DisplayPort, DVI, and HDMI all support HDCP.
371 case OUTPUT_TYPE_DISPLAYPORT: 317 case OUTPUT_TYPE_DISPLAYPORT:
372 case OUTPUT_TYPE_DVI: 318 case OUTPUT_TYPE_DVI:
373 case OUTPUT_TYPE_HDMI: { 319 case OUTPUT_TYPE_HDMI: {
374 HDCPState state; 320 HDCPState state;
375 if (!native_display_delegate_->GetHDCPState(*it, &state)) 321 if (!native_display_delegate_->GetHDCPState(*it->display, &state))
376 return false; 322 return false;
377 if (state == HDCP_STATE_ENABLED) 323 if (state == HDCP_STATE_ENABLED)
378 enabled |= OUTPUT_PROTECTION_METHOD_HDCP; 324 enabled |= OUTPUT_PROTECTION_METHOD_HDCP;
379 else 325 else
380 unfulfilled |= OUTPUT_PROTECTION_METHOD_HDCP; 326 unfulfilled |= OUTPUT_PROTECTION_METHOD_HDCP;
381 break; 327 break;
382 } 328 }
383 case OUTPUT_TYPE_INTERNAL: 329 case OUTPUT_TYPE_INTERNAL:
384 case OUTPUT_TYPE_VGA: 330 case OUTPUT_TYPE_VGA:
385 case OUTPUT_TYPE_NETWORK: 331 case OUTPUT_TYPE_NETWORK:
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
465 UpdateCachedOutputs(); 411 UpdateCachedOutputs();
466 412
467 const OutputState new_state = ChooseOutputState(power_state); 413 const OutputState new_state = ChooseOutputState(power_state);
468 bool attempted_change = false; 414 bool attempted_change = false;
469 bool success = false; 415 bool success = false;
470 416
471 bool only_if_single_internal_display = 417 bool only_if_single_internal_display =
472 flags & kSetDisplayPowerOnlyIfSingleInternalDisplay; 418 flags & kSetDisplayPowerOnlyIfSingleInternalDisplay;
473 bool single_internal_display = 419 bool single_internal_display =
474 cached_outputs_.size() == 1 && 420 cached_outputs_.size() == 1 &&
475 cached_outputs_[0].type == OUTPUT_TYPE_INTERNAL; 421 cached_outputs_[0].display->type() == OUTPUT_TYPE_INTERNAL;
476 if (single_internal_display || !only_if_single_internal_display) { 422 if (single_internal_display || !only_if_single_internal_display) {
477 success = EnterStateOrFallBackToSoftwareMirroring(new_state, power_state); 423 success = EnterStateOrFallBackToSoftwareMirroring(new_state, power_state);
478 attempted_change = true; 424 attempted_change = true;
479 425
480 // Force the DPMS on since the driver doesn't always detect that it 426 // Force the DPMS on since the driver doesn't always detect that it
481 // should turn on. This is needed when coming back from idle suspend. 427 // should turn on. This is needed when coming back from idle suspend.
482 if (success && power_state != chromeos::DISPLAY_POWER_ALL_OFF) 428 if (success && power_state != chromeos::DISPLAY_POWER_ALL_OFF)
483 native_display_delegate_->ForceDPMSOn(); 429 native_display_delegate_->ForceDPMSOn();
484 } 430 }
485 431
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
553 } 499 }
554 } 500 }
555 501
556 void OutputConfigurator::ResumeDisplays() { 502 void OutputConfigurator::ResumeDisplays() {
557 // Force probing to ensure that we pick up any changes that were made 503 // Force probing to ensure that we pick up any changes that were made
558 // while the system was suspended. 504 // while the system was suspended.
559 SetDisplayPower(power_state_, kSetDisplayPowerForceProbe); 505 SetDisplayPower(power_state_, kSetDisplayPowerForceProbe);
560 } 506 }
561 507
562 void OutputConfigurator::UpdateCachedOutputs() { 508 void OutputConfigurator::UpdateCachedOutputs() {
563 cached_outputs_ = native_display_delegate_->GetOutputs(); 509 std::vector<DisplaySnapshot*> snapshots =
510 native_display_delegate_->GetOutputs();
511
512 cached_outputs_.clear();
513 for (size_t i = 0; i < snapshots.size(); ++i) {
514 DisplayState display_state;
515 display_state.display = snapshots[i];
516 cached_outputs_.push_back(display_state);
517 }
518
564 touchscreen_delegate_->AssociateTouchscreens(&cached_outputs_); 519 touchscreen_delegate_->AssociateTouchscreens(&cached_outputs_);
565 520
566 // Set |selected_mode| fields. 521 // Set |selected_mode| fields.
567 for (size_t i = 0; i < cached_outputs_.size(); ++i) { 522 for (size_t i = 0; i < cached_outputs_.size(); ++i) {
568 OutputSnapshot* output = &cached_outputs_[i]; 523 DisplayState* output = &cached_outputs_[i];
569 if (output->has_display_id) { 524 if (output->display->has_proper_display_id()) {
570 int width = 0, height = 0; 525 gfx::Size size;
571 if (state_controller_ && state_controller_->GetResolutionForDisplayId( 526 if (state_controller_ && state_controller_->GetResolutionForDisplayId(
572 output->display_id, &width, &height)) { 527 output->display->display_id(), &size)) {
573 output->selected_mode = 528 output->selected_mode =
574 FindOutputModeMatchingSize(*output, width, height); 529 FindDisplayModeMatchingSize(*output->display, size);
575 } 530 }
576 } 531 }
577 // Fall back to native mode. 532 // Fall back to native mode.
578 if (output->selected_mode == None) 533 if (!output->selected_mode)
579 output->selected_mode = output->native_mode; 534 output->selected_mode = output->display->native_mode();
580 } 535 }
581 536
582 // Set |mirror_mode| fields. 537 // Set |mirror_mode| fields.
583 if (cached_outputs_.size() == 2) { 538 if (cached_outputs_.size() == 2) {
584 bool one_is_internal = cached_outputs_[0].type == OUTPUT_TYPE_INTERNAL; 539 bool one_is_internal =
585 bool two_is_internal = cached_outputs_[1].type == OUTPUT_TYPE_INTERNAL; 540 cached_outputs_[0].display->type() == OUTPUT_TYPE_INTERNAL;
541 bool two_is_internal =
542 cached_outputs_[1].display->type() == OUTPUT_TYPE_INTERNAL;
586 int internal_outputs = 543 int internal_outputs =
587 (one_is_internal ? 1 : 0) + (two_is_internal ? 1 : 0); 544 (one_is_internal ? 1 : 0) + (two_is_internal ? 1 : 0);
588 DCHECK_LT(internal_outputs, 2); 545 DCHECK_LT(internal_outputs, 2);
589 LOG_IF(WARNING, internal_outputs == 2) << "Two internal outputs detected."; 546 LOG_IF(WARNING, internal_outputs == 2) << "Two internal outputs detected.";
590 547
591 bool can_mirror = false; 548 bool can_mirror = false;
592 for (int attempt = 0; !can_mirror && attempt < 2; ++attempt) { 549 for (int attempt = 0; !can_mirror && attempt < 2; ++attempt) {
593 // Try preserving external output's aspect ratio on the first attempt. 550 // Try preserving external output's aspect ratio on the first attempt.
594 // If that fails, fall back to the highest matching resolution. 551 // If that fails, fall back to the highest matching resolution.
595 bool preserve_aspect = attempt == 0; 552 bool preserve_aspect = attempt == 0;
(...skipping 21 matching lines...) Expand all
617 // it will succeed with the other. This way we will have the correct 574 // it will succeed with the other. This way we will have the correct
618 // aspect ratio on at least one of them. 575 // aspect ratio on at least one of them.
619 can_mirror = FindMirrorMode( 576 can_mirror = FindMirrorMode(
620 &cached_outputs_[1], &cached_outputs_[0], false, preserve_aspect); 577 &cached_outputs_[1], &cached_outputs_[0], false, preserve_aspect);
621 } 578 }
622 } 579 }
623 } 580 }
624 } 581 }
625 } 582 }
626 583
627 bool OutputConfigurator::FindMirrorMode(OutputSnapshot* internal_output, 584 bool OutputConfigurator::FindMirrorMode(DisplayState* internal_output,
628 OutputSnapshot* external_output, 585 DisplayState* external_output,
629 bool try_panel_fitting, 586 bool try_panel_fitting,
630 bool preserve_aspect) { 587 bool preserve_aspect) {
631 const ModeInfo* internal_native_info = 588 const DisplayMode* internal_native_info =
632 GetModeInfo(*internal_output, internal_output->native_mode); 589 internal_output->display->native_mode();
633 const ModeInfo* external_native_info = 590 const DisplayMode* external_native_info =
634 GetModeInfo(*external_output, external_output->native_mode); 591 external_output->display->native_mode();
635 if (!internal_native_info || !external_native_info) 592 if (!internal_native_info || !external_native_info)
636 return false; 593 return false;
637 594
638 // Check if some external output resolution can be mirrored on internal. 595 // Check if some external output resolution can be mirrored on internal.
639 // Prefer the modes in the order that X sorts them, assuming this is the order 596 // Prefer the modes in the order that X sorts them, assuming this is the order
640 // in which they look better on the monitor. 597 // in which they look better on the monitor.
641 for (ModeInfoMap::const_iterator external_it = 598 for (DisplayModeList::const_iterator external_it =
642 external_output->mode_infos.begin(); 599 external_output->display->modes().begin();
643 external_it != external_output->mode_infos.end(); 600 external_it != external_output->display->modes().end();
644 ++external_it) { 601 ++external_it) {
645 const ModeInfo& external_info = external_it->second; 602 const DisplayMode& external_info = **external_it;
646 bool is_native_aspect_ratio = 603 bool is_native_aspect_ratio =
647 external_native_info->width * external_info.height == 604 external_native_info->size().width() * external_info.size().height() ==
648 external_native_info->height * external_info.width; 605 external_native_info->size().height() * external_info.size().width();
649 if (preserve_aspect && !is_native_aspect_ratio) 606 if (preserve_aspect && !is_native_aspect_ratio)
650 continue; // Allow only aspect ratio preserving modes for mirroring. 607 continue; // Allow only aspect ratio preserving modes for mirroring.
651 608
652 // Try finding an exact match. 609 // Try finding an exact match.
653 for (ModeInfoMap::const_iterator internal_it = 610 for (DisplayModeList::const_iterator internal_it =
654 internal_output->mode_infos.begin(); 611 internal_output->display->modes().begin();
655 internal_it != internal_output->mode_infos.end(); 612 internal_it != internal_output->display->modes().end();
656 ++internal_it) { 613 ++internal_it) {
657 const ModeInfo& internal_info = internal_it->second; 614 const DisplayMode& internal_info = **internal_it;
658 if (internal_info.width == external_info.width && 615 if (internal_info.size().width() == external_info.size().width() &&
659 internal_info.height == external_info.height && 616 internal_info.size().height() == external_info.size().height() &&
660 internal_info.interlaced == external_info.interlaced) { 617 internal_info.is_interlaced() == external_info.is_interlaced()) {
661 internal_output->mirror_mode = internal_it->first; 618 internal_output->mirror_mode = *internal_it;
662 external_output->mirror_mode = external_it->first; 619 external_output->mirror_mode = *external_it;
663 return true; // Mirror mode found. 620 return true; // Mirror mode found.
664 } 621 }
665 } 622 }
666 623
667 // Try to create a matching internal output mode by panel fitting. 624 // Try to create a matching internal output mode by panel fitting.
668 if (try_panel_fitting) { 625 if (try_panel_fitting) {
669 // We can downscale by 1.125, and upscale indefinitely. Downscaling looks 626 // We can downscale by 1.125, and upscale indefinitely. Downscaling looks
670 // ugly, so, can fit == can upscale. Also, internal panels don't support 627 // ugly, so, can fit == can upscale. Also, internal panels don't support
671 // fitting interlaced modes. 628 // fitting interlaced modes.
672 bool can_fit = internal_native_info->width >= external_info.width && 629 bool can_fit = internal_native_info->size().width() >=
673 internal_native_info->height >= external_info.height && 630 external_info.size().width() &&
674 !external_info.interlaced; 631 internal_native_info->size().height() >=
632 external_info.size().height() &&
633 !external_info.is_interlaced();
675 if (can_fit) { 634 if (can_fit) {
676 RRMode mode = external_it->first; 635 native_display_delegate_->AddMode(*internal_output->display,
677 native_display_delegate_->AddMode(*internal_output, mode); 636 *external_it);
678 internal_output->mode_infos.insert(std::make_pair(mode, external_info)); 637 internal_output->display->add_mode(*external_it);
679 internal_output->mirror_mode = mode; 638 internal_output->mirror_mode = *external_it;
680 external_output->mirror_mode = mode; 639 external_output->mirror_mode = *external_it;
681 return true; // Mirror mode created. 640 return true; // Mirror mode created.
682 } 641 }
683 } 642 }
684 } 643 }
685 644
686 return false; 645 return false;
687 } 646 }
688 647
689 void OutputConfigurator::ConfigureOutputs() { 648 void OutputConfigurator::ConfigureOutputs() {
690 configure_timer_.reset(); 649 configure_timer_.reset();
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
733 692
734 bool OutputConfigurator::EnterState(OutputState output_state, 693 bool OutputConfigurator::EnterState(OutputState output_state,
735 chromeos::DisplayPowerState power_state) { 694 chromeos::DisplayPowerState power_state) {
736 std::vector<bool> output_power; 695 std::vector<bool> output_power;
737 int num_on_outputs = 696 int num_on_outputs =
738 GetOutputPower(cached_outputs_, power_state, &output_power); 697 GetOutputPower(cached_outputs_, power_state, &output_power);
739 VLOG(1) << "EnterState: output=" << OutputStateToString(output_state) 698 VLOG(1) << "EnterState: output=" << OutputStateToString(output_state)
740 << " power=" << DisplayPowerStateToString(power_state); 699 << " power=" << DisplayPowerStateToString(power_state);
741 700
742 // Framebuffer dimensions. 701 // Framebuffer dimensions.
743 int width = 0, height = 0; 702 gfx::Size size;
744 std::vector<OutputSnapshot> updated_outputs = cached_outputs_; 703
704 std::vector<gfx::Point> new_origins(cached_outputs_.size(), gfx::Point());
705 std::vector<const DisplayMode*> new_mode;
706 for (size_t i = 0; i < cached_outputs_.size(); ++i)
707 new_mode.push_back(cached_outputs_[i].display->current_mode());
745 708
746 switch (output_state) { 709 switch (output_state) {
747 case OUTPUT_STATE_INVALID: 710 case OUTPUT_STATE_INVALID:
748 NOTREACHED() << "Ignoring request to enter invalid state with " 711 NOTREACHED() << "Ignoring request to enter invalid state with "
749 << updated_outputs.size() << " connected output(s)"; 712 << cached_outputs_.size() << " connected output(s)";
750 return false; 713 return false;
751 case OUTPUT_STATE_HEADLESS: 714 case OUTPUT_STATE_HEADLESS:
752 if (updated_outputs.size() != 0) { 715 if (cached_outputs_.size() != 0) {
753 LOG(WARNING) << "Ignoring request to enter headless mode with " 716 LOG(WARNING) << "Ignoring request to enter headless mode with "
754 << updated_outputs.size() << " connected output(s)"; 717 << cached_outputs_.size() << " connected output(s)";
755 return false; 718 return false;
756 } 719 }
757 break; 720 break;
758 case OUTPUT_STATE_SINGLE: { 721 case OUTPUT_STATE_SINGLE: {
759 // If there are multiple outputs connected, only one should be turned on. 722 // If there are multiple outputs connected, only one should be turned on.
760 if (updated_outputs.size() != 1 && num_on_outputs != 1) { 723 if (cached_outputs_.size() != 1 && num_on_outputs != 1) {
761 LOG(WARNING) << "Ignoring request to enter single mode with " 724 LOG(WARNING) << "Ignoring request to enter single mode with "
762 << updated_outputs.size() << " connected outputs and " 725 << cached_outputs_.size() << " connected outputs and "
763 << num_on_outputs << " turned on"; 726 << num_on_outputs << " turned on";
764 return false; 727 return false;
765 } 728 }
766 729
767 for (size_t i = 0; i < updated_outputs.size(); ++i) { 730 for (size_t i = 0; i < cached_outputs_.size(); ++i) {
768 OutputSnapshot* output = &updated_outputs[i]; 731 DisplayState* output = &cached_outputs_[i];
769 output->x = 0; 732 new_mode[i] = output_power[i] ? output->selected_mode : NULL;
770 output->y = 0;
771 output->current_mode = output_power[i] ? output->selected_mode : None;
772 733
773 if (output_power[i] || updated_outputs.size() == 1) { 734 if (output_power[i] || cached_outputs_.size() == 1) {
774 const ModeInfo* mode_info = 735 const DisplayMode* mode_info = output->selected_mode;
775 GetModeInfo(*output, output->selected_mode);
776 if (!mode_info) 736 if (!mode_info)
777 return false; 737 return false;
778 if (mode_info->width == 1024 && mode_info->height == 768) { 738 if (mode_info->size() == gfx::Size(1024, 768)) {
779 VLOG(1) << "Potentially misdetecting display(1024x768):" 739 VLOG(1) << "Potentially misdetecting display(1024x768):"
780 << " outputs size=" << updated_outputs.size() 740 << " outputs size=" << cached_outputs_.size()
781 << ", num_on_outputs=" << num_on_outputs 741 << ", num_on_outputs=" << num_on_outputs
782 << ", current size:" << width << "x" << height 742 << ", current size:" << size.width() << "x" << size.height()
783 << ", i=" << i 743 << ", i=" << i << ", output=" << output->display->ToString()
784 << ", output=" << OutputSnapshotToString(output) 744 << ", display_mode=" << DisplayModeToString(mode_info);
785 << ", mode_info=" << ModeInfoToString(mode_info);
786 } 745 }
787 width = mode_info->width; 746 size = mode_info->size();
788 height = mode_info->height;
789 } 747 }
790 } 748 }
791 break; 749 break;
792 } 750 }
793 case OUTPUT_STATE_DUAL_MIRROR: { 751 case OUTPUT_STATE_DUAL_MIRROR: {
794 if (updated_outputs.size() != 2 || 752 if (cached_outputs_.size() != 2 ||
795 (num_on_outputs != 0 && num_on_outputs != 2)) { 753 (num_on_outputs != 0 && num_on_outputs != 2)) {
796 LOG(WARNING) << "Ignoring request to enter mirrored mode with " 754 LOG(WARNING) << "Ignoring request to enter mirrored mode with "
797 << updated_outputs.size() << " connected output(s) and " 755 << cached_outputs_.size() << " connected output(s) and "
798 << num_on_outputs << " turned on"; 756 << num_on_outputs << " turned on";
799 return false; 757 return false;
800 } 758 }
801 759
802 if (!updated_outputs[0].mirror_mode) 760 const DisplayMode* mode_info = cached_outputs_[0].mirror_mode;
803 return false;
804 const ModeInfo* mode_info =
805 GetModeInfo(updated_outputs[0], updated_outputs[0].mirror_mode);
806 if (!mode_info) 761 if (!mode_info)
807 return false; 762 return false;
808 width = mode_info->width; 763 size = mode_info->size();
809 height = mode_info->height;
810 764
811 for (size_t i = 0; i < updated_outputs.size(); ++i) { 765 for (size_t i = 0; i < cached_outputs_.size(); ++i) {
812 OutputSnapshot* output = &updated_outputs[i]; 766 DisplayState* output = &cached_outputs_[i];
813 output->x = 0; 767 new_mode[i] = output_power[i] ? output->mirror_mode : NULL;
814 output->y = 0;
815 output->current_mode = output_power[i] ? output->mirror_mode : None;
816 if (output->touch_device_id) { 768 if (output->touch_device_id) {
817 // CTM needs to be calculated if aspect preserving scaling is used. 769 // CTM needs to be calculated if aspect preserving scaling is used.
818 // Otherwise, assume it is full screen, and use identity CTM. 770 // Otherwise, assume it is full screen, and use identity CTM.
819 if (output->mirror_mode != output->native_mode && 771 if (output->mirror_mode != output->display->native_mode() &&
820 output->is_aspect_preserving_scaling) { 772 output->display->is_aspect_preserving_scaling()) {
821 output->transform = GetMirrorModeCTM(*output); 773 output->transform = GetMirrorModeCTM(*output);
822 mirrored_display_area_ratio_map_[output->touch_device_id] = 774 mirrored_display_area_ratio_map_[output->touch_device_id] =
823 GetMirroredDisplayAreaRatio(*output); 775 GetMirroredDisplayAreaRatio(*output);
824 } 776 }
825 } 777 }
826 } 778 }
827 break; 779 break;
828 } 780 }
829 case OUTPUT_STATE_DUAL_EXTENDED: { 781 case OUTPUT_STATE_DUAL_EXTENDED: {
830 if (updated_outputs.size() != 2 || 782 if (cached_outputs_.size() != 2 ||
831 (num_on_outputs != 0 && num_on_outputs != 2)) { 783 (num_on_outputs != 0 && num_on_outputs != 2)) {
832 LOG(WARNING) << "Ignoring request to enter extended mode with " 784 LOG(WARNING) << "Ignoring request to enter extended mode with "
833 << updated_outputs.size() << " connected output(s) and " 785 << cached_outputs_.size() << " connected output(s) and "
834 << num_on_outputs << " turned on"; 786 << num_on_outputs << " turned on";
835 return false; 787 return false;
836 } 788 }
837 789
838 for (size_t i = 0; i < updated_outputs.size(); ++i) { 790 for (size_t i = 0; i < cached_outputs_.size(); ++i) {
839 OutputSnapshot* output = &updated_outputs[i]; 791 DisplayState* output = &cached_outputs_[i];
840 output->x = 0; 792 new_origins[i].set_y(size.height() ? size.height() + kVerticalGap : 0);
841 output->y = height ? height + kVerticalGap : 0; 793 new_mode[i] = output_power[i] ? output->selected_mode : NULL;
842 output->current_mode = output_power[i] ? output->selected_mode : None;
843 794
844 // Retain the full screen size even if all outputs are off so the 795 // Retain the full screen size even if all outputs are off so the
845 // same desktop configuration can be restored when the outputs are 796 // same desktop configuration can be restored when the outputs are
846 // turned back on. 797 // turned back on.
847 const ModeInfo* mode_info = 798 const DisplayMode* mode_info = cached_outputs_[i].selected_mode;
848 GetModeInfo(updated_outputs[i], updated_outputs[i].selected_mode);
849 if (!mode_info) 799 if (!mode_info)
850 return false; 800 return false;
851 width = std::max<int>(width, mode_info->width); 801
852 height += (height ? kVerticalGap : 0) + mode_info->height; 802 size.set_width(std::max<int>(size.width(), mode_info->size().width()));
803 size.set_height(size.height() + (size.height() ? kVerticalGap : 0) +
804 mode_info->size().height());
853 } 805 }
854 806
855 for (size_t i = 0; i < updated_outputs.size(); ++i) { 807 for (size_t i = 0; i < cached_outputs_.size(); ++i) {
856 OutputSnapshot* output = &updated_outputs[i]; 808 DisplayState* output = &cached_outputs_[i];
857 if (output->touch_device_id) 809 if (output->touch_device_id)
858 output->transform = GetExtendedModeCTM(*output, width, height); 810 output->transform = GetExtendedModeCTM(*output, new_origins[i], size);
859 } 811 }
860 break; 812 break;
861 } 813 }
862 } 814 }
863 815
864 // Finally, apply the desired changes. 816 // Finally, apply the desired changes.
865 DCHECK_EQ(cached_outputs_.size(), updated_outputs.size());
866 bool all_succeeded = true; 817 bool all_succeeded = true;
867 if (!updated_outputs.empty()) { 818 if (!cached_outputs_.empty()) {
868 native_display_delegate_->CreateFrameBuffer(width, height, updated_outputs); 819 native_display_delegate_->CreateFrameBuffer(size);
869 for (size_t i = 0; i < updated_outputs.size(); ++i) { 820 for (size_t i = 0; i < cached_outputs_.size(); ++i) {
870 const OutputSnapshot& output = updated_outputs[i]; 821 const DisplayState& output = cached_outputs_[i];
871 bool configure_succeeded = false; 822 bool configure_succeeded = false;
872 823
873 while (true) { 824 while (true) {
874 if (native_display_delegate_->Configure( 825 if (native_display_delegate_->Configure(
875 output, output.current_mode, output.x, output.y)) { 826 *output.display, new_mode[i], new_origins[i])) {
827 output.display->set_current_mode(new_mode[i]);
828 output.display->set_origin(new_origins[i]);
829
876 configure_succeeded = true; 830 configure_succeeded = true;
877 break; 831 break;
878 } 832 }
879 833
880 LOG(WARNING) << "Unable to configure CRTC " << output.crtc << ":" 834 const DisplayMode* mode_info = new_mode[i];
881 << " mode=" << output.current_mode
882 << " output=" << output.output << " x=" << output.x
883 << " y=" << output.y;
884
885 const ModeInfo* mode_info = GetModeInfo(output, output.current_mode);
886 if (!mode_info) 835 if (!mode_info)
887 break; 836 break;
888 837
889 // Find the mode with the next-best resolution and see if that can 838 // Find the mode with the next-best resolution and see if that can
890 // be set. 839 // be set.
891 int best_mode_pixels = 0; 840 int best_mode_pixels = 0;
892 841
893 int current_mode_pixels = mode_info->width * mode_info->height; 842 int current_mode_pixels = mode_info->size().GetArea();
894 for (ModeInfoMap::const_iterator it = output.mode_infos.begin(); 843 for (DisplayModeList::const_iterator it =
895 it != output.mode_infos.end(); 844 output.display->modes().begin();
845 it != output.display->modes().end();
896 it++) { 846 it++) {
897 int pixel_count = it->second.width * it->second.height; 847 int pixel_count = (*it)->size().GetArea();
898 if ((pixel_count < current_mode_pixels) && 848 if ((pixel_count < current_mode_pixels) &&
899 (pixel_count > best_mode_pixels)) { 849 (pixel_count > best_mode_pixels)) {
900 updated_outputs[i].current_mode = it->first; 850 new_mode[i] = *it;
901 best_mode_pixels = pixel_count; 851 best_mode_pixels = pixel_count;
902 } 852 }
903 } 853 }
904 854
905 if (best_mode_pixels == 0) 855 if (best_mode_pixels == 0)
906 break; 856 break;
907 } 857 }
908 858
909 if (configure_succeeded) { 859 if (configure_succeeded) {
910 if (output.touch_device_id) 860 if (output.touch_device_id)
911 touchscreen_delegate_->ConfigureCTM(output.touch_device_id, 861 touchscreen_delegate_->ConfigureCTM(output.touch_device_id,
912 output.transform); 862 output.transform);
913 cached_outputs_[i] = updated_outputs[i];
914 } else { 863 } else {
915 all_succeeded = false; 864 all_succeeded = false;
916 } 865 }
917 866
918 // If we are trying to set mirror mode and one of the modesets fails, 867 // If we are trying to set mirror mode and one of the modesets fails,
919 // then the two monitors will be mis-matched. In this case, return 868 // then the two monitors will be mis-matched. In this case, return
920 // false to let the observers be aware. 869 // false to let the observers be aware.
921 if (output_state == OUTPUT_STATE_DUAL_MIRROR && output_power[i] && 870 if (output_state == OUTPUT_STATE_DUAL_MIRROR && output_power[i] &&
922 output.current_mode != output.mirror_mode) 871 output.display->current_mode() != output.mirror_mode)
923 all_succeeded = false; 872 all_succeeded = false;
924 } 873 }
925 } 874 }
926 875
927 if (all_succeeded) { 876 if (all_succeeded) {
928 output_state_ = output_state; 877 output_state_ = output_state;
929 power_state_ = power_state; 878 power_state_ = power_state;
930 } 879 }
931 return all_succeeded; 880 return all_succeeded;
932 } 881 }
(...skipping 10 matching lines...) Expand all
943 if (num_on_outputs == 1) { 892 if (num_on_outputs == 1) {
944 // If only one output is currently turned on, return the "single" 893 // If only one output is currently turned on, return the "single"
945 // state so that its native mode will be used. 894 // state so that its native mode will be used.
946 return OUTPUT_STATE_SINGLE; 895 return OUTPUT_STATE_SINGLE;
947 } else { 896 } else {
948 // With either both outputs on or both outputs off, use one of the 897 // With either both outputs on or both outputs off, use one of the
949 // dual modes. 898 // dual modes.
950 std::vector<int64> display_ids; 899 std::vector<int64> display_ids;
951 for (size_t i = 0; i < cached_outputs_.size(); ++i) { 900 for (size_t i = 0; i < cached_outputs_.size(); ++i) {
952 // If display id isn't available, switch to extended mode. 901 // If display id isn't available, switch to extended mode.
953 if (!cached_outputs_[i].has_display_id) 902 if (!cached_outputs_[i].display->has_proper_display_id())
954 return OUTPUT_STATE_DUAL_EXTENDED; 903 return OUTPUT_STATE_DUAL_EXTENDED;
955 display_ids.push_back(cached_outputs_[i].display_id); 904 display_ids.push_back(cached_outputs_[i].display->display_id());
956 } 905 }
957 return state_controller_->GetStateForDisplayIds(display_ids); 906 return state_controller_->GetStateForDisplayIds(display_ids);
958 } 907 }
959 } 908 }
960 default: 909 default:
961 NOTREACHED(); 910 NOTREACHED();
962 } 911 }
963 return OUTPUT_STATE_INVALID; 912 return OUTPUT_STATE_INVALID;
964 } 913 }
965 914
966 OutputConfigurator::CoordinateTransformation 915 OutputConfigurator::CoordinateTransformation
967 OutputConfigurator::GetMirrorModeCTM( 916 OutputConfigurator::GetMirrorModeCTM(const DisplayState& output) {
968 const OutputConfigurator::OutputSnapshot& output) {
969 CoordinateTransformation ctm; // Default to identity 917 CoordinateTransformation ctm; // Default to identity
970 const ModeInfo* native_mode_info = GetModeInfo(output, output.native_mode); 918 const DisplayMode* native_mode_info = output.display->native_mode();
971 const ModeInfo* mirror_mode_info = GetModeInfo(output, output.mirror_mode); 919 const DisplayMode* mirror_mode_info = output.mirror_mode;
972 920
973 if (!native_mode_info || !mirror_mode_info || native_mode_info->height == 0 || 921 if (!native_mode_info || !mirror_mode_info ||
974 mirror_mode_info->height == 0 || native_mode_info->width == 0 || 922 native_mode_info->size().height() == 0 ||
975 mirror_mode_info->width == 0) 923 mirror_mode_info->size().height() == 0 ||
924 native_mode_info->size().width() == 0 ||
925 mirror_mode_info->size().width() == 0)
976 return ctm; 926 return ctm;
977 927
978 float native_mode_ar = static_cast<float>(native_mode_info->width) / 928 float native_mode_ar = static_cast<float>(native_mode_info->size().width()) /
979 static_cast<float>(native_mode_info->height); 929 static_cast<float>(native_mode_info->size().height());
980 float mirror_mode_ar = static_cast<float>(mirror_mode_info->width) / 930 float mirror_mode_ar = static_cast<float>(mirror_mode_info->size().width()) /
981 static_cast<float>(mirror_mode_info->height); 931 static_cast<float>(mirror_mode_info->size().height());
982 932
983 if (mirror_mode_ar > native_mode_ar) { // Letterboxing 933 if (mirror_mode_ar > native_mode_ar) { // Letterboxing
984 ctm.x_scale = 1.0; 934 ctm.x_scale = 1.0;
985 ctm.x_offset = 0.0; 935 ctm.x_offset = 0.0;
986 ctm.y_scale = mirror_mode_ar / native_mode_ar; 936 ctm.y_scale = mirror_mode_ar / native_mode_ar;
987 ctm.y_offset = (native_mode_ar / mirror_mode_ar - 1.0) * 0.5; 937 ctm.y_offset = (native_mode_ar / mirror_mode_ar - 1.0) * 0.5;
988 return ctm; 938 return ctm;
989 } 939 }
990 if (native_mode_ar > mirror_mode_ar) { // Pillarboxing 940 if (native_mode_ar > mirror_mode_ar) { // Pillarboxing
991 ctm.y_scale = 1.0; 941 ctm.y_scale = 1.0;
992 ctm.y_offset = 0.0; 942 ctm.y_offset = 0.0;
993 ctm.x_scale = native_mode_ar / mirror_mode_ar; 943 ctm.x_scale = native_mode_ar / mirror_mode_ar;
994 ctm.x_offset = (mirror_mode_ar / native_mode_ar - 1.0) * 0.5; 944 ctm.x_offset = (mirror_mode_ar / native_mode_ar - 1.0) * 0.5;
995 return ctm; 945 return ctm;
996 } 946 }
997 947
998 return ctm; // Same aspect ratio - return identity 948 return ctm; // Same aspect ratio - return identity
999 } 949 }
1000 950
1001 OutputConfigurator::CoordinateTransformation 951 OutputConfigurator::CoordinateTransformation
1002 OutputConfigurator::GetExtendedModeCTM( 952 OutputConfigurator::GetExtendedModeCTM(const DisplayState& output,
1003 const OutputConfigurator::OutputSnapshot& output, 953 const gfx::Point& new_origin,
1004 int framebuffer_width, 954 const gfx::Size& framebuffer_size) {
1005 int framebuffer_height) {
1006 CoordinateTransformation ctm; // Default to identity 955 CoordinateTransformation ctm; // Default to identity
1007 const ModeInfo* mode_info = GetModeInfo(output, output.selected_mode); 956 const DisplayMode* mode_info = output.selected_mode;
1008 DCHECK(mode_info); 957 DCHECK(mode_info);
1009 if (!mode_info) 958 if (!mode_info)
1010 return ctm; 959 return ctm;
1011 // An example of how to calculate the CTM. 960 // An example of how to calculate the CTM.
1012 // Suppose we have 2 monitors, the first one has size 1366 x 768. 961 // Suppose we have 2 monitors, the first one has size 1366 x 768.
1013 // The second one has size 2560 x 1600 962 // The second one has size 2560 x 1600
1014 // The total size of framebuffer is 2560 x 2428 963 // The total size of framebuffer is 2560 x 2428
1015 // where 2428 = 768 + 60 (hidden gap) + 1600 964 // where 2428 = 768 + 60 (hidden gap) + 1600
1016 // and the sceond monitor is translated to Point (0, 828) in the 965 // and the sceond monitor is translated to Point (0, 828) in the
1017 // framebuffer. 966 // framebuffer.
1018 // X will first map input event location to [0, 2560) x [0, 2428), 967 // X will first map input event location to [0, 2560) x [0, 2428),
1019 // then apply CTM on it. 968 // then apply CTM on it.
1020 // So to compute CTM, for monitor1, we have 969 // So to compute CTM, for monitor1, we have
1021 // x_scale = (1366 - 1) / (2560 - 1) 970 // x_scale = (1366 - 1) / (2560 - 1)
1022 // x_offset = 0 / (2560 - 1) 971 // x_offset = 0 / (2560 - 1)
1023 // y_scale = (768 - 1) / (2428 - 1) 972 // y_scale = (768 - 1) / (2428 - 1)
1024 // y_offset = 0 / (2428 -1) 973 // y_offset = 0 / (2428 -1)
1025 // For Monitor 2, we have 974 // For Monitor 2, we have
1026 // x_scale = (2560 - 1) / (2560 - 1) 975 // x_scale = (2560 - 1) / (2560 - 1)
1027 // x_offset = 0 / (2560 - 1) 976 // x_offset = 0 / (2560 - 1)
1028 // y_scale = (1600 - 1) / (2428 - 1) 977 // y_scale = (1600 - 1) / (2428 - 1)
1029 // y_offset = 828 / (2428 -1) 978 // y_offset = 828 / (2428 -1)
1030 // See the unittest OutputConfiguratorTest.CTMForMultiScreens. 979 // See the unittest OutputConfiguratorTest.CTMForMultiScreens.
1031 ctm.x_scale = 980 ctm.x_scale = static_cast<float>(mode_info->size().width() - 1) /
1032 static_cast<float>(mode_info->width - 1) / (framebuffer_width - 1); 981 (framebuffer_size.width() - 1);
1033 ctm.x_offset = static_cast<float>(output.x) / (framebuffer_width - 1); 982 ctm.x_offset =
1034 ctm.y_scale = 983 static_cast<float>(new_origin.x()) / (framebuffer_size.width() - 1);
1035 static_cast<float>(mode_info->height - 1) / (framebuffer_height - 1); 984 ctm.y_scale = static_cast<float>(mode_info->size().height() - 1) /
1036 ctm.y_offset = static_cast<float>(output.y) / (framebuffer_height - 1); 985 (framebuffer_size.height() - 1);
986 ctm.y_offset =
987 static_cast<float>(new_origin.y()) / (framebuffer_size.height() - 1);
1037 return ctm; 988 return ctm;
1038 } 989 }
1039 990
1040 float OutputConfigurator::GetMirroredDisplayAreaRatio( 991 float OutputConfigurator::GetMirroredDisplayAreaRatio(
1041 const OutputConfigurator::OutputSnapshot& output) { 992 const DisplayState& output) {
1042 float area_ratio = 1.0f; 993 float area_ratio = 1.0f;
1043 const ModeInfo* native_mode_info = GetModeInfo(output, output.native_mode); 994 const DisplayMode* native_mode_info = output.display->native_mode();
1044 const ModeInfo* mirror_mode_info = GetModeInfo(output, output.mirror_mode); 995 const DisplayMode* mirror_mode_info = output.mirror_mode;
1045 996
1046 if (!native_mode_info || !mirror_mode_info || native_mode_info->height == 0 || 997 if (!native_mode_info || !mirror_mode_info ||
1047 mirror_mode_info->height == 0 || native_mode_info->width == 0 || 998 native_mode_info->size().height() == 0 ||
1048 mirror_mode_info->width == 0) 999 mirror_mode_info->size().height() == 0 ||
1000 native_mode_info->size().width() == 0 ||
1001 mirror_mode_info->size().width() == 0)
1049 return area_ratio; 1002 return area_ratio;
1050 1003
1051 float width_ratio = static_cast<float>(mirror_mode_info->width) / 1004 float width_ratio = static_cast<float>(mirror_mode_info->size().width()) /
1052 static_cast<float>(native_mode_info->width); 1005 static_cast<float>(native_mode_info->size().width());
1053 float height_ratio = static_cast<float>(mirror_mode_info->height) / 1006 float height_ratio = static_cast<float>(mirror_mode_info->size().height()) /
1054 static_cast<float>(native_mode_info->height); 1007 static_cast<float>(native_mode_info->size().height());
1055 1008
1056 area_ratio = width_ratio * height_ratio; 1009 area_ratio = width_ratio * height_ratio;
1057 return area_ratio; 1010 return area_ratio;
1058 } 1011 }
1059 1012
1060 } // namespace ui 1013 } // namespace ui
OLDNEW
« no previous file with comments | « ui/display/chromeos/output_configurator.h ('k') | ui/display/chromeos/output_configurator_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698