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

Commit 3f028660 authored by Rachel Lee's avatar Rachel Lee
Browse files

Revert "Revert "Send multiple scheduler frame timelines.""

This reverts commit caaa47d6.

Reason for revert: Fix the reverted CL in 2nd CL.

Bug: 198192508
Bug: 204941507
Test: See 2nd CL.

Change-Id: I15c693c2e0a82ef81a490319da11871bd74298b3
parent 44880877
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -130,6 +130,19 @@ int DisplayEventDispatcher::handleEvent(int, int events, void*) {
    return 1; // keep the callback
}

void DisplayEventDispatcher::populateFrameTimelines(const DisplayEventReceiver::Event& event,
                                                    VsyncEventData* outVsyncEventData) const {
    for (size_t i = 0; i < DisplayEventReceiver::kFrameTimelinesLength; i++) {
        DisplayEventReceiver::Event::VSync::FrameTimeline receiverTimeline =
                event.vsync.frameTimelines[i];
        outVsyncEventData->frameTimelines[i] = {.id = receiverTimeline.vsyncId,
                                                .deadlineTimestamp =
                                                        receiverTimeline.deadlineTimestamp,
                                                .expectedPresentTime =
                                                        receiverTimeline.expectedVSyncTimestamp};
    }
}

bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp,
                                                  PhysicalDisplayId* outDisplayId,
                                                  uint32_t* outCount,
@@ -154,6 +167,9 @@ bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp,
                    outVsyncEventData->deadlineTimestamp = ev.vsync.deadlineTimestamp;
                    outVsyncEventData->frameInterval = ev.vsync.frameInterval;
                    outVsyncEventData->expectedPresentTime = ev.vsync.expectedVSyncTimestamp;
                    outVsyncEventData->preferredFrameTimelineIndex =
                            ev.vsync.preferredFrameTimelineIndex;
                    populateFrameTimelines(ev, outVsyncEventData);
                    break;
                case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
                    dispatchHotplug(ev.header.timestamp, ev.header.displayId, ev.hotplug.connected);
+24 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include <gui/DisplayEventReceiver.h>
#include <utils/Log.h>
#include <utils/Looper.h>
#include <array>

namespace android {
using FrameRateOverride = DisplayEventReceiver::Event::FrameRateOverride;
@@ -36,6 +37,26 @@ struct VsyncEventData {

    // The anticipated Vsync present time.
    int64_t expectedPresentTime = 0;

    struct FrameTimeline {
        // The Vsync Id corresponsing to this vsync event. This will be used to
        // populate ISurfaceComposer::setFrameTimelineVsync and
        // SurfaceComposerClient::setFrameTimelineVsync
        int64_t id = FrameTimelineInfo::INVALID_VSYNC_ID;

        // The deadline in CLOCK_MONOTONIC that the app needs to complete its
        // frame by (both on the CPU and the GPU)
        int64_t deadlineTimestamp = std::numeric_limits<int64_t>::max();

        // The anticipated Vsync present time.
        int64_t expectedPresentTime = 0;
    };

    // Sorted possible frame timelines.
    std::array<FrameTimeline, DisplayEventReceiver::kFrameTimelinesLength> frameTimelines;

    // Index into the frameTimelines that represents the platform's preferred frame timeline.
    size_t preferredFrameTimelineIndex = std::numeric_limits<size_t>::max();
};

class DisplayEventDispatcher : public LooperCallback {
@@ -77,5 +98,8 @@ private:

    bool processPendingEvents(nsecs_t* outTimestamp, PhysicalDisplayId* outDisplayId,
                              uint32_t* outCount, VsyncEventData* outVsyncEventData);

