diff options
author | Riley Andrews <riandrews@google.com> | 2014-08-15 12:27:24 -0700 |
---|---|---|
committer | Riley Andrews <riandrews@google.com> | 2014-08-19 19:27:14 +0000 |
commit | 866399093f9f60e7305f291e688abb456bace710 (patch) | |
tree | 23203e23b5b208885571aa390cd22393fd2d9b1b | |
parent | b1f0f288e30c0448cabd46d19c60b3bd0d272f74 (diff) | |
download | frameworks_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.cpp | 52 |
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; |