Pass fence to HWC on first use of buffer
Also do a CPU-wait on the fence before using it for GL composition.
Change-Id: I0f645a42a44803276cae11b904e5a26d65871562
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 6aba16a..5b9327d 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -60,6 +60,7 @@
mCurrentOpacity(true),
mRefreshPending(false),
mFrameLatencyNeeded(false),
+ mNeedHwcFence(false),
mFrameLatencyOffset(0),
mFormat(PIXEL_FORMAT_NONE),
mGLExtensions(GLExtensions::getInstance()),
@@ -299,6 +300,20 @@
// NOTE: buffer can be NULL if the client never drew into this
// layer yet, or if we ran out of memory
layer.setBuffer(buffer);
+
+ if (mNeedHwcFence) {
+ sp<Fence> fence = mSurfaceTexture->getCurrentFence();
+ if (fence.get()) {
+ int fenceFd = fence->dup();
+ if (fenceFd == -1) {
+ ALOGW("failed to dup layer fence, skipping sync: %d", errno);
+ }
+ layer.setAcquireFenceFd(fenceFd);
+ }
+ mNeedHwcFence = false;
+ } else {
+ layer.setAcquireFenceFd(-1);
+ }
}
void Layer::onDraw(const DisplayHardware& hw, const Region& clip) const
@@ -333,6 +348,15 @@
return;
}
+ // TODO: replace this with a server-side wait
+ sp<Fence> fence = mSurfaceTexture->getCurrentFence();
+ if (fence.get()) {
+ status_t err = fence->wait(Fence::TIMEOUT_NEVER);
+ ALOGW_IF(err != OK, "Layer::onDraw: failed waiting for fence: %d", err);
+ // Go ahead and draw the buffer anyway; no matter what we do the screen
+ // is probably going to have something visibly wrong.
+ }
+
if (!isProtected()) {
// TODO: we could be more subtle with isFixedSize()
const bool useFiltering = getFiltering() || needsFiltering() || isFixedSize();
@@ -627,6 +651,7 @@
mRefreshPending = true;
mFrameLatencyNeeded = true;
+ mNeedHwcFence = true;
if (oldActiveBuffer == NULL) {
// the first time we receive a buffer, we need to trigger a
// geometry invalidation.