Release virtual display buffer immediately after HWC set
Previously we only queued a virtual display buffer to the sink when
the next frame was about to be displayed. This may delay the "last"
frame of an animation indefinitely. Now we queue the buffer as soon as
HWC set() returns and gives us the release fence.
Bug: 8384764
Change-Id: I3844a188e0f6ef6ff28f3e11477cfa063a924b1a
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 433e1eb..fac6c3e 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -26,16 +26,14 @@
: mHwc(hwc),
mDisplayId(disp),
mSource(new BufferQueueInterposer(sink, name)),
- mName(name),
- mReleaseFence(Fence::NO_FENCE)
+ mName(name)
{}
VirtualDisplaySurface::~VirtualDisplaySurface() {
if (mAcquiredBuffer != NULL) {
- status_t result = mSource->releaseBuffer(mReleaseFence);
+ status_t result = mSource->releaseBuffer(Fence::NO_FENCE);
ALOGE_IF(result != NO_ERROR, "VirtualDisplaySurface \"%s\": "
- "failed to release previous buffer: %d",
- mName.string(), result);
+ "failed to release buffer: %d", mName.string(), result);
}
}
@@ -52,12 +50,10 @@
status_t result = NO_ERROR;
if (mAcquiredBuffer != NULL) {
- result = mSource->releaseBuffer(mReleaseFence);
- ALOGE_IF(result != NO_ERROR, "VirtualDisplaySurface \"%s\": "
- "failed to release previous buffer: %d",
- mName.string(), result);
- mAcquiredBuffer.clear();
- mReleaseFence = Fence::NO_FENCE;
+ ALOGE("VirtualDisplaySurface \"%s\": "
+ "advanceFrame called twice without onFrameCommitted",
+ mName.string());
+ return INVALID_OPERATION;
}
sp<Fence> fence;
@@ -74,25 +70,15 @@
return mHwc.fbPost(mDisplayId, fence, mAcquiredBuffer);
}
-status_t VirtualDisplaySurface::setReleaseFenceFd(int fenceFd) {
- if (fenceFd >= 0) {
- sp<Fence> fence(new Fence(fenceFd));
- Mutex::Autolock lock(mMutex);
- sp<Fence> mergedFence = Fence::merge(
- String8::format("VirtualDisplaySurface \"%s\"",
- mName.string()),
- mReleaseFence, fence);
- if (!mergedFence->isValid()) {
- ALOGE("VirtualDisplaySurface \"%s\": failed to merge release fence",
- mName.string());
- // synchronization is broken, the best we can do is hope fences
- // signal in order so the new fence will act like a union
- mReleaseFence = fence;
- return BAD_VALUE;
- }
- mReleaseFence = mergedFence;
+void VirtualDisplaySurface::onFrameCommitted(int fenceFd) {
+ Mutex::Autolock lock(mMutex);
+ sp<Fence> fence(new Fence(fenceFd));
+ if (mAcquiredBuffer != NULL) {
+ status_t result = mSource->releaseBuffer(fence);
+ ALOGE_IF(result != NO_ERROR, "VirtualDisplaySurface \"%s\": "
+ "failed to release buffer: %d", mName.string(), result);
+ mAcquiredBuffer.clear();
}
- return NO_ERROR;
}
void VirtualDisplaySurface::dump(String8& result) const {