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

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

Issue 10824071: chromeos: output_configurator: various style fixes (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 4 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 | « chromeos/display/output_configurator.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "chromeos/display/output_configurator.h"
6 6
7 #include <X11/Xlib.h> 7 #include <X11/Xlib.h>
8 #include <X11/extensions/dpms.h> 8 #include <X11/extensions/dpms.h>
9 #include <X11/extensions/Xrandr.h> 9 #include <X11/extensions/Xrandr.h>
10 10
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
215 static float ComputeDeviceScaleFactor(unsigned int width, 215 static float ComputeDeviceScaleFactor(unsigned int width,
216 unsigned long mm_width) { 216 unsigned long mm_width) {
217 float device_scale_factor = 1.0f; 217 float device_scale_factor = 1.0f;
218 if (mm_width > 0 && (kMmInInch * width / mm_width) > kHighDensityDIPThreshold) 218 if (mm_width > 0 && (kMmInInch * width / mm_width) > kHighDensityDIPThreshold)
219 device_scale_factor = 2.0f; 219 device_scale_factor = 2.0f;
220 return device_scale_factor; 220 return device_scale_factor;
221 } 221 }
222 222
223 } // namespace 223 } // namespace
224 224
225 OutputConfigurator::OutputConfigurator()
226 : is_running_on_chrome_os_(base::chromeos::IsRunningOnChromeOS()),
227 output_count_(0),
228 output_cache_(NULL),
229 mirror_supported_(false),
230 primary_output_index_(-1),
231 secondary_output_index_(-1),
232 xrandr_event_base_(0),
233 output_state_(STATE_INVALID) {
234 if (!is_running_on_chrome_os_)
235 return;
236 // Send the signal to powerd to tell it that we will take over output
237 // control.
238 // Note that this can be removed once the legacy powerd support is removed.
239 chromeos::DBusThreadManager* manager = chromeos::DBusThreadManager::Get();
240 dbus::Bus* bus = manager->GetSystemBus();
241 dbus::ExportedObject* remote_object = bus->GetExportedObject(
242 dbus::ObjectPath(power_manager::kPowerManagerServicePath));
243 dbus::Signal signal(power_manager::kPowerManagerInterface,
244 power_manager::kUseNewMonitorConfigSignal);
245 CHECK(signal.raw_message() != NULL);
246 remote_object->SendSignal(&signal);
247
248 // Cache the initial output state.
249 Display* display = base::MessagePumpAuraX11::GetDefaultXDisplay();
250 CHECK(display != NULL);
251 XGrabServer(display);
252 Window window = DefaultRootWindow(display);
253 XRRScreenResources* screen = XRRGetScreenResources(display, window);
254 CHECK(screen != NULL);
255 bool did_detect_outputs = TryRecacheOutputs(display, screen);
256 CHECK(did_detect_outputs);
257 OutputState current_state = InferCurrentState(display, screen);
258 if (current_state == STATE_INVALID) {
259 // Unknown state. Transition into the default state.
260 OutputState state = GetDefaultState();
261 UpdateCacheAndXrandrToState(display, screen, window, state);
262 } else {
263 // This is a valid state so just save it to |output_state_|.
264 output_state_ = current_state;
265 }
266 // Find xrandr_event_base_ since we need it to interpret events, later.
267 int error_base_ignored = 0;
268 XRRQueryExtension(display, &xrandr_event_base_, &error_base_ignored);
269 // Relinquish X resources.
270 XRRFreeScreenResources(screen);
271 XUngrabServer(display);
272 CheckIsProjectingAndNotify();
273 }
274
275 OutputConfigurator::~OutputConfigurator() {
276 }
277
278 bool OutputConfigurator::CycleDisplayMode(bool extended_desktop_enabled) {
279 VLOG(1) << "CycleDisplayMode";
280 if (!is_running_on_chrome_os_)
281 return false;
282
283 bool did_change = false;
284 // Rules:
285 // - if there are 0 or 1 displays, do nothing and return false.
286 // - use y-coord of CRTCs to determine if we are mirror, primary-first, or
287 // secondary-first. The cycle order is:
288 // mirror->primary->secondary->mirror.
289 // Note: If the extended desktop is enabled, the cycle order becomes,
290 // mirror->extended->mirror
291 OutputState new_state = STATE_INVALID;
292 switch (output_state_) {
293 case STATE_DUAL_MIRROR:
294 new_state = STATE_DUAL_PRIMARY_ONLY;
295 break;
296 case STATE_DUAL_PRIMARY_ONLY:
297 if (extended_desktop_enabled) {
298 if (mirror_supported_)
299 new_state = STATE_DUAL_MIRROR;
300 else
301 new_state = STATE_INVALID;
302 } else {
303 new_state = STATE_DUAL_SECONDARY_ONLY;
304 }
305 break;
306 case STATE_DUAL_SECONDARY_ONLY:
307 new_state = mirror_supported_ ?
308 STATE_DUAL_MIRROR :
309 STATE_DUAL_PRIMARY_ONLY;
310 break;
311 default:
312 // Do nothing - we aren't in a mode which we can rotate.
313 break;
314 }
315 if (STATE_INVALID != new_state)
316 did_change = SetDisplayMode(new_state);
317
318 return did_change;
319 }
320
321 bool OutputConfigurator::ScreenPowerSet(bool power_on, bool all_displays) {
322 VLOG(1) << "OutputConfigurator::SetScreensOn " << power_on
323 << " all displays " << all_displays;
324 if (!is_running_on_chrome_os_)
325 return false;
326
327 bool success = false;
328 Display* display = base::MessagePumpAuraX11::GetDefaultXDisplay();
329 CHECK(display != NULL);
330 XGrabServer(display);
331 Window window = DefaultRootWindow(display);
332 XRRScreenResources* screen = XRRGetScreenResources(display, window);
333 CHECK(screen != NULL);
334
335 // Set the CRTCs based on whether we want to turn the power on or off and
336 // select the outputs to operate on by name or all_displays.
337 for (int i = 0; i < output_count_; ++i) {
338 if (all_displays || output_cache_[i].is_internal) {
339 const int x = output_cache_[i].x;
340 const int y = output_cache_[i].y;
341 RROutput output = output_cache_[i].output;
342 RRCrtc crtc = output_cache_[i].crtc;
343 RRMode mode = None;
344 if (power_on) {
345 mode = (STATE_DUAL_MIRROR == output_state_) ?
346 output_cache_[i].mirror_mode :
347 output_cache_[i].ideal_mode;
348 }
349
350 VLOG(1) << "SET POWER crtc: " << crtc
351 << ", mode " << mode
352 << ", output " << output
353 << ", x " << x
354 << ", y " << y;
355 // The values we are setting are already from the cache so no update
356 // required.
357 ConfigureCrtc(display,
358 screen,
359 crtc,
360 x,
361 y,
362 mode,
363 output);
364 output_cache_[i].is_powered_on = power_on;
365 success = true;
366 }
367 }
368
369 // Force the DPMS on since the driver doesn't always detect that it should
370 // turn on.
371 if (power_on) {
372 CHECK(DPMSEnable(display));
373 CHECK(DPMSForceLevel(display, DPMSModeOn));
374 }
375
376 XRRFreeScreenResources(screen);
377 XUngrabServer(display);
378
379 return success;
380 }
381
382 bool OutputConfigurator::SetDisplayMode(OutputState new_state) {
383 if (output_state_ == STATE_INVALID ||
384 output_state_ == STATE_HEADLESS ||
385 output_state_ == STATE_SINGLE)
386 return false;
387
388 Display* display = base::MessagePumpAuraX11::GetDefaultXDisplay();
389 CHECK(display != NULL);
390 XGrabServer(display);
391 Window window = DefaultRootWindow(display);
392 XRRScreenResources* screen = XRRGetScreenResources(display, window);
393 CHECK(screen != NULL);
394
395 UpdateCacheAndXrandrToState(display,
396 screen,
397 window,
398 new_state);
399 XRRFreeScreenResources(screen);
400 XUngrabServer(display);
401 return true;
402 }
403
404 bool OutputConfigurator::Dispatch(const base::NativeEvent& event) {
405 // Ignore this event if the Xrandr extension isn't supported.
406 if (!is_running_on_chrome_os_ ||
407 (event->type - xrandr_event_base_ != RRNotify)) {
408 return true;
409 }
410 XEvent* xevent = static_cast<XEvent*>(event);
411 XRRNotifyEvent* notify_event =
412 reinterpret_cast<XRRNotifyEvent*>(xevent);
413 if (notify_event->subtype == RRNotify_OutputChange) {
414 XRROutputChangeNotifyEvent* output_change_event =
415 reinterpret_cast<XRROutputChangeNotifyEvent*>(xevent);
416 if ((output_change_event->connection == RR_Connected) ||
417 (output_change_event->connection == RR_Disconnected)) {
418 RecacheAndUseDefaultState();
419 CheckIsProjectingAndNotify();
420 }
421 // Ignore the case of RR_UnkownConnection.
422 }
423 return true;
424 }
425
225 bool OutputConfigurator::TryRecacheOutputs(Display* display, 426 bool OutputConfigurator::TryRecacheOutputs(Display* display,
226 XRRScreenResources* screen) { 427 XRRScreenResources* screen) {
227 bool outputs_did_change = false; 428 bool outputs_did_change = false;
228 int previous_connected_count = 0; 429 int previous_connected_count = 0;
229 int new_connected_count = 0; 430 int new_connected_count = 0;
230 431
231 if (output_count_ != screen->noutput) { 432 if (output_count_ != screen->noutput) {
232 outputs_did_change = true; 433 outputs_did_change = true;
233 } else { 434 } else {
234 // The outputs might have changed so compare the connected states in the 435 // The outputs might have changed so compare the connected states in the
235 // screen to our existing cache. 436 // screen to our existing cache.
236 for (int i = 0; (i < output_count_) && !outputs_did_change; ++i) { 437 for (int i = 0; (i < output_count_) && !outputs_did_change; ++i) {
237 RROutput thisID = screen->outputs[i]; 438 RROutput thisID = screen->outputs[i];
238 XRROutputInfo* output = XRRGetOutputInfo(display, screen, thisID); 439 XRROutputInfo* output = XRRGetOutputInfo(display, screen, thisID);
239 bool now_connected = (RR_Connected == output->connection); 440 bool now_connected = (RR_Connected == output->connection);
240 outputs_did_change = (now_connected != output_cache_[i].is_connected); 441 outputs_did_change = (now_connected != output_cache_[i].is_connected);
241 XRRFreeOutputInfo(output); 442 XRRFreeOutputInfo(output);
242 443
243 if (output_cache_[i].is_connected) 444 if (output_cache_[i].is_connected)
244 previous_connected_count += 1; 445 previous_connected_count += 1;
245 if (now_connected) 446 if (now_connected)
246 new_connected_count += 1; 447 new_connected_count += 1;
247 } 448 }
248 } 449 }
249 450
250 if (outputs_did_change) { 451 if (!outputs_did_change)
251 // We now know that we need to recache so free and re-alloc the buffer. 452 return false;
252 output_count_ = screen->noutput; 453 // We now know that we need to recache so free and re-alloc the buffer.
253 if (output_count_ == 0) { 454 output_count_ = screen->noutput;
254 output_cache_.reset(NULL); 455 if (output_count_ == 0) {
255 } else { 456 output_cache_.reset(NULL);
256 // Ideally, this would be allocated inline in the OutputConfigurator 457 } else {
257 // instance since we support at most 2 connected outputs but this dynamic 458 // Ideally, this would be allocated inline in the OutputConfigurator
258 // allocation was specifically requested. 459 // instance since we support at most 2 connected outputs but this dynamic
259 output_cache_.reset(new CachedOutputDescription[output_count_]); 460 // allocation was specifically requested.
461 output_cache_.reset(new CachedOutputDescription[output_count_]);
462 }
463
464 // TODO: This approach to finding CRTCs only supports two. Expand on this.
465 RRCrtc used_crtc = None;
466 primary_output_index_ = -1;
467 secondary_output_index_ = -1;
468
469 for (int i = 0; i < output_count_; ++i) {
470 RROutput this_id = screen->outputs[i];
471 XRROutputInfo* output = XRRGetOutputInfo(display, screen, this_id);
472 bool is_connected = (RR_Connected == output->connection);
473 RRCrtc crtc = None;
474 RRMode ideal_mode = None;
475 int x = 0;
476 int y = 0;
477 unsigned long mm_width = output->mm_width;
478 unsigned long mm_height = output->mm_height;
479 bool is_internal = false;
480
481 if (is_connected) {
482 for (int j = 0; (j < output->ncrtc) && (None == crtc); ++j) {
483 RRCrtc possible = output->crtcs[j];
484 if (possible != used_crtc) {
485 crtc = possible;
486 used_crtc = possible;
487 }
488 }
489
490 const char* name = output->name;
491 is_internal =
492 (strncmp(kInternal_LVDS,
493 name,
494 arraysize(kInternal_LVDS) - 1) == 0) ||
495 (strncmp(kInternal_eDP,
496 name,
497 arraysize(kInternal_eDP) - 1) == 0);
498 if (output->nmode > 0)
499 ideal_mode = output->modes[0];
500
501 if (crtc != None) {
502 XRRCrtcInfo* crtcInfo = XRRGetCrtcInfo(display, screen, crtc);
503 x = crtcInfo->x;
504 y = crtcInfo->y;
505 XRRFreeCrtcInfo(crtcInfo);
506 }
507
508 // Save this for later mirror mode detection.
509 if (primary_output_index_ == -1)
510 primary_output_index_ = i;
511 else if (secondary_output_index_ == -1)
512 secondary_output_index_ = i;
260 } 513 }
514 XRRFreeOutputInfo(output);
261 515
262 // TODO: This approach to finding CRTCs only supports two. Expand on this. 516 // Now save the cached state for this output (we will default to mirror
263 RRCrtc used_crtc = None; 517 // disabled and detect that after we have identified the first two
264 primary_output_index_ = -1; 518 // connected outputs).
265 secondary_output_index_ = -1; 519 VLOG(1) << "Recache output index: " << i
520 << ", output id: " << this_id
521 << ", crtc id: " << crtc
522 << ", ideal mode id: " << ideal_mode
523 << ", x: " << x
524 << ", y: " << y
525 << ", is connected: " << is_connected
526 << ", is_internal: " << is_internal
527 << ", mm_width: " << mm_width
528 << ", mm_height: " << mm_height;
529 output_cache_[i].output = this_id;
530 output_cache_[i].crtc = crtc;
531 output_cache_[i].mirror_mode = None;
532 output_cache_[i].ideal_mode = ideal_mode;
533 output_cache_[i].x = x;
534 output_cache_[i].y = y;
535 output_cache_[i].is_connected = is_connected;
536 output_cache_[i].is_powered_on = true;
537 output_cache_[i].is_internal = is_internal;
538 output_cache_[i].mm_width = mm_width;
539 output_cache_[i].mm_height = mm_height;
540 }
266 541
267 for (int i = 0; i < output_count_; ++i) { 542 // Now, detect the mirror modes if we have two connected outputs.
268 RROutput this_id = screen->outputs[i]; 543 if ((primary_output_index_ != -1) && (secondary_output_index_ != -1)) {
269 XRROutputInfo* output = XRRGetOutputInfo(display, screen, this_id); 544 mirror_supported_ = FindMirrorModeForOutputs(
270 bool is_connected = (RR_Connected == output->connection); 545 display,
271 RRCrtc crtc = None; 546 screen,
272 RRMode ideal_mode = None; 547 output_cache_[primary_output_index_].output,
273 int x = 0; 548 output_cache_[secondary_output_index_].output,
274 int y = 0; 549 &output_cache_[primary_output_index_].mirror_mode,
275 unsigned long mm_width = output->mm_width; 550 &output_cache_[secondary_output_index_].mirror_mode);
276 unsigned long mm_height = output->mm_height;
277 bool is_internal = false;
278 551
279 if (is_connected) { 552 RRMode primary_mode = output_cache_[primary_output_index_].mirror_mode;
280 for (int j = 0; (j < output->ncrtc) && (None == crtc); ++j) { 553 RRMode second_mode = output_cache_[secondary_output_index_].mirror_mode;
281 RRCrtc possible = output->crtcs[j]; 554 VLOG(1) << "Mirror mode supported " << mirror_supported_
282 if (possible != used_crtc) { 555 << " primary " << primary_mode
283 crtc = possible; 556 << " secondary " << second_mode;
284 used_crtc = possible;
285 }
286 }
287
288 const char* name = output->name;
289 is_internal =
290 (strncmp(kInternal_LVDS,
291 name,
292 arraysize(kInternal_LVDS) - 1) == 0) ||
293 (strncmp(kInternal_eDP,
294 name,
295 arraysize(kInternal_eDP) - 1) == 0);
296 if (output->nmode > 0)
297 ideal_mode = output->modes[0];
298
299 if (crtc != None) {
300 XRRCrtcInfo* crtcInfo = XRRGetCrtcInfo(display, screen, crtc);
301 x = crtcInfo->x;
302 y = crtcInfo->y;
303 XRRFreeCrtcInfo(crtcInfo);
304 }
305
306 // Save this for later mirror mode detection.
307 if (primary_output_index_ == -1)
308 primary_output_index_ = i;
309 else if (secondary_output_index_ == -1)
310 secondary_output_index_ = i;
311 }
312 XRRFreeOutputInfo(output);
313
314 // Now save the cached state for this output (we will default to mirror
315 // disabled and detect that after we have identified the first two
316 // connected outputs).
317 VLOG(1) << "Recache output index: " << i
318 << ", output id: " << this_id
319 << ", crtc id: " << crtc
320 << ", ideal mode id: " << ideal_mode
321 << ", x: " << x
322 << ", y: " << y
323 << ", is connected: " << is_connected
324 << ", is_internal: " << is_internal
325 << ", mm_width: " << mm_width
326 << ", mm_height: " << mm_height;
327 output_cache_[i].output = this_id;
328 output_cache_[i].crtc = crtc;
329 output_cache_[i].mirror_mode = None;
330 output_cache_[i].ideal_mode = ideal_mode;
331 output_cache_[i].x = x;
332 output_cache_[i].y = y;
333 output_cache_[i].is_connected = is_connected;
334 output_cache_[i].is_powered_on = true;
335 output_cache_[i].is_internal = is_internal;
336 output_cache_[i].mm_width = mm_width;
337 output_cache_[i].mm_height = mm_height;
338 }
339
340 // Now, detect the mirror modes if we have two connected outputs.
341 if ((primary_output_index_ != -1) && (secondary_output_index_ != -1)) {
342 mirror_supported_ = FindMirrorModeForOutputs(
343 display,
344 screen,
345 output_cache_[primary_output_index_].output,
346 output_cache_[secondary_output_index_].output,
347 &output_cache_[primary_output_index_].mirror_mode,
348 &output_cache_[secondary_output_index_].mirror_mode);
349
350 RRMode primary_mode = output_cache_[primary_output_index_].mirror_mode;
351 RRMode second_mode = output_cache_[secondary_output_index_].mirror_mode;
352 VLOG(1) << "Mirror mode supported " << mirror_supported_
353 << " primary " << primary_mode
354 << " secondary " << second_mode;
355 }
356 } 557 }
357 return outputs_did_change; 558 return outputs_did_change;
358 } 559 }
359 560
360 OutputConfigurator::OutputConfigurator()
361 : is_running_on_chrome_os_(base::chromeos::IsRunningOnChromeOS()),
362 output_count_(0),
363 output_cache_(NULL),
364 mirror_supported_(false),
365 primary_output_index_(-1),
366 secondary_output_index_(-1),
367 xrandr_event_base_(0),
368 output_state_(STATE_INVALID) {
369 if (is_running_on_chrome_os_) {
370 // Send the signal to powerd to tell it that we will take over output
371 // control.
372 // Note that this can be removed once the legacy powerd support is removed.
373 chromeos::DBusThreadManager* manager = chromeos::DBusThreadManager::Get();
374 dbus::Bus* bus = manager->GetSystemBus();
375 dbus::ExportedObject* remote_object = bus->GetExportedObject(
376 dbus::ObjectPath(power_manager::kPowerManagerServicePath));
377 dbus::Signal signal(power_manager::kPowerManagerInterface,
378 power_manager::kUseNewMonitorConfigSignal);
379 CHECK(signal.raw_message() != NULL);
380 remote_object->SendSignal(&signal);
381
382 // Cache the initial output state.
383 Display* display = base::MessagePumpAuraX11::GetDefaultXDisplay();
384 CHECK(display != NULL);
385 XGrabServer(display);
386 Window window = DefaultRootWindow(display);
387 XRRScreenResources* screen = XRRGetScreenResources(display, window);
388 CHECK(screen != NULL);
389 bool did_detect_outputs = TryRecacheOutputs(display, screen);
390 CHECK(did_detect_outputs);
391 State current_state = InferCurrentState(display, screen);
392 if (current_state == STATE_INVALID) {
393 // Unknown state. Transition into the default state.
394 State state = GetDefaultState();
395 UpdateCacheAndXrandrToState(display, screen, window, state);
396 } else {
397 // This is a valid state so just save it to |output_state_|.
398 output_state_ = current_state;
399 }
400 // Find xrandr_event_base_ since we need it to interpret events, later.
401 int error_base_ignored = 0;
402 XRRQueryExtension(display, &xrandr_event_base_, &error_base_ignored);
403 // Relinquish X resources.
404 XRRFreeScreenResources(screen);
405 XUngrabServer(display);
406 CheckIsProjectingAndNotify();
407 }
408 }
409
410 OutputConfigurator::~OutputConfigurator() {
411 }
412
413 void OutputConfigurator::UpdateCacheAndXrandrToState( 561 void OutputConfigurator::UpdateCacheAndXrandrToState(
414 Display* display, 562 Display* display,
415 XRRScreenResources* screen, 563 XRRScreenResources* screen,
416 Window window, 564 Window window,
417 State new_state) { 565 OutputState new_state) {
418 // Default rules: 566 // Default rules:
419 // - single display = rebuild framebuffer and set to ideal_mode. 567 // - single display = rebuild framebuffer and set to ideal_mode.
420 // - multi display = rebuild framebuffer and set to mirror_mode. 568 // - multi display = rebuild framebuffer and set to mirror_mode.
421 569
422 // First, calculate the width and height of the framebuffer (we could retain 570 // First, calculate the width and height of the framebuffer (we could retain
423 // the existing buffer, if it isn't resizing, but that causes an odd display 571 // the existing buffer, if it isn't resizing, but that causes an odd display
424 // state where the CRTCs are repositioned over the root windows before Chrome 572 // state where the CRTCs are repositioned over the root windows before Chrome
425 // can move them). It is a feature worth considering, though, and wouldn't 573 // can move them). It is a feature worth considering, though, and wouldn't
426 // be difficult to implement (just check the current framebuffer size before 574 // be difficult to implement (just check the current framebuffer size before
427 // changing it). 575 // changing it).
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
555 UMA_HISTOGRAM_BOOLEAN("Display.XRRGetScreenResources_completed", false); 703 UMA_HISTOGRAM_BOOLEAN("Display.XRRGetScreenResources_completed", false);
556 PerfTimer histogram_timer; 704 PerfTimer histogram_timer;
557 XRRScreenResources* screen = XRRGetScreenResources(display, window); 705 XRRScreenResources* screen = XRRGetScreenResources(display, window);
558 base::TimeDelta duration = histogram_timer.Elapsed(); 706 base::TimeDelta duration = histogram_timer.Elapsed();
559 UMA_HISTOGRAM_BOOLEAN("Display.XRRGetScreenResources_completed", true); 707 UMA_HISTOGRAM_BOOLEAN("Display.XRRGetScreenResources_completed", true);
560 UMA_HISTOGRAM_LONG_TIMES("Display.XRRGetScreenResources_duration", duration); 708 UMA_HISTOGRAM_LONG_TIMES("Display.XRRGetScreenResources_duration", duration);
561 CHECK(screen != NULL); 709 CHECK(screen != NULL);
562 710
563 bool did_detect_change = TryRecacheOutputs(display, screen); 711 bool did_detect_change = TryRecacheOutputs(display, screen);
564 if (did_detect_change) { 712 if (did_detect_change) {
565 State state = GetDefaultState(); 713 OutputState state = GetDefaultState();
566 UpdateCacheAndXrandrToState(display, screen, window, state); 714 UpdateCacheAndXrandrToState(display, screen, window, state);
567 } 715 }
568 XRRFreeScreenResources(screen); 716 XRRFreeScreenResources(screen);
569 XUngrabServer(display); 717 XUngrabServer(display);
570 return did_detect_change; 718 return did_detect_change;
571 } 719 }
572 720
573 State OutputConfigurator::GetDefaultState() const { 721 OutputState OutputConfigurator::GetDefaultState() const {
574 State state = STATE_HEADLESS; 722 OutputState state = STATE_HEADLESS;
575 if (-1 != primary_output_index_) { 723 if (-1 != primary_output_index_) {
576 if (-1 != secondary_output_index_) 724 if (-1 != secondary_output_index_)
577 state = mirror_supported_ ? STATE_DUAL_MIRROR : STATE_DUAL_PRIMARY_ONLY; 725 state = mirror_supported_ ? STATE_DUAL_MIRROR : STATE_DUAL_PRIMARY_ONLY;
578 else 726 else
579 state = STATE_SINGLE; 727 state = STATE_SINGLE;
580 } 728 }
581 return state; 729 return state;
582 } 730 }
583 731
584 State OutputConfigurator::InferCurrentState(Display* display, 732 OutputState OutputConfigurator::InferCurrentState(
585 XRRScreenResources* screen) const { 733 Display* display, XRRScreenResources* screen) const {
586 // STATE_INVALID will be our default or "unknown" state. 734 // STATE_INVALID will be our default or "unknown" state.
587 State state = STATE_INVALID; 735 OutputState state = STATE_INVALID;
588 // First step: count the number of connected outputs. 736 // First step: count the number of connected outputs.
589 if (secondary_output_index_ == -1) { 737 if (secondary_output_index_ == -1) {
590 // No secondary display. 738 // No secondary display.
591 if (primary_output_index_ == -1) { 739 if (primary_output_index_ == -1) {
592 // No primary display implies HEADLESS. 740 // No primary display implies HEADLESS.
593 state = STATE_HEADLESS; 741 state = STATE_HEADLESS;
594 } else { 742 } else {
595 // The common case of primary-only. 743 // The common case of primary-only.
596 // The only sanity check we require in this case is that the current mode 744 // The only sanity check we require in this case is that the current mode
597 // of the output's CRTC is the ideal mode we determined for it. 745 // of the output's CRTC is the ideal mode we determined for it.
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
652 // Primary is tiled first. 800 // Primary is tiled first.
653 state = STATE_DUAL_PRIMARY_ONLY; 801 state = STATE_DUAL_PRIMARY_ONLY;
654 } 802 }
655 } 803 }
656 } 804 }
657 } 805 }
658 806
659 return state; 807 return state;
660 } 808 }
661 809
662 bool OutputConfigurator::CycleDisplayMode(bool extended_desktop_enabled) {
663 VLOG(1) << "CycleDisplayMode";
664 bool did_change = false;
665
666 if (is_running_on_chrome_os_) {
667 // Rules:
668 // - if there are 0 or 1 displays, do nothing and return false.
669 // - use y-coord of CRTCs to determine if we are mirror, primary-first, or
670 // secondary-first. The cycle order is:
671 // mirror->primary->secondary->mirror.
672 // Note: If the extended desktop is enabled, the cycle order becomes,
673 // mirror->extended->mirror
674 State new_state = STATE_INVALID;
675 switch (output_state_) {
676 case STATE_DUAL_MIRROR:
677 new_state = STATE_DUAL_PRIMARY_ONLY;
678 break;
679 case STATE_DUAL_PRIMARY_ONLY:
680 if (extended_desktop_enabled) {
681 if (mirror_supported_)
682 new_state = STATE_DUAL_MIRROR;
683 else
684 new_state = STATE_INVALID;
685 } else {
686 new_state = STATE_DUAL_SECONDARY_ONLY;
687 }
688 break;
689 case STATE_DUAL_SECONDARY_ONLY:
690 new_state = mirror_supported_ ?
691 STATE_DUAL_MIRROR :
692 STATE_DUAL_PRIMARY_ONLY;
693 break;
694 default:
695 // Do nothing - we aren't in a mode which we can rotate.
696 break;
697 }
698 if (STATE_INVALID != new_state)
699 did_change = SetDisplayMode(new_state);
700 }
701 return did_change;
702 }
703
704 bool OutputConfigurator::ScreenPowerSet(bool power_on, bool all_displays) {
705 VLOG(1) << "OutputConfigurator::SetScreensOn " << power_on
706 << " all displays " << all_displays;
707 bool success = false;
708 if (is_running_on_chrome_os_) {
709 Display* display = base::MessagePumpAuraX11::GetDefaultXDisplay();
710 CHECK(display != NULL);
711 XGrabServer(display);
712 Window window = DefaultRootWindow(display);
713 XRRScreenResources* screen = XRRGetScreenResources(display, window);
714 CHECK(screen != NULL);
715
716 // Set the CRTCs based on whether we want to turn the power on or off and
717 // select the outputs to operate on by name or all_displays.
718 for (int i = 0; i < output_count_; ++i) {
719 if (all_displays || output_cache_[i].is_internal) {
720 const int x = output_cache_[i].x;
721 const int y = output_cache_[i].y;
722 RROutput output = output_cache_[i].output;
723 RRCrtc crtc = output_cache_[i].crtc;
724 RRMode mode = None;
725 if (power_on) {
726 mode = (STATE_DUAL_MIRROR == output_state_) ?
727 output_cache_[i].mirror_mode :
728 output_cache_[i].ideal_mode;
729 }
730
731 VLOG(1) << "SET POWER crtc: " << crtc
732 << ", mode " << mode
733 << ", output " << output
734 << ", x " << x
735 << ", y " << y;
736 // The values we are setting are already from the cache so no update
737 // required.
738 ConfigureCrtc(display,
739 screen,
740 crtc,
741 x,
742 y,
743 mode,
744 output);
745 output_cache_[i].is_powered_on = power_on;
746 success = true;
747 }
748 }
749
750 // Force the DPMS on since the driver doesn't always detect that it should
751 // turn on.
752 if (power_on) {
753 CHECK(DPMSEnable(display));
754 CHECK(DPMSForceLevel(display, DPMSModeOn));
755 }
756
757 XRRFreeScreenResources(screen);
758 XUngrabServer(display);
759 }
760 return success;
761 }
762
763 bool OutputConfigurator::SetDisplayMode(State new_state) {
764 if (output_state_ == STATE_INVALID ||
765 output_state_ == STATE_HEADLESS ||
766 output_state_ == STATE_SINGLE)
767 return false;
768
769 Display* display = base::MessagePumpAuraX11::GetDefaultXDisplay();
770 CHECK(display != NULL);
771 XGrabServer(display);
772 Window window = DefaultRootWindow(display);
773 XRRScreenResources* screen = XRRGetScreenResources(display, window);
774 CHECK(screen != NULL);
775
776 UpdateCacheAndXrandrToState(display,
777 screen,
778 window,
779 new_state);
780 XRRFreeScreenResources(screen);
781 XUngrabServer(display);
782 return true;
783 }
784
785 bool OutputConfigurator::Dispatch(const base::NativeEvent& event) {
786 // Ignore this event if the Xrandr extension isn't supported.
787 if (is_running_on_chrome_os_ &&
788 (event->type - xrandr_event_base_ == RRNotify)) {
789 XEvent* xevent = static_cast<XEvent*>(event);
790 XRRNotifyEvent* notify_event =
791 reinterpret_cast<XRRNotifyEvent*>(xevent);
792 if (notify_event->subtype == RRNotify_OutputChange) {
793 XRROutputChangeNotifyEvent* output_change_event =
794 reinterpret_cast<XRROutputChangeNotifyEvent*>(xevent);
795 if ((output_change_event->connection == RR_Connected) ||
796 (output_change_event->connection == RR_Disconnected)) {
797 RecacheAndUseDefaultState();
798 CheckIsProjectingAndNotify();
799 }
800 // Ignore the case of RR_UnkownConnection.
801 }
802 }
803 return true;
804 }
805
806 void OutputConfigurator::CheckIsProjectingAndNotify() { 810 void OutputConfigurator::CheckIsProjectingAndNotify() {
807 // Determine if there is an "internal" output and how many outputs are 811 // Determine if there is an "internal" output and how many outputs are
808 // connected. 812 // connected.
809 bool has_internal_output = false; 813 bool has_internal_output = false;
810 int connected_output_count = 0; 814 int connected_output_count = 0;
811 for (int i = 0; i < output_count_; ++i) { 815 for (int i = 0; i < output_count_; ++i) {
812 if (output_cache_[i].is_connected) { 816 if (output_cache_[i].is_connected) {
813 connected_output_count += 1; 817 connected_output_count += 1;
814 has_internal_output |= output_cache_[i].is_internal; 818 has_internal_output |= output_cache_[i].is_internal;
815 } 819 }
(...skipping 12 matching lines...) Expand all
828 power_manager::kSetIsProjectingMethod); 832 power_manager::kSetIsProjectingMethod);
829 dbus::MessageWriter writer(&method_call); 833 dbus::MessageWriter writer(&method_call);
830 writer.AppendBool(is_projecting); 834 writer.AppendBool(is_projecting);
831 power_manager_proxy->CallMethod( 835 power_manager_proxy->CallMethod(
832 &method_call, 836 &method_call,
833 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, 837 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
834 dbus::ObjectProxy::EmptyResponseCallback()); 838 dbus::ObjectProxy::EmptyResponseCallback());
835 } 839 }
836 840
837 } // namespace chromeos 841 } // namespace chromeos
OLDNEW
« no previous file with comments | « chromeos/display/output_configurator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698