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