diff options
-rw-r--r-- | libs/hwui/renderthread/RenderThread.cpp | 26 | ||||
-rw-r--r-- | libs/hwui/renderthread/RenderThread.h | 4 | ||||
-rw-r--r-- | libs/hwui/renderthread/TimeLord.cpp | 4 | ||||
-rw-r--r-- | libs/hwui/renderthread/TimeLord.h | 3 |
4 files changed, 22 insertions, 15 deletions
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp index 38cb4cd..3e4e965 100644 --- a/libs/hwui/renderthread/RenderThread.cpp +++ b/libs/hwui/renderthread/RenderThread.cpp @@ -40,7 +40,7 @@ namespace renderthread { static const size_t EVENT_BUFFER_SIZE = 100; // Slight delay to give the UI time to push us a new frame before we replay -static const int DISPATCH_FRAME_CALLBACKS_DELAY = 4; +static const nsecs_t DISPATCH_FRAME_CALLBACKS_DELAY = milliseconds_to_nanoseconds(4); TaskQueue::TaskQueue() : mHead(0), mTail(0) {} @@ -209,16 +209,16 @@ static nsecs_t latestVsyncEvent(DisplayEventReceiver* receiver) { return latest; } -void RenderThread::drainDisplayEventQueue(bool skipCallbacks) { +void RenderThread::drainDisplayEventQueue() { ATRACE_CALL(); nsecs_t vsyncEvent = latestVsyncEvent(mDisplayEventReceiver); if (vsyncEvent > 0) { mVsyncRequested = false; - mTimeLord.vsyncReceived(vsyncEvent); - if (!skipCallbacks && !mFrameCallbackTaskPending) { + if (mTimeLord.vsyncReceived(vsyncEvent) && !mFrameCallbackTaskPending) { ATRACE_NAME("queue mFrameCallbackTask"); mFrameCallbackTaskPending = true; - queueDelayed(mFrameCallbackTask, DISPATCH_FRAME_CALLBACKS_DELAY); + nsecs_t runAt = (vsyncEvent + DISPATCH_FRAME_CALLBACKS_DELAY); + queueAt(mFrameCallbackTask, runAt); } } } @@ -230,8 +230,13 @@ void RenderThread::dispatchFrameCallbacks() { std::set<IFrameCallback*> callbacks; mFrameCallbacks.swap(callbacks); - for (std::set<IFrameCallback*>::iterator it = callbacks.begin(); it != callbacks.end(); it++) { - (*it)->doFrame(); + if (callbacks.size()) { + // Assume one of them will probably animate again so preemptively + // request the next vsync in case it occurs mid-frame + requestVsync(); + for (std::set<IFrameCallback*>::iterator it = callbacks.begin(); it != callbacks.end(); it++) { + (*it)->doFrame(); + } } } @@ -273,7 +278,7 @@ bool RenderThread::threadLoop() { } if (mPendingRegistrationFrameCallbacks.size() && !mFrameCallbackTaskPending) { - drainDisplayEventQueue(true); + drainDisplayEventQueue(); mFrameCallbacks.insert( mPendingRegistrationFrameCallbacks.begin(), mPendingRegistrationFrameCallbacks.end()); mPendingRegistrationFrameCallbacks.clear(); @@ -299,9 +304,8 @@ void RenderThread::queueAtFront(RenderTask* task) { mLooper->wake(); } -void RenderThread::queueDelayed(RenderTask* task, int delayMs) { - nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); - task->mRunAt = now + milliseconds_to_nanoseconds(delayMs); +void RenderThread::queueAt(RenderTask* task, nsecs_t runAtNs) { + task->mRunAt = runAtNs; queue(task); } diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h index 4126d02..99c2e15 100644 --- a/libs/hwui/renderthread/RenderThread.h +++ b/libs/hwui/renderthread/RenderThread.h @@ -75,7 +75,7 @@ public: // and will delete them after they are run ANDROID_API void queue(RenderTask* task); ANDROID_API void queueAtFront(RenderTask* task); - void queueDelayed(RenderTask* task, int delayMs); + void queueAt(RenderTask* task, nsecs_t runAtNs); void remove(RenderTask* task); // Mimics android.view.Choreographer @@ -103,7 +103,7 @@ private: void initThreadLocals(); void initializeDisplayEventReceiver(); static int displayEventReceiverCallback(int fd, int events, void* data); - void drainDisplayEventQueue(bool skipCallbacks = false); + void drainDisplayEventQueue(); void dispatchFrameCallbacks(); void requestVsync(); diff --git a/libs/hwui/renderthread/TimeLord.cpp b/libs/hwui/renderthread/TimeLord.cpp index 9bd4eae..f187493 100644 --- a/libs/hwui/renderthread/TimeLord.cpp +++ b/libs/hwui/renderthread/TimeLord.cpp @@ -24,10 +24,12 @@ TimeLord::TimeLord() , mFrameTimeNanos(0) { } -void TimeLord::vsyncReceived(nsecs_t vsync) { +bool TimeLord::vsyncReceived(nsecs_t vsync) { if (vsync > mFrameTimeNanos) { mFrameTimeNanos = vsync; + return true; } + return false; } nsecs_t TimeLord::computeFrameTimeMs() { diff --git a/libs/hwui/renderthread/TimeLord.h b/libs/hwui/renderthread/TimeLord.h index 8b0372c..7c155d2 100644 --- a/libs/hwui/renderthread/TimeLord.h +++ b/libs/hwui/renderthread/TimeLord.h @@ -29,7 +29,8 @@ class RenderThread; class TimeLord { public: void setFrameInterval(nsecs_t intervalNanos) { mFrameIntervalNanos = intervalNanos; } - void vsyncReceived(nsecs_t vsync); + // returns true if the vsync is newer, false if it was rejected for staleness + bool vsyncReceived(nsecs_t vsync); nsecs_t computeFrameTimeMs(); private: |