Index: chromeos/display/output_configurator.cc |
diff --git a/chromeos/display/output_configurator.cc b/chromeos/display/output_configurator.cc |
index dcf82029a7b82f197c571e6189f9205d0bab0b33..7cd9fcc63c25eaf9bb2c791ac2ada4baf4fbddb6 100644 |
--- a/chromeos/display/output_configurator.cc |
+++ b/chromeos/display/output_configurator.cc |
@@ -27,6 +27,17 @@ |
namespace chromeos { |
+typedef struct OutputSnapshot { |
+ RROutput output; |
+ RRCrtc crtc; |
+ RRMode current_mode; |
+ int height; |
+ int y; |
+ RRMode native_mode; |
+ RRMode mirror_mode; |
+ bool is_internal; |
+} OutputSnapshot; |
+ |
namespace { |
// DPI measurements. |
const float kMmInInch = 25.4; |
@@ -194,97 +205,6 @@ static void CreateFrameBuffer(Display* display, |
XRRSetScreenSize(display, window, width, height, mm_width, mm_height); |
} |
-typedef struct OutputSnapshot { |
- RROutput output; |
- RRCrtc crtc; |
- RRMode current_mode; |
- int height; |
- int y; |
- RRMode native_mode; |
- RRMode mirror_mode; |
- bool is_internal; |
-} OutputSnapshot; |
- |
-static int GetDualOutputs(Display* display, |
- XRRScreenResources* screen, |
- OutputSnapshot* one, |
- OutputSnapshot* two) { |
- int found_count = 0; |
- XRROutputInfo* one_info = NULL; |
- XRROutputInfo* two_info = NULL; |
- |
- for (int i = 0; (i < screen->noutput) && (found_count < 2); ++i) { |
- RROutput this_id = screen->outputs[i]; |
- XRROutputInfo* output_info = XRRGetOutputInfo(display, screen, this_id); |
- bool is_connected = (RR_Connected == output_info->connection); |
- |
- if (is_connected) { |
- OutputSnapshot *to_populate = NULL; |
- |
- if (0 == found_count) { |
- to_populate = one; |
- one_info = output_info; |
- } else { |
- to_populate = two; |
- two_info = output_info; |
- } |
- |
- to_populate->output = this_id; |
- // Now, look up the corresponding CRTC and any related info. |
- to_populate->crtc = output_info->crtc; |
- if (None != to_populate->crtc) { |
- XRRCrtcInfo* crtc_info = |
- XRRGetCrtcInfo(display, screen, to_populate->crtc); |
- to_populate->current_mode = crtc_info->mode; |
- to_populate->height = crtc_info->height; |
- to_populate->y = crtc_info->y; |
- XRRFreeCrtcInfo(crtc_info); |
- } else { |
- to_populate->current_mode = 0; |
- to_populate->height = 0; |
- to_populate->y = 0; |
- } |
- // 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->mirror_mode = 0; |
- |
- // See if this output refers to an internal display. |
- to_populate->is_internal = |
- OutputConfigurator::IsInternalOutputName( |
- std::string(output_info->name)); |
- |
- VLOG(1) << "Found display #" << found_count |
- << " with output " << (int)to_populate->output |
- << " crtc " << (int)to_populate->crtc |
- << " current mode " << (int)to_populate->current_mode; |
- ++found_count; |
- } else { |
- XRRFreeOutputInfo(output_info); |
- } |
- } |
- |
- if (2 == found_count) { |
- // Find the mirror modes (if there are any). |
- bool can_mirror = FindMirrorModeForOutputs(display, |
- screen, |
- one->output, |
- two->output, |
- &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; |
- } |
- } |
- |
- XRRFreeOutputInfo(one_info); |
- XRRFreeOutputInfo(two_info); |
- return found_count; |
-} |
- |
static OutputState InferCurrentState(Display* display, |
XRRScreenResources* screen, |
const OutputSnapshot* outputs, |
@@ -562,11 +482,18 @@ static bool IsProjecting(const OutputSnapshot* outputs, int output_count) { |
OutputConfigurator::OutputConfigurator() |
: is_running_on_chrome_os_(base::chromeos::IsRunningOnChromeOS()), |
+ is_panel_fitting_enabled_(false), |
+ connected_output_count_(0), |
xrandr_event_base_(0), |
output_state_(STATE_INVALID) { |
+} |
+ |
+void OutputConfigurator::Init(bool is_panel_fitting_enabled) { |
if (!is_running_on_chrome_os_) |
return; |
+ is_panel_fitting_enabled_ = is_panel_fitting_enabled; |
+ |
// Cache the initial output state. |
Display* display = base::MessagePumpAuraX11::GetDefaultXDisplay(); |
CHECK(display != NULL); |
@@ -815,9 +742,178 @@ void OutputConfigurator::RemoveObserver(Observer* observer) { |
bool OutputConfigurator::IsInternalOutputName(const std::string& name) { |
return name.find(kInternal_LVDS) == 0 || name.find(kInternal_eDP) == 0; |
} |
+// static |
+bool OutputConfigurator::IsInternalOutput(const XRROutputInfo* output_info) { |
+ return IsInternalOutputName(std::string(output_info->name)); |
+} |
+ |
+// static |
+RRMode OutputConfigurator::GetOutputNativeMode( |
+ const XRROutputInfo* output_info) { |
+ if (output_info->nmode <= 0) { |
+ return None; |
+ } |
oshima
2012/09/21 19:38:12
nuke {}
ynovikov
2012/09/21 23:05:36
Done.
|
+ |
+ return output_info->modes[0]; |
+} |
void OutputConfigurator::NotifyOnDisplayChanged() { |
FOR_EACH_OBSERVER(Observer, observers_, OnDisplayModeChanged()); |
} |
+bool OutputConfigurator::AddMirrorModeToInternalOutput( |
+ Display* display, |
+ XRRScreenResources* screen, |
+ RROutput output_one, |
+ RROutput output_two, |
+ RRMode* output_one_mode, |
+ RRMode* output_two_mode) { |
+ // Add new mode only if panel fitting hardware will be able to display it. |
+ if (!is_panel_fitting_enabled_) { |
+ return false; |
+ } |
oshima
2012/09/21 19:38:12
nuke {}
ynovikov
2012/09/21 23:05:36
Done.
|
+ |
+ XRROutputInfo* output_one_info = |
+ XRRGetOutputInfo(display, screen, output_one); |
+ XRROutputInfo* output_two_info = |
+ XRRGetOutputInfo(display, screen, output_two); |
+ bool success = false; |
+ |
+ // Both outputs should be connected in mirror mode |
+ if (output_one_info->connection == RR_Connected && |
+ output_two_info->connection == RR_Connected) { |
+ bool one_is_internal = IsInternalOutput(output_one_info); |
+ bool two_is_internal = IsInternalOutput(output_two_info); |
+ |
+ XRROutputInfo* internal_info = NULL; |
+ XRROutputInfo* external_info = NULL; |
+ |
+ if (one_is_internal) { |
+ internal_info = output_one_info; |
+ external_info = output_two_info; |
+ |
+ VLOG_IF(1, two_is_internal) << "Two internal outputs detected."; |
+ DCHECK(!two_is_internal); |
+ } else if (two_is_internal) { |
+ internal_info = output_two_info; |
+ external_info = output_one_info; |
+ } |
+ |
+ bool internal_output_found = internal_info != NULL; |
+ |
+ if (internal_output_found) { |
+ RRMode internal_native_mode_id = GetOutputNativeMode(internal_info); |
+ RRMode external_native_mode_id = GetOutputNativeMode(external_info); |
+ |
+ if (internal_native_mode_id != None && external_native_mode_id != None) { |
+ XRRModeInfo* internal_native_mode = |
+ ModeInfoForID(screen, internal_native_mode_id); |
+ XRRModeInfo* external_native_mode = |
+ ModeInfoForID(screen, external_native_mode_id); |
+ |
+ // Panel fitting will not work if the internal output maximal resolution |
+ // is lower than that of the external output |
+ if (internal_native_mode->width >= external_native_mode->width && |
+ internal_native_mode->height >= external_native_mode->height) { |
+ XRRAddOutputMode(display, one_is_internal ? output_one : output_two, |
+ external_native_mode_id); |
+ |
+ *output_one_mode = *output_two_mode = external_native_mode_id; |
+ success = true; |
+ } |
+ } |
+ } |
+ } |
+ |
+ XRRFreeOutputInfo(output_one_info); |
+ XRRFreeOutputInfo(output_two_info); |
+ |
+ return success; |
+} |
+ |
+int OutputConfigurator::GetDualOutputs(Display* display, |
cwolfe
2012/09/21 19:17:21
Just for my sanity, here's a diff -b between the v
ynovikov
2012/09/21 23:05:36
Done.
|
+ XRRScreenResources* screen, |
+ OutputSnapshot* one, |
+ OutputSnapshot* two) { |
+ int found_count = 0; |
+ XRROutputInfo* one_info = NULL; |
+ XRROutputInfo* two_info = NULL; |
+ |
+ for (int i = 0; (i < screen->noutput) && (found_count < 2); ++i) { |
+ RROutput this_id = screen->outputs[i]; |
+ XRROutputInfo* output_info = XRRGetOutputInfo(display, screen, this_id); |
+ bool is_connected = (RR_Connected == output_info->connection); |
+ |
+ if (is_connected) { |
+ OutputSnapshot *to_populate = NULL; |
+ |
+ if (0 == found_count) { |
+ to_populate = one; |
+ one_info = output_info; |
+ } else { |
+ to_populate = two; |
+ two_info = output_info; |
+ } |
+ |
+ to_populate->output = this_id; |
+ // Now, look up the corresponding CRTC and any related info. |
+ to_populate->crtc = output_info->crtc; |
+ if (None != to_populate->crtc) { |
+ XRRCrtcInfo* crtc_info = |
+ XRRGetCrtcInfo(display, screen, to_populate->crtc); |
+ to_populate->current_mode = crtc_info->mode; |
+ to_populate->height = crtc_info->height; |
+ to_populate->y = crtc_info->y; |
+ XRRFreeCrtcInfo(crtc_info); |
+ } else { |
+ to_populate->current_mode = 0; |
+ to_populate->height = 0; |
+ to_populate->y = 0; |
+ } |
+ // Find the native_mode and leave the mirror_mode for the pass after the |
+ // loop. |
+ to_populate->native_mode = GetOutputNativeMode(output_info); |
+ to_populate->mirror_mode = 0; |
+ |
+ // See if this output refers to an internal display. |
+ to_populate->is_internal = IsInternalOutput(output_info); |
+ |
+ VLOG(1) << "Found display #" << found_count |
+ << " with output " << (int)to_populate->output |
+ << " crtc " << (int)to_populate->crtc |
+ << " current mode " << (int)to_populate->current_mode; |
+ ++found_count; |
oshima
2012/09/21 19:38:12
you probably want to increment this before VLOG.
ynovikov
2012/09/21 23:05:36
I didn't change this code, just moved it.
It does
|
+ } else { |
+ XRRFreeOutputInfo(output_info); |
+ } |
+ } |
+ |
+ if (2 == found_count) { |
+ // Find the mirror modes (if there are any). |
+ bool mirror_mode_found = FindMirrorModeForOutputs(display, |
+ screen, |
+ one->output, |
+ two->output, |
+ &one->mirror_mode, |
+ &two->mirror_mode); |
+ if (!mirror_mode_found) { |
+ bool mirror_mode_added = AddMirrorModeToInternalOutput(display, |
+ screen, |
+ one->output, |
+ two->output, |
+ &one->mirror_mode, |
+ &two->mirror_mode); |
+ if (!mirror_mode_added) { |
+ // We can't mirror so set mirror_mode to 0. |
+ one->mirror_mode = 0; |
+ two->mirror_mode = 0; |
+ } |
+ } |
+ } |
+ |
+ XRRFreeOutputInfo(one_info); |
+ XRRFreeOutputInfo(two_info); |
+ return found_count; |
+} |
+ |
} // namespace chromeos |