summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRiley Andrews <riandrews@google.com>2014-08-15 12:27:24 -0700
committerRiley Andrews <riandrews@google.com>2014-08-19 19:27:14 +0000
commit866399093f9f60e7305f291e688abb456bace710 (patch)
tree23203e23b5b208885571aa390cd22393fd2d9b1b
parentb1f0f288e30c0448cabd46d19c60b3bd0d272f74 (diff)
downloadframeworks_native-866399093f9f60e7305f291e688abb456bace710.zip
frameworks_native-866399093f9f60e7305f291e688abb456bace710.tar.gz
frameworks_native-866399093f9f60e7305f291e688abb456bace710.tar.bz2
Take advantage of sync points during screen cap.
Do not wait for the screen capture to complete within surface flinger, instead pass a sync point back with the captured gralloc buffer. Change-Id: I7137c0e0fc710688d1d61f189159418fb27ea263
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp52
1 files changed, 35 insertions, 17 deletions
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index bbe2aa1..b9c70e0 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3111,6 +3111,7 @@ status_t SurfaceFlinger::captureScreenImplLocked(
*/
result = native_window_dequeue_buffer_and_wait(window, &buffer);
if (result == NO_ERROR) {
+ int syncFd = -1;
// create an EGLImage from the buffer so we can later
// turn it into a texture
EGLImageKHR image = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT,
@@ -3127,27 +3128,41 @@ status_t SurfaceFlinger::captureScreenImplLocked(
renderScreenImplLocked(hw, sourceCrop, reqWidth, reqHeight,
minLayerZ, maxLayerZ, true, useIdentityTransform);
- // Create a sync point and wait on it, so we know the buffer is
- // ready before we pass it along. We can't trivially call glFlush(),
- // so we use a wait flag instead.
- // TODO: pass a sync fd to queueBuffer() and let the consumer wait.
- EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, NULL);
+ // Attempt to create a sync khr object that can produce a sync point. If that
+ // isn't available, create a non-dupable sync object in the fallback path and
+ // wait on it directly.
+ EGLSyncKHR sync;
+ if (!DEBUG_SCREENSHOTS) {
+ sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
+ } else {
+ sync = EGL_NO_SYNC_KHR;
+ }
if (sync != EGL_NO_SYNC_KHR) {
- EGLint result = eglClientWaitSyncKHR(mEGLDisplay, sync,
- EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, 2000000000 /*2 sec*/);
- EGLint eglErr = eglGetError();
+ // get the sync fd
+ syncFd = eglDupNativeFenceFDANDROID(mEGLDisplay, sync);
+ if (syncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
+ ALOGW("captureScreen: failed to dup sync khr object");
+ syncFd = -1;
+ }
eglDestroySyncKHR(mEGLDisplay, sync);
- if (result == EGL_TIMEOUT_EXPIRED_KHR) {
- ALOGW("captureScreen: fence wait timed out");
+ } else {
+ // fallback path
+ sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, NULL);
+ if (sync != EGL_NO_SYNC_KHR) {
+ EGLint result = eglClientWaitSyncKHR(mEGLDisplay, sync,
+ EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, 2000000000 /*2 sec*/);
+ EGLint eglErr = eglGetError();
+ if (result == EGL_TIMEOUT_EXPIRED_KHR) {
+ ALOGW("captureScreen: fence wait timed out");
+ } else {
+ ALOGW_IF(eglErr != EGL_SUCCESS,
+ "captureScreen: error waiting on EGL fence: %#x", eglErr);
+ }
+ eglDestroySyncKHR(mEGLDisplay, sync);
} else {
- ALOGW_IF(eglErr != EGL_SUCCESS,
- "captureScreen: error waiting on EGL fence: %#x", eglErr);
+ ALOGW("captureScreen: error creating EGL fence: %#x", eglGetError());
}
- } else {
- ALOGW("captureScreen: error creating EGL fence: %#x", eglGetError());
- // not fatal
}
-
if (DEBUG_SCREENSHOTS) {
uint32_t* pixels = new uint32_t[reqWidth*reqHeight];
getRenderEngine().readPixels(0, 0, reqWidth, reqHeight, pixels);
@@ -3165,7 +3180,10 @@ status_t SurfaceFlinger::captureScreenImplLocked(
} else {
result = BAD_VALUE;
}
- window->queueBuffer(window, buffer, -1);
+ window->queueBuffer(window, buffer, syncFd);
+ if (syncFd != -1) {
+ close(syncFd);
+ }
}
} else {
result = BAD_VALUE;