Add support for latching unsignaled buffers in Skia RenderEngine.
When we re-added support for latching unsignaled buffers we forgot to
propagate this support to Skia RenderEngine, since we were assuming that
latching unsignaled buffers would no longer be supported.
Because partners are still relying on latching unsignaled buffers being
available for good performance in some use-cases, Skia RenderEngine
needs to wait on incoming buffer fences to prevent tearing.
Bug: 196201621
Bug: 195033578
Test: atest librenderengine_test
Merged-In: I1f3be882e55de20bdbfa3bf92bf0b8f88b8bc3ea
Change-Id: I1f3be882e55de20bdbfa3bf92bf0b8f88b8bc3ea
(cherry picked from commit 4ee7b493f770fefc81076131913061cfd407288f)
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
index 3c59f11..94023e6 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -424,14 +424,28 @@
return fenceFd;
}
-bool SkiaGLRenderEngine::waitFence(base::unique_fd fenceFd) {
+void SkiaGLRenderEngine::waitFence(base::borrowed_fd fenceFd) {
+ if (fenceFd.get() >= 0 && !waitGpuFence(fenceFd)) {
+ ATRACE_NAME("SkiaGLRenderEngine::waitFence");
+ sync_wait(fenceFd.get(), -1);
+ }
+}
+
+bool SkiaGLRenderEngine::waitGpuFence(base::borrowed_fd fenceFd) {
if (!gl::GLExtensions::getInstance().hasNativeFenceSync() ||
!gl::GLExtensions::getInstance().hasWaitSync()) {
return false;
}
+ // Duplicate the fence for passing to eglCreateSyncKHR.
+ base::unique_fd fenceDup(dup(fenceFd.get()));
+ if (fenceDup.get() < 0) {
+ ALOGE("failed to create duplicate fence fd: %d", fenceDup.get());
+ return false;
+ }
+
// release the fd and transfer the ownership to EGLSync
- EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd.release(), EGL_NONE};
+ EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceDup.release(), EGL_NONE};
EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
if (sync == EGL_NO_SYNC_KHR) {
ALOGE("failed to create EGL native fence sync: %#x", eglGetError());
@@ -726,14 +740,6 @@
return NO_ERROR;
}
- if (bufferFence.get() >= 0) {
- // Duplicate the fence for passing to waitFence.
- base::unique_fd bufferFenceDup(dup(bufferFence.get()));
- if (bufferFenceDup < 0 || !waitFence(std::move(bufferFenceDup))) {
- ATRACE_NAME("Waiting before draw");
- sync_wait(bufferFence.get(), -1);
- }
- }
if (buffer == nullptr) {
ALOGE("No output buffer provided. Aborting GPU composition.");
return BAD_VALUE;
@@ -758,6 +764,9 @@
true, mTextureCleanupMgr);
}
+ // wait on the buffer to be ready to use prior to using it
+ waitFence(bufferFence);
+
const ui::Dataspace dstDataspace =
mUseColorManagement ? display.outputDataspace : ui::Dataspace::V0_SRGB_LINEAR;
sk_sp<SkSurface> dstSurface = surfaceTextureRef->getOrCreateSurface(dstDataspace, grContext);
@@ -1014,6 +1023,12 @@
false, mTextureCleanupMgr);
}
+ // if the layer's buffer has a fence, then we must must respect the fence prior to using
+ // the buffer.
+ if (layer->source.buffer.fence != nullptr) {
+ waitFence(layer->source.buffer.fence->get());
+ }
+
// isOpaque means we need to ignore the alpha in the image,
// replacing it with the alpha specified by the LayerSettings. See
// https://developer.android.com/reference/android/view/SurfaceControl.Builder#setOpaque(boolean)
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h
index a852bbc..238ad8f 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.h
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.h
@@ -99,7 +99,10 @@
inline GrDirectContext* getActiveGrContext() const;
base::unique_fd flush();
- bool waitFence(base::unique_fd fenceFd);
+ // waitFence attempts to wait in the GPU, and if unable to waits on the CPU instead.
+ void waitFence(base::borrowed_fd fenceFd);
+ bool waitGpuFence(base::borrowed_fd fenceFd);
+
void initCanvas(SkCanvas* canvas, const DisplaySettings& display);
void drawShadow(SkCanvas* canvas, const SkRRect& casterRRect,
const ShadowSettings& shadowSettings);