OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "ui/display/chromeos/display_configurator.h" | 5 #include "ui/display/chromeos/display_configurator.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
82 if (display_power) | 82 if (display_power) |
83 (*display_power)[i] = on; | 83 (*display_power)[i] = on; |
84 if (on) | 84 if (on) |
85 num_on_displays++; | 85 num_on_displays++; |
86 } | 86 } |
87 return num_on_displays; | 87 return num_on_displays; |
88 } | 88 } |
89 | 89 |
90 } // namespace | 90 } // namespace |
91 | 91 |
92 DisplayConfigurator::CoordinateTransformation::CoordinateTransformation() | |
93 : x_scale(1.0), | |
94 x_offset(0.0), | |
95 y_scale(1.0), | |
96 y_offset(0.0) {} | |
97 | |
98 DisplayConfigurator::DisplayState::DisplayState() | 92 DisplayConfigurator::DisplayState::DisplayState() |
99 : display(NULL), | 93 : display(NULL), |
100 touch_device_id(0), | 94 touch_device_id(0), |
101 selected_mode(NULL), | 95 selected_mode(NULL), |
102 mirror_mode(NULL) {} | 96 mirror_mode(NULL) {} |
103 | 97 |
104 bool DisplayConfigurator::TestApi::TriggerConfigureTimeout() { | 98 bool DisplayConfigurator::TestApi::TriggerConfigureTimeout() { |
105 if (configurator_->configure_timer_.get() && | 99 if (configurator_->configure_timer_.get() && |
106 configurator_->configure_timer_->IsRunning()) { | 100 configurator_->configure_timer_->IsRunning()) { |
107 configurator_->configure_timer_.reset(); | 101 configurator_->configure_timer_.reset(); |
(...skipping 681 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
789 | 783 |
790 const DisplayMode* mode_info = cached_displays_[0].mirror_mode; | 784 const DisplayMode* mode_info = cached_displays_[0].mirror_mode; |
791 if (!mode_info) | 785 if (!mode_info) |
792 return false; | 786 return false; |
793 size = mode_info->size(); | 787 size = mode_info->size(); |
794 | 788 |
795 for (size_t i = 0; i < cached_displays_.size(); ++i) { | 789 for (size_t i = 0; i < cached_displays_.size(); ++i) { |
796 DisplayState* state = &cached_displays_[i]; | 790 DisplayState* state = &cached_displays_[i]; |
797 new_mode[i] = display_power[i] ? state->mirror_mode : NULL; | 791 new_mode[i] = display_power[i] ? state->mirror_mode : NULL; |
798 if (state->touch_device_id) { | 792 if (state->touch_device_id) { |
799 // CTM needs to be calculated if aspect preserving scaling is used. | |
800 // Otherwise, assume it is full screen, and use identity CTM. | |
801 if (state->mirror_mode != state->display->native_mode() && | 793 if (state->mirror_mode != state->display->native_mode() && |
802 state->display->is_aspect_preserving_scaling()) { | 794 state->display->is_aspect_preserving_scaling()) { |
803 state->transform = GetMirrorModeCTM(*state); | |
804 mirrored_display_area_ratio_map_[state->touch_device_id] = | 795 mirrored_display_area_ratio_map_[state->touch_device_id] = |
805 GetMirroredDisplayAreaRatio(*state); | 796 GetMirroredDisplayAreaRatio(*state); |
806 } | 797 } |
807 } | 798 } |
808 } | 799 } |
809 break; | 800 break; |
810 } | 801 } |
811 case MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED: { | 802 case MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED: { |
812 if (cached_displays_.size() != 2 || | 803 if (cached_displays_.size() != 2 || |
813 (num_on_displays != 0 && num_on_displays != 2)) { | 804 (num_on_displays != 0 && num_on_displays != 2)) { |
(...skipping 12 matching lines...) Expand all Loading... |
826 // same desktop configuration can be restored when the displays are | 817 // same desktop configuration can be restored when the displays are |
827 // turned back on. | 818 // turned back on. |
828 const DisplayMode* mode_info = cached_displays_[i].selected_mode; | 819 const DisplayMode* mode_info = cached_displays_[i].selected_mode; |
829 if (!mode_info) | 820 if (!mode_info) |
830 return false; | 821 return false; |
831 | 822 |
832 size.set_width(std::max<int>(size.width(), mode_info->size().width())); | 823 size.set_width(std::max<int>(size.width(), mode_info->size().width())); |
833 size.set_height(size.height() + (size.height() ? kVerticalGap : 0) + | 824 size.set_height(size.height() + (size.height() ? kVerticalGap : 0) + |
834 mode_info->size().height()); | 825 mode_info->size().height()); |
835 } | 826 } |
836 | |
837 for (size_t i = 0; i < cached_displays_.size(); ++i) { | |
838 DisplayState* state = &cached_displays_[i]; | |
839 if (state->touch_device_id) | |
840 state->transform = GetExtendedModeCTM(*state, new_origins[i], size); | |
841 } | |
842 break; | 827 break; |
843 } | 828 } |
844 } | 829 } |
845 | 830 |
846 // Finally, apply the desired changes. | 831 // Finally, apply the desired changes. |
847 bool all_succeeded = true; | 832 bool all_succeeded = true; |
848 if (!cached_displays_.empty()) { | 833 if (!cached_displays_.empty()) { |
849 native_display_delegate_->CreateFrameBuffer(size); | 834 native_display_delegate_->CreateFrameBuffer(size); |
850 for (size_t i = 0; i < cached_displays_.size(); ++i) { | 835 for (size_t i = 0; i < cached_displays_.size(); ++i) { |
851 const DisplayState& state = cached_displays_[i]; | 836 const DisplayState& state = cached_displays_[i]; |
(...skipping 27 matching lines...) Expand all Loading... |
879 (pixel_count > best_mode_pixels)) { | 864 (pixel_count > best_mode_pixels)) { |
880 new_mode[i] = *it; | 865 new_mode[i] = *it; |
881 best_mode_pixels = pixel_count; | 866 best_mode_pixels = pixel_count; |
882 } | 867 } |
883 } | 868 } |
884 | 869 |
885 if (best_mode_pixels == 0) | 870 if (best_mode_pixels == 0) |
886 break; | 871 break; |
887 } | 872 } |
888 | 873 |
889 if (configure_succeeded) { | 874 if (!configure_succeeded) |
890 if (state.touch_device_id) | |
891 touchscreen_delegate_->ConfigureCTM(state.touch_device_id, | |
892 state.transform); | |
893 } else { | |
894 all_succeeded = false; | 875 all_succeeded = false; |
895 } | |
896 | 876 |
897 // If we are trying to set mirror mode and one of the modesets fails, | 877 // If we are trying to set mirror mode and one of the modesets fails, |
898 // then the two monitors will be mis-matched. In this case, return | 878 // then the two monitors will be mis-matched. In this case, return |
899 // false to let the observers be aware. | 879 // false to let the observers be aware. |
900 if (display_state == MULTIPLE_DISPLAY_STATE_DUAL_MIRROR && | 880 if (display_state == MULTIPLE_DISPLAY_STATE_DUAL_MIRROR && |
901 display_power[i] && | 881 display_power[i] && |
902 state.display->current_mode() != state.mirror_mode) | 882 state.display->current_mode() != state.mirror_mode) |
903 all_succeeded = false; | 883 all_succeeded = false; |
904 } | 884 } |
905 } | 885 } |
906 | 886 |
907 if (all_succeeded) { | 887 if (all_succeeded) { |
908 display_state_ = display_state; | 888 display_state_ = display_state; |
909 power_state_ = power_state; | 889 power_state_ = power_state; |
| 890 framebuffer_size_ = size; |
910 } | 891 } |
911 return all_succeeded; | 892 return all_succeeded; |
912 } | 893 } |
913 | 894 |
914 MultipleDisplayState DisplayConfigurator::ChooseDisplayState( | 895 MultipleDisplayState DisplayConfigurator::ChooseDisplayState( |
915 chromeos::DisplayPowerState power_state) const { | 896 chromeos::DisplayPowerState power_state) const { |
916 int num_on_displays = GetDisplayPower(cached_displays_, power_state, NULL); | 897 int num_on_displays = GetDisplayPower(cached_displays_, power_state, NULL); |
917 switch (cached_displays_.size()) { | 898 switch (cached_displays_.size()) { |
918 case 0: | 899 case 0: |
919 return MULTIPLE_DISPLAY_STATE_HEADLESS; | 900 return MULTIPLE_DISPLAY_STATE_HEADLESS; |
(...skipping 18 matching lines...) Expand all Loading... |
938 } | 919 } |
939 return state_controller_->GetStateForDisplayIds(display_ids); | 920 return state_controller_->GetStateForDisplayIds(display_ids); |
940 } | 921 } |
941 } | 922 } |
942 default: | 923 default: |
943 NOTREACHED(); | 924 NOTREACHED(); |
944 } | 925 } |
945 return MULTIPLE_DISPLAY_STATE_INVALID; | 926 return MULTIPLE_DISPLAY_STATE_INVALID; |
946 } | 927 } |
947 | 928 |
948 DisplayConfigurator::CoordinateTransformation | |
949 DisplayConfigurator::GetMirrorModeCTM(const DisplayState& display_state) { | |
950 CoordinateTransformation ctm; // Default to identity | |
951 const DisplayMode* native_mode_info = display_state.display->native_mode(); | |
952 const DisplayMode* mirror_mode_info = display_state.mirror_mode; | |
953 | |
954 if (!native_mode_info || !mirror_mode_info || | |
955 native_mode_info->size().height() == 0 || | |
956 mirror_mode_info->size().height() == 0 || | |
957 native_mode_info->size().width() == 0 || | |
958 mirror_mode_info->size().width() == 0) | |
959 return ctm; | |
960 | |
961 float native_mode_ar = static_cast<float>(native_mode_info->size().width()) / | |
962 static_cast<float>(native_mode_info->size().height()); | |
963 float mirror_mode_ar = static_cast<float>(mirror_mode_info->size().width()) / | |
964 static_cast<float>(mirror_mode_info->size().height()); | |
965 | |
966 if (mirror_mode_ar > native_mode_ar) { // Letterboxing | |
967 ctm.x_scale = 1.0; | |
968 ctm.x_offset = 0.0; | |
969 ctm.y_scale = mirror_mode_ar / native_mode_ar; | |
970 ctm.y_offset = (native_mode_ar / mirror_mode_ar - 1.0) * 0.5; | |
971 return ctm; | |
972 } | |
973 if (native_mode_ar > mirror_mode_ar) { // Pillarboxing | |
974 ctm.y_scale = 1.0; | |
975 ctm.y_offset = 0.0; | |
976 ctm.x_scale = native_mode_ar / mirror_mode_ar; | |
977 ctm.x_offset = (mirror_mode_ar / native_mode_ar - 1.0) * 0.5; | |
978 return ctm; | |
979 } | |
980 | |
981 return ctm; // Same aspect ratio - return identity | |
982 } | |
983 | |
984 DisplayConfigurator::CoordinateTransformation | |
985 DisplayConfigurator::GetExtendedModeCTM(const DisplayState& display_state, | |
986 const gfx::Point& new_origin, | |
987 const gfx::Size& framebuffer_size) { | |
988 CoordinateTransformation ctm; // Default to identity | |
989 const DisplayMode* mode_info = display_state.selected_mode; | |
990 DCHECK(mode_info); | |
991 if (!mode_info) | |
992 return ctm; | |
993 // An example of how to calculate the CTM. | |
994 // Suppose we have 2 monitors, the first one has size 1366 x 768. | |
995 // The second one has size 2560 x 1600 | |
996 // The total size of framebuffer is 2560 x 2428 | |
997 // where 2428 = 768 + 60 (hidden gap) + 1600 | |
998 // and the sceond monitor is translated to Point (0, 828) in the | |
999 // framebuffer. | |
1000 // X will first map input event location to [0, 2560) x [0, 2428), | |
1001 // then apply CTM on it. | |
1002 // So to compute CTM, for monitor1, we have | |
1003 // x_scale = (1366 - 1) / (2560 - 1) | |
1004 // x_offset = 0 / (2560 - 1) | |
1005 // y_scale = (768 - 1) / (2428 - 1) | |
1006 // y_offset = 0 / (2428 -1) | |
1007 // For Monitor 2, we have | |
1008 // x_scale = (2560 - 1) / (2560 - 1) | |
1009 // x_offset = 0 / (2560 - 1) | |
1010 // y_scale = (1600 - 1) / (2428 - 1) | |
1011 // y_offset = 828 / (2428 -1) | |
1012 // See the unittest DisplayConfiguratorTest.CTMForMultiScreens. | |
1013 ctm.x_scale = static_cast<float>(mode_info->size().width() - 1) / | |
1014 (framebuffer_size.width() - 1); | |
1015 ctm.x_offset = | |
1016 static_cast<float>(new_origin.x()) / (framebuffer_size.width() - 1); | |
1017 ctm.y_scale = static_cast<float>(mode_info->size().height() - 1) / | |
1018 (framebuffer_size.height() - 1); | |
1019 ctm.y_offset = | |
1020 static_cast<float>(new_origin.y()) / (framebuffer_size.height() - 1); | |
1021 return ctm; | |
1022 } | |
1023 | |
1024 float DisplayConfigurator::GetMirroredDisplayAreaRatio( | 929 float DisplayConfigurator::GetMirroredDisplayAreaRatio( |
1025 const DisplayState& display_state) { | 930 const DisplayState& display_state) { |
1026 float area_ratio = 1.0f; | 931 float area_ratio = 1.0f; |
1027 const DisplayMode* native_mode_info = display_state.display->native_mode(); | 932 const DisplayMode* native_mode_info = display_state.display->native_mode(); |
1028 const DisplayMode* mirror_mode_info = display_state.mirror_mode; | 933 const DisplayMode* mirror_mode_info = display_state.mirror_mode; |
1029 | 934 |
1030 if (!native_mode_info || !mirror_mode_info || | 935 if (!native_mode_info || !mirror_mode_info || |
1031 native_mode_info->size().height() == 0 || | 936 native_mode_info->size().height() == 0 || |
1032 mirror_mode_info->size().height() == 0 || | 937 mirror_mode_info->size().height() == 0 || |
1033 native_mode_info->size().width() == 0 || | 938 native_mode_info->size().width() == 0 || |
1034 mirror_mode_info->size().width() == 0) | 939 mirror_mode_info->size().width() == 0) |
1035 return area_ratio; | 940 return area_ratio; |
1036 | 941 |
1037 float width_ratio = static_cast<float>(mirror_mode_info->size().width()) / | 942 float width_ratio = static_cast<float>(mirror_mode_info->size().width()) / |
1038 static_cast<float>(native_mode_info->size().width()); | 943 static_cast<float>(native_mode_info->size().width()); |
1039 float height_ratio = static_cast<float>(mirror_mode_info->size().height()) / | 944 float height_ratio = static_cast<float>(mirror_mode_info->size().height()) / |
1040 static_cast<float>(native_mode_info->size().height()); | 945 static_cast<float>(native_mode_info->size().height()); |
1041 | 946 |
1042 area_ratio = width_ratio * height_ratio; | 947 area_ratio = width_ratio * height_ratio; |
1043 return area_ratio; | 948 return area_ratio; |
1044 } | 949 } |
1045 | 950 |
1046 } // namespace ui | 951 } // namespace ui |
OLD | NEW |