summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Brian Anderson <brianderson@google.com> 2017-08-30 23:53:44 +0000
committer android-build-merger <android-build-merger@google.com> 2017-08-30 23:53:44 +0000
commitc2cc8f714ddf482f6c155c0d0bd05c61cfa2dea7 (patch)
treefd084bf9ec12303d9f347cf1d3775c396a552a1b
parent94ffdb29188bdefffa0d070eb9335f750ed1df72 (diff)
parentbc52c7039cc89e5cb14a8ee48fabfc70a96c0c89 (diff)
Merge fences when needed for accurate timestamps.
am: bc52c7039c Change-Id: Ib0e177944ec6a163a1572e91b04515d7e4536358
-rw-r--r--libs/gui/ConsumerBase.cpp31
1 files changed, 25 insertions, 6 deletions
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index 3d3637648c..7aa7872513 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -335,16 +335,25 @@ status_t ConsumerBase::addReleaseFenceLocked(int slot,
return OK;
}
- auto status = mSlots[slot].mFence->getStatus();
-
- if (status == Fence::Status::Invalid) {
- CB_LOGE("fence has invalid state");
+ // Check status of fences first because merging is expensive.
+ // Merging an invalid fence with any other fence results in an
+ // invalid fence.
+ auto currentStatus = mSlots[slot].mFence->getStatus();
+ if (currentStatus == Fence::Status::Invalid) {
+ CB_LOGE("Existing fence has invalid state");
return BAD_VALUE;
}
- if (status == Fence::Status::Signaled) {
+ auto incomingStatus = fence->getStatus();
+ if (incomingStatus == Fence::Status::Invalid) {
+ CB_LOGE("New fence has invalid state");
mSlots[slot].mFence = fence;
- } else { // status == Fence::Status::Unsignaled
+ return BAD_VALUE;
+ }
+
+ // If both fences are signaled or both are unsignaled, we need to merge
+ // them to get an accurate timestamp.
+ if (currentStatus == incomingStatus) {
char fenceName[32] = {};
snprintf(fenceName, 32, "%.28s:%d", mName.string(), slot);
sp<Fence> mergedFence = Fence::merge(
@@ -357,7 +366,17 @@ status_t ConsumerBase::addReleaseFenceLocked(int slot,
return BAD_VALUE;
}
mSlots[slot].mFence = mergedFence;
+ } else if (incomingStatus == Fence::Status::Unsignaled) {
+ // If one fence has signaled and the other hasn't, the unsignaled
+ // fence will approximately correspond with the correct timestamp.
+ // There's a small race if both fences signal at about the same time
+ // and their statuses are retrieved with unfortunate timing. However,
+ // by this point, they will have both signaled and only the timestamp
+ // will be slightly off; any dependencies after this point will
+ // already have been met.
+ mSlots[slot].mFence = fence;
}
+ // else if (currentStatus == Fence::Status::Unsignaled) is a no-op.
return OK;
}