OLD | NEW |
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 <cmath> | 7 #include <cmath> |
8 | 8 |
9 #include <X11/Xatom.h> | 9 #include <X11/Xatom.h> |
10 #include <X11/Xlib.h> | 10 #include <X11/Xlib.h> |
(...skipping 520 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
531 } // namespace | 531 } // namespace |
532 | 532 |
533 OutputConfigurator::OutputConfigurator() | 533 OutputConfigurator::OutputConfigurator() |
534 // If we aren't running on ChromeOS (like linux desktop), | 534 // If we aren't running on ChromeOS (like linux desktop), |
535 // don't try to configure display. | 535 // don't try to configure display. |
536 : configure_display_(base::chromeos::IsRunningOnChromeOS()), | 536 : configure_display_(base::chromeos::IsRunningOnChromeOS()), |
537 is_panel_fitting_enabled_(false), | 537 is_panel_fitting_enabled_(false), |
538 connected_output_count_(0), | 538 connected_output_count_(0), |
539 xrandr_event_base_(0), | 539 xrandr_event_base_(0), |
540 output_state_(STATE_INVALID), | 540 output_state_(STATE_INVALID), |
| 541 power_state_(DISPLAY_POWER_ALL_ON), |
541 mirror_mode_will_preserve_aspect_(false), | 542 mirror_mode_will_preserve_aspect_(false), |
542 mirror_mode_preserved_aspect_(false), | 543 mirror_mode_preserved_aspect_(false), |
543 last_enter_state_time_() { | 544 last_enter_state_time_() { |
544 } | 545 } |
545 | 546 |
546 OutputConfigurator::~OutputConfigurator() { | 547 OutputConfigurator::~OutputConfigurator() { |
547 RecordPreviousStateUMA(); | 548 RecordPreviousStateUMA(); |
548 } | 549 } |
549 | 550 |
550 void OutputConfigurator::Init(bool is_panel_fitting_enabled, | 551 void OutputConfigurator::Init(bool is_panel_fitting_enabled, |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
587 } | 588 } |
588 | 589 |
589 output_state_ = InferCurrentState(display, screen, outputs); | 590 output_state_ = InferCurrentState(display, screen, outputs); |
590 // Ensure that we are in a supported state with all connected displays powered | 591 // Ensure that we are in a supported state with all connected displays powered |
591 // on. | 592 // on. |
592 OutputState starting_state = GetNextState(display, | 593 OutputState starting_state = GetNextState(display, |
593 screen, | 594 screen, |
594 STATE_INVALID, | 595 STATE_INVALID, |
595 outputs); | 596 outputs); |
596 if (output_state_ != starting_state && | 597 if (output_state_ != starting_state && |
597 EnterState(display, | 598 EnterState(display, screen, window, starting_state, power_state_, |
598 screen, | |
599 window, | |
600 starting_state, | |
601 outputs)) { | 599 outputs)) { |
602 output_state_ = starting_state; | 600 output_state_ = starting_state; |
603 } | 601 } |
604 bool is_projecting = IsProjecting(outputs); | 602 bool is_projecting = IsProjecting(outputs); |
605 | 603 |
606 // Find xrandr_event_base_ since we need it to interpret events, later. | 604 // Find xrandr_event_base_ since we need it to interpret events, later. |
607 int error_base_ignored = 0; | 605 int error_base_ignored = 0; |
608 XRRQueryExtension(display, &xrandr_event_base_, &error_base_ignored); | 606 XRRQueryExtension(display, &xrandr_event_base_, &error_base_ignored); |
609 | 607 |
610 // Force the DPMS on chrome startup as the driver doesn't always detect | 608 // Force the DPMS on chrome startup as the driver doesn't always detect |
(...skipping 25 matching lines...) Expand all Loading... |
636 XGrabServer(display); | 634 XGrabServer(display); |
637 Window window = DefaultRootWindow(display); | 635 Window window = DefaultRootWindow(display); |
638 XRRScreenResources* screen = GetScreenResourcesAndRecordUMA(display, window); | 636 XRRScreenResources* screen = GetScreenResourcesAndRecordUMA(display, window); |
639 CHECK(screen != NULL); | 637 CHECK(screen != NULL); |
640 | 638 |
641 std::vector<OutputSnapshot> outputs = GetDualOutputs(display, screen); | 639 std::vector<OutputSnapshot> outputs = GetDualOutputs(display, screen); |
642 connected_output_count_ = outputs.size(); | 640 connected_output_count_ = outputs.size(); |
643 OutputState original = InferCurrentState(display, screen, outputs); | 641 OutputState original = InferCurrentState(display, screen, outputs); |
644 OutputState next_state = GetNextState(display, screen, original, outputs); | 642 OutputState next_state = GetNextState(display, screen, original, outputs); |
645 if (original != next_state && | 643 if (original != next_state && |
646 EnterState(display, screen, window, next_state, outputs)) { | 644 EnterState(display, screen, window, next_state, power_state_, outputs)) { |
647 did_change = true; | 645 did_change = true; |
648 } | 646 } |
649 // We have seen cases where the XRandR data can get out of sync with our own | 647 // We have seen cases where the XRandR data can get out of sync with our own |
650 // cache so over-write it with whatever we detected, even if we didn't think | 648 // cache so over-write it with whatever we detected, even if we didn't think |
651 // anything changed. | 649 // anything changed. |
652 output_state_ = next_state; | 650 output_state_ = next_state; |
653 | 651 |
654 XRRFreeScreenResources(screen); | 652 XRRFreeScreenResources(screen); |
655 XUngrabServer(display); | 653 XUngrabServer(display); |
656 | 654 |
657 if (did_change) { | 655 if (did_change) { |
658 NotifyOnDisplayChanged(); | 656 NotifyOnDisplayChanged(); |
659 } else { | 657 } else { |
660 FOR_EACH_OBSERVER( | 658 FOR_EACH_OBSERVER( |
661 Observer, observers_, OnDisplayModeChangeFailed(next_state)); | 659 Observer, observers_, OnDisplayModeChangeFailed(next_state)); |
662 } | 660 } |
663 return did_change; | 661 return did_change; |
664 } | 662 } |
665 | 663 |
666 bool OutputConfigurator::ScreenPowerSet(bool power_on, bool all_displays) { | 664 bool OutputConfigurator::SetDisplayPower(DisplayPowerState power_state, |
667 TRACE_EVENT0("chromeos", "OutputConfigurator::ScreenPowerSet"); | 665 bool force_probe) { |
668 VLOG(1) << "OutputConfigurator::SetScreensOn " << power_on | 666 TRACE_EVENT0("chromeos", "OutputConfigurator::SetDisplayPower"); |
669 << " all displays " << all_displays; | 667 VLOG(1) << "OutputConfigurator::SetDisplayPower: power_state=" << power_state |
| 668 << " force_probe=" << force_probe; |
| 669 |
670 if (!configure_display_) | 670 if (!configure_display_) |
671 return false; | 671 return false; |
| 672 if (power_state == power_state_ && !force_probe) |
| 673 return true; |
672 | 674 |
673 bool success = false; | |
674 Display* display = base::MessagePumpAuraX11::GetDefaultXDisplay(); | 675 Display* display = base::MessagePumpAuraX11::GetDefaultXDisplay(); |
675 CHECK(display != NULL); | 676 CHECK(display); |
676 XGrabServer(display); | 677 XGrabServer(display); |
677 Window window = DefaultRootWindow(display); | 678 Window window = DefaultRootWindow(display); |
678 XRRScreenResources* screen = GetScreenResourcesAndRecordUMA(display, window); | 679 XRRScreenResources* screen = GetScreenResourcesAndRecordUMA(display, window); |
679 CHECK(screen != NULL); | 680 CHECK(screen); |
680 | |
681 std::vector<OutputSnapshot> outputs = GetDualOutputs(display, screen); | 681 std::vector<OutputSnapshot> outputs = GetDualOutputs(display, screen); |
682 connected_output_count_ = outputs.size(); | 682 connected_output_count_ = outputs.size(); |
683 | 683 |
684 if (all_displays && power_on) { | 684 if (EnterState(display, screen, window, output_state_, power_state, |
685 // Resume all displays using the current state. | 685 outputs)) { |
686 if (EnterState(display, screen, window, output_state_, outputs)) { | 686 power_state_ = power_state; |
687 // Force the DPMS on since the driver doesn't always detect that it should | 687 if (power_state != DISPLAY_POWER_ALL_OFF) { |
688 // turn on. This is needed when coming back from idle suspend. | 688 // Force the DPMS on since the driver doesn't always detect that it |
| 689 // should turn on. This is needed when coming back from idle suspend. |
689 CHECK(DPMSEnable(display)); | 690 CHECK(DPMSEnable(display)); |
690 CHECK(DPMSForceLevel(display, DPMSModeOn)); | 691 CHECK(DPMSForceLevel(display, DPMSModeOn)); |
691 | |
692 XRRFreeScreenResources(screen); | |
693 XUngrabServer(display); | |
694 return true; | |
695 } | 692 } |
696 } | 693 } |
697 | 694 |
698 CrtcConfig config; | |
699 config.crtc = None; | |
700 // Set the CRTCs based on whether we want to turn the power on or off and | |
701 // select the outputs to operate on by name or all_displays. | |
702 for (int i = 0; i < connected_output_count_; ++i) { | |
703 if (all_displays || outputs[i].is_internal || power_on) { | |
704 config.x = 0; | |
705 config.y = outputs[i].y; | |
706 config.output = outputs[i].output; | |
707 config.mode = None; | |
708 if (power_on) { | |
709 config.mode = (output_state_ == STATE_DUAL_MIRROR) ? | |
710 outputs[i].mirror_mode : outputs[i].native_mode; | |
711 } else if (connected_output_count_ > 1 && !all_displays && | |
712 outputs[i].is_internal) { | |
713 // Workaround for crbug.com/148365: leave internal display in native | |
714 // mode so user can move cursor (and hence windows) onto internal | |
715 // display even when dimmed | |
716 config.mode = outputs[i].native_mode; | |
717 } | |
718 config.crtc = GetNextCrtcAfter(display, screen, config.output, | |
719 config.crtc); | |
720 | |
721 ConfigureCrtc(display, screen, &config); | |
722 success = true; | |
723 } | |
724 } | |
725 | |
726 // Force the DPMS on since the driver doesn't always detect that it should | |
727 // turn on. This is needed when coming back from idle suspend. | |
728 if (power_on) { | |
729 CHECK(DPMSEnable(display)); | |
730 CHECK(DPMSForceLevel(display, DPMSModeOn)); | |
731 } | |
732 | |
733 XRRFreeScreenResources(screen); | 695 XRRFreeScreenResources(screen); |
734 XUngrabServer(display); | 696 XUngrabServer(display); |
735 | 697 |
736 return success; | 698 return true; |
737 } | 699 } |
738 | 700 |
739 bool OutputConfigurator::SetDisplayMode(OutputState new_state) { | 701 bool OutputConfigurator::SetDisplayMode(OutputState new_state) { |
740 TRACE_EVENT0("chromeos", "OutputConfigurator::SetDisplayMode"); | 702 TRACE_EVENT0("chromeos", "OutputConfigurator::SetDisplayMode"); |
741 if (output_state_ == STATE_INVALID || | 703 if (output_state_ == STATE_INVALID || |
742 output_state_ == STATE_HEADLESS || | 704 output_state_ == STATE_HEADLESS || |
743 output_state_ == STATE_SINGLE) | 705 output_state_ == STATE_SINGLE) |
744 return false; | 706 return false; |
745 | 707 |
746 if (output_state_ == new_state) | 708 if (output_state_ == new_state) |
747 return true; | 709 return true; |
748 | 710 |
749 Display* display = base::MessagePumpAuraX11::GetDefaultXDisplay(); | 711 Display* display = base::MessagePumpAuraX11::GetDefaultXDisplay(); |
750 CHECK(display != NULL); | 712 CHECK(display != NULL); |
751 XGrabServer(display); | 713 XGrabServer(display); |
752 Window window = DefaultRootWindow(display); | 714 Window window = DefaultRootWindow(display); |
753 XRRScreenResources* screen = GetScreenResourcesAndRecordUMA(display, window); | 715 XRRScreenResources* screen = GetScreenResourcesAndRecordUMA(display, window); |
754 CHECK(screen != NULL); | 716 CHECK(screen != NULL); |
755 | 717 |
756 std::vector<OutputSnapshot> outputs = GetDualOutputs(display, screen); | 718 std::vector<OutputSnapshot> outputs = GetDualOutputs(display, screen); |
757 connected_output_count_ = outputs.size(); | 719 connected_output_count_ = outputs.size(); |
758 if (EnterState(display, screen, window, new_state, outputs)) | 720 if (EnterState(display, screen, window, new_state, power_state_, outputs)) |
759 output_state_ = new_state; | 721 output_state_ = new_state; |
760 | 722 |
761 XRRFreeScreenResources(screen); | 723 XRRFreeScreenResources(screen); |
762 XUngrabServer(display); | 724 XUngrabServer(display); |
763 | 725 |
764 if (output_state_ == new_state) { | 726 if (output_state_ == new_state) { |
765 NotifyOnDisplayChanged(); | 727 NotifyOnDisplayChanged(); |
766 } else { | 728 } else { |
767 FOR_EACH_OBSERVER( | 729 FOR_EACH_OBSERVER( |
768 Observer, observers_, OnDisplayModeChangeFailed(new_state)); | 730 Observer, observers_, OnDisplayModeChangeFailed(new_state)); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
822 std::vector<OutputSnapshot> outputs = GetDualOutputs(display, screen); | 784 std::vector<OutputSnapshot> outputs = GetDualOutputs(display, screen); |
823 int new_output_count = outputs.size(); | 785 int new_output_count = outputs.size(); |
824 // Don't skip even if the output counts didn't change because | 786 // Don't skip even if the output counts didn't change because |
825 // a display might have been swapped during the suspend. | 787 // a display might have been swapped during the suspend. |
826 connected_output_count_ = new_output_count; | 788 connected_output_count_ = new_output_count; |
827 OutputState new_state = | 789 OutputState new_state = |
828 GetNextState(display, screen, STATE_INVALID, outputs); | 790 GetNextState(display, screen, STATE_INVALID, outputs); |
829 // When a display was swapped, the state moves from | 791 // When a display was swapped, the state moves from |
830 // STATE_DUAL_EXTENDED to STATE_DUAL_EXTENDED, so don't rely on | 792 // STATE_DUAL_EXTENDED to STATE_DUAL_EXTENDED, so don't rely on |
831 // the state chagne to tell if it was successful. | 793 // the state chagne to tell if it was successful. |
832 bool success = EnterState(display, screen, window, new_state, outputs); | 794 bool success = |
| 795 EnterState(display, screen, window, new_state, power_state_, outputs); |
833 bool is_projecting = IsProjecting(outputs); | 796 bool is_projecting = IsProjecting(outputs); |
834 XRRFreeScreenResources(screen); | 797 XRRFreeScreenResources(screen); |
835 XUngrabServer(display); | 798 XUngrabServer(display); |
836 | 799 |
837 if (success) { | 800 if (success) { |
838 output_state_ = new_state; | 801 output_state_ = new_state; |
839 NotifyOnDisplayChanged(); | 802 NotifyOnDisplayChanged(); |
840 } else { | 803 } else { |
841 FOR_EACH_OBSERVER( | 804 FOR_EACH_OBSERVER( |
842 Observer, observers_, OnDisplayModeChangeFailed(new_state)); | 805 Observer, observers_, OnDisplayModeChangeFailed(new_state)); |
843 } | 806 } |
844 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()-> | 807 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()-> |
845 SetIsProjecting(is_projecting); | 808 SetIsProjecting(is_projecting); |
846 } | 809 } |
847 | 810 |
848 void OutputConfigurator::AddObserver(Observer* observer) { | 811 void OutputConfigurator::AddObserver(Observer* observer) { |
849 observers_.AddObserver(observer); | 812 observers_.AddObserver(observer); |
850 } | 813 } |
851 | 814 |
852 void OutputConfigurator::RemoveObserver(Observer* observer) { | 815 void OutputConfigurator::RemoveObserver(Observer* observer) { |
853 observers_.RemoveObserver(observer); | 816 observers_.RemoveObserver(observer); |
854 } | 817 } |
855 | 818 |
856 // static | 819 // static |
857 bool OutputConfigurator::IsInternalOutputName(const std::string& name) { | 820 bool OutputConfigurator::IsInternalOutputName(const std::string& name) { |
858 return name.find(kInternal_LVDS) == 0 || name.find(kInternal_eDP) == 0; | 821 return name.find(kInternal_LVDS) == 0 || name.find(kInternal_eDP) == 0; |
859 } | 822 } |
860 | 823 |
861 void OutputConfigurator::SuspendDisplays() { | 824 void OutputConfigurator::SuspendDisplays() { |
862 // Turn displays on before suspend. At this point, the backlight is off, | 825 // Turn internal displays on before suspend. At this point, the backlight |
863 // so we turn on the internal display so that we can resume directly into | 826 // is off, so we turn on the internal display so that we can resume |
864 // "on" state. This greatly reduces resume times. | 827 // directly into "on" state. This greatly reduces resume times. |
865 ScreenPowerSet(true, true); | 828 SetDisplayPower(DISPLAY_POWER_INTERNAL_ON_EXTERNAL_OFF, false); |
| 829 |
866 // We need to make sure that the monitor configuration we just did actually | 830 // We need to make sure that the monitor configuration we just did actually |
867 // completes before we return, because otherwise the X message could be | 831 // completes before we return, because otherwise the X message could be |
868 // racing with the HandleSuspendReadiness message. | 832 // racing with the HandleSuspendReadiness message. |
869 XSync(base::MessagePumpAuraX11::GetDefaultXDisplay(), 0); | 833 XSync(base::MessagePumpAuraX11::GetDefaultXDisplay(), 0); |
870 } | 834 } |
871 | 835 |
| 836 void OutputConfigurator::ResumeDisplays() { |
| 837 // Force probing to ensure that we pick up any changes that were made |
| 838 // while the system was suspended. |
| 839 SetDisplayPower(DISPLAY_POWER_ALL_ON, true); |
| 840 } |
| 841 |
872 void OutputConfigurator::NotifyOnDisplayChanged() { | 842 void OutputConfigurator::NotifyOnDisplayChanged() { |
873 TRACE_EVENT0("chromeos", "OutputConfigurator::NotifyOnDisplayChanged"); | 843 TRACE_EVENT0("chromeos", "OutputConfigurator::NotifyOnDisplayChanged"); |
874 FOR_EACH_OBSERVER(Observer, observers_, OnDisplayModeChanged()); | 844 FOR_EACH_OBSERVER(Observer, observers_, OnDisplayModeChanged()); |
875 } | 845 } |
876 | 846 |
877 std::vector<OutputSnapshot> OutputConfigurator::GetDualOutputs( | 847 std::vector<OutputSnapshot> OutputConfigurator::GetDualOutputs( |
878 Display* display, | 848 Display* display, |
879 XRRScreenResources* screen) { | 849 XRRScreenResources* screen) { |
880 std::vector<OutputSnapshot> outputs; | 850 std::vector<OutputSnapshot> outputs; |
881 XRROutputInfo* one_info = NULL; | 851 XRROutputInfo* one_info = NULL; |
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1185 } | 1155 } |
1186 } | 1156 } |
1187 | 1157 |
1188 XIFreeDeviceInfo(info); | 1158 XIFreeDeviceInfo(info); |
1189 } | 1159 } |
1190 | 1160 |
1191 bool OutputConfigurator::EnterState( | 1161 bool OutputConfigurator::EnterState( |
1192 Display* display, | 1162 Display* display, |
1193 XRRScreenResources* screen, | 1163 XRRScreenResources* screen, |
1194 Window window, | 1164 Window window, |
1195 OutputState new_state, | 1165 OutputState output_state, |
| 1166 DisplayPowerState power_state, |
1196 const std::vector<OutputSnapshot>& outputs) { | 1167 const std::vector<OutputSnapshot>& outputs) { |
1197 TRACE_EVENT0("chromeos", "OutputConfigurator::EnterState"); | 1168 TRACE_EVENT0("chromeos", "OutputConfigurator::EnterState"); |
1198 switch (outputs.size()) { | 1169 switch (outputs.size()) { |
1199 case 0: | 1170 case 0: |
1200 // Do nothing as no 0-display states are supported. | 1171 // Do nothing as no 0-display states are supported. |
1201 break; | 1172 break; |
1202 case 1: { | 1173 case 1: { |
1203 // Re-allocate the framebuffer to fit. | 1174 // Re-allocate the framebuffer to fit. |
1204 XRRModeInfo* mode_info = ModeInfoForID(screen, outputs[0].native_mode); | 1175 XRRModeInfo* mode_info = ModeInfoForID(screen, outputs[0].native_mode); |
1205 if (mode_info == NULL) { | 1176 if (mode_info == NULL) { |
1206 UMA_HISTOGRAM_COUNTS("Display.EnterState.single_failures", 1); | 1177 UMA_HISTOGRAM_COUNTS("Display.EnterState.single_failures", 1); |
1207 return false; | 1178 return false; |
1208 } | 1179 } |
1209 | 1180 |
| 1181 bool power_on = power_state == DISPLAY_POWER_ALL_ON || |
| 1182 (power_state == DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON && |
| 1183 !outputs[0].is_internal) || |
| 1184 (power_state == DISPLAY_POWER_INTERNAL_ON_EXTERNAL_OFF && |
| 1185 outputs[0].is_internal); |
1210 CrtcConfig config( | 1186 CrtcConfig config( |
1211 GetNextCrtcAfter(display, screen, outputs[0].output, None), | 1187 GetNextCrtcAfter(display, screen, outputs[0].output, None), |
1212 0, 0, outputs[0].native_mode, outputs[0].output); | 1188 0, 0, power_on ? outputs[0].native_mode : None, outputs[0].output); |
1213 | 1189 |
1214 int width = mode_info->width; | 1190 CreateFrameBuffer(display, screen, window, mode_info->width, |
1215 int height = mode_info->height; | 1191 mode_info->height, &config, NULL); |
1216 CreateFrameBuffer(display, screen, window, width, height, &config, NULL); | |
1217 | 1192 |
1218 // Re-attach native mode for the CRTC. | |
1219 ConfigureCrtc(display, screen, &config); | 1193 ConfigureCrtc(display, screen, &config); |
| 1194 |
1220 // Restore identity transformation for single monitor in native mode. | 1195 // Restore identity transformation for single monitor in native mode. |
1221 if (outputs[0].touch_device_id != None) { | 1196 if (outputs[0].touch_device_id != None) { |
1222 CoordinateTransformation ctm; // Defaults to identity | 1197 CoordinateTransformation ctm; // Defaults to identity |
1223 ConfigureCTM(display, outputs[0].touch_device_id, ctm); | 1198 ConfigureCTM(display, outputs[0].touch_device_id, ctm); |
1224 } | 1199 } |
1225 break; | 1200 break; |
1226 } | 1201 } |
1227 case 2: { | 1202 case 2: { |
1228 RRCrtc primary_crtc = | 1203 RRCrtc primary_crtc = |
1229 GetNextCrtcAfter(display, screen, outputs[0].output, None); | 1204 GetNextCrtcAfter(display, screen, outputs[0].output, None); |
1230 RRCrtc secondary_crtc = | 1205 RRCrtc secondary_crtc = |
1231 GetNextCrtcAfter(display, screen, outputs[1].output, primary_crtc); | 1206 GetNextCrtcAfter(display, screen, outputs[1].output, primary_crtc); |
1232 | 1207 |
1233 if (new_state == STATE_DUAL_MIRROR) { | 1208 // Workaround for crbug.com/148365: leave internal display on for |
| 1209 // internal-off, external-on so user can move cursor (and hence |
| 1210 // windows) onto internal display even when it's off. |
| 1211 bool primary_power_on = power_state == DISPLAY_POWER_ALL_ON || |
| 1212 (power_state == DISPLAY_POWER_INTERNAL_ON_EXTERNAL_OFF && |
| 1213 outputs[0].is_internal); |
| 1214 bool secondary_power_on = power_state == DISPLAY_POWER_ALL_ON || |
| 1215 (power_state == DISPLAY_POWER_INTERNAL_ON_EXTERNAL_OFF && |
| 1216 outputs[1].is_internal); |
| 1217 |
| 1218 if (output_state == STATE_DUAL_MIRROR) { |
1234 XRRModeInfo* mode_info = ModeInfoForID(screen, outputs[0].mirror_mode); | 1219 XRRModeInfo* mode_info = ModeInfoForID(screen, outputs[0].mirror_mode); |
1235 if (mode_info == NULL) { | 1220 if (mode_info == NULL) { |
1236 UMA_HISTOGRAM_COUNTS("Display.EnterState.mirror_failures", 1); | 1221 UMA_HISTOGRAM_COUNTS("Display.EnterState.mirror_failures", 1); |
1237 return false; | 1222 return false; |
1238 } | 1223 } |
1239 | 1224 |
1240 CrtcConfig config1(primary_crtc, 0, 0, outputs[0].mirror_mode, | 1225 CrtcConfig config1(primary_crtc, 0, 0, |
| 1226 primary_power_on ? outputs[0].mirror_mode : None, |
1241 outputs[0].output); | 1227 outputs[0].output); |
1242 CrtcConfig config2(secondary_crtc, 0, 0, outputs[1].mirror_mode, | 1228 CrtcConfig config2(secondary_crtc, 0, 0, |
| 1229 secondary_power_on ? outputs[1].mirror_mode : None, |
1243 outputs[1].output); | 1230 outputs[1].output); |
1244 | 1231 |
1245 int width = mode_info->width; | 1232 CreateFrameBuffer(display, screen, window, mode_info->width, |
1246 int height = mode_info->height; | 1233 mode_info->height, &config1, &config2); |
1247 CreateFrameBuffer(display, screen, window, width, height, | |
1248 &config1, &config2); | |
1249 | 1234 |
1250 ConfigureCrtc(display, screen, &config1); | 1235 ConfigureCrtc(display, screen, &config1); |
1251 ConfigureCrtc(display, screen, &config2); | 1236 ConfigureCrtc(display, screen, &config2); |
| 1237 |
1252 for (size_t i = 0; i < outputs.size(); i++) { | 1238 for (size_t i = 0; i < outputs.size(); i++) { |
1253 if (outputs[i].touch_device_id == None) | 1239 if (outputs[i].touch_device_id == None) |
1254 continue; | 1240 continue; |
1255 | 1241 |
1256 CoordinateTransformation ctm; | 1242 CoordinateTransformation ctm; |
1257 // CTM needs to be calculated if aspect preserving scaling is used. | 1243 // CTM needs to be calculated if aspect preserving scaling is used. |
1258 // Otherwise, assume it is full screen, and use identity CTM. | 1244 // Otherwise, assume it is full screen, and use identity CTM. |
1259 if (outputs[i].mirror_mode != outputs[i].native_mode && | 1245 if (outputs[i].mirror_mode != outputs[i].native_mode && |
1260 outputs[i].is_aspect_preserving_scaling) { | 1246 outputs[i].is_aspect_preserving_scaling) { |
1261 ctm = GetMirrorModeCTM(screen, &outputs[i]); | 1247 ctm = GetMirrorModeCTM(screen, &outputs[i]); |
1262 } | 1248 } |
1263 ConfigureCTM(display, outputs[i].touch_device_id, ctm); | 1249 ConfigureCTM(display, outputs[i].touch_device_id, ctm); |
1264 } | 1250 } |
1265 } else { | 1251 } else { |
1266 XRRModeInfo* primary_mode_info = | 1252 XRRModeInfo* primary_mode_info = |
1267 ModeInfoForID(screen, outputs[0].native_mode); | 1253 ModeInfoForID(screen, outputs[0].native_mode); |
1268 XRRModeInfo* secondary_mode_info = | 1254 XRRModeInfo* secondary_mode_info = |
1269 ModeInfoForID(screen, outputs[1].native_mode); | 1255 ModeInfoForID(screen, outputs[1].native_mode); |
1270 if (primary_mode_info == NULL || secondary_mode_info == NULL) { | 1256 if (primary_mode_info == NULL || secondary_mode_info == NULL) { |
1271 UMA_HISTOGRAM_COUNTS("Display.EnterState.dual_failures", 1); | 1257 UMA_HISTOGRAM_COUNTS("Display.EnterState.dual_failures", 1); |
1272 return false; | 1258 return false; |
1273 } | 1259 } |
1274 | 1260 |
1275 int primary_height = primary_mode_info->height; | 1261 int primary_height = primary_mode_info->height; |
1276 int secondary_height = secondary_mode_info->height; | 1262 int secondary_height = secondary_mode_info->height; |
1277 CrtcConfig config1(primary_crtc, 0, 0, outputs[0].native_mode, | 1263 CrtcConfig config1(primary_crtc, 0, 0, |
| 1264 primary_power_on ? outputs[0].native_mode : None, |
1278 outputs[0].output); | 1265 outputs[0].output); |
1279 CrtcConfig config2(secondary_crtc, 0, 0, outputs[1].native_mode, | 1266 CrtcConfig config2(secondary_crtc, 0, 0, |
| 1267 secondary_power_on ? outputs[1].native_mode : None, |
1280 outputs[1].output); | 1268 outputs[1].output); |
1281 | 1269 |
1282 if (new_state == STATE_DUAL_EXTENDED) | 1270 if (output_state == STATE_DUAL_EXTENDED) |
1283 config2.y = primary_height + kVerticalGap; | 1271 config2.y = primary_height + kVerticalGap; |
1284 else | 1272 else |
1285 config1.y = secondary_height + kVerticalGap; | 1273 config1.y = secondary_height + kVerticalGap; |
1286 | 1274 |
1287 | 1275 int width = std::max<int>( |
1288 int width = | 1276 primary_mode_info->width, secondary_mode_info->width); |
1289 std::max<int>(primary_mode_info->width, secondary_mode_info->width); | |
1290 int height = primary_height + secondary_height + kVerticalGap; | 1277 int height = primary_height + secondary_height + kVerticalGap; |
1291 | 1278 |
1292 CreateFrameBuffer(display, screen, window, width, height, &config1, | 1279 CreateFrameBuffer(display, screen, window, width, height, &config1, |
1293 &config2); | 1280 &config2); |
1294 | 1281 |
1295 ConfigureCrtc(display, screen, &config1); | 1282 ConfigureCrtc(display, screen, &config1); |
1296 ConfigureCrtc(display, screen, &config2); | 1283 ConfigureCrtc(display, screen, &config2); |
1297 | 1284 |
1298 if (outputs[0].touch_device_id != None) { | 1285 if (outputs[0].touch_device_id != None) { |
1299 CoordinateTransformation ctm; | 1286 CoordinateTransformation ctm; |
1300 ctm.x_scale = static_cast<float>(primary_mode_info->width) / width; | 1287 ctm.x_scale = static_cast<float>(primary_mode_info->width) / width; |
1301 ctm.x_offset = static_cast<float>(config1.x) / width; | 1288 ctm.x_offset = static_cast<float>(config1.x) / width; |
1302 ctm.y_scale = static_cast<float>(primary_height) / height; | 1289 ctm.y_scale = static_cast<float>(primary_height) / height; |
1303 ctm.y_offset = static_cast<float>(config1.y) / height; | 1290 ctm.y_offset = static_cast<float>(config1.y) / height; |
1304 ConfigureCTM(display, outputs[0].touch_device_id, ctm); | 1291 ConfigureCTM(display, outputs[0].touch_device_id, ctm); |
1305 } | 1292 } |
1306 if (outputs[1].touch_device_id != None) { | 1293 if (outputs[1].touch_device_id != None) { |
1307 CoordinateTransformation ctm; | 1294 CoordinateTransformation ctm; |
1308 ctm.x_scale = static_cast<float>(secondary_mode_info->width) / width; | 1295 ctm.x_scale = static_cast<float>(secondary_mode_info->width) / |
| 1296 width; |
1309 ctm.x_offset = static_cast<float>(config2.x) / width; | 1297 ctm.x_offset = static_cast<float>(config2.x) / width; |
1310 ctm.y_scale = static_cast<float>(secondary_height) / height; | 1298 ctm.y_scale = static_cast<float>(secondary_height) / height; |
1311 ctm.y_offset = static_cast<float>(config2.y) / height; | 1299 ctm.y_offset = static_cast<float>(config2.y) / height; |
1312 ConfigureCTM(display, outputs[1].touch_device_id, ctm); | 1300 ConfigureCTM(display, outputs[1].touch_device_id, ctm); |
1313 } | 1301 } |
1314 } | 1302 } |
1315 break; | 1303 break; |
1316 } | 1304 } |
1317 default: | 1305 default: |
1318 CHECK(false); | 1306 CHECK(false); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1361 // static | 1349 // static |
1362 RRMode OutputConfigurator::GetOutputNativeMode( | 1350 RRMode OutputConfigurator::GetOutputNativeMode( |
1363 const XRROutputInfo* output_info) { | 1351 const XRROutputInfo* output_info) { |
1364 if (output_info->nmode <= 0) | 1352 if (output_info->nmode <= 0) |
1365 return None; | 1353 return None; |
1366 | 1354 |
1367 return output_info->modes[0]; | 1355 return output_info->modes[0]; |
1368 } | 1356 } |
1369 | 1357 |
1370 } // namespace chromeos | 1358 } // namespace chromeos |
OLD | NEW |