Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6216446a authored by Alec Mouri's avatar Alec Mouri Committed by Derek Sollenberger
Browse files

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 4ee7b493)
parent 5bcc5bd9
Loading
Loading
Loading
Loading
+25 −10
Original line number Diff line number Diff line
@@ -424,14 +424,28 @@ base::unique_fd SkiaGLRenderEngine::flush() {
    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 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display,
        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 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display,
                                                               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 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display,
                                                      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)
+4 −1
Original line number Diff line number Diff line
@@ -99,7 +99,10 @@ private:
    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);