summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/gui/BufferQueueConsumer.cpp26
-rw-r--r--libs/gui/ConsumerBase.cpp8
-rw-r--r--libs/gui/GLConsumer.cpp26
-rw-r--r--libs/gui/IGraphicBufferConsumer.cpp7
-rw-r--r--libs/gui/include/gui/BufferQueueConsumer.h11
-rw-r--r--libs/gui/include/gui/ConsumerBase.h5
-rw-r--r--libs/gui/include/gui/GLConsumer.h13
-rw-r--r--libs/gui/include/gui/IGraphicBufferConsumer.h5
-rw-r--r--libs/gui/include/gui/mock/GraphicBufferConsumer.h5
-rw-r--r--libs/nativedisplay/include/surfacetexture/EGLConsumer.h15
-rw-r--r--libs/nativedisplay/include/surfacetexture/SurfaceTexture.h4
-rw-r--r--libs/nativedisplay/surfacetexture/EGLConsumer.cpp17
-rw-r--r--libs/nativedisplay/surfacetexture/ImageConsumer.cpp28
-rw-r--r--libs/nativedisplay/surfacetexture/SurfaceTexture.cpp8
14 files changed, 126 insertions, 52 deletions
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index f0125868ae..270bfbdc64 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -477,9 +477,14 @@ status_t BufferQueueConsumer::attachBuffer(int* outSlot,
return NO_ERROR;
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber,
+ const sp<Fence>& releaseFence) {
+#else
status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber,
const sp<Fence>& releaseFence, EGLDisplay eglDisplay,
EGLSyncKHR eglFence) {
+#endif
ATRACE_CALL();
ATRACE_BUFFER_INDEX(slot);
@@ -493,27 +498,6 @@ status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber,
return BAD_VALUE;
}
-#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
- if (eglFence != EGL_NO_SYNC_KHR) {
- // Most platforms will be using native fences, so it's unlikely that we'll ever have to
- // process an eglFence. Ideally we can remove this code eventually. In the mean time, do our
- // best to wait for it so the buffer stays valid, otherwise return an error to the caller.
- //
- // EGL_SYNC_FLUSH_COMMANDS_BIT_KHR so that we don't wait forever on a fence that hasn't
- // shown up on the GPU yet.
- EGLint result = eglClientWaitSyncKHR(eglDisplay, eglFence, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
- 1000000000);
- if (result == EGL_FALSE) {
- BQ_LOGE("releaseBuffer: error %#x waiting for fence", eglGetError());
- return UNKNOWN_ERROR;
- } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
- BQ_LOGE("releaseBuffer: timeout waiting for fence");
- return UNKNOWN_ERROR;
- }
- eglDestroySyncKHR(eglDisplay, eglFence);
- }
-#endif
-
sp<IProducerListener> listener;
{ // Autolock scope
std::lock_guard<std::mutex> lock(mCore->mMutex);
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index 504509dbec..3ad0e529a5 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -656,9 +656,13 @@ status_t ConsumerBase::addReleaseFenceLocked(int slot,
return OK;
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+status_t ConsumerBase::releaseBufferLocked(int slot, const sp<GraphicBuffer> graphicBuffer) {
+#else
status_t ConsumerBase::releaseBufferLocked(
int slot, const sp<GraphicBuffer> graphicBuffer,
EGLDisplay display, EGLSyncKHR eglFence) {
+#endif
if (mAbandoned) {
CB_LOGE("releaseBufferLocked: ConsumerBase is abandoned!");
return NO_INIT;
@@ -675,8 +679,12 @@ status_t ConsumerBase::releaseBufferLocked(
CB_LOGV("releaseBufferLocked: slot=%d/%" PRIu64,
slot, mSlots[slot].mFrameNumber);
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ status_t err = mConsumer->releaseBuffer(slot, mSlots[slot].mFrameNumber, mSlots[slot].mFence);
+#else
status_t err = mConsumer->releaseBuffer(slot, mSlots[slot].mFrameNumber,
display, eglFence, mSlots[slot].mFence);
+#endif
if (err == IGraphicBufferConsumer::STALE_BUFFER_SLOT) {
freeBufferLocked(slot);
}
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index 168129b1f7..052b8edfaa 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -417,18 +417,18 @@ void GLConsumer::onSlotCountChanged(int slotCount) {
}
#endif
-status_t GLConsumer::releaseBufferLocked(int buf,
- sp<GraphicBuffer> graphicBuffer,
- EGLDisplay display, EGLSyncKHR eglFence) {
+#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+status_t GLConsumer::releaseBufferLocked(int buf, sp<GraphicBuffer> graphicBuffer,
+ EGLDisplay display, EGLSyncKHR eglFence) {
// release the buffer if it hasn't already been discarded by the
// BufferQueue. This can happen, for example, when the producer of this
// buffer has reallocated the original buffer slot after this buffer
// was acquired.
- status_t err = ConsumerBase::releaseBufferLocked(
- buf, graphicBuffer, display, eglFence);
+ status_t err = ConsumerBase::releaseBufferLocked(buf, graphicBuffer, display, eglFence);
mEglSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
return err;
}
+#endif
status_t GLConsumer::updateAndReleaseLocked(const BufferItem& item,
PendingRelease* pendingRelease)
@@ -490,9 +490,14 @@ status_t GLConsumer::updateAndReleaseLocked(const BufferItem& item,
// release old buffer
if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
if (pendingRelease == nullptr) {
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ status_t status =
+ releaseBufferLocked(mCurrentTexture, mCurrentTextureImage->graphicBuffer());
+#else
status_t status = releaseBufferLocked(
mCurrentTexture, mCurrentTextureImage->graphicBuffer(),
mEglDisplay, mEglSlots[mCurrentTexture].mEglFence);
+#endif
if (status < NO_ERROR) {
GLC_LOGE("updateAndRelease: failed to release buffer: %s (%d)",
strerror(-status), status);
@@ -501,10 +506,7 @@ status_t GLConsumer::updateAndReleaseLocked(const BufferItem& item,
}
} else {
pendingRelease->currentTexture = mCurrentTexture;
- pendingRelease->graphicBuffer =
- mCurrentTextureImage->graphicBuffer();
- pendingRelease->display = mEglDisplay;
- pendingRelease->fence = mEglSlots[mCurrentTexture].mEglFence;
+ pendingRelease->graphicBuffer = mCurrentTextureImage->graphicBuffer();
pendingRelease->isPending = true;
}
}
@@ -744,6 +746,11 @@ status_t GLConsumer::syncForReleaseLocked(EGLDisplay dpy) {
return err;
}
} else if (mUseFenceSync && SyncFeatures::getInstance().useFenceSync()) {
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ // Basically all clients are using native fence syncs. If they aren't, we lose nothing
+ // by waiting here, because the alternative can cause deadlocks (b/339705065).
+ glFinish();
+#else
EGLSyncKHR fence = mEglSlots[mCurrentTexture].mEglFence;
if (fence != EGL_NO_SYNC_KHR) {
// There is already a fence for the current slot. We need to
@@ -773,6 +780,7 @@ status_t GLConsumer::syncForReleaseLocked(EGLDisplay dpy) {
}
glFlush();
mEglSlots[mCurrentTexture].mEglFence = fence;
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
}
}
diff --git a/libs/gui/IGraphicBufferConsumer.cpp b/libs/gui/IGraphicBufferConsumer.cpp
index c1b65689d6..e133532e02 100644
--- a/libs/gui/IGraphicBufferConsumer.cpp
+++ b/libs/gui/IGraphicBufferConsumer.cpp
@@ -85,6 +85,12 @@ public:
return callRemote<Signature>(Tag::ATTACH_BUFFER, slot, buffer);
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ status_t releaseBuffer(int buf, uint64_t frameNumber, const sp<Fence>& releaseFence) override {
+ using Signature = status_t (IGraphicBufferConsumer::*)(int, uint64_t, const sp<Fence>&);
+ return callRemote<Signature>(Tag::RELEASE_BUFFER, buf, frameNumber, releaseFence);
+ }
+#else
status_t releaseBuffer(int buf, uint64_t frameNumber,
EGLDisplay display __attribute__((unused)),
EGLSyncKHR fence __attribute__((unused)),
@@ -92,6 +98,7 @@ public:
using Signature = status_t (IGraphicBufferConsumer::*)(int, uint64_t, const sp<Fence>&);
return callRemote<Signature>(Tag::RELEASE_BUFFER, buf, frameNumber, releaseFence);
}
+#endif
status_t consumerConnect(const sp<IConsumerListener>& consumer, bool controlledByApp) override {
using Signature = decltype(&IGraphicBufferConsumer::consumerConnect);
diff --git a/libs/gui/include/gui/BufferQueueConsumer.h b/libs/gui/include/gui/BufferQueueConsumer.h
index e00c44eb70..f99b54beb1 100644
--- a/libs/gui/include/gui/BufferQueueConsumer.h
+++ b/libs/gui/include/gui/BufferQueueConsumer.h
@@ -65,13 +65,14 @@ public:
// any references to the just-released buffer that it might have, as if it
// had received a onBuffersReleased() call with a mask set for the released
// buffer.
- //
- // Note that the dependencies on EGL will be removed once we switch to using
- // the Android HW Sync HAL.
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ virtual status_t releaseBuffer(int slot, uint64_t frameNumber,
+ const sp<Fence>& releaseFence) override;
+#else
virtual status_t releaseBuffer(int slot, uint64_t frameNumber,
const sp<Fence>& releaseFence, EGLDisplay display,
EGLSyncKHR fence);
-
+#endif
// connect connects a consumer to the BufferQueue. Only one
// consumer may be connected, and when that consumer disconnects the
// BufferQueue is placed into the "abandoned" state, causing most
@@ -167,6 +168,7 @@ public:
// dump our state in a String
status_t dumpState(const String8& prefix, String8* outResult) const override;
+#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
// Functions required for backwards compatibility.
// These will be modified/renamed in IGraphicBufferConsumer and will be
// removed from this class at that time. See b/13306289.
@@ -176,6 +178,7 @@ public:
const sp<Fence>& releaseFence) {
return releaseBuffer(buf, frameNumber, releaseFence, display, fence);
}
+#endif
virtual status_t consumerConnect(const sp<IConsumerListener>& consumer,
bool controlledByApp) {
diff --git a/libs/gui/include/gui/ConsumerBase.h b/libs/gui/include/gui/ConsumerBase.h
index 5cd19c1583..acb0006754 100644
--- a/libs/gui/include/gui/ConsumerBase.h
+++ b/libs/gui/include/gui/ConsumerBase.h
@@ -245,10 +245,13 @@ protected:
// must take place when a buffer is released back to the BufferQueue. If
// it is overridden the derived class's implementation must call
// ConsumerBase::releaseBufferLocked.
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ virtual status_t releaseBufferLocked(int slot, const sp<GraphicBuffer> graphicBuffer);
+#else
virtual status_t releaseBufferLocked(int slot,
const sp<GraphicBuffer> graphicBuffer,
EGLDisplay display = EGL_NO_DISPLAY, EGLSyncKHR eglFence = EGL_NO_SYNC_KHR);
-
+#endif
// returns true iff the slot still has the graphicBuffer in it.
bool stillTracking(int slot, const sp<GraphicBuffer> graphicBuffer);
diff --git a/libs/gui/include/gui/GLConsumer.h b/libs/gui/include/gui/GLConsumer.h
index 30cbfa2f9f..dbf707f35f 100644
--- a/libs/gui/include/gui/GLConsumer.h
+++ b/libs/gui/include/gui/GLConsumer.h
@@ -271,6 +271,7 @@ protected:
#endif
// releaseBufferLocked overrides the ConsumerBase method to update the
// mEglSlots array in addition to the ConsumerBase.
+#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
virtual status_t releaseBufferLocked(int slot, const sp<GraphicBuffer> graphicBuffer,
EGLDisplay display = EGL_NO_DISPLAY,
EGLSyncKHR eglFence = EGL_NO_SYNC_KHR) override;
@@ -279,16 +280,14 @@ protected:
const sp<GraphicBuffer> graphicBuffer, EGLSyncKHR eglFence) {
return releaseBufferLocked(slot, graphicBuffer, mEglDisplay, eglFence);
}
+#endif
struct PendingRelease {
- PendingRelease() : isPending(false), currentTexture(-1),
- graphicBuffer(), display(nullptr), fence(nullptr) {}
+ PendingRelease() : isPending(false), currentTexture(-1), graphicBuffer() {}
bool isPending;
int currentTexture;
sp<GraphicBuffer> graphicBuffer;
- EGLDisplay display;
- EGLSyncKHR fence;
};
// This releases the buffer in the slot referenced by mCurrentTexture,
@@ -468,16 +467,18 @@ private:
// EGLSlot contains the information and object references that
// GLConsumer maintains about a BufferQueue buffer slot.
struct EglSlot {
+#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
EglSlot() : mEglFence(EGL_NO_SYNC_KHR) {}
-
+#endif
// mEglImage is the EGLImage created from mGraphicBuffer.
sp<EglImage> mEglImage;
-
+#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
// mFence is the EGL sync object that must signal before the buffer
// associated with this buffer slot may be dequeued. It is initialized
// to EGL_NO_SYNC_KHR when the buffer is created and (optionally, based
// on a compile-time option) set to a new sync object in updateTexImage.
EGLSyncKHR mEglFence;
+#endif
};
// mEglDisplay is the EGLDisplay with which this GLConsumer is currently
diff --git a/libs/gui/include/gui/IGraphicBufferConsumer.h b/libs/gui/include/gui/IGraphicBufferConsumer.h
index 56eb291335..f6b3e894c2 100644
--- a/libs/gui/include/gui/IGraphicBufferConsumer.h
+++ b/libs/gui/include/gui/IGraphicBufferConsumer.h
@@ -139,12 +139,17 @@ public:
// * the buffer slot was invalid
// * the fence was NULL
// * the buffer slot specified is not in the acquired state
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ virtual status_t releaseBuffer(int buf, uint64_t frameNumber,
+ const sp<Fence>& releaseFence) = 0;
+#else
virtual status_t releaseBuffer(int buf, uint64_t frameNumber, EGLDisplay display,
EGLSyncKHR fence, const sp<Fence>& releaseFence) = 0;
status_t releaseBuffer(int buf, uint64_t frameNumber, const sp<Fence>& releaseFence) {
return releaseBuffer(buf, frameNumber, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, releaseFence);
}
+#endif
// consumerConnect connects a consumer to the BufferQueue. Only one consumer may be connected,
// and when that consumer disconnects the BufferQueue is placed into the "abandoned" state,
diff --git a/libs/gui/include/gui/mock/GraphicBufferConsumer.h b/libs/gui/include/gui/mock/GraphicBufferConsumer.h
index 98f24c2d44..8dfd3cb1f7 100644
--- a/libs/gui/include/gui/mock/GraphicBufferConsumer.h
+++ b/libs/gui/include/gui/mock/GraphicBufferConsumer.h
@@ -18,6 +18,7 @@
#include <gmock/gmock.h>
+#include <com_android_graphics_libgui_flags.h>
#include <gui/IGraphicBufferConsumer.h>
#include <utils/RefBase.h>
@@ -33,7 +34,11 @@ public:
MOCK_METHOD3(acquireBuffer, status_t(BufferItem*, nsecs_t, uint64_t));
MOCK_METHOD1(detachBuffer, status_t(int));
MOCK_METHOD2(attachBuffer, status_t(int*, const sp<GraphicBuffer>&));
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ MOCK_METHOD3(releaseBuffer, status_t(int, uint64_t, const sp<Fence>&));
+#else
MOCK_METHOD5(releaseBuffer, status_t(int, uint64_t, EGLDisplay, EGLSyncKHR, const sp<Fence>&));
+#endif
MOCK_METHOD2(consumerConnect, status_t(const sp<IConsumerListener>&, bool));
MOCK_METHOD0(consumerDisconnect, status_t());
MOCK_METHOD1(getReleasedBuffers, status_t(uint64_t*));
diff --git a/libs/nativedisplay/include/surfacetexture/EGLConsumer.h b/libs/nativedisplay/include/surfacetexture/EGLConsumer.h
index 444722bf83..226a8a60af 100644
--- a/libs/nativedisplay/include/surfacetexture/EGLConsumer.h
+++ b/libs/nativedisplay/include/surfacetexture/EGLConsumer.h
@@ -113,18 +113,11 @@ public:
protected:
struct PendingRelease {
- PendingRelease()
- : isPending(false),
- currentTexture(-1),
- graphicBuffer(),
- display(nullptr),
- fence(nullptr) {}
+ PendingRelease() : isPending(false), currentTexture(-1), graphicBuffer() {}
bool isPending;
int currentTexture;
sp<GraphicBuffer> graphicBuffer;
- EGLDisplay display;
- EGLSyncKHR fence;
};
/**
@@ -250,13 +243,16 @@ protected:
* EGLConsumer maintains about a BufferQueue buffer slot.
*/
struct EglSlot {
- EglSlot() : mEglFence(EGL_NO_SYNC_KHR) {}
+#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ EglSlot() : mEglFence(EGL_NO_SYNC_KHR) {}
+#endif
/**
* mEglImage is the EGLImage created from mGraphicBuffer.
*/
sp<EglImage> mEglImage;
+#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
/**
* mFence is the EGL sync object that must signal before the buffer
* associated with this buffer slot may be dequeued. It is initialized
@@ -264,6 +260,7 @@ protected:
* on a compile-time option) set to a new sync object in updateTexImage.
*/
EGLSyncKHR mEglFence;
+#endif
};
/**
diff --git a/libs/nativedisplay/include/surfacetexture/SurfaceTexture.h b/libs/nativedisplay/include/surfacetexture/SurfaceTexture.h
index 006a785cb7..253aa18a24 100644
--- a/libs/nativedisplay/include/surfacetexture/SurfaceTexture.h
+++ b/libs/nativedisplay/include/surfacetexture/SurfaceTexture.h
@@ -343,9 +343,13 @@ protected:
* releaseBufferLocked overrides the ConsumerBase method to update the
* mEglSlots array in addition to the ConsumerBase.
*/
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ virtual status_t releaseBufferLocked(int slot, const sp<GraphicBuffer> graphicBuffer) override;
+#else
virtual status_t releaseBufferLocked(int slot, const sp<GraphicBuffer> graphicBuffer,
EGLDisplay display = EGL_NO_DISPLAY,
EGLSyncKHR eglFence = EGL_NO_SYNC_KHR) override;
+#endif
/**
* freeBufferLocked frees up the given buffer slot. If the slot has been
diff --git a/libs/nativedisplay/surfacetexture/EGLConsumer.cpp b/libs/nativedisplay/surfacetexture/EGLConsumer.cpp
index 3959fce008..fad0f6cd0b 100644
--- a/libs/nativedisplay/surfacetexture/EGLConsumer.cpp
+++ b/libs/nativedisplay/surfacetexture/EGLConsumer.cpp
@@ -221,7 +221,11 @@ void EGLConsumer::onAcquireBufferLocked(BufferItem* item, SurfaceTexture& st) {
}
void EGLConsumer::onReleaseBufferLocked(int buf) {
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ (void)buf;
+#else
mEglSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
+#endif
}
status_t EGLConsumer::updateAndReleaseLocked(const BufferItem& item, PendingRelease* pendingRelease,
@@ -283,10 +287,15 @@ status_t EGLConsumer::updateAndReleaseLocked(const BufferItem& item, PendingRele
// release old buffer
if (st.mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
if (pendingRelease == nullptr) {
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ status_t status = st.releaseBufferLocked(st.mCurrentTexture,
+ mCurrentTextureImage->graphicBuffer());
+#else
status_t status =
st.releaseBufferLocked(st.mCurrentTexture,
mCurrentTextureImage->graphicBuffer(), mEglDisplay,
mEglSlots[st.mCurrentTexture].mEglFence);
+#endif
if (status < NO_ERROR) {
EGC_LOGE("updateAndRelease: failed to release buffer: %s (%d)", strerror(-status),
status);
@@ -296,8 +305,6 @@ status_t EGLConsumer::updateAndReleaseLocked(const BufferItem& item, PendingRele
} else {
pendingRelease->currentTexture = st.mCurrentTexture;
pendingRelease->graphicBuffer = mCurrentTextureImage->graphicBuffer();
- pendingRelease->display = mEglDisplay;
- pendingRelease->fence = mEglSlots[st.mCurrentTexture].mEglFence;
pendingRelease->isPending = true;
}
}
@@ -502,6 +509,11 @@ status_t EGLConsumer::syncForReleaseLocked(EGLDisplay dpy, SurfaceTexture& st) {
return err;
}
} else if (st.mUseFenceSync && SyncFeatures::getInstance().useFenceSync()) {
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ // Basically all clients are using native fence syncs. If they aren't, we lose nothing
+ // by waiting here, because the alternative can cause deadlocks (b/339705065).
+ glFinish();
+#else
EGLSyncKHR fence = mEglSlots[st.mCurrentTexture].mEglFence;
if (fence != EGL_NO_SYNC_KHR) {
// There is already a fence for the current slot. We need to
@@ -531,6 +543,7 @@ status_t EGLConsumer::syncForReleaseLocked(EGLDisplay dpy, SurfaceTexture& st) {
}
glFlush();
mEglSlots[st.mCurrentTexture].mEglFence = fence;
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
}
}
diff --git a/libs/nativedisplay/surfacetexture/ImageConsumer.cpp b/libs/nativedisplay/surfacetexture/ImageConsumer.cpp
index 60e87b54d5..1ffd382b80 100644
--- a/libs/nativedisplay/surfacetexture/ImageConsumer.cpp
+++ b/libs/nativedisplay/surfacetexture/ImageConsumer.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+#define EGL_EGLEXT_PROTOTYPES
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
#include <gui/BufferQueue.h>
#include <surfacetexture/ImageConsumer.h>
#include <surfacetexture/SurfaceTexture.h>
@@ -95,10 +99,34 @@ sp<GraphicBuffer> ImageConsumer::dequeueBuffer(int* outSlotid, android_dataspace
}
// Finally release the old buffer.
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ EGLSyncKHR previousFence = mImageSlots[st.mCurrentTexture].eglFence();
+ if (previousFence != EGL_NO_SYNC_KHR) {
+ // Most platforms will be using native fences, so it's unlikely that we'll ever have to
+ // process an eglFence. Ideally we can remove this code eventually. In the mean time, do
+ // our best to wait for it so the buffer stays valid, otherwise return an error to the
+ // caller.
+ //
+ // EGL_SYNC_FLUSH_COMMANDS_BIT_KHR so that we don't wait forever on a fence that hasn't
+ // shown up on the GPU yet.
+ EGLint result = eglClientWaitSyncKHR(display, previousFence,
+ EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, 1000000000);
+ if (result == EGL_FALSE) {
+ IMG_LOGE("dequeueBuffer: error %#x waiting for fence", eglGetError());
+ } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
+ IMG_LOGE("dequeueBuffer: timeout waiting for fence");
+ }
+ eglDestroySyncKHR(display, previousFence);
+ }
+
+ status_t status = st.releaseBufferLocked(st.mCurrentTexture,
+ st.mSlots[st.mCurrentTexture].mGraphicBuffer);
+#else
status_t status =
st.releaseBufferLocked(st.mCurrentTexture,
st.mSlots[st.mCurrentTexture].mGraphicBuffer, display,
mImageSlots[st.mCurrentTexture].eglFence());
+#endif
if (status < NO_ERROR) {
IMG_LOGE("dequeueImage: failed to release buffer: %s (%d)", strerror(-status), status);
err = status;
diff --git a/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp b/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp
index ce232cc4c7..c0a1cc5c36 100644
--- a/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp
+++ b/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp
@@ -178,13 +178,21 @@ status_t SurfaceTexture::acquireBufferLocked(BufferItem* item, nsecs_t presentWh
return NO_ERROR;
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+status_t SurfaceTexture::releaseBufferLocked(int buf, sp<GraphicBuffer> graphicBuffer) {
+#else
status_t SurfaceTexture::releaseBufferLocked(int buf, sp<GraphicBuffer> graphicBuffer,
EGLDisplay display, EGLSyncKHR eglFence) {
+#endif
// release the buffer if it hasn't already been discarded by the
// BufferQueue. This can happen, for example, when the producer of this
// buffer has reallocated the original buffer slot after this buffer
// was acquired.
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ status_t err = ConsumerBase::releaseBufferLocked(buf, graphicBuffer);
+#else
status_t err = ConsumerBase::releaseBufferLocked(buf, graphicBuffer, display, eglFence);
+#endif
// We could be releasing an EGL/Vulkan buffer, even if not currently
// attached to a GL context.
mImageConsumer.onReleaseBufferLocked(buf);