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

Unified 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: merge 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chromeos/display/output_configurator.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chromeos/display/output_configurator.cc
diff --git a/chromeos/display/output_configurator.cc b/chromeos/display/output_configurator.cc
index b41362ff9657278b8fdc1ffc2178ada9a6b79700..fb1c9c043de138e40b143d8bab3e6411eb7249d0 100644
--- a/chromeos/display/output_configurator.cc
+++ b/chromeos/display/output_configurator.cc
@@ -28,6 +28,7 @@
#include "base/message_pump_aurax11.h"
#include "base/metrics/histogram.h"
#include "base/perftimer.h"
+#include "base/strings/string_number_conversions.h"
#include "base/time.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/power_manager_client.h"
@@ -93,6 +94,7 @@ enum MirrorModeType {
};
namespace {
+
// DPI measurements.
const float kMmInInch = 25.4;
const float kDpi96 = 96.0;
@@ -120,6 +122,22 @@ const int64 kConfigureDelayMs = 500;
// See crbug.com/130188 for initial discussion.
const int kVerticalGap = 60;
+// Returns a string describing |state|.
+std::string DisplayPowerStateToString(DisplayPowerState state) {
+ switch (state) {
+ case DISPLAY_POWER_ALL_ON:
+ return "ALL_ON";
+ case DISPLAY_POWER_ALL_OFF:
+ return "ALL_OFF";
+ case DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON:
+ return "INTERNAL_OFF_EXTERNAL_ON";
+ case DISPLAY_POWER_INTERNAL_ON_EXTERNAL_OFF:
+ return "INTERNAL_ON_EXTERNAL_OFF";
+ default:
+ return "unknown (" + base::IntToString(state) + ")";
+ }
+}
+
// TODO: Determine if we need to organize modes in a way which provides better
// than O(n) lookup time. In many call sites, for example, the "next" mode is
// typically what we are looking for so using this helper might be too
@@ -597,14 +615,14 @@ void OutputConfigurator::Stop() {
}
bool OutputConfigurator::SetDisplayPower(DisplayPowerState power_state,
- bool force_probe) {
+ int flags) {
TRACE_EVENT0("chromeos", "OutputConfigurator::SetDisplayPower");
- VLOG(1) << "OutputConfigurator::SetDisplayPower: power_state=" << power_state
- << " force_probe=" << force_probe;
+ VLOG(1) << "SetDisplayPower: power_state="
+ << DisplayPowerStateToString(power_state) << " flags=" << flags;
if (!configure_display_)
return false;
- if (power_state == power_state_ && !force_probe)
+ if (power_state == power_state_ && !(flags & kSetDisplayPowerForceProbe))
return true;
Display* display = base::MessagePumpAuraX11::GetDefaultXDisplay();
@@ -616,7 +634,11 @@ bool OutputConfigurator::SetDisplayPower(DisplayPowerState power_state,
std::vector<OutputSnapshot> outputs = GetDualOutputs(display, screen);
connected_output_count_ = outputs.size();
- if (EnterState(display, screen, window, output_state_, power_state,
+ bool only_if_single_internal_display =
+ flags & kSetDisplayPowerOnlyIfSingleInternalDisplay;
+ bool single_internal_display = outputs.size() == 1 && outputs[0].is_internal;
+ if ((single_internal_display || !only_if_single_internal_display) &&
+ EnterState(display, screen, window, output_state_, power_state,
outputs)) {
power_state_ = power_state;
if (power_state != DISPLAY_POWER_ALL_OFF) {
@@ -629,7 +651,6 @@ bool OutputConfigurator::SetDisplayPower(DisplayPowerState power_state,
XRRFreeScreenResources(screen);
XUngrabServer(display);
-
return true;
}
@@ -757,10 +778,15 @@ bool OutputConfigurator::IsInternalOutputName(const std::string& name) {
}
void OutputConfigurator::SuspendDisplays() {
- // Turn internal displays on before suspend. At this point, the backlight
- // is off, so we turn on the internal display so that we can resume
- // directly into "on" state. This greatly reduces resume times.
- SetDisplayPower(DISPLAY_POWER_INTERNAL_ON_EXTERNAL_OFF, false);
+ // If the display is off due to user inactivity and there's only a single
+ // internal display connected, switch to the all-on state before
+ // suspending. This shouldn't be very noticeable to the user since the
+ // backlight is off at this point, and doing this lets us resume directly
+ // into the "on" state, which greatly reduces resume times.
+ if (power_state_ == DISPLAY_POWER_ALL_OFF) {
+ SetDisplayPower(DISPLAY_POWER_ALL_ON,
+ kSetDisplayPowerOnlyIfSingleInternalDisplay);
+ }
// We need to make sure that the monitor configuration we just did actually
// completes before we return, because otherwise the X message could be
@@ -771,7 +797,7 @@ void OutputConfigurator::SuspendDisplays() {
void OutputConfigurator::ResumeDisplays() {
// Force probing to ensure that we pick up any changes that were made
// while the system was suspended.
- SetDisplayPower(DISPLAY_POWER_ALL_ON, true);
+ SetDisplayPower(power_state_, kSetDisplayPowerForceProbe);
}
void OutputConfigurator::NotifyOnDisplayChanged() {
@@ -1102,6 +1128,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 +1152,104 @@ 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);
-
- for (size_t i = 0; i < outputs.size(); i++) {
- if (outputs[i].touch_device_id == None)
- continue;
-
- 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]);
+ 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);
}
- 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;
}
+ } 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;
+ }
- 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);
+ configs[i] = CrtcConfig(
+ crtcs[i], 0, height,
+ output_power[i] ? outputs[i].native_mode : None,
+ outputs[i].output);
+
+ // Retain the full screen size if all outputs are off so the same
+ // desktop configuration can be restored when the outputs are
+ // turned back on.
+ if (output_power[i] || all_outputs_off) {
+ width = std::max<int>(width, mode_infos[i]->width);
+ height += (height ? kVerticalGap : 0) + mode_infos[i]->height;
+ }
}
- 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;
}
« no previous file with comments | « chromeos/display/output_configurator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698