| 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 |