diff options
author | 2016-07-23 23:37:30 -0700 | |
---|---|---|
committer | 2016-11-15 12:59:26 -0800 | |
commit | d6927fb1143398370c0885844bfb58923ef740b7 (patch) | |
tree | 209199f1c052507a71d3894cf5339191da7bd20d | |
parent | eae5819174ef95363b50affbc96c3117ccc458a6 (diff) |
Track frame events incrementally and per layer.
* Replaces FenceTracker, which was owned by SurfaceFlinger,
with FrameEventHistory, which is owned by Layer.
* Updates FrameEventHistory as events occur.
* Changes SurfaceFlinger flag "--fences" to
"--frame-events".
Test: adb shell /data/nativetest/libgui_test/libgui_test
--gtest_filter=*GetFrameTimestamps*
Change-Id: I868c2ef93964656d7e41848243433499e7f45fe7
22 files changed, 626 insertions, 467 deletions
diff --git a/include/gui/BufferQueue.h b/include/gui/BufferQueue.h index f24f13529f..8cf8b67149 100644 --- a/include/gui/BufferQueue.h +++ b/include/gui/BufferQueue.h @@ -66,8 +66,9 @@ public: virtual void onFrameReplaced(const BufferItem& item) override; virtual void onBuffersReleased() override; virtual void onSidebandStreamChanged() override; - virtual bool getFrameTimestamps(uint64_t frameNumber, - FrameTimestamps* outTimestamps) const override; + virtual bool addAndGetFrameTimestamps( + const NewFrameEventsEntry* newTimestamps, + uint64_t frameNumber, FrameTimestamps* outTimestamps) override; private: // mConsumerListener is a weak reference to the IConsumerListener. This is // the raison d'etre of ProxyConsumerListener. diff --git a/include/gui/BufferQueueProducer.h b/include/gui/BufferQueueProducer.h index 65dea0dd11..9cfb3835dc 100644 --- a/include/gui/BufferQueueProducer.h +++ b/include/gui/BufferQueueProducer.h @@ -178,7 +178,7 @@ public: // See IGraphicBufferProducer::getFrameTimestamps virtual bool getFrameTimestamps(uint64_t frameNumber, - FrameTimestamps* outTimestamps) const override; + FrameTimestamps* outTimestamps) override; // See IGraphicBufferProducer::getUniqueId virtual status_t getUniqueId(uint64_t* outId) const override; @@ -195,6 +195,10 @@ private: // BufferQueueCore::INVALID_BUFFER_SLOT otherwise int getFreeSlotLocked() const; + bool addAndGetFrameTimestamps( + const NewFrameEventsEntry* newTimestamps, + uint64_t frameNumber, FrameTimestamps* outTimestamps); + // waitForFreeSlotThenRelock finds the oldest slot in the FREE state. It may // block if there are no available slots and we are not in non-blocking // mode (producer and consumer controlled by the application). If it blocks, diff --git a/include/gui/FrameTimestamps.h b/include/gui/FrameTimestamps.h index b8bfcd7f15..6d3bd6ca23 100644 --- a/include/gui/FrameTimestamps.h +++ b/include/gui/FrameTimestamps.h @@ -17,11 +17,20 @@ #ifndef ANDROID_GUI_FRAMETIMESTAMPS_H #define ANDROID_GUI_FRAMETIMESTAMPS_H -#include <utils/Timers.h> +#include <ui/Fence.h> #include <utils/Flattenable.h> +#include <utils/StrongPointer.h> +#include <utils/Timers.h> + +#include <array> namespace android { + +struct FrameEvents; +class String8; + + enum class SupportableFrameTimestamps { REQUESTED_PRESENT, ACQUIRE, @@ -32,8 +41,14 @@ enum class SupportableFrameTimestamps { RELEASE_TIME, }; + +// The timestamps the consumer sends to the producer over binder. struct FrameTimestamps : public LightFlattenablePod<FrameTimestamps> { + FrameTimestamps() = default; + explicit FrameTimestamps(const FrameEvents& fences); + uint64_t frameNumber{0}; + nsecs_t postedTime{0}; nsecs_t requestedPresentTime{0}; nsecs_t acquireTime{0}; nsecs_t refreshStartTime{0}; @@ -43,5 +58,72 @@ struct FrameTimestamps : public LightFlattenablePod<FrameTimestamps> { nsecs_t releaseTime{0}; }; + +// A collection of timestamps corresponding to a single frame. +struct FrameEvents { + void checkFencesForCompletion(); + void dump(String8& outString) const; + + bool valid{false}; + uint64_t frameNumber{0}; + + // Whether or not certain points in the frame's life cycle have been + // encountered help us determine if timestamps aren't available because + // a) we'll just never get them or b) they're not ready yet. + bool addPostCompositeCalled{false}; + bool addRetireCalled{false}; + + nsecs_t postedTime{0}; + nsecs_t requestedPresentTime{0}; + nsecs_t latchTime{0}; + nsecs_t firstRefreshStartTime{0}; + nsecs_t lastRefreshStartTime{0}; + + nsecs_t acquireTime{0}; + nsecs_t gpuCompositionDoneTime{0}; + nsecs_t displayPresentTime{0}; + nsecs_t displayRetireTime{0}; + nsecs_t releaseTime{0}; + + sp<Fence> acquireFence{Fence::NO_FENCE}; + sp<Fence> gpuCompositionDoneFence{Fence::NO_FENCE}; + sp<Fence> displayPresentFence{Fence::NO_FENCE}; + sp<Fence> displayRetireFence{Fence::NO_FENCE}; + sp<Fence> releaseFence{Fence::NO_FENCE}; +}; + + +struct NewFrameEventsEntry { + uint64_t frameNumber{0}; + nsecs_t postedTime{0}; + nsecs_t requestedPresentTime{0}; + sp<Fence> acquireFence{Fence::NO_FENCE}; +}; + + +class FrameEventHistory { +public: + FrameEvents* getFrame(uint64_t frameNumber); + FrameEvents* getFrame(uint64_t frameNumber, size_t* iHint); + void checkFencesForCompletion(); + void dump(String8& outString) const; + + void addQueue(const NewFrameEventsEntry& newFrameEntry); + void addLatch(uint64_t frameNumber, nsecs_t latchTime); + void addPreComposition(uint64_t frameNumber, nsecs_t refreshStartTime); + void addPostComposition(uint64_t frameNumber, + sp<Fence> gpuCompositionDone, sp<Fence> displayPresent); + void addRetire(uint64_t frameNumber, sp<Fence> displayRetire); + void addRelease(uint64_t frameNumber, sp<Fence> release); + +private: + static constexpr size_t MAX_FRAME_HISTORY = 8; + std::array<FrameEvents, MAX_FRAME_HISTORY> mFrames; + size_t mQueueOffset{0}; + size_t mCompositionOffset{0}; + size_t mRetireOffset{0}; + size_t mReleaseOffset{0}; +}; + } // namespace android #endif diff --git a/include/gui/IConsumerListener.h b/include/gui/IConsumerListener.h index 0ab75900d9..8eab3c5618 100644 --- a/include/gui/IConsumerListener.h +++ b/include/gui/IConsumerListener.h @@ -82,10 +82,13 @@ public: // different stream. virtual void onSidebandStreamChanged() = 0; /* Asynchronous */ - // See IGraphicBufferProducer::getFrameTimestamps - // This queries the consumer for the timestamps - virtual bool getFrameTimestamps(uint64_t /*frameNumber*/, - FrameTimestamps* /*outTimestamps*/) const { return false; } + // Notifies the consumer of any new producer-side events and then queries + // the consumer timestamps + virtual bool addAndGetFrameTimestamps( + const NewFrameEventsEntry* /*newTimestamps*/, + uint64_t /*frameNumber*/, FrameTimestamps* /*outTimestamps*/) { + return false; + } }; diff --git a/include/gui/IGraphicBufferProducer.h b/include/gui/IGraphicBufferProducer.h index 20cffe059b..493143a9bf 100644 --- a/include/gui/IGraphicBufferProducer.h +++ b/include/gui/IGraphicBufferProducer.h @@ -594,7 +594,7 @@ public: // // If a fence has not yet signaled the timestamp returned will be 0; virtual bool getFrameTimestamps(uint64_t /*frameNumber*/, - FrameTimestamps* /*outTimestamps*/) const { return false; } + FrameTimestamps* /*outTimestamps*/) { return false; } // Returns a unique id for this BufferQueue virtual status_t getUniqueId(uint64_t* outId) const = 0; diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp index 9ba85a6dbe..bf758cea4b 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -71,6 +71,7 @@ cc_library_shared { "ConsumerBase.cpp", "CpuConsumer.cpp", "DisplayEventReceiver.cpp", + "FrameTimestamps.cpp", "GLConsumer.cpp", "GraphicBufferAlloc.cpp", "GuiConfig.cpp", diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp index 47f5eba26f..6d4335e460 100644 --- a/libs/gui/BufferQueue.cpp +++ b/libs/gui/BufferQueue.cpp @@ -61,13 +61,15 @@ void BufferQueue::ProxyConsumerListener::onSidebandStreamChanged() { } } -bool BufferQueue::ProxyConsumerListener::getFrameTimestamps( - uint64_t frameNumber, FrameTimestamps* outTimestamps) const { +bool BufferQueue::ProxyConsumerListener::addAndGetFrameTimestamps( + const NewFrameEventsEntry* newTimestamps, + uint64_t frameNumber, FrameTimestamps* outTimestamps) { sp<ConsumerListener> listener(mConsumerListener.promote()); - if (listener != NULL) { - return listener->getFrameTimestamps(frameNumber, outTimestamps); + if (listener == nullptr) { + return false; } - return false; + return listener->addAndGetFrameTimestamps( + newTimestamps, frameNumber, outTimestamps); } void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer, diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp index 81d4f31eec..6bd1cfdb0a 100644 --- a/libs/gui/BufferQueueProducer.cpp +++ b/libs/gui/BufferQueueProducer.cpp @@ -740,19 +740,19 @@ status_t BufferQueueProducer::queueBuffer(int slot, ATRACE_CALL(); ATRACE_BUFFER_INDEX(slot); - int64_t timestamp; + int64_t requestedPresentTimestamp; bool isAutoTimestamp; android_dataspace dataSpace; Rect crop(Rect::EMPTY_RECT); int scalingMode; uint32_t transform; uint32_t stickyTransform; - sp<Fence> fence; - input.deflate(×tamp, &isAutoTimestamp, &dataSpace, &crop, &scalingMode, - &transform, &fence, &stickyTransform); + sp<Fence> acquireFence; + input.deflate(&requestedPresentTimestamp, &isAutoTimestamp, &dataSpace, + &crop, &scalingMode, &transform, &acquireFence, &stickyTransform); Region surfaceDamage = input.getSurfaceDamage(); - if (fence == NULL) { + if (acquireFence == NULL) { BQ_LOGE("queueBuffer: fence is NULL"); return BAD_VALUE; } @@ -771,6 +771,7 @@ status_t BufferQueueProducer::queueBuffer(int slot, sp<IConsumerListener> frameAvailableListener; sp<IConsumerListener> frameReplacedListener; int callbackTicket = 0; + uint64_t currentFrameNumber = 0; BufferItem item; { // Autolock scope Mutex::Autolock lock(mCore->mMutex); @@ -809,8 +810,9 @@ status_t BufferQueueProducer::queueBuffer(int slot, BQ_LOGV("queueBuffer: slot=%d/%" PRIu64 " time=%" PRIu64 " dataSpace=%d" " crop=[%d,%d,%d,%d] transform=%#x scale=%s", - slot, mCore->mFrameCounter + 1, timestamp, dataSpace, - crop.left, crop.top, crop.right, crop.bottom, transform, + slot, mCore->mFrameCounter + 1, requestedPresentTimestamp, + dataSpace, crop.left, crop.top, crop.right, crop.bottom, + transform, BufferItem::scalingModeName(static_cast<uint32_t>(scalingMode))); const sp<GraphicBuffer>& graphicBuffer(mSlots[slot].mGraphicBuffer); @@ -828,11 +830,14 @@ status_t BufferQueueProducer::queueBuffer(int slot, dataSpace = mCore->mDefaultBufferDataSpace; } - mSlots[slot].mFence = fence; + mSlots[slot].mFence = acquireFence; mSlots[slot].mBufferState.queue(); + // Increment the frame counter and store a local version of it + // for use outside the lock on mCore->mMutex. ++mCore->mFrameCounter; - mSlots[slot].mFrameNumber = mCore->mFrameCounter; + currentFrameNumber = mCore->mFrameCounter; + mSlots[slot].mFrameNumber = currentFrameNumber; item.mAcquireCalled = mSlots[slot].mAcquireCalled; item.mGraphicBuffer = mSlots[slot].mGraphicBuffer; @@ -842,12 +847,12 @@ status_t BufferQueueProducer::queueBuffer(int slot, item.mTransformToDisplayInverse = (transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) != 0; item.mScalingMode = static_cast<uint32_t>(scalingMode); - item.mTimestamp = timestamp; + item.mTimestamp = requestedPresentTimestamp; item.mIsAutoTimestamp = isAutoTimestamp; item.mDataSpace = dataSpace; - item.mFrameNumber = mCore->mFrameCounter; + item.mFrameNumber = currentFrameNumber; item.mSlot = slot; - item.mFence = fence; + item.mFence = acquireFence; item.mIsDroppable = mCore->mAsyncMode || mCore->mDequeueBufferCannotBlock || (mCore->mSharedBufferMode && mCore->mSharedBufferSlot == slot); @@ -958,10 +963,20 @@ status_t BufferQueueProducer::queueBuffer(int slot, // small trade-off in favor of latency rather than throughput. mLastQueueBufferFence->waitForever("Throttling EGL Production"); } - mLastQueueBufferFence = fence; + mLastQueueBufferFence = acquireFence; mLastQueuedCrop = item.mCrop; mLastQueuedTransform = item.mTransform; + // Update and get FrameEventHistory. + nsecs_t postedTime = systemTime(SYSTEM_TIME_MONOTONIC); + NewFrameEventsEntry newFrameEventsEntry = { + currentFrameNumber, + postedTime, + requestedPresentTimestamp, + acquireFence + }; + addAndGetFrameTimestamps(&newFrameEventsEntry, 0, nullptr); + return NO_ERROR; } @@ -1449,18 +1464,28 @@ status_t BufferQueueProducer::getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer, return NO_ERROR; } -bool BufferQueueProducer::getFrameTimestamps(uint64_t frameNumber, - FrameTimestamps* outTimestamps) const { +bool BufferQueueProducer::getFrameTimestamps( + uint64_t frameNumber, FrameTimestamps* outTimestamps) { + return addAndGetFrameTimestamps(nullptr, frameNumber, outTimestamps); +} + +bool BufferQueueProducer::addAndGetFrameTimestamps( + const NewFrameEventsEntry* newTimestamps, + uint64_t frameNumber, FrameTimestamps* outTimestamps) { + if (newTimestamps == nullptr && outTimestamps == nullptr) { + return false; + } + ATRACE_CALL(); - BQ_LOGV("getFrameTimestamps, %" PRIu64, frameNumber); + BQ_LOGV("addAndGetFrameTimestamps"); sp<IConsumerListener> listener; - { Mutex::Autolock lock(mCore->mMutex); listener = mCore->mConsumerListener; } if (listener != NULL) { - return listener->getFrameTimestamps(frameNumber, outTimestamps); + return listener->addAndGetFrameTimestamps( + newTimestamps, frameNumber, outTimestamps); } return false; } diff --git a/libs/gui/FrameTimestamps.cpp b/libs/gui/FrameTimestamps.cpp new file mode 100644 index 0000000000..a919911988 --- /dev/null +++ b/libs/gui/FrameTimestamps.cpp @@ -0,0 +1,290 @@ +/* +* Copyright 2016 The Android Open Source Project +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <gui/FrameTimestamps.h> + +#include <inttypes.h> +#include <utils/String8.h> + +#include <algorithm> +#include <limits> + +namespace android { + +static inline bool isValidTimestamp(nsecs_t time) { + return time > 0 && time < INT64_MAX; +} + +// ============================================================================ +// FrameTimestamps +// ============================================================================ + +FrameTimestamps::FrameTimestamps(const FrameEvents& events) : + frameNumber(events.frameNumber), + postedTime(events.postedTime), + requestedPresentTime(events.requestedPresentTime), + acquireTime(events.acquireTime), + refreshStartTime(events.firstRefreshStartTime), + glCompositionDoneTime(events.gpuCompositionDoneTime), + displayPresentTime(events.displayPresentTime), + displayRetireTime(events.displayRetireTime), + releaseTime(events.releaseTime) {} + + +// ============================================================================ +// FrameEvents +// ============================================================================ + +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); +} + +void FrameEvents::dump(String8& outString) const +{ + if (!valid) { + return; + } + + outString.appendFormat("-- Frame %" PRIu64 "\n", frameNumber); + outString.appendFormat("--- Posted \t%" PRId64 "\n", postedTime); + outString.appendFormat("--- Req. Present\t%" PRId64 "\n", requestedPresentTime); + + outString.appendFormat("--- Latched \t"); + if (isValidTimestamp(latchTime)) { + outString.appendFormat("%" PRId64 "\n", latchTime); + } else { + outString.appendFormat("Pending\n"); + } + + outString.appendFormat("--- Refresh (First)\t"); + if (isValidTimestamp(firstRefreshStartTime)) { + outString.appendFormat("%" PRId64 "\n", firstRefreshStartTime); + } else { + outString.appendFormat("Pending\n"); + } + + outString.appendFormat("--- Refresh (Last)\t"); + if (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"); + } +} + + +// ============================================================================ +// FrameEventHistory +// ============================================================================ + +namespace { + +struct FrameNumberEqual { + FrameNumberEqual(uint64_t frameNumber) : mFrameNumber(frameNumber) {} + bool operator()(const FrameEvents& frame) { + return frame.valid && mFrameNumber == frame.frameNumber; + } + const uint64_t mFrameNumber; +}; + +} // namespace + + +FrameEvents* FrameEventHistory::getFrame(uint64_t frameNumber) { + auto frame = std::find_if( + mFrames.begin(), mFrames.end(), FrameNumberEqual(frameNumber)); + return frame == mFrames.end() ? nullptr : &(*frame); +} + +FrameEvents* FrameEventHistory::getFrame(uint64_t frameNumber, size_t* iHint) { + *iHint = std::min(*iHint, mFrames.size()); + auto hint = mFrames.begin() + *iHint; + auto frame = std::find_if( + hint, mFrames.end(), FrameNumberEqual(frameNumber)); + if (frame == mFrames.end()) { + frame = std::find_if( + mFrames.begin(), hint, FrameNumberEqual(frameNumber)); + if (frame == hint) { + return nullptr; + } + } + *iHint = static_cast<size_t>(std::distance(mFrames.begin(), frame)); + return &(*frame); +} + +void FrameEventHistory::checkFencesForCompletion() { + for (auto& frame : mFrames) { + frame.checkFencesForCompletion(); + } +} + +// Uses !|valid| as the MSB. +static bool FrameNumberLessThan( + const FrameEvents& lhs, const FrameEvents& rhs) { + if (lhs.valid == rhs.valid) { + return lhs.frameNumber < rhs.frameNumber; + } + return lhs.valid; +} + +void FrameEventHistory::dump(String8& outString) const { + auto earliestFrame = std::min_element( + mFrames.begin(), mFrames.end(), &FrameNumberLessThan); + if (!earliestFrame->valid) { + outString.appendFormat("-- N/A\n"); + return; + } + for (auto frame = earliestFrame; frame != mFrames.end(); ++frame) { + frame->dump(outString); + } + for (auto frame = mFrames.begin(); frame != earliestFrame; ++frame) { + frame->dump(outString); + } +} + +void FrameEventHistory::addQueue(const NewFrameEventsEntry& newFrameEntry) { + // Overwrite all fields of the frame with default values unless set here. + FrameEvents newTimestamps; + newTimestamps.frameNumber = newFrameEntry.frameNumber; + newTimestamps.postedTime = newFrameEntry.postedTime; + newTimestamps.requestedPresentTime = newFrameEntry.requestedPresentTime; + newTimestamps.acquireFence = newFrameEntry.acquireFence; + newTimestamps.valid = true; + mFrames[mQueueOffset] = newTimestamps; + + mQueueOffset = mQueueOffset + 1; + if (mQueueOffset >= mFrames.size()) { + mQueueOffset = 0; + } +} + +void FrameEventHistory::addLatch(uint64_t frameNumber, nsecs_t latchTime) { + FrameEvents* frame = getFrame(frameNumber, &mCompositionOffset); + if (frame == nullptr) { + ALOGE("FrameEventHistory::addLatch: Did not find frame."); + return; + } + frame->latchTime = latchTime; + return; +} + +void FrameEventHistory::addPreComposition( + uint64_t frameNumber, nsecs_t refreshStartTime) { + FrameEvents* frame = getFrame(frameNumber, &mCompositionOffset); + if (frame == nullptr) { + ALOGE("FrameEventHistory::addPreComposition: Did not find frame."); + return; + } + frame->lastRefreshStartTime = refreshStartTime; + if (!isValidTimestamp(frame->firstRefreshStartTime)) { + frame->firstRefreshStartTime = refreshStartTime; + } +} + +void FrameEventHistory::addPostComposition(uint64_t frameNumber, + sp<Fence> gpuCompositionDone, sp<Fence> displayPresent) { + FrameEvents* frame = getFrame(frameNumber, &mCompositionOffset); + if (frame == nullptr) { + ALOGE("FrameEventHistory::addPostComposition: Did not find frame."); + return; + } + + // Only get GPU and present info for the first composite. + if (!frame->addPostCompositeCalled) { + frame->addPostCompositeCalled = true; + frame->gpuCompositionDoneFence = gpuCompositionDone; + if (!frame->displayPresentFence->isValid()) { + frame->displayPresentFence = displayPresent; + } + } +} + +void FrameEventHistory::addRetire( + uint64_t frameNumber, sp<Fence> displayRetire) { + FrameEvents* frame = getFrame(frameNumber, &mRetireOffset); + if (frame == nullptr) { + ALOGE("FrameEventHistory::addRetire: Did not find frame."); + return; + } + frame->addRetireCalled = true; + frame->displayRetireFence = displayRetire; +} + +void FrameEventHistory::addRelease( + uint64_t frameNumber, sp<Fence> release) { + FrameEvents* frame = getFrame(frameNumber, &mReleaseOffset); + if (frame == nullptr) { + ALOGE("FrameEventHistory::addRelease: Did not find frame."); + return; + } + frame->releaseFence = release; +} + +} // namespace android diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp index 89f852c36b..a4de7eb99a 100644 --- a/libs/gui/IGraphicBufferProducer.cpp +++ b/libs/gui/IGraphicBufferProducer.cpp @@ -430,7 +430,7 @@ public: } virtual bool getFrameTimestamps(uint64_t frameNumber, - FrameTimestamps* outTimestamps) const { + FrameTimestamps* outTimestamps) { Parcel data, reply; status_t result = data.writeInterfaceToken( IGraphicBufferProducer::getInterfaceDescriptor()); diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index 7135ed3bd1..dd8719afd4 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -10,7 +10,6 @@ LOCAL_SRC_FILES := \ DispSync.cpp \ EventControlThread.cpp \ EventThread.cpp \ - FenceTracker.cpp \ FrameTracker.cpp \ GpuService.cpp \ Layer.cpp \ diff --git a/services/surfaceflinger/FenceTracker.cpp b/services/surfaceflinger/FenceTracker.cpp deleted file mode 100644 index 4dac0dbc4c..0000000000 --- a/services/surfaceflinger/FenceTracker.cpp +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define ATRACE_TAG ATRACE_TAG_GRAPHICS - -#include <inttypes.h> -#include "FenceTracker.h" -#include "Layer.h" -#include <utils/Trace.h> - -namespace android { - -FenceTracker::FenceTracker() : - mFrameCounter(0), - mOffset(0), - mFrames(), - mMutex() { -} - -void FenceTracker::dump(String8* outString) { - Mutex::Autolock lock(mMutex); - checkFencesForCompletion(); - - for (size_t i = 0; i < MAX_FRAME_HISTORY; i++) { - int index = (mOffset + i) % MAX_FRAME_HISTORY; - const FrameRecord& frame = mFrames[index]; - - outString->appendFormat("Frame %" PRIu64 "\n", frame.frameId); - outString->appendFormat("- Refresh start\t%" PRId64 "\n", - frame.refreshStartTime); - - if (frame.glesCompositionDoneTime) { - outString->appendFormat("- GLES done\t%" PRId64 "\n", - frame.glesCompositionDoneTime); - } else if (frame.glesCompositionDoneFence != Fence::NO_FENCE) { - outString->append("- GLES done\tNot signaled\n"); - } - - if (frame.presentTime) { - outString->appendFormat("- Present\t%" PRId64 "\n", - frame.presentTime); - } else if (frame.presentFence != Fence::NO_FENCE) { - outString->append("- Present\tNot signaled\n"); - } - - if (frame.retireTime) { - outString->appendFormat("- Retire\t%" PRId64 "\n", - frame.retireTime); - } else if (frame.retireFence != Fence::NO_FENCE) { - outString->append("- Retire\tNot signaled\n"); - } - - for (const auto& kv : frame.layers) { - const LayerRecord& layer = kv.second; - outString->appendFormat("-- %s\n", layer.name.string()); - outString->appendFormat("---- Frame # %" PRIu64 " (%s)\n", - layer.frameNumber, - layer.isGlesComposition ? "GLES" : "HWC"); - outString->appendFormat("---- Req.Present.\t%" PRId64 "\n", - layer.requestedPresentTime); - if (layer.acquireTime) { - outString->appendFormat("---- Acquire\t%" PRId64 "\n", - layer.acquireTime); - } else { - outString->append("---- Acquire\tNot signaled\n"); - } - if (layer.releaseTime) { - outString->appendFormat("---- Release\t%" PRId64 "\n", - layer.releaseTime); - } else { - outString->append("---- Release\tNot signaled\n"); - } - } - } -} - -static inline bool isValidTimestamp(nsecs_t time) { - return time > 0 && time < INT64_MAX; -} - -void FenceTracker::checkFencesForCompletion() { - ATRACE_CALL(); - for (auto& frame : mFrames) { - if (frame.presentFence != Fence::NO_FENCE) { - nsecs_t time = frame.presentFence->getSignalTime(); - if (isValidTimestamp(time)) { - frame.presentTime = time; - frame.presentFence = Fence::NO_FENCE; - } - } - if (frame.retireFence != Fence::NO_FENCE) { - nsecs_t time = frame.retireFence->getSignalTime(); - if (isValidTimestamp(time)) { - frame.retireTime = time; - frame.retireFence = Fence::NO_FENCE; - } - } - if (frame.glesCompositionDoneFence != Fence::NO_FENCE) { - nsecs_t time = frame.glesCompositionDoneFence->getSignalTime(); - if (isValidTimestamp(time)) { - frame.glesCompositionDoneTime = time; - frame.glesCompositionDoneFence = Fence::NO_FENCE; - } - } - for (auto& kv : frame.layers) { - LayerRecord& layer = kv.second; - if (layer.acquireFence != Fence::NO_FENCE) { - nsecs_t time = layer.acquireFence->getSignalTime(); - if (isValidTimestamp(time)) { - layer.acquireTime = time; - layer.acquireFence = Fence::NO_FENCE; - } - } - if (layer.releaseFence != Fence::NO_FENCE) { - nsecs_t time = layer.releaseFence->getSignalTime(); - if (isValidTimestamp(time)) { - layer.releaseTime = time; - layer.releaseFence = Fence::NO_FENCE; - } - } - } - } -} - -void FenceTracker::addFrame(nsecs_t refreshStartTime, sp<Fence> presentFence, - sp<Fence> retireFence, const Vector<sp<Layer>>& layers, - sp<Fence> glDoneFence) { - ATRACE_CALL(); - Mutex::Autolock lock(mMutex); - FrameRecord& frame = mFrames[mOffset]; - FrameRecord& prevFrame = mFrames[(mOffset + MAX_FRAME_HISTORY - 1) % - MAX_FRAME_HISTORY]; - frame.layers.clear(); - - bool wasGlesCompositionDone = false; - const size_t count = layers.size(); - for (size_t i = 0; i < count; i++) { - String8 name; - uint64_t frameNumber; - bool glesComposition; - nsecs_t requestedPresentTime; - sp<Fence> acquireFence; - sp<Fence> prevReleaseFence; - int32_t layerId = layers[i]->getSequence(); - - layers[i]->getFenceData(&name, &frameNumber, &glesComposition, - &requestedPresentTime, &acquireFence, &prevReleaseFence); - - frame.layers.emplace(std::piecewise_construct, - std::forward_as_tuple(layerId), - std::forward_as_tuple(name, frameNumber, glesComposition, - requestedPresentTime, 0, 0, acquireFence, Fence::NO_FENCE)); - auto prevLayer = prevFrame.layers.find(layerId); - if (prevLayer != prevFrame.layers.end()) { - if (frameNumber != prevLayer->second.frameNumber) { - prevLayer->second.releaseFence = prevReleaseFence; - } - } - } - - frame.frameId = mFrameCounter; - frame.refreshStartTime = refreshStartTime; - frame.presentTime = 0; - frame.retireTime = 0; - frame.glesCompositionDoneTime = 0; - frame.presentFence = presentFence; - prevFrame.retireFence = retireFence; - frame.retireFence = Fence::NO_FENCE; - frame.glesCompositionDoneFence = wasGlesCompositionDone ? glDoneFence : - Fence::NO_FENCE; - - mOffset = (mOffset + 1) % MAX_FRAME_HISTORY; - mFrameCounter++; -} - -bool FenceTracker::getFrameTimestamps(const Layer& layer, - uint64_t frameNumber, FrameTimestamps* outTimestamps) { - Mutex::Autolock lock(mMutex); - checkFencesForCompletion(); - int32_t layerId = layer.getSequence(); - - size_t i = 0; - for (; i < MAX_FRAME_HISTORY; i++) { - if (mFrames[i].layers.count(layerId) && - mFrames[i].layers[layerId].frameNumber == frameNumber) { - break; - } - } - if (i == MAX_FRAME_HISTORY) { - return false; - } - - const FrameRecord& frameRecord = mFrames[i]; - const LayerRecord& layerRecord = mFrames[i].layers[layerId]; - outTimestamps->frameNumber = frameNumber; - outTimestamps->requestedPresentTime = layerRecord.requestedPresentTime; - outTimestamps->acquireTime = layerRecord.acquireTime; - outTimestamps->refreshStartTime = frameRecord.refreshStartTime; - outTimestamps->glCompositionDoneTime = frameRecord.glesCompositionDoneTime; - outTimestamps->displayPresentTime = frameRecord.presentTime; - outTimestamps->displayRetireTime = frameRecord.retireTime; - outTimestamps->releaseTime = layerRecord.releaseTime; - return true; -} - -} // namespace android diff --git a/services/surfaceflinger/FenceTracker.h b/services/surfaceflinger/FenceTracker.h deleted file mode 100644 index 3b429d189c..0000000000 --- a/services/surfaceflinger/FenceTracker.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_FENCETRACKER_H -#define ANDROID_FENCETRACKER_H - -#include <ui/Fence.h> -#include <utils/Mutex.h> -#include <utils/RefBase.h> -#include <utils/String8.h> -#include <utils/Timers.h> -#include <utils/Vector.h> - -#include <unordered_map> - -namespace android { - -class Layer; -struct FrameTimestamps; -/* - * Keeps a circular buffer of fence/timestamp data for the last N frames in - * SurfaceFlinger. Gets timestamps for fences after they have signaled. - */ -class FenceTracker { -public: - FenceTracker(); - void dump(String8* outString); - void addFrame(nsecs_t refreshStartTime, sp<Fence> presentFence, - sp<Fence> retireFence, const Vector<sp<Layer>>& layers, - sp<Fence> glDoneFence); - bool getFrameTimestamps(const Layer& layer, uint64_t frameNumber, - FrameTimestamps* outTimestamps); - -protected: - static constexpr size_t MAX_FRAME_HISTORY = 8; - - struct LayerRecord { - String8 name; // layer name - uint64_t frameNumber; // frame number for this layer - bool isGlesComposition; // was GLES composition used for this layer? - // time the producer requested this frame be presented - nsecs_t requestedPresentTime; - nsecs_t acquireTime; // timestamp from the acquire fence - nsecs_t releaseTime; // timestamp from the release fence - sp<Fence> acquireFence; // acquire fence - sp<Fence> releaseFence; // release fence - - LayerRecord(const String8& name, uint64_t frameNumber, - bool isGlesComposition, nsecs_t requestedPresentTime, - nsecs_t acquireTime, nsecs_t releaseTime, - sp<Fence> acquireFence, sp<Fence> releaseFence) : - name(name), frameNumber(frameNumber), - isGlesComposition(isGlesComposition), - requestedPresentTime(requestedPresentTime), - acquireTime(acquireTime), releaseTime(releaseTime), - acquireFence(acquireFence), releaseFence(releaseFence) {}; - LayerRecord() : name("uninitialized"), frameNumber(0), - isGlesComposition(false), requestedPresentTime(0), - acquireTime(0), releaseTime(0), acquireFence(Fence::NO_FENCE), - releaseFence(Fence::NO_FENCE) {}; - }; - - struct FrameRecord { - // global SurfaceFlinger frame counter - uint64_t frameId; - // layer data for this frame - std::unordered_map<int32_t, LayerRecord> layers; - // timestamp for when SurfaceFlinger::handleMessageRefresh() was called - nsecs_t refreshStartTime; - // timestamp from the present fence - nsecs_t presentTime; - // timestamp from the retire fence - nsecs_t retireTime; - // timestamp from the GLES composition completion fence - nsecs_t glesCompositionDoneTime; - // primary display present fence for this frame - sp<Fence> presentFence; - // primary display retire fence for this frame - sp<Fence> retireFence; - // if GLES composition was done, the fence for its completion - sp<Fence> glesCompositionDoneFence; - - FrameRecord() : frameId(0), layers(), refreshStartTime(0), - presentTime(0), retireTime(0), glesCompositionDoneTime(0), - presentFence(Fence::NO_FENCE), retireFence(Fence::NO_FENCE), - glesCompositionDoneFence(Fence::NO_FENCE) {} - }; - - uint64_t mFrameCounter; - uint32_t mOffset; - FrameRecord mFrames[MAX_FRAME_HISTORY]; - Mutex mMutex; - - void checkFencesForCompletion(); -}; - -} - -#endif // ANDROID_FRAMETRACKER_H diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 4772fc11ab..c16af59ad2 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -80,7 +80,9 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client, mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), mOverrideScalingMode(-1), mCurrentOpacity(true), + mBufferLatched(false), mCurrentFrameNumber(0), + mPreviousFrameNumber(-1U), mRefreshPending(false), mFrameLatencyNeeded(false), mFiltering(false), @@ -1729,14 +1731,53 @@ bool Layer::shouldPresentNow(const DispSync& dispSync) const { return isDue || !isPlausible; } -bool Layer::onPreComposition() { +bool Layer::onPreComposition(nsecs_t refreshStartTime) { + if (mBufferLatched) { + Mutex::Autolock lock(mFrameEventHistoryMutex); + mFrameEventHistory.addPreComposition(mCurrentFrameNumber, refreshStartTime); + } mRefreshPending = false; return mQueuedFrames > 0 || mSidebandStreamChanged || mAutoRefresh; } -bool Layer::onPostComposition() { +bool Layer::onPostComposition(sp<Fence> glDoneFence) { + // mFrameLatencyNeeded is true when a new frame was latched for the + // composition. bool frameLatencyNeeded = mFrameLatencyNeeded; if (mFrameLatencyNeeded) { + const HWComposer& hwc = mFlinger->getHwComposer(); +#ifdef USE_HWC2 + sp<Fence> retireFence = Fence::NO_FENCE; + sp<Fence> presentFence = Fence::NO_FENCE; + sp<Fence> presentOrRetireFence = Fence::NO_FENCE; + if (hwc.retireFenceRepresentsStartOfScanout()) { + presentFence = hwc.getRetireFence(HWC_DISPLAY_PRIMARY); + presentOrRetireFence = presentFence; + } else { + retireFence = hwc.getRetireFence(HWC_DISPLAY_PRIMARY); + presentOrRetireFence = retireFence; + } + bool wasGpuComposited = mHwcLayers.count(HWC_DISPLAY_PRIMARY) ? + mHwcLayers.at(HWC_DISPLAY_PRIMARY).compositionType == + HWC2::Composition::Client : true; +#else + sp<Fence> retireFence = hwc.getDisplayFence(HWC_DISPLAY_PRIMARY); + sp<Fence> presentFence = Fence::NO_FENCE; + sp<Fence> presentOrRetireFence = retireFence; + bool wasGpuComposited = mIsGlesComposition; +#endif + + // Update mFrameEventHistory. + { + Mutex::Autolock lock(mFrameEventHistoryMutex); + mFrameEventHistory.addPostComposition(mCurrentFrameNumber, + wasGpuComposited ? glDoneFence : Fence::NO_FENCE, + presentFence); + mFrameEventHistory.addRetire(mPreviousFrameNumber, + retireFence); + } + + // Update mFrameTracker. nsecs_t desiredPresentTime = mSurfaceFlingerConsumer->getTimestamp(); mFrameTracker.setDesiredPresentTime(desiredPresentTime); @@ -1749,14 +1790,8 @@ bool Layer::onPostComposition() { mFrameTracker.setFrameReadyTime(desiredPresentTime); } - const HWComposer& hwc = mFlinger->getHwComposer(); -#ifdef USE_HWC2 - sp<Fence> presentFence = hwc.getRetireFence(HWC_DISPLAY_PRIMARY); -#else - sp<Fence> presentFence = hwc.getDisplayFence(HWC_DISPLAY_PRIMARY); -#endif - if (presentFence->isValid()) { - mFrameTracker.setActualPresentFence(presentFence); + if (presentOrRetireFence->isValid()) { + mFrameTracker.setActualPresentFence(presentOrRetireFence); } else { // The HWC doesn't support present fences, so use the refresh // timestamp instead. @@ -1773,6 +1808,9 @@ bool Layer::onPostComposition() { #ifdef USE_HWC2 void Layer::releasePendingBuffer() { mSurfaceFlingerConsumer->releasePendingBuffer(); + Mutex::Autolock lock(mFrameEventHistoryMutex); + mFrameEventHistory.addRelease(mPreviousFrameNumber, + mSurfaceFlingerConsumer->getPrevFinalReleaseFence()); } #endif @@ -1813,7 +1851,7 @@ bool Layer::allTransactionsSignaled() { return !matchingFramesFound || allTransactionsApplied; } -Region Layer::latchBuffer(bool& recomputeVisibleRegions) +Region Layer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) { ATRACE_CALL(); @@ -1937,6 +1975,19 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions) return outDirtyRegion; } + mBufferLatched = true; + mPreviousFrameNumber = mCurrentFrameNumber; + mCurrentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber(); + + { + Mutex::Autolock lock(mFrameEventHistoryMutex); + mFrameEventHistory.addLatch(mCurrentFrameNumber, latchTime); +#ifndef USE_HWC2 + mFrameEventHistory.addRelease(mPreviousFrameNumber, + mSurfaceFlingerConsumer->getPrevFinalReleaseFence()); +#endif + } + mRefreshPending = true; mFrameLatencyNeeded = true; if (oldActiveBuffer == NULL) { @@ -1972,8 +2023,6 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions) recomputeVisibleRegions = true; } - mCurrentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber(); - // Remove any sync points corresponding to the buffer which was just // latched { @@ -2158,22 +2207,32 @@ void Layer::getFrameStats(FrameStats* outStats) const { mFrameTracker.getStats(outStats); } -void Layer::getFenceData(String8* outName, uint64_t* outFrameNumber, - bool* outIsGlesComposition, nsecs_t* outRequestedPresentTime, - sp<Fence>* outAcquireFence, sp<Fence>* outPrevReleaseFence) const { - *outName = mName; - *outFrameNumber = mSurfaceFlingerConsumer->getFrameNumber(); +void Layer::dumpFrameEvents(String8& result) { + result.appendFormat("- Layer %s (%s, %p)\n", + getName().string(), getTypeId(), this); + Mutex::Autolock lock(mFrameEventHistoryMutex); + mFrameEventHistory.checkFencesForCompletion(); + mFrameEventHistory.dump(result); +} + +bool Layer::addAndGetFrameTimestamps( + const NewFrameEventsEntry* newTimestamps, + uint64_t frameNumber, FrameTimestamps *outTimestamps) { + Mutex::Autolock lock(mFrameEventHistoryMutex); + if (newTimestamps) { + mFrameEventHistory.addQueue(*newTimestamps); + } -#ifdef USE_HWC2 - *outIsGlesComposition = mHwcLayers.count(HWC_DISPLAY_PRIMARY) ? - mHwcLayers.at(HWC_DISPLAY_PRIMARY).compositionType == - HWC2::Composition::Client : true; -#else - *outIsGlesComposition = mIsGlesComposition; -#endif - *outRequestedPresentTime = mSurfaceFlingerConsumer->getTimestamp(); - *outAcquireFence = mSurfaceFlingerConsumer->getCurrentFence(); - *outPrevReleaseFence = mSurfaceFlingerConsumer->getPrevFinalReleaseFence(); + if (outTimestamps) { + FrameEvents* frameEvents = mFrameEventHistory.getFrame(frameNumber); + if (frameEvents) { + frameEvents->checkFencesForCompletion(); + *outTimestamps = FrameTimestamps(*frameEvents); + return true; + } + } + + return false; } std::vector<OccupancyTracker::Segment> Layer::getOccupancyHistory( diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 5aba69bd08..98ea053162 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -270,13 +270,13 @@ public: * called before composition. * returns true if the layer has pending updates. */ - bool onPreComposition(); + bool onPreComposition(nsecs_t refreshStartTime); /* * called after composition. * returns true if the layer latched a new buffer this frame. */ - bool onPostComposition(); + bool onPostComposition(sp<Fence> glCompositionDoneFence); #ifdef USE_HWC2 // If a buffer was replaced this frame, release the former buffer @@ -323,7 +323,7 @@ public: * operation, so this should be set only if needed). Typically this is used * to figure out if the content or size of a surface has changed. */ - Region latchBuffer(bool& recomputeVisibleRegions); + Region latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime); bool isPotentialCursor() const { return mPotentialCursor;} @@ -402,20 +402,17 @@ public: void miniDump(String8& result, int32_t hwcId) const; #endif void dumpFrameStats(String8& result) const; + void dumpFrameEvents(String8& result); void clearFrameStats(); void logFrameStats(); void getFrameStats(FrameStats* outStats) const; - void getFenceData(String8* outName, uint64_t* outFrameNumber, - bool* outIsGlesComposition, nsecs_t* outRequestedPresentTime, - sp<Fence>* outAcquireFence, sp<Fence>* outPrevReleaseFence) const; std::vector<OccupancyTracker::Segment> getOccupancyHistory(bool forceFlush); - bool getFrameTimestamps(uint64_t frameNumber, - FrameTimestamps* outTimestamps) const { - return mFlinger->getFrameTimestamps(*this, frameNumber, outTimestamps); - } + bool addAndGetFrameTimestamps( + const NewFrameEventsEntry* newTimestamps, + uint64_t frameNumber, FrameTimestamps* outTimestamps); bool getTransformToDisplayInverse() const; @@ -583,8 +580,15 @@ private: // thread-safe volatile int32_t mQueuedFrames; volatile int32_t mSidebandStreamChanged; // used like an atomic boolean + + // Timestamp history for UIAutomation. Thread safe. FrameTracker mFrameTracker; + // Timestamp history for the consumer to query. + // Accessed by both consumer and producer on main and binder threads. + Mutex mFrameEventHistoryMutex; + FrameEventHistory mFrameEventHistory; + // main thread sp<GraphicBuffer> mActiveBuffer; sp<NativeHandle> mSidebandStream; @@ -594,7 +598,9 @@ private: // We encode unset as -1. int32_t mOverrideScalingMode; bool mCurrentOpacity; + bool mBufferLatched = false; // TODO: Use mActiveBuffer? std::atomic<uint64_t> mCurrentFrameNumber; + uint64_t mPreviousFrameNumber; // Only accessed on the main thread. bool mRefreshPending; bool mFrameLatencyNeeded; // Whether filtering is forced on or not @@ -644,7 +650,7 @@ private: Condition mQueueItemCondition; Vector<BufferItem> mQueueItems; std::atomic<uint64_t> mLastFrameNumberReceived; - bool mUpdateTexImageFailed; // This is only modified from the main thread + bool mUpdateTexImageFailed; // This is only accessed on the main thread. bool mAutoRefresh; bool mFreezePositionUpdates; diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp index ffaee7a107..4604e01a5f 100644 --- a/services/surfaceflinger/MonitoredProducer.cpp +++ b/services/surfaceflinger/MonitoredProducer.cpp @@ -145,6 +145,11 @@ status_t MonitoredProducer::getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer, outTransformMatrix); } +bool MonitoredProducer::getFrameTimestamps( + uint64_t frameNumber, FrameTimestamps* outTimestamps) { + return mProducer->getFrameTimestamps(frameNumber, outTimestamps); +} + status_t MonitoredProducer::getUniqueId(uint64_t* outId) const { return mProducer->getUniqueId(outId); } diff --git a/services/surfaceflinger/MonitoredProducer.h b/services/surfaceflinger/MonitoredProducer.h index 66f6cf0bdb..5a2351f0be 100644 --- a/services/surfaceflinger/MonitoredProducer.h +++ b/services/surfaceflinger/MonitoredProducer.h @@ -63,6 +63,8 @@ public: virtual IBinder* onAsBinder(); virtual status_t setSharedBufferMode(bool sharedBufferMode) override; virtual status_t setAutoRefresh(bool autoRefresh) override; + virtual bool getFrameTimestamps(uint64_t frameNumber, + FrameTimestamps* outTimestamps) override; virtual status_t getUniqueId(uint64_t* outId) const override; private: diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 2f273ae909..8400136507 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1132,12 +1132,12 @@ void SurfaceFlinger::handleMessageRefresh() { nsecs_t refreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC); - preComposition(); + preComposition(refreshStartTime); rebuildLayerStacks(); setUpHWComposer(); doDebugFlashRegions(); doComposition(); - postComposition(refreshStartTime); + postComposition(); mPreviousPresentFence = mHwc->getRetireFence(HWC_DISPLAY_PRIMARY); @@ -1195,7 +1195,7 @@ void SurfaceFlinger::doDebugFlashRegions() } } -void SurfaceFlinger::preComposition() +void SurfaceFlinger::preComposition(nsecs_t refreshStartTime) { ATRACE_CALL(); ALOGV("preComposition"); @@ -1204,7 +1204,7 @@ void SurfaceFlinger::preComposition() const LayerVector& layers(mDrawingState.layersSortedByZ); const size_t count = layers.size(); for (size_t i=0 ; i<count ; i++) { - if (layers[i]->onPreComposition()) { + if (layers[i]->onPreComposition(refreshStartTime)) { needExtraInvalidate = true; } } @@ -1213,7 +1213,7 @@ void SurfaceFlinger::preComposition() } } -void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) +void SurfaceFlinger::postComposition() { ATRACE_CALL(); ALOGV("postComposition"); @@ -1223,10 +1223,16 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) layer->releasePendingBuffer(); } + bool hadClientComposition = mHwc->hasClientComposition(HWC_DISPLAY_PRIMARY); + + const sp<const DisplayDevice> hw(getDefaultDisplayDevice()); + sp<Fence> glCompositionDoneFence = hadClientComposition + ? hw->getClientTargetAcquireFence() + : Fence::NO_FENCE; const LayerVector& layers(mDrawingState.layersSortedByZ); const size_t count = layers.size(); for (size_t i=0 ; i<count ; i++) { - bool frameLatched = layers[i]->onPostComposition(); + bool frameLatched = layers[i]->onPostComposition(glCompositionDoneFence); if (frameLatched) { recordBufferingStats(layers[i]->getName().string(), layers[i]->getOccupancyHistory(false)); @@ -1243,26 +1249,12 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) } } - const sp<const DisplayDevice> hw(getDefaultDisplayDevice()); if (kIgnorePresentFences) { if (hw->isDisplayOn()) { enableHardwareVsync(); } } - sp<Fence> fenceTrackerPresentFence; - sp<Fence> fenceTrackerRetireFence; - if (mHwc->retireFenceRepresentsStartOfScanout()) { - fenceTrackerPresentFence = presentFence; - fenceTrackerRetireFence = Fence::NO_FENCE; - } else { - fenceTrackerPresentFence = Fence::NO_FENCE; - fenceTrackerRetireFence = presentFence; - } - mFenceTracker.addFrame(refreshStartTime, - fenceTrackerPresentFence, fenceTrackerRetireFence, - hw->getVisibleLayersSortedByZ(), hw->getClientTargetAcquireFence()); - if (mAnimCompositionPending) { mAnimCompositionPending = false; @@ -2019,6 +2011,7 @@ bool SurfaceFlinger::handlePageFlip() { ALOGV("handlePageFlip"); + nsecs_t latchTime = systemTime(); Region dirtyRegion; bool visibleRegions = false; @@ -2048,7 +2041,7 @@ bool SurfaceFlinger::handlePageFlip() } } for (auto& layer : mLayersWithQueuedFrames) { - const Region dirty(layer->latchBuffer(visibleRegions)); + const Region dirty(layer->latchBuffer(visibleRegions, latchTime)); layer->useSurfaceDamage(); const Layer::State& s(layer->getDrawingState()); invalidateLayerStack(s.layerStack, dirty); @@ -2845,9 +2838,9 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) } if ((index < numArgs) && - (args[index] == String16("--fences"))) { + (args[index] == String16("--frame-events"))) { index++; - mFenceTracker.dump(&result); + dumpFrameEventsLocked(result); dumpAll = false; } } @@ -2988,6 +2981,16 @@ void SurfaceFlinger::recordBufferingStats(const char* layerName, } } +void SurfaceFlinger::dumpFrameEventsLocked(String8& result) { + result.appendFormat("Layer frame timestamps:\n"); + + const LayerVector& currentLayers = mCurrentState.layersSortedByZ; + const size_t count = currentLayers.size(); + for (size_t i=0 ; i<count ; i++) { + currentLayers[i]->dumpFrameEvents(result); + } +} + void SurfaceFlinger::dumpBufferingStats(String8& result) const { result.append("Buffering stats:\n"); result.append(" [Layer name] <Active time> <Two buffer> " @@ -3907,11 +3910,6 @@ void SurfaceFlinger::checkScreenshot(size_t w, size_t s, size_t h, void const* v } } -bool SurfaceFlinger::getFrameTimestamps(const Layer& layer, - uint64_t frameNumber, FrameTimestamps* outTimestamps) { - return mFenceTracker.getFrameTimestamps(layer, frameNumber, outTimestamps); -} - // --------------------------------------------------------------------------- SurfaceFlinger::LayerVector::LayerVector() { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index bdb261478f..5b216ddd9c 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -53,7 +53,6 @@ #include "Barrier.h" #include "DisplayDevice.h" #include "DispSync.h" -#include "FenceTracker.h" #include "FrameTracker.h" #include "MessageQueue.h" #include "SurfaceInterceptor.h" @@ -401,8 +400,8 @@ private: const LayerVector& currentLayers, uint32_t layerStack, Region& dirtyRegion, Region& opaqueRegion); - void preComposition(); - void postComposition(nsecs_t refreshStartTime); + void preComposition(nsecs_t refreshStartTime); + void postComposition(); void rebuildLayerStacks(); void setUpHWComposer(); void doComposition(); @@ -446,14 +445,13 @@ private: void logFrameStats(); void dumpStaticScreenStats(String8& result) const; + // Not const because each Layer needs to query Fences and cache timestamps. + void dumpFrameEventsLocked(String8& result); void recordBufferingStats(const char* layerName, std::vector<OccupancyTracker::Segment>&& history); void dumpBufferingStats(String8& result) const; - bool getFrameTimestamps(const Layer& layer, uint64_t frameNumber, - FrameTimestamps* outTimestamps); - /* ------------------------------------------------------------------------ * Attributes */ @@ -519,7 +517,6 @@ private: nsecs_t mLastTransactionTime; bool mBootFinished; bool mForceFullDamage; - FenceTracker mFenceTracker; #ifdef USE_HWC2 bool mPropagateBackpressure = true; #endif diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.cpp b/services/surfaceflinger/SurfaceFlingerConsumer.cpp index 5317cc7fd8..1ef7065a28 100644 --- a/services/surfaceflinger/SurfaceFlingerConsumer.cpp +++ b/services/surfaceflinger/SurfaceFlingerConsumer.cpp @@ -248,10 +248,15 @@ void SurfaceFlingerConsumer::onSidebandStreamChanged() { } } -bool SurfaceFlingerConsumer::getFrameTimestamps(uint64_t frameNumber, - FrameTimestamps* outTimestamps) const { - sp<const Layer> l = mLayer.promote(); - return l.get() ? l->getFrameTimestamps(frameNumber, outTimestamps) : false; +bool SurfaceFlingerConsumer::addAndGetFrameTimestamps( + const NewFrameEventsEntry* newTimestamps, + uint64_t frameNumber, FrameTimestamps *outTimestamps) { + sp<Layer> l = mLayer.promote(); + if (!l.get()) { + return false; + } + return l->addAndGetFrameTimestamps( + newTimestamps, frameNumber, outTimestamps); } // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.h b/services/surfaceflinger/SurfaceFlingerConsumer.h index cb4c334d32..0f46ddc797 100644 --- a/services/surfaceflinger/SurfaceFlingerConsumer.h +++ b/services/surfaceflinger/SurfaceFlingerConsumer.h @@ -37,7 +37,7 @@ public: }; SurfaceFlingerConsumer(const sp<IGraphicBufferConsumer>& consumer, - uint32_t tex, const Layer* layer) + uint32_t tex, Layer* layer) : GLConsumer(consumer, tex, GLConsumer::TEXTURE_EXTERNAL, false, false), mTransformToDisplayInverse(false), mSurfaceDamage(), mLayer(layer) {} @@ -84,8 +84,9 @@ public: void releasePendingBuffer(); #endif - virtual bool getFrameTimestamps(uint64_t frameNumber, - FrameTimestamps* outTimestamps) const override; + virtual bool addAndGetFrameTimestamps( + const NewFrameEventsEntry* newTimestamps, + uint64_t frameNumber, FrameTimestamps* outTimestamps) override; private: virtual void onSidebandStreamChanged(); @@ -107,7 +108,7 @@ private: #endif // The layer for this SurfaceFlingerConsumer - wp<const Layer> mLayer; + const wp<Layer> mLayer; }; // ---------------------------------------------------------------------------- diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp index 0143d99934..3bdb0214f1 100644 --- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp +++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp @@ -1068,12 +1068,12 @@ void SurfaceFlinger::handleMessageRefresh() { nsecs_t refreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC); - preComposition(); + preComposition(refreshStartTime); rebuildLayerStacks(); setUpHWComposer(); doDebugFlashRegions(); doComposition(); - postComposition(refreshStartTime); + postComposition(); } void SurfaceFlinger::doDebugFlashRegions() @@ -1116,13 +1116,13 @@ void SurfaceFlinger::doDebugFlashRegions() } } -void SurfaceFlinger::preComposition() +void SurfaceFlinger::preComposition(nsecs_t refreshStartTime) { bool needExtraInvalidate = false; const LayerVector& layers(mDrawingState.layersSortedByZ); const size_t count = layers.size(); for (size_t i=0 ; i<count ; i++) { - if (layers[i]->onPreComposition()) { + if (layers[i]->onPreComposition(refreshStartTime)) { needExtraInvalidate = true; } } @@ -1131,19 +1131,28 @@ void SurfaceFlinger::preComposition() } } -void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) +void SurfaceFlinger::postComposition() { + const HWComposer& hwc = getHwComposer(); + const sp<const DisplayDevice> hw(getDefaultDisplayDevice()); + + bool hadGlesComposition = + getHwComposer().hasGlesComposition(hw->getHwcDisplayId()); + sp<Fence> glCompositionDoneFence = hadGlesComposition + ? hw->getClientTargetAcquireFence() + : Fence::NO_FENCE; + const LayerVector& layers(mDrawingState.layersSortedByZ); const size_t count = layers.size(); for (size_t i=0 ; i<count ; i++) { - bool frameLatched = layers[i]->onPostComposition(); + bool frameLatched = layers[i]->onPostComposition( + glCompositionDoneFence); if (frameLatched) { recordBufferingStats(layers[i]->getName().string(), layers[i]->getOccupancyHistory(false)); } } - const HWComposer& hwc = getHwComposer(); sp<Fence> presentFence = hwc.getDisplayFence(HWC_DISPLAY_PRIMARY); if (presentFence->isValid()) { @@ -1154,17 +1163,12 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) } } - const sp<const DisplayDevice> hw(getDefaultDisplayDevice()); if (kIgnorePresentFences) { if (hw->isDisplayOn()) { enableHardwareVsync(); } } - // The present fence is actually a retire fence in HWC1. - mFenceTracker.addFrame(refreshStartTime, Fence::NO_FENCE, presentFence, - hw->getVisibleLayersSortedByZ(), hw->getClientTargetAcquireFence()); - if (mAnimCompositionPending) { mAnimCompositionPending = false; @@ -1932,6 +1936,7 @@ void SurfaceFlinger::invalidateLayerStack(uint32_t layerStack, bool SurfaceFlinger::handlePageFlip() { + nsecs_t latchTime = systemTime(); Region dirtyRegion; bool visibleRegions = false; @@ -1963,7 +1968,7 @@ bool SurfaceFlinger::handlePageFlip() } for (size_t i = 0, count = layersWithQueuedFrames.size() ; i<count ; i++) { Layer* layer = layersWithQueuedFrames[i]; - const Region dirty(layer->latchBuffer(visibleRegions)); + const Region dirty(layer->latchBuffer(visibleRegions, latchTime)); layer->useSurfaceDamage(); const Layer::State& s(layer->getDrawingState()); invalidateLayerStack(s.layerStack, dirty); @@ -2755,9 +2760,9 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) } if ((index < numArgs) && - (args[index] == String16("--fences"))) { + (args[index] == String16("--frame-events"))) { index++; - mFenceTracker.dump(&result); + dumpFrameEventsLocked(result); dumpAll = false; } } @@ -2880,6 +2885,16 @@ void SurfaceFlinger::dumpStaticScreenStats(String8& result) const NUM_BUCKETS - 1, bucketTimeSec, percent); } +void SurfaceFlinger::dumpFrameEventsLocked(String8& result) { + result.appendFormat("Layer frame timestamps:\n"); + + const LayerVector& currentLayers = mCurrentState.layersSortedByZ; + const size_t count = currentLayers.size(); + for (size_t i=0 ; i<count ; i++) { + currentLayers[i]->dumpFrameEvents(result); + } +} + void SurfaceFlinger::recordBufferingStats(const char* layerName, std::vector<OccupancyTracker::Segment>&& history) { Mutex::Autolock lock(mBufferingStatsMutex); @@ -3754,11 +3769,6 @@ status_t SurfaceFlinger::captureScreenImplLocked( return result; } -bool SurfaceFlinger::getFrameTimestamps(const Layer& layer, - uint64_t frameNumber, FrameTimestamps* outTimestamps) { - return mFenceTracker.getFrameTimestamps(layer, frameNumber, outTimestamps); -} - void SurfaceFlinger::checkScreenshot(size_t w, size_t s, size_t h, void const* vaddr, const sp<const DisplayDevice>& hw, uint32_t minLayerZ, uint32_t maxLayerZ) { if (DEBUG_SCREENSHOTS) { |