| 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 |