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

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

Issue 22605008: chromeos: Make OutputConfigurator save latest config. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix interpretation of XRRSetCrtcConfig return value Created 7 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
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/Xrandr.h> 8 #include <X11/extensions/Xrandr.h>
9 #include <X11/extensions/XInput2.h> 9 #include <X11/extensions/XInput2.h>
10 10
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
91 for (size_t i = 0; i < outputs.size(); ++i) 91 for (size_t i = 0; i < outputs.size(); ++i)
92 has_internal_output |= outputs[i].is_internal; 92 has_internal_output |= outputs[i].is_internal;
93 93
94 // "Projecting" is defined as having more than 1 output connected while at 94 // "Projecting" is defined as having more than 1 output connected while at
95 // least one of them is an internal output. 95 // least one of them is an internal output.
96 return has_internal_output && (connected_output_count > 1); 96 return has_internal_output && (connected_output_count > 1);
97 } 97 }
98 98
99 } // namespace 99 } // namespace
100 100
101 OutputConfigurator::CoordinateTransformation::CoordinateTransformation()
102 : x_scale(1.0),
103 x_offset(0.0),
104 y_scale(1.0),
105 y_offset(0.0) {}
106
101 OutputConfigurator::OutputSnapshot::OutputSnapshot() 107 OutputConfigurator::OutputSnapshot::OutputSnapshot()
102 : output(None), 108 : output(None),
103 crtc(None), 109 crtc(None),
104 current_mode(None), 110 current_mode(None),
105 native_mode(None), 111 native_mode(None),
106 mirror_mode(None), 112 mirror_mode(None),
107 selected_mode(None), 113 selected_mode(None),
114 x(0),
108 y(0), 115 y(0),
109 height(0),
110 is_internal(false), 116 is_internal(false),
111 is_aspect_preserving_scaling(false), 117 is_aspect_preserving_scaling(false),
112 touch_device_id(0), 118 touch_device_id(0),
113 display_id(0), 119 display_id(0),
114 has_display_id(false) {} 120 has_display_id(false) {}
115 121
116 OutputConfigurator::CoordinateTransformation::CoordinateTransformation()
117 : x_scale(1.0),
118 x_offset(0.0),
119 y_scale(1.0),
120 y_offset(0.0) {}
121
122 OutputConfigurator::CrtcConfig::CrtcConfig()
123 : crtc(None),
124 x(0),
125 y(0),
126 mode(None),
127 output(None) {}
128
129 OutputConfigurator::CrtcConfig::CrtcConfig(RRCrtc crtc,
130 int x, int y,
131 RRMode mode,
132 RROutput output)
133 : crtc(crtc),
134 x(x),
135 y(y),
136 mode(mode),
137 output(output) {}
138
139 bool OutputConfigurator::TestApi::SendOutputChangeEvents(bool connected) { 122 bool OutputConfigurator::TestApi::SendOutputChangeEvents(bool connected) {
140 XRRScreenChangeNotifyEvent screen_event; 123 XRRScreenChangeNotifyEvent screen_event;
141 memset(&screen_event, 0, sizeof(screen_event)); 124 memset(&screen_event, 0, sizeof(screen_event));
142 screen_event.type = xrandr_event_base_ + RRScreenChangeNotify; 125 screen_event.type = xrandr_event_base_ + RRScreenChangeNotify;
143 configurator_->Dispatch( 126 configurator_->Dispatch(
144 reinterpret_cast<const base::NativeEvent>(&screen_event)); 127 reinterpret_cast<const base::NativeEvent>(&screen_event));
145 128
146 XRROutputChangeNotifyEvent notify_event; 129 XRROutputChangeNotifyEvent notify_event;
147 memset(&notify_event, 0, sizeof(notify_event)); 130 memset(&notify_event, 0, sizeof(notify_event));
148 notify_event.type = xrandr_event_base_ + RRNotify; 131 notify_event.type = xrandr_event_base_ + RRNotify;
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after
411 } 394 }
412 395
413 bool OutputConfigurator::EnterState( 396 bool OutputConfigurator::EnterState(
414 OutputState output_state, 397 OutputState output_state,
415 DisplayPowerState power_state, 398 DisplayPowerState power_state,
416 const std::vector<OutputSnapshot>& outputs) { 399 const std::vector<OutputSnapshot>& outputs) {
417 std::vector<bool> output_power; 400 std::vector<bool> output_power;
418 int num_on_outputs = GetOutputPower(outputs, power_state, &output_power); 401 int num_on_outputs = GetOutputPower(outputs, power_state, &output_power);
419 VLOG(1) << "EnterState: output=" << OutputStateToString(output_state) 402 VLOG(1) << "EnterState: output=" << OutputStateToString(output_state)
420 << " power=" << DisplayPowerStateToString(power_state); 403 << " power=" << DisplayPowerStateToString(power_state);
404
405 // Framebuffer dimensions.
406 int width = 0, height = 0;
407 std::vector<OutputSnapshot> updated_outputs = outputs;
408
421 switch (output_state) { 409 switch (output_state) {
410 case STATE_INVALID:
411 NOTREACHED() << "Ignoring request to enter invalid state with "
412 << outputs.size() << " connected output(s)";
413 return false;
422 case STATE_HEADLESS: 414 case STATE_HEADLESS:
423 if (outputs.size() != 0) { 415 if (outputs.size() != 0) {
424 LOG(WARNING) << "Ignoring request to enter headless mode with " 416 LOG(WARNING) << "Ignoring request to enter headless mode with "
425 << outputs.size() << " connected output(s)"; 417 << outputs.size() << " connected output(s)";
426 return false; 418 return false;
427 } 419 }
428 break; 420 break;
429 case STATE_SINGLE: { 421 case STATE_SINGLE: {
430 // If there are multiple outputs connected, only one should be turned on. 422 // If there are multiple outputs connected, only one should be turned on.
431 if (outputs.size() != 1 && num_on_outputs != 1) { 423 if (outputs.size() != 1 && num_on_outputs != 1) {
432 LOG(WARNING) << "Ignoring request to enter single mode with " 424 LOG(WARNING) << "Ignoring request to enter single mode with "
433 << outputs.size() << " connected outputs and " 425 << outputs.size() << " connected outputs and "
434 << num_on_outputs << " turned on"; 426 << num_on_outputs << " turned on";
435 return false; 427 return false;
436 } 428 }
437 429
438 // Determine which output to use. 430 for (size_t i = 0; i < updated_outputs.size(); ++i) {
439 const OutputSnapshot& output = outputs.size() == 1 ? outputs[0] : 431 OutputSnapshot* output = &updated_outputs[i];
440 (output_power[0] ? outputs[0] : outputs[1]); 432 output->x = 0;
441 int width = 0, height = 0; 433 output->y = 0;
442 if (!delegate_->GetModeDetails( 434 output->current_mode = output_power[i] ? output->selected_mode : None;
443 output.selected_mode, &width, &height, NULL))
444 return false;
445 435
446 std::vector<CrtcConfig> configs(outputs.size()); 436 if (output_power[i] || outputs.size() == 1) {
447 for (size_t i = 0; i < outputs.size(); ++i) { 437 if (!delegate_->GetModeDetails(
448 configs[i] = CrtcConfig( 438 output->selected_mode, &width, &height, NULL))
449 outputs[i].crtc, 0, 0, 439 return false;
450 output_power[i] ? outputs[i].selected_mode : None,
451 outputs[i].output);
452 }
453 delegate_->CreateFrameBuffer(width, height, configs);
454
455 for (size_t i = 0; i < outputs.size(); ++i) {
456 delegate_->ConfigureCrtc(&configs[i]);
457 if (outputs[i].touch_device_id) {
458 delegate_->ConfigureCTM(outputs[i].touch_device_id,
459 CoordinateTransformation());
460 } 440 }
461 } 441 }
462 break; 442 break;
463 } 443 }
464 case STATE_DUAL_MIRROR: { 444 case STATE_DUAL_MIRROR: {
465 if (outputs.size() != 2 || (num_on_outputs != 0 && num_on_outputs != 2)) { 445 if (outputs.size() != 2 || (num_on_outputs != 0 && num_on_outputs != 2)) {
466 LOG(WARNING) << "Ignoring request to enter mirrored mode with " 446 LOG(WARNING) << "Ignoring request to enter mirrored mode with "
467 << outputs.size() << " connected output(s) and " 447 << outputs.size() << " connected output(s) and "
468 << num_on_outputs << " turned on"; 448 << num_on_outputs << " turned on";
469 return false; 449 return false;
470 } 450 }
471 451
472 int width = 0, height = 0;
473 if (!delegate_->GetModeDetails( 452 if (!delegate_->GetModeDetails(
474 outputs[0].mirror_mode, &width, &height, NULL)) { 453 outputs[0].mirror_mode, &width, &height, NULL))
475 return false; 454 return false;
476 }
477
478 std::vector<CrtcConfig> configs(outputs.size());
479 for (size_t i = 0; i < outputs.size(); ++i) {
480 configs[i] = CrtcConfig(
481 outputs[i].crtc, 0, 0,
482 output_power[i] ? outputs[i].mirror_mode : None,
483 outputs[i].output);
484 }
485 delegate_->CreateFrameBuffer(width, height, configs);
486 455
487 for (size_t i = 0; i < outputs.size(); ++i) { 456 for (size_t i = 0; i < outputs.size(); ++i) {
488 delegate_->ConfigureCrtc(&configs[i]); 457 OutputSnapshot* output = &updated_outputs[i];
489 if (outputs[i].touch_device_id) { 458 output->x = 0;
490 CoordinateTransformation ctm; 459 output->y = 0;
460 output->current_mode = output_power[i] ? output->mirror_mode : None;
461 if (output->touch_device_id) {
491 // CTM needs to be calculated if aspect preserving scaling is used. 462 // CTM needs to be calculated if aspect preserving scaling is used.
492 // Otherwise, assume it is full screen, and use identity CTM. 463 // Otherwise, assume it is full screen, and use identity CTM.
493 if (outputs[i].mirror_mode != outputs[i].native_mode && 464 if (output->mirror_mode != output->native_mode &&
494 outputs[i].is_aspect_preserving_scaling) { 465 output->is_aspect_preserving_scaling) {
495 ctm = GetMirrorModeCTM(&outputs[i]); 466 output->transform = GetMirrorModeCTM(output);
496 mirrored_display_area_ratio_map_[outputs[i].touch_device_id] = 467 mirrored_display_area_ratio_map_[output->touch_device_id] =
497 GetMirroredDisplayAreaRatio(&outputs[i]); 468 GetMirroredDisplayAreaRatio(output);
498 } 469 }
499 delegate_->ConfigureCTM(outputs[i].touch_device_id, ctm);
500 } 470 }
501 } 471 }
502 break; 472 break;
503 } 473 }
504 case STATE_DUAL_EXTENDED: { 474 case STATE_DUAL_EXTENDED: {
505 if (outputs.size() != 2 || (num_on_outputs != 0 && num_on_outputs != 2)) { 475 if (outputs.size() != 2 || (num_on_outputs != 0 && num_on_outputs != 2)) {
506 LOG(WARNING) << "Ignoring request to enter extended mode with " 476 LOG(WARNING) << "Ignoring request to enter extended mode with "
507 << outputs.size() << " connected output(s) and " 477 << outputs.size() << " connected output(s) and "
508 << num_on_outputs << " turned on"; 478 << num_on_outputs << " turned on";
509 return false; 479 return false;
510 } 480 }
511 481
512 // Pairs are [width, height] corresponding to the given output's mode. 482 // Pairs are [width, height] corresponding to the given output's mode.
513 std::vector<std::pair<int, int> > mode_sizes(outputs.size()); 483 std::vector<std::pair<int, int> > mode_sizes(outputs.size());
514 std::vector<CrtcConfig> configs(outputs.size());
515 int width = 0, height = 0;
516 484
517 for (size_t i = 0; i < outputs.size(); ++i) { 485 for (size_t i = 0; i < outputs.size(); ++i) {
518 if (!delegate_->GetModeDetails(outputs[i].selected_mode, 486 if (!delegate_->GetModeDetails(outputs[i].selected_mode,
519 &(mode_sizes[i].first), &(mode_sizes[i].second), NULL)) { 487 &(mode_sizes[i].first), &(mode_sizes[i].second), NULL)) {
520 return false; 488 return false;
521 } 489 }
522 490
523 configs[i] = CrtcConfig( 491 OutputSnapshot* output = &updated_outputs[i];
524 outputs[i].crtc, 0, (height ? height + kVerticalGap : 0), 492 output->x = 0;
525 output_power[i] ? outputs[i].selected_mode : None, 493 output->y = height ? height + kVerticalGap : 0;
526 outputs[i].output); 494 output->current_mode = output_power[i] ? output->selected_mode : None;
527 495
528 // Retain the full screen size even if all outputs are off so the 496 // Retain the full screen size even if all outputs are off so the
529 // same desktop configuration can be restored when the outputs are 497 // same desktop configuration can be restored when the outputs are
530 // turned back on. 498 // turned back on.
531 width = std::max<int>(width, mode_sizes[i].first); 499 width = std::max<int>(width, mode_sizes[i].first);
532 height += (height ? kVerticalGap : 0) + mode_sizes[i].second; 500 height += (height ? kVerticalGap : 0) + mode_sizes[i].second;
533 } 501 }
534 502
535 delegate_->CreateFrameBuffer(width, height, configs);
536
537 for (size_t i = 0; i < outputs.size(); ++i) { 503 for (size_t i = 0; i < outputs.size(); ++i) {
538 delegate_->ConfigureCrtc(&configs[i]); 504 OutputSnapshot* output = &updated_outputs[i];
539 if (outputs[i].touch_device_id) { 505 if (output->touch_device_id) {
540 CoordinateTransformation ctm; 506 CoordinateTransformation* ctm = &(output->transform);
541 ctm.x_scale = static_cast<float>(mode_sizes[i].first) / width; 507 ctm->x_scale = static_cast<float>(mode_sizes[i].first) / width;
542 ctm.x_offset = static_cast<float>(configs[i].x) / width; 508 ctm->x_offset = static_cast<float>(output->x) / width;
543 ctm.y_scale = static_cast<float>(mode_sizes[i].second) / height; 509 ctm->y_scale = static_cast<float>(mode_sizes[i].second) / height;
544 ctm.y_offset = static_cast<float>(configs[i].y) / height; 510 ctm->y_offset = static_cast<float>(output->y) / height;
545 delegate_->ConfigureCTM(outputs[i].touch_device_id, ctm);
546 } 511 }
547 } 512 }
548 break; 513 break;
549 } 514 }
550 default: 515 }
551 NOTREACHED() << "Got request to enter output state " << output_state 516
552 << " with " << outputs.size() << " output(s)"; 517 // Finally, apply the desired changes.
553 return false; 518 DCHECK_EQ(outputs.size(), updated_outputs.size());
519 if (!outputs.empty()) {
520 delegate_->CreateFrameBuffer(width, height, updated_outputs);
521 for (size_t i = 0; i < outputs.size(); ++i) {
522 const OutputSnapshot& output = updated_outputs[i];
523 if (delegate_->ConfigureCrtc(output.crtc, output.current_mode,
524 output.output, output.x, output.y)) {
525 if (output.touch_device_id)
526 delegate_->ConfigureCTM(output.touch_device_id, output.transform);
527 } else {
528 LOG(WARNING) << "Unable to configure CRTC " << output.crtc << ":"
529 << " mode=" << output.current_mode
530 << " output=" << output.output
531 << " x=" << output.x
532 << " y=" << output.y;
533 updated_outputs[i] = outputs[i];
534 }
535 }
554 } 536 }
555 537
556 output_state_ = output_state; 538 output_state_ = output_state;
557 power_state_ = power_state; 539 power_state_ = power_state;
540 cached_outputs_ = updated_outputs;
558 return true; 541 return true;
559 } 542 }
560 543
561 OutputState OutputConfigurator::GetOutputState( 544 OutputState OutputConfigurator::GetOutputState(
562 const std::vector<OutputSnapshot>& outputs, 545 const std::vector<OutputSnapshot>& outputs,
563 DisplayPowerState power_state) const { 546 DisplayPowerState power_state) const {
564 int num_on_outputs = GetOutputPower(outputs, power_state, NULL); 547 int num_on_outputs = GetOutputPower(outputs, power_state, NULL);
565 switch (outputs.size()) { 548 switch (outputs.size()) {
566 case 0: 549 case 0:
567 return STATE_HEADLESS; 550 return STATE_HEADLESS;
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
648 float width_ratio = static_cast<float>(mirror_mode_width) / 631 float width_ratio = static_cast<float>(mirror_mode_width) /
649 static_cast<float>(native_mode_width); 632 static_cast<float>(native_mode_width);
650 float height_ratio = static_cast<float>(mirror_mode_height) / 633 float height_ratio = static_cast<float>(mirror_mode_height) /
651 static_cast<float>(native_mode_height); 634 static_cast<float>(native_mode_height);
652 635
653 area_ratio = width_ratio * height_ratio; 636 area_ratio = width_ratio * height_ratio;
654 return area_ratio; 637 return area_ratio;
655 } 638 }
656 639
657 } // namespace chromeos 640 } // namespace chromeos
OLDNEW
« no previous file with comments | « chromeos/display/output_configurator.h ('k') | chromeos/display/output_configurator_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698