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

Commit 0d28d76a authored by Ady Abraham's avatar Ady Abraham
Browse files

SurfaceFlinger: pass frame deadline to Choreographer

Pass the frame deadline calculated by SF to AChoreographer so
hwui would be able to improve its stats by knowing if a frame is
likely to be late.

Bug: 169858174
Test: manul
Change-Id: I9433d990684b968cbe1cd3ce17717b616d01b9a2
parent f5c9e22f
Loading
Loading
Loading
Loading
+11 −9
Original line number Diff line number Diff line
@@ -73,8 +73,8 @@ status_t DisplayEventDispatcher::scheduleVsync() {
        nsecs_t vsyncTimestamp;
        PhysicalDisplayId vsyncDisplayId;
        uint32_t vsyncCount;
        int64_t vsyncId;
        if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, &vsyncId)) {
        VsyncEventData vsyncEventData;
        if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, &vsyncEventData)) {
            ALOGE("dispatcher %p ~ last event processed while scheduling was for %" PRId64 "", this,
                  ns2ms(static_cast<nsecs_t>(vsyncTimestamp)));
        }
@@ -117,13 +117,14 @@ int DisplayEventDispatcher::handleEvent(int, int events, void*) {
    nsecs_t vsyncTimestamp;
    PhysicalDisplayId vsyncDisplayId;
    uint32_t vsyncCount;
    int64_t vsyncId;
    if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, &vsyncId)) {
    VsyncEventData vsyncEventData;
    if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, &vsyncEventData)) {
        ALOGV("dispatcher %p ~ Vsync pulse: timestamp=%" PRId64
              ", displayId=%s, count=%d, vsyncId=%" PRId64,
              this, ns2ms(vsyncTimestamp), to_string(vsyncDisplayId).c_str(), vsyncCount, vsyncId);
              this, ns2ms(vsyncTimestamp), to_string(vsyncDisplayId).c_str(), vsyncCount,
              vsyncEventData.id);
        mWaitingForVsync = false;
        dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount, vsyncId);
        dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount, vsyncEventData);
    }

    return 1; // keep the callback
@@ -131,11 +132,11 @@ int DisplayEventDispatcher::handleEvent(int, int events, void*) {

bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp,
                                                  PhysicalDisplayId* outDisplayId,
                                                  uint32_t* outCount, int64_t* outVsyncId) {
                                                  uint32_t* outCount,
                                                  VsyncEventData* outVsyncEventData) {
    bool gotVsync = false;
    DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
    ssize_t n;
    *outVsyncId = 0;
    while ((n = mReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
        ALOGV("dispatcher %p ~ Read %d events.", this, int(n));
        for (ssize_t i = 0; i < n; i++) {
@@ -148,7 +149,8 @@ bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp,
                    *outTimestamp = ev.header.timestamp;
                    *outDisplayId = ev.header.displayId;
                    *outCount = ev.vsync.count;
                    *outVsyncId = ev.vsync.vsyncId;
                    outVsyncEventData->id = ev.vsync.vsyncId;
                    outVsyncEventData->deadlineTimestamp = ev.vsync.deadlineTimestamp;
                    break;
                case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
                    dispatchHotplug(ev.header.timestamp, ev.header.displayId, ev.hotplug.connected);
+13 −2
Original line number Diff line number Diff line
@@ -20,6 +20,17 @@

namespace android {

struct VsyncEventData {
    // The Vsync Id corresponsing to this vsync event. This will be used to
    // populate ISurfaceComposer::setFrameTimelineVsync and
    // SurfaceComposerClient::setFrameTimelineVsync
    int64_t id = ISurfaceComposer::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();
};

class DisplayEventDispatcher : public LooperCallback {
public:
    explicit DisplayEventDispatcher(
@@ -44,7 +55,7 @@ private:
    bool mWaitingForVsync;

    virtual void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count,
                               int64_t vsyncId) = 0;
                               VsyncEventData vsyncEventData) = 0;
    virtual void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId,
                                 bool connected) = 0;
    virtual void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId,
@@ -54,6 +65,6 @@ private:
    virtual void dispatchNullEvent(nsecs_t timestamp, PhysicalDisplayId displayId) = 0;

    bool processPendingEvents(nsecs_t* outTimestamp, PhysicalDisplayId* outDisplayId,
                              uint32_t* outCount, int64_t* outVsyncId);
                              uint32_t* outCount, VsyncEventData* outVsyncEventData);
};
} // namespace android
+15 −5
Original line number Diff line number Diff line
@@ -129,13 +129,14 @@ public:
    static Choreographer* getForThread();
    virtual ~Choreographer() override EXCLUDES(gChoreographers.lock);
    int64_t getVsyncId() const;
    int64_t getFrameDeadline() const;


private:
    Choreographer(const Choreographer&) = delete;

    void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count,
                       int64_t vsyncId) override;
                       VsyncEventData vsyncEventData) override;
    void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) override;
    void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId, int32_t configId,
                               nsecs_t vsyncPeriod) override;
