OLD | NEW |
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/display_configurator.h" | 5 #include "ui/display/chromeos/display_configurator.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 17 matching lines...) Expand all Loading... |
28 namespace ui { | 28 namespace ui { |
29 | 29 |
30 namespace { | 30 namespace { |
31 | 31 |
32 typedef std::vector<const DisplayMode*> DisplayModeList; | 32 typedef std::vector<const DisplayMode*> DisplayModeList; |
33 | 33 |
34 // The delay to perform configuration after RRNotify. See the comment for | 34 // The delay to perform configuration after RRNotify. See the comment for |
35 // |configure_timer_|. | 35 // |configure_timer_|. |
36 const int kConfigureDelayMs = 500; | 36 const int kConfigureDelayMs = 500; |
37 | 37 |
| 38 // The delay spent before reading the display configuration after coming out of |
| 39 // suspend. While coming out of suspend the display state may be updating. This |
| 40 // is used to wait until the hardware had a chance to update the display state |
| 41 // such that we read an up to date state. |
| 42 const int kResumeDelayMs = 500; |
| 43 |
38 // The EDID specification marks the top bit of the manufacturer id as reserved. | 44 // The EDID specification marks the top bit of the manufacturer id as reserved. |
39 const int16_t kReservedManufacturerID = static_cast<int16_t>(1 << 15); | 45 const int16_t kReservedManufacturerID = static_cast<int16_t>(1 << 15); |
40 | 46 |
41 struct DisplayState { | 47 struct DisplayState { |
42 DisplaySnapshot* display = nullptr; // Not owned. | 48 DisplaySnapshot* display = nullptr; // Not owned. |
43 | 49 |
44 // User-selected mode for the display. | 50 // User-selected mode for the display. |
45 const DisplayMode* selected_mode = nullptr; | 51 const DisplayMode* selected_mode = nullptr; |
46 | 52 |
47 // Mode used when displaying the same desktop on multiple displays. | 53 // Mode used when displaying the same desktop on multiple displays. |
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
463 | 469 |
464 DisplayConfigurator::DisplayConfigurator() | 470 DisplayConfigurator::DisplayConfigurator() |
465 : state_controller_(NULL), | 471 : state_controller_(NULL), |
466 mirroring_controller_(NULL), | 472 mirroring_controller_(NULL), |
467 is_panel_fitting_enabled_(false), | 473 is_panel_fitting_enabled_(false), |
468 configure_display_(base::SysInfo::IsRunningOnChromeOS()), | 474 configure_display_(base::SysInfo::IsRunningOnChromeOS()), |
469 current_display_state_(MULTIPLE_DISPLAY_STATE_INVALID), | 475 current_display_state_(MULTIPLE_DISPLAY_STATE_INVALID), |
470 current_power_state_(chromeos::DISPLAY_POWER_ALL_ON), | 476 current_power_state_(chromeos::DISPLAY_POWER_ALL_ON), |
471 requested_display_state_(MULTIPLE_DISPLAY_STATE_INVALID), | 477 requested_display_state_(MULTIPLE_DISPLAY_STATE_INVALID), |
472 requested_power_state_(chromeos::DISPLAY_POWER_ALL_ON), | 478 requested_power_state_(chromeos::DISPLAY_POWER_ALL_ON), |
473 pending_power_state_(chromeos::DISPLAY_POWER_ALL_ON), | 479 requested_power_state_change_(false), |
474 has_pending_power_state_(false), | 480 requested_power_flags_(kSetDisplayPowerNoFlags), |
475 pending_power_flags_(kSetDisplayPowerNoFlags), | |
476 force_configure_(false), | 481 force_configure_(false), |
477 next_display_protection_client_id_(1), | 482 next_display_protection_client_id_(1), |
478 display_externally_controlled_(false), | 483 display_externally_controlled_(false), |
479 display_control_changing_(false), | 484 display_control_changing_(false), |
480 displays_suspended_(false), | 485 displays_suspended_(false), |
481 layout_manager_(new DisplayLayoutManagerImpl(this)), | 486 layout_manager_(new DisplayLayoutManagerImpl(this)), |
482 weak_ptr_factory_(this) { | 487 weak_ptr_factory_(this) { |
483 } | 488 } |
484 | 489 |
485 DisplayConfigurator::~DisplayConfigurator() { | 490 DisplayConfigurator::~DisplayConfigurator() { |
(...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
832 *display, degamma_lut, gamma_lut, correction_matrix); | 837 *display, degamma_lut, gamma_lut, correction_matrix); |
833 } | 838 } |
834 | 839 |
835 return false; | 840 return false; |
836 } | 841 } |
837 | 842 |
838 void DisplayConfigurator::PrepareForExit() { | 843 void DisplayConfigurator::PrepareForExit() { |
839 configure_display_ = false; | 844 configure_display_ = false; |
840 } | 845 } |
841 | 846 |
842 void DisplayConfigurator::SetDisplayPowerInternal( | |
843 chromeos::DisplayPowerState power_state, | |
844 int flags, | |
845 const ConfigurationCallback& callback) { | |
846 if (power_state == current_power_state_ && | |
847 !(flags & kSetDisplayPowerForceProbe)) { | |
848 callback.Run(true); | |
849 return; | |
850 } | |
851 | |
852 pending_power_state_ = power_state; | |
853 has_pending_power_state_ = true; | |
854 pending_power_flags_ = flags; | |
855 queued_configuration_callbacks_.push_back(callback); | |
856 | |
857 RunPendingConfiguration(); | |
858 } | |
859 | |
860 void DisplayConfigurator::SetDisplayPower( | 847 void DisplayConfigurator::SetDisplayPower( |
861 chromeos::DisplayPowerState power_state, | 848 chromeos::DisplayPowerState power_state, |
862 int flags, | 849 int flags, |
863 const ConfigurationCallback& callback) { | 850 const ConfigurationCallback& callback) { |
864 if (!configure_display_ || display_externally_controlled_) { | 851 if (!configure_display_ || display_externally_controlled_) { |
865 callback.Run(false); | 852 callback.Run(false); |
866 return; | 853 return; |
867 } | 854 } |
868 | 855 |
869 VLOG(1) << "SetDisplayPower: power_state=" | 856 VLOG(1) << "SetDisplayPower: power_state=" |
870 << DisplayPowerStateToString(power_state) << " flags=" << flags | 857 << DisplayPowerStateToString(power_state) << " flags=" << flags |
871 << ", configure timer=" | 858 << ", configure timer=" |
872 << (configure_timer_.IsRunning() ? "Running" : "Stopped"); | 859 << (configure_timer_.IsRunning() ? "Running" : "Stopped"); |
| 860 if (power_state == requested_power_state_ && |
| 861 !(flags & kSetDisplayPowerForceProbe)) { |
| 862 callback.Run(true); |
| 863 return; |
| 864 } |
873 | 865 |
874 requested_power_state_ = power_state; | 866 requested_power_state_ = power_state; |
875 SetDisplayPowerInternal(requested_power_state_, flags, callback); | 867 requested_power_state_change_ = true; |
| 868 requested_power_flags_ = flags; |
| 869 queued_configuration_callbacks_.push_back(callback); |
| 870 |
| 871 RunPendingConfiguration(); |
876 } | 872 } |
877 | 873 |
878 void DisplayConfigurator::SetDisplayMode(MultipleDisplayState new_state) { | 874 void DisplayConfigurator::SetDisplayMode(MultipleDisplayState new_state) { |
879 if (!configure_display_ || display_externally_controlled_) | 875 if (!configure_display_ || display_externally_controlled_) |
880 return; | 876 return; |
881 | 877 |
882 VLOG(1) << "SetDisplayMode: state=" | 878 VLOG(1) << "SetDisplayMode: state=" |
883 << MultipleDisplayStateToString(new_state); | 879 << MultipleDisplayStateToString(new_state); |
884 if (current_display_state_ == new_state) { | 880 if (current_display_state_ == new_state) { |
885 // Cancel software mirroring if the state is moving from | 881 // Cancel software mirroring if the state is moving from |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
928 void DisplayConfigurator::AddObserver(Observer* observer) { | 924 void DisplayConfigurator::AddObserver(Observer* observer) { |
929 observers_.AddObserver(observer); | 925 observers_.AddObserver(observer); |
930 } | 926 } |
931 | 927 |
932 void DisplayConfigurator::RemoveObserver(Observer* observer) { | 928 void DisplayConfigurator::RemoveObserver(Observer* observer) { |
933 observers_.RemoveObserver(observer); | 929 observers_.RemoveObserver(observer); |
934 } | 930 } |
935 | 931 |
936 void DisplayConfigurator::SuspendDisplays( | 932 void DisplayConfigurator::SuspendDisplays( |
937 const ConfigurationCallback& callback) { | 933 const ConfigurationCallback& callback) { |
938 if (!configure_display_ || display_externally_controlled_) { | 934 // If the display is off due to user inactivity and there's only a single |
939 callback.Run(false); | 935 // internal display connected, switch to the all-on state before |
940 return; | 936 // suspending. This shouldn't be very noticeable to the user since the |
| 937 // backlight is off at this point, and doing this lets us resume directly |
| 938 // into the "on" state, which greatly reduces resume times. |
| 939 if (requested_power_state_ == chromeos::DISPLAY_POWER_ALL_OFF) { |
| 940 SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON, |
| 941 kSetDisplayPowerOnlyIfSingleInternalDisplay, callback); |
| 942 |
| 943 // We need to make sure that the monitor configuration we just did actually |
| 944 // completes before we return, because otherwise the X message could be |
| 945 // racing with the HandleSuspendReadiness message. |
| 946 native_display_delegate_->SyncWithServer(); |
| 947 } else { |
| 948 callback.Run(true); |
941 } | 949 } |
942 | 950 |
943 displays_suspended_ = true; | 951 displays_suspended_ = true; |
944 | 952 |
945 // Stop |configure_timer_| because we will force probe and configure all the | 953 // Stop |configure_timer_| because we will force probe and configure all the |
946 // displays at resume time anyway. | 954 // displays at resume time anyway. |
947 configure_timer_.Stop(); | 955 configure_timer_.Stop(); |
948 | |
949 // Turn off the displays for suspend. This way, if we wake up for lucid sleep, | |
950 // the displays will not turn on (all displays should be off for lucid sleep | |
951 // unless explicitly requested by lucid sleep code). Use | |
952 // SetDisplayPowerInternal so requested_power_state_ is maintained. | |
953 SetDisplayPowerInternal(chromeos::DISPLAY_POWER_ALL_OFF, | |
954 kSetDisplayPowerNoFlags, callback); | |
955 | |
956 // We need to make sure that the monitor configuration we just did actually | |
957 // completes before we return. | |
958 native_display_delegate_->SyncWithServer(); | |
959 } | 956 } |
960 | 957 |
961 void DisplayConfigurator::ResumeDisplays() { | 958 void DisplayConfigurator::ResumeDisplays() { |
962 if (!configure_display_ || display_externally_controlled_) | |
963 return; | |
964 | |
965 displays_suspended_ = false; | 959 displays_suspended_ = false; |
966 | 960 |
967 // If requested_power_state_ is ALL_OFF due to idle suspend, powerd will turn | 961 configure_timer_.Start( |
968 // the display power on when it enables the backlight. | 962 FROM_HERE, |
969 SetDisplayPower(requested_power_state_, kSetDisplayPowerNoFlags, | 963 base::TimeDelta::FromMilliseconds(kResumeDelayMs), |
970 base::Bind(&DoNothing)); | 964 base::Bind(&DisplayConfigurator::RestoreRequestedPowerStateAfterResume, |
| 965 base::Unretained(this))); |
971 } | 966 } |
972 | 967 |
973 void DisplayConfigurator::ConfigureDisplays() { | 968 void DisplayConfigurator::ConfigureDisplays() { |
974 if (!configure_display_ || display_externally_controlled_) | 969 if (!configure_display_ || display_externally_controlled_) |
975 return; | 970 return; |
976 | 971 |
977 force_configure_ = true; | 972 force_configure_ = true; |
978 RunPendingConfiguration(); | 973 RunPendingConfiguration(); |
979 } | 974 } |
980 | 975 |
981 void DisplayConfigurator::RunPendingConfiguration() { | 976 void DisplayConfigurator::RunPendingConfiguration() { |
982 // Configuration task is currently running. Do not start a second | 977 // Configuration task is currently running. Do not start a second |
983 // configuration. | 978 // configuration. |
984 if (configuration_task_) | 979 if (configuration_task_) |
985 return; | 980 return; |
986 | 981 |
987 if (!ShouldRunConfigurationTask()) { | 982 if (!ShouldRunConfigurationTask()) { |
988 LOG(ERROR) << "Called RunPendingConfiguration without any changes" | 983 LOG(ERROR) << "Called RunPendingConfiguration without any changes" |
989 " requested"; | 984 " requested"; |
990 CallAndClearQueuedCallbacks(true); | 985 CallAndClearQueuedCallbacks(true); |
991 return; | 986 return; |
992 } | 987 } |
993 | 988 |
994 configuration_task_.reset(new UpdateDisplayConfigurationTask( | 989 configuration_task_.reset(new UpdateDisplayConfigurationTask( |
995 native_display_delegate_.get(), layout_manager_.get(), | 990 native_display_delegate_.get(), layout_manager_.get(), |
996 requested_display_state_, pending_power_state_, pending_power_flags_, | 991 requested_display_state_, requested_power_state_, requested_power_flags_, |
997 0, force_configure_, base::Bind(&DisplayConfigurator::OnConfigured, | 992 0, force_configure_, base::Bind(&DisplayConfigurator::OnConfigured, |
998 weak_ptr_factory_.GetWeakPtr()))); | 993 weak_ptr_factory_.GetWeakPtr()))); |
999 configuration_task_->set_virtual_display_snapshots( | 994 configuration_task_->set_virtual_display_snapshots( |
1000 virtual_display_snapshots_.get()); | 995 virtual_display_snapshots_.get()); |
1001 | 996 |
1002 // Reset the flags before running the task; otherwise it may end up scheduling | 997 // Reset the flags before running the task; otherwise it may end up scheduling |
1003 // another configuration. | 998 // another configuration. |
1004 force_configure_ = false; | 999 force_configure_ = false; |
1005 pending_power_flags_ = kSetDisplayPowerNoFlags; | 1000 requested_power_flags_ = kSetDisplayPowerNoFlags; |
1006 has_pending_power_state_ = false; | 1001 requested_power_state_change_ = false; |
1007 requested_display_state_ = MULTIPLE_DISPLAY_STATE_INVALID; | 1002 requested_display_state_ = MULTIPLE_DISPLAY_STATE_INVALID; |
1008 | 1003 |
1009 DCHECK(in_progress_configuration_callbacks_.empty()); | 1004 DCHECK(in_progress_configuration_callbacks_.empty()); |
1010 in_progress_configuration_callbacks_.swap(queued_configuration_callbacks_); | 1005 in_progress_configuration_callbacks_.swap(queued_configuration_callbacks_); |
1011 | 1006 |
1012 configuration_task_->Run(); | 1007 configuration_task_->Run(); |
1013 } | 1008 } |
1014 | 1009 |
1015 void DisplayConfigurator::OnConfigured( | 1010 void DisplayConfigurator::OnConfigured( |
1016 bool success, | 1011 bool success, |
(...skipping 15 matching lines...) Expand all Loading... |
1032 // or all displays are off. | 1027 // or all displays are off. |
1033 DCHECK(!framebuffer_size.IsEmpty() || | 1028 DCHECK(!framebuffer_size.IsEmpty() || |
1034 (mirroring_controller_ && | 1029 (mirroring_controller_ && |
1035 mirroring_controller_->SoftwareMirroringEnabled()) || | 1030 mirroring_controller_->SoftwareMirroringEnabled()) || |
1036 new_display_state == MULTIPLE_DISPLAY_STATE_HEADLESS || | 1031 new_display_state == MULTIPLE_DISPLAY_STATE_HEADLESS || |
1037 new_power_state == chromeos::DISPLAY_POWER_ALL_OFF); | 1032 new_power_state == chromeos::DISPLAY_POWER_ALL_OFF); |
1038 | 1033 |
1039 if (!framebuffer_size.IsEmpty()) | 1034 if (!framebuffer_size.IsEmpty()) |
1040 framebuffer_size_ = framebuffer_size; | 1035 framebuffer_size_ = framebuffer_size; |
1041 | 1036 |
1042 // If the pending power state hasn't changed then make sure that value | 1037 // If the requested power state hasn't changed then make sure that value |
1043 // gets updated as well since the last requested value may have been | 1038 // gets updated as well since the last requested value may have been |
1044 // dependent on certain conditions (ie: if only the internal monitor was | 1039 // dependent on certain conditions (ie: if only the internal monitor was |
1045 // present). | 1040 // present). |
1046 if (!has_pending_power_state_) | 1041 if (!requested_power_state_change_) |
1047 pending_power_state_ = new_power_state; | 1042 requested_power_state_ = new_power_state; |
1048 | 1043 |
1049 if (old_power_state != current_power_state_) | 1044 if (old_power_state != current_power_state_) |
1050 NotifyPowerStateObservers(); | 1045 NotifyPowerStateObservers(); |
1051 } | 1046 } |
1052 | 1047 |
1053 configuration_task_.reset(); | 1048 configuration_task_.reset(); |
1054 NotifyDisplayStateObservers(success, new_display_state); | 1049 NotifyDisplayStateObservers(success, new_display_state); |
1055 CallAndClearInProgressCallbacks(success); | 1050 CallAndClearInProgressCallbacks(success); |
1056 | 1051 |
1057 if (success && !configure_timer_.IsRunning() && | 1052 if (success && !configure_timer_.IsRunning() && |
(...skipping 12 matching lines...) Expand all Loading... |
1070 bool DisplayConfigurator::ShouldRunConfigurationTask() const { | 1065 bool DisplayConfigurator::ShouldRunConfigurationTask() const { |
1071 if (force_configure_) | 1066 if (force_configure_) |
1072 return true; | 1067 return true; |
1073 | 1068 |
1074 // Schedule if there is a request to change the display state. | 1069 // Schedule if there is a request to change the display state. |
1075 if (requested_display_state_ != current_display_state_ && | 1070 if (requested_display_state_ != current_display_state_ && |
1076 requested_display_state_ != MULTIPLE_DISPLAY_STATE_INVALID) | 1071 requested_display_state_ != MULTIPLE_DISPLAY_STATE_INVALID) |
1077 return true; | 1072 return true; |
1078 | 1073 |
1079 // Schedule if there is a request to change the power state. | 1074 // Schedule if there is a request to change the power state. |
1080 if (has_pending_power_state_) | 1075 if (requested_power_state_change_) |
1081 return true; | 1076 return true; |
1082 | 1077 |
1083 return false; | 1078 return false; |
1084 } | 1079 } |
1085 | 1080 |
1086 void DisplayConfigurator::CallAndClearInProgressCallbacks(bool success) { | 1081 void DisplayConfigurator::CallAndClearInProgressCallbacks(bool success) { |
1087 for (const auto& callback : in_progress_configuration_callbacks_) | 1082 for (const auto& callback : in_progress_configuration_callbacks_) |
1088 callback.Run(success); | 1083 callback.Run(success); |
1089 | 1084 |
1090 in_progress_configuration_callbacks_.clear(); | 1085 in_progress_configuration_callbacks_.clear(); |
1091 } | 1086 } |
1092 | 1087 |
1093 void DisplayConfigurator::CallAndClearQueuedCallbacks(bool success) { | 1088 void DisplayConfigurator::CallAndClearQueuedCallbacks(bool success) { |
1094 for (const auto& callback : queued_configuration_callbacks_) | 1089 for (const auto& callback : queued_configuration_callbacks_) |
1095 callback.Run(success); | 1090 callback.Run(success); |
1096 | 1091 |
1097 queued_configuration_callbacks_.clear(); | 1092 queued_configuration_callbacks_.clear(); |
1098 } | 1093 } |
1099 | 1094 |
| 1095 void DisplayConfigurator::RestoreRequestedPowerStateAfterResume() { |
| 1096 // Force probing to ensure that we pick up any changes that were made while |
| 1097 // the system was suspended. |
| 1098 SetDisplayPower(requested_power_state_, kSetDisplayPowerForceProbe, |
| 1099 base::Bind(&DoNothing)); |
| 1100 } |
| 1101 |
1100 void DisplayConfigurator::NotifyDisplayStateObservers( | 1102 void DisplayConfigurator::NotifyDisplayStateObservers( |
1101 bool success, | 1103 bool success, |
1102 MultipleDisplayState attempted_state) { | 1104 MultipleDisplayState attempted_state) { |
1103 if (success) { | 1105 if (success) { |
1104 FOR_EACH_OBSERVER( | 1106 FOR_EACH_OBSERVER( |
1105 Observer, observers_, OnDisplayModeChanged(cached_displays_)); | 1107 Observer, observers_, OnDisplayModeChanged(cached_displays_)); |
1106 } else { | 1108 } else { |
1107 FOR_EACH_OBSERVER( | 1109 FOR_EACH_OBSERVER( |
1108 Observer, observers_, OnDisplayModeChangeFailed(cached_displays_, | 1110 Observer, observers_, OnDisplayModeChangeFailed(cached_displays_, |
1109 attempted_state)); | 1111 attempted_state)); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1152 last_virtual_display_id_ = max_display_id & 0xff; | 1154 last_virtual_display_id_ = max_display_id & 0xff; |
1153 | 1155 |
1154 return true; | 1156 return true; |
1155 } | 1157 } |
1156 | 1158 |
1157 bool DisplayConfigurator::IsDisplayOn() const { | 1159 bool DisplayConfigurator::IsDisplayOn() const { |
1158 return current_power_state_ != chromeos::DISPLAY_POWER_ALL_OFF; | 1160 return current_power_state_ != chromeos::DISPLAY_POWER_ALL_OFF; |
1159 } | 1161 } |
1160 | 1162 |
1161 } // namespace ui | 1163 } // namespace ui |
OLD | NEW |