OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 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 "chromeos/display/output_configurator.h" | 5 #include "chromeos/display/output_configurator.h" |
6 | 6 |
7 #include <X11/Xlib.h> | 7 #include <X11/Xlib.h> |
8 #include <X11/extensions/Xrandr.h> | 8 #include <X11/extensions/Xrandr.h> |
9 #include <X11/extensions/XInput2.h> | 9 #include <X11/extensions/XInput2.h> |
10 | 10 |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 } | 97 } |
98 | 98 |
99 } // namespace | 99 } // namespace |
100 | 100 |
101 OutputConfigurator::OutputSnapshot::OutputSnapshot() | 101 OutputConfigurator::OutputSnapshot::OutputSnapshot() |
102 : output(None), | 102 : output(None), |
103 crtc(None), | 103 crtc(None), |
104 current_mode(None), | 104 current_mode(None), |
105 native_mode(None), | 105 native_mode(None), |
106 mirror_mode(None), | 106 mirror_mode(None), |
| 107 selected_mode(None), |
107 y(0), | 108 y(0), |
108 height(0), | 109 height(0), |
109 is_internal(false), | 110 is_internal(false), |
110 is_aspect_preserving_scaling(false), | 111 is_aspect_preserving_scaling(false), |
111 touch_device_id(0), | 112 touch_device_id(0), |
112 display_id(0), | 113 display_id(0), |
113 has_display_id(false) {} | 114 has_display_id(false) {} |
114 | 115 |
115 OutputConfigurator::CoordinateTransformation::CoordinateTransformation() | 116 OutputConfigurator::CoordinateTransformation::CoordinateTransformation() |
116 : x_scale(1.0), | 117 : x_scale(1.0), |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
185 uint32 background_color_argb) { | 186 uint32 background_color_argb) { |
186 if (!configure_display_) | 187 if (!configure_display_) |
187 return; | 188 return; |
188 | 189 |
189 if (!delegate_) | 190 if (!delegate_) |
190 delegate_.reset(new RealOutputConfiguratorDelegate()); | 191 delegate_.reset(new RealOutputConfiguratorDelegate()); |
191 | 192 |
192 // Cache the initial output state. | 193 // Cache the initial output state. |
193 delegate_->SetPanelFittingEnabled(is_panel_fitting_enabled); | 194 delegate_->SetPanelFittingEnabled(is_panel_fitting_enabled); |
194 delegate_->GrabServer(); | 195 delegate_->GrabServer(); |
195 std::vector<OutputSnapshot> outputs = delegate_->GetOutputs(); | 196 std::vector<OutputSnapshot> outputs = |
| 197 delegate_->GetOutputs(state_controller_); |
196 if (outputs.size() > 1 && background_color_argb) | 198 if (outputs.size() > 1 && background_color_argb) |
197 delegate_->SetBackgroundColor(background_color_argb); | 199 delegate_->SetBackgroundColor(background_color_argb); |
198 delegate_->UngrabServer(); | 200 delegate_->UngrabServer(); |
199 } | 201 } |
200 | 202 |
201 void OutputConfigurator::Start() { | 203 void OutputConfigurator::Start() { |
202 if (!configure_display_) | 204 if (!configure_display_) |
203 return; | 205 return; |
204 | 206 |
205 delegate_->GrabServer(); | 207 delegate_->GrabServer(); |
206 delegate_->InitXRandRExtension(&xrandr_event_base_); | 208 delegate_->InitXRandRExtension(&xrandr_event_base_); |
207 | 209 |
208 std::vector<OutputSnapshot> outputs = delegate_->GetOutputs(); | 210 std::vector<OutputSnapshot> outputs = |
| 211 delegate_->GetOutputs(state_controller_); |
209 EnterStateOrFallBackToSoftwareMirroring( | 212 EnterStateOrFallBackToSoftwareMirroring( |
210 GetOutputState(outputs, power_state_), power_state_, outputs); | 213 GetOutputState(outputs, power_state_), power_state_, outputs); |
211 | 214 |
212 // Force the DPMS on chrome startup as the driver doesn't always detect | 215 // Force the DPMS on chrome startup as the driver doesn't always detect |
213 // that all displays are on when signing out. | 216 // that all displays are on when signing out. |
214 delegate_->ForceDPMSOn(); | 217 delegate_->ForceDPMSOn(); |
215 delegate_->UngrabServer(); | 218 delegate_->UngrabServer(); |
216 delegate_->SendProjectingStateToPowerManager(IsProjecting(outputs)); | 219 delegate_->SendProjectingStateToPowerManager(IsProjecting(outputs)); |
217 } | 220 } |
218 | 221 |
219 void OutputConfigurator::Stop() { | 222 void OutputConfigurator::Stop() { |
220 configure_display_ = false; | 223 configure_display_ = false; |
221 } | 224 } |
222 | 225 |
223 bool OutputConfigurator::SetDisplayPower(DisplayPowerState power_state, | 226 bool OutputConfigurator::SetDisplayPower(DisplayPowerState power_state, |
224 int flags) { | 227 int flags) { |
225 if (!configure_display_) | 228 if (!configure_display_) |
226 return false; | 229 return false; |
227 | 230 |
228 VLOG(1) << "SetDisplayPower: power_state=" | 231 VLOG(1) << "SetDisplayPower: power_state=" |
229 << DisplayPowerStateToString(power_state) << " flags=" << flags; | 232 << DisplayPowerStateToString(power_state) << " flags=" << flags; |
230 if (power_state == power_state_ && !(flags & kSetDisplayPowerForceProbe)) | 233 if (power_state == power_state_ && !(flags & kSetDisplayPowerForceProbe)) |
231 return true; | 234 return true; |
232 | 235 |
233 delegate_->GrabServer(); | 236 delegate_->GrabServer(); |
234 std::vector<OutputSnapshot> outputs = delegate_->GetOutputs(); | 237 std::vector<OutputSnapshot> outputs = |
| 238 delegate_->GetOutputs(state_controller_); |
235 | 239 |
236 bool only_if_single_internal_display = | 240 bool only_if_single_internal_display = |
237 flags & kSetDisplayPowerOnlyIfSingleInternalDisplay; | 241 flags & kSetDisplayPowerOnlyIfSingleInternalDisplay; |
238 bool single_internal_display = outputs.size() == 1 && outputs[0].is_internal; | 242 bool single_internal_display = outputs.size() == 1 && outputs[0].is_internal; |
239 if ((single_internal_display || !only_if_single_internal_display) && | 243 if ((single_internal_display || !only_if_single_internal_display) && |
240 EnterStateOrFallBackToSoftwareMirroring( | 244 EnterStateOrFallBackToSoftwareMirroring( |
241 GetOutputState(outputs, power_state), power_state, outputs)) { | 245 GetOutputState(outputs, power_state), power_state, outputs)) { |
242 if (power_state != DISPLAY_POWER_ALL_OFF) { | 246 if (power_state != DISPLAY_POWER_ALL_OFF) { |
243 // Force the DPMS on since the driver doesn't always detect that it | 247 // Force the DPMS on since the driver doesn't always detect that it |
244 // should turn on. This is needed when coming back from idle suspend. | 248 // should turn on. This is needed when coming back from idle suspend. |
(...skipping 13 matching lines...) Expand all Loading... |
258 if (output_state_ == new_state) { | 262 if (output_state_ == new_state) { |
259 // Cancel software mirroring if the state is moving from | 263 // Cancel software mirroring if the state is moving from |
260 // STATE_DUAL_EXTENDED to STATE_DUAL_EXTENDED. | 264 // STATE_DUAL_EXTENDED to STATE_DUAL_EXTENDED. |
261 if (mirroring_controller_ && new_state == STATE_DUAL_EXTENDED) | 265 if (mirroring_controller_ && new_state == STATE_DUAL_EXTENDED) |
262 mirroring_controller_->SetSoftwareMirroring(false); | 266 mirroring_controller_->SetSoftwareMirroring(false); |
263 NotifyOnDisplayChanged(); | 267 NotifyOnDisplayChanged(); |
264 return true; | 268 return true; |
265 } | 269 } |
266 | 270 |
267 delegate_->GrabServer(); | 271 delegate_->GrabServer(); |
268 std::vector<OutputSnapshot> outputs = delegate_->GetOutputs(); | 272 std::vector<OutputSnapshot> outputs = |
| 273 delegate_->GetOutputs(state_controller_); |
269 bool success = EnterStateOrFallBackToSoftwareMirroring( | 274 bool success = EnterStateOrFallBackToSoftwareMirroring( |
270 new_state, power_state_, outputs); | 275 new_state, power_state_, outputs); |
271 delegate_->UngrabServer(); | 276 delegate_->UngrabServer(); |
272 | 277 |
273 if (success) { | 278 if (success) { |
274 NotifyOnDisplayChanged(); | 279 NotifyOnDisplayChanged(); |
275 } else { | 280 } else { |
276 FOR_EACH_OBSERVER( | 281 FOR_EACH_OBSERVER( |
277 Observer, observers_, OnDisplayModeChangeFailed(new_state)); | 282 Observer, observers_, OnDisplayModeChangeFailed(new_state)); |
278 } | 283 } |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
350 delegate_->SyncWithServer(); | 355 delegate_->SyncWithServer(); |
351 } | 356 } |
352 } | 357 } |
353 | 358 |
354 void OutputConfigurator::ResumeDisplays() { | 359 void OutputConfigurator::ResumeDisplays() { |
355 // Force probing to ensure that we pick up any changes that were made | 360 // Force probing to ensure that we pick up any changes that were made |
356 // while the system was suspended. | 361 // while the system was suspended. |
357 SetDisplayPower(power_state_, kSetDisplayPowerForceProbe); | 362 SetDisplayPower(power_state_, kSetDisplayPowerForceProbe); |
358 } | 363 } |
359 | 364 |
| 365 void OutputConfigurator::ScheduleConfigureOutputs() { |
| 366 if (configure_timer_.get()) { |
| 367 configure_timer_->Reset(); |
| 368 } else { |
| 369 configure_timer_.reset(new base::OneShotTimer<OutputConfigurator>()); |
| 370 configure_timer_->Start( |
| 371 FROM_HERE, |
| 372 base::TimeDelta::FromMilliseconds(kConfigureDelayMs), |
| 373 this, |
| 374 &OutputConfigurator::ConfigureOutputs); |
| 375 } |
| 376 } |
| 377 |
360 void OutputConfigurator::ConfigureOutputs() { | 378 void OutputConfigurator::ConfigureOutputs() { |
361 configure_timer_.reset(); | 379 configure_timer_.reset(); |
362 | 380 |
363 delegate_->GrabServer(); | 381 delegate_->GrabServer(); |
364 std::vector<OutputSnapshot> outputs = delegate_->GetOutputs(); | 382 std::vector<OutputSnapshot> outputs = |
| 383 delegate_->GetOutputs(state_controller_); |
365 OutputState new_state = GetOutputState(outputs, power_state_); | 384 OutputState new_state = GetOutputState(outputs, power_state_); |
366 bool success = EnterStateOrFallBackToSoftwareMirroring( | 385 bool success = EnterStateOrFallBackToSoftwareMirroring( |
367 new_state, power_state_, outputs); | 386 new_state, power_state_, outputs); |
368 delegate_->UngrabServer(); | 387 delegate_->UngrabServer(); |
369 | 388 |
370 if (success) { | 389 if (success) { |
371 NotifyOnDisplayChanged(); | 390 NotifyOnDisplayChanged(); |
372 } else { | 391 } else { |
373 FOR_EACH_OBSERVER( | 392 FOR_EACH_OBSERVER( |
374 Observer, observers_, OnDisplayModeChangeFailed(new_state)); | 393 Observer, observers_, OnDisplayModeChangeFailed(new_state)); |
375 } | 394 } |
376 delegate_->SendProjectingStateToPowerManager(IsProjecting(outputs)); | 395 delegate_->SendProjectingStateToPowerManager(IsProjecting(outputs)); |
377 } | 396 } |
378 | 397 |
379 void OutputConfigurator::ScheduleConfigureOutputs() { | |
380 if (configure_timer_.get()) { | |
381 configure_timer_->Reset(); | |
382 } else { | |
383 configure_timer_.reset(new base::OneShotTimer<OutputConfigurator>()); | |
384 configure_timer_->Start( | |
385 FROM_HERE, | |
386 base::TimeDelta::FromMilliseconds(kConfigureDelayMs), | |
387 this, | |
388 &OutputConfigurator::ConfigureOutputs); | |
389 } | |
390 } | |
391 | |
392 void OutputConfigurator::NotifyOnDisplayChanged() { | 398 void OutputConfigurator::NotifyOnDisplayChanged() { |
393 FOR_EACH_OBSERVER(Observer, observers_, OnDisplayModeChanged()); | 399 FOR_EACH_OBSERVER(Observer, observers_, OnDisplayModeChanged()); |
394 } | 400 } |
395 | 401 |
396 bool OutputConfigurator::EnterStateOrFallBackToSoftwareMirroring( | 402 bool OutputConfigurator::EnterStateOrFallBackToSoftwareMirroring( |
397 OutputState output_state, | 403 OutputState output_state, |
398 DisplayPowerState power_state, | 404 DisplayPowerState power_state, |
399 const std::vector<OutputSnapshot>& outputs) { | 405 const std::vector<OutputSnapshot>& outputs) { |
400 bool success = EnterState(output_state, power_state, outputs); | 406 bool success = EnterState(output_state, power_state, outputs); |
401 if (mirroring_controller_) { | 407 if (mirroring_controller_) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
433 LOG(WARNING) << "Ignoring request to enter single mode with " | 439 LOG(WARNING) << "Ignoring request to enter single mode with " |
434 << outputs.size() << " connected outputs and " | 440 << outputs.size() << " connected outputs and " |
435 << num_on_outputs << " turned on"; | 441 << num_on_outputs << " turned on"; |
436 return false; | 442 return false; |
437 } | 443 } |
438 | 444 |
439 // Determine which output to use. | 445 // Determine which output to use. |
440 const OutputSnapshot& output = outputs.size() == 1 ? outputs[0] : | 446 const OutputSnapshot& output = outputs.size() == 1 ? outputs[0] : |
441 (output_power[0] ? outputs[0] : outputs[1]); | 447 (output_power[0] ? outputs[0] : outputs[1]); |
442 int width = 0, height = 0; | 448 int width = 0, height = 0; |
443 if (!delegate_->GetModeDetails(output.native_mode, &width, &height, NULL)) | 449 if (!delegate_->GetModeDetails( |
| 450 output.selected_mode, &width, &height, NULL)) |
444 return false; | 451 return false; |
445 | 452 |
446 std::vector<CrtcConfig> configs(outputs.size()); | 453 std::vector<CrtcConfig> configs(outputs.size()); |
447 for (size_t i = 0; i < outputs.size(); ++i) { | 454 for (size_t i = 0; i < outputs.size(); ++i) { |
448 configs[i] = CrtcConfig( | 455 configs[i] = CrtcConfig( |
449 outputs[i].crtc, 0, 0, | 456 outputs[i].crtc, 0, 0, |
450 output_power[i] ? outputs[i].native_mode : None, | 457 output_power[i] ? outputs[i].selected_mode : None, |
451 outputs[i].output); | 458 outputs[i].output); |
452 } | 459 } |
453 delegate_->CreateFrameBuffer(width, height, configs); | 460 delegate_->CreateFrameBuffer(width, height, configs); |
454 | 461 |
455 for (size_t i = 0; i < outputs.size(); ++i) { | 462 for (size_t i = 0; i < outputs.size(); ++i) { |
456 delegate_->ConfigureCrtc(&configs[i]); | 463 delegate_->ConfigureCrtc(&configs[i]); |
457 if (outputs[i].touch_device_id) { | 464 if (outputs[i].touch_device_id) { |
458 delegate_->ConfigureCTM(outputs[i].touch_device_id, | 465 delegate_->ConfigureCTM(outputs[i].touch_device_id, |
459 CoordinateTransformation()); | 466 CoordinateTransformation()); |
460 } | 467 } |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
508 << num_on_outputs << " turned on"; | 515 << num_on_outputs << " turned on"; |
509 return false; | 516 return false; |
510 } | 517 } |
511 | 518 |
512 // Pairs are [width, height] corresponding to the given output's mode. | 519 // Pairs are [width, height] corresponding to the given output's mode. |
513 std::vector<std::pair<int, int> > mode_sizes(outputs.size()); | 520 std::vector<std::pair<int, int> > mode_sizes(outputs.size()); |
514 std::vector<CrtcConfig> configs(outputs.size()); | 521 std::vector<CrtcConfig> configs(outputs.size()); |
515 int width = 0, height = 0; | 522 int width = 0, height = 0; |
516 | 523 |
517 for (size_t i = 0; i < outputs.size(); ++i) { | 524 for (size_t i = 0; i < outputs.size(); ++i) { |
518 if (!delegate_->GetModeDetails(outputs[i].native_mode, | 525 if (!delegate_->GetModeDetails(outputs[i].selected_mode, |
519 &(mode_sizes[i].first), &(mode_sizes[i].second), NULL)) { | 526 &(mode_sizes[i].first), &(mode_sizes[i].second), NULL)) { |
520 return false; | 527 return false; |
521 } | 528 } |
522 | 529 |
523 configs[i] = CrtcConfig( | 530 configs[i] = CrtcConfig( |
524 outputs[i].crtc, 0, (height ? height + kVerticalGap : 0), | 531 outputs[i].crtc, 0, (height ? height + kVerticalGap : 0), |
525 output_power[i] ? outputs[i].native_mode : None, | 532 output_power[i] ? outputs[i].selected_mode : None, |
526 outputs[i].output); | 533 outputs[i].output); |
527 | 534 |
528 // Retain the full screen size even if all outputs are off so the | 535 // Retain the full screen size even if all outputs are off so the |
529 // same desktop configuration can be restored when the outputs are | 536 // same desktop configuration can be restored when the outputs are |
530 // turned back on. | 537 // turned back on. |
531 width = std::max<int>(width, mode_sizes[i].first); | 538 width = std::max<int>(width, mode_sizes[i].first); |
532 height += (height ? kVerticalGap : 0) + mode_sizes[i].second; | 539 height += (height ? kVerticalGap : 0) + mode_sizes[i].second; |
533 } | 540 } |
534 | 541 |
535 delegate_->CreateFrameBuffer(width, height, configs); | 542 delegate_->CreateFrameBuffer(width, height, configs); |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
648 float width_ratio = static_cast<float>(mirror_mode_width) / | 655 float width_ratio = static_cast<float>(mirror_mode_width) / |
649 static_cast<float>(native_mode_width); | 656 static_cast<float>(native_mode_width); |
650 float height_ratio = static_cast<float>(mirror_mode_height) / | 657 float height_ratio = static_cast<float>(mirror_mode_height) / |
651 static_cast<float>(native_mode_height); | 658 static_cast<float>(native_mode_height); |
652 | 659 |
653 area_ratio = width_ratio * height_ratio; | 660 area_ratio = width_ratio * height_ratio; |
654 return area_ratio; | 661 return area_ratio; |
655 } | 662 } |
656 | 663 |
657 } // namespace chromeos | 664 } // namespace chromeos |
OLD | NEW |