Index: chromeos/display/output_configurator.cc |
diff --git a/chromeos/display/output_configurator.cc b/chromeos/display/output_configurator.cc |
index 67da273b64965469c0b9d252e2e64e3c8ab16158..174730da1024bd07886c364b0f59052441eb27e2 100644 |
--- a/chromeos/display/output_configurator.cc |
+++ b/chromeos/display/output_configurator.cc |
@@ -941,28 +941,73 @@ bool OutputConfigurator::EnterState( |
// Finally, apply the desired changes. |
DCHECK_EQ(cached_outputs_.size(), updated_outputs.size()); |
+ bool all_succeeded = true; |
if (!updated_outputs.empty()) { |
delegate_->CreateFrameBuffer(width, height, updated_outputs); |
for (size_t i = 0; i < updated_outputs.size(); ++i) { |
const OutputSnapshot& output = updated_outputs[i]; |
- if (delegate_->ConfigureCrtc(output.crtc, output.current_mode, |
- output.output, output.x, output.y)) { |
- if (output.touch_device_id) |
- delegate_->ConfigureCTM(output.touch_device_id, output.transform); |
- cached_outputs_[i] = updated_outputs[i]; |
- } else { |
+ bool configure_succeeded =false; |
+ |
+ while (true) { |
+ if (delegate_->ConfigureCrtc(output.crtc, output.current_mode, |
+ output.output, output.x, output.y)) { |
+ configure_succeeded = true; |
+ break; |
+ } |
+ |
LOG(WARNING) << "Unable to configure CRTC " << output.crtc << ":" |
<< " mode=" << output.current_mode |
<< " output=" << output.output |
<< " x=" << output.x |
<< " y=" << output.y; |
+ |
+ const ModeInfo* mode_info = GetModeInfo(output, output.current_mode); |
+ if (!mode_info) |
+ break; |
+ |
+ // Find the mode with the next-best resolution and see if that can |
+ // be set. |
+ int best_mode_pixels = 0; |
+ |
+ int current_mode_pixels = mode_info->width * mode_info->height; |
+ for (ModeInfoMap::const_iterator it = output.mode_infos.begin(); |
+ it != output.mode_infos.end(); it++) { |
+ int pixel_count = it->second.width * it->second.height; |
+ if ((pixel_count < current_mode_pixels) && |
+ (pixel_count > best_mode_pixels)) { |
+ updated_outputs[i].current_mode = it->first; |
+ best_mode_pixels = pixel_count; |
+ } |
+ } |
+ |
+ if (best_mode_pixels == 0) |
+ break; |
} |
+ |
+ if (configure_succeeded) { |
+ if (output.touch_device_id) |
+ delegate_->ConfigureCTM(output.touch_device_id, output.transform); |
+ cached_outputs_[i] = updated_outputs[i]; |
+ } else { |
+ all_succeeded = false; |
+ } |
+ |
+ // If we are trying to set mirror mode and one of the modesets fails, |
+ // then the two monitors will be mis-matched. In this case, return |
+ // false to let the observers be aware. |
+ if (output_state == STATE_DUAL_MIRROR && |
+ output_power[i] && |
+ output.current_mode != output.mirror_mode) |
+ all_succeeded = false; |
+ |
} |
} |
- output_state_ = output_state; |
- power_state_ = power_state; |
- return true; |
+ if (all_succeeded) { |
+ output_state_ = output_state; |
+ power_state_ = power_state; |
+ } |
+ return all_succeeded; |
} |
OutputState OutputConfigurator::ChooseOutputState( |