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

Commit fd501b8b authored by Ram Indani's avatar Ram Indani Committed by Android (Google) Code Review
Browse files

Merge "Update FrameInterval using next vsync generated" into main

parents 2f8ab0ea 0491e646
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
@@ -313,6 +313,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;
@@ -548,6 +554,60 @@ TEST_F(SchedulerTest, onFrameSignalMultipleDisplays) {
    EXPECT_EQ(makeVsyncIds(VsyncId(44), true), compositor.vsyncIds.composite);
}

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