diff options
Diffstat (limited to 'libs/gui/FrameTimestamps.cpp')
-rw-r--r-- | libs/gui/FrameTimestamps.cpp | 275 |
1 files changed, 146 insertions, 129 deletions
diff --git a/libs/gui/FrameTimestamps.cpp b/libs/gui/FrameTimestamps.cpp index 30ff65ffa7..6503e9cc47 100644 --- a/libs/gui/FrameTimestamps.cpp +++ b/libs/gui/FrameTimestamps.cpp @@ -16,6 +16,7 @@ #include <gui/FrameTimestamps.h> +#include <cutils/compiler.h> // For CC_[UN]LIKELY #include <inttypes.h> #include <utils/String8.h> @@ -25,28 +26,25 @@ namespace android { -static inline bool isValidTimestamp(nsecs_t time) { - return time > 0 && time < INT64_MAX; -} // ============================================================================ // FrameEvents // ============================================================================ bool FrameEvents::hasPostedInfo() const { - return isValidTimestamp(postedTime); + return Fence::isValidTimestamp(postedTime); } bool FrameEvents::hasRequestedPresentInfo() const { - return isValidTimestamp(requestedPresentTime); + return Fence::isValidTimestamp(requestedPresentTime); } bool FrameEvents::hasLatchInfo() const { - return isValidTimestamp(latchTime); + return Fence::isValidTimestamp(latchTime); } bool FrameEvents::hasFirstRefreshStartInfo() const { - return isValidTimestamp(firstRefreshStartTime); + return Fence::isValidTimestamp(firstRefreshStartTime); } bool FrameEvents::hasLastRefreshStartInfo() const { @@ -57,7 +55,7 @@ bool FrameEvents::hasLastRefreshStartInfo() const { } bool FrameEvents::hasAcquireInfo() const { - return isValidTimestamp(acquireTime) || acquireFence->isValid(); + return acquireFence->isValid(); } bool FrameEvents::hasGpuCompositionDoneInfo() const { @@ -80,22 +78,27 @@ bool FrameEvents::hasReleaseInfo() const { return addReleaseCalled; } -static void checkFenceForCompletion(sp<Fence>* fence, nsecs_t* dstTime) { - if ((*fence)->isValid()) { - nsecs_t time = (*fence)->getSignalTime(); - if (isValidTimestamp(time)) { - *dstTime = time; - *fence = Fence::NO_FENCE; - } - } -} - void FrameEvents::checkFencesForCompletion() { - checkFenceForCompletion(&acquireFence, &acquireTime); - checkFenceForCompletion(&gpuCompositionDoneFence, &gpuCompositionDoneTime); - checkFenceForCompletion(&displayPresentFence, &displayPresentTime); - checkFenceForCompletion(&displayRetireFence, &displayRetireTime); - checkFenceForCompletion(&releaseFence, &releaseTime); + acquireFence->getSignalTime(); + gpuCompositionDoneFence->getSignalTime(); + displayPresentFence->getSignalTime(); + displayRetireFence->getSignalTime(); + releaseFence->getSignalTime(); +} + +static void dumpFenceTime(String8& outString, const char* name, + bool pending, const FenceTime& fenceTime) { + outString.appendFormat("--- %s", name); + nsecs_t signalTime = fenceTime.getCachedSignalTime(); + if (Fence::isValidTimestamp(signalTime)) { + outString.appendFormat("%" PRId64 "\n", signalTime); + } else if (pending || signalTime == Fence::SIGNAL_TIME_PENDING) { + outString.appendFormat("Pending\n"); + } else if (&fenceTime == FenceTime::NO_FENCE.get()){ + outString.appendFormat("N/A\n"); + } else { + outString.appendFormat("Error\n"); + } } void FrameEvents::dump(String8& outString) const @@ -109,66 +112,36 @@ void FrameEvents::dump(String8& outString) const outString.appendFormat("--- Req. Present\t%" PRId64 "\n", requestedPresentTime); outString.appendFormat("--- Latched \t"); - if (isValidTimestamp(latchTime)) { + if (Fence::isValidTimestamp(latchTime)) { outString.appendFormat("%" PRId64 "\n", latchTime); } else { outString.appendFormat("Pending\n"); } outString.appendFormat("--- Refresh (First)\t"); - if (isValidTimestamp(firstRefreshStartTime)) { + if (Fence::isValidTimestamp(firstRefreshStartTime)) { outString.appendFormat("%" PRId64 "\n", firstRefreshStartTime); } else { outString.appendFormat("Pending\n"); } outString.appendFormat("--- Refresh (Last)\t"); - if (isValidTimestamp(lastRefreshStartTime)) { + if (Fence::isValidTimestamp(lastRefreshStartTime)) { outString.appendFormat("%" PRId64 "\n", lastRefreshStartTime); } else { outString.appendFormat("Pending\n"); } - outString.appendFormat("--- Acquire \t"); - if (isValidTimestamp(acquireTime)) { - outString.appendFormat("%" PRId64 "\n", acquireTime); - } else { - outString.appendFormat("Pending\n"); - } - - outString.appendFormat("--- GPU Composite Done\t"); - if (isValidTimestamp(gpuCompositionDoneTime)) { - outString.appendFormat("%" PRId64 "\n", gpuCompositionDoneTime); - } else if (!addPostCompositeCalled || gpuCompositionDoneFence->isValid()) { - outString.appendFormat("Pending\n"); - } else { - outString.appendFormat("N/A\n"); - } - - outString.appendFormat("--- Display Present\t"); - if (isValidTimestamp(displayPresentTime)) { - outString.appendFormat("%" PRId64 "\n", displayPresentTime); - } else if (!addPostCompositeCalled || displayPresentFence->isValid()) { - outString.appendFormat("Pending\n"); - } else { - outString.appendFormat("N/A\n"); - } - - outString.appendFormat("--- Display Retire\t"); - if (isValidTimestamp(displayRetireTime)) { - outString.appendFormat("%" PRId64 "\n", displayRetireTime); - } else if (!addRetireCalled || displayRetireFence->isValid()) { - outString.appendFormat("Pending\n"); - } else { - outString.appendFormat("N/A\n"); - } - - outString.appendFormat("--- Release \t"); - if (isValidTimestamp(releaseTime)) { - outString.appendFormat("%" PRId64 "\n", releaseTime); - } else { - outString.appendFormat("Pending\n"); - } + dumpFenceTime(outString, "Acquire \t", + true, *acquireFence); + dumpFenceTime(outString, "GPU Composite Done\t", + !addPostCompositeCalled, *gpuCompositionDoneFence); + dumpFenceTime(outString, "Display Present \t", + !addPostCompositeCalled, *displayPresentFence); + dumpFenceTime(outString, "Display Retire \t", + !addRetireCalled, *displayRetireFence); + dumpFenceTime(outString, "Release \t", + true, *releaseFence); } @@ -250,7 +223,7 @@ void FrameEventHistory::dump(String8& outString) const { ProducerFrameEventHistory::~ProducerFrameEventHistory() = default; void ProducerFrameEventHistory::updateAcquireFence( - uint64_t frameNumber, sp<Fence> acquire) { + uint64_t frameNumber, std::shared_ptr<FenceTime>&& acquire) { FrameEvents* frame = getFrame(frameNumber, &mAcquireOffset); if (frame == nullptr) { ALOGE("ProducerFrameEventHistory::updateAcquireFence: " @@ -259,20 +232,39 @@ void ProducerFrameEventHistory::updateAcquireFence( } if (acquire->isValid()) { - frame->acquireFence = acquire; + mAcquireTimeline.push(acquire); + frame->acquireFence = std::move(acquire); } else { // If there isn't an acquire fence, assume that buffer was // ready for the consumer when posted. - frame->acquireTime = frame->postedTime; + frame->acquireFence = std::make_shared<FenceTime>(frame->postedTime); } } -static void applyFenceDelta(sp<Fence>* dst, const sp<Fence>& src) { - if (src->isValid()) { - if ((*dst)->isValid()) { - ALOGE("applyFenceDelta: Unexpected fence."); - } - *dst = src; +static void applyFenceDelta(FenceTimeline* timeline, + std::shared_ptr<FenceTime>* dst, const FenceTime::Snapshot& src) { + if (CC_UNLIKELY(dst == nullptr)) { + ALOGE("applyFenceDelta: dst is null."); + return; + } + + switch (src.state) { + case FenceTime::Snapshot::State::EMPTY: + return; + case FenceTime::Snapshot::State::FENCE: + if (CC_UNLIKELY((*dst)->isValid())) { + ALOGE("applyFenceDelta: Unexpected fence."); + } + *dst = std::make_shared<FenceTime>(src.fence); + timeline->push(*dst); + return; + case FenceTime::Snapshot::State::SIGNAL_TIME: + if ((*dst)->isValid()) { + (*dst)->applyTrustedSnapshot(src); + } else { + *dst = std::make_shared<FenceTime>(src.signalTime); + } + return; } } @@ -297,40 +289,37 @@ void ProducerFrameEventHistory::applyDelta( frame.firstRefreshStartTime = d.mFirstRefreshStartTime; frame.lastRefreshStartTime = d.mLastRefreshStartTime; - if (frame.frameNumber == d.mFrameNumber) { - // Existing frame. Merge. - // Consumer never sends timestamps of fences, only the fences - // themselves, so we never need to update the fence timestamps here. - applyFenceDelta( - &frame.gpuCompositionDoneFence, d.mGpuCompositionDoneFence); - applyFenceDelta(&frame.displayPresentFence, d.mDisplayPresentFence); - applyFenceDelta(&frame.displayRetireFence, d.mDisplayRetireFence); - applyFenceDelta(&frame.releaseFence, d.mReleaseFence); - } else { - // New frame. Overwrite. + if (frame.frameNumber != d.mFrameNumber) { + // We got a new frame. Initialize some of the fields. frame.frameNumber = d.mFrameNumber; - - frame.gpuCompositionDoneFence = d.mGpuCompositionDoneFence; - frame.displayPresentFence = d.mDisplayPresentFence; - frame.displayRetireFence = d.mDisplayRetireFence; - frame.releaseFence = d.mReleaseFence; - - // Set aquire fence and time at this point. - frame.acquireTime = 0; - frame.acquireFence = Fence::NO_FENCE; - - // Reset fence-related timestamps - frame.gpuCompositionDoneTime = 0; - frame.displayPresentTime = 0; - frame.displayRetireTime = 0; - frame.releaseTime = 0; - + frame.acquireFence = FenceTime::NO_FENCE; + frame.gpuCompositionDoneFence = FenceTime::NO_FENCE; + frame.displayPresentFence = FenceTime::NO_FENCE; + frame.displayRetireFence = FenceTime::NO_FENCE; + frame.releaseFence = FenceTime::NO_FENCE; // The consumer only sends valid frames. frame.valid = true; } + + applyFenceDelta(&mGpuCompositionDoneTimeline, + &frame.gpuCompositionDoneFence, d.mGpuCompositionDoneFence); + applyFenceDelta(&mPresentTimeline, + &frame.displayPresentFence, d.mDisplayPresentFence); + applyFenceDelta(&mRetireTimeline, + &frame.displayRetireFence, d.mDisplayRetireFence); + applyFenceDelta(&mReleaseTimeline, + &frame.releaseFence, d.mReleaseFence); } } +void ProducerFrameEventHistory::updateSignalTimes() { + mAcquireTimeline.updateSignalTimes(); + mGpuCompositionDoneTimeline.updateSignalTimes(); + mPresentTimeline.updateSignalTimes(); + mRetireTimeline.updateSignalTimes(); + mReleaseTimeline.updateSignalTimes(); +} + // ============================================================================ // ConsumerFrameEventHistory @@ -377,14 +366,15 @@ void ConsumerFrameEventHistory::addPreComposition( } frame->lastRefreshStartTime = refreshStartTime; mFramesDirty[mCompositionOffset].setDirty<FrameEvent::LAST_REFRESH_START>(); - if (!isValidTimestamp(frame->firstRefreshStartTime)) { + if (!Fence::isValidTimestamp(frame->firstRefreshStartTime)) { frame->firstRefreshStartTime = refreshStartTime; mFramesDirty[mCompositionOffset].setDirty<FrameEvent::FIRST_REFRESH_START>(); } } void ConsumerFrameEventHistory::addPostComposition(uint64_t frameNumber, - sp<Fence> gpuCompositionDone, sp<Fence> displayPresent) { + const std::shared_ptr<FenceTime>& gpuCompositionDone, + const std::shared_ptr<FenceTime>& displayPresent) { FrameEvents* frame = getFrame(frameNumber, &mCompositionOffset); if (frame == nullptr) { ALOGE("ConsumerFrameEventHistory::addPostComposition: " @@ -404,7 +394,7 @@ void ConsumerFrameEventHistory::addPostComposition(uint64_t frameNumber, } void ConsumerFrameEventHistory::addRetire( - uint64_t frameNumber, sp<Fence> displayRetire) { + uint64_t frameNumber, const std::shared_ptr<FenceTime>& displayRetire) { FrameEvents* frame = getFrame(frameNumber, &mRetireOffset); if (frame == nullptr) { ALOGE("ConsumerFrameEventHistory::addRetire: Did not find frame."); @@ -416,26 +406,39 @@ void ConsumerFrameEventHistory::addRetire( } void ConsumerFrameEventHistory::addRelease( - uint64_t frameNumber, sp<Fence> release) { + uint64_t frameNumber, std::shared_ptr<FenceTime>&& release) { FrameEvents* frame = getFrame(frameNumber, &mReleaseOffset); if (frame == nullptr) { ALOGE("ConsumerFrameEventHistory::addRelease: Did not find frame."); return; } frame->addReleaseCalled = true; - frame->releaseFence = release; + frame->releaseFence = std::move(release); mFramesDirty[mReleaseOffset].setDirty<FrameEvent::RELEASE>(); } +void ConsumerFrameEventHistory::getFrameDelta( + FrameEventHistoryDelta* delta, + const std::array<FrameEvents, MAX_FRAME_HISTORY>::iterator& frame) { + size_t i = static_cast<size_t>(std::distance(mFrames.begin(), frame)); + if (mFramesDirty[i].anyDirty()) { + delta->mDeltas.emplace_back(i, *frame, mFramesDirty[i]); + mFramesDirty[i].reset(); + } +} + void ConsumerFrameEventHistory::getAndResetDelta( FrameEventHistoryDelta* delta) { + // Write these in order of frame number so that it is easy to + // add them to a FenceTimeline in the proper order producer side. delta->mDeltas.reserve(mFramesDirty.size()); - for (size_t i = 0; i < mFramesDirty.size(); i++) { - if (mFramesDirty[i].anyDirty()) { - delta->mDeltas.push_back( - FrameEventsDelta(i, mFrames[i], mFramesDirty[i])); - mFramesDirty[i].reset(); - } + auto earliestFrame = std::min_element( + mFrames.begin(), mFrames.end(), &FrameNumberLessThan); + for (auto frame = earliestFrame; frame != mFrames.end(); ++frame) { + getFrameDelta(delta, frame); + } + for (auto frame = mFrames.begin(); frame != earliestFrame; ++frame) { + getFrameDelta(delta, frame); } } @@ -458,15 +461,20 @@ FrameEventsDelta::FrameEventsDelta( mLatchTime(frameTimestamps.latchTime), mFirstRefreshStartTime(frameTimestamps.firstRefreshStartTime), mLastRefreshStartTime(frameTimestamps.lastRefreshStartTime) { - mGpuCompositionDoneFence = - dirtyFields.isDirty<FrameEvent::GL_COMPOSITION_DONE>() ? - frameTimestamps.gpuCompositionDoneFence : Fence::NO_FENCE; - mDisplayPresentFence = dirtyFields.isDirty<FrameEvent::DISPLAY_PRESENT>() ? - frameTimestamps.displayPresentFence : Fence::NO_FENCE; - mDisplayRetireFence = dirtyFields.isDirty<FrameEvent::DISPLAY_RETIRE>() ? - frameTimestamps.displayRetireFence : Fence::NO_FENCE; - mReleaseFence = dirtyFields.isDirty<FrameEvent::RELEASE>() ? - frameTimestamps.releaseFence : Fence::NO_FENCE; + if (dirtyFields.isDirty<FrameEvent::GL_COMPOSITION_DONE>()) { + mGpuCompositionDoneFence = + frameTimestamps.gpuCompositionDoneFence->getSnapshot(); + } + if (dirtyFields.isDirty<FrameEvent::DISPLAY_PRESENT>()) { + mDisplayPresentFence = + frameTimestamps.displayPresentFence->getSnapshot(); + } + if (dirtyFields.isDirty<FrameEvent::DISPLAY_RETIRE>()) { + mDisplayRetireFence = frameTimestamps.displayRetireFence->getSnapshot(); + } + if (dirtyFields.isDirty<FrameEvent::RELEASE>()) { + mReleaseFence = frameTimestamps.releaseFence->getSnapshot(); + } } size_t FrameEventsDelta::minFlattenedSize() { @@ -489,16 +497,16 @@ size_t FrameEventsDelta::getFlattenedSize() const { auto fences = allFences(this); return minFlattenedSize() + std::accumulate(fences.begin(), fences.end(), size_t(0), - [](size_t a, const sp<Fence>* fence) { - return a + (*fence)->getFlattenedSize(); + [](size_t a, const FenceTime::Snapshot* fence) { + return a + fence->getFlattenedSize(); }); } size_t FrameEventsDelta::getFdCount() const { auto fences = allFences(this); return std::accumulate(fences.begin(), fences.end(), size_t(0), - [](size_t a, const sp<Fence>* fence) { - return a + (*fence)->getFdCount(); + [](size_t a, const FenceTime::Snapshot* fence) { + return a + fence->getFdCount(); }); } @@ -532,7 +540,7 @@ status_t FrameEventsDelta::flatten(void*& buffer, size_t& size, int*& fds, // Fences for (auto fence : allFences(this)) { - status_t status = (*fence)->flatten(buffer, size, fds, count); + status_t status = fence->flatten(buffer, size, fds, count); if (status != NO_ERROR) { return status; } @@ -570,8 +578,7 @@ status_t FrameEventsDelta::unflatten(void const*& buffer, size_t& size, // Fences for (auto fence : allFences(this)) { - *fence = new Fence; - status_t status = (*fence)->unflatten(buffer, size, fds, count); + status_t status = fence->unflatten(buffer, size, fds, count); if (status != NO_ERROR) { return status; } @@ -584,6 +591,16 @@ status_t FrameEventsDelta::unflatten(void const*& buffer, size_t& size, // FrameEventHistoryDelta // ============================================================================ +FrameEventHistoryDelta& FrameEventHistoryDelta::operator=( + FrameEventHistoryDelta&& src) { + if (CC_UNLIKELY(!mDeltas.empty())) { + ALOGE("FrameEventHistoryDelta: Clobbering history."); + } + mDeltas = std::move(src.mDeltas); + ALOGE_IF(src.mDeltas.empty(), "Source mDeltas not empty."); + return *this; +} + size_t FrameEventHistoryDelta::minFlattenedSize() { return sizeof(uint32_t); } |