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

Commit 0491e646 authored by ramindani's avatar ramindani
Browse files

Update FrameInterval using next vsync generated

use the expectedPresentTime + threshold to get
the next frames interval.

Test: atrace and atest libsurfaceflinger_unittest --test-filter="SchedulerTest*"
BUG: 296636176
Change-Id: I9eb0d2784a81491028ec13d579356da2f34b85df
parent 81d8aadf
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -545,6 +545,7 @@ status_t HWComposer::getDeviceCompositionChanges(
        }
    }

    ATRACE_FORMAT("NextFrameInterval %d_Hz", frameInterval.getIntValue());
    if (canSkipValidate) {
        sp<Fence> outPresentFence = Fence::NO_FENCE;
        uint32_t state = UINT32_MAX;
+18 −0
Original line number Diff line number Diff line
@@ -579,6 +579,24 @@ void Scheduler::setRenderRate(PhysicalDisplayId id, Fps renderFrameRate) {
    display.schedulePtr->getTracker().setRenderRate(renderFrameRate);
}

Fps Scheduler::getNextFrameInterval(PhysicalDisplayId id,
                                    TimePoint currentExpectedPresentTime) const {
    std::scoped_lock lock(mDisplayLock);
    ftl::FakeGuard guard(kMainThreadContext);

    const auto displayOpt = mDisplays.get(id);
    if (!displayOpt) {
        ALOGW("%s: Invalid display %s!", __func__, to_string(id).c_str());
        return Fps{};
    }
    const Display& display = *displayOpt;
    const nsecs_t threshold =
            display.selectorPtr->getActiveMode().modePtr->getVsyncRate().getPeriodNsecs() / 2;
    const nsecs_t nextVsyncTime = display.schedulePtr->getTracker().nextAnticipatedVSyncTimeFrom(
            currentExpectedPresentTime.ns() + threshold);
    return Fps::fromPeriodNsecs(nextVsyncTime - currentExpectedPresentTime.ns());
}

void Scheduler::resync() {
    static constexpr nsecs_t kIgnoreDelay = ms2ns(750);

+3 −0
Original line number Diff line number Diff line
@@ -312,6 +312,9 @@ public:
        return pacesetterSelectorPtr()->getActiveMode().fps;
    }

    Fps getNextFrameInterval(PhysicalDisplayId, TimePoint currentExpectedPresentTime) const
            EXCLUDES(mDisplayLock);

    // Returns the framerate of the layer with the given sequence ID
    float getLayerFramerate(nsecs_t now, int32_t id) const {
        return mLayerHistory.getLayerFramerate(now, id);
+4 −5
Original line number Diff line number Diff line
@@ -2619,10 +2619,6 @@ CompositeResultsPerDisplay SurfaceFlinger::composite(
                refreshArgs.outputs.push_back(display->getCompositionDisplay());
            }
        }
        if (display->getId() == pacesetterId) {
            // TODO(b/255601557) Update frameInterval per display
            refreshArgs.frameInterval = display->refreshRateSelector().getActiveMode().fps;
        }
    }
    mPowerAdvisor->setDisplays(displayIds);

@@ -2687,8 +2683,11 @@ CompositeResultsPerDisplay SurfaceFlinger::composite(
                pacesetterTarget.previousFrameVsyncTime(minFramePeriod) - hwcMinWorkDuration;
    }

    const TimePoint expectedPresentTime = pacesetterTarget.expectedPresentTime();
    // TODO(b/255601557) Update frameInterval per display
    refreshArgs.frameInterval = mScheduler->getNextFrameInterval(pacesetterId, expectedPresentTime);
    refreshArgs.scheduledFrameTime = mScheduler->getScheduledFrameTime();
    refreshArgs.expectedPresentTime = pacesetterTarget.expectedPresentTime().ns();
    refreshArgs.expectedPresentTime = expectedPresentTime.ns();
    refreshArgs.hasTrustedPresentationListener = mNumTrustedPresentationListeners > 0;

    // Store the present time just before calling to the composition engine so we could notify
