Chromium Code Reviews| Index: chromeos/display/output_configurator.cc |
| diff --git a/chromeos/display/output_configurator.cc b/chromeos/display/output_configurator.cc |
| index dcf82029a7b82f197c571e6189f9205d0bab0b33..1a4a72846866266e47f7753a2aa8d0768e21c0f6 100644 |
| --- a/chromeos/display/output_configurator.cc |
| +++ b/chromeos/display/output_configurator.cc |
| @@ -121,6 +121,83 @@ static bool FindMirrorModeForOutputs(Display* display, |
| return found; |
| } |
| +// Should be called if the internal (built-in) output didn't advertise a mode |
| +// which would be capable to support mirror mode. |
| +// Relies on hardware panel fitting support, |
| +// should not be called if it is not available. |
| +// Tries to add the native mode of the external output to the internal output, |
| +// assuming panel fitter hardware will take care of scaling and letterboxing. |
| +// The RROutput IDs |out_one| and |out_two| are used to look up the modes and |
| +// configure the internal output, |
| +// |out_one_mode| and |out_two_mode| are the out-parameters for the modes |
| +// on the two outputs which will have same resolution. |
| +// Returns false if it fails to configure the internal output appropriately. |
| +static bool AddMirrorModeToInternalOutput(Display* display, |
| + XRRScreenResources* screen, |
| + RROutput out_one, |
|
cwolfe
2012/09/18 13:27:47
Would prefer output_* for these names. I initially
ynovikov
2012/09/21 18:48:27
Done.
|
| + RROutput out_two, |
| + RRMode* out_one_mode, |
| + RRMode* out_two_mode) { |
| + XRROutputInfo* out_one_info = XRRGetOutputInfo(display, screen, out_one); |
| + XRROutputInfo* out_two_info = XRRGetOutputInfo(display, screen, out_two); |
| + bool success = false; |
| + |
| + // Both outputs should be connected in mirror mode |
| + if (out_one_info->connection == RR_Connected && |
| + out_two_info->connection == RR_Connected) { |
| + bool one_is_internal = OutputConfigurator::IsInternalOutputName( |
|
cwolfe
2012/09/18 13:27:47
Make this a member of OutputConfigurator to shorte
ynovikov
2012/09/18 15:16:21
I like the idea of IsInternalOutput(output_one_inf
oshima
2012/09/18 21:11:31
Fine with me.
ynovikov
2012/09/21 18:48:27
Done.
|
| + std::string(out_one_info->name)); |
| + bool two_is_internal = OutputConfigurator::IsInternalOutputName( |
| + std::string(out_two_info->name)); |
| + |
| + XRROutputInfo* internal_info = NULL; |
| + XRROutputInfo* external_info = NULL; |
| + |
| + bool there_is_one_internal_output = true; |
|
cwolfe
2012/09/18 13:27:47
found_internal_output with a comment that it will
ynovikov
2012/09/18 15:16:21
I think your suggestion will make the code more ob
cwolfe
2012/09/18 20:55:50
Fair enough. I was first going to suggest a bool f
ynovikov
2012/09/21 18:48:27
Done.
|
| + |
| + // Make sure exactly one of the outputs is internal |
|
cwolfe
2012/09/18 13:27:47
Since it would simplify this, I suggest we ignore
oshima
2012/09/18 14:31:11
with some log message in case it indeed detects tw
ynovikov
2012/09/18 15:16:21
I agree with Oshima that two-internal-outputs case
cwolfe
2012/09/18 20:55:50
To (possibly) clarify, I was leaning toward "if th
oshima
2012/09/18 21:11:31
I don't think we have to support two internal disp
ynovikov
2012/09/21 18:48:27
Done.
|
| + if (one_is_internal && !two_is_internal) { |
| + internal_info = out_one_info; |
| + external_info = out_two_info; |
| + } else if (!one_is_internal && two_is_internal) { |
| + internal_info = out_two_info; |
| + external_info = out_one_info; |
| + } else { |
| + there_is_one_internal_output = false; |
| + } |
| + |
| + if (there_is_one_internal_output) { |
| + RRMode internal_ideal_mode_id = |
| + OutputConfigurator::GetOutputNativeMode(internal_info); |
| + RRMode external_ideal_mode_id = |
| + OutputConfigurator::GetOutputNativeMode(external_info); |
| + |
| + if (internal_ideal_mode_id != None && external_ideal_mode_id != None) { |
| + XRRModeInfo* internal_ideal_mode = |
| + ModeInfoForID(screen, internal_ideal_mode_id); |
| + XRRModeInfo* external_ideal_mode = |
| + ModeInfoForID(screen, external_ideal_mode_id); |
| + |
| + // Panel fitting will not work if the internal output maximal resolution |
| + // is lower than that of the external output |
| + if (internal_ideal_mode->width >= external_ideal_mode->width && |
| + internal_ideal_mode->height >= external_ideal_mode->height) { |
| + XRRAddOutputMode(display, one_is_internal ? out_one : out_two, |
| + external_ideal_mode_id); |
| + |
| + *out_one_mode = *out_two_mode = external_ideal_mode_id; |
|
cwolfe
2012/09/18 13:27:47
Merge those parameters?
ynovikov
2012/09/18 15:16:21
Their identity is implementation dependent, if in
cwolfe
2012/09/18 20:55:50
Fair enough.
On 2012/09/18 15:16:21, ynovikov wro
ynovikov
2012/09/21 18:48:27
Done.
|
| + success = true; |
| + } |
| + } |
| + } |
| + } |
| + |
| + XRRFreeOutputInfo(out_one_info); |
| + XRRFreeOutputInfo(out_two_info); |
| + |
| + return success; |
| +} |
| + |
| // A helper to call XRRSetCrtcConfig with the given options but some of our |
| // default output count and rotation arguments. |
| static void ConfigureCrtc(Display* display, |
| @@ -208,7 +285,8 @@ typedef struct OutputSnapshot { |
| static int GetDualOutputs(Display* display, |
| XRRScreenResources* screen, |
| OutputSnapshot* one, |
| - OutputSnapshot* two) { |
| + OutputSnapshot* two, |
| + bool is_panel_fitting_supported) { |
|
cwolfe
2012/09/18 13:27:47
Would it be clearer to make these functions member
ynovikov
2012/09/18 15:16:21
Perhaps it would, I am not sure why these function
ynovikov
2012/09/21 18:48:27
Done.
|
| int found_count = 0; |
| XRROutputInfo* one_info = NULL; |
| XRROutputInfo* two_info = NULL; |
| @@ -246,8 +324,8 @@ static int GetDualOutputs(Display* display, |
| } |
| // Find the native_mode and leave the mirror_mode for the pass after the |
| // loop. |
| - if (output_info->nmode > 0) |
| - to_populate->native_mode = output_info->modes[0]; |
| + to_populate->native_mode = |
| + OutputConfigurator::GetOutputNativeMode(output_info); |
| to_populate->mirror_mode = 0; |
| // See if this output refers to an internal display. |
| @@ -274,9 +352,17 @@ static int GetDualOutputs(Display* display, |
| &one->mirror_mode, |
| &two->mirror_mode); |
| if (!can_mirror) { |
| - // We can't mirror so set mirror_mode to 0. |
| - one->mirror_mode = 0; |
| - two->mirror_mode = 0; |
| + bool can_add_mirror_mode = false; |
| + if (is_panel_fitting_supported) { |
| + can_add_mirror_mode = |
|
cwolfe
2012/09/18 13:27:47
added_mirror_mode?
ynovikov
2012/09/18 15:16:21
Sounds good to me, how about mirror_mode_found for
cwolfe
2012/09/18 20:55:50
SGTM
On 2012/09/18 15:16:21, ynovikov wrote:
ynovikov
2012/09/21 18:48:27
Done.
|
| + AddMirrorModeToInternalOutput(display, screen, |
| + one->output, two->output, &one->mirror_mode, &two->mirror_mode); |
| + } |
| + if (!can_add_mirror_mode) { |
| + // We can't mirror so set mirror_mode to 0. |
| + one->mirror_mode = 0; |
| + two->mirror_mode = 0; |
| + } |
| } |
| } |
| @@ -562,11 +648,18 @@ static bool IsProjecting(const OutputSnapshot* outputs, int output_count) { |
| OutputConfigurator::OutputConfigurator() |
| : is_running_on_chrome_os_(base::chromeos::IsRunningOnChromeOS()), |
| + is_panel_fitting_supported_(false), |
| + connected_output_count_(0), |
| xrandr_event_base_(0), |
| output_state_(STATE_INVALID) { |
| +} |
| + |
| +void OutputConfigurator::Init(bool is_panel_fitting_supported) { |
| if (!is_running_on_chrome_os_) |
| return; |
| + is_panel_fitting_supported_ = is_panel_fitting_supported; |
| + |
| // Cache the initial output state. |
| Display* display = base::MessagePumpAuraX11::GetDefaultXDisplay(); |
| CHECK(display != NULL); |
| @@ -578,7 +671,8 @@ OutputConfigurator::OutputConfigurator() |
| // Detect our initial state. |
| OutputSnapshot outputs[2] = { {0}, {0} }; |
| connected_output_count_ = |
| - GetDualOutputs(display, screen, &outputs[0], &outputs[1]); |
| + GetDualOutputs(display, screen, &outputs[0], &outputs[1], |
|
cwolfe
2012/09/18 13:27:47
Yeah, I'd prefer making GetDualOutputs a non-stati
ynovikov
2012/09/21 18:48:27
Done.
|
| + is_panel_fitting_supported_); |
| output_state_ = |
| InferCurrentState(display, screen, outputs, connected_output_count_); |
| // Ensure that we are in a supported state with all connected displays powered |
| @@ -629,7 +723,8 @@ bool OutputConfigurator::CycleDisplayMode() { |
| OutputSnapshot outputs[2] = { {0}, {0} }; |
| connected_output_count_ = |
| - GetDualOutputs(display, screen, &outputs[0], &outputs[1]); |
| + GetDualOutputs(display, screen, &outputs[0], &outputs[1], |
| + is_panel_fitting_supported_); |
| OutputState original = |
| InferCurrentState(display, screen, outputs, connected_output_count_); |
| OutputState next_state = |
| @@ -669,7 +764,8 @@ bool OutputConfigurator::ScreenPowerSet(bool power_on, bool all_displays) { |
| OutputSnapshot outputs[2] = { {0}, {0} }; |
| connected_output_count_ = |
| - GetDualOutputs(display, screen, &outputs[0], &outputs[1]); |
| + GetDualOutputs(display, screen, &outputs[0], &outputs[1], |
| + is_panel_fitting_supported_); |
| output_state_ = |
| InferCurrentState(display, screen, outputs, connected_output_count_); |
| @@ -729,7 +825,8 @@ bool OutputConfigurator::SetDisplayMode(OutputState new_state) { |
| OutputSnapshot outputs[2] = { {0}, {0} }; |
| connected_output_count_ = |
| - GetDualOutputs(display, screen, &outputs[0], &outputs[1]); |
| + GetDualOutputs(display, screen, &outputs[0], &outputs[1], |
| + is_panel_fitting_supported_); |
| if (EnterState(display, |
| screen, |
| window, |
| @@ -773,7 +870,8 @@ bool OutputConfigurator::Dispatch(const base::NativeEvent& event) { |
| OutputSnapshot outputs[2] = { {0}, {0} }; |
| int new_output_count = |
| - GetDualOutputs(display, screen, &outputs[0], &outputs[1]); |
| + GetDualOutputs(display, screen, &outputs[0], &outputs[1], |
| + is_panel_fitting_supported_); |
| if (new_output_count != connected_output_count_) { |
| connected_output_count_ = new_output_count; |
| OutputState new_state = GetNextState(display, |
| @@ -816,6 +914,18 @@ bool OutputConfigurator::IsInternalOutputName(const std::string& name) { |
| return name.find(kInternal_LVDS) == 0 || name.find(kInternal_eDP) == 0; |
| } |
| +// static |
| +RRMode OutputConfigurator::GetOutputNativeMode( |
|
cwolfe
2012/09/18 13:27:47
Seems like this should be "GetOutputPreferredMode"
ynovikov
2012/09/18 15:16:21
No, what this function should return is the Native
cwolfe
2012/09/18 20:55:50
I dislike the implication that we know anything ab
ynovikov
2012/09/21 18:48:27
Done.
|
| + const XRROutputInfo* output_info) { |
| + RRMode native_mode = None; |
| + |
| + if (output_info->nmode > 0) { |
|
cwolfe
2012/09/18 13:27:47
This is one of the places I actually like early re
oshima
2012/09/18 14:31:11
+1 This matches chrome preferred style.
ynovikov
2012/09/21 18:48:27
Done.
|
| + native_mode = output_info->modes[0]; |
| + } |
| + |
| + return native_mode; |
| +} |
| + |
| void OutputConfigurator::NotifyOnDisplayChanged() { |
| FOR_EACH_OBSERVER(Observer, observers_, OnDisplayModeChanged()); |
| } |