Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(40)

Side by Side Diff: ui/display/chromeos/display_configurator.cc

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

Powered by Google App Engine
This is Rietveld 408576698