am 86639909: Take advantage of sync points during screen cap.

* commit '866399093f9f60e7305f291e688abb456bace710':
  Take advantage of sync points during screen cap.
This commit is contained in:
Riley Andrews 2014-08-19 20:02:07 +00:00 committed by Android Git Automerger
commit 66a9921997

View File

@ -3111,6 +3111,7 @@ status_t SurfaceFlinger::captureScreenImplLocked(
*/ */
result = native_window_dequeue_buffer_and_wait(window, &buffer); result = native_window_dequeue_buffer_and_wait(window, &buffer);
if (result == NO_ERROR) { if (result == NO_ERROR) {
int syncFd = -1;
// create an EGLImage from the buffer so we can later // create an EGLImage from the buffer so we can later
// turn it into a texture // turn it into a texture
EGLImageKHR image = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT, EGLImageKHR image = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT,
@ -3127,27 +3128,41 @@ status_t SurfaceFlinger::captureScreenImplLocked(
renderScreenImplLocked(hw, sourceCrop, reqWidth, reqHeight, renderScreenImplLocked(hw, sourceCrop, reqWidth, reqHeight,
minLayerZ, maxLayerZ, true, useIdentityTransform); minLayerZ, maxLayerZ, true, useIdentityTransform);
// Create a sync point and wait on it, so we know the buffer is // Attempt to create a sync khr object that can produce a sync point. If that
// ready before we pass it along. We can't trivially call glFlush(), // isn't available, create a non-dupable sync object in the fallback path and
// so we use a wait flag instead. // wait on it directly.
// TODO: pass a sync fd to queueBuffer() and let the consumer wait. EGLSyncKHR sync;
EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, NULL); if (!DEBUG_SCREENSHOTS) {
sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
} else {
sync = EGL_NO_SYNC_KHR;
}
if (sync != EGL_NO_SYNC_KHR) {
// 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);
} else {
// fallback path
sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, NULL);
if (sync != EGL_NO_SYNC_KHR) { if (sync != EGL_NO_SYNC_KHR) {
EGLint result = eglClientWaitSyncKHR(mEGLDisplay, sync, EGLint result = eglClientWaitSyncKHR(mEGLDisplay, sync,
EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, 2000000000 /*2 sec*/); EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, 2000000000 /*2 sec*/);
EGLint eglErr = eglGetError(); EGLint eglErr = eglGetError();
eglDestroySyncKHR(mEGLDisplay, sync);
if (result == EGL_TIMEOUT_EXPIRED_KHR) { if (result == EGL_TIMEOUT_EXPIRED_KHR) {
ALOGW("captureScreen: fence wait timed out"); ALOGW("captureScreen: fence wait timed out");
} else { } else {
ALOGW_IF(eglErr != EGL_SUCCESS, ALOGW_IF(eglErr != EGL_SUCCESS,
"captureScreen: error waiting on EGL fence: %#x", eglErr); "captureScreen: error waiting on EGL fence: %#x", eglErr);
} }
eglDestroySyncKHR(mEGLDisplay, sync);
} else { } else {
ALOGW("captureScreen: error creating EGL fence: %#x", eglGetError()); ALOGW("captureScreen: error creating EGL fence: %#x", eglGetError());
// not fatal
} }
}
if (DEBUG_SCREENSHOTS) { if (DEBUG_SCREENSHOTS) {
uint32_t* pixels = new uint32_t[reqWidth*reqHeight]; uint32_t* pixels = new uint32_t[reqWidth*reqHeight];
getRenderEngine().readPixels(0, 0, reqWidth, reqHeight, pixels); getRenderEngine().readPixels(0, 0, reqWidth, reqHeight, pixels);
@ -3165,7 +3180,10 @@ status_t SurfaceFlinger::captureScreenImplLocked(
} else { } else {
result = BAD_VALUE; result = BAD_VALUE;
} }
window->queueBuffer(window, buffer, -1); window->queueBuffer(window, buffer, syncFd);
if (syncFd != -1) {
close(syncFd);
}
} }
} else { } else {
result = BAD_VALUE; result = BAD_VALUE;