@@ -149,7 +150,7 @@ private:
    std::vector<RefreshRateCallback> mRefreshRateCallbacks;

    nsecs_t mLatestVsyncPeriod = -1;
    int64_t mLastVsyncId = -1;
    VsyncEventData mLastVsyncEventData;

    const sp<Looper> mLooper;
    const std::thread::id mThreadId;
@@ -354,7 +355,8 @@ void Choreographer::handleRefreshRateUpdates() {
// TODO(b/74619554): The PhysicalDisplayId is ignored because SF only emits VSYNC events for the
// internal display and DisplayEventReceiver::requestNextVsync only allows requesting VSYNC for
// the internal display implicitly.
void Choreographer::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId, uint32_t, int64_t vsyncId) {
void Choreographer::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId, uint32_t,
                                  VsyncEventData vsyncEventData) {
    std::vector<FrameCallback> callbacks{};
    {
        std::lock_guard<std::mutex> _l{mLock};
@@ -364,7 +366,7 @@ void Choreographer::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId, uint32_t
            mFrameCallbacks.pop();
        }
    }
    mLastVsyncId = vsyncId;
    mLastVsyncEventData = vsyncEventData;
    for (const auto& cb : callbacks) {
        if (cb.callback64 != nullptr) {
            cb.callback64(timestamp, cb.data);
@@ -410,7 +412,11 @@ void Choreographer::handleMessage(const Message& message) {
}

int64_t Choreographer::getVsyncId() const {
    return mLastVsyncId;
    return mLastVsyncEventData.id;
}

int64_t Choreographer::getFrameDeadline() const {
    return mLastVsyncEventData.deadlineTimestamp;
}

} // namespace android
@@ -492,6 +498,10 @@ int64_t AChoreographer_getVsyncId(const AChoreographer* choreographer) {
    return AChoreographer_to_Choreographer(choreographer)->getVsyncId();
}

int64_t AChoreographer_getFrameDeadline(const AChoreographer* choreographer) {
    return AChoreographer_to_Choreographer(choreographer)->getFrameDeadline();
}

} // namespace android

/* Glue for the NDK interface */
+7 −0
Original line number Diff line number Diff line
@@ -35,6 +35,13 @@ void AChoreographer_signalRefreshRateCallbacks(int64_t vsyncPeriod);
// this function from anywhere else will return an undefined value.
int64_t AChoreographer_getVsyncId(const AChoreographer* choreographer);

// Returns the deadline timestamp (in CLOCK_MONOTONIC) of the last frame callback.
// Client are expected to call this function from their frame callback function
// to get the deadline and use it to know whether a frame is likely to miss
// presentation. Calling this function from anywhere else will return an undefined
// value.
int64_t AChoreographer_getFrameDeadline(const AChoreographer* choreographer);

// Trampoline functions allowing libandroid.so to define the NDK symbols without including
// the entirety of libnativedisplay as a whole static lib. As libnativedisplay
// maintains global state, libnativedisplay can never be directly statically
+1 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ LIBNATIVEDISPLAY_PLATFORM {
      android::AChoreographer_routeUnregisterRefreshRateCallback*;
      android::AChoreographer_signalRefreshRateCallbacks*;
      android::AChoreographer_getVsyncId*;
      android::AChoreographer_getFrameDeadline*;
      android::ADisplay_acquirePhysicalDisplays*;
      android::ADisplay_release*;
      android::ADisplay_getMaxSupportedFps*;