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

Side by Side Diff: chromeos/display/output_configurator.cc

Issue 13006006: chromeos: Support turning displays off in extended mode. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: merge Created 7 years, 8 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 | Annotate | Revision Log
« no previous file with comments | « chromeos/display/output_configurator.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 <cmath> 7 #include <cmath>
8 8
9 #include <X11/Xatom.h> 9 #include <X11/Xatom.h>
10 #include <X11/Xlib.h> 10 #include <X11/Xlib.h>
(...skipping 10 matching lines...) Expand all
21 #undef Status 21 #undef Status
22 #undef RootWindow 22 #undef RootWindow
23 23
24 #include "base/bind.h" 24 #include "base/bind.h"
25 #include "base/chromeos/chromeos_version.h" 25 #include "base/chromeos/chromeos_version.h"
26 #include "base/debug/trace_event.h" 26 #include "base/debug/trace_event.h"
27 #include "base/logging.h" 27 #include "base/logging.h"
28 #include "base/message_pump_aurax11.h" 28 #include "base/message_pump_aurax11.h"
29 #include "base/metrics/histogram.h" 29 #include "base/metrics/histogram.h"
30 #include "base/perftimer.h" 30 #include "base/perftimer.h"
31 #include "base/strings/string_number_conversions.h"
31 #include "base/time.h" 32 #include "base/time.h"
32 #include "chromeos/dbus/dbus_thread_manager.h" 33 #include "chromeos/dbus/dbus_thread_manager.h"
33 #include "chromeos/dbus/power_manager_client.h" 34 #include "chromeos/dbus/power_manager_client.h"
34 35
35 namespace chromeos { 36 namespace chromeos {
36 37
37 struct OutputSnapshot { 38 struct OutputSnapshot {
38 RROutput output; 39 RROutput output;
39 RRCrtc crtc; 40 RRCrtc crtc;
40 RRMode current_mode; 41 RRMode current_mode;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 }; 87 };
87 88
88 enum MirrorModeType { 89 enum MirrorModeType {
89 MIRROR_MODE_NONE, 90 MIRROR_MODE_NONE,
90 MIRROR_MODE_ASPECT_PRESERVING, 91 MIRROR_MODE_ASPECT_PRESERVING,
91 MIRROR_MODE_FALLBACK, 92 MIRROR_MODE_FALLBACK,
92 MIRROR_MODE_TYPE_COUNT 93 MIRROR_MODE_TYPE_COUNT
93 }; 94 };
94 95
95 namespace { 96 namespace {
97
96 // DPI measurements. 98 // DPI measurements.
97 const float kMmInInch = 25.4; 99 const float kMmInInch = 25.4;
98 const float kDpi96 = 96.0; 100 const float kDpi96 = 96.0;
99 const float kPixelsToMmScale = kMmInInch / kDpi96; 101 const float kPixelsToMmScale = kMmInInch / kDpi96;
100 102
101 // The DPI threshold to detech high density screen. 103 // The DPI threshold to detech high density screen.
102 // Higher DPI than this will use device_scale_factor=2 104 // Higher DPI than this will use device_scale_factor=2
103 // Should be kept in sync with display_change_observer_x11.cc 105 // Should be kept in sync with display_change_observer_x11.cc
104 const unsigned int kHighDensityDIPThreshold = 160; 106 const unsigned int kHighDensityDIPThreshold = 160;
105 107
106 // Prefixes for the built-in displays. 108 // Prefixes for the built-in displays.
107 const char kInternal_LVDS[] = "LVDS"; 109 const char kInternal_LVDS[] = "LVDS";
108 const char kInternal_eDP[] = "eDP"; 110 const char kInternal_eDP[] = "eDP";
109 111
110 // The delay to perform configuration after RRNotify. See the comment 112 // The delay to perform configuration after RRNotify. See the comment
111 // in |Dispatch()|. 113 // in |Dispatch()|.
112 const int64 kConfigureDelayMs = 500; 114 const int64 kConfigureDelayMs = 500;
113 115
114 // Gap between screens so cursor at bottom of active display doesn't partially 116 // Gap between screens so cursor at bottom of active display doesn't partially
115 // appear on top of inactive display. Higher numbers guard against larger 117 // appear on top of inactive display. Higher numbers guard against larger
116 // cursors, but also waste more memory. 118 // cursors, but also waste more memory.
117 // For simplicity, this is hard-coded to 60 to avoid the complexity of always 119 // For simplicity, this is hard-coded to 60 to avoid the complexity of always
118 // determining the DPI of the screen and rationalizing which screen we need to 120 // determining the DPI of the screen and rationalizing which screen we need to
119 // use for the DPI calculation. 121 // use for the DPI calculation.
120 // See crbug.com/130188 for initial discussion. 122 // See crbug.com/130188 for initial discussion.
121 const int kVerticalGap = 60; 123 const int kVerticalGap = 60;
122 124
125 // Returns a string describing |state|.
126 std::string DisplayPowerStateToString(DisplayPowerState state) {
127 switch (state) {
128 case DISPLAY_POWER_ALL_ON:
129 return "ALL_ON";
130 case DISPLAY_POWER_ALL_OFF:
131 return "ALL_OFF";
132 case DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON:
133 return "INTERNAL_OFF_EXTERNAL_ON";
134 case DISPLAY_POWER_INTERNAL_ON_EXTERNAL_OFF:
135 return "INTERNAL_ON_EXTERNAL_OFF";
136 default:
137 return "unknown (" + base::IntToString(state) + ")";
138 }
139 }
140
123 // TODO: Determine if we need to organize modes in a way which provides better 141 // TODO: Determine if we need to organize modes in a way which provides better
124 // than O(n) lookup time. In many call sites, for example, the "next" mode is 142 // than O(n) lookup time. In many call sites, for example, the "next" mode is
125 // typically what we are looking for so using this helper might be too 143 // typically what we are looking for so using this helper might be too
126 // expensive. 144 // expensive.
127 XRRModeInfo* ModeInfoForID(XRRScreenResources* screen, RRMode modeID) { 145 XRRModeInfo* ModeInfoForID(XRRScreenResources* screen, RRMode modeID) {
128 XRRModeInfo* result = NULL; 146 XRRModeInfo* result = NULL;
129 for (int i = 0; (i < screen->nmode) && (result == NULL); i++) 147 for (int i = 0; (i < screen->nmode) && (result == NULL); i++)
130 if (modeID == screen->modes[i].id) 148 if (modeID == screen->modes[i].id)
131 result = &screen->modes[i]; 149 result = &screen->modes[i];
132 150
(...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after
590 608
591 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()-> 609 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
592 SetIsProjecting(is_projecting); 610 SetIsProjecting(is_projecting);
593 } 611 }
594 612
595 void OutputConfigurator::Stop() { 613 void OutputConfigurator::Stop() {
596 configure_display_ = false; 614 configure_display_ = false;
597 } 615 }
598 616
599 bool OutputConfigurator::SetDisplayPower(DisplayPowerState power_state, 617 bool OutputConfigurator::SetDisplayPower(DisplayPowerState power_state,
600 bool force_probe) { 618 int flags) {
601 TRACE_EVENT0("chromeos", "OutputConfigurator::SetDisplayPower"); 619 TRACE_EVENT0("chromeos", "OutputConfigurator::SetDisplayPower");
602 VLOG(1) << "OutputConfigurator::SetDisplayPower: power_state=" << power_state 620 VLOG(1) << "SetDisplayPower: power_state="
603 << " force_probe=" << force_probe; 621 << DisplayPowerStateToString(power_state) << " flags=" << flags;
604 622
605 if (!configure_display_) 623 if (!configure_display_)
606 return false; 624 return false;
607 if (power_state == power_state_ && !force_probe) 625 if (power_state == power_state_ && !(flags & kSetDisplayPowerForceProbe))
608 return true; 626 return true;
609 627
610 Display* display = base::MessagePumpAuraX11::GetDefaultXDisplay(); 628 Display* display = base::MessagePumpAuraX11::GetDefaultXDisplay();
611 CHECK(display); 629 CHECK(display);
612 XGrabServer(display); 630 XGrabServer(display);
613 Window window = DefaultRootWindow(display); 631 Window window = DefaultRootWindow(display);
614 XRRScreenResources* screen = GetScreenResourcesAndRecordUMA(display, window); 632 XRRScreenResources* screen = GetScreenResourcesAndRecordUMA(display, window);
615 CHECK(screen); 633 CHECK(screen);
616 std::vector<OutputSnapshot> outputs = GetDualOutputs(display, screen); 634 std::vector<OutputSnapshot> outputs = GetDualOutputs(display, screen);
617 connected_output_count_ = outputs.size(); 635 connected_output_count_ = outputs.size();
618 636
619 if (EnterState(display, screen, window, output_state_, power_state, 637 bool only_if_single_internal_display =
638 flags & kSetDisplayPowerOnlyIfSingleInternalDisplay;
639 bool single_internal_display = outputs.size() == 1 && outputs[0].is_internal;
640 if ((single_internal_display || !only_if_single_internal_display) &&
641 EnterState(display, screen, window, output_state_, power_state,
620 outputs)) { 642 outputs)) {
621 power_state_ = power_state; 643 power_state_ = power_state;
622 if (power_state != DISPLAY_POWER_ALL_OFF) { 644 if (power_state != DISPLAY_POWER_ALL_OFF) {
623 // Force the DPMS on since the driver doesn't always detect that it 645 // Force the DPMS on since the driver doesn't always detect that it
624 // should turn on. This is needed when coming back from idle suspend. 646 // should turn on. This is needed when coming back from idle suspend.
625 CHECK(DPMSEnable(display)); 647 CHECK(DPMSEnable(display));
626 CHECK(DPMSForceLevel(display, DPMSModeOn)); 648 CHECK(DPMSForceLevel(display, DPMSModeOn));
627 } 649 }
628 } 650 }
629 651
630 XRRFreeScreenResources(screen); 652 XRRFreeScreenResources(screen);
631 XUngrabServer(display); 653 XUngrabServer(display);
632
633 return true; 654 return true;
634 } 655 }
635 656
636 bool OutputConfigurator::SetDisplayMode(OutputState new_state) { 657 bool OutputConfigurator::SetDisplayMode(OutputState new_state) {
637 TRACE_EVENT0("chromeos", "OutputConfigurator::SetDisplayMode"); 658 TRACE_EVENT0("chromeos", "OutputConfigurator::SetDisplayMode");
638 if (output_state_ == STATE_INVALID || 659 if (output_state_ == STATE_INVALID ||
639 output_state_ == STATE_HEADLESS || 660 output_state_ == STATE_HEADLESS ||
640 output_state_ == STATE_SINGLE) 661 output_state_ == STATE_SINGLE)
641 return false; 662 return false;
642 663
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
750 void OutputConfigurator::RemoveObserver(Observer* observer) { 771 void OutputConfigurator::RemoveObserver(Observer* observer) {
751 observers_.RemoveObserver(observer); 772 observers_.RemoveObserver(observer);
752 } 773 }
753 774
754 // static 775 // static
755 bool OutputConfigurator::IsInternalOutputName(const std::string& name) { 776 bool OutputConfigurator::IsInternalOutputName(const std::string& name) {
756 return name.find(kInternal_LVDS) == 0 || name.find(kInternal_eDP) == 0; 777 return name.find(kInternal_LVDS) == 0 || name.find(kInternal_eDP) == 0;
757 } 778 }
758 779
759 void OutputConfigurator::SuspendDisplays() { 780 void OutputConfigurator::SuspendDisplays() {
760 // Turn internal displays on before suspend. At this point, the backlight 781 // If the display is off due to user inactivity and there's only a single
761 // is off, so we turn on the internal display so that we can resume 782 // internal display connected, switch to the all-on state before
762 // directly into "on" state. This greatly reduces resume times. 783 // suspending. This shouldn't be very noticeable to the user since the
763 SetDisplayPower(DISPLAY_POWER_INTERNAL_ON_EXTERNAL_OFF, false); 784 // backlight is off at this point, and doing this lets us resume directly
785 // into the "on" state, which greatly reduces resume times.
786 if (power_state_ == DISPLAY_POWER_ALL_OFF) {
787 SetDisplayPower(DISPLAY_POWER_ALL_ON,
788 kSetDisplayPowerOnlyIfSingleInternalDisplay);
789 }
764 790
765 // We need to make sure that the monitor configuration we just did actually 791 // We need to make sure that the monitor configuration we just did actually
766 // completes before we return, because otherwise the X message could be 792 // completes before we return, because otherwise the X message could be
767 // racing with the HandleSuspendReadiness message. 793 // racing with the HandleSuspendReadiness message.
768 XSync(base::MessagePumpAuraX11::GetDefaultXDisplay(), 0); 794 XSync(base::MessagePumpAuraX11::GetDefaultXDisplay(), 0);
769 } 795 }
770 796
771 void OutputConfigurator::ResumeDisplays() { 797 void OutputConfigurator::ResumeDisplays() {
772 // Force probing to ensure that we pick up any changes that were made 798 // Force probing to ensure that we pick up any changes that were made
773 // while the system was suspended. 799 // while the system was suspended.
774 SetDisplayPower(DISPLAY_POWER_ALL_ON, true); 800 SetDisplayPower(power_state_, kSetDisplayPowerForceProbe);
775 } 801 }
776 802
777 void OutputConfigurator::NotifyOnDisplayChanged() { 803 void OutputConfigurator::NotifyOnDisplayChanged() {
778 TRACE_EVENT0("chromeos", "OutputConfigurator::NotifyOnDisplayChanged"); 804 TRACE_EVENT0("chromeos", "OutputConfigurator::NotifyOnDisplayChanged");
779 FOR_EACH_OBSERVER(Observer, observers_, OnDisplayModeChanged()); 805 FOR_EACH_OBSERVER(Observer, observers_, OnDisplayModeChanged());
780 } 806 }
781 807
782 std::vector<OutputSnapshot> OutputConfigurator::GetDualOutputs( 808 std::vector<OutputSnapshot> OutputConfigurator::GetDualOutputs(
783 Display* display, 809 Display* display,
784 XRRScreenResources* screen) { 810 XRRScreenResources* screen) {
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after
1095 } 1121 }
1096 1122
1097 bool OutputConfigurator::EnterState( 1123 bool OutputConfigurator::EnterState(
1098 Display* display, 1124 Display* display,
1099 XRRScreenResources* screen, 1125 XRRScreenResources* screen,
1100 Window window, 1126 Window window,
1101 OutputState output_state, 1127 OutputState output_state,
1102 DisplayPowerState power_state, 1128 DisplayPowerState power_state,
1103 const std::vector<OutputSnapshot>& outputs) { 1129 const std::vector<OutputSnapshot>& outputs) {
1104 TRACE_EVENT0("chromeos", "OutputConfigurator::EnterState"); 1130 TRACE_EVENT0("chromeos", "OutputConfigurator::EnterState");
1131
1132 std::vector<RRCrtc> crtcs(outputs.size());
1133 std::vector<bool> output_power(outputs.size());
1134 bool all_outputs_off = true;
1135
1136 RRCrtc prev_crtc = None;
1137 for (size_t i = 0; i < outputs.size(); prev_crtc = crtcs[i], ++i) {
1138 crtcs[i] = GetNextCrtcAfter(display, screen, outputs[i].output, prev_crtc);
1139 output_power[i] = power_state == DISPLAY_POWER_ALL_ON ||
1140 (power_state == DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON &&
1141 !outputs[i].is_internal) ||
1142 (power_state == DISPLAY_POWER_INTERNAL_ON_EXTERNAL_OFF &&
1143 outputs[i].is_internal);
1144 if (output_power[i])
1145 all_outputs_off = false;
1146 }
1147
1105 switch (outputs.size()) { 1148 switch (outputs.size()) {
1106 case 0: 1149 case 0:
1107 // Do nothing as no 0-display states are supported. 1150 // Do nothing as no 0-display states are supported.
1108 break; 1151 break;
1109 case 1: { 1152 case 1: {
1110 // Re-allocate the framebuffer to fit. 1153 // Re-allocate the framebuffer to fit.
1111 XRRModeInfo* mode_info = ModeInfoForID(screen, outputs[0].native_mode); 1154 XRRModeInfo* mode_info = ModeInfoForID(screen, outputs[0].native_mode);
1112 if (mode_info == NULL) { 1155 if (!mode_info) {
1113 UMA_HISTOGRAM_COUNTS("Display.EnterState.single_failures", 1); 1156 UMA_HISTOGRAM_COUNTS("Display.EnterState.single_failures", 1);
1114 return false; 1157 return false;
1115 } 1158 }
1116 1159
1117 bool power_on = power_state == DISPLAY_POWER_ALL_ON || 1160 CrtcConfig config(crtcs[0], 0, 0,
1118 (power_state == DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON && 1161 output_power[0] ? outputs[0].native_mode : None,
1119 !outputs[0].is_internal) || 1162 outputs[0].output);
1120 (power_state == DISPLAY_POWER_INTERNAL_ON_EXTERNAL_OFF &&
1121 outputs[0].is_internal);
1122 CrtcConfig config(
1123 GetNextCrtcAfter(display, screen, outputs[0].output, None),
1124 0, 0, power_on ? outputs[0].native_mode : None, outputs[0].output);
1125
1126 CreateFrameBuffer(display, screen, window, mode_info->width, 1163 CreateFrameBuffer(display, screen, window, mode_info->width,
1127 mode_info->height, &config, NULL); 1164 mode_info->height, &config, NULL);
1128
1129 ConfigureCrtc(display, screen, &config); 1165 ConfigureCrtc(display, screen, &config);
1130 1166 if (outputs[0].touch_device_id) {
1131 // Restore identity transformation for single monitor in native mode. 1167 // Restore identity transformation for single monitor in native mode.
1132 if (outputs[0].touch_device_id != None) { 1168 ConfigureCTM(display, outputs[0].touch_device_id,
1133 CoordinateTransformation ctm; // Defaults to identity 1169 CoordinateTransformation());
1134 ConfigureCTM(display, outputs[0].touch_device_id, ctm);
1135 } 1170 }
1136 break; 1171 break;
1137 } 1172 }
1138 case 2: { 1173 case 2: {
1139 RRCrtc primary_crtc =
1140 GetNextCrtcAfter(display, screen, outputs[0].output, None);
1141 RRCrtc secondary_crtc =
1142 GetNextCrtcAfter(display, screen, outputs[1].output, primary_crtc);
1143
1144 // Workaround for crbug.com/148365: leave internal display on for
1145 // internal-off, external-on so user can move cursor (and hence
1146 // windows) onto internal display even when it's off.
1147 bool primary_power_on = power_state == DISPLAY_POWER_ALL_ON ||
1148 (power_state == DISPLAY_POWER_INTERNAL_ON_EXTERNAL_OFF &&
1149 outputs[0].is_internal);
1150 bool secondary_power_on = power_state == DISPLAY_POWER_ALL_ON ||
1151 (power_state == DISPLAY_POWER_INTERNAL_ON_EXTERNAL_OFF &&
1152 outputs[1].is_internal);
1153
1154 if (output_state == STATE_DUAL_MIRROR) { 1174 if (output_state == STATE_DUAL_MIRROR) {
1155 XRRModeInfo* mode_info = ModeInfoForID(screen, outputs[0].mirror_mode); 1175 XRRModeInfo* mode_info = ModeInfoForID(screen, outputs[0].mirror_mode);
1156 if (mode_info == NULL) { 1176 if (!mode_info) {
1157 UMA_HISTOGRAM_COUNTS("Display.EnterState.mirror_failures", 1); 1177 UMA_HISTOGRAM_COUNTS("Display.EnterState.mirror_failures", 1);
1158 return false; 1178 return false;
1159 } 1179 }
1160 1180
1161 CrtcConfig config1(primary_crtc, 0, 0, 1181 std::vector<CrtcConfig> configs(outputs.size());
1162 primary_power_on ? outputs[0].mirror_mode : None, 1182 for (size_t i = 0; i < outputs.size(); ++i) {
1163 outputs[0].output); 1183 configs[i] = CrtcConfig(
1164 CrtcConfig config2(secondary_crtc, 0, 0, 1184 crtcs[i], 0, 0,
1165 secondary_power_on ? outputs[1].mirror_mode : None, 1185 output_power[i] ? outputs[i].mirror_mode : None,
1166 outputs[1].output); 1186 outputs[i].output);
1187 }
1167 1188
1168 CreateFrameBuffer(display, screen, window, mode_info->width, 1189 CreateFrameBuffer(display, screen, window, mode_info->width,
1169 mode_info->height, &config1, &config2); 1190 mode_info->height, &configs[0], &configs[1]);
1170 1191
1171 ConfigureCrtc(display, screen, &config1); 1192 for (size_t i = 0; i < outputs.size(); ++i) {
1172 ConfigureCrtc(display, screen, &config2); 1193 ConfigureCrtc(display, screen, &configs[i]);
1194 if (outputs[i].touch_device_id) {
1195 CoordinateTransformation ctm;
1196 // CTM needs to be calculated if aspect preserving scaling is used.
1197 // Otherwise, assume it is full screen, and use identity CTM.
1198 if (outputs[i].mirror_mode != outputs[i].native_mode &&
1199 outputs[i].is_aspect_preserving_scaling) {
1200 ctm = GetMirrorModeCTM(screen, &outputs[i]);
1201 }
1202 ConfigureCTM(display, outputs[i].touch_device_id, ctm);
1203 }
1204 }
1205 } else { // STATE_DUAL_EXTENDED
1206 std::vector<XRRModeInfo*> mode_infos(outputs.size());
1207 std::vector<CrtcConfig> configs(outputs.size());
1208 int width = 0, height = 0;
1173 1209
1174 for (size_t i = 0; i < outputs.size(); i++) { 1210 for (size_t i = 0; i < outputs.size(); ++i) {
1175 if (outputs[i].touch_device_id == None) 1211 mode_infos[i] = ModeInfoForID(screen, outputs[i].native_mode);
1176 continue; 1212 if (!mode_infos[i]) {
1213 UMA_HISTOGRAM_COUNTS("Display.EnterState.dual_failures", 1);
1214 return false;
1215 }
1177 1216
1178 CoordinateTransformation ctm; 1217 configs[i] = CrtcConfig(
1179 // CTM needs to be calculated if aspect preserving scaling is used. 1218 crtcs[i], 0, height,
1180 // Otherwise, assume it is full screen, and use identity CTM. 1219 output_power[i] ? outputs[i].native_mode : None,
1181 if (outputs[i].mirror_mode != outputs[i].native_mode && 1220 outputs[i].output);
1182 outputs[i].is_aspect_preserving_scaling) { 1221
1183 ctm = GetMirrorModeCTM(screen, &outputs[i]); 1222 // Retain the full screen size if all outputs are off so the same
1223 // desktop configuration can be restored when the outputs are
1224 // turned back on.
1225 if (output_power[i] || all_outputs_off) {
1226 width = std::max<int>(width, mode_infos[i]->width);
1227 height += (height ? kVerticalGap : 0) + mode_infos[i]->height;
1184 } 1228 }
1185 ConfigureCTM(display, outputs[i].touch_device_id, ctm);
1186 }
1187 } else {
1188 XRRModeInfo* primary_mode_info =
1189 ModeInfoForID(screen, outputs[0].native_mode);
1190 XRRModeInfo* secondary_mode_info =
1191 ModeInfoForID(screen, outputs[1].native_mode);
1192 if (primary_mode_info == NULL || secondary_mode_info == NULL) {
1193 UMA_HISTOGRAM_COUNTS("Display.EnterState.dual_failures", 1);
1194 return false;
1195 } 1229 }
1196 1230
1197 int primary_height = primary_mode_info->height; 1231 CreateFrameBuffer(display, screen, window, width, height,
1198 int secondary_height = secondary_mode_info->height; 1232 &configs[0], &configs[1]);
1199 CrtcConfig config1(primary_crtc, 0, 0,
1200 primary_power_on ? outputs[0].native_mode : None,
1201 outputs[0].output);
1202 CrtcConfig config2(secondary_crtc, 0, 0,
1203 secondary_power_on ? outputs[1].native_mode : None,
1204 outputs[1].output);
1205 1233
1206 if (output_state == STATE_DUAL_EXTENDED) 1234 for (size_t i = 0; i < outputs.size(); ++i) {
1207 config2.y = primary_height + kVerticalGap; 1235 ConfigureCrtc(display, screen, &configs[i]);
1208 else 1236 if (outputs[i].touch_device_id) {
1209 config1.y = secondary_height + kVerticalGap; 1237 CoordinateTransformation ctm;
1210 1238 ctm.x_scale = static_cast<float>(mode_infos[i]->width) / width;
1211 int width = std::max<int>( 1239 ctm.x_offset = static_cast<float>(configs[i].x) / width;
1212 primary_mode_info->width, secondary_mode_info->width); 1240 ctm.y_scale = static_cast<float>(mode_infos[i]->height) / height;
1213 int height = primary_height + secondary_height + kVerticalGap; 1241 ctm.y_offset = static_cast<float>(configs[i].y) / height;
1214 1242 ConfigureCTM(display, outputs[i].touch_device_id, ctm);
1215 CreateFrameBuffer(display, screen, window, width, height, &config1, 1243 }
1216 &config2);
1217
1218 ConfigureCrtc(display, screen, &config1);
1219 ConfigureCrtc(display, screen, &config2);
1220
1221 if (outputs[0].touch_device_id != None) {
1222 CoordinateTransformation ctm;
1223 ctm.x_scale = static_cast<float>(primary_mode_info->width) / width;
1224 ctm.x_offset = static_cast<float>(config1.x) / width;
1225 ctm.y_scale = static_cast<float>(primary_height) / height;
1226 ctm.y_offset = static_cast<float>(config1.y) / height;
1227 ConfigureCTM(display, outputs[0].touch_device_id, ctm);
1228 }
1229 if (outputs[1].touch_device_id != None) {
1230 CoordinateTransformation ctm;
1231 ctm.x_scale = static_cast<float>(secondary_mode_info->width) /
1232 width;
1233 ctm.x_offset = static_cast<float>(config2.x) / width;
1234 ctm.y_scale = static_cast<float>(secondary_height) / height;
1235 ctm.y_offset = static_cast<float>(config2.y) / height;
1236 ConfigureCTM(display, outputs[1].touch_device_id, ctm);
1237 } 1244 }
1238 } 1245 }
1239 break; 1246 break;
1240 } 1247 }
1241 default: 1248 default:
1242 CHECK(false); 1249 NOTREACHED() << "Got " << outputs.size() << " outputs";
1243 } 1250 }
1244 1251
1245 RecordPreviousStateUMA(); 1252 RecordPreviousStateUMA();
1246
1247 return true; 1253 return true;
1248 } 1254 }
1249 1255
1250 void OutputConfigurator::RecordPreviousStateUMA() { 1256 void OutputConfigurator::RecordPreviousStateUMA() {
1251 base::TimeDelta duration = base::TimeTicks::Now() - last_enter_state_time_; 1257 base::TimeDelta duration = base::TimeTicks::Now() - last_enter_state_time_;
1252 1258
1253 // |output_state_| can be used for the state being left, 1259 // |output_state_| can be used for the state being left,
1254 // since RecordPreviousStateUMA is called from EnterState, 1260 // since RecordPreviousStateUMA is called from EnterState,
1255 // and |output_state_| is always updated after EnterState is called. 1261 // and |output_state_| is always updated after EnterState is called.
1256 switch (output_state_) { 1262 switch (output_state_) {
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1332 // static 1338 // static
1333 RRMode OutputConfigurator::GetOutputNativeMode( 1339 RRMode OutputConfigurator::GetOutputNativeMode(
1334 const XRROutputInfo* output_info) { 1340 const XRROutputInfo* output_info) {
1335 if (output_info->nmode <= 0) 1341 if (output_info->nmode <= 0)
1336 return None; 1342 return None;
1337 1343
1338 return output_info->modes[0]; 1344 return output_info->modes[0];
1339 } 1345 }
1340 1346
1341 } // namespace chromeos 1347 } // namespace chromeos
OLDNEW
« no previous file with comments | « chromeos/display/output_configurator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698