Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 084cf9a9 authored by Ana Krulec's avatar Ana Krulec Committed by Android (Google) Code Review
Browse files

Merge "SF: Offsets should be dependend on the refresh rate."

parents e4cc9036 757f63aa
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -152,6 +152,7 @@ filegroup {
        "Scheduler/MessageQueue.cpp",
        "Scheduler/Scheduler.cpp",
        "Scheduler/SchedulerUtils.cpp",
        "Scheduler/PhaseOffsets.cpp",
        "StartPropertySetThread.cpp",
        "SurfaceFlinger.cpp",
        "SurfaceInterceptor.cpp",
+1 −12
Original line number Diff line number Diff line
@@ -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
+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
+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
+1 −1
Original line number Diff line number Diff line
@@ -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