summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorderat@chromium.org <derat@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-16 19:56:47 +0000
committerderat@chromium.org <derat@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-16 19:56:47 +0000
commit5d99ee6aabc1dc165374898d0fcd4d114e4e1698 (patch)
treef6dd48eb0397711a04300a62210eeb3e8be5046f
parent1d07e92b5484360b2bbf8855c2ed29f5684c114c (diff)
downloadchromium_src-5d99ee6aabc1dc165374898d0fcd4d114e4e1698.zip
chromium_src-5d99ee6aabc1dc165374898d0fcd4d114e4e1698.tar.gz
chromium_src-5d99ee6aabc1dc165374898d0fcd4d114e4e1698.tar.bz2
chromeos: Include mode details in OutputSnapshot.
This updates OutputConfigurator to include modes' resolutions and interlaced-ness in OutputSnapshot structs, and to pass OutputSnapshots to observers after the display mode is changed. A following change will update ash's DisplayChangeObserverX11 class to use OutputSnapshots instead of asking the X server for the same information via XRandR. BUG=266113 Review URL: https://chromiumcodereview.appspot.com/22871010 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@218069 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--ash/display/display_change_observer_x11.cc9
-rw-r--r--ash/display/display_change_observer_x11.h4
-rw-r--r--ash/display/display_util_x11.cc2
-rw-r--r--ash/display/output_configurator_animation.cc3
-rw-r--r--ash/display/output_configurator_animation.h4
-rw-r--r--ash/touch/touch_observer_hud.cc3
-rw-r--r--ash/touch/touch_observer_hud.h4
-rw-r--r--chromeos/display/output_configurator.cc116
-rw-r--r--chromeos/display/output_configurator.h45
-rw-r--r--chromeos/display/output_configurator_unittest.cc39
-rw-r--r--chromeos/display/output_util.cc6
-rw-r--r--chromeos/display/output_util.h2
-rw-r--r--chromeos/display/real_output_configurator_delegate.cc217
-rw-r--r--chromeos/display/real_output_configurator_delegate.h18
14 files changed, 273 insertions, 199 deletions
diff --git a/ash/display/display_change_observer_x11.cc b/ash/display/display_change_observer_x11.cc
index 860a5ea..2802e6c 100644
--- a/ash/display/display_change_observer_x11.cc
+++ b/ash/display/display_change_observer_x11.cc
@@ -27,6 +27,9 @@
namespace ash {
namespace internal {
+
+using chromeos::OutputConfigurator;
+
namespace {
// The DPI threshold to detect high density screen.
@@ -89,7 +92,9 @@ bool DisplayChangeObserverX11::GetResolutionForDisplayId(int64 display_id,
return true;
}
-void DisplayChangeObserverX11::OnDisplayModeChanged() {
+void DisplayChangeObserverX11::OnDisplayModeChanged(
+ const std::vector<OutputConfigurator::OutputSnapshot>& outputs) {
+ // TODO(derat): Use |outputs| instead of re-fetching information.
XRRScreenResources* screen_resources =
XRRGetScreenResources(xdisplay_, x_root_window_);
std::map<XID, XRRCrtcInfo*> crtc_info_map;
@@ -131,7 +136,7 @@ void DisplayChangeObserverX11::OnDisplayModeChanged() {
continue;
}
const XRRModeInfo* mode =
- chromeos::FindModeInfo(screen_resources, crtc_info->mode);
+ chromeos::FindXRRModeInfo(screen_resources, crtc_info->mode);
if (!mode) {
LOG(WARNING) << "Could not find a mode for the output: output_index="
<< output_index;
diff --git a/ash/display/display_change_observer_x11.h b/ash/display/display_change_observer_x11.h
index 6781151..33fafb3 100644
--- a/ash/display/display_change_observer_x11.h
+++ b/ash/display/display_change_observer_x11.h
@@ -36,7 +36,9 @@ class DisplayChangeObserverX11
int* height) const OVERRIDE;
// Overriden from chromeos::OutputConfigurator::Observer:
- virtual void OnDisplayModeChanged() OVERRIDE;
+ virtual void OnDisplayModeChanged(
+ const std::vector<chromeos::OutputConfigurator::OutputSnapshot>& outputs)
+ OVERRIDE;
// Overriden from ShellObserver:
virtual void OnAppTerminating() OVERRIDE;
diff --git a/ash/display/display_util_x11.cc b/ash/display/display_util_x11.cc
index e662ce2..984ed53 100644
--- a/ash/display/display_util_x11.cc
+++ b/ash/display/display_util_x11.cc
@@ -63,7 +63,7 @@ std::vector<Resolution> GetResolutionList(
for (int i = 0; i < output_info->nmode; i++) {
RRMode mode = output_info->modes[i];
- const XRRModeInfo* info = chromeos::FindModeInfo(screen_resources, mode);
+ const XRRModeInfo* info = chromeos::FindXRRModeInfo(screen_resources, mode);
DCHECK(info);
// Just ignore bad entry on Release build.
if (!info)
diff --git a/ash/display/output_configurator_animation.cc b/ash/display/output_configurator_animation.cc
index 6161bef..5e58497 100644
--- a/ash/display/output_configurator_animation.cc
+++ b/ash/display/output_configurator_animation.cc
@@ -203,7 +203,8 @@ void OutputConfiguratorAnimation::StartFadeInAnimation() {
}
}
-void OutputConfiguratorAnimation::OnDisplayModeChanged() {
+void OutputConfiguratorAnimation::OnDisplayModeChanged(
+ const std::vector<chromeos::OutputConfigurator::OutputSnapshot>& outputs) {
if (!hiding_layers_.empty())
StartFadeInAnimation();
}
diff --git a/ash/display/output_configurator_animation.h b/ash/display/output_configurator_animation.h
index 3fefe92..42a66ef 100644
--- a/ash/display/output_configurator_animation.h
+++ b/ash/display/output_configurator_animation.h
@@ -42,7 +42,9 @@ class ASH_EXPORT OutputConfiguratorAnimation
protected:
// chromeos::OutputConfigurator::Observer overrides:
- virtual void OnDisplayModeChanged() OVERRIDE;
+ virtual void OnDisplayModeChanged(
+ const std::vector<chromeos::OutputConfigurator::OutputSnapshot>& outputs)
+ OVERRIDE;
virtual void OnDisplayModeChangeFailed(
chromeos::OutputState failed_new_state) OVERRIDE;
diff --git a/ash/touch/touch_observer_hud.cc b/ash/touch/touch_observer_hud.cc
index 3daeba6..9dcccd3 100644
--- a/ash/touch/touch_observer_hud.cc
+++ b/ash/touch/touch_observer_hud.cc
@@ -104,7 +104,8 @@ void TouchObserverHUD::OnDisplayRemoved(const gfx::Display& old_display) {
}
#if defined(OS_CHROMEOS)
-void TouchObserverHUD::OnDisplayModeChanged() {
+void TouchObserverHUD::OnDisplayModeChanged(
+ const std::vector<chromeos::OutputConfigurator::OutputSnapshot>& outputs) {
// Clear touch HUD for any change in display mode (single, dual extended, dual
// mirrored, ...).
Clear();
diff --git a/ash/touch/touch_observer_hud.h b/ash/touch/touch_observer_hud.h
index 850bc5e..70e23a7 100644
--- a/ash/touch/touch_observer_hud.h
+++ b/ash/touch/touch_observer_hud.h
@@ -67,7 +67,9 @@ class ASH_EXPORT TouchObserverHUD
#if defined(OS_CHROMEOS)
// Overriden from chromeos::OutputConfigurator::Observer.
- virtual void OnDisplayModeChanged() OVERRIDE;
+ virtual void OnDisplayModeChanged(
+ const std::vector<chromeos::OutputConfigurator::OutputSnapshot>& outputs)
+ OVERRIDE;
#endif // defined(OS_CHROMEOS)
// Overriden form DisplayController::Observer.
diff --git a/chromeos/display/output_configurator.cc b/chromeos/display/output_configurator.cc
index be84741..c8de844 100644
--- a/chromeos/display/output_configurator.cc
+++ b/chromeos/display/output_configurator.cc
@@ -98,6 +98,11 @@ bool IsProjecting(
} // namespace
+OutputConfigurator::ModeInfo::ModeInfo()
+ : width(0),
+ height(0),
+ interlaced(false) {}
+
OutputConfigurator::CoordinateTransformation::CoordinateTransformation()
: x_scale(1.0),
x_offset(0.0),
@@ -113,12 +118,16 @@ OutputConfigurator::OutputSnapshot::OutputSnapshot()
selected_mode(None),
x(0),
y(0),
+ width_mm(0),
+ height_mm(0),
is_internal(false),
is_aspect_preserving_scaling(false),
touch_device_id(0),
display_id(0),
has_display_id(false) {}
+OutputConfigurator::OutputSnapshot::~OutputSnapshot() {}
+
void OutputConfigurator::TestApi::SendScreenChangeEvent() {
XRRScreenChangeNotifyEvent event = {0};
event.type = xrandr_event_base_ + RRScreenChangeNotify;
@@ -150,6 +159,19 @@ bool OutputConfigurator::TestApi::TriggerConfigureTimeout() {
}
}
+// static
+const OutputConfigurator::ModeInfo* OutputConfigurator::GetModeInfo(
+ const OutputSnapshot& output,
+ RRMode mode) {
+ std::map<RRMode, ModeInfo>::const_iterator it = output.mode_infos.find(mode);
+ if (it == output.mode_infos.end()) {
+ LOG(WARNING) << "Unable to find info about mode " << mode
+ << " for output " << output.output;
+ return NULL;
+ }
+ return &it->second;
+}
+
OutputConfigurator::OutputConfigurator()
: state_controller_(NULL),
mirroring_controller_(NULL),
@@ -405,7 +427,8 @@ void OutputConfigurator::ConfigureOutputs() {
}
void OutputConfigurator::NotifyOnDisplayChanged() {
- FOR_EACH_OBSERVER(Observer, observers_, OnDisplayModeChanged());
+ FOR_EACH_OBSERVER(Observer, observers_,
+ OnDisplayModeChanged(cached_outputs_));
}
bool OutputConfigurator::EnterStateOrFallBackToSoftwareMirroring(
@@ -467,9 +490,12 @@ bool OutputConfigurator::EnterState(
output->current_mode = output_power[i] ? output->selected_mode : None;
if (output_power[i] || outputs.size() == 1) {
- if (!delegate_->GetModeDetails(
- output->selected_mode, &width, &height, NULL))
+ const ModeInfo* mode_info =
+ GetModeInfo(*output, output->selected_mode);
+ if (!mode_info)
return false;
+ width = mode_info->width;
+ height = mode_info->height;
}
}
break;
@@ -482,9 +508,14 @@ bool OutputConfigurator::EnterState(
return false;
}
- if (!delegate_->GetModeDetails(
- outputs[0].mirror_mode, &width, &height, NULL))
+ if (!outputs[0].mirror_mode)
+ return false;
+ const ModeInfo* mode_info =
+ GetModeInfo(outputs[0], outputs[0].mirror_mode);
+ if (!mode_info)
return false;
+ width = mode_info->width;
+ height = mode_info->height;
for (size_t i = 0; i < outputs.size(); ++i) {
OutputSnapshot* output = &updated_outputs[i];
@@ -496,9 +527,9 @@ bool OutputConfigurator::EnterState(
// Otherwise, assume it is full screen, and use identity CTM.
if (output->mirror_mode != output->native_mode &&
output->is_aspect_preserving_scaling) {
- output->transform = GetMirrorModeCTM(output);
+ output->transform = GetMirrorModeCTM(*output);
mirrored_display_area_ratio_map_[output->touch_device_id] =
- GetMirroredDisplayAreaRatio(output);
+ GetMirroredDisplayAreaRatio(*output);
}
}
}
@@ -512,15 +543,7 @@ bool OutputConfigurator::EnterState(
return false;
}
- // Pairs are [width, height] corresponding to the given output's mode.
- std::vector<std::pair<int, int> > mode_sizes(outputs.size());
-
for (size_t i = 0; i < outputs.size(); ++i) {
- if (!delegate_->GetModeDetails(outputs[i].selected_mode,
- &(mode_sizes[i].first), &(mode_sizes[i].second), NULL)) {
- return false;
- }
-
OutputSnapshot* output = &updated_outputs[i];
output->x = 0;
output->y = height ? height + kVerticalGap : 0;
@@ -529,17 +552,24 @@ bool OutputConfigurator::EnterState(
// Retain the full screen size even if all outputs are off so the
// same desktop configuration can be restored when the outputs are
// turned back on.
- width = std::max<int>(width, mode_sizes[i].first);
- height += (height ? kVerticalGap : 0) + mode_sizes[i].second;
+ const ModeInfo* mode_info =
+ GetModeInfo(outputs[i], outputs[i].selected_mode);
+ if (!mode_info)
+ return false;
+ width = std::max<int>(width, mode_info->width);
+ height += (height ? kVerticalGap : 0) + mode_info->height;
}
for (size_t i = 0; i < outputs.size(); ++i) {
OutputSnapshot* output = &updated_outputs[i];
if (output->touch_device_id) {
+ const ModeInfo* mode_info =
+ GetModeInfo(*output, output->selected_mode);
+ DCHECK(mode_info);
CoordinateTransformation* ctm = &(output->transform);
- ctm->x_scale = static_cast<float>(mode_sizes[i].first) / width;
+ ctm->x_scale = static_cast<float>(mode_info->width) / width;
ctm->x_offset = static_cast<float>(output->x) / width;
- ctm->y_scale = static_cast<float>(mode_sizes[i].second) / height;
+ ctm->y_scale = static_cast<float>(mode_info->height) / height;
ctm->y_offset = static_cast<float>(output->y) / height;
}
}
@@ -609,24 +639,20 @@ OutputState OutputConfigurator::GetOutputState(
OutputConfigurator::CoordinateTransformation
OutputConfigurator::GetMirrorModeCTM(
- const OutputConfigurator::OutputSnapshot* output) {
+ const OutputConfigurator::OutputSnapshot& output) {
CoordinateTransformation ctm; // Default to identity
- int native_mode_width = 0, native_mode_height = 0;
- int mirror_mode_width = 0, mirror_mode_height = 0;
- if (!delegate_->GetModeDetails(output->native_mode,
- &native_mode_width, &native_mode_height, NULL) ||
- !delegate_->GetModeDetails(output->mirror_mode,
- &mirror_mode_width, &mirror_mode_height, NULL))
- return ctm;
+ const ModeInfo* native_mode_info = GetModeInfo(output, output.native_mode);
+ const ModeInfo* mirror_mode_info = GetModeInfo(output, output.mirror_mode);
- if (native_mode_height == 0 || mirror_mode_height == 0 ||
- native_mode_width == 0 || mirror_mode_width == 0)
+ if (!native_mode_info || !mirror_mode_info ||
+ native_mode_info->height == 0 || mirror_mode_info->height == 0 ||
+ native_mode_info->width == 0 || mirror_mode_info->width == 0)
return ctm;
- float native_mode_ar = static_cast<float>(native_mode_width) /
- static_cast<float>(native_mode_height);
- float mirror_mode_ar = static_cast<float>(mirror_mode_width) /
- static_cast<float>(mirror_mode_height);
+ float native_mode_ar = static_cast<float>(native_mode_info->width) /
+ static_cast<float>(native_mode_info->height);
+ float mirror_mode_ar = static_cast<float>(mirror_mode_info->width) /
+ static_cast<float>(mirror_mode_info->height);
if (mirror_mode_ar > native_mode_ar) { // Letterboxing
ctm.x_scale = 1.0;
@@ -647,24 +673,20 @@ OutputConfigurator::GetMirrorModeCTM(
}
float OutputConfigurator::GetMirroredDisplayAreaRatio(
- const OutputConfigurator::OutputSnapshot* output) {
+ const OutputConfigurator::OutputSnapshot& output) {
float area_ratio = 1.0f;
- int native_mode_width = 0, native_mode_height = 0;
- int mirror_mode_width = 0, mirror_mode_height = 0;
- if (!delegate_->GetModeDetails(output->native_mode,
- &native_mode_width, &native_mode_height, NULL) ||
- !delegate_->GetModeDetails(output->mirror_mode,
- &mirror_mode_width, &mirror_mode_height, NULL))
- return area_ratio;
+ const ModeInfo* native_mode_info = GetModeInfo(output, output.native_mode);
+ const ModeInfo* mirror_mode_info = GetModeInfo(output, output.mirror_mode);
- if (native_mode_height == 0 || mirror_mode_height == 0 ||
- native_mode_width == 0 || mirror_mode_width == 0)
+ if (!native_mode_info || !mirror_mode_info ||
+ native_mode_info->height == 0 || mirror_mode_info->height == 0 ||
+ native_mode_info->width == 0 || mirror_mode_info->width == 0)
return area_ratio;
- float width_ratio = static_cast<float>(mirror_mode_width) /
- static_cast<float>(native_mode_width);
- float height_ratio = static_cast<float>(mirror_mode_height) /
- static_cast<float>(native_mode_height);
+ float width_ratio = static_cast<float>(mirror_mode_info->width) /
+ static_cast<float>(native_mode_info->width);
+ float height_ratio = static_cast<float>(mirror_mode_info->height) /
+ static_cast<float>(native_mode_info->height);
area_ratio = width_ratio * height_ratio;
return area_ratio;
diff --git a/chromeos/display/output_configurator.h b/chromeos/display/output_configurator.h
index b9d7faf..6e25b4d 100644
--- a/chromeos/display/output_configurator.h
+++ b/chromeos/display/output_configurator.h
@@ -42,6 +42,14 @@ class CHROMEOS_EXPORT OutputConfigurator
: public base::MessageLoop::Dispatcher,
public base::MessagePumpObserver {
public:
+ struct ModeInfo {
+ ModeInfo();
+
+ int width;
+ int height;
+ bool interlaced;
+ };
+
struct CoordinateTransformation {
// Initialized to the identity transformation.
CoordinateTransformation();
@@ -55,6 +63,7 @@ class CHROMEOS_EXPORT OutputConfigurator
// Information about an output's current state.
struct OutputSnapshot {
OutputSnapshot();
+ ~OutputSnapshot();
RROutput output;
@@ -78,9 +87,16 @@ class CHROMEOS_EXPORT OutputConfigurator
int x;
int y;
+ // Output's physical dimensions.
+ uint64 width_mm;
+ uint64 height_mm;
+
bool is_internal;
bool is_aspect_preserving_scaling;
+ // Map from mode IDs to details about the corresponding modes.
+ std::map<RRMode, ModeInfo> mode_infos;
+
// XInput device ID or 0 if this output isn't a touchscreen.
int touch_device_id;
@@ -96,12 +112,15 @@ class CHROMEOS_EXPORT OutputConfigurator
public:
virtual ~Observer() {}
- // Called when the change of the display mode finished. It will usually
- // start the fading in the displays.
- virtual void OnDisplayModeChanged() {}
+ // Called after the display mode has been changed. |output| contains the
+ // just-applied configuration. Note that the X server is no longer grabbed
+ // when this method is called, so the actual configuration could've changed
+ // already.
+ virtual void OnDisplayModeChanged(
+ const std::vector<OutputSnapshot>& outputs) {}
- // Called when the change of the display mode is issued but failed.
- // |failed_new_state| is the new state which the system failed to enter.
+ // Called after a display mode change attempt failed. |failed_new_state| is
+ // the new state which the system failed to enter.
virtual void OnDisplayModeChangeFailed(OutputState failed_new_state) {}
};
@@ -168,13 +187,6 @@ class CHROMEOS_EXPORT OutputConfigurator
virtual std::vector<OutputSnapshot> GetOutputs(
const StateController* state_controller) = 0;
- // Gets details corresponding to |mode|. Parameters may be NULL.
- // Returns true on success.
- virtual bool GetModeDetails(RRMode mode,
- int* width,
- int* height,
- bool* interlaced) = 0;
-
// Calls XRRSetCrtcConfig() with the given options but some of our default
// output count and rotation arguments. Returns true on success.
virtual bool ConfigureCrtc(RRCrtc crtc,
@@ -249,6 +261,11 @@ class CHROMEOS_EXPORT OutputConfigurator
// See crbug.com/130188 for initial discussion.
static const int kVerticalGap = 60;
+ // Returns a pointer to the ModeInfo struct in |output| corresponding to
+ // |mode|, or NULL if the struct isn't present.
+ static const ModeInfo* GetModeInfo(const OutputSnapshot& output,
+ RRMode mode);
+
OutputConfigurator();
virtual ~OutputConfigurator();
@@ -360,12 +377,12 @@ class CHROMEOS_EXPORT OutputConfigurator
// |output| is the output on which mirror mode is being applied.
// Returns the transformation or identity if computations fail.
CoordinateTransformation GetMirrorModeCTM(
- const OutputConfigurator::OutputSnapshot* output);
+ const OutputConfigurator::OutputSnapshot& output);
// Returns the ratio between mirrored mode area and native mode area:
// (mirror_mode_width * mirrow_mode_height) / (native_width * native_height)
float GetMirroredDisplayAreaRatio(
- const OutputConfigurator::OutputSnapshot* output);
+ const OutputConfigurator::OutputSnapshot& output);
StateController* state_controller_;
SoftwareMirroringController* mirroring_controller_;
diff --git a/chromeos/display/output_configurator_unittest.cc b/chromeos/display/output_configurator_unittest.cc
index 6769e51..0749399 100644
--- a/chromeos/display/output_configurator_unittest.cc
+++ b/chromeos/display/output_configurator_unittest.cc
@@ -114,11 +114,6 @@ class TestDelegate : public OutputConfigurator::Delegate {
return actions;
}
- // Adds a mode to be returned by GetModeDetails().
- void AddMode(RRMode mode, int width, int height, bool interlaced) {
- modes_[mode] = ModeDetails(width, height, interlaced);
- }
-
// OutputConfigurator::Delegate overrides:
virtual void SetPanelFittingEnabled(bool enabled) OVERRIDE {}
virtual void InitXRandRExtension(int* event_base) OVERRIDE {
@@ -138,23 +133,6 @@ class TestDelegate : public OutputConfigurator::Delegate {
const OutputConfigurator::StateController* controller) OVERRIDE {
return outputs_;
}
- virtual bool GetModeDetails(
- RRMode mode,
- int* width,
- int* height,
- bool* interlaced) OVERRIDE {
- std::map<RRMode, ModeDetails>::const_iterator it = modes_.find(mode);
- if (it == modes_.end())
- return false;
-
- if (width)
- *width = it->second.width;
- if (height)
- *height = it->second.height;
- if (interlaced)
- *interlaced = it->second.interlaced;
- return true;
- }
virtual bool ConfigureCrtc(RRCrtc crtc,
RRMode mode,
RROutput output,
@@ -270,6 +248,14 @@ class OutputConfiguratorTest : public testing::Test {
configurator_.set_state_controller(&state_controller_);
configurator_.set_mirroring_controller(&mirroring_controller_);
+ OutputConfigurator::ModeInfo small_mode_info;
+ small_mode_info.width = kSmallModeWidth;
+ small_mode_info.height = kSmallModeHeight;
+
+ OutputConfigurator::ModeInfo big_mode_info;
+ big_mode_info.width = kBigModeWidth;
+ big_mode_info.height = kBigModeHeight;
+
OutputConfigurator::OutputSnapshot* o = &outputs_[0];
o->output = 1;
o->crtc = 10;
@@ -281,6 +267,7 @@ class OutputConfiguratorTest : public testing::Test {
o->y = 0;
o->is_internal = true;
o->is_aspect_preserving_scaling = true;
+ o->mode_infos[kSmallModeId] = small_mode_info;
o->touch_device_id = 0;
o->has_display_id = true;
@@ -295,12 +282,12 @@ class OutputConfiguratorTest : public testing::Test {
o->y = 0;
o->is_internal = false;
o->is_aspect_preserving_scaling = true;
+ o->mode_infos[kSmallModeId] = small_mode_info;
+ o->mode_infos[kBigModeId] = big_mode_info;
o->touch_device_id = 0;
o->has_display_id = true;
UpdateOutputs(2, false);
- delegate_->AddMode(kSmallModeId, kSmallModeWidth, kSmallModeHeight, false);
- delegate_->AddMode(kBigModeId, kBigModeWidth, kBigModeHeight, false);
}
void DisableNativeMirroring() {
@@ -704,9 +691,7 @@ TEST_F(OutputConfiguratorTest, Headless) {
delegate_->GetActionsAndClear());
// Connect an external display and check that it's configured correctly.
- outputs_[0].is_internal = false;
- outputs_[0].native_mode = kBigModeId;
- outputs_[0].selected_mode = kBigModeId;
+ outputs_[0] = outputs_[1];
UpdateOutputs(1, true);
EXPECT_EQ(JoinActions(kUpdateXRandR, kGrab,
GetFramebufferAction(kBigModeWidth, kBigModeHeight,
diff --git a/chromeos/display/output_util.cc b/chromeos/display/output_util.cc
index d9d2913..4800a2d 100644
--- a/chromeos/display/output_util.cc
+++ b/chromeos/display/output_util.cc
@@ -331,8 +331,8 @@ bool IsInternalOutputName(const std::string& name) {
name.find(kInternal_DSI) == 0;
}
-const XRRModeInfo* FindModeInfo(const XRRScreenResources* screen_resources,
- XID current_mode) {
+const XRRModeInfo* FindXRRModeInfo(const XRRScreenResources* screen_resources,
+ XID current_mode) {
for (int m = 0; m < screen_resources->nmode; m++) {
XRRModeInfo *mode = &screen_resources->modes[m];
if (mode->id == current_mode)
@@ -353,7 +353,7 @@ RRMode FindOutputModeMatchingSize(
bool non_interlaced_found = false;
for (int i = 0; i < output_info->nmode; ++i) {
RRMode mode = output_info->modes[i];
- const XRRModeInfo* info = FindModeInfo(screen_resources, mode);
+ const XRRModeInfo* info = FindXRRModeInfo(screen_resources, mode);
if (info->width == width && info->height == height) {
float rate = GetRefreshRate(info);
diff --git a/chromeos/display/output_util.h b/chromeos/display/output_util.h
index d464ba6..d2f1f01 100644
--- a/chromeos/display/output_util.h
+++ b/chromeos/display/output_util.h
@@ -65,7 +65,7 @@ CHROMEOS_EXPORT bool ParseOutputOverscanFlag(const unsigned char* prop,
CHROMEOS_EXPORT bool IsInternalOutputName(const std::string& name);
// Find a XRRModeInfo that matches |mode|.
-CHROMEOS_EXPORT const XRRModeInfo* FindModeInfo(
+CHROMEOS_EXPORT const XRRModeInfo* FindXRRModeInfo(
const XRRScreenResources* screen_resources,
XID mode);
diff --git a/chromeos/display/real_output_configurator_delegate.cc b/chromeos/display/real_output_configurator_delegate.cc
index 5b2d3c7..6d3497b 100644
--- a/chromeos/display/real_output_configurator_delegate.cc
+++ b/chromeos/display/real_output_configurator_delegate.cc
@@ -13,6 +13,7 @@
#include <cmath>
#include <set>
+#include <utility>
#include "base/logging.h"
#include "base/message_loop/message_pump_aurax11.h"
@@ -116,68 +117,38 @@ RealOutputConfiguratorDelegate::GetOutputs(
RRCrtc last_used_crtc = None;
for (int i = 0; i < screen_->noutput && outputs.size() < 2; ++i) {
- RROutput this_id = screen_->outputs[i];
- XRROutputInfo* output_info = XRRGetOutputInfo(display_, screen_, this_id);
+ RROutput output_id = screen_->outputs[i];
+ XRROutputInfo* output_info = XRRGetOutputInfo(display_, screen_, output_id);
bool is_connected = (output_info->connection == RR_Connected);
- if (is_connected) {
- OutputConfigurator::OutputSnapshot to_populate;
- to_populate.output = this_id;
- to_populate.has_display_id =
- GetDisplayId(this_id, i, &to_populate.display_id);
- to_populate.is_internal = IsInternalOutput(output_info);
- // Use the index as a valid display id even if the internal
- // display doesn't have valid EDID because the index
- // will never change.
- if (!to_populate.has_display_id && to_populate.is_internal)
- to_populate.has_display_id = true;
-
- (outputs.empty() ? one_info : two_info) = output_info;
-
- // Now, look up the current CRTC and any related info.
- if (output_info->crtc) {
- XRRCrtcInfo* crtc_info = XRRGetCrtcInfo(
- display_, screen_, output_info->crtc);
- to_populate.current_mode = crtc_info->mode;
- to_populate.x = crtc_info->x;
- to_populate.y = crtc_info->y;
- XRRFreeCrtcInfo(crtc_info);
- }
+ if (!is_connected) {
+ XRRFreeOutputInfo(output_info);
+ continue;
+ }
- // Assign a CRTC that isn't already in use.
- for (int j = 0; j < output_info->ncrtc; ++j) {
- if (output_info->crtcs[j] != last_used_crtc) {
- to_populate.crtc = output_info->crtcs[j];
- last_used_crtc = to_populate.crtc;
- break;
- }
- }
- to_populate.native_mode = GetOutputNativeMode(output_info);
- if (to_populate.has_display_id) {
- int width = 0, height = 0;
- if (state_controller &&
- state_controller->GetResolutionForDisplayId(
- to_populate.display_id, &width, &height)) {
- to_populate.selected_mode =
- FindOutputModeMatchingSize(screen_, output_info, width, height);
- }
+ (outputs.empty() ? one_info : two_info) = output_info;
+
+ OutputConfigurator::OutputSnapshot output = InitOutputSnapshot(
+ output_id, output_info, &last_used_crtc, i);
+
+ if (output.has_display_id) {
+ int width = 0, height = 0;
+ if (state_controller &&
+ state_controller->GetResolutionForDisplayId(
+ output.display_id, &width, &height)) {
+ output.selected_mode =
+ FindOutputModeMatchingSize(screen_, output_info, width, height);
}
- // Fallback to native mode.
- if (to_populate.selected_mode == None)
- to_populate.selected_mode = to_populate.native_mode;
-
- to_populate.is_aspect_preserving_scaling =
- IsOutputAspectPreservingScaling(this_id);
- to_populate.touch_device_id = None;
-
- VLOG(2) << "Found display " << outputs.size() << ":"
- << " output=" << to_populate.output
- << " crtc=" << to_populate.crtc
- << " current_mode=" << to_populate.current_mode;
- outputs.push_back(to_populate);
- } else {
- XRRFreeOutputInfo(output_info);
}
+ // Fall back to native mode.
+ if (output.selected_mode == None)
+ output.selected_mode = output.native_mode;
+
+ VLOG(2) << "Found display " << outputs.size() << ":"
+ << " output=" << output.output
+ << " crtc=" << output.crtc
+ << " current_mode=" << output.current_mode;
+ outputs.push_back(output);
}
if (outputs.size() == 2) {
@@ -229,30 +200,6 @@ RealOutputConfiguratorDelegate::GetOutputs(
return outputs;
}
-bool RealOutputConfiguratorDelegate::GetModeDetails(RRMode mode,
- int* width,
- int* height,
- bool* interlaced) {
- CHECK(screen_) << "Server not grabbed";
- // 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 expensive.
- for (int i = 0; i < screen_->nmode; ++i) {
- if (mode == screen_->modes[i].id) {
- const XRRModeInfo& info = screen_->modes[i];
- if (width)
- *width = info.width;
- if (height)
- *height = info.height;
- if (interlaced)
- *interlaced = info.modeFlags & RR_Interlace;
- return true;
- }
- }
- return false;
-}
-
bool RealOutputConfiguratorDelegate::ConfigureCrtc(
RRCrtc crtc,
RRMode mode,
@@ -344,6 +291,84 @@ void RealOutputConfiguratorDelegate::SendProjectingStateToPowerManager(
SetIsProjecting(projecting);
}
+bool RealOutputConfiguratorDelegate::GetModeDetails(RRMode mode,
+ int* width,
+ int* height,
+ bool* interlaced) {
+ CHECK(screen_) << "Server not grabbed";
+ // 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 expensive.
+ for (int i = 0; i < screen_->nmode; ++i) {
+ if (mode == screen_->modes[i].id) {
+ const XRRModeInfo& info = screen_->modes[i];
+ if (width)
+ *width = info.width;
+ if (height)
+ *height = info.height;
+ if (interlaced)
+ *interlaced = info.modeFlags & RR_Interlace;
+ return true;
+ }
+ }
+ return false;
+}
+
+OutputConfigurator::OutputSnapshot
+RealOutputConfiguratorDelegate::InitOutputSnapshot(
+ RROutput id,
+ XRROutputInfo* info,
+ RRCrtc* last_used_crtc,
+ int index) {
+ OutputConfigurator::OutputSnapshot output;
+ output.output = id;
+ output.width_mm = info->mm_width;
+ output.height_mm = info->mm_height;
+ output.has_display_id = GetDisplayId(id, index, &output.display_id);
+ output.is_internal = IsInternalOutput(info);
+
+ // Use the index as a valid display ID even if the internal
+ // display doesn't have valid EDID because the index
+ // will never change.
+ if (!output.has_display_id && output.is_internal)
+ output.has_display_id = true;
+
+ if (info->crtc) {
+ XRRCrtcInfo* crtc_info = XRRGetCrtcInfo(display_, screen_, info->crtc);
+ output.current_mode = crtc_info->mode;
+ output.x = crtc_info->x;
+ output.y = crtc_info->y;
+ XRRFreeCrtcInfo(crtc_info);
+ }
+
+ // Assign a CRTC that isn't already in use.
+ for (int i = 0; i < info->ncrtc; ++i) {
+ if (info->crtcs[i] != *last_used_crtc) {
+ output.crtc = info->crtcs[i];
+ *last_used_crtc = output.crtc;
+ break;
+ }
+ }
+
+ output.native_mode = GetOutputNativeMode(info);
+ output.is_aspect_preserving_scaling = IsOutputAspectPreservingScaling(id);
+ output.touch_device_id = None;
+
+ for (int i = 0; i < info->nmode; ++i) {
+ const RRMode mode = info->modes[i];
+ OutputConfigurator::ModeInfo mode_info;
+ if (GetModeDetails(mode, &mode_info.width, &mode_info.height,
+ &mode_info.interlaced)) {
+ output.mode_infos.insert(std::make_pair(mode, mode_info));
+ } else {
+ LOG(WARNING) << "Unable to find XRRModeInfo for mode " << mode;
+ }
+ }
+
+ return output;
+}
+
void RealOutputConfiguratorDelegate::DestroyUnusedCrtcs(
const std::vector<OutputConfigurator::OutputSnapshot>& outputs) {
CHECK(screen_) << "Server not grabbed";
@@ -363,25 +388,28 @@ void RealOutputConfiguratorDelegate::DestroyUnusedCrtcs(
RRCrtc crtc = screen_->crtcs[i];
RRMode mode = None;
RROutput output = None;
+ const OutputConfigurator::ModeInfo* mode_info = NULL;
for (std::vector<OutputConfigurator::OutputSnapshot>::const_iterator it =
outputs.begin(); it != outputs.end(); ++it) {
if (crtc == it->crtc) {
mode = it->current_mode;
output = it->output;
+ if (mode != None)
+ mode_info = OutputConfigurator::GetModeInfo(*it, mode);
break;
}
}
- if (mode != None) {
+ if (mode_info) {
// In case our CRTC doesn't fit in our current framebuffer, disable it.
// It'll get reenabled after we resize the framebuffer.
- int mode_width = 0, mode_height = 0;
- CHECK(GetModeDetails(mode, &mode_width, &mode_height, NULL));
int current_width = DisplayWidth(display_, DefaultScreen(display_));
int current_height = DisplayHeight(display_, DefaultScreen(display_));
- if (mode_width > current_width || mode_height > current_height) {
+ if (mode_info->width > current_width ||
+ mode_info->height > current_height) {
mode = None;
output = None;
+ mode_info = NULL;
}
}
@@ -556,12 +584,13 @@ void RealOutputConfiguratorDelegate::GetTouchscreens(
if (width > 0.0 && height > 0.0 && is_direct_touch) {
size_t k = 0;
for (; k < outputs->size(); k++) {
- if ((*outputs)[k].native_mode == None ||
- (*outputs)[k].touch_device_id != None)
+ OutputConfigurator::OutputSnapshot* output = &(*outputs)[k];
+ if (output->native_mode == None || output->touch_device_id != None)
continue;
- int native_mode_width = 0, native_mode_height = 0;
- if (!GetModeDetails((*outputs)[k].native_mode, &native_mode_width,
- &native_mode_height, NULL))
+
+ const OutputConfigurator::ModeInfo* mode_info =
+ OutputConfigurator::GetModeInfo(*output, output->native_mode);
+ if (!mode_info)
continue;
// Allow 1 pixel difference between screen and touchscreen
@@ -569,12 +598,12 @@ void RealOutputConfiguratorDelegate::GetTouchscreens(
// 1024x768 touchscreen's resolution would be 1024x768, but for
// some 1023x767. It really depends on touchscreen's firmware
// configuration.
- if (std::abs(native_mode_width - width) <= 1.0 &&
- std::abs(native_mode_height - height) <= 1.0) {
- (*outputs)[k].touch_device_id = info[i].deviceid;
+ if (std::abs(mode_info->width - width) <= 1.0 &&
+ std::abs(mode_info->height - height) <= 1.0) {
+ output->touch_device_id = info[i].deviceid;
VLOG(2) << "Found touchscreen for output #" << k
- << " id " << (*outputs)[k].touch_device_id
+ << " id " << output->touch_device_id
<< " width " << width
<< " height " << height;
break;
diff --git a/chromeos/display/real_output_configurator_delegate.h b/chromeos/display/real_output_configurator_delegate.h
index 9f083cf..2753ae5 100644
--- a/chromeos/display/real_output_configurator_delegate.h
+++ b/chromeos/display/real_output_configurator_delegate.h
@@ -39,11 +39,6 @@ class RealOutputConfiguratorDelegate : public OutputConfigurator::Delegate {
virtual void ForceDPMSOn() OVERRIDE;
virtual std::vector<OutputConfigurator::OutputSnapshot> GetOutputs(
const OutputConfigurator::StateController* state_controller) OVERRIDE;
- virtual bool GetModeDetails(
- RRMode mode,
- int* width,
- int* height,
- bool* interlaced) OVERRIDE;
virtual bool ConfigureCrtc(
RRCrtc crtc,
RRMode mode,
@@ -60,6 +55,19 @@ class RealOutputConfiguratorDelegate : public OutputConfigurator::Delegate {
virtual void SendProjectingStateToPowerManager(bool projecting) OVERRIDE;
private:
+ // Gets details corresponding to |mode|. Parameters may be NULL. Returns
+ // true on success.
+ bool GetModeDetails(RRMode mode, int* width, int* height, bool* interlaced);
+
+ // Helper method for GetOutputs() that returns an OutputSnapshot struct based
+ // on the passed-in information. Further initialization is required (e.g.
+ // |selected_mode|, |mirror_mode|, and |touch_device_id|).
+ OutputConfigurator::OutputSnapshot InitOutputSnapshot(
+ RROutput id,
+ XRROutputInfo* info,
+ RRCrtc* last_used_crtc,
+ int index);
+
// Destroys unused CRTCs and parks used CRTCs in a way which allows a
// framebuffer resize. This is faster than turning them off, resizing,
// then turning them back on.