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

Commit 7c9e8263 authored by Mathias Agopian's avatar Mathias Agopian Committed by Android (Google) Code Review
Browse files

Merge "simplify further vsync handling" into jb-mr1-dev

parents d12780ed f6bbd44a
Loading
Loading
Loading
Loading
+75 −84
Original line number Diff line number Diff line
@@ -60,14 +60,6 @@ status_t EventThread::registerDisplayEventConnection(
    return NO_ERROR;
}

status_t EventThread::unregisterDisplayEventConnection(
        const wp<EventThread::Connection>& connection) {
    Mutex::Autolock _l(mLock);
    mDisplayEventConnections.remove(connection);
    mCondition.broadcast();
    return NO_ERROR;
}

void EventThread::removeDisplayEventConnection(
        const wp<EventThread::Connection>& connection) {
    Mutex::Autolock _l(mLock);
@@ -122,43 +114,63 @@ void EventThread::onVSyncReceived(int, nsecs_t timestamp) {
}

bool EventThread::threadLoop() {

    nsecs_t timestamp;
    size_t vsyncCount;
    DisplayEventReceiver::Event vsync;
    Vector< sp<EventThread::Connection> > activeConnections;
    Vector< sp<EventThread::Connection> > signalConnections;
    signalConnections = waitForEvent(&vsync);

    do {
        // release our references
        signalConnections.clear();
        activeConnections.clear();
    // dispatch vsync events to listeners...
    const size_t count = signalConnections.size();
    for (size_t i=0 ; i<count ; i++) {
        const sp<Connection>& conn(signalConnections[i]);
        // now see if we still need to report this VSYNC event
        status_t err = conn->postEvent(vsync);
        if (err == -EAGAIN || err == -EWOULDBLOCK) {
            // The destination doesn't accept events anymore, it's probably
            // full. For now, we just drop the events on the floor.
            // Note that some events cannot be dropped and would have to be
            // re-sent later. Right-now we don't have the ability to do
            // this, but it doesn't matter for VSYNC.
        } else if (err < 0) {
            // handle any other error on the pipe as fatal. the only
            // reasonable thing to do is to clean-up this connection.
            // The most common error we'll get here is -EPIPE.
            removeDisplayEventConnection(signalConnections[i]);
        }
    }
    return true;
}

Vector< sp<EventThread::Connection> > EventThread::waitForEvent(
        DisplayEventReceiver::Event* event)
{
    Mutex::Autolock _l(mLock);

    size_t vsyncCount;
    nsecs_t timestamp;
    Vector< sp<EventThread::Connection> > signalConnections;

    do {
        // latch VSYNC event if any
        bool waitForVSync = false;
        vsyncCount = mVSyncCount;
        timestamp = mVSyncTimestamp;
        mVSyncTimestamp = 0;

        // find out connections waiting for VSYNC events
        // find out connections waiting for events
        size_t count = mDisplayEventConnections.size();
        for (size_t i=0 ; i<count ; i++) {
            sp<Connection> connection(mDisplayEventConnections[i].promote());
            if (connection != NULL) {
                activeConnections.add(connection);
                if (connection->count >= 0) {
                    // we need vsync events because at least
                    // one connection is waiting for it
                    waitForVSync = true;
                    if (timestamp) {
                        // we consume the event only if it's time
                        // (ie: we received a vsync event)
                        if (connection->count == 0) {
                            // fired this time around
                        if (timestamp) {
                            // only "consume" this event if we're going to
                            // report it
                            connection->count = -1;
                        }
                            signalConnections.add(connection);
                        } else if (connection->count == 1 ||
                                (vsyncCount % connection->count) == 0) {
@@ -167,29 +179,25 @@ bool EventThread::threadLoop() {
                        }
                    }
                }
            } else {
                // we couldn't promote this reference, the connection has
                // died, so clean-up!
                mDisplayEventConnections.removeAt(i);
                --i; --count;
            }
        }

        if (timestamp) {
            // we have a vsync event we can dispatch
            if (!waitForVSync) {
        // Here we figure out if we need to enable or disable vsyncs
        if (timestamp && !waitForVSync) {
            // we received a VSYNC but we have no clients
            // don't report it, and disable VSYNC events
            disableVSyncLocked();
            } else {
                // report VSYNC event
                break;
            }
        } else {
            // never disable VSYNC events immediately, instead
            // we'll wait to receive the event and we'll
            // reevaluate whether we need to dispatch it and/or
            // disable VSYNC events then.
            if (waitForVSync) {
                // enable
        } else if (!timestamp && waitForVSync) {
            enableVSyncLocked();
        }
        }

        // note: !timestamp implies signalConnections.isEmpty()
        if (!timestamp) {
            // wait for something to happen
            if (CC_UNLIKELY(mUseSoftwareVSync && waitForVSync)) {
                // h/w vsync cannot be used (screen is off), so we use
@@ -200,39 +208,21 @@ bool EventThread::threadLoop() {
                    mVSyncCount++;
                }
            } else {
            if (!timestamp || signalConnections.isEmpty()) {
                // This is where we spend most of our time, waiting
                // for a vsync events and registered clients
                mCondition.wait(mLock);
            }
        }
    } while (!timestamp || signalConnections.isEmpty());
    } while (signalConnections.isEmpty());

    // dispatch vsync events to listeners...
    vsync.header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
    vsync.header.timestamp = timestamp;
    vsync.vsync.count = vsyncCount;
    // here we're guaranteed to have a timestamp and some connections to signal

    const size_t count = signalConnections.size();
    for (size_t i=0 ; i<count ; i++) {
        const sp<Connection>& conn(signalConnections[i]);
        // now see if we still need to report this VSYNC event
        status_t err = conn->postEvent(vsync);
        if (err == -EAGAIN || err == -EWOULDBLOCK) {
            // The destination doesn't accept events anymore, it's probably
            // full. For now, we just drop the events on the floor.
            // Note that some events cannot be dropped and would have to be
            // re-sent later. Right-now we don't have the ability to do
            // this, but it doesn't matter for VSYNC.
        } else if (err < 0) {
            // handle any other error on the pipe as fatal. the only
            // reasonable thing to do is to clean-up this connection.
            // The most common error we'll get here is -EPIPE.
            removeDisplayEventConnection(signalConnections[i]);
        }
    }
    // dispatch vsync events to listeners...
    event->header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
    event->header.timestamp = timestamp;
    event->vsync.count = vsyncCount;

    return true;
    return signalConnections;
}

void EventThread::enableVSyncLocked() {
@@ -280,7 +270,8 @@ EventThread::Connection::Connection(
}

EventThread::Connection::~Connection() {
    mEventThread->unregisterDisplayEventConnection(this);
    // do nothing here -- clean-up will happen automatically
    // when the main thread wakes up
}

void EventThread::Connection::onFirstRef() {
+3 −1
Original line number Diff line number Diff line
@@ -65,7 +65,6 @@ public:

    sp<Connection> createEventConnection() const;
    status_t registerDisplayEventConnection(const sp<Connection>& connection);
    status_t unregisterDisplayEventConnection(const wp<Connection>& connection);

    void setVsyncRate(uint32_t count, const sp<Connection>& connection);
    void requestNextVsync(const sp<Connection>& connection);
@@ -79,6 +78,9 @@ public:
    // called when receiving a vsync event
    void onVSyncReceived(int display, nsecs_t timestamp);

    Vector< sp<EventThread::Connection> > waitForEvent(
            DisplayEventReceiver::Event* event);

    void dump(String8& result, char* buffer, size_t SIZE) const;

private: