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
This commit is contained in:
parent
b1f0f288e3
commit
866399093f
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user