summaryrefslogtreecommitdiffstats
path: root/libs
diff options
context:
space:
mode:
authorJamie Gennis <jgennis@google.com>2012-09-06 14:54:19 -0700
committerJamie Gennis <jgennis@google.com>2012-09-09 12:58:23 -0700
commit01dbf5539bff4bece3f9bbfa55046b04a8a45e99 (patch)
tree3544410513f9a5918ca24e2e8d4d476686ea5b24 /libs
parent4fb3999cea652617be5125f8a42c257467bf3c77 (diff)
downloadframeworks_native-01dbf5539bff4bece3f9bbfa55046b04a8a45e99.zip
frameworks_native-01dbf5539bff4bece3f9bbfa55046b04a8a45e99.tar.gz
frameworks_native-01dbf5539bff4bece3f9bbfa55046b04a8a45e99.tar.bz2
SurfaceTexture: use EGL-created native fences
This change adds support for using Android fences that come from EGLSyncKHR objects as the release fence for a buffer. Change-Id: Ice192ce2ec001020f909a2018afdf0f17b24dec9
Diffstat (limited to 'libs')
-rw-r--r--libs/gui/SurfaceTexture.cpp90
1 files changed, 64 insertions, 26 deletions
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index b5872b8..c999080 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -39,6 +39,20 @@
#include <utils/String8.h>
#include <utils/Trace.h>
+// This compile option makes SurfaceTexture use the
+// EGL_ANDROID_native_fence_sync extension to create Android native fences to
+// signal when all GLES reads for a given buffer have completed. It is not
+// compatible with using the EGL_KHR_fence_sync extension for the same
+// purpose.
+#ifdef USE_NATIVE_FENCE_SYNC
+#ifdef USE_FENCE_SYNC
+#error "USE_NATIVE_FENCE_SYNC and USE_FENCE_SYNC are incompatible"
+#endif
+const bool useNativeFenceSync = true;
+#else
+const bool useNativeFenceSync = false;
+#endif
+
// This compile option makes SurfaceTexture use the EGL_KHR_fence_sync extension
// to synchronize access to the buffers. It will cause dequeueBuffer to stall,
// waiting for the GL reads for the buffer being dequeued to complete before
@@ -443,36 +457,60 @@ status_t SurfaceTexture::attachToContext(GLuint tex) {
status_t SurfaceTexture::syncForReleaseLocked(EGLDisplay dpy) {
ST_LOGV("syncForReleaseLocked");
- if (mUseFenceSync && mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
- EGLSyncKHR fence = mEglSlots[mCurrentTexture].mEglFence;
- if (fence != EGL_NO_SYNC_KHR) {
- // There is already a fence for the current slot. We need to wait
- // on that before replacing it with another fence to ensure that all
- // outstanding buffer accesses have completed before the producer
- // accesses it.
- EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000);
- if (result == EGL_FALSE) {
- ST_LOGE("syncForReleaseLocked: error waiting for previous "
- "fence: %#x", eglGetError());
+ if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
+ if (useNativeFenceSync) {
+ EGLSyncKHR sync = eglCreateSyncKHR(dpy,
+ EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
+ if (sync == EGL_NO_SYNC_KHR) {
+ ST_LOGE("syncForReleaseLocked: error creating EGL fence: %#x",
+ eglGetError());
return UNKNOWN_ERROR;
- } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
- ST_LOGE("syncForReleaseLocked: timeout waiting for previous "
- "fence");
- return TIMED_OUT;
}
- eglDestroySyncKHR(dpy, fence);
- }
+ glFlush();
+ int fenceFd = eglDupNativeFenceFDANDROID(dpy, sync);
+ if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
+ ST_LOGE("syncForReleaseLocked: error dup'ing native fence "
+ "fd: %#x", eglGetError());
+ return UNKNOWN_ERROR;
+ }
+ sp<Fence> fence(new Fence(fenceFd));
+ status_t err = addReleaseFence(mCurrentTexture, fence);
+ if (err != OK) {
+ ST_LOGE("syncForReleaseLocked: error adding release fence: "
+ "%s (%d)", strerror(-err), err);
+ return err;
+ }
+ } else if (mUseFenceSync) {
+ EGLSyncKHR fence = mEglSlots[mCurrentTexture].mEglFence;
+ if (fence != EGL_NO_SYNC_KHR) {
+ // There is already a fence for the current slot. We need to
+ // wait on that before replacing it with another fence to
+ // ensure that all outstanding buffer accesses have completed
+ // before the producer accesses it.
+ EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000);
+ if (result == EGL_FALSE) {
+ ST_LOGE("syncForReleaseLocked: error waiting for previous "
+ "fence: %#x", eglGetError());
+ return UNKNOWN_ERROR;
+ } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
+ ST_LOGE("syncForReleaseLocked: timeout waiting for previous "
+ "fence");
+ return TIMED_OUT;
+ }
+ eglDestroySyncKHR(dpy, fence);
+ }
- // Create a fence for the outstanding accesses in the current OpenGL ES
- // context.
- fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
- if (fence == EGL_NO_SYNC_KHR) {
- ST_LOGE("syncForReleaseLocked: error creating fence: %#x",
- eglGetError());
- return UNKNOWN_ERROR;
+ // Create a fence for the outstanding accesses in the current
+ // OpenGL ES context.
+ fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
+ if (fence == EGL_NO_SYNC_KHR) {
+ ST_LOGE("syncForReleaseLocked: error creating fence: %#x",
+ eglGetError());
+ return UNKNOWN_ERROR;
+ }
+ glFlush();
+ mEglSlots[mCurrentTexture].mEglFence = fence;
}
- glFlush();
- mEglSlots[mCurrentTexture].mEglFence = fence;
}
return OK;