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
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 7135ed3..dd8719a 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -10,7 +10,6 @@
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 4dac0db..0000000
--- 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 3b429d1..0000000
--- 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 4772fc1..c16af59 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -80,7 +80,9 @@
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 @@
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 @@
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 @@
#ifdef USE_HWC2
void Layer::releasePendingBuffer() {
mSurfaceFlingerConsumer->releasePendingBuffer();
+ Mutex::Autolock lock(mFrameEventHistoryMutex);
+ mFrameEventHistory.addRelease(mPreviousFrameNumber,
+ mSurfaceFlingerConsumer->getPrevFinalReleaseFence());
}
#endif
@@ -1813,7 +1851,7 @@
return !matchingFramesFound || allTransactionsApplied;
}
-Region Layer::latchBuffer(bool& recomputeVisibleRegions)
+Region Layer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime)
{
ATRACE_CALL();
@@ -1937,6 +1975,19 @@
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 @@
recomputeVisibleRegions = true;
}
- mCurrentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber();
-
// Remove any sync points corresponding to the buffer which was just
// latched
{
@@ -2158,22 +2207,32 @@
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);
+}
-#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();
+bool Layer::addAndGetFrameTimestamps(
+ const NewFrameEventsEntry* newTimestamps,
+ uint64_t frameNumber, FrameTimestamps *outTimestamps) {
+ Mutex::Autolock lock(mFrameEventHistoryMutex);
+ if (newTimestamps) {
+ mFrameEventHistory.addQueue(*newTimestamps);
+ }
+
+ 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 5aba69b..98ea053 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -270,13 +270,13 @@
* 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 @@
* 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 @@
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 @@
// 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 @@
// 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 @@
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 ffaee7a..4604e01 100644
--- a/services/surfaceflinger/MonitoredProducer.cpp
+++ b/services/surfaceflinger/MonitoredProducer.cpp
@@ -145,6 +145,11 @@
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 66f6cf0..5a2351f 100644
--- a/services/surfaceflinger/MonitoredProducer.h
+++ b/services/surfaceflinger/MonitoredProducer.h
@@ -63,6 +63,8 @@
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 2f273ae..8400136 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1132,12 +1132,12 @@
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::preComposition()
+void SurfaceFlinger::preComposition(nsecs_t refreshStartTime)
{
ATRACE_CALL();
ALOGV("preComposition");
@@ -1204,7 +1204,7 @@
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::postComposition(nsecs_t refreshStartTime)
+void SurfaceFlinger::postComposition()
{
ATRACE_CALL();
ALOGV("postComposition");
@@ -1223,10 +1223,16 @@
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 @@
}
}
- 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 @@
{
ALOGV("handlePageFlip");
+ nsecs_t latchTime = systemTime();
Region dirtyRegion;
bool visibleRegions = false;
@@ -2048,7 +2041,7 @@
}
}
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 @@
}
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::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 @@
}
}
-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 bdb2614..5b216dd 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 @@
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 @@
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 @@
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 5317cc7..1ef7065 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.cpp
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
@@ -248,10 +248,15 @@
}
}
-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 cb4c334..0f46ddc 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.h
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.h
@@ -37,7 +37,7 @@
};
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 @@
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 @@
#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 0143d99..3bdb021 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -1068,12 +1068,12 @@
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::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::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 @@
}
}
- 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 @@
bool SurfaceFlinger::handlePageFlip()
{
+ nsecs_t latchTime = systemTime();
Region dirtyRegion;
bool visibleRegions = false;
@@ -1963,7 +1968,7 @@
}
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 @@
}
if ((index < numArgs) &&
- (args[index] == String16("--fences"))) {
+ (args[index] == String16("--frame-events"))) {
index++;
- mFenceTracker.dump(&result);
+ dumpFrameEventsLocked(result);
dumpAll = false;
}
}
@@ -2880,6 +2885,16 @@
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 @@
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) {