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

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: clean up EnterState() Created 7 years, 9 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 | « no previous file | 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 1084 matching lines...) Expand 10 before | Expand all | Expand 10 after
1095 } 1095 }
1096 1096
1097 bool OutputConfigurator::EnterState( 1097 bool OutputConfigurator::EnterState(
1098 Display* display, 1098 Display* display,
1099 XRRScreenResources* screen, 1099 XRRScreenResources* screen,
1100 Window window, 1100 Window window,
1101 OutputState output_state, 1101 OutputState output_state,
1102 DisplayPowerState power_state, 1102 DisplayPowerState power_state,
1103 const std::vector<OutputSnapshot>& outputs) { 1103 const std::vector<OutputSnapshot>& outputs) {
1104 TRACE_EVENT0("chromeos", "OutputConfigurator::EnterState"); 1104 TRACE_EVENT0("chromeos", "OutputConfigurator::EnterState");
1105
1106 std::vector<RRCrtc> crtcs(outputs.size());
1107 std::vector<bool> output_power(outputs.size());
1108 bool all_outputs_off = true;
1109
1110 RRCrtc prev_crtc = None;
1111 for (size_t i = 0; i < outputs.size(); prev_crtc = crtcs[i], ++i) {
1112 crtcs[i] = GetNextCrtcAfter(display, screen, outputs[i].output, prev_crtc);
1113 output_power[i] = power_state == DISPLAY_POWER_ALL_ON ||
1114 (power_state == DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON &&
1115 !outputs[i].is_internal) ||
1116 (power_state == DISPLAY_POWER_INTERNAL_ON_EXTERNAL_OFF &&
1117 outputs[i].is_internal);
1118 if (output_power[i])
1119 all_outputs_off = false;
1120 }
1121
1105 switch (outputs.size()) { 1122 switch (outputs.size()) {
1106 case 0: 1123 case 0:
1107 // Do nothing as no 0-display states are supported. 1124 // Do nothing as no 0-display states are supported.
1108 break; 1125 break;
1109 case 1: { 1126 case 1: {
1110 // Re-allocate the framebuffer to fit. 1127 // Re-allocate the framebuffer to fit.
1111 XRRModeInfo* mode_info = ModeInfoForID(screen, outputs[0].native_mode); 1128 XRRModeInfo* mode_info = ModeInfoForID(screen, outputs[0].native_mode);
1112 if (mode_info == NULL) { 1129 if (!mode_info) {
1113 UMA_HISTOGRAM_COUNTS("Display.EnterState.single_failures", 1); 1130 UMA_HISTOGRAM_COUNTS("Display.EnterState.single_failures", 1);
1114 return false; 1131 return false;
1115 } 1132 }
1116 1133
1117 bool power_on = power_state == DISPLAY_POWER_ALL_ON || 1134 CrtcConfig config(crtcs[0], 0, 0,
1118 (power_state == DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON && 1135 output_power[0] ? outputs[0].native_mode : None,
1119 !outputs[0].is_internal) || 1136 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, 1137 CreateFrameBuffer(display, screen, window, mode_info->width,
1127 mode_info->height, &config, NULL); 1138 mode_info->height, &config, NULL);
1128
1129 ConfigureCrtc(display, screen, &config); 1139 ConfigureCrtc(display, screen, &config);
1130 1140 if (outputs[0].touch_device_id) {
1131 // Restore identity transformation for single monitor in native mode. 1141 // Restore identity transformation for single monitor in native mode.
1132 if (outputs[0].touch_device_id != None) { 1142 ConfigureCTM(display, outputs[0].touch_device_id,
1133 CoordinateTransformation ctm; // Defaults to identity 1143 CoordinateTransformation());
1134 ConfigureCTM(display, outputs[0].touch_device_id, ctm);
1135 } 1144 }
1136 break; 1145 break;
1137 } 1146 }
1138 case 2: { 1147 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) { 1148 if (output_state == STATE_DUAL_MIRROR) {
1155 XRRModeInfo* mode_info = ModeInfoForID(screen, outputs[0].mirror_mode); 1149 XRRModeInfo* mode_info = ModeInfoForID(screen, outputs[0].mirror_mode);
1156 if (mode_info == NULL) { 1150 if (!mode_info) {
1157 UMA_HISTOGRAM_COUNTS("Display.EnterState.mirror_failures", 1); 1151 UMA_HISTOGRAM_COUNTS("Display.EnterState.mirror_failures", 1);
1158 return false; 1152 return false;
1159 } 1153 }
1160 1154
1161 CrtcConfig config1(primary_crtc, 0, 0, 1155 std::vector<CrtcConfig> configs(outputs.size());
1162 primary_power_on ? outputs[0].mirror_mode : None, 1156 for (size_t i = 0; i < outputs.size(); ++i) {
1163 outputs[0].output); 1157 configs[i] = CrtcConfig(
1164 CrtcConfig config2(secondary_crtc, 0, 0, 1158 crtcs[i], 0, 0,
1165 secondary_power_on ? outputs[1].mirror_mode : None, 1159 output_power[i] ? outputs[i].mirror_mode : None,
1166 outputs[1].output); 1160 outputs[i].output);
1161 }
1167 1162
1168 CreateFrameBuffer(display, screen, window, mode_info->width, 1163 CreateFrameBuffer(display, screen, window, mode_info->width,
1169 mode_info->height, &config1, &config2); 1164 mode_info->height, &configs[0], &configs[1]);
1170 1165
1171 ConfigureCrtc(display, screen, &config1); 1166 for (size_t i = 0; i < outputs.size(); ++i) {
1172 ConfigureCrtc(display, screen, &config2); 1167 ConfigureCrtc(display, screen, &configs[i]);
1168 if (outputs[i].touch_device_id) {
1169 CoordinateTransformation ctm;
1170 // CTM needs to be calculated if aspect preserving scaling is used.
1171 // Otherwise, assume it is full screen, and use identity CTM.
1172 if (outputs[i].mirror_mode != outputs[i].native_mode &&
1173 outputs[i].is_aspect_preserving_scaling) {
1174 ctm = GetMirrorModeCTM(screen, &outputs[i]);
1175 }
1176 ConfigureCTM(display, outputs[i].touch_device_id, ctm);
1177 }
1178 }
1179 } else { // STATE_DUAL_EXTENDED
1180 std::vector<XRRModeInfo*> mode_infos(outputs.size());
1181 std::vector<CrtcConfig> configs(outputs.size());
1182 int width = 0, height = 0;
1173 1183
1174 for (size_t i = 0; i < outputs.size(); i++) { 1184 for (size_t i = 0; i < outputs.size(); ++i) {
1175 if (outputs[i].touch_device_id == None) 1185 mode_infos[i] = ModeInfoForID(screen, outputs[i].native_mode);
1176 continue; 1186 if (!mode_infos[i]) {
1187 UMA_HISTOGRAM_COUNTS("Display.EnterState.dual_failures", 1);
1188 return false;
1189 }
1177 1190
1178 CoordinateTransformation ctm; 1191 configs[i] = CrtcConfig(
1179 // CTM needs to be calculated if aspect preserving scaling is used. 1192 crtcs[i], 0, height,
1180 // Otherwise, assume it is full screen, and use identity CTM. 1193 output_power[i] ? outputs[i].native_mode : None,
1181 if (outputs[i].mirror_mode != outputs[i].native_mode && 1194 outputs[i].output);
1182 outputs[i].is_aspect_preserving_scaling) { 1195
1183 ctm = GetMirrorModeCTM(screen, &outputs[i]); 1196 // Avoid ending up with 0-by-0 if all outputs are off.
oshima 2013/03/26 23:20:31 // Keep the full screen size if all outputs are of
Daniel Erat 2013/03/26 23:23:16 Done.
1197 if (output_power[i] || all_outputs_off) {
1198 width = std::max<int>(width, mode_infos[i]->width);
1199 height += (height ? kVerticalGap : 0) + mode_infos[i]->height;
1184 } 1200 }
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 } 1201 }
1196 1202
1197 int primary_height = primary_mode_info->height; 1203 CreateFrameBuffer(display, screen, window, width, height,
1198 int secondary_height = secondary_mode_info->height; 1204 &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 1205
1206 if (output_state == STATE_DUAL_EXTENDED) 1206 for (size_t i = 0; i < outputs.size(); ++i) {
1207 config2.y = primary_height + kVerticalGap; 1207 ConfigureCrtc(display, screen, &configs[i]);
1208 else 1208 if (outputs[i].touch_device_id) {
1209 config1.y = secondary_height + kVerticalGap; 1209 CoordinateTransformation ctm;
1210 1210 ctm.x_scale = static_cast<float>(mode_infos[i]->width) / width;
1211 int width = std::max<int>( 1211 ctm.x_offset = static_cast<float>(configs[i].x) / width;
1212 primary_mode_info->width, secondary_mode_info->width); 1212 ctm.y_scale = static_cast<float>(mode_infos[i]->height) / height;
1213 int height = primary_height + secondary_height + kVerticalGap; 1213 ctm.y_offset = static_cast<float>(configs[i].y) / height;
1214 1214 ConfigureCTM(display, outputs[i].touch_device_id, ctm);
1215 CreateFrameBuffer(display, screen, window, width, height, &config1, 1215 }
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 } 1216 }
1238 } 1217 }
1239 break; 1218 break;
1240 } 1219 }
1241 default: 1220 default:
1242 CHECK(false); 1221 NOTREACHED() << "Got " << outputs.size() << " outputs";
1243 } 1222 }
1244 1223
1245 RecordPreviousStateUMA(); 1224 RecordPreviousStateUMA();
1246
1247 return true; 1225 return true;
1248 } 1226 }
1249 1227
1250 void OutputConfigurator::RecordPreviousStateUMA() { 1228 void OutputConfigurator::RecordPreviousStateUMA() {
1251 base::TimeDelta duration = base::TimeTicks::Now() - last_enter_state_time_; 1229 base::TimeDelta duration = base::TimeTicks::Now() - last_enter_state_time_;
1252 1230
1253 // |output_state_| can be used for the state being left, 1231 // |output_state_| can be used for the state being left,
1254 // since RecordPreviousStateUMA is called from EnterState, 1232 // since RecordPreviousStateUMA is called from EnterState,
1255 // and |output_state_| is always updated after EnterState is called. 1233 // and |output_state_| is always updated after EnterState is called.
1256 switch (output_state_) { 1234 switch (output_state_) {
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1332 // static 1310 // static
1333 RRMode OutputConfigurator::GetOutputNativeMode( 1311 RRMode OutputConfigurator::GetOutputNativeMode(
1334 const XRROutputInfo* output_info) { 1312 const XRROutputInfo* output_info) {
1335 if (output_info->nmode <= 0) 1313 if (output_info->nmode <= 0)
1336 return None; 1314 return None;
1337 1315
1338 return output_info->modes[0]; 1316 return output_info->modes[0];
1339 } 1317 }
1340 1318
1341 } // namespace chromeos 1319 } // namespace chromeos
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698