Chromium Code Reviews| Index: chromeos/display/output_configurator.cc |
| diff --git a/chromeos/display/output_configurator.cc b/chromeos/display/output_configurator.cc |
| index b41362ff9657278b8fdc1ffc2178ada9a6b79700..e79f4a81cd3314b55e97986491310ed520598a4b 100644 |
| --- a/chromeos/display/output_configurator.cc |
| +++ b/chromeos/display/output_configurator.cc |
| @@ -1102,6 +1102,23 @@ bool OutputConfigurator::EnterState( |
| DisplayPowerState power_state, |
| const std::vector<OutputSnapshot>& outputs) { |
| TRACE_EVENT0("chromeos", "OutputConfigurator::EnterState"); |
| + |
| + std::vector<RRCrtc> crtcs(outputs.size()); |
| + std::vector<bool> output_power(outputs.size()); |
| + bool all_outputs_off = true; |
| + |
| + RRCrtc prev_crtc = None; |
| + for (size_t i = 0; i < outputs.size(); prev_crtc = crtcs[i], ++i) { |
| + crtcs[i] = GetNextCrtcAfter(display, screen, outputs[i].output, prev_crtc); |
| + output_power[i] = power_state == DISPLAY_POWER_ALL_ON || |
| + (power_state == DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON && |
| + !outputs[i].is_internal) || |
| + (power_state == DISPLAY_POWER_INTERNAL_ON_EXTERNAL_OFF && |
| + outputs[i].is_internal); |
| + if (output_power[i]) |
| + all_outputs_off = false; |
| + } |
| + |
| switch (outputs.size()) { |
| case 0: |
| // Do nothing as no 0-display states are supported. |
| @@ -1109,141 +1126,102 @@ bool OutputConfigurator::EnterState( |
| case 1: { |
| // Re-allocate the framebuffer to fit. |
| XRRModeInfo* mode_info = ModeInfoForID(screen, outputs[0].native_mode); |
| - if (mode_info == NULL) { |
| + if (!mode_info) { |
| UMA_HISTOGRAM_COUNTS("Display.EnterState.single_failures", 1); |
| return false; |
| } |
| - bool power_on = power_state == DISPLAY_POWER_ALL_ON || |
| - (power_state == DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON && |
| - !outputs[0].is_internal) || |
| - (power_state == DISPLAY_POWER_INTERNAL_ON_EXTERNAL_OFF && |
| - outputs[0].is_internal); |
| - CrtcConfig config( |
| - GetNextCrtcAfter(display, screen, outputs[0].output, None), |
| - 0, 0, power_on ? outputs[0].native_mode : None, outputs[0].output); |
| - |
| + CrtcConfig config(crtcs[0], 0, 0, |
| + output_power[0] ? outputs[0].native_mode : None, |
| + outputs[0].output); |
| CreateFrameBuffer(display, screen, window, mode_info->width, |
| mode_info->height, &config, NULL); |
| - |
| ConfigureCrtc(display, screen, &config); |
| - |
| - // Restore identity transformation for single monitor in native mode. |
| - if (outputs[0].touch_device_id != None) { |
| - CoordinateTransformation ctm; // Defaults to identity |
| - ConfigureCTM(display, outputs[0].touch_device_id, ctm); |
| + if (outputs[0].touch_device_id) { |
| + // Restore identity transformation for single monitor in native mode. |
| + ConfigureCTM(display, outputs[0].touch_device_id, |
| + CoordinateTransformation()); |
| } |
| break; |
| } |
| case 2: { |
| - RRCrtc primary_crtc = |
| - GetNextCrtcAfter(display, screen, outputs[0].output, None); |
| - RRCrtc secondary_crtc = |
| - GetNextCrtcAfter(display, screen, outputs[1].output, primary_crtc); |
| - |
| - // Workaround for crbug.com/148365: leave internal display on for |
| - // internal-off, external-on so user can move cursor (and hence |
| - // windows) onto internal display even when it's off. |
| - bool primary_power_on = power_state == DISPLAY_POWER_ALL_ON || |
| - (power_state == DISPLAY_POWER_INTERNAL_ON_EXTERNAL_OFF && |
| - outputs[0].is_internal); |
| - bool secondary_power_on = power_state == DISPLAY_POWER_ALL_ON || |
| - (power_state == DISPLAY_POWER_INTERNAL_ON_EXTERNAL_OFF && |
| - outputs[1].is_internal); |
| - |
| if (output_state == STATE_DUAL_MIRROR) { |
| XRRModeInfo* mode_info = ModeInfoForID(screen, outputs[0].mirror_mode); |
| - if (mode_info == NULL) { |
| + if (!mode_info) { |
| UMA_HISTOGRAM_COUNTS("Display.EnterState.mirror_failures", 1); |
| return false; |
| } |
| - CrtcConfig config1(primary_crtc, 0, 0, |
| - primary_power_on ? outputs[0].mirror_mode : None, |
| - outputs[0].output); |
| - CrtcConfig config2(secondary_crtc, 0, 0, |
| - secondary_power_on ? outputs[1].mirror_mode : None, |
| - outputs[1].output); |
| + std::vector<CrtcConfig> configs(outputs.size()); |
| + for (size_t i = 0; i < outputs.size(); ++i) { |
| + configs[i] = CrtcConfig( |
| + crtcs[i], 0, 0, |
| + output_power[i] ? outputs[i].mirror_mode : None, |
| + outputs[i].output); |
| + } |
| CreateFrameBuffer(display, screen, window, mode_info->width, |
| - mode_info->height, &config1, &config2); |
| - |
| - ConfigureCrtc(display, screen, &config1); |
| - ConfigureCrtc(display, screen, &config2); |
| + mode_info->height, &configs[0], &configs[1]); |
| + |
| + for (size_t i = 0; i < outputs.size(); ++i) { |
| + ConfigureCrtc(display, screen, &configs[i]); |
| + if (outputs[i].touch_device_id) { |
| + CoordinateTransformation ctm; |
| + // CTM needs to be calculated if aspect preserving scaling is used. |
| + // Otherwise, assume it is full screen, and use identity CTM. |
| + if (outputs[i].mirror_mode != outputs[i].native_mode && |
| + outputs[i].is_aspect_preserving_scaling) { |
| + ctm = GetMirrorModeCTM(screen, &outputs[i]); |
| + } |
| + ConfigureCTM(display, outputs[i].touch_device_id, ctm); |
| + } |
| + } |
| + } else { // STATE_DUAL_EXTENDED |
| + std::vector<XRRModeInfo*> mode_infos(outputs.size()); |
| + std::vector<CrtcConfig> configs(outputs.size()); |
| + int width = 0, height = 0; |
| + |
| + for (size_t i = 0; i < outputs.size(); ++i) { |
| + mode_infos[i] = ModeInfoForID(screen, outputs[i].native_mode); |
| + if (!mode_infos[i]) { |
| + UMA_HISTOGRAM_COUNTS("Display.EnterState.dual_failures", 1); |
| + return false; |
| + } |
| - for (size_t i = 0; i < outputs.size(); i++) { |
| - if (outputs[i].touch_device_id == None) |
| - continue; |
| + configs[i] = CrtcConfig( |
| + crtcs[i], 0, height, |
| + output_power[i] ? outputs[i].native_mode : None, |
| + outputs[i].output); |
| - CoordinateTransformation ctm; |
| - // CTM needs to be calculated if aspect preserving scaling is used. |
| - // Otherwise, assume it is full screen, and use identity CTM. |
| - if (outputs[i].mirror_mode != outputs[i].native_mode && |
| - outputs[i].is_aspect_preserving_scaling) { |
| - ctm = GetMirrorModeCTM(screen, &outputs[i]); |
| + // 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.
|
| + if (output_power[i] || all_outputs_off) { |
| + width = std::max<int>(width, mode_infos[i]->width); |
| + height += (height ? kVerticalGap : 0) + mode_infos[i]->height; |
| } |
| - ConfigureCTM(display, outputs[i].touch_device_id, ctm); |
| - } |
| - } else { |
| - XRRModeInfo* primary_mode_info = |
| - ModeInfoForID(screen, outputs[0].native_mode); |
| - XRRModeInfo* secondary_mode_info = |
| - ModeInfoForID(screen, outputs[1].native_mode); |
| - if (primary_mode_info == NULL || secondary_mode_info == NULL) { |
| - UMA_HISTOGRAM_COUNTS("Display.EnterState.dual_failures", 1); |
| - return false; |
| } |
| - int primary_height = primary_mode_info->height; |
| - int secondary_height = secondary_mode_info->height; |
| - CrtcConfig config1(primary_crtc, 0, 0, |
| - primary_power_on ? outputs[0].native_mode : None, |
| - outputs[0].output); |
| - CrtcConfig config2(secondary_crtc, 0, 0, |
| - secondary_power_on ? outputs[1].native_mode : None, |
| - outputs[1].output); |
| - |
| - if (output_state == STATE_DUAL_EXTENDED) |
| - config2.y = primary_height + kVerticalGap; |
| - else |
| - config1.y = secondary_height + kVerticalGap; |
| - |
| - int width = std::max<int>( |
| - primary_mode_info->width, secondary_mode_info->width); |
| - int height = primary_height + secondary_height + kVerticalGap; |
| - |
| - CreateFrameBuffer(display, screen, window, width, height, &config1, |
| - &config2); |
| - |
| - ConfigureCrtc(display, screen, &config1); |
| - ConfigureCrtc(display, screen, &config2); |
| - |
| - if (outputs[0].touch_device_id != None) { |
| - CoordinateTransformation ctm; |
| - ctm.x_scale = static_cast<float>(primary_mode_info->width) / width; |
| - ctm.x_offset = static_cast<float>(config1.x) / width; |
| - ctm.y_scale = static_cast<float>(primary_height) / height; |
| - ctm.y_offset = static_cast<float>(config1.y) / height; |
| - ConfigureCTM(display, outputs[0].touch_device_id, ctm); |
| - } |
| - if (outputs[1].touch_device_id != None) { |
| - CoordinateTransformation ctm; |
| - ctm.x_scale = static_cast<float>(secondary_mode_info->width) / |
| - width; |
| - ctm.x_offset = static_cast<float>(config2.x) / width; |
| - ctm.y_scale = static_cast<float>(secondary_height) / height; |
| - ctm.y_offset = static_cast<float>(config2.y) / height; |
| - ConfigureCTM(display, outputs[1].touch_device_id, ctm); |
| + CreateFrameBuffer(display, screen, window, width, height, |
| + &configs[0], &configs[1]); |
| + |
| + for (size_t i = 0; i < outputs.size(); ++i) { |
| + ConfigureCrtc(display, screen, &configs[i]); |
| + if (outputs[i].touch_device_id) { |
| + CoordinateTransformation ctm; |
| + ctm.x_scale = static_cast<float>(mode_infos[i]->width) / width; |
| + ctm.x_offset = static_cast<float>(configs[i].x) / width; |
| + ctm.y_scale = static_cast<float>(mode_infos[i]->height) / height; |
| + ctm.y_offset = static_cast<float>(configs[i].y) / height; |
| + ConfigureCTM(display, outputs[i].touch_device_id, ctm); |
| + } |
| } |
| } |
| break; |
| } |
| default: |
| - CHECK(false); |
| + NOTREACHED() << "Got " << outputs.size() << " outputs"; |
| } |
| RecordPreviousStateUMA(); |
| - |
| return true; |
| } |