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

Side by Side Diff: monitor_reconfigure.cc

Issue 6854002: Merge monitor_reconfigure into powerd. (Closed) Base URL: ssh://gitrw.chromium.org:9222/power_manager.git@master
Patch Set: . Created 9 years, 8 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « monitor_reconfigure.h ('k') | powerd.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "power_manager/monitor_reconfigure.h"
6
7 #include <algorithm>
8 #include <cstdio>
9 #include <cstdlib>
10
11 #include "base/logging.h"
12 #include "power_manager/backlight_controller.h"
13 #include "power_manager/udev_controller.h"
14
15 using std::sort;
16 using std::vector;
17
18 namespace {
19 // Name of the internal output.
20 const char kLcdOutputName[] = "LVDS1";
21 // The screen DPI we pass to X11.
22 const float kScreenDpi = 96.0;
23 // An inch in mm.
24 const float kInchInMm = 25.4;
25 }
26
27 namespace power_manager {
28
29 void MonitorReconfigureDelegate::Run(GIOChannel* /* source */,
30 GIOCondition /* condition */) {
31 monitor_reconfigure_->Run();
32 }
33
34 MonitorReconfigure::MonitorReconfigure()
35 : display_(NULL),
36 window_(0),
37 lcd_output_(0),
38 lcd_output_info_(NULL),
39 external_output_(0),
40 external_output_info_(NULL),
41 backlight_ctl_(NULL),
42 delegate_(NULL),
43 controller_(NULL) {}
44
45 MonitorReconfigure::MonitorReconfigure(
46 BacklightController* backlight_ctl)
47 : display_(NULL),
48 window_(0),
49 lcd_output_(0),
50 lcd_output_info_(NULL),
51 external_output_(0),
52 external_output_info_(NULL),
53 backlight_ctl_(backlight_ctl),
54 delegate_(NULL),
55 controller_(NULL) {}
56
57 MonitorReconfigure::~MonitorReconfigure() {
58 }
59
60 bool MonitorReconfigure::Init() {
61 DCHECK(delegate_ == NULL);
62 delegate_ = new MonitorReconfigureDelegate(this);
63 controller_ = new UdevController(delegate_, "drm");
64 return controller_->Init();
65 }
66
67 void MonitorReconfigure::Run() {
68 lcd_output_ = 0;
69 lcd_output_info_ = NULL;
70 external_output_ = 0;
71 external_output_info_ = NULL;
72 display_ = XOpenDisplay(NULL);
73 CHECK(display_) << "Could not open display";
74
75 window_ = RootWindow(display_, DefaultScreen(display_));
76 screen_info_ = XRRGetScreenResources(display_, window_);
77
78 for (int i = 0; i < screen_info_->nmode; ++i) {
79 XRRModeInfo* current_mode = &screen_info_->modes[i];
80 mode_map_[current_mode->id] = current_mode;
81 }
82 DetermineOutputs();
83 vector<ResolutionSelector::Mode> lcd_modes;
84 SortModesByResolution(lcd_output_, &lcd_modes);
85 DCHECK(!lcd_modes.empty());
86
87 vector<ResolutionSelector::Mode> external_modes;
88 if (IsExternalMonitorConnected()) {
89 SortModesByResolution(external_output_, &external_modes);
90 DCHECK(!external_modes.empty());
91 }
92
93 ResolutionSelector selector;
94 ResolutionSelector::Mode lcd_resolution;
95 ResolutionSelector::Mode external_resolution;
96 ResolutionSelector::Mode screen_resolution;
97
98 CHECK(selector.FindBestResolutions(lcd_modes,
99 external_modes,
100 &lcd_resolution,
101 &external_resolution,
102 &screen_resolution));
103 CHECK(!lcd_resolution.name.empty() || !external_resolution.name.empty());
104
105 // Disable the backlight before resizing anything on the screen.
106 if (lcd_resolution.name.empty())
107 backlight_ctl_->SetPowerState(BACKLIGHT_ACTIVE_OFF);
108
109 // Grab the server during mode changes.
110 XGrabServer(display_);
111
112 // Disable the LCD if we were told to do so (because we're using a higher
113 // resolution that'd be clipped on the LCD).
114 // Otherwise enable the LCD if appropriate.
115 if (lcd_resolution.name.empty())
116 DisableDevice(lcd_output_info_);
117 else
118 SetDeviceResolution(lcd_output_, lcd_output_info_, lcd_resolution);
119
120 // If there's no external output connected, disable the device before we try
121 // to set the screen resolution; otherwise xrandr will complain if we're
122 // trying to set the screen to a smaller size than what the now-unplugged
123 // device was using.
124 // Otherwise enable the external device if appropriate.
125 if (external_resolution.name.empty())
126 DisableDevice(external_output_info_);
127 else
128 SetDeviceResolution(external_output_, external_output_info_,
129 external_resolution);
130
131 // Set the fb resolution.
132 SetScreenResolution(screen_resolution);
133
134 // Now let the server go and sync all changes.
135 XUngrabServer(display_);
136 XSync(display_, False);
137
138 XRRFreeOutputInfo(lcd_output_info_);
139 XRRFreeOutputInfo(external_output_info_);
140 XRRFreeScreenResources(screen_info_);
141
142 // Enable the backlight. We do not want to do this before the resize is
143 // done so that we can hide the resize when going off->on.
144 if (!lcd_resolution.name.empty())
145 backlight_ctl_->SetPowerState(BACKLIGHT_ACTIVE_ON);
146
147 XCloseDisplay(display_);
148 }
149
150 void MonitorReconfigure::DetermineOutputs() {
151 CHECK(screen_info_->noutput > 1) << "Expected at least two outputs";
152 CHECK(!lcd_output_info_);
153 CHECK(!external_output_info_);
154
155 RROutput first_output = screen_info_->outputs[0];
156 RROutput second_output = screen_info_->outputs[1];
157
158 XRROutputInfo* first_output_info =
159 XRRGetOutputInfo(display_, screen_info_, first_output);
160 XRROutputInfo* second_output_info =
161 XRRGetOutputInfo(display_, screen_info_, second_output);
162
163 if (strcmp(first_output_info->name, kLcdOutputName) == 0) {
164 lcd_output_ = first_output;
165 lcd_output_info_ = first_output_info;
166 external_output_ = second_output;
167 external_output_info_ = second_output_info;
168 } else {
169 lcd_output_ = second_output;
170 lcd_output_info_ = second_output_info;
171 external_output_ = first_output;
172 external_output_info_ = first_output_info;
173 }
174
175 LOG(INFO) << "LCD name: " << lcd_output_info_->name << " (xid "
176 << lcd_output_ << ")";
177 for (int i = 0; i < lcd_output_info_->nmode; ++i) {
178 XRRModeInfo* mode = mode_map_[lcd_output_info_->modes[i]];
179 LOG(INFO) << " Mode: " << mode->width << "x" << mode->height
180 << " (xid " << mode->id << ")";
181 }
182
183 LOG(INFO) << "External name: " << external_output_info_->name
184 << " (xid " << external_output_ << ")";
185 for (int i = 0; i < external_output_info_->nmode; ++i) {
186 XRRModeInfo* mode = mode_map_[external_output_info_->modes[i]];
187 LOG(INFO) << " Mode: " << mode->width << "x" << mode->height
188 << " (xid " << mode->id << ")";
189 }
190 }
191
192 bool MonitorReconfigure::IsExternalMonitorConnected() {
193 return (external_output_info_->connection == RR_Connected);
194 }
195
196 void MonitorReconfigure::SortModesByResolution(
197 RROutput output,
198 vector<ResolutionSelector::Mode>* modes_out) {
199 modes_out->clear();
200
201 XRROutputInfo* output_info = XRRGetOutputInfo(display_, screen_info_, output);
202 for (int i = 0; i < output_info->nmode; ++i) {
203 const XRRModeInfo* mode = mode_map_[output_info->modes[i]];
204 DCHECK(mode);
205 LOG(INFO) << "Adding mode " << mode->width << " " << mode->height
206 << " (xid " << mode->id << ")";
207 modes_out->push_back(
208 ResolutionSelector::Mode(mode->width, mode->height, mode->name,
209 mode->id));
210 }
211
212 sort(modes_out->begin(), modes_out->end(),
213 ResolutionSelector::ModeResolutionComparator());
214
215 XRRFreeOutputInfo(output_info);
216 }
217
218 bool MonitorReconfigure::SetDeviceResolution(
219 RROutput output,
220 const XRROutputInfo* output_info,
221 const ResolutionSelector::Mode& resolution) {
222 Status s = XRRSetCrtcConfig(display_, screen_info_, output_info->crtcs[0],
223 CurrentTime, 0, 0, resolution.id, RR_Rotate_0,
224 &output, 1);
225 return (s == RRSetConfigSuccess);
226 }
227
228 bool MonitorReconfigure::SetScreenResolution(
229 const ResolutionSelector::Mode& resolution) {
230 LOG(INFO) << "Setting resolution " << resolution.name.c_str() << " "
231 << resolution.width << "x" << resolution.height;
232 // Do not switch resolutions if we don't need to, this avoids blinking.
233 int screen = DefaultScreen(display_);
234 if ( (resolution.width != DisplayWidth(display_, screen))||
235 (resolution.height != DisplayHeight(display_, screen)) )
236 XRRSetScreenSize(display_, window_,
237 resolution.width,
238 resolution.height,
239 resolution.width * kInchInMm / kScreenDpi,
240 resolution.height * kInchInMm / kScreenDpi);
241
242 return true;
243 }
244
245 bool MonitorReconfigure::DisableDevice(const XRROutputInfo* output_info) {
246 if (!output_info->crtc)
247 return true;
248 LOG(INFO) << "Disabling output " << output_info->name;
249 Status s = XRRSetCrtcConfig(display_, screen_info_, output_info->crtc,
250 CurrentTime, 0, 0, None, RR_Rotate_0, NULL, 0);
251 return (s == RRSetConfigSuccess);
252 }
253
254 } // namespace power_manager
OLDNEW
« no previous file with comments | « monitor_reconfigure.h ('k') | powerd.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698