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

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: minor updates 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) {
422 case STATE_HEADLESS: 410 case STATE_HEADLESS:
oshima 2013/08/08 01:19:49 do you think we can nuke STATE_HEADLESS?
Daniel Erat 2013/08/08 16:07:37 What's the alternate proposal? Do you think we sho
oshima 2013/08/08 16:52:09 Exit early if there is no output and just leave th
423 if (outputs.size() != 0) { 411 if (outputs.size() != 0) {
424 LOG(WARNING) << "Ignoring request to enter headless mode with " 412 LOG(WARNING) << "Ignoring request to enter headless mode with "
425 << outputs.size() << " connected output(s)"; 413 << outputs.size() << " connected output(s)";
426 return false; 414 return false;
427 } 415 }
428 break; 416 break;
429 case STATE_SINGLE: { 417 case STATE_SINGLE: {
430 // If there are multiple outputs connected, only one should be turned on. 418 // If there are multiple outputs connected, only one should be turned on.
431 if (outputs.size() != 1 && num_on_outputs != 1) { 419 if (outputs.size() != 1 && num_on_outputs != 1) {
432 LOG(WARNING) << "Ignoring request to enter single mode with " 420 LOG(WARNING) << "Ignoring request to enter single mode with "
433 << outputs.size() << " connected outputs and " 421 << outputs.size() << " connected outputs and "
434 << num_on_outputs << " turned on"; 422 << num_on_outputs << " turned on";
435 return false; 423 return false;
436 } 424 }
437 425
438 // Determine which output to use. 426 for (size_t i = 0; i < updated_outputs.size(); ++i) {
439 const OutputSnapshot& output = outputs.size() == 1 ? outputs[0] : 427 OutputSnapshot* output = &updated_outputs[i];
440 (output_power[0] ? outputs[0] : outputs[1]); 428 output->x = 0;
441 int width = 0, height = 0; 429 output->y = 0;
442 if (!delegate_->GetModeDetails( 430 output->current_mode = output_power[i] ? output->selected_mode : None;
443 output.selected_mode, &width, &height, NULL))
444 return false;
445 431
446 std::vector<CrtcConfig> configs(outputs.size()); 432 if (output_power[i] || outputs.size() == 1) {
447 for (size_t i = 0; i < outputs.size(); ++i) { 433 if (!delegate_->GetModeDetails(
448 configs[i] = CrtcConfig( 434 output->selected_mode, &width, &height, NULL))
449 outputs[i].crtc, 0, 0, 435 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 } 436 }
461 } 437 }
462 break; 438 break;
463 } 439 }
464 case STATE_DUAL_MIRROR: { 440 case STATE_DUAL_MIRROR: {
465 if (outputs.size() != 2 || (num_on_outputs != 0 && num_on_outputs != 2)) { 441 if (outputs.size() != 2 || (num_on_outputs != 0 && num_on_outputs != 2)) {
466 LOG(WARNING) << "Ignoring request to enter mirrored mode with " 442 LOG(WARNING) << "Ignoring request to enter mirrored mode with "
467 << outputs.size() << " connected output(s) and " 443 << outputs.size() << " connected output(s) and "
468 << num_on_outputs << " turned on"; 444 << num_on_outputs << " turned on";
469 return false; 445 return false;
470 } 446 }
471 447
472 int width = 0, height = 0;
473 if (!delegate_->GetModeDetails( 448 if (!delegate_->GetModeDetails(
474 outputs[0].mirror_mode, &width, &height, NULL)) { 449 outputs[0].mirror_mode, &width, &height, NULL))
475 return false; 450 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 451
487 for (size_t i = 0; i < outputs.size(); ++i) { 452 for (size_t i = 0; i < outputs.size(); ++i) {
488 delegate_->ConfigureCrtc(&configs[i]); 453 OutputSnapshot* output = &updated_outputs[i];
489 if (outputs[i].touch_device_id) { 454 output->x = 0;
490 CoordinateTransformation ctm; 455 output->y = 0;
456 output->current_mode = output_power[i] ? output->mirror_mode : None;
457 if (output->touch_device_id) {
491 // CTM needs to be calculated if aspect preserving scaling is used. 458 // CTM needs to be calculated if aspect preserving scaling is used.
492 // Otherwise, assume it is full screen, and use identity CTM. 459 // Otherwise, assume it is full screen, and use identity CTM.
493 if (outputs[i].mirror_mode != outputs[i].native_mode && 460 if (output->mirror_mode != output->native_mode &&
494 outputs[i].is_aspect_preserving_scaling) { 461 output->is_aspect_preserving_scaling) {
495 ctm = GetMirrorModeCTM(&outputs[i]); 462 output->transform = GetMirrorModeCTM(output);
496 mirrored_display_area_ratio_map_[outputs[i].touch_device_id] = 463 mirrored_display_area_ratio_map_[output->touch_device_id] =
497 GetMirroredDisplayAreaRatio(&outputs[i]); 464 GetMirroredDisplayAreaRatio(output);
498 } 465 }
499 delegate_->ConfigureCTM(outputs[i].touch_device_id, ctm);
500 } 466 }
501 } 467 }
502 break; 468 break;
503 } 469 }
504 case STATE_DUAL_EXTENDED: { 470 case STATE_DUAL_EXTENDED: {
505 if (outputs.size() != 2 || (num_on_outputs != 0 && num_on_outputs != 2)) { 471 if (outputs.size() != 2 || (num_on_outputs != 0 && num_on_outputs != 2)) {
506 LOG(WARNING) << "Ignoring request to enter extended mode with " 472 LOG(WARNING) << "Ignoring request to enter extended mode with "
507 << outputs.size() << " connected output(s) and " 473 << outputs.size() << " connected output(s) and "
508 << num_on_outputs << " turned on"; 474 << num_on_outputs << " turned on";
509 return false; 475 return false;
510 } 476 }
511 477
512 // Pairs are [width, height] corresponding to the given output's mode. 478 // Pairs are [width, height] corresponding to the given output's mode.
513 std::vector<std::pair<int, int> > mode_sizes(outputs.size()); 479 std::vector<std::pair<int, int> > mode_sizes(outputs.size());
514 std::vector<CrtcConfig> configs(outputs.size());
515 int width = 0, height = 0;
516 480
517 for (size_t i = 0; i < outputs.size(); ++i) { 481 for (size_t i = 0; i < outputs.size(); ++i) {
518 if (!delegate_->GetModeDetails(outputs[i].selected_mode, 482 if (!delegate_->GetModeDetails(outputs[i].selected_mode,
519 &(mode_sizes[i].first), &(mode_sizes[i].second), NULL)) { 483 &(mode_sizes[i].first), &(mode_sizes[i].second), NULL)) {
520 return false; 484 return false;
521 } 485 }
522 486
523 configs[i] = CrtcConfig( 487 OutputSnapshot* output = &updated_outputs[i];
524 outputs[i].crtc, 0, (height ? height + kVerticalGap : 0), 488 output->x = 0;
525 output_power[i] ? outputs[i].selected_mode : None, 489 output->y = height ? height + kVerticalGap : 0;
526 outputs[i].output); 490 output->current_mode = output_power[i] ? output->selected_mode : None;
527 491
528 // Retain the full screen size even if all outputs are off so the 492 // Retain the full screen size even if all outputs are off so the
529 // same desktop configuration can be restored when the outputs are 493 // same desktop configuration can be restored when the outputs are
530 // turned back on. 494 // turned back on.
531 width = std::max<int>(width, mode_sizes[i].first); 495 width = std::max<int>(width, mode_sizes[i].first);
532 height += (height ? kVerticalGap : 0) + mode_sizes[i].second; 496 height += (height ? kVerticalGap : 0) + mode_sizes[i].second;
533 } 497 }
534 498
535 delegate_->CreateFrameBuffer(width, height, configs);
536
537 for (size_t i = 0; i < outputs.size(); ++i) { 499 for (size_t i = 0; i < outputs.size(); ++i) {
538 delegate_->ConfigureCrtc(&configs[i]); 500 OutputSnapshot* output = &updated_outputs[i];
539 if (outputs[i].touch_device_id) { 501 if (output->touch_device_id) {
540 CoordinateTransformation ctm; 502 CoordinateTransformation* ctm = &(output->transform);
541 ctm.x_scale = static_cast<float>(mode_sizes[i].first) / width; 503 ctm->x_scale = static_cast<float>(mode_sizes[i].first) / width;
542 ctm.x_offset = static_cast<float>(configs[i].x) / width; 504 ctm->x_offset = static_cast<float>(output->x) / width;
543 ctm.y_scale = static_cast<float>(mode_sizes[i].second) / height; 505 ctm->y_scale = static_cast<float>(mode_sizes[i].second) / height;
544 ctm.y_offset = static_cast<float>(configs[i].y) / height; 506 ctm->y_offset = static_cast<float>(output->y) / height;
545 delegate_->ConfigureCTM(outputs[i].touch_device_id, ctm);
546 } 507 }
547 } 508 }
548 break; 509 break;
549 } 510 }
550 default: 511 default:
551 NOTREACHED() << "Got request to enter output state " << output_state 512 NOTREACHED() << "Got request to enter output state " << output_state
552 << " with " << outputs.size() << " output(s)"; 513 << " with " << outputs.size() << " output(s)";
553 return false; 514 return false;
oshima 2013/08/08 01:19:49 let's remove default because output_state is enum.
Daniel Erat 2013/08/08 16:07:37 It was covering STATE_INVALID. I've added a separa
554 } 515 }
555 516
517 // Finally, apply the desired changes.
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 }
536 }
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