    void populateFrameTimelines(const DisplayEventReceiver::Event& event,
                                VsyncEventData* outVsyncEventData) const;
};
} // namespace android
+9 −0
Original line number Diff line number Diff line
@@ -49,6 +49,9 @@ static inline constexpr uint32_t fourcc(char c1, char c2, char c3, char c4) {
// ----------------------------------------------------------------------------
class DisplayEventReceiver {
public:
    // Max amount of frame timelines is arbitrarily set to be reasonable.
    static constexpr int64_t kFrameTimelinesLength = 7;

    enum {
        DISPLAY_EVENT_VSYNC = fourcc('v', 's', 'y', 'n'),
        DISPLAY_EVENT_HOTPLUG = fourcc('p', 'l', 'u', 'g'),
@@ -77,6 +80,12 @@ public:
            nsecs_t deadlineTimestamp __attribute__((aligned(8)));
            nsecs_t frameInterval __attribute__((aligned(8)));
            int64_t vsyncId;
            size_t preferredFrameTimelineIndex __attribute__((aligned(8)));
            struct FrameTimeline {
                nsecs_t expectedVSyncTimestamp __attribute__((aligned(8)));
                nsecs_t deadlineTimestamp __attribute__((aligned(8)));
                int64_t vsyncId;
            } frameTimelines[kFrameTimelinesLength];
        };

        struct Hotplug {
+11 −23
Original line number Diff line number Diff line
@@ -100,17 +100,10 @@ class Choreographer;
 * Implementation of AChoreographerFrameCallbackData.
 */
struct ChoreographerFrameCallbackDataImpl {
    struct FrameTimeline {
        int64_t vsyncId{0};
        int64_t expectedPresentTimeNanos{0};
        int64_t deadlineNanos{0};
    };

    int64_t frameTimeNanos{0};

    size_t frameTimelinesLength;

    std::vector<FrameTimeline> frameTimelines;
    std::array<VsyncEventData::FrameTimeline, DisplayEventReceiver::kFrameTimelinesLength>
            frameTimelines;

    size_t preferredFrameTimelineIndex;

@@ -456,14 +449,9 @@ bool Choreographer::inCallback() const {
}

ChoreographerFrameCallbackDataImpl Choreographer::createFrameCallbackData(nsecs_t timestamp) const {
    std::vector<ChoreographerFrameCallbackDataImpl::FrameTimeline> frameTimelines;
    frameTimelines.push_back({.vsyncId = mLastVsyncEventData.id,
                              .expectedPresentTimeNanos = mLastVsyncEventData.expectedPresentTime,
                              .deadlineNanos = mLastVsyncEventData.deadlineTimestamp});
    return {.frameTimeNanos = timestamp,
            .frameTimelinesLength = 1,
            .preferredFrameTimelineIndex = 0,
            .frameTimelines = frameTimelines,
            .preferredFrameTimelineIndex = mLastVsyncEventData.preferredFrameTimelineIndex,
            .frameTimelines = mLastVsyncEventData.frameTimelines,
            .choreographer = this};
}

@@ -646,7 +634,7 @@ size_t AChoreographerFrameCallbackData_getFrameTimelinesLength(
            AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data);
    LOG_ALWAYS_FATAL_IF(!frameCallbackData->choreographer->inCallback(),
                        "Data is only valid in callback");
    return frameCallbackData->frameTimelinesLength;
    return frameCallbackData->frameTimelines.size();
}
size_t AChoreographerFrameCallbackData_getPreferredFrameTimelineIndex(
        const AChoreographerFrameCallbackData* data) {
@@ -662,8 +650,8 @@ int64_t AChoreographerFrameCallbackData_getFrameTimelineVsyncId(
            AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data);
    LOG_ALWAYS_FATAL_IF(!frameCallbackData->choreographer->inCallback(),
                        "Data is only valid in callback");
    LOG_ALWAYS_FATAL_IF(index >= frameCallbackData->frameTimelinesLength, "Index out of bounds");
    return frameCallbackData->frameTimelines[index].vsyncId;
    LOG_ALWAYS_FATAL_IF(index >= frameCallbackData->frameTimelines.size(), "Index out of bounds");
    return frameCallbackData->frameTimelines[index].id;
}
int64_t AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentTime(
        const AChoreographerFrameCallbackData* data, size_t index) {
@@ -671,8 +659,8 @@ int64_t AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentTime(
            AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data);
    LOG_ALWAYS_FATAL_IF(!frameCallbackData->choreographer->inCallback(),
                        "Data is only valid in callback");
    LOG_ALWAYS_FATAL_IF(index >= frameCallbackData->frameTimelinesLength, "Index out of bounds");
    return frameCallbackData->frameTimelines[index].expectedPresentTimeNanos;
    LOG_ALWAYS_FATAL_IF(index >= frameCallbackData->frameTimelines.size(), "Index out of bounds");
    return frameCallbackData->frameTimelines[index].expectedPresentTime;
}
int64_t AChoreographerFrameCallbackData_getFrameTimelineDeadline(
        const AChoreographerFrameCallbackData* data, size_t index) {
@@ -680,8 +668,8 @@ int64_t AChoreographerFrameCallbackData_getFrameTimelineDeadline(
            AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data);
    LOG_ALWAYS_FATAL_IF(!frameCallbackData->choreographer->inCallback(),
                        "Data is only valid in callback");
    LOG_ALWAYS_FATAL_IF(index >= frameCallbackData->frameTimelinesLength, "Index out of bounds");
    return frameCallbackData->frameTimelines[index].deadlineNanos;
    LOG_ALWAYS_FATAL_IF(index >= frameCallbackData->frameTimelines.size(), "Index out of bounds");
    return frameCallbackData->frameTimelines[index].deadlineTimestamp;
}

AChoreographer* AChoreographer_create() {
+37 −8
Original line number Diff line number Diff line
@@ -355,14 +355,7 @@ void EventThread::onVSyncEvent(nsecs_t timestamp, nsecs_t expectedVSyncTimestamp
    std::lock_guard<std::mutex> lock(mMutex);

    LOG_FATAL_IF(!mVSyncState);
    const int64_t vsyncId = [&] {
        if (mTokenManager != nullptr) {
            return mTokenManager->generateTokenForPredictions(
                    {timestamp, deadlineTimestamp, expectedVSyncTimestamp});
        }
        return FrameTimelineInfo::INVALID_VSYNC_ID;
    }();

    const int64_t vsyncId = generateToken(timestamp, deadlineTimestamp, expectedVSyncTimestamp);
    mPendingEvents.push_back(makeVSync(mVSyncState->displayId, timestamp, ++mVSyncState->count,
                                       expectedVSyncTimestamp, deadlineTimestamp, vsyncId));
    mCondition.notify_all();
@@ -567,12 +560,48 @@ bool EventThread::shouldConsumeEvent(const DisplayEventReceiver::Event& event,
    }
}

int64_t EventThread::generateToken(nsecs_t timestamp, nsecs_t expectedVSyncTimestamp,
                                   nsecs_t deadlineTimestamp) const {
    if (mTokenManager != nullptr) {
        return mTokenManager->generateTokenForPredictions(
                {timestamp, deadlineTimestamp, expectedVSyncTimestamp});
    }
    return FrameTimelineInfo::INVALID_VSYNC_ID;
}

void EventThread::generateFrameTimeline(DisplayEventReceiver::Event& event) const {
    // Add 1 to ensure the preferredFrameTimelineIndex entry (when multiplier == 0) is included.
    for (int multiplier = -DisplayEventReceiver::kFrameTimelinesLength + 1, currentIndex = 0;
         currentIndex < DisplayEventReceiver::kFrameTimelinesLength; multiplier++) {
        nsecs_t deadline = event.vsync.deadlineTimestamp + multiplier * event.vsync.frameInterval;
        // Valid possible frame timelines must have future values.
        if (deadline > event.header.timestamp) {
            if (multiplier == 0) {
                event.vsync.preferredFrameTimelineIndex = currentIndex;
                event.vsync.frameTimelines[currentIndex] =
                        {.vsyncId = event.vsync.vsyncId,
                         .deadlineTimestamp = event.vsync.deadlineTimestamp,
                         .expectedVSyncTimestamp = event.vsync.expectedVSyncTimestamp};
            } else {
                nsecs_t expectedVSync =
                        event.vsync.expectedVSyncTimestamp + multiplier * event.vsync.frameInterval;
                event.vsync.frameTimelines[currentIndex] =
                        {.vsyncId = generateToken(event.header.timestamp, expectedVSync, deadline),
                         .deadlineTimestamp = deadline,
                         .expectedVSyncTimestamp = expectedVSync};
            }
            currentIndex++;
        }
    }
}

void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event,
                                const DisplayEventConsumers& consumers) {
    for (const auto& consumer : consumers) {
        DisplayEventReceiver::Event copy = event;
        if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
            copy.vsync.frameInterval = mGetVsyncPeriodFunction(consumer->mOwnerUid);
            generateFrameTimeline(copy);
        }
        switch (consumer->postEvent(copy)) {
            case NO_ERROR:
Loading