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

Side by Side Diff: ui/display/chromeos/output_configurator.cc

Issue 192483007: Move chromeos/display/* to ui/display/chromeos (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Include display.gyp into ChromeOS builds only Created 6 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chromeos/display/output_configurator.h" 5 #include "ui/display/chromeos/output_configurator.h"
6 6
7 #include <X11/Xlib.h> 7 #include <X11/Xlib.h>
8 #include <X11/extensions/Xrandr.h> 8 #include <X11/extensions/Xrandr.h>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/strings/string_number_conversions.h" 12 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/stringprintf.h" 13 #include "base/strings/stringprintf.h"
14 #include "base/sys_info.h" 14 #include "base/sys_info.h"
15 #include "base/time/time.h" 15 #include "base/time/time.h"
16 #include "chromeos/display/native_display_delegate_x11.h" 16 #include "ui/display/chromeos/x11/display_util.h"
17 #include "chromeos/display/output_util.h" 17 #include "ui/display/chromeos/x11/native_display_delegate_x11.h"
18 #include "chromeos/display/touchscreen_delegate_x11.h" 18 #include "ui/display/chromeos/x11/touchscreen_delegate_x11.h"
19 19
20 namespace chromeos { 20 namespace ui {
21 21
22 namespace { 22 namespace {
23 23
24 // The delay to perform configuration after RRNotify. See the comment 24 // The delay to perform configuration after RRNotify. See the comment
25 // in |Dispatch()|. 25 // in |Dispatch()|.
26 const int64 kConfigureDelayMs = 500; 26 const int64 kConfigureDelayMs = 500;
27 27
28 // Returns a string describing |state|. 28 // Returns a string describing |state|.
29 std::string DisplayPowerStateToString(DisplayPowerState state) { 29 std::string DisplayPowerStateToString(chromeos::DisplayPowerState state) {
30 switch (state) { 30 switch (state) {
31 case DISPLAY_POWER_ALL_ON: 31 case chromeos::DISPLAY_POWER_ALL_ON:
32 return "ALL_ON"; 32 return "ALL_ON";
33 case DISPLAY_POWER_ALL_OFF: 33 case chromeos::DISPLAY_POWER_ALL_OFF:
34 return "ALL_OFF"; 34 return "ALL_OFF";
35 case DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON: 35 case chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON:
36 return "INTERNAL_OFF_EXTERNAL_ON"; 36 return "INTERNAL_OFF_EXTERNAL_ON";
37 case DISPLAY_POWER_INTERNAL_ON_EXTERNAL_OFF: 37 case chromeos::DISPLAY_POWER_INTERNAL_ON_EXTERNAL_OFF:
38 return "INTERNAL_ON_EXTERNAL_OFF"; 38 return "INTERNAL_ON_EXTERNAL_OFF";
39 default: 39 default:
40 return "unknown (" + base::IntToString(state) + ")"; 40 return "unknown (" + base::IntToString(state) + ")";
41 } 41 }
42 } 42 }
43 43
44 // Returns a string describing |state|. 44 // Returns a string describing |state|.
45 std::string OutputStateToString(ui::OutputState state) { 45 std::string OutputStateToString(OutputState state) {
46 switch (state) { 46 switch (state) {
47 case ui::OUTPUT_STATE_INVALID: 47 case OUTPUT_STATE_INVALID:
48 return "INVALID"; 48 return "INVALID";
49 case ui::OUTPUT_STATE_HEADLESS: 49 case OUTPUT_STATE_HEADLESS:
50 return "HEADLESS"; 50 return "HEADLESS";
51 case ui::OUTPUT_STATE_SINGLE: 51 case OUTPUT_STATE_SINGLE:
52 return "SINGLE"; 52 return "SINGLE";
53 case ui::OUTPUT_STATE_DUAL_MIRROR: 53 case OUTPUT_STATE_DUAL_MIRROR:
54 return "DUAL_MIRROR"; 54 return "DUAL_MIRROR";
55 case ui::OUTPUT_STATE_DUAL_EXTENDED: 55 case OUTPUT_STATE_DUAL_EXTENDED:
56 return "DUAL_EXTENDED"; 56 return "DUAL_EXTENDED";
57 } 57 }
58 NOTREACHED() << "Unknown state " << state; 58 NOTREACHED() << "Unknown state " << state;
59 return "INVALID"; 59 return "INVALID";
60 } 60 }
61 61
62 // Returns a string representation of OutputSnapshot. 62 // Returns a string representation of OutputSnapshot.
63 std::string OutputSnapshotToString( 63 std::string OutputSnapshotToString(
64 const OutputConfigurator::OutputSnapshot* output) { 64 const OutputConfigurator::OutputSnapshot* output) {
65 return base::StringPrintf( 65 return base::StringPrintf(
66 "[type=%d, output=%ld, crtc=%ld, mode=%ld, dim=%dx%d]", 66 "[type=%d, output=%ld, crtc=%ld, mode=%ld, dim=%dx%d]",
67 output->type, 67 output->type,
68 output->output, 68 output->output,
69 output->crtc, 69 output->crtc,
70 output->current_mode, 70 output->current_mode,
71 static_cast<int>(output->width_mm), 71 static_cast<int>(output->width_mm),
72 static_cast<int>(output->height_mm)); 72 static_cast<int>(output->height_mm));
73 } 73 }
74 74
75 // Returns a string representation of ModeInfo. 75 // Returns a string representation of ModeInfo.
76 std::string ModeInfoToString(const OutputConfigurator::ModeInfo* mode) { 76 std::string ModeInfoToString(const OutputConfigurator::ModeInfo* mode) {
77 return base::StringPrintf("[%dx%d %srate=%f]", 77 return base::StringPrintf("[%dx%d %srate=%f]",
78 mode->width, 78 mode->width,
79 mode->height, 79 mode->height,
80 mode->interlaced ? "interlaced " : "", 80 mode->interlaced ? "interlaced " : "",
81 mode->refresh_rate); 81 mode->refresh_rate);
82
83 } 82 }
84 83
85 // Returns the number of outputs in |outputs| that should be turned on, per 84 // Returns the number of outputs in |outputs| that should be turned on, per
86 // |state|. If |output_power| is non-NULL, it is updated to contain the 85 // |state|. If |output_power| is non-NULL, it is updated to contain the
87 // on/off state of each corresponding entry in |outputs|. 86 // on/off state of each corresponding entry in |outputs|.
88 int GetOutputPower( 87 int GetOutputPower(
89 const std::vector<OutputConfigurator::OutputSnapshot>& outputs, 88 const std::vector<OutputConfigurator::OutputSnapshot>& outputs,
90 DisplayPowerState state, 89 chromeos::DisplayPowerState state,
91 std::vector<bool>* output_power) { 90 std::vector<bool>* output_power) {
92 int num_on_outputs = 0; 91 int num_on_outputs = 0;
93 if (output_power) 92 if (output_power)
94 output_power->resize(outputs.size()); 93 output_power->resize(outputs.size());
95 94
96 for (size_t i = 0; i < outputs.size(); ++i) { 95 for (size_t i = 0; i < outputs.size(); ++i) {
97 bool internal = outputs[i].type == ui::OUTPUT_TYPE_INTERNAL; 96 bool internal = outputs[i].type == OUTPUT_TYPE_INTERNAL;
98 bool on = state == DISPLAY_POWER_ALL_ON || 97 bool on =
99 (state == DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON && !internal) || 98 state == chromeos::DISPLAY_POWER_ALL_ON ||
100 (state == DISPLAY_POWER_INTERNAL_ON_EXTERNAL_OFF && internal); 99 (state == chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON &&
100 !internal) ||
101 (state == chromeos::DISPLAY_POWER_INTERNAL_ON_EXTERNAL_OFF && internal);
101 if (output_power) 102 if (output_power)
102 (*output_power)[i] = on; 103 (*output_power)[i] = on;
103 if (on) 104 if (on)
104 num_on_outputs++; 105 num_on_outputs++;
105 } 106 }
106 return num_on_outputs; 107 return num_on_outputs;
107 } 108 }
108 109
109 } // namespace 110 } // namespace
110 111
(...skipping 23 matching lines...) Expand all
134 crtc(None), 135 crtc(None),
135 current_mode(None), 136 current_mode(None),
136 native_mode(None), 137 native_mode(None),
137 mirror_mode(None), 138 mirror_mode(None),
138 selected_mode(None), 139 selected_mode(None),
139 x(0), 140 x(0),
140 y(0), 141 y(0),
141 width_mm(0), 142 width_mm(0),
142 height_mm(0), 143 height_mm(0),
143 is_aspect_preserving_scaling(false), 144 is_aspect_preserving_scaling(false),
144 type(ui::OUTPUT_TYPE_UNKNOWN), 145 type(OUTPUT_TYPE_UNKNOWN),
145 touch_device_id(0), 146 touch_device_id(0),
146 display_id(0), 147 display_id(0),
147 has_display_id(false), 148 has_display_id(false),
148 index(0) {} 149 index(0) {}
149 150
150 OutputConfigurator::OutputSnapshot::~OutputSnapshot() {} 151 OutputConfigurator::OutputSnapshot::~OutputSnapshot() {}
151 152
152 bool OutputConfigurator::TestApi::TriggerConfigureTimeout() { 153 bool OutputConfigurator::TestApi::TriggerConfigureTimeout() {
153 if (configurator_->configure_timer_.get() && 154 if (configurator_->configure_timer_.get() &&
154 configurator_->configure_timer_->IsRunning()) { 155 configurator_->configure_timer_->IsRunning()) {
155 configurator_->configure_timer_.reset(); 156 configurator_->configure_timer_.reset();
156 configurator_->ConfigureOutputs(); 157 configurator_->ConfigureOutputs();
157 return true; 158 return true;
158 } else { 159 } else {
159 return false; 160 return false;
160 } 161 }
161 } 162 }
162 163
163 // static 164 // static
164 const OutputConfigurator::ModeInfo* OutputConfigurator::GetModeInfo( 165 const OutputConfigurator::ModeInfo* OutputConfigurator::GetModeInfo(
165 const OutputSnapshot& output, 166 const OutputSnapshot& output,
166 RRMode mode) { 167 RRMode mode) {
167 if (mode == None) 168 if (mode == None)
168 return NULL; 169 return NULL;
169 170
170 ModeInfoMap::const_iterator it = output.mode_infos.find(mode); 171 ModeInfoMap::const_iterator it = output.mode_infos.find(mode);
171 if (it == output.mode_infos.end()) { 172 if (it == output.mode_infos.end()) {
172 LOG(WARNING) << "Unable to find info about mode " << mode 173 LOG(WARNING) << "Unable to find info about mode " << mode << " for output "
173 << " for output " << output.output; 174 << output.output;
174 return NULL; 175 return NULL;
175 } 176 }
176 return &it->second; 177 return &it->second;
177 } 178 }
178 179
179 // static 180 // static
180 RRMode OutputConfigurator::FindOutputModeMatchingSize( 181 RRMode OutputConfigurator::FindOutputModeMatchingSize(
181 const OutputSnapshot& output, 182 const OutputSnapshot& output,
182 int width, 183 int width,
183 int height) { 184 int height) {
184 RRMode found = None; 185 RRMode found = None;
185 float best_rate = 0; 186 float best_rate = 0;
186 bool non_interlaced_found = false; 187 bool non_interlaced_found = false;
187 for (ModeInfoMap::const_iterator it = output.mode_infos.begin(); 188 for (ModeInfoMap::const_iterator it = output.mode_infos.begin();
188 it != output.mode_infos.end(); ++it) { 189 it != output.mode_infos.end();
190 ++it) {
189 RRMode mode = it->first; 191 RRMode mode = it->first;
190 const ModeInfo& info = it->second; 192 const ModeInfo& info = it->second;
191 193
192 if (info.width == width && info.height == height) { 194 if (info.width == width && info.height == height) {
193 if (info.interlaced) { 195 if (info.interlaced) {
194 if (non_interlaced_found) 196 if (non_interlaced_found)
195 continue; 197 continue;
196 } else { 198 } else {
197 // Reset the best rate if the non interlaced is 199 // Reset the best rate if the non interlaced is
198 // found the first time. 200 // found the first time.
199 if (!non_interlaced_found) 201 if (!non_interlaced_found)
200 best_rate = info.refresh_rate; 202 best_rate = info.refresh_rate;
201 non_interlaced_found = true; 203 non_interlaced_found = true;
202 } 204 }
203 if (info.refresh_rate < best_rate) 205 if (info.refresh_rate < best_rate)
204 continue; 206 continue;
205 207
206 found = mode; 208 found = mode;
207 best_rate = info.refresh_rate; 209 best_rate = info.refresh_rate;
208 } 210 }
209 } 211 }
210 return found; 212 return found;
211 } 213 }
212 214
213 OutputConfigurator::OutputConfigurator() 215 OutputConfigurator::OutputConfigurator()
214 : state_controller_(NULL), 216 : state_controller_(NULL),
215 mirroring_controller_(NULL), 217 mirroring_controller_(NULL),
216 is_panel_fitting_enabled_(false), 218 is_panel_fitting_enabled_(false),
217 configure_display_(base::SysInfo::IsRunningOnChromeOS()), 219 configure_display_(base::SysInfo::IsRunningOnChromeOS()),
218 output_state_(ui::OUTPUT_STATE_INVALID), 220 output_state_(OUTPUT_STATE_INVALID),
219 power_state_(DISPLAY_POWER_ALL_ON), 221 power_state_(chromeos::DISPLAY_POWER_ALL_ON),
220 next_output_protection_client_id_(1) {} 222 next_output_protection_client_id_(1) {}
221 223
222 OutputConfigurator::~OutputConfigurator() { 224 OutputConfigurator::~OutputConfigurator() {
223 if (native_display_delegate_) 225 if (native_display_delegate_)
224 native_display_delegate_->RemoveObserver(this); 226 native_display_delegate_->RemoveObserver(this);
225 } 227 }
226 228
227 void OutputConfigurator::SetNativeDisplayDelegateForTesting( 229 void OutputConfigurator::SetNativeDisplayDelegateForTesting(
228 scoped_ptr<NativeDisplayDelegate> delegate) { 230 scoped_ptr<NativeDisplayDelegate> delegate) {
229 DCHECK(!native_display_delegate_); 231 DCHECK(!native_display_delegate_);
230 232
231 native_display_delegate_ = delegate.Pass(); 233 native_display_delegate_ = delegate.Pass();
232 native_display_delegate_->AddObserver(this); 234 native_display_delegate_->AddObserver(this);
233 configure_display_ = true; 235 configure_display_ = true;
234 } 236 }
235 237
236 void OutputConfigurator::SetTouchscreenDelegateForTesting( 238 void OutputConfigurator::SetTouchscreenDelegateForTesting(
237 scoped_ptr<TouchscreenDelegate> delegate) { 239 scoped_ptr<TouchscreenDelegate> delegate) {
238 DCHECK(!touchscreen_delegate_); 240 DCHECK(!touchscreen_delegate_);
239 241
240 touchscreen_delegate_ = delegate.Pass(); 242 touchscreen_delegate_ = delegate.Pass();
241 } 243 }
242 244
243 void OutputConfigurator::SetInitialDisplayPower(DisplayPowerState power_state) { 245 void OutputConfigurator::SetInitialDisplayPower(
244 DCHECK_EQ(output_state_, ui::OUTPUT_STATE_INVALID); 246 chromeos::DisplayPowerState power_state) {
247 DCHECK_EQ(output_state_, OUTPUT_STATE_INVALID);
245 power_state_ = power_state; 248 power_state_ = power_state;
246 } 249 }
247 250
248 void OutputConfigurator::Init(bool is_panel_fitting_enabled) { 251 void OutputConfigurator::Init(bool is_panel_fitting_enabled) {
249 is_panel_fitting_enabled_ = is_panel_fitting_enabled; 252 is_panel_fitting_enabled_ = is_panel_fitting_enabled;
250 if (!configure_display_) 253 if (!configure_display_)
251 return; 254 return;
252 255
253 if (!native_display_delegate_) { 256 if (!native_display_delegate_) {
254 native_display_delegate_.reset(new NativeDisplayDelegateX11()); 257 native_display_delegate_.reset(new NativeDisplayDelegateX11());
255 native_display_delegate_->AddObserver(this); 258 native_display_delegate_->AddObserver(this);
256 } 259 }
257 260
258 if (!touchscreen_delegate_) 261 if (!touchscreen_delegate_)
259 touchscreen_delegate_.reset(new TouchscreenDelegateX11()); 262 touchscreen_delegate_.reset(new TouchscreenDelegateX11());
260 } 263 }
261 264
262 void OutputConfigurator::ForceInitialConfigure(uint32 background_color_argb) { 265 void OutputConfigurator::ForceInitialConfigure(uint32 background_color_argb) {
263 if (!configure_display_) 266 if (!configure_display_)
264 return; 267 return;
265 268
266 native_display_delegate_->GrabServer(); 269 native_display_delegate_->GrabServer();
267 native_display_delegate_->Initialize(); 270 native_display_delegate_->Initialize();
268 271
269 UpdateCachedOutputs(); 272 UpdateCachedOutputs();
270 if (cached_outputs_.size() > 1 && background_color_argb) 273 if (cached_outputs_.size() > 1 && background_color_argb)
271 native_display_delegate_->SetBackgroundColor(background_color_argb); 274 native_display_delegate_->SetBackgroundColor(background_color_argb);
272 const ui::OutputState new_state = ChooseOutputState(power_state_); 275 const OutputState new_state = ChooseOutputState(power_state_);
273 const bool success = EnterStateOrFallBackToSoftwareMirroring( 276 const bool success =
274 new_state, power_state_); 277 EnterStateOrFallBackToSoftwareMirroring(new_state, power_state_);
275 278
276 // Force the DPMS on chrome startup as the driver doesn't always detect 279 // Force the DPMS on chrome startup as the driver doesn't always detect
277 // that all displays are on when signing out. 280 // that all displays are on when signing out.
278 native_display_delegate_->ForceDPMSOn(); 281 native_display_delegate_->ForceDPMSOn();
279 native_display_delegate_->UngrabServer(); 282 native_display_delegate_->UngrabServer();
280 NotifyObservers(success, new_state); 283 NotifyObservers(success, new_state);
281 } 284 }
282 285
283 bool OutputConfigurator::ApplyProtections(const DisplayProtections& requests) { 286 bool OutputConfigurator::ApplyProtections(const DisplayProtections& requests) {
284 for (std::vector<OutputSnapshot>::const_iterator it = cached_outputs_.begin(); 287 for (std::vector<OutputSnapshot>::const_iterator it = cached_outputs_.begin();
285 it != cached_outputs_.end(); ++it) { 288 it != cached_outputs_.end();
289 ++it) {
286 uint32_t all_desired = 0; 290 uint32_t all_desired = 0;
287 DisplayProtections::const_iterator request_it = requests.find( 291 DisplayProtections::const_iterator request_it =
288 it->display_id); 292 requests.find(it->display_id);
289 if (request_it != requests.end()) 293 if (request_it != requests.end())
290 all_desired = request_it->second; 294 all_desired = request_it->second;
291 switch (it->type) { 295 switch (it->type) {
292 case ui::OUTPUT_TYPE_UNKNOWN: 296 case OUTPUT_TYPE_UNKNOWN:
293 return false; 297 return false;
294 // DisplayPort, DVI, and HDMI all support HDCP. 298 // DisplayPort, DVI, and HDMI all support HDCP.
295 case ui::OUTPUT_TYPE_DISPLAYPORT: 299 case OUTPUT_TYPE_DISPLAYPORT:
296 case ui::OUTPUT_TYPE_DVI: 300 case OUTPUT_TYPE_DVI:
297 case ui::OUTPUT_TYPE_HDMI: { 301 case OUTPUT_TYPE_HDMI: {
298 ui::HDCPState new_desired_state = 302 HDCPState new_desired_state =
299 (all_desired & ui::OUTPUT_PROTECTION_METHOD_HDCP) 303 (all_desired & OUTPUT_PROTECTION_METHOD_HDCP) ?
300 ? ui::HDCP_STATE_DESIRED 304 HDCP_STATE_DESIRED : HDCP_STATE_UNDESIRED;
301 : ui::HDCP_STATE_UNDESIRED;
302 if (!native_display_delegate_->SetHDCPState(*it, new_desired_state)) 305 if (!native_display_delegate_->SetHDCPState(*it, new_desired_state))
303 return false; 306 return false;
304 break; 307 break;
305 } 308 }
306 case ui::OUTPUT_TYPE_INTERNAL: 309 case OUTPUT_TYPE_INTERNAL:
307 case ui::OUTPUT_TYPE_VGA: 310 case OUTPUT_TYPE_VGA:
308 case ui::OUTPUT_TYPE_NETWORK: 311 case OUTPUT_TYPE_NETWORK:
309 // No protections for these types. Do nothing. 312 // No protections for these types. Do nothing.
310 break; 313 break;
311 case ui::OUTPUT_TYPE_NONE: 314 case OUTPUT_TYPE_NONE:
312 NOTREACHED(); 315 NOTREACHED();
313 break; 316 break;
314 } 317 }
315 } 318 }
316 319
317 return true; 320 return true;
318 } 321 }
319 322
320 OutputConfigurator::OutputProtectionClientId 323 OutputConfigurator::OutputProtectionClientId
321 OutputConfigurator::RegisterOutputProtectionClient() { 324 OutputConfigurator::RegisterOutputProtectionClient() {
322 if (!configure_display_) 325 if (!configure_display_)
323 return kInvalidClientId; 326 return kInvalidClientId;
324 327
325 return next_output_protection_client_id_++; 328 return next_output_protection_client_id_++;
326 } 329 }
327 330
328 void OutputConfigurator::UnregisterOutputProtectionClient( 331 void OutputConfigurator::UnregisterOutputProtectionClient(
329 OutputProtectionClientId client_id) { 332 OutputProtectionClientId client_id) {
330 client_protection_requests_.erase(client_id); 333 client_protection_requests_.erase(client_id);
331 334
332 DisplayProtections protections; 335 DisplayProtections protections;
333 for (ProtectionRequests::const_iterator it = 336 for (ProtectionRequests::const_iterator it =
334 client_protection_requests_.begin(); 337 client_protection_requests_.begin();
335 it != client_protection_requests_.end(); 338 it != client_protection_requests_.end();
336 ++it) { 339 ++it) {
337 for (DisplayProtections::const_iterator it2 = it->second.begin(); 340 for (DisplayProtections::const_iterator it2 = it->second.begin();
338 it2 != it->second.end(); ++it2) { 341 it2 != it->second.end();
342 ++it2) {
339 protections[it2->first] |= it2->second; 343 protections[it2->first] |= it2->second;
340 } 344 }
341 } 345 }
342 346
343 ApplyProtections(protections); 347 ApplyProtections(protections);
344 } 348 }
345 349
346 bool OutputConfigurator::QueryOutputProtectionStatus( 350 bool OutputConfigurator::QueryOutputProtectionStatus(
347 OutputProtectionClientId client_id, 351 OutputProtectionClientId client_id,
348 int64 display_id, 352 int64 display_id,
349 uint32_t* link_mask, 353 uint32_t* link_mask,
350 uint32_t* protection_mask) { 354 uint32_t* protection_mask) {
351 if (!configure_display_) 355 if (!configure_display_)
352 return false; 356 return false;
353 357
354 uint32_t enabled = 0; 358 uint32_t enabled = 0;
355 uint32_t unfulfilled = 0; 359 uint32_t unfulfilled = 0;
356 *link_mask = 0; 360 *link_mask = 0;
357 for (std::vector<OutputSnapshot>::const_iterator it = cached_outputs_.begin(); 361 for (std::vector<OutputSnapshot>::const_iterator it = cached_outputs_.begin();
358 it != cached_outputs_.end(); ++it) { 362 it != cached_outputs_.end();
363 ++it) {
359 if (it->display_id != display_id) 364 if (it->display_id != display_id)
360 continue; 365 continue;
361 *link_mask |= it->type; 366 *link_mask |= it->type;
362 switch (it->type) { 367 switch (it->type) {
363 case ui::OUTPUT_TYPE_UNKNOWN: 368 case OUTPUT_TYPE_UNKNOWN:
364 return false; 369 return false;
365 // DisplayPort, DVI, and HDMI all support HDCP. 370 // DisplayPort, DVI, and HDMI all support HDCP.
366 case ui::OUTPUT_TYPE_DISPLAYPORT: 371 case OUTPUT_TYPE_DISPLAYPORT:
367 case ui::OUTPUT_TYPE_DVI: 372 case OUTPUT_TYPE_DVI:
368 case ui::OUTPUT_TYPE_HDMI: { 373 case OUTPUT_TYPE_HDMI: {
369 ui::HDCPState state; 374 HDCPState state;
370 if (!native_display_delegate_->GetHDCPState(*it, &state)) 375 if (!native_display_delegate_->GetHDCPState(*it, &state))
371 return false; 376 return false;
372 if (state == ui::HDCP_STATE_ENABLED) 377 if (state == HDCP_STATE_ENABLED)
373 enabled |= ui::OUTPUT_PROTECTION_METHOD_HDCP; 378 enabled |= OUTPUT_PROTECTION_METHOD_HDCP;
374 else 379 else
375 unfulfilled |= ui::OUTPUT_PROTECTION_METHOD_HDCP; 380 unfulfilled |= OUTPUT_PROTECTION_METHOD_HDCP;
376 break; 381 break;
377 } 382 }
378 case ui::OUTPUT_TYPE_INTERNAL: 383 case OUTPUT_TYPE_INTERNAL:
379 case ui::OUTPUT_TYPE_VGA: 384 case OUTPUT_TYPE_VGA:
380 case ui::OUTPUT_TYPE_NETWORK: 385 case OUTPUT_TYPE_NETWORK:
381 // No protections for these types. Do nothing. 386 // No protections for these types. Do nothing.
382 break; 387 break;
383 case ui::OUTPUT_TYPE_NONE: 388 case OUTPUT_TYPE_NONE:
384 NOTREACHED(); 389 NOTREACHED();
385 break; 390 break;
386 } 391 }
387 } 392 }
388 393
389 // Don't reveal protections requested by other clients. 394 // Don't reveal protections requested by other clients.
390 ProtectionRequests::iterator it = client_protection_requests_.find(client_id); 395 ProtectionRequests::iterator it = client_protection_requests_.find(client_id);
391 if (it != client_protection_requests_.end()) { 396 if (it != client_protection_requests_.end()) {
392 uint32_t requested_mask = 0; 397 uint32_t requested_mask = 0;
393 if (it->second.find(display_id) != it->second.end()) 398 if (it->second.find(display_id) != it->second.end())
(...skipping 11 matching lines...) Expand all
405 uint32_t desired_method_mask) { 410 uint32_t desired_method_mask) {
406 if (!configure_display_) 411 if (!configure_display_)
407 return false; 412 return false;
408 413
409 DisplayProtections protections; 414 DisplayProtections protections;
410 for (ProtectionRequests::const_iterator it = 415 for (ProtectionRequests::const_iterator it =
411 client_protection_requests_.begin(); 416 client_protection_requests_.begin();
412 it != client_protection_requests_.end(); 417 it != client_protection_requests_.end();
413 ++it) { 418 ++it) {
414 for (DisplayProtections::const_iterator it2 = it->second.begin(); 419 for (DisplayProtections::const_iterator it2 = it->second.begin();
415 it2 != it->second.end(); ++it2) { 420 it2 != it->second.end();
421 ++it2) {
416 if (it->first == client_id && it2->first == display_id) 422 if (it->first == client_id && it2->first == display_id)
417 continue; 423 continue;
418 protections[it2->first] |= it2->second; 424 protections[it2->first] |= it2->second;
419 } 425 }
420 } 426 }
421 protections[display_id] |= desired_method_mask; 427 protections[display_id] |= desired_method_mask;
422 428
423 if (!ApplyProtections(protections)) 429 if (!ApplyProtections(protections))
424 return false; 430 return false;
425 431
426 if (desired_method_mask == ui::OUTPUT_PROTECTION_METHOD_NONE) { 432 if (desired_method_mask == OUTPUT_PROTECTION_METHOD_NONE) {
427 if (client_protection_requests_.find(client_id) != 433 if (client_protection_requests_.find(client_id) !=
428 client_protection_requests_.end()) { 434 client_protection_requests_.end()) {
429 client_protection_requests_[client_id].erase(display_id); 435 client_protection_requests_[client_id].erase(display_id);
430 if (client_protection_requests_[client_id].size() == 0) 436 if (client_protection_requests_[client_id].size() == 0)
431 client_protection_requests_.erase(client_id); 437 client_protection_requests_.erase(client_id);
432 } 438 }
433 } else { 439 } else {
434 client_protection_requests_[client_id][display_id] = desired_method_mask; 440 client_protection_requests_[client_id][display_id] = desired_method_mask;
435 } 441 }
436 442
437 return true; 443 return true;
438 } 444 }
439 445
440 void OutputConfigurator::PrepareForExit() { 446 void OutputConfigurator::PrepareForExit() {
441 configure_display_ = false; 447 configure_display_ = false;
442 } 448 }
443 449
444 bool OutputConfigurator::SetDisplayPower(DisplayPowerState power_state, 450 bool OutputConfigurator::SetDisplayPower(
445 int flags) { 451 chromeos::DisplayPowerState power_state,
452 int flags) {
446 if (!configure_display_) 453 if (!configure_display_)
447 return false; 454 return false;
448 455
449 VLOG(1) << "SetDisplayPower: power_state=" 456 VLOG(1) << "SetDisplayPower: power_state="
450 << DisplayPowerStateToString(power_state) << " flags=" << flags 457 << DisplayPowerStateToString(power_state) << " flags=" << flags
451 << ", configure timer=" 458 << ", configure timer="
452 << ((configure_timer_.get() && configure_timer_->IsRunning()) ? 459 << ((configure_timer_.get() && configure_timer_->IsRunning()) ?
453 "Running" : "Stopped"); 460 "Running" : "Stopped");
454 if (power_state == power_state_ && !(flags & kSetDisplayPowerForceProbe)) 461 if (power_state == power_state_ && !(flags & kSetDisplayPowerForceProbe))
455 return true; 462 return true;
456 463
457 native_display_delegate_->GrabServer(); 464 native_display_delegate_->GrabServer();
458 UpdateCachedOutputs(); 465 UpdateCachedOutputs();
459 466
460 const ui::OutputState new_state = ChooseOutputState(power_state); 467 const OutputState new_state = ChooseOutputState(power_state);
461 bool attempted_change = false; 468 bool attempted_change = false;
462 bool success = false; 469 bool success = false;
463 470
464 bool only_if_single_internal_display = 471 bool only_if_single_internal_display =
465 flags & kSetDisplayPowerOnlyIfSingleInternalDisplay; 472 flags & kSetDisplayPowerOnlyIfSingleInternalDisplay;
466 bool single_internal_display = 473 bool single_internal_display =
467 cached_outputs_.size() == 1 && 474 cached_outputs_.size() == 1 &&
468 cached_outputs_[0].type == ui::OUTPUT_TYPE_INTERNAL; 475 cached_outputs_[0].type == OUTPUT_TYPE_INTERNAL;
469 if (single_internal_display || !only_if_single_internal_display) { 476 if (single_internal_display || !only_if_single_internal_display) {
470 success = EnterStateOrFallBackToSoftwareMirroring(new_state, power_state); 477 success = EnterStateOrFallBackToSoftwareMirroring(new_state, power_state);
471 attempted_change = true; 478 attempted_change = true;
472 479
473 // Force the DPMS on since the driver doesn't always detect that it 480 // Force the DPMS on since the driver doesn't always detect that it
474 // should turn on. This is needed when coming back from idle suspend. 481 // should turn on. This is needed when coming back from idle suspend.
475 if (success && power_state != DISPLAY_POWER_ALL_OFF) 482 if (success && power_state != chromeos::DISPLAY_POWER_ALL_OFF)
476 native_display_delegate_->ForceDPMSOn(); 483 native_display_delegate_->ForceDPMSOn();
477 } 484 }
478 485
479 native_display_delegate_->UngrabServer(); 486 native_display_delegate_->UngrabServer();
480 if (attempted_change) 487 if (attempted_change)
481 NotifyObservers(success, new_state); 488 NotifyObservers(success, new_state);
482 return true; 489 return true;
483 } 490 }
484 491
485 bool OutputConfigurator::SetDisplayMode(ui::OutputState new_state) { 492 bool OutputConfigurator::SetDisplayMode(OutputState new_state) {
486 if (!configure_display_) 493 if (!configure_display_)
487 return false; 494 return false;
488 495
489 VLOG(1) << "SetDisplayMode: state=" << OutputStateToString(new_state); 496 VLOG(1) << "SetDisplayMode: state=" << OutputStateToString(new_state);
490 if (output_state_ == new_state) { 497 if (output_state_ == new_state) {
491 // Cancel software mirroring if the state is moving from 498 // Cancel software mirroring if the state is moving from
492 // OUTPUT_STATE_DUAL_EXTENDED to OUTPUT_STATE_DUAL_EXTENDED. 499 // OUTPUT_STATE_DUAL_EXTENDED to OUTPUT_STATE_DUAL_EXTENDED.
493 if (mirroring_controller_ && new_state == ui::OUTPUT_STATE_DUAL_EXTENDED) 500 if (mirroring_controller_ && new_state == OUTPUT_STATE_DUAL_EXTENDED)
494 mirroring_controller_->SetSoftwareMirroring(false); 501 mirroring_controller_->SetSoftwareMirroring(false);
495 NotifyObservers(true, new_state); 502 NotifyObservers(true, new_state);
496 return true; 503 return true;
497 } 504 }
498 505
499 native_display_delegate_->GrabServer(); 506 native_display_delegate_->GrabServer();
500 UpdateCachedOutputs(); 507 UpdateCachedOutputs();
501 const bool success = EnterStateOrFallBackToSoftwareMirroring( 508 const bool success =
502 new_state, power_state_); 509 EnterStateOrFallBackToSoftwareMirroring(new_state, power_state_);
503 native_display_delegate_->UngrabServer(); 510 native_display_delegate_->UngrabServer();
504 511
505 NotifyObservers(success, new_state); 512 NotifyObservers(success, new_state);
506 return success; 513 return success;
507 } 514 }
508 515
509 void OutputConfigurator::OnConfigurationChanged() { 516 void OutputConfigurator::OnConfigurationChanged() {
510 // Configure outputs with |kConfigureDelayMs| delay, 517 // Configure outputs with |kConfigureDelayMs| delay,
511 // so that time-consuming ConfigureOutputs() won't be called multiple times. 518 // so that time-consuming ConfigureOutputs() won't be called multiple times.
512 if (configure_timer_.get()) { 519 if (configure_timer_.get()) {
(...skipping 15 matching lines...) Expand all
528 void OutputConfigurator::RemoveObserver(Observer* observer) { 535 void OutputConfigurator::RemoveObserver(Observer* observer) {
529 observers_.RemoveObserver(observer); 536 observers_.RemoveObserver(observer);
530 } 537 }
531 538
532 void OutputConfigurator::SuspendDisplays() { 539 void OutputConfigurator::SuspendDisplays() {
533 // If the display is off due to user inactivity and there's only a single 540 // If the display is off due to user inactivity and there's only a single
534 // internal display connected, switch to the all-on state before 541 // internal display connected, switch to the all-on state before
535 // suspending. This shouldn't be very noticeable to the user since the 542 // suspending. This shouldn't be very noticeable to the user since the
536 // backlight is off at this point, and doing this lets us resume directly 543 // backlight is off at this point, and doing this lets us resume directly
537 // into the "on" state, which greatly reduces resume times. 544 // into the "on" state, which greatly reduces resume times.
538 if (power_state_ == DISPLAY_POWER_ALL_OFF) { 545 if (power_state_ == chromeos::DISPLAY_POWER_ALL_OFF) {
539 SetDisplayPower(DISPLAY_POWER_ALL_ON, 546 SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON,
540 kSetDisplayPowerOnlyIfSingleInternalDisplay); 547 kSetDisplayPowerOnlyIfSingleInternalDisplay);
541 548
542 // We need to make sure that the monitor configuration we just did actually 549 // We need to make sure that the monitor configuration we just did actually
543 // completes before we return, because otherwise the X message could be 550 // completes before we return, because otherwise the X message could be
544 // racing with the HandleSuspendReadiness message. 551 // racing with the HandleSuspendReadiness message.
545 native_display_delegate_->SyncWithServer(); 552 native_display_delegate_->SyncWithServer();
546 } 553 }
547 } 554 }
548 555
549 void OutputConfigurator::ResumeDisplays() { 556 void OutputConfigurator::ResumeDisplays() {
550 // Force probing to ensure that we pick up any changes that were made 557 // Force probing to ensure that we pick up any changes that were made
551 // while the system was suspended. 558 // while the system was suspended.
552 SetDisplayPower(power_state_, kSetDisplayPowerForceProbe); 559 SetDisplayPower(power_state_, kSetDisplayPowerForceProbe);
553 } 560 }
554 561
555 void OutputConfigurator::UpdateCachedOutputs() { 562 void OutputConfigurator::UpdateCachedOutputs() {
556 cached_outputs_ = native_display_delegate_->GetOutputs(); 563 cached_outputs_ = native_display_delegate_->GetOutputs();
557 touchscreen_delegate_->AssociateTouchscreens(&cached_outputs_); 564 touchscreen_delegate_->AssociateTouchscreens(&cached_outputs_);
558 565
559 // Set |selected_mode| fields. 566 // Set |selected_mode| fields.
560 for (size_t i = 0; i < cached_outputs_.size(); ++i) { 567 for (size_t i = 0; i < cached_outputs_.size(); ++i) {
561 OutputSnapshot* output = &cached_outputs_[i]; 568 OutputSnapshot* output = &cached_outputs_[i];
562 if (output->has_display_id) { 569 if (output->has_display_id) {
563 int width = 0, height = 0; 570 int width = 0, height = 0;
564 if (state_controller_ && 571 if (state_controller_ && state_controller_->GetResolutionForDisplayId(
565 state_controller_->GetResolutionForDisplayId( 572 output->display_id, &width, &height)) {
566 output->display_id, &width, &height)) {
567 output->selected_mode = 573 output->selected_mode =
568 FindOutputModeMatchingSize(*output, width, height); 574 FindOutputModeMatchingSize(*output, width, height);
569 } 575 }
570 } 576 }
571 // Fall back to native mode. 577 // Fall back to native mode.
572 if (output->selected_mode == None) 578 if (output->selected_mode == None)
573 output->selected_mode = output->native_mode; 579 output->selected_mode = output->native_mode;
574 } 580 }
575 581
576 // Set |mirror_mode| fields. 582 // Set |mirror_mode| fields.
577 if (cached_outputs_.size() == 2) { 583 if (cached_outputs_.size() == 2) {
578 bool one_is_internal = cached_outputs_[0].type == ui::OUTPUT_TYPE_INTERNAL; 584 bool one_is_internal = cached_outputs_[0].type == OUTPUT_TYPE_INTERNAL;
579 bool two_is_internal = cached_outputs_[1].type == ui::OUTPUT_TYPE_INTERNAL; 585 bool two_is_internal = cached_outputs_[1].type == OUTPUT_TYPE_INTERNAL;
580 int internal_outputs = (one_is_internal ? 1 : 0) + 586 int internal_outputs =
581 (two_is_internal ? 1 : 0); 587 (one_is_internal ? 1 : 0) + (two_is_internal ? 1 : 0);
582 DCHECK_LT(internal_outputs, 2); 588 DCHECK_LT(internal_outputs, 2);
583 LOG_IF(WARNING, internal_outputs == 2) 589 LOG_IF(WARNING, internal_outputs == 2) << "Two internal outputs detected.";
584 << "Two internal outputs detected.";
585 590
586 bool can_mirror = false; 591 bool can_mirror = false;
587 for (int attempt = 0; !can_mirror && attempt < 2; ++attempt) { 592 for (int attempt = 0; !can_mirror && attempt < 2; ++attempt) {
588 // Try preserving external output's aspect ratio on the first attempt. 593 // Try preserving external output's aspect ratio on the first attempt.
589 // If that fails, fall back to the highest matching resolution. 594 // If that fails, fall back to the highest matching resolution.
590 bool preserve_aspect = attempt == 0; 595 bool preserve_aspect = attempt == 0;
591 596
592 if (internal_outputs == 1) { 597 if (internal_outputs == 1) {
593 if (one_is_internal) { 598 if (one_is_internal) {
594 can_mirror = FindMirrorMode(&cached_outputs_[0], &cached_outputs_[1], 599 can_mirror = FindMirrorMode(&cached_outputs_[0],
595 is_panel_fitting_enabled_, preserve_aspect); 600 &cached_outputs_[1],
601 is_panel_fitting_enabled_,
602 preserve_aspect);
596 } else { 603 } else {
597 DCHECK(two_is_internal); 604 DCHECK(two_is_internal);
598 can_mirror = FindMirrorMode(&cached_outputs_[1], &cached_outputs_[0], 605 can_mirror = FindMirrorMode(&cached_outputs_[1],
599 is_panel_fitting_enabled_, preserve_aspect); 606 &cached_outputs_[0],
607 is_panel_fitting_enabled_,
608 preserve_aspect);
600 } 609 }
601 } else { // if (internal_outputs == 0) 610 } else { // if (internal_outputs == 0)
602 // No panel fitting for external outputs, so fall back to exact match. 611 // No panel fitting for external outputs, so fall back to exact match.
603 can_mirror = FindMirrorMode(&cached_outputs_[0], &cached_outputs_[1], 612 can_mirror = FindMirrorMode(
604 false, preserve_aspect); 613 &cached_outputs_[0], &cached_outputs_[1], false, preserve_aspect);
605 if (!can_mirror && preserve_aspect) { 614 if (!can_mirror && preserve_aspect) {
606 // FindMirrorMode() will try to preserve aspect ratio of what it 615 // FindMirrorMode() will try to preserve aspect ratio of what it
607 // thinks is external display, so if it didn't succeed with one, maybe 616 // thinks is external display, so if it didn't succeed with one, maybe
608 // it will succeed with the other. This way we will have the correct 617 // it will succeed with the other. This way we will have the correct
609 // aspect ratio on at least one of them. 618 // aspect ratio on at least one of them.
610 can_mirror = FindMirrorMode(&cached_outputs_[1], &cached_outputs_[0], 619 can_mirror = FindMirrorMode(
611 false, preserve_aspect); 620 &cached_outputs_[1], &cached_outputs_[0], false, preserve_aspect);
612 } 621 }
613 } 622 }
614 } 623 }
615 } 624 }
616 } 625 }
617 626
618 bool OutputConfigurator::FindMirrorMode(OutputSnapshot* internal_output, 627 bool OutputConfigurator::FindMirrorMode(OutputSnapshot* internal_output,
619 OutputSnapshot* external_output, 628 OutputSnapshot* external_output,
620 bool try_panel_fitting, 629 bool try_panel_fitting,
621 bool preserve_aspect) { 630 bool preserve_aspect) {
622 const ModeInfo* internal_native_info = 631 const ModeInfo* internal_native_info =
623 GetModeInfo(*internal_output, internal_output->native_mode); 632 GetModeInfo(*internal_output, internal_output->native_mode);
624 const ModeInfo* external_native_info = 633 const ModeInfo* external_native_info =
625 GetModeInfo(*external_output, external_output->native_mode); 634 GetModeInfo(*external_output, external_output->native_mode);
626 if (!internal_native_info || !external_native_info) 635 if (!internal_native_info || !external_native_info)
627 return false; 636 return false;
628 637
629 // Check if some external output resolution can be mirrored on internal. 638 // Check if some external output resolution can be mirrored on internal.
630 // Prefer the modes in the order that X sorts them, assuming this is the order 639 // Prefer the modes in the order that X sorts them, assuming this is the order
631 // in which they look better on the monitor. 640 // in which they look better on the monitor.
632 for (ModeInfoMap::const_iterator external_it = 641 for (ModeInfoMap::const_iterator external_it =
633 external_output->mode_infos.begin(); 642 external_output->mode_infos.begin();
634 external_it != external_output->mode_infos.end(); ++external_it) { 643 external_it != external_output->mode_infos.end();
644 ++external_it) {
635 const ModeInfo& external_info = external_it->second; 645 const ModeInfo& external_info = external_it->second;
636 bool is_native_aspect_ratio = 646 bool is_native_aspect_ratio =
637 external_native_info->width * external_info.height == 647 external_native_info->width * external_info.height ==
638 external_native_info->height * external_info.width; 648 external_native_info->height * external_info.width;
639 if (preserve_aspect && !is_native_aspect_ratio) 649 if (preserve_aspect && !is_native_aspect_ratio)
640 continue; // Allow only aspect ratio preserving modes for mirroring. 650 continue; // Allow only aspect ratio preserving modes for mirroring.
641 651
642 // Try finding an exact match. 652 // Try finding an exact match.
643 for (ModeInfoMap::const_iterator internal_it = 653 for (ModeInfoMap::const_iterator internal_it =
644 internal_output->mode_infos.begin(); 654 internal_output->mode_infos.begin();
645 internal_it != internal_output->mode_infos.end(); ++internal_it) { 655 internal_it != internal_output->mode_infos.end();
656 ++internal_it) {
646 const ModeInfo& internal_info = internal_it->second; 657 const ModeInfo& internal_info = internal_it->second;
647 if (internal_info.width == external_info.width && 658 if (internal_info.width == external_info.width &&
648 internal_info.height == external_info.height && 659 internal_info.height == external_info.height &&
649 internal_info.interlaced == external_info.interlaced) { 660 internal_info.interlaced == external_info.interlaced) {
650 internal_output->mirror_mode = internal_it->first; 661 internal_output->mirror_mode = internal_it->first;
651 external_output->mirror_mode = external_it->first; 662 external_output->mirror_mode = external_it->first;
652 return true; // Mirror mode found. 663 return true; // Mirror mode found.
653 } 664 }
654 } 665 }
655 666
656 // Try to create a matching internal output mode by panel fitting. 667 // Try to create a matching internal output mode by panel fitting.
657 if (try_panel_fitting) { 668 if (try_panel_fitting) {
658 // We can downscale by 1.125, and upscale indefinitely. Downscaling looks 669 // We can downscale by 1.125, and upscale indefinitely. Downscaling looks
659 // ugly, so, can fit == can upscale. Also, internal panels don't support 670 // ugly, so, can fit == can upscale. Also, internal panels don't support
660 // fitting interlaced modes. 671 // fitting interlaced modes.
661 bool can_fit = 672 bool can_fit = internal_native_info->width >= external_info.width &&
662 internal_native_info->width >= external_info.width && 673 internal_native_info->height >= external_info.height &&
663 internal_native_info->height >= external_info.height && 674 !external_info.interlaced;
664 !external_info.interlaced;
665 if (can_fit) { 675 if (can_fit) {
666 RRMode mode = external_it->first; 676 RRMode mode = external_it->first;
667 native_display_delegate_->AddMode(*internal_output, mode); 677 native_display_delegate_->AddMode(*internal_output, mode);
668 internal_output->mode_infos.insert(std::make_pair(mode, external_info)); 678 internal_output->mode_infos.insert(std::make_pair(mode, external_info));
669 internal_output->mirror_mode = mode; 679 internal_output->mirror_mode = mode;
670 external_output->mirror_mode = mode; 680 external_output->mirror_mode = mode;
671 return true; // Mirror mode created. 681 return true; // Mirror mode created.
672 } 682 }
673 } 683 }
674 } 684 }
675 685
676 return false; 686 return false;
677 } 687 }
678 688
679 void OutputConfigurator::ConfigureOutputs() { 689 void OutputConfigurator::ConfigureOutputs() {
680 configure_timer_.reset(); 690 configure_timer_.reset();
681 691
682 if (!configure_display_) 692 if (!configure_display_)
683 return; 693 return;
684 694
685 native_display_delegate_->GrabServer(); 695 native_display_delegate_->GrabServer();
686 UpdateCachedOutputs(); 696 UpdateCachedOutputs();
687 const ui::OutputState new_state = ChooseOutputState(power_state_); 697 const OutputState new_state = ChooseOutputState(power_state_);
688 const bool success = EnterStateOrFallBackToSoftwareMirroring( 698 const bool success =
689 new_state, power_state_); 699 EnterStateOrFallBackToSoftwareMirroring(new_state, power_state_);
690 native_display_delegate_->UngrabServer(); 700 native_display_delegate_->UngrabServer();
691 701
692 NotifyObservers(success, new_state); 702 NotifyObservers(success, new_state);
693 } 703 }
694 704
695 void OutputConfigurator::NotifyObservers(bool success, 705 void OutputConfigurator::NotifyObservers(bool success,
696 ui::OutputState attempted_state) { 706 OutputState attempted_state) {
697 if (success) { 707 if (success) {
698 FOR_EACH_OBSERVER(Observer, observers_, 708 FOR_EACH_OBSERVER(
699 OnDisplayModeChanged(cached_outputs_)); 709 Observer, observers_, OnDisplayModeChanged(cached_outputs_));
700 } else { 710 } else {
701 FOR_EACH_OBSERVER(Observer, observers_, 711 FOR_EACH_OBSERVER(
702 OnDisplayModeChangeFailed(attempted_state)); 712 Observer, observers_, OnDisplayModeChangeFailed(attempted_state));
703 } 713 }
704 } 714 }
705 715
706 bool OutputConfigurator::EnterStateOrFallBackToSoftwareMirroring( 716 bool OutputConfigurator::EnterStateOrFallBackToSoftwareMirroring(
707 ui::OutputState output_state, 717 OutputState output_state,
708 DisplayPowerState power_state) { 718 chromeos::DisplayPowerState power_state) {
709 bool success = EnterState(output_state, power_state); 719 bool success = EnterState(output_state, power_state);
710 if (mirroring_controller_) { 720 if (mirroring_controller_) {
711 bool enable_software_mirroring = false; 721 bool enable_software_mirroring = false;
712 if (!success && output_state == ui::OUTPUT_STATE_DUAL_MIRROR) { 722 if (!success && output_state == OUTPUT_STATE_DUAL_MIRROR) {
713 if (output_state_ != ui::OUTPUT_STATE_DUAL_EXTENDED || 723 if (output_state_ != OUTPUT_STATE_DUAL_EXTENDED ||
714 power_state_ != power_state) 724 power_state_ != power_state)
715 EnterState(ui::OUTPUT_STATE_DUAL_EXTENDED, power_state); 725 EnterState(OUTPUT_STATE_DUAL_EXTENDED, power_state);
716 enable_software_mirroring = success = 726 enable_software_mirroring = success =
717 output_state_ == ui::OUTPUT_STATE_DUAL_EXTENDED; 727 output_state_ == OUTPUT_STATE_DUAL_EXTENDED;
718 } 728 }
719 mirroring_controller_->SetSoftwareMirroring(enable_software_mirroring); 729 mirroring_controller_->SetSoftwareMirroring(enable_software_mirroring);
720 } 730 }
721 return success; 731 return success;
722 } 732 }
723 733
724 bool OutputConfigurator::EnterState(ui::OutputState output_state, 734 bool OutputConfigurator::EnterState(OutputState output_state,
725 DisplayPowerState power_state) { 735 chromeos::DisplayPowerState power_state) {
726 std::vector<bool> output_power; 736 std::vector<bool> output_power;
727 int num_on_outputs = GetOutputPower( 737 int num_on_outputs =
728 cached_outputs_, power_state, &output_power); 738 GetOutputPower(cached_outputs_, power_state, &output_power);
729 VLOG(1) << "EnterState: output=" << OutputStateToString(output_state) 739 VLOG(1) << "EnterState: output=" << OutputStateToString(output_state)
730 << " power=" << DisplayPowerStateToString(power_state); 740 << " power=" << DisplayPowerStateToString(power_state);
731 741
732 // Framebuffer dimensions. 742 // Framebuffer dimensions.
733 int width = 0, height = 0; 743 int width = 0, height = 0;
734 std::vector<OutputSnapshot> updated_outputs = cached_outputs_; 744 std::vector<OutputSnapshot> updated_outputs = cached_outputs_;
735 745
736 switch (output_state) { 746 switch (output_state) {
737 case ui::OUTPUT_STATE_INVALID: 747 case OUTPUT_STATE_INVALID:
738 NOTREACHED() << "Ignoring request to enter invalid state with " 748 NOTREACHED() << "Ignoring request to enter invalid state with "
739 << updated_outputs.size() << " connected output(s)"; 749 << updated_outputs.size() << " connected output(s)";
740 return false; 750 return false;
741 case ui::OUTPUT_STATE_HEADLESS: 751 case OUTPUT_STATE_HEADLESS:
742 if (updated_outputs.size() != 0) { 752 if (updated_outputs.size() != 0) {
743 LOG(WARNING) << "Ignoring request to enter headless mode with " 753 LOG(WARNING) << "Ignoring request to enter headless mode with "
744 << updated_outputs.size() << " connected output(s)"; 754 << updated_outputs.size() << " connected output(s)";
745 return false; 755 return false;
746 } 756 }
747 break; 757 break;
748 case ui::OUTPUT_STATE_SINGLE: { 758 case OUTPUT_STATE_SINGLE: {
749 // If there are multiple outputs connected, only one should be turned on. 759 // If there are multiple outputs connected, only one should be turned on.
750 if (updated_outputs.size() != 1 && num_on_outputs != 1) { 760 if (updated_outputs.size() != 1 && num_on_outputs != 1) {
751 LOG(WARNING) << "Ignoring request to enter single mode with " 761 LOG(WARNING) << "Ignoring request to enter single mode with "
752 << updated_outputs.size() << " connected outputs and " 762 << updated_outputs.size() << " connected outputs and "
753 << num_on_outputs << " turned on"; 763 << num_on_outputs << " turned on";
754 return false; 764 return false;
755 } 765 }
756 766
757 for (size_t i = 0; i < updated_outputs.size(); ++i) { 767 for (size_t i = 0; i < updated_outputs.size(); ++i) {
758 OutputSnapshot* output = &updated_outputs[i]; 768 OutputSnapshot* output = &updated_outputs[i];
(...skipping 14 matching lines...) Expand all
773 << ", i=" << i 783 << ", i=" << i
774 << ", output=" << OutputSnapshotToString(output) 784 << ", output=" << OutputSnapshotToString(output)
775 << ", mode_info=" << ModeInfoToString(mode_info); 785 << ", mode_info=" << ModeInfoToString(mode_info);
776 } 786 }
777 width = mode_info->width; 787 width = mode_info->width;
778 height = mode_info->height; 788 height = mode_info->height;
779 } 789 }
780 } 790 }
781 break; 791 break;
782 } 792 }
783 case ui::OUTPUT_STATE_DUAL_MIRROR: { 793 case OUTPUT_STATE_DUAL_MIRROR: {
784 if (updated_outputs.size() != 2 || 794 if (updated_outputs.size() != 2 ||
785 (num_on_outputs != 0 && num_on_outputs != 2)) { 795 (num_on_outputs != 0 && num_on_outputs != 2)) {
786 LOG(WARNING) << "Ignoring request to enter mirrored mode with " 796 LOG(WARNING) << "Ignoring request to enter mirrored mode with "
787 << updated_outputs.size() << " connected output(s) and " 797 << updated_outputs.size() << " connected output(s) and "
788 << num_on_outputs << " turned on"; 798 << num_on_outputs << " turned on";
789 return false; 799 return false;
790 } 800 }
791 801
792 if (!updated_outputs[0].mirror_mode) 802 if (!updated_outputs[0].mirror_mode)
793 return false; 803 return false;
(...skipping 15 matching lines...) Expand all
809 if (output->mirror_mode != output->native_mode && 819 if (output->mirror_mode != output->native_mode &&
810 output->is_aspect_preserving_scaling) { 820 output->is_aspect_preserving_scaling) {
811 output->transform = GetMirrorModeCTM(*output); 821 output->transform = GetMirrorModeCTM(*output);
812 mirrored_display_area_ratio_map_[output->touch_device_id] = 822 mirrored_display_area_ratio_map_[output->touch_device_id] =
813 GetMirroredDisplayAreaRatio(*output); 823 GetMirroredDisplayAreaRatio(*output);
814 } 824 }
815 } 825 }
816 } 826 }
817 break; 827 break;
818 } 828 }
819 case ui::OUTPUT_STATE_DUAL_EXTENDED: { 829 case OUTPUT_STATE_DUAL_EXTENDED: {
820 if (updated_outputs.size() != 2 || 830 if (updated_outputs.size() != 2 ||
821 (num_on_outputs != 0 && num_on_outputs != 2)) { 831 (num_on_outputs != 0 && num_on_outputs != 2)) {
822 LOG(WARNING) << "Ignoring request to enter extended mode with " 832 LOG(WARNING) << "Ignoring request to enter extended mode with "
823 << updated_outputs.size() << " connected output(s) and " 833 << updated_outputs.size() << " connected output(s) and "
824 << num_on_outputs << " turned on"; 834 << num_on_outputs << " turned on";
825 return false; 835 return false;
826 } 836 }
827 837
828 for (size_t i = 0; i < updated_outputs.size(); ++i) { 838 for (size_t i = 0; i < updated_outputs.size(); ++i) {
829 OutputSnapshot* output = &updated_outputs[i]; 839 OutputSnapshot* output = &updated_outputs[i];
(...skipping 21 matching lines...) Expand all
851 } 861 }
852 } 862 }
853 863
854 // Finally, apply the desired changes. 864 // Finally, apply the desired changes.
855 DCHECK_EQ(cached_outputs_.size(), updated_outputs.size()); 865 DCHECK_EQ(cached_outputs_.size(), updated_outputs.size());
856 bool all_succeeded = true; 866 bool all_succeeded = true;
857 if (!updated_outputs.empty()) { 867 if (!updated_outputs.empty()) {
858 native_display_delegate_->CreateFrameBuffer(width, height, updated_outputs); 868 native_display_delegate_->CreateFrameBuffer(width, height, updated_outputs);
859 for (size_t i = 0; i < updated_outputs.size(); ++i) { 869 for (size_t i = 0; i < updated_outputs.size(); ++i) {
860 const OutputSnapshot& output = updated_outputs[i]; 870 const OutputSnapshot& output = updated_outputs[i];
861 bool configure_succeeded =false; 871 bool configure_succeeded = false;
862 872
863 while (true) { 873 while (true) {
864 if (native_display_delegate_->Configure(output, 874 if (native_display_delegate_->Configure(
865 output.current_mode, 875 output, output.current_mode, output.x, output.y)) {
866 output.x,
867 output.y)) {
868 configure_succeeded = true; 876 configure_succeeded = true;
869 break; 877 break;
870 } 878 }
871 879
872 LOG(WARNING) << "Unable to configure CRTC " << output.crtc << ":" 880 LOG(WARNING) << "Unable to configure CRTC " << output.crtc << ":"
873 << " mode=" << output.current_mode 881 << " mode=" << output.current_mode
874 << " output=" << output.output 882 << " output=" << output.output << " x=" << output.x
875 << " x=" << output.x
876 << " y=" << output.y; 883 << " y=" << output.y;
877 884
878 const ModeInfo* mode_info = GetModeInfo(output, output.current_mode); 885 const ModeInfo* mode_info = GetModeInfo(output, output.current_mode);
879 if (!mode_info) 886 if (!mode_info)
880 break; 887 break;
881 888
882 // Find the mode with the next-best resolution and see if that can 889 // Find the mode with the next-best resolution and see if that can
883 // be set. 890 // be set.
884 int best_mode_pixels = 0; 891 int best_mode_pixels = 0;
885 892
886 int current_mode_pixels = mode_info->width * mode_info->height; 893 int current_mode_pixels = mode_info->width * mode_info->height;
887 for (ModeInfoMap::const_iterator it = output.mode_infos.begin(); 894 for (ModeInfoMap::const_iterator it = output.mode_infos.begin();
888 it != output.mode_infos.end(); it++) { 895 it != output.mode_infos.end();
896 it++) {
889 int pixel_count = it->second.width * it->second.height; 897 int pixel_count = it->second.width * it->second.height;
890 if ((pixel_count < current_mode_pixels) && 898 if ((pixel_count < current_mode_pixels) &&
891 (pixel_count > best_mode_pixels)) { 899 (pixel_count > best_mode_pixels)) {
892 updated_outputs[i].current_mode = it->first; 900 updated_outputs[i].current_mode = it->first;
893 best_mode_pixels = pixel_count; 901 best_mode_pixels = pixel_count;
894 } 902 }
895 } 903 }
896 904
897 if (best_mode_pixels == 0) 905 if (best_mode_pixels == 0)
898 break; 906 break;
899 } 907 }
900 908
901 if (configure_succeeded) { 909 if (configure_succeeded) {
902 if (output.touch_device_id) 910 if (output.touch_device_id)
903 touchscreen_delegate_->ConfigureCTM(output.touch_device_id, 911 touchscreen_delegate_->ConfigureCTM(output.touch_device_id,
904 output.transform); 912 output.transform);
905 cached_outputs_[i] = updated_outputs[i]; 913 cached_outputs_[i] = updated_outputs[i];
906 } else { 914 } else {
907 all_succeeded = false; 915 all_succeeded = false;
908 } 916 }
909 917
910 // If we are trying to set mirror mode and one of the modesets fails, 918 // If we are trying to set mirror mode and one of the modesets fails,
911 // then the two monitors will be mis-matched. In this case, return 919 // then the two monitors will be mis-matched. In this case, return
912 // false to let the observers be aware. 920 // false to let the observers be aware.
913 if (output_state == ui::OUTPUT_STATE_DUAL_MIRROR && output_power[i] && 921 if (output_state == OUTPUT_STATE_DUAL_MIRROR && output_power[i] &&
914 output.current_mode != output.mirror_mode) 922 output.current_mode != output.mirror_mode)
915 all_succeeded = false; 923 all_succeeded = false;
916
917 } 924 }
918 } 925 }
919 926
920 if (all_succeeded) { 927 if (all_succeeded) {
921 output_state_ = output_state; 928 output_state_ = output_state;
922 power_state_ = power_state; 929 power_state_ = power_state;
923 } 930 }
924 return all_succeeded; 931 return all_succeeded;
925 } 932 }
926 933
927 ui::OutputState OutputConfigurator::ChooseOutputState( 934 OutputState OutputConfigurator::ChooseOutputState(
928 DisplayPowerState power_state) const { 935 chromeos::DisplayPowerState power_state) const {
929 int num_on_outputs = GetOutputPower(cached_outputs_, power_state, NULL); 936 int num_on_outputs = GetOutputPower(cached_outputs_, power_state, NULL);
930 switch (cached_outputs_.size()) { 937 switch (cached_outputs_.size()) {
931 case 0: 938 case 0:
932 return ui::OUTPUT_STATE_HEADLESS; 939 return OUTPUT_STATE_HEADLESS;
933 case 1: 940 case 1:
934 return ui::OUTPUT_STATE_SINGLE; 941 return OUTPUT_STATE_SINGLE;
935 case 2: { 942 case 2: {
936 if (num_on_outputs == 1) { 943 if (num_on_outputs == 1) {
937 // If only one output is currently turned on, return the "single" 944 // If only one output is currently turned on, return the "single"
938 // state so that its native mode will be used. 945 // state so that its native mode will be used.
939 return ui::OUTPUT_STATE_SINGLE; 946 return OUTPUT_STATE_SINGLE;
940 } else { 947 } else {
941 // With either both outputs on or both outputs off, use one of the 948 // With either both outputs on or both outputs off, use one of the
942 // dual modes. 949 // dual modes.
943 std::vector<int64> display_ids; 950 std::vector<int64> display_ids;
944 for (size_t i = 0; i < cached_outputs_.size(); ++i) { 951 for (size_t i = 0; i < cached_outputs_.size(); ++i) {
945 // If display id isn't available, switch to extended mode. 952 // If display id isn't available, switch to extended mode.
946 if (!cached_outputs_[i].has_display_id) 953 if (!cached_outputs_[i].has_display_id)
947 return ui::OUTPUT_STATE_DUAL_EXTENDED; 954 return OUTPUT_STATE_DUAL_EXTENDED;
948 display_ids.push_back(cached_outputs_[i].display_id); 955 display_ids.push_back(cached_outputs_[i].display_id);
949 } 956 }
950 return state_controller_->GetStateForDisplayIds(display_ids); 957 return state_controller_->GetStateForDisplayIds(display_ids);
951 } 958 }
952 } 959 }
953 default: 960 default:
954 NOTREACHED(); 961 NOTREACHED();
955 } 962 }
956 return ui::OUTPUT_STATE_INVALID; 963 return OUTPUT_STATE_INVALID;
957 } 964 }
958 965
959 OutputConfigurator::CoordinateTransformation 966 OutputConfigurator::CoordinateTransformation
960 OutputConfigurator::GetMirrorModeCTM( 967 OutputConfigurator::GetMirrorModeCTM(
961 const OutputConfigurator::OutputSnapshot& output) { 968 const OutputConfigurator::OutputSnapshot& output) {
962 CoordinateTransformation ctm; // Default to identity 969 CoordinateTransformation ctm; // Default to identity
963 const ModeInfo* native_mode_info = GetModeInfo(output, output.native_mode); 970 const ModeInfo* native_mode_info = GetModeInfo(output, output.native_mode);
964 const ModeInfo* mirror_mode_info = GetModeInfo(output, output.mirror_mode); 971 const ModeInfo* mirror_mode_info = GetModeInfo(output, output.mirror_mode);
965 972
966 if (!native_mode_info || !mirror_mode_info || 973 if (!native_mode_info || !mirror_mode_info || native_mode_info->height == 0 ||
967 native_mode_info->height == 0 || mirror_mode_info->height == 0 || 974 mirror_mode_info->height == 0 || native_mode_info->width == 0 ||
968 native_mode_info->width == 0 || mirror_mode_info->width == 0) 975 mirror_mode_info->width == 0)
969 return ctm; 976 return ctm;
970 977
971 float native_mode_ar = static_cast<float>(native_mode_info->width) / 978 float native_mode_ar = static_cast<float>(native_mode_info->width) /
972 static_cast<float>(native_mode_info->height); 979 static_cast<float>(native_mode_info->height);
973 float mirror_mode_ar = static_cast<float>(mirror_mode_info->width) / 980 float mirror_mode_ar = static_cast<float>(mirror_mode_info->width) /
974 static_cast<float>(mirror_mode_info->height); 981 static_cast<float>(mirror_mode_info->height);
975 982
976 if (mirror_mode_ar > native_mode_ar) { // Letterboxing 983 if (mirror_mode_ar > native_mode_ar) { // Letterboxing
977 ctm.x_scale = 1.0; 984 ctm.x_scale = 1.0;
978 ctm.x_offset = 0.0; 985 ctm.x_offset = 0.0;
979 ctm.y_scale = mirror_mode_ar / native_mode_ar; 986 ctm.y_scale = mirror_mode_ar / native_mode_ar;
980 ctm.y_offset = (native_mode_ar / mirror_mode_ar - 1.0) * 0.5; 987 ctm.y_offset = (native_mode_ar / mirror_mode_ar - 1.0) * 0.5;
981 return ctm; 988 return ctm;
982 } 989 }
983 if (native_mode_ar > mirror_mode_ar) { // Pillarboxing 990 if (native_mode_ar > mirror_mode_ar) { // Pillarboxing
984 ctm.y_scale = 1.0; 991 ctm.y_scale = 1.0;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1029 ctm.y_offset = static_cast<float>(output.y) / (framebuffer_height - 1); 1036 ctm.y_offset = static_cast<float>(output.y) / (framebuffer_height - 1);
1030 return ctm; 1037 return ctm;
1031 } 1038 }
1032 1039
1033 float OutputConfigurator::GetMirroredDisplayAreaRatio( 1040 float OutputConfigurator::GetMirroredDisplayAreaRatio(
1034 const OutputConfigurator::OutputSnapshot& output) { 1041 const OutputConfigurator::OutputSnapshot& output) {
1035 float area_ratio = 1.0f; 1042 float area_ratio = 1.0f;
1036 const ModeInfo* native_mode_info = GetModeInfo(output, output.native_mode); 1043 const ModeInfo* native_mode_info = GetModeInfo(output, output.native_mode);
1037 const ModeInfo* mirror_mode_info = GetModeInfo(output, output.mirror_mode); 1044 const ModeInfo* mirror_mode_info = GetModeInfo(output, output.mirror_mode);
1038 1045
1039 if (!native_mode_info || !mirror_mode_info || 1046 if (!native_mode_info || !mirror_mode_info || native_mode_info->height == 0 ||
1040 native_mode_info->height == 0 || mirror_mode_info->height == 0 || 1047 mirror_mode_info->height == 0 || native_mode_info->width == 0 ||
1041 native_mode_info->width == 0 || mirror_mode_info->width == 0) 1048 mirror_mode_info->width == 0)
1042 return area_ratio; 1049 return area_ratio;
1043 1050
1044 float width_ratio = static_cast<float>(mirror_mode_info->width) / 1051 float width_ratio = static_cast<float>(mirror_mode_info->width) /
1045 static_cast<float>(native_mode_info->width); 1052 static_cast<float>(native_mode_info->width);
1046 float height_ratio = static_cast<float>(mirror_mode_info->height) / 1053 float height_ratio = static_cast<float>(mirror_mode_info->height) /
1047 static_cast<float>(native_mode_info->height); 1054 static_cast<float>(native_mode_info->height);
1048 1055
1049 area_ratio = width_ratio * height_ratio; 1056 area_ratio = width_ratio * height_ratio;
1050 return area_ratio; 1057 return area_ratio;
1051 } 1058 }
1052 1059
1053 } // namespace chromeos 1060 } // namespace ui
OLDNEW
« no previous file with comments | « ui/display/chromeos/output_configurator.h ('k') | ui/display/chromeos/output_configurator_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698