| Ana Krulec | 757f63a | 2019-01-25 10:46:18 -0800 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright 2019 The Android Open Source Project | 
 | 3 |  * | 
 | 4 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
 | 5 |  * you may not use this file except in compliance with the License. | 
 | 6 |  * You may obtain a copy of the License at | 
 | 7 |  * | 
 | 8 |  *      http://www.apache.org/licenses/LICENSE-2.0 | 
 | 9 |  * | 
 | 10 |  * Unless required by applicable law or agreed to in writing, software | 
 | 11 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
 | 12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | 13 |  * See the License for the specific language governing permissions and | 
 | 14 |  * limitations under the License. | 
 | 15 |  */ | 
 | 16 |  | 
 | 17 | #include "PhaseOffsets.h" | 
 | 18 |  | 
 | 19 | #include <cutils/properties.h> | 
 | 20 |  | 
| Dominik Laskowski | eddeda1 | 2019-07-19 11:54:13 -0700 | [diff] [blame] | 21 | #include <optional> | 
 | 22 |  | 
| Ana Krulec | 757f63a | 2019-01-25 10:46:18 -0800 | [diff] [blame] | 23 | #include "SurfaceFlingerProperties.h" | 
 | 24 |  | 
| Dominik Laskowski | eddeda1 | 2019-07-19 11:54:13 -0700 | [diff] [blame] | 25 | namespace { | 
| Ana Krulec | 757f63a | 2019-01-25 10:46:18 -0800 | [diff] [blame] | 26 |  | 
| Dominik Laskowski | f83570c | 2019-08-26 12:04:07 -0700 | [diff] [blame] | 27 | std::optional<nsecs_t> getProperty(const char* name) { | 
| Dominik Laskowski | eddeda1 | 2019-07-19 11:54:13 -0700 | [diff] [blame] | 28 |     char value[PROPERTY_VALUE_MAX]; | 
 | 29 |     property_get(name, value, "-1"); | 
 | 30 |     if (const int i = atoi(value); i != -1) return i; | 
 | 31 |     return std::nullopt; | 
 | 32 | } | 
| Ana Krulec | 757f63a | 2019-01-25 10:46:18 -0800 | [diff] [blame] | 33 |  | 
| Dominik Laskowski | eddeda1 | 2019-07-19 11:54:13 -0700 | [diff] [blame] | 34 | } // namespace | 
 | 35 |  | 
 | 36 | namespace android::scheduler { | 
 | 37 |  | 
| Ana Krulec | 757f63a | 2019-01-25 10:46:18 -0800 | [diff] [blame] | 38 | PhaseOffsets::~PhaseOffsets() = default; | 
 | 39 |  | 
 | 40 | namespace impl { | 
| Dominik Laskowski | eddeda1 | 2019-07-19 11:54:13 -0700 | [diff] [blame] | 41 |  | 
| Ana Krulec | 757f63a | 2019-01-25 10:46:18 -0800 | [diff] [blame] | 42 | PhaseOffsets::PhaseOffsets() { | 
| Ady Abraham | be0f948 | 2019-04-24 15:41:53 -0700 | [diff] [blame] | 43 |     // Below defines the threshold when an offset is considered to be negative, i.e. targeting | 
 | 44 |     // for the N+2 vsync instead of N+1. This means that: | 
 | 45 |     // For offset < threshold, SF wake up (vsync_duration - offset) before HW vsync. | 
 | 46 |     // For offset >= threshold, SF wake up (2 * vsync_duration - offset) before HW vsync. | 
| Dominik Laskowski | eddeda1 | 2019-07-19 11:54:13 -0700 | [diff] [blame] | 47 |     const nsecs_t thresholdForNextVsync = | 
 | 48 |             getProperty("debug.sf.phase_offset_threshold_for_next_vsync_ns") | 
 | 49 |                     .value_or(std::numeric_limits<nsecs_t>::max()); | 
| Ady Abraham | be0f948 | 2019-04-24 15:41:53 -0700 | [diff] [blame] | 50 |  | 
| Dominik Laskowski | eddeda1 | 2019-07-19 11:54:13 -0700 | [diff] [blame] | 51 |     const Offsets defaultOffsets = getDefaultOffsets(thresholdForNextVsync); | 
 | 52 |     const Offsets highFpsOffsets = getHighFpsOffsets(thresholdForNextVsync); | 
| Alec Mouri | d7599d8 | 2019-05-22 19:58:00 -0700 | [diff] [blame] | 53 |  | 
 | 54 |     mOffsets.insert({RefreshRateType::POWER_SAVING, defaultOffsets}); | 
 | 55 |     mOffsets.insert({RefreshRateType::DEFAULT, defaultOffsets}); | 
 | 56 |     mOffsets.insert({RefreshRateType::PERFORMANCE, highFpsOffsets}); | 
| Ana Krulec | 757f63a | 2019-01-25 10:46:18 -0800 | [diff] [blame] | 57 | } | 
 | 58 |  | 
| Ady Abraham | 796beb0 | 2019-04-11 15:23:07 -0700 | [diff] [blame] | 59 | PhaseOffsets::Offsets PhaseOffsets::getOffsetsForRefreshRate( | 
| Dominik Laskowski | eddeda1 | 2019-07-19 11:54:13 -0700 | [diff] [blame] | 60 |         RefreshRateType refreshRateType) const { | 
| Alec Mouri | d7599d8 | 2019-05-22 19:58:00 -0700 | [diff] [blame] | 61 |     return mOffsets.at(refreshRateType); | 
| Ana Krulec | 757f63a | 2019-01-25 10:46:18 -0800 | [diff] [blame] | 62 | } | 
 | 63 |  | 
 | 64 | void PhaseOffsets::dump(std::string& result) const { | 
| Dominik Laskowski | eddeda1 | 2019-07-19 11:54:13 -0700 | [diff] [blame] | 65 |     const auto [early, earlyGl, late, threshold] = getCurrentOffsets(); | 
| Dominik Laskowski | 9804183 | 2019-08-01 18:35:59 -0700 | [diff] [blame] | 66 |     using base::StringAppendF; | 
 | 67 |     StringAppendF(&result, | 
 | 68 |                   "           app phase: %9" PRId64 " ns\t         SF phase: %9" PRId64 " ns\n" | 
 | 69 |                   "     early app phase: %9" PRId64 " ns\t   early SF phase: %9" PRId64 " ns\n" | 
 | 70 |                   "  GL early app phase: %9" PRId64 " ns\tGL early SF phase: %9" PRId64 " ns\n" | 
 | 71 |                   "next VSYNC threshold: %9" PRId64 " ns\n", | 
 | 72 |                   late.app, late.sf, early.app, early.sf, earlyGl.app, earlyGl.sf, threshold); | 
| Ana Krulec | 757f63a | 2019-01-25 10:46:18 -0800 | [diff] [blame] | 73 | } | 
 | 74 |  | 
| Dominik Laskowski | eddeda1 | 2019-07-19 11:54:13 -0700 | [diff] [blame] | 75 | PhaseOffsets::Offsets PhaseOffsets::getDefaultOffsets(nsecs_t thresholdForNextVsync) { | 
 | 76 |     const int64_t vsyncPhaseOffsetNs = sysprop::vsync_event_phase_offset_ns(1000000); | 
 | 77 |     const int64_t sfVsyncPhaseOffsetNs = sysprop::vsync_sf_event_phase_offset_ns(1000000); | 
 | 78 |  | 
 | 79 |     const auto earlySfOffsetNs = getProperty("debug.sf.early_phase_offset_ns"); | 
 | 80 |     const auto earlyGlSfOffsetNs = getProperty("debug.sf.early_gl_phase_offset_ns"); | 
 | 81 |     const auto earlyAppOffsetNs = getProperty("debug.sf.early_app_phase_offset_ns"); | 
 | 82 |     const auto earlyGlAppOffsetNs = getProperty("debug.sf.early_gl_app_phase_offset_ns"); | 
 | 83 |  | 
 | 84 |     return {{RefreshRateType::DEFAULT, earlySfOffsetNs.value_or(sfVsyncPhaseOffsetNs), | 
 | 85 |              earlyAppOffsetNs.value_or(vsyncPhaseOffsetNs)}, | 
 | 86 |  | 
 | 87 |             {RefreshRateType::DEFAULT, earlyGlSfOffsetNs.value_or(sfVsyncPhaseOffsetNs), | 
 | 88 |              earlyGlAppOffsetNs.value_or(vsyncPhaseOffsetNs)}, | 
 | 89 |  | 
 | 90 |             {RefreshRateType::DEFAULT, sfVsyncPhaseOffsetNs, vsyncPhaseOffsetNs}, | 
 | 91 |  | 
 | 92 |             thresholdForNextVsync}; | 
| Ana Krulec | 757f63a | 2019-01-25 10:46:18 -0800 | [diff] [blame] | 93 | } | 
 | 94 |  | 
| Dominik Laskowski | eddeda1 | 2019-07-19 11:54:13 -0700 | [diff] [blame] | 95 | PhaseOffsets::Offsets PhaseOffsets::getHighFpsOffsets(nsecs_t thresholdForNextVsync) { | 
 | 96 |     // TODO(b/122905996): Define these in device.mk. | 
 | 97 |     const int highFpsLateAppOffsetNs = | 
 | 98 |             getProperty("debug.sf.high_fps_late_app_phase_offset_ns").value_or(2000000); | 
 | 99 |     const int highFpsLateSfOffsetNs = | 
 | 100 |             getProperty("debug.sf.high_fps_late_sf_phase_offset_ns").value_or(1000000); | 
 | 101 |  | 
 | 102 |     const auto highFpsEarlySfOffsetNs = getProperty("debug.sf.high_fps_early_phase_offset_ns"); | 
 | 103 |     const auto highFpsEarlyGlSfOffsetNs = getProperty("debug.sf.high_fps_early_gl_phase_offset_ns"); | 
 | 104 |     const auto highFpsEarlyAppOffsetNs = getProperty("debug.sf.high_fps_early_app_phase_offset_ns"); | 
 | 105 |     const auto highFpsEarlyGlAppOffsetNs = | 
 | 106 |             getProperty("debug.sf.high_fps_early_gl_app_phase_offset_ns"); | 
 | 107 |  | 
 | 108 |     return {{RefreshRateType::PERFORMANCE, highFpsEarlySfOffsetNs.value_or(highFpsLateSfOffsetNs), | 
 | 109 |              highFpsEarlyAppOffsetNs.value_or(highFpsLateAppOffsetNs)}, | 
 | 110 |  | 
 | 111 |             {RefreshRateType::PERFORMANCE, highFpsEarlyGlSfOffsetNs.value_or(highFpsLateSfOffsetNs), | 
 | 112 |              highFpsEarlyGlAppOffsetNs.value_or(highFpsLateAppOffsetNs)}, | 
 | 113 |  | 
 | 114 |             {RefreshRateType::PERFORMANCE, highFpsLateSfOffsetNs, highFpsLateAppOffsetNs}, | 
 | 115 |  | 
 | 116 |             thresholdForNextVsync}; | 
| Ana Krulec | 757f63a | 2019-01-25 10:46:18 -0800 | [diff] [blame] | 117 | } | 
 | 118 |  | 
 | 119 | } // namespace impl | 
| Dominik Laskowski | eddeda1 | 2019-07-19 11:54:13 -0700 | [diff] [blame] | 120 | } // namespace android::scheduler |