Loading services/surfaceflinger/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -152,6 +152,7 @@ filegroup { "Scheduler/MessageQueue.cpp", "Scheduler/Scheduler.cpp", "Scheduler/SchedulerUtils.cpp", "Scheduler/PhaseOffsets.cpp", "StartPropertySetThread.cpp", "SurfaceFlinger.cpp", "SurfaceInterceptor.cpp", Loading services/surfaceflinger/Scheduler/DispSync.cpp +1 −12 Original line number Diff line number Diff line Loading @@ -757,18 +757,7 @@ nsecs_t DispSync::expectedPresentTime() { const uint32_t hwcLatency = 0; // Ask DispSync when the next refresh will be (CLOCK_MONOTONIC). const nsecs_t nextRefresh = computeNextRefresh(hwcLatency); // The DispSync time is already adjusted for the difference between // vsync and reported-vsync (SurfaceFlinger::dispSyncPresentTimeOffset), so // we don't need to factor that in here. Pad a little to avoid // weird effects if apps might be requesting times right on the edge. nsecs_t extraPadding = 0; if (SurfaceFlinger::vsyncPhaseOffsetNs == 0) { extraPadding = 1000000; // 1ms (6% of 60Hz) } return nextRefresh + extraPadding; return computeNextRefresh(hwcLatency); } } // namespace impl Loading services/surfaceflinger/Scheduler/PhaseOffsets.cpp 0 → 100644 +117 −0 Original line number Diff line number Diff line /* * Copyright 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "PhaseOffsets.h" #include <cutils/properties.h> #include "SurfaceFlingerProperties.h" namespace android { using namespace android::sysprop; namespace scheduler { PhaseOffsets::~PhaseOffsets() = default; namespace impl { PhaseOffsets::PhaseOffsets() { int64_t vsyncPhaseOffsetNs = vsync_event_phase_offset_ns(1000000); int64_t sfVsyncPhaseOffsetNs = vsync_sf_event_phase_offset_ns(1000000); char value[PROPERTY_VALUE_MAX]; property_get("debug.sf.early_phase_offset_ns", value, "-1"); const int earlySfOffsetNs = atoi(value); property_get("debug.sf.early_gl_phase_offset_ns", value, "-1"); const int earlyGlSfOffsetNs = atoi(value); property_get("debug.sf.early_app_phase_offset_ns", value, "-1"); const int earlyAppOffsetNs = atoi(value); property_get("debug.sf.early_gl_app_phase_offset_ns", value, "-1"); const int earlyGlAppOffsetNs = atoi(value); property_get("debug.sf.high_fps_early_phase_offset_ns", value, "-1"); const int highFpsEarlySfOffsetNs = atoi(value); property_get("debug.sf.high_fps_early_gl_phase_offset_ns", value, "-1"); const int highFpsEarlyGlSfOffsetNs = atoi(value); property_get("debug.sf.high_fps_early_app_phase_offset_ns", value, "-1"); const int highFpsEarlyAppOffsetNs = atoi(value); property_get("debug.sf.high_fps_early_gl_app_phase_offset_ns", value, "-1"); const int highFpsEarlyGlAppOffsetNs = atoi(value); // TODO(b/122905996): Define these in device.mk. property_get("debug.sf.high_fps_late_app_phase_offset_ns", value, "1000000"); const int highFpsLateAppOffsetNs = atoi(value); property_get("debug.sf.high_fps_late_sf_phase_offset_ns", value, "8000000"); const int highFpsLateSfOffsetNs = atoi(value); mDefaultRefreshRateOffsets.early = {earlySfOffsetNs != -1 ? earlySfOffsetNs : sfVsyncPhaseOffsetNs, earlyAppOffsetNs != -1 ? earlyAppOffsetNs : vsyncPhaseOffsetNs}; mDefaultRefreshRateOffsets.earlyGl = {earlyGlSfOffsetNs != -1 ? earlyGlSfOffsetNs : sfVsyncPhaseOffsetNs, earlyGlAppOffsetNs != -1 ? earlyGlAppOffsetNs : vsyncPhaseOffsetNs}; mDefaultRefreshRateOffsets.late = {sfVsyncPhaseOffsetNs, vsyncPhaseOffsetNs}; mHighRefreshRateOffsets.early = {highFpsEarlySfOffsetNs != -1 ? highFpsEarlySfOffsetNs : highFpsLateAppOffsetNs, highFpsEarlyAppOffsetNs != -1 ? highFpsEarlyAppOffsetNs : highFpsLateSfOffsetNs}; mHighRefreshRateOffsets.earlyGl = {highFpsEarlyGlSfOffsetNs != -1 ? highFpsEarlyGlSfOffsetNs : highFpsLateAppOffsetNs, highFpsEarlyGlAppOffsetNs != -1 ? highFpsEarlyGlAppOffsetNs : highFpsLateSfOffsetNs}; mHighRefreshRateOffsets.late = {highFpsLateAppOffsetNs, highFpsLateSfOffsetNs}; } PhaseOffsets::Offsets PhaseOffsets::getCurrentOffsets() const { switch (mRefreshRateType) { case RefreshRateConfigs::RefreshRateType::PERFORMANCE: return mHighRefreshRateOffsets; default: return mDefaultRefreshRateOffsets; } } void PhaseOffsets::dump(std::string& result) const { const auto [early, earlyGl, late] = getCurrentOffsets(); base::StringAppendF(&result, " app phase: %9" PRId64 " ns\t SF phase: %9" PRId64 " ns\n" " early app phase: %9" PRId64 " ns\t early SF phase: %9" PRId64 " ns\n" "GL early app phase: %9" PRId64 " ns\tGL early SF phase: %9" PRId64 " ns\n", late.app, late.sf, early.app, early.sf, earlyGl.app, earlyGl.sf); } nsecs_t PhaseOffsets::getCurrentAppOffset() { return getCurrentOffsets().late.app; } nsecs_t PhaseOffsets::getCurrentSfOffset() { return getCurrentOffsets().late.sf; } } // namespace impl } // namespace scheduler } // namespace android services/surfaceflinger/Scheduler/PhaseOffsets.h 0 → 100644 +83 −0 Original line number Diff line number Diff line /* * Copyright 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include <cinttypes> #include "RefreshRateConfigs.h" #include "VSyncModulator.h" namespace android { namespace scheduler { /* * This class encapsulates offsets for different refresh rates. Depending * on what refresh rate we are using, and wheter we are composing in GL, * different offsets will help us with latency. This class keeps track of * which mode the device is on, and returns approprate offsets when needed. */ class PhaseOffsets { public: struct Offsets { VSyncModulator::Offsets early; VSyncModulator::Offsets earlyGl; VSyncModulator::Offsets late; }; virtual ~PhaseOffsets(); virtual nsecs_t getCurrentAppOffset() = 0; virtual nsecs_t getCurrentSfOffset() = 0; virtual Offsets getCurrentOffsets() const = 0; virtual void setRefreshRateType(RefreshRateConfigs::RefreshRateType refreshRateType) = 0; virtual void dump(std::string& result) const = 0; }; namespace impl { class PhaseOffsets : public scheduler::PhaseOffsets { public: PhaseOffsets(); nsecs_t getCurrentAppOffset() override; nsecs_t getCurrentSfOffset() override; // Returns early, early GL, and late offsets for Apps and SF. Offsets getCurrentOffsets() const override; // This function should be called when the device is switching between different // refresh rates, to properly update the offsets. void setRefreshRateType(RefreshRateConfigs::RefreshRateType refreshRateType) override { mRefreshRateType = refreshRateType; } // Returns current offsets in human friendly format. void dump(std::string& result) const override; private: Offsets getmDefaultRefreshRateOffsets() { return mDefaultRefreshRateOffsets; } Offsets getmHighRefreshRateOffsets() { return mHighRefreshRateOffsets; } std::atomic<RefreshRateConfigs::RefreshRateType> mRefreshRateType = RefreshRateConfigs::RefreshRateType::DEFAULT; Offsets mDefaultRefreshRateOffsets; Offsets mHighRefreshRateOffsets; }; } // namespace impl } // namespace scheduler } // namespace android services/surfaceflinger/Scheduler/Scheduler.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -70,7 +70,7 @@ Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function) mEventControlThread = std::make_unique<impl::EventControlThread>(function); char value[PROPERTY_VALUE_MAX]; property_get("debug.sf.set_idle_timer_ms", value, "0"); property_get("debug.sf.set_idle_timer_ms", value, "30"); mSetIdleTimerMs = atoi(value); if (mSetIdleTimerMs > 0) { Loading Loading
services/surfaceflinger/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -152,6 +152,7 @@ filegroup { "Scheduler/MessageQueue.cpp", "Scheduler/Scheduler.cpp", "Scheduler/SchedulerUtils.cpp", "Scheduler/PhaseOffsets.cpp", "StartPropertySetThread.cpp", "SurfaceFlinger.cpp", "SurfaceInterceptor.cpp", Loading
services/surfaceflinger/Scheduler/DispSync.cpp +1 −12 Original line number Diff line number Diff line Loading @@ -757,18 +757,7 @@ nsecs_t DispSync::expectedPresentTime() { const uint32_t hwcLatency = 0; // Ask DispSync when the next refresh will be (CLOCK_MONOTONIC). const nsecs_t nextRefresh = computeNextRefresh(hwcLatency); // The DispSync time is already adjusted for the difference between // vsync and reported-vsync (SurfaceFlinger::dispSyncPresentTimeOffset), so // we don't need to factor that in here. Pad a little to avoid // weird effects if apps might be requesting times right on the edge. nsecs_t extraPadding = 0; if (SurfaceFlinger::vsyncPhaseOffsetNs == 0) { extraPadding = 1000000; // 1ms (6% of 60Hz) } return nextRefresh + extraPadding; return computeNextRefresh(hwcLatency); } } // namespace impl Loading
services/surfaceflinger/Scheduler/PhaseOffsets.cpp 0 → 100644 +117 −0 Original line number Diff line number Diff line /* * Copyright 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "PhaseOffsets.h" #include <cutils/properties.h> #include "SurfaceFlingerProperties.h" namespace android { using namespace android::sysprop; namespace scheduler { PhaseOffsets::~PhaseOffsets() = default; namespace impl { PhaseOffsets::PhaseOffsets() { int64_t vsyncPhaseOffsetNs = vsync_event_phase_offset_ns(1000000); int64_t sfVsyncPhaseOffsetNs = vsync_sf_event_phase_offset_ns(1000000); char value[PROPERTY_VALUE_MAX]; property_get("debug.sf.early_phase_offset_ns", value, "-1"); const int earlySfOffsetNs = atoi(value); property_get("debug.sf.early_gl_phase_offset_ns", value, "-1"); const int earlyGlSfOffsetNs = atoi(value); property_get("debug.sf.early_app_phase_offset_ns", value, "-1"); const int earlyAppOffsetNs = atoi(value); property_get("debug.sf.early_gl_app_phase_offset_ns", value, "-1"); const int earlyGlAppOffsetNs = atoi(value); property_get("debug.sf.high_fps_early_phase_offset_ns", value, "-1"); const int highFpsEarlySfOffsetNs = atoi(value); property_get("debug.sf.high_fps_early_gl_phase_offset_ns", value, "-1"); const int highFpsEarlyGlSfOffsetNs = atoi(value); property_get("debug.sf.high_fps_early_app_phase_offset_ns", value, "-1"); const int highFpsEarlyAppOffsetNs = atoi(value); property_get("debug.sf.high_fps_early_gl_app_phase_offset_ns", value, "-1"); const int highFpsEarlyGlAppOffsetNs = atoi(value); // TODO(b/122905996): Define these in device.mk. property_get("debug.sf.high_fps_late_app_phase_offset_ns", value, "1000000"); const int highFpsLateAppOffsetNs = atoi(value); property_get("debug.sf.high_fps_late_sf_phase_offset_ns", value, "8000000"); const int highFpsLateSfOffsetNs = atoi(value); mDefaultRefreshRateOffsets.early = {earlySfOffsetNs != -1 ? earlySfOffsetNs : sfVsyncPhaseOffsetNs, earlyAppOffsetNs != -1 ? earlyAppOffsetNs : vsyncPhaseOffsetNs}; mDefaultRefreshRateOffsets.earlyGl = {earlyGlSfOffsetNs != -1 ? earlyGlSfOffsetNs : sfVsyncPhaseOffsetNs, earlyGlAppOffsetNs != -1 ? earlyGlAppOffsetNs : vsyncPhaseOffsetNs}; mDefaultRefreshRateOffsets.late = {sfVsyncPhaseOffsetNs, vsyncPhaseOffsetNs}; mHighRefreshRateOffsets.early = {highFpsEarlySfOffsetNs != -1 ? highFpsEarlySfOffsetNs : highFpsLateAppOffsetNs, highFpsEarlyAppOffsetNs != -1 ? highFpsEarlyAppOffsetNs : highFpsLateSfOffsetNs}; mHighRefreshRateOffsets.earlyGl = {highFpsEarlyGlSfOffsetNs != -1 ? highFpsEarlyGlSfOffsetNs : highFpsLateAppOffsetNs, highFpsEarlyGlAppOffsetNs != -1 ? highFpsEarlyGlAppOffsetNs : highFpsLateSfOffsetNs}; mHighRefreshRateOffsets.late = {highFpsLateAppOffsetNs, highFpsLateSfOffsetNs}; } PhaseOffsets::Offsets PhaseOffsets::getCurrentOffsets() const { switch (mRefreshRateType) { case RefreshRateConfigs::RefreshRateType::PERFORMANCE: return mHighRefreshRateOffsets; default: return mDefaultRefreshRateOffsets; } } void PhaseOffsets::dump(std::string& result) const { const auto [early, earlyGl, late] = getCurrentOffsets(); base::StringAppendF(&result, " app phase: %9" PRId64 " ns\t SF phase: %9" PRId64 " ns\n" " early app phase: %9" PRId64 " ns\t early SF phase: %9" PRId64 " ns\n" "GL early app phase: %9" PRId64 " ns\tGL early SF phase: %9" PRId64 " ns\n", late.app, late.sf, early.app, early.sf, earlyGl.app, earlyGl.sf); } nsecs_t PhaseOffsets::getCurrentAppOffset() { return getCurrentOffsets().late.app; } nsecs_t PhaseOffsets::getCurrentSfOffset() { return getCurrentOffsets().late.sf; } } // namespace impl } // namespace scheduler } // namespace android
services/surfaceflinger/Scheduler/PhaseOffsets.h 0 → 100644 +83 −0 Original line number Diff line number Diff line /* * Copyright 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include <cinttypes> #include "RefreshRateConfigs.h" #include "VSyncModulator.h" namespace android { namespace scheduler { /* * This class encapsulates offsets for different refresh rates. Depending * on what refresh rate we are using, and wheter we are composing in GL, * different offsets will help us with latency. This class keeps track of * which mode the device is on, and returns approprate offsets when needed. */ class PhaseOffsets { public: struct Offsets { VSyncModulator::Offsets early; VSyncModulator::Offsets earlyGl; VSyncModulator::Offsets late; }; virtual ~PhaseOffsets(); virtual nsecs_t getCurrentAppOffset() = 0; virtual nsecs_t getCurrentSfOffset() = 0; virtual Offsets getCurrentOffsets() const = 0; virtual void setRefreshRateType(RefreshRateConfigs::RefreshRateType refreshRateType) = 0; virtual void dump(std::string& result) const = 0; }; namespace impl { class PhaseOffsets : public scheduler::PhaseOffsets { public: PhaseOffsets(); nsecs_t getCurrentAppOffset() override; nsecs_t getCurrentSfOffset() override; // Returns early, early GL, and late offsets for Apps and SF. Offsets getCurrentOffsets() const override; // This function should be called when the device is switching between different // refresh rates, to properly update the offsets. void setRefreshRateType(RefreshRateConfigs::RefreshRateType refreshRateType) override { mRefreshRateType = refreshRateType; } // Returns current offsets in human friendly format. void dump(std::string& result) const override; private: Offsets getmDefaultRefreshRateOffsets() { return mDefaultRefreshRateOffsets; } Offsets getmHighRefreshRateOffsets() { return mHighRefreshRateOffsets; } std::atomic<RefreshRateConfigs::RefreshRateType> mRefreshRateType = RefreshRateConfigs::RefreshRateType::DEFAULT; Offsets mDefaultRefreshRateOffsets; Offsets mHighRefreshRateOffsets; }; } // namespace impl } // namespace scheduler } // namespace android
services/surfaceflinger/Scheduler/Scheduler.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -70,7 +70,7 @@ Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function) mEventControlThread = std::make_unique<impl::EventControlThread>(function); char value[PROPERTY_VALUE_MAX]; property_get("debug.sf.set_idle_timer_ms", value, "0"); property_get("debug.sf.set_idle_timer_ms", value, "30"); mSetIdleTimerMs = atoi(value); if (mSetIdleTimerMs > 0) { Loading