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

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: Round 6. Also did I forget mock_monitor_reconfigure.h before? 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
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 // TODO(marcheu): here set the gamma ramp.
119 SetDeviceResolution(lcd_output_, lcd_output_info_, lcd_resolution);
120
121 // If there's no external output connected, disable the device before we try
122 // to set the screen resolution; otherwise xrandr will complain if we're
123 // trying to set the screen to a smaller size than what the now-unplugged
124 // device was using.
125 // Otherwise enable the external device if appropriate.
126 if (external_resolution.name.empty())
127 DisableDevice(external_output_info_);
128 else
129 SetDeviceResolution(external_output_, external_output_info_,
130 external_resolution);
131
132 // Set the fb resolution.
133 SetScreenResolution(screen_resolution);
134
135 // Now let the server go and sync all changes.
136 XUngrabServer(display_);
137 XSync(display_, False);
138
139 XRRFreeOutputInfo(lcd_output_info_);
140 XRRFreeOutputInfo(external_output_info_);
141 XRRFreeScreenResources(screen_info_);
142
143 // Enable the backlight. We do not want to do this before the resize is
144 // done so that we can hide the resize when going off->on.
145 if (!lcd_resolution.name.empty())
146 backlight_ctl_->SetPowerState(BACKLIGHT_ACTIVE_ON);
147
148 XCloseDisplay(display_);
149 }
150
151 void MonitorReconfigure::DetermineOutputs() {
152 CHECK(screen_info_->noutput > 1) << "Expected at least two outputs";
153 CHECK(!lcd_output_info_);
154 CHECK(!external_output_info_);
155
156 RROutput first_output = screen_info_->outputs[0];
157 RROutput second_output = screen_info_->outputs[1];
158
159 XRROutputInfo* first_output_info =
160 XRRGetOutputInfo(display_, screen_info_, first_output);
161 XRROutputInfo* second_output_info =
162 XRRGetOutputInfo(display_, screen_info_, second_output);
163
164 if (strcmp(first_output_info->name, kLcdOutputName) == 0) {
165 lcd_output_ = first_output;
166 lcd_output_info_ = first_output_info;
167 external_output_ = second_output;
168 external_output_info_ = second_output_info;
169 } else {
170 lcd_output_ = second_output;
171 lcd_output_info_ = second_output_info;
172 external_output_ = first_output;
173 external_output_info_ = first_output_info;
174 }
175
176 LOG(INFO) << "LCD name: " << lcd_output_info_->name << " (xid "
177 << lcd_output_ << ")";
178 for (int i = 0; i < lcd_output_info_->nmode; ++i) {
179 XRRModeInfo* mode = mode_map_[lcd_output_info_->modes[i]];
180 LOG(INFO) << " Mode: " << mode->width << "x" << mode->height
181 << " (xid " << mode->id << ")";
182 }
183
184 LOG(INFO) << "External name: " << external_output_info_->name
185 << " (xid " << external_output_ << ")";
186 for (int i = 0; i < external_output_info_->nmode; ++i) {
187 XRRModeInfo* mode = mode_map_[external_output_info_->modes[i]];
188 LOG(INFO) << " Mode: " << mode->width << "x" << mode->height
189 << " (xid " << mode->id << ")";
190 }
191 }
192
193 bool MonitorReconfigure::IsExternalMonitorConnected() {
194 return (external_output_info_->connection == RR_Connected);
195 }
196
197 void MonitorReconfigure::SortModesByResolution(
198 RROutput output,
199 vector<ResolutionSelector::Mode>* modes_out) {
200 modes_out->clear();
201
202 XRROutputInfo* output_info = XRRGetOutputInfo(display_, screen_info_, output);
203 for (int i = 0; i < output_info->nmode; ++i) {
204 const XRRModeInfo* mode = mode_map_[output_info->modes[i]];
205 DCHECK(mode);
206 LOG(INFO) << "Adding mode " << mode->width << " " << mode->height
207 << " (xid " << mode->id << ")";
208 modes_out->push_back(
209 ResolutionSelector::Mode(mode->width, mode->height, mode->name,
210 mode->id));
211 }
212
213 sort(modes_out->begin(), modes_out->end(),
214 ResolutionSelector::ModeResolutionComparator());
215
216 XRRFreeOutputInfo(output_info);
217 }
218
219 bool MonitorReconfigure::SetDeviceResolution(
220 RROutput output,
221 const XRROutputInfo* output_info,
222 const ResolutionSelector::Mode& resolution) {
223 Status s = XRRSetCrtcConfig(display_, screen_info_, output_info->crtcs[0],
224 CurrentTime, 0, 0, resolution.id, RR_Rotate_0,
225 &output, 1);
226 return (s == RRSetConfigSuccess);
227 }
228
229 bool MonitorReconfigure::SetScreenResolution(
230 const ResolutionSelector::Mode& resolution) {
231 LOG(INFO) << "Setting resolution " << resolution.name.c_str() << " "
232 << resolution.width << "x" << resolution.height;
233 // Do not switch resolutions if we don't need to, this avoids blinking.
234 int screen = DefaultScreen(display_);
235 if ( (resolution.width != DisplayWidth(display_, screen))||
236 (resolution.height != DisplayHeight(display_, screen)) )
237 XRRSetScreenSize(display_, window_,
238 resolution.width,
239 resolution.height,
240 resolution.width * kInchInMm / kScreenDpi,
241 resolution.height * kInchInMm / kScreenDpi);
242
243 return true;
244 }
245
246 bool MonitorReconfigure::DisableDevice(const XRROutputInfo* output_info) {
247 if (!output_info->crtc)
248 return true;
249 LOG(INFO) << "Disabling output " << output_info->name;
250 Status s = XRRSetCrtcConfig(display_, screen_info_, output_info->crtc,
251 CurrentTime, 0, 0, None, RR_Rotate_0, NULL, 0);
252 return (s == RRSetConfigSuccess);
253 }
254
255 } // namespace power_manager
OLDNEW
« no previous file with comments | « monitor_reconfigure.h ('k') | powerd.h » ('j') | resolution_selector.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698