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

Commit 3498e3c5 authored by Chia-I Wu's avatar Chia-I Wu
Browse files

surfaceflinger: use RenderEngine sync primitives

Update BufferLayerConsumer to use RenderEngine sync primitives.

Test: SurfaceFlinger_test
Change-Id: I142ea24ac7484b8a1b5fb6459f03861e8dabff96
parent 9f2db77e
Loading
Loading
Loading
Loading
+14 −38
Original line number Diff line number Diff line
@@ -354,7 +354,7 @@ status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item,

    // Do whatever sync ops we need to do before releasing the old slot.
    if (slot != mCurrentTexture) {
        err = syncForReleaseLocked(mEglDisplay);
        err = syncForReleaseLocked();
        if (err != NO_ERROR) {
            // Release the buffer we just acquired.  It's not safe to
            // release the old buffer, so instead we just drop the new frame.
@@ -429,26 +429,17 @@ status_t BufferLayerConsumer::bindTextureImageLocked() {
    mCurrentTextureImage->bindToTextureTarget(sTexTarget);

    // Wait for the new buffer to be ready.
    return doGLFenceWaitLocked();
    return doFenceWaitLocked();
}

status_t BufferLayerConsumer::syncForReleaseLocked(EGLDisplay dpy) {
status_t BufferLayerConsumer::syncForReleaseLocked() {
    BLC_LOGV("syncForReleaseLocked");

    if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
        if (SyncFeatures::getInstance().useNativeFenceSync()) {
            EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
            if (sync == EGL_NO_SYNC_KHR) {
                BLC_LOGE("syncForReleaseLocked: error creating EGL fence: %#x", eglGetError());
                return UNKNOWN_ERROR;
            }
            glFlush();
            int fenceFd = eglDupNativeFenceFDANDROID(dpy, sync);
            eglDestroySyncKHR(dpy, sync);
            if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
                BLC_LOGE("syncForReleaseLocked: error dup'ing native fence "
                         "fd: %#x",
                         eglGetError());
            base::unique_fd fenceFd = mRE.flush();
            if (fenceFd == -1) {
                BLC_LOGE("syncForReleaseLocked: failed to flush RenderEngine");
                return UNKNOWN_ERROR;
            }
            sp<Fence> fence(new Fence(fenceFd));
@@ -567,42 +558,27 @@ std::shared_ptr<FenceTime> BufferLayerConsumer::getCurrentFenceTime() const {
    return mCurrentFenceTime;
}

status_t BufferLayerConsumer::doGLFenceWaitLocked() const {
status_t BufferLayerConsumer::doFenceWaitLocked() const {
    if (!mRE.isCurrent()) {
        BLC_LOGE("doGLFenceWait: RenderEngine is not current");
        BLC_LOGE("doFenceWait: RenderEngine is not current");
        return INVALID_OPERATION;
    }

    if (mCurrentFence->isValid()) {
        if (SyncFeatures::getInstance().useWaitSync()) {
            // Create an EGLSyncKHR from the current fence.
            int fenceFd = mCurrentFence->dup();
            base::unique_fd fenceFd(mCurrentFence->dup());
            if (fenceFd == -1) {
                BLC_LOGE("doGLFenceWait: error dup'ing fence fd: %d", errno);
                BLC_LOGE("doFenceWait: error dup'ing fence fd: %d", errno);
                return -errno;
            }
            EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd, EGL_NONE};
            EGLSyncKHR sync = eglCreateSyncKHR(mEglDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
            if (sync == EGL_NO_SYNC_KHR) {
                close(fenceFd);
                BLC_LOGE("doGLFenceWait: error creating EGL fence: %#x", eglGetError());
                return UNKNOWN_ERROR;
            }

            // XXX: The spec draft is inconsistent as to whether this should
            // return an EGLint or void.  Ignore the return value for now, as
            // it's not strictly needed.
            eglWaitSyncKHR(mEglDisplay, sync, 0);
            EGLint eglErr = eglGetError();
            eglDestroySyncKHR(mEglDisplay, sync);
            if (eglErr != EGL_SUCCESS) {
                BLC_LOGE("doGLFenceWait: error waiting for EGL fence: %#x", eglErr);
            if (!mRE.waitFence(std::move(fenceFd))) {
                BLC_LOGE("doFenceWait: failed to wait on fence fd");
                return UNKNOWN_ERROR;
            }
        } else {
            status_t err = mCurrentFence->waitForever("BufferLayerConsumer::doGLFenceWaitLocked");
            status_t err = mCurrentFence->waitForever("BufferLayerConsumer::doFenceWaitLocked");
            if (err != NO_ERROR) {
                BLC_LOGE("doGLFenceWait: error waiting for fence: %d", err);
                BLC_LOGE("doFenceWait: error waiting for fence: %d", err);
                return err;
            }
        }
+9 −9
Original line number Diff line number Diff line
@@ -89,7 +89,7 @@ public:
    // This call may only be made while the OpenGL ES context to which the
    // target texture belongs is bound to the calling thread.
    //
    // This calls doGLFenceWait to ensure proper synchronization.
    // This calls doFenceWait to ensure proper synchronization.
    //
    // This version of updateTexImage() takes a functor that may be used to
    // reject the newly acquired buffer.  Unlike the GLConsumer version,
@@ -229,7 +229,7 @@ protected:

    // Binds mTexName and the current buffer to sTexTarget.  Uses
    // mCurrentTexture if it's set, mCurrentTextureImage if not.  If the
    // bind succeeds, this calls doGLFenceWait.
    // bind succeeds, this calls doFenceWait.
    status_t bindTextureImageLocked();

private:
@@ -301,16 +301,16 @@ private:
    // mCurrentTextureImage must not be NULL.
    void computeCurrentTransformMatrixLocked();

    // doGLFenceWaitLocked inserts a wait command into the OpenGL ES command
    // stream to ensure that it is safe for future OpenGL ES commands to
    // doFenceWaitLocked inserts a wait command into the RenderEngine command
    // stream to ensure that it is safe for future RenderEngine commands to
    // access the current texture buffer.
    status_t doGLFenceWaitLocked() const;
    status_t doFenceWaitLocked() const;

    // syncForReleaseLocked performs the synchronization needed to release the
    // current slot from an OpenGL ES context.  If needed it will set the
    // current slot's fence to guard against a producer accessing the buffer
    // before the outstanding accesses have completed.
    status_t syncForReleaseLocked(EGLDisplay dpy);
    // current slot from RenderEngine.  If needed it will set the current
    // slot's fence to guard against a producer accessing the buffer before
    // the outstanding accesses have completed.
    status_t syncForReleaseLocked();

    // sTexTarget is the GL texture target with which the GL texture object is
    // associated.