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

Commit a1273194 authored by Rachel Lee's avatar Rachel Lee Committed by Android (Google) Code Review
Browse files

Merge changes Ib9d8df90,I15c693c2

* changes:
  Send multiple scheduler frame timelines (fix).
  Revert "Revert "Send multiple scheduler frame timelines.""
parents 040744c6 8d0c6101
Loading
Loading
Loading
Loading
+16 −0
Original line number Original line Diff line number Diff line
@@ -130,6 +130,19 @@ int DisplayEventDispatcher::handleEvent(int, int events, void*) {
    return 1; // keep the callback
    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,
bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp,
                                                  PhysicalDisplayId* outDisplayId,
                                                  PhysicalDisplayId* outDisplayId,
                                                  uint32_t* outCount,
                                                  uint32_t* outCount,
@@ -154,6 +167,9 @@ bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp,
                    outVsyncEventData->deadlineTimestamp = ev.vsync.deadlineTimestamp;
                    outVsyncEventData->deadlineTimestamp = ev.vsync.deadlineTimestamp;
                    outVsyncEventData->frameInterval = ev.vsync.frameInterval;
                    outVsyncEventData->frameInterval = ev.vsync.frameInterval;
                    outVsyncEventData->expectedPresentTime = ev.vsync.expectedVSyncTimestamp;
                    outVsyncEventData->expectedPresentTime = ev.vsync.expectedVSyncTimestamp;
                    outVsyncEventData->preferredFrameTimelineIndex =
                            ev.vsync.preferredFrameTimelineIndex;
                    populateFrameTimelines(ev, outVsyncEventData);
                    break;
                    break;
                case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
                case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
                    dispatchHotplug(ev.header.timestamp, ev.header.displayId, ev.hotplug.connected);
                    dispatchHotplug(ev.header.timestamp, ev.header.displayId, ev.hotplug.connected);
+24 −0
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@
#include <gui/DisplayEventReceiver.h>
#include <gui/DisplayEventReceiver.h>
#include <utils/Log.h>
#include <utils/Log.h>
#include <utils/Looper.h>
#include <utils/Looper.h>
#include <array>


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


    // The anticipated Vsync present time.
    // The anticipated Vsync present time.
    int64_t expectedPresentTime = 0;
    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 {
class DisplayEventDispatcher : public LooperCallback {
@@ -77,5 +98,8 @@ private:


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

    void populateFrameTimelines(const DisplayEventReceiver::Event& event,
                                VsyncEventData* outVsyncEventData) const;
};
};
} // namespace android
} // namespace android
+9 −0
Original line number Original line 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 {
class DisplayEventReceiver {
public:
public:
    // Max amount of frame timelines is arbitrarily set to be reasonable.
    static constexpr int64_t kFrameTimelinesLength = 7;

    enum {
    enum {
        DISPLAY_EVENT_VSYNC = fourcc('v', 's', 'y', 'n'),
        DISPLAY_EVENT_VSYNC = fourcc('v', 's', 'y', 'n'),
        DISPLAY_EVENT_HOTPLUG = fourcc('p', 'l', 'u', 'g'),
        DISPLAY_EVENT_HOTPLUG = fourcc('p', 'l', 'u', 'g'),
@@ -77,6 +80,12 @@ public:
            nsecs_t deadlineTimestamp __attribute__((aligned(8)));
            nsecs_t deadlineTimestamp __attribute__((aligned(8)));
            nsecs_t frameInterval __attribute__((aligned(8)));
            nsecs_t frameInterval __attribute__((aligned(8)));
            int64_t vsyncId;
            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 {
        struct Hotplug {
+11 −23
Original line number Original line Diff line number Diff line
@@ -100,17 +100,10 @@ class Choreographer;
 * Implementation of AChoreographerFrameCallbackData.
 * Implementation of AChoreographerFrameCallbackData.
 */
 */
struct ChoreographerFrameCallbackDataImpl {
struct ChoreographerFrameCallbackDataImpl {
    struct FrameTimeline {
        int64_t vsyncId{0};
        int64_t expectedPresentTimeNanos{0};
        int64_t deadlineNanos{0};
    };

    int64_t frameTimeNanos{0};
    int64_t frameTimeNanos{0};


    size_t frameTimelinesLength;
    std::array<VsyncEventData::FrameTimeline, DisplayEventReceiver::kFrameTimelinesLength>

            frameTimelines;
    std::vector<FrameTimeline> frameTimelines;


    size_t preferredFrameTimelineIndex;
    size_t preferredFrameTimelineIndex;


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


ChoreographerFrameCallbackDataImpl Choreographer::createFrameCallbackData(nsecs_t timestamp) 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,
    return {.frameTimeNanos = timestamp,
            .frameTimelinesLength = 1,
            .preferredFrameTimelineIndex = mLastVsyncEventData.preferredFrameTimelineIndex,
            .preferredFrameTimelineIndex = 0,
            .frameTimelines = mLastVsyncEventData.frameTimelines,
            .frameTimelines = frameTimelines,
            .choreographer = this};
            .choreographer = this};
}
}


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


AChoreographer* AChoreographer_create() {
AChoreographer* AChoreographer_create() {
+37 −8
Original line number Original line 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);
    std::lock_guard<std::mutex> lock(mMutex);


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

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


int64_t EventThread::generateToken(nsecs_t timestamp, nsecs_t deadlineTimestamp,
                                   nsecs_t expectedVSyncTimestamp) 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, deadline, expectedVSync),
                         .deadlineTimestamp = deadline,
                         .expectedVSyncTimestamp = expectedVSync};
            }
            currentIndex++;
        }
    }
}

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