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