+60 −0
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
 * limitations under the License.
 */

#include <common/test/FlagUtils.h>
#include <ftl/fake_guard.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
@@ -23,6 +24,7 @@

#include "Scheduler/EventThread.h"
#include "Scheduler/RefreshRateSelector.h"
#include "Scheduler/VSyncPredictor.h"
#include "TestableScheduler.h"
#include "TestableSurfaceFlinger.h"
#include "mock/DisplayHardware/MockDisplayMode.h"
@@ -32,11 +34,15 @@

#include <FrontEnd/LayerHierarchy.h>

#include <com_android_graphics_surfaceflinger_flags.h>
#include "FpsOps.h"

using namespace com::android::graphics::surfaceflinger;

namespace android::scheduler {

using android::mock::createDisplayMode;
using android::mock::createVrrDisplayMode;

using testing::_;
using testing::Return;
@@ -503,6 +509,60 @@ TEST_F(SchedulerTest, onFrameSignalMultipleDisplays) {
    EXPECT_EQ(makeVsyncIds(VsyncId(43)), compositor.vsyncIds);
}

TEST_F(SchedulerTest, nextFrameIntervalTest) {
    SET_FLAG_FOR_TEST(flags::vrr_config, true);

    static constexpr size_t kHistorySize = 10;
    static constexpr size_t kMinimumSamplesForPrediction = 6;
    static constexpr size_t kOutlierTolerancePercent = 25;
    const auto refreshRate = Fps::fromPeriodNsecs(500);
    auto frameRate = Fps::fromPeriodNsecs(1000);

    const ftl::NonNull<DisplayModePtr> kMode = ftl::as_non_null(
            createVrrDisplayMode(DisplayModeId(0), refreshRate,
                                 hal::VrrConfig{.minFrameIntervalNs = static_cast<int32_t>(
                                                        frameRate.getPeriodNsecs())}));
    std::shared_ptr<VSyncPredictor> vrrTracker =
            std::make_shared<VSyncPredictor>(kMode, kHistorySize, kMinimumSamplesForPrediction,
                                             kOutlierTolerancePercent, mVsyncTrackerCallback);
    std::shared_ptr<RefreshRateSelector> vrrSelectorPtr =
            std::make_shared<RefreshRateSelector>(makeModes(kMode), kMode->getId());
    TestableScheduler scheduler{std::make_unique<android::mock::VsyncController>(),
                                vrrTracker,
                                vrrSelectorPtr,
                                sp<VsyncModulator>::make(VsyncConfigSet{}),
                                mSchedulerCallback,
                                mVsyncTrackerCallback};

    scheduler.registerDisplay(kMode->getPhysicalDisplayId(), vrrSelectorPtr, vrrTracker);
    vrrSelectorPtr->setActiveMode(kMode->getId(), frameRate);
    scheduler.setRenderRate(kMode->getPhysicalDisplayId(), frameRate);
    vrrTracker->addVsyncTimestamp(0);

    // Next frame at refresh rate as no previous frame
    EXPECT_EQ(refreshRate,
              scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(), TimePoint::fromNs(0)));

    EXPECT_EQ(Fps::fromPeriodNsecs(1000),
              scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
                                             TimePoint::fromNs(500)));
    EXPECT_EQ(Fps::fromPeriodNsecs(1000),
              scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
                                             TimePoint::fromNs(1500)));

    // Change render rate
    frameRate = Fps::fromPeriodNsecs(2000);
    vrrSelectorPtr->setActiveMode(kMode->getId(), frameRate);
    scheduler.setRenderRate(kMode->getPhysicalDisplayId(), frameRate);

    EXPECT_EQ(Fps::fromPeriodNsecs(2000),
              scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
                                             TimePoint::fromNs(2500)));
    EXPECT_EQ(Fps::fromPeriodNsecs(2000),
              scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
                                             TimePoint::fromNs(4500)));
}

class AttachedChoreographerTest : public SchedulerTest {
protected:
    void frameRateTestScenario(Fps layerFps, int8_t frameRateCompatibility, Fps displayFps,
Loading