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 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
189 delegate_->SetPanelFittingEnabled(is_panel_fitting_enabled); | 190 delegate_->SetPanelFittingEnabled(is_panel_fitting_enabled); |
190 } | 191 } |
191 | 192 |
192 void OutputConfigurator::Start(uint32 background_color_argb) { | 193 void OutputConfigurator::Start(uint32 background_color_argb) { |
193 if (!configure_display_) | 194 if (!configure_display_) |
194 return; | 195 return; |
195 | 196 |
196 delegate_->GrabServer(); | 197 delegate_->GrabServer(); |
197 delegate_->InitXRandRExtension(&xrandr_event_base_); | 198 delegate_->InitXRandRExtension(&xrandr_event_base_); |
198 | 199 |
199 std::vector<OutputSnapshot> outputs = delegate_->GetOutputs(); | 200 std::vector<OutputSnapshot> outputs = |
| 201 delegate_->GetOutputs(state_controller_); |
200 if (outputs.size() > 1 && background_color_argb) | 202 if (outputs.size() > 1 && background_color_argb) |
201 delegate_->SetBackgroundColor(background_color_argb); | 203 delegate_->SetBackgroundColor(background_color_argb); |
202 EnterStateOrFallBackToSoftwareMirroring( | 204 EnterStateOrFallBackToSoftwareMirroring( |
203 GetOutputState(outputs, power_state_), power_state_, outputs); | 205 GetOutputState(outputs, power_state_), power_state_, outputs); |
204 | 206 |
205 // Force the DPMS on chrome startup as the driver doesn't always detect | 207 // Force the DPMS on chrome startup as the driver doesn't always detect |
206 // that all displays are on when signing out. | 208 // that all displays are on when signing out. |
207 delegate_->ForceDPMSOn(); | 209 delegate_->ForceDPMSOn(); |
208 delegate_->UngrabServer(); | 210 delegate_->UngrabServer(); |
209 delegate_->SendProjectingStateToPowerManager(IsProjecting(outputs)); | 211 delegate_->SendProjectingStateToPowerManager(IsProjecting(outputs)); |
210 NotifyOnDisplayChanged(); | 212 NotifyOnDisplayChanged(); |
211 } | 213 } |
212 | 214 |
213 void OutputConfigurator::Stop() { | 215 void OutputConfigurator::Stop() { |
214 configure_display_ = false; | 216 configure_display_ = false; |
215 } | 217 } |
216 | 218 |
217 bool OutputConfigurator::SetDisplayPower(DisplayPowerState power_state, | 219 bool OutputConfigurator::SetDisplayPower(DisplayPowerState power_state, |
218 int flags) { | 220 int flags) { |
219 if (!configure_display_) | 221 if (!configure_display_) |
220 return false; | 222 return false; |
221 | 223 |
222 VLOG(1) << "SetDisplayPower: power_state=" | 224 VLOG(1) << "SetDisplayPower: power_state=" |
223 << DisplayPowerStateToString(power_state) << " flags=" << flags; | 225 << DisplayPowerStateToString(power_state) << " flags=" << flags; |
224 if (power_state == power_state_ && !(flags & kSetDisplayPowerForceProbe)) | 226 if (power_state == power_state_ && !(flags & kSetDisplayPowerForceProbe)) |
225 return true; | 227 return true; |
226 | 228 |
227 delegate_->GrabServer(); | 229 delegate_->GrabServer(); |
228 std::vector<OutputSnapshot> outputs = delegate_->GetOutputs(); | 230 std::vector<OutputSnapshot> outputs = |
| 231 delegate_->GetOutputs(state_controller_); |
229 | 232 |
230 bool only_if_single_internal_display = | 233 bool only_if_single_internal_display = |
231 flags & kSetDisplayPowerOnlyIfSingleInternalDisplay; | 234 flags & kSetDisplayPowerOnlyIfSingleInternalDisplay; |
232 bool single_internal_display = outputs.size() == 1 && outputs[0].is_internal; | 235 bool single_internal_display = outputs.size() == 1 && outputs[0].is_internal; |
233 if ((single_internal_display || !only_if_single_internal_display) && | 236 if ((single_internal_display || !only_if_single_internal_display) && |
234 EnterStateOrFallBackToSoftwareMirroring( | 237 EnterStateOrFallBackToSoftwareMirroring( |
235 GetOutputState(outputs, power_state), power_state, outputs)) { | 238 GetOutputState(outputs, power_state), power_state, outputs)) { |
236 if (power_state != DISPLAY_POWER_ALL_OFF) { | 239 if (power_state != DISPLAY_POWER_ALL_OFF) { |
237 // Force the DPMS on since the driver doesn't always detect that it | 240 // Force the DPMS on since the driver doesn't always detect that it |
238 // should turn on. This is needed when coming back from idle suspend. | 241 // should turn on. This is needed when coming back from idle suspend. |
(...skipping 13 matching lines...) Expand all Loading... |
252 if (output_state_ == new_state) { | 255 if (output_state_ == new_state) { |
253 // Cancel software mirroring if the state is moving from | 256 // Cancel software mirroring if the state is moving from |
254 // STATE_DUAL_EXTENDED to STATE_DUAL_EXTENDED. | 257 // STATE_DUAL_EXTENDED to STATE_DUAL_EXTENDED. |
255 if (mirroring_controller_ && new_state == STATE_DUAL_EXTENDED) | 258 if (mirroring_controller_ && new_state == STATE_DUAL_EXTENDED) |
256 mirroring_controller_->SetSoftwareMirroring(false); | 259 mirroring_controller_->SetSoftwareMirroring(false); |
257 NotifyOnDisplayChanged(); | 260 NotifyOnDisplayChanged(); |
258 return true; | 261 return true; |
259 } | 262 } |
260 | 263 |
261 delegate_->GrabServer(); | 264 delegate_->GrabServer(); |
262 std::vector<OutputSnapshot> outputs = delegate_->GetOutputs(); | 265 std::vector<OutputSnapshot> outputs = |
| 266 delegate_->GetOutputs(state_controller_); |
263 bool success = EnterStateOrFallBackToSoftwareMirroring( | 267 bool success = EnterStateOrFallBackToSoftwareMirroring( |
264 new_state, power_state_, outputs); | 268 new_state, power_state_, outputs); |
265 delegate_->UngrabServer(); | 269 delegate_->UngrabServer(); |
266 | 270 |
267 if (success) { | 271 if (success) { |
268 NotifyOnDisplayChanged(); | 272 NotifyOnDisplayChanged(); |
269 } else { | 273 } else { |
270 FOR_EACH_OBSERVER( | 274 FOR_EACH_OBSERVER( |
271 Observer, observers_, OnDisplayModeChangeFailed(new_state)); | 275 Observer, observers_, OnDisplayModeChangeFailed(new_state)); |
272 } | 276 } |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
344 delegate_->SyncWithServer(); | 348 delegate_->SyncWithServer(); |
345 } | 349 } |
346 } | 350 } |
347 | 351 |
348 void OutputConfigurator::ResumeDisplays() { | 352 void OutputConfigurator::ResumeDisplays() { |
349 // Force probing to ensure that we pick up any changes that were made | 353 // Force probing to ensure that we pick up any changes that were made |
350 // while the system was suspended. | 354 // while the system was suspended. |
351 SetDisplayPower(power_state_, kSetDisplayPowerForceProbe); | 355 SetDisplayPower(power_state_, kSetDisplayPowerForceProbe); |
352 } | 356 } |
353 | 357 |
| 358 void OutputConfigurator::ScheduleConfigureOutputs() { |
| 359 if (configure_timer_.get()) { |
| 360 configure_timer_->Reset(); |
| 361 } else { |
| 362 configure_timer_.reset(new base::OneShotTimer<OutputConfigurator>()); |
| 363 configure_timer_->Start( |
| 364 FROM_HERE, |
| 365 base::TimeDelta::FromMilliseconds(kConfigureDelayMs), |
| 366 this, |
| 367 &OutputConfigurator::ConfigureOutputs); |
| 368 } |
| 369 } |
| 370 |
354 void OutputConfigurator::ConfigureOutputs() { | 371 void OutputConfigurator::ConfigureOutputs() { |
355 configure_timer_.reset(); | 372 configure_timer_.reset(); |
356 | 373 |
357 delegate_->GrabServer(); | 374 delegate_->GrabServer(); |
358 std::vector<OutputSnapshot> outputs = delegate_->GetOutputs(); | 375 std::vector<OutputSnapshot> outputs = |
| 376 delegate_->GetOutputs(state_controller_); |
359 OutputState new_state = GetOutputState(outputs, power_state_); | 377 OutputState new_state = GetOutputState(outputs, power_state_); |
360 bool success = EnterStateOrFallBackToSoftwareMirroring( | 378 bool success = EnterStateOrFallBackToSoftwareMirroring( |
361 new_state, power_state_, outputs); | 379 new_state, power_state_, outputs); |
362 delegate_->UngrabServer(); | 380 delegate_->UngrabServer(); |
363 | 381 |
364 if (success) { | 382 if (success) { |
365 NotifyOnDisplayChanged(); | 383 NotifyOnDisplayChanged(); |
366 } else { | 384 } else { |
367 FOR_EACH_OBSERVER( | 385 FOR_EACH_OBSERVER( |
368 Observer, observers_, OnDisplayModeChangeFailed(new_state)); | 386 Observer, observers_, OnDisplayModeChangeFailed(new_state)); |
369 } | 387 } |
370 delegate_->SendProjectingStateToPowerManager(IsProjecting(outputs)); | 388 delegate_->SendProjectingStateToPowerManager(IsProjecting(outputs)); |
371 } | 389 } |
372 | 390 |
373 void OutputConfigurator::ScheduleConfigureOutputs() { | |
374 if (configure_timer_.get()) { | |
375 configure_timer_->Reset(); | |
376 } else { | |
377 configure_timer_.reset(new base::OneShotTimer<OutputConfigurator>()); | |
378 configure_timer_->Start( | |
379 FROM_HERE, | |
380 base::TimeDelta::FromMilliseconds(kConfigureDelayMs), | |
381 this, | |
382 &OutputConfigurator::ConfigureOutputs); | |
383 } | |
384 } | |
385 | |
386 void OutputConfigurator::NotifyOnDisplayChanged() { | 391 void OutputConfigurator::NotifyOnDisplayChanged() { |
387 FOR_EACH_OBSERVER(Observer, observers_, OnDisplayModeChanged()); | 392 FOR_EACH_OBSERVER(Observer, observers_, OnDisplayModeChanged()); |
388 } | 393 } |
389 | 394 |
390 bool OutputConfigurator::EnterStateOrFallBackToSoftwareMirroring( | 395 bool OutputConfigurator::EnterStateOrFallBackToSoftwareMirroring( |
391 OutputState output_state, | 396 OutputState output_state, |
392 DisplayPowerState power_state, | 397 DisplayPowerState power_state, |
393 const std::vector<OutputSnapshot>& outputs) { | 398 const std::vector<OutputSnapshot>& outputs) { |
394 bool success = EnterState(output_state, power_state, outputs); | 399 bool success = EnterState(output_state, power_state, outputs); |
395 if (mirroring_controller_) { | 400 if (mirroring_controller_) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
427 LOG(WARNING) << "Ignoring request to enter single mode with " | 432 LOG(WARNING) << "Ignoring request to enter single mode with " |
428 << outputs.size() << " connected outputs and " | 433 << outputs.size() << " connected outputs and " |
429 << num_on_outputs << " turned on"; | 434 << num_on_outputs << " turned on"; |
430 return false; | 435 return false; |
431 } | 436 } |
432 | 437 |
433 // Determine which output to use. | 438 // Determine which output to use. |
434 const OutputSnapshot& output = outputs.size() == 1 ? outputs[0] : | 439 const OutputSnapshot& output = outputs.size() == 1 ? outputs[0] : |
435 (output_power[0] ? outputs[0] : outputs[1]); | 440 (output_power[0] ? outputs[0] : outputs[1]); |
436 int width = 0, height = 0; | 441 int width = 0, height = 0; |
437 if (!delegate_->GetModeDetails(output.native_mode, &width, &height, NULL)) | 442 if (!delegate_->GetModeDetails( |
| 443 output.selected_mode, &width, &height, NULL)) |
438 return false; | 444 return false; |
439 | 445 |
440 std::vector<CrtcConfig> configs(outputs.size()); | 446 std::vector<CrtcConfig> configs(outputs.size()); |
441 for (size_t i = 0; i < outputs.size(); ++i) { | 447 for (size_t i = 0; i < outputs.size(); ++i) { |
442 configs[i] = CrtcConfig( | 448 configs[i] = CrtcConfig( |
443 outputs[i].crtc, 0, 0, | 449 outputs[i].crtc, 0, 0, |
444 output_power[i] ? outputs[i].native_mode : None, | 450 output_power[i] ? outputs[i].selected_mode : None, |
445 outputs[i].output); | 451 outputs[i].output); |
446 } | 452 } |
447 delegate_->CreateFrameBuffer(width, height, configs); | 453 delegate_->CreateFrameBuffer(width, height, configs); |
448 | 454 |
449 for (size_t i = 0; i < outputs.size(); ++i) { | 455 for (size_t i = 0; i < outputs.size(); ++i) { |
450 delegate_->ConfigureCrtc(&configs[i]); | 456 delegate_->ConfigureCrtc(&configs[i]); |
451 if (outputs[i].touch_device_id) { | 457 if (outputs[i].touch_device_id) { |
452 delegate_->ConfigureCTM(outputs[i].touch_device_id, | 458 delegate_->ConfigureCTM(outputs[i].touch_device_id, |
453 CoordinateTransformation()); | 459 CoordinateTransformation()); |
454 } | 460 } |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
502 << num_on_outputs << " turned on"; | 508 << num_on_outputs << " turned on"; |
503 return false; | 509 return false; |
504 } | 510 } |
505 | 511 |
506 // Pairs are [width, height] corresponding to the given output's mode. | 512 // Pairs are [width, height] corresponding to the given output's mode. |
507 std::vector<std::pair<int, int> > mode_sizes(outputs.size()); | 513 std::vector<std::pair<int, int> > mode_sizes(outputs.size()); |
508 std::vector<CrtcConfig> configs(outputs.size()); | 514 std::vector<CrtcConfig> configs(outputs.size()); |
509 int width = 0, height = 0; | 515 int width = 0, height = 0; |
510 | 516 |
511 for (size_t i = 0; i < outputs.size(); ++i) { | 517 for (size_t i = 0; i < outputs.size(); ++i) { |
512 if (!delegate_->GetModeDetails(outputs[i].native_mode, | 518 if (!delegate_->GetModeDetails(outputs[i].selected_mode, |
513 &(mode_sizes[i].first), &(mode_sizes[i].second), NULL)) { | 519 &(mode_sizes[i].first), &(mode_sizes[i].second), NULL)) { |
514 return false; | 520 return false; |
515 } | 521 } |
516 | 522 |
517 configs[i] = CrtcConfig( | 523 configs[i] = CrtcConfig( |
518 outputs[i].crtc, 0, (height ? height + kVerticalGap : 0), | 524 outputs[i].crtc, 0, (height ? height + kVerticalGap : 0), |
519 output_power[i] ? outputs[i].native_mode : None, | 525 output_power[i] ? outputs[i].selected_mode : None, |
520 outputs[i].output); | 526 outputs[i].output); |
521 | 527 |
522 // Retain the full screen size even if all outputs are off so the | 528 // Retain the full screen size even if all outputs are off so the |
523 // same desktop configuration can be restored when the outputs are | 529 // same desktop configuration can be restored when the outputs are |
524 // turned back on. | 530 // turned back on. |
525 width = std::max<int>(width, mode_sizes[i].first); | 531 width = std::max<int>(width, mode_sizes[i].first); |
526 height += (height ? kVerticalGap : 0) + mode_sizes[i].second; | 532 height += (height ? kVerticalGap : 0) + mode_sizes[i].second; |
527 } | 533 } |
528 | 534 |
529 delegate_->CreateFrameBuffer(width, height, configs); | 535 delegate_->CreateFrameBuffer(width, height, configs); |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
642 float width_ratio = static_cast<float>(mirror_mode_width) / | 648 float width_ratio = static_cast<float>(mirror_mode_width) / |
643 static_cast<float>(native_mode_width); | 649 static_cast<float>(native_mode_width); |
644 float height_ratio = static_cast<float>(mirror_mode_height) / | 650 float height_ratio = static_cast<float>(mirror_mode_height) / |
645 static_cast<float>(native_mode_height); | 651 static_cast<float>(native_mode_height); |
646 | 652 |
647 area_ratio = width_ratio * height_ratio; | 653 area_ratio = width_ratio * height_ratio; |
648 return area_ratio; | 654 return area_ratio; |
649 } | 655 } |
650 | 656 |
651 } // namespace chromeos | 657 } // namespace chromeos |
OLD | NEW |