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

Commit 6fbb788f authored by chaviw's avatar chaviw
Browse files

Fix blur in ViewRootImpl

The blur code in ViewRootImpl had a few issues

1. The transaction was applied or merged in frameCompleteCallback. This
is too late since the frame could have already been sent to
SurfaceFlinger and possibly latched already. We need to make sure we
apply or merge the transaction before latching. Therefore, moved the
blur request code into the frameCallback, which is invoked before the
buffers are swapped.

2. The blur code was using the blast sync transaction. This means the
blur would only get applied if a request to sync transactions was
called, which isn't very often. Instead, use mergeWithNextTransaction
which will send the transaction to the BBQ. The BBQ will either apply
it when the buffers are swapped or merge with a pending transaction that
is applied later to work with blast sync. This ensures the transaction
is synchronized with the correct frame

Test: manual
Bug: 174145445
Change-Id: Id36719c03f18739513e3198602c8a7ec4fd8da69
parent b5048e48
Loading
Loading
Loading
Loading
+69 −67
Original line number Diff line number Diff line
@@ -3868,8 +3868,6 @@ public final class ViewRootImpl implements ViewParent,
    private HardwareRenderer.FrameCompleteCallback createFrameCompleteCallback(Handler handler,
            boolean reportNextDraw, ArrayList<Runnable> commitCallbacks) {
        return frameNr -> {
            mBlurRegionAggregator.dispatchBlurTransactionIfNeeded(frameNr);

            if (DEBUG_BLAST) {
                Log.d(mTag, "Received frameCompleteCallback frameNum=" + frameNr);
            }
@@ -3903,8 +3901,7 @@ public final class ViewRootImpl implements ViewParent,
                .captureFrameCommitCallbacks();
        final boolean needFrameCompleteCallback =
                mNextDrawUseBLASTSyncTransaction || mReportNextDraw
                        || (commitCallbacks != null && commitCallbacks.size() > 0)
                        || mBlurRegionAggregator.hasRegions();
                        || (commitCallbacks != null && commitCallbacks.size() > 0);
        if (needFrameCompleteCallback) {
            if (DEBUG_BLAST) {
                Log.d(mTag, "Creating frameCompleteCallback"
@@ -3921,28 +3918,61 @@ public final class ViewRootImpl implements ViewParent,
        return false;
    }

    /**
     * The callback will run on a worker thread pool from the render thread.
     */
    private HardwareRenderer.FrameDrawingCallback createFrameDrawingCallback(
            boolean addTransactionComplete) {
        return frame -> {
    private void addFrameCallbackIfNeeded() {
        boolean nextDrawUseBlastSync = mNextDrawUseBLASTSyncTransaction;
        boolean hasBlur = mBlurRegionAggregator.hasRegions();
        boolean reportNextDraw = mReportNextDraw;
        boolean addTransactionComplete = mSendNextFrameToWm;

        if (!nextDrawUseBlastSync && !reportNextDraw && !hasBlur) {
            return;
        }

        mNextDrawUseBLASTSyncTransaction = false;

        if (DEBUG_BLAST) {
            Log.d(mTag, "Creating frameDrawingCallback"
                    + " nextDrawUseBlastSync=" + nextDrawUseBlastSync
                    + " reportNextDraw=" + reportNextDraw
                    + " hasBlur=" + hasBlur);
        }

        // The callback will run on a worker thread pool from the render thread.
        HardwareRenderer.FrameDrawingCallback frameDrawingCallback = frame -> {
            if (DEBUG_BLAST) {
                Log.d(mTag, "Received frameDrawingCallback frameNum=" + frame + "."
                        + " Creating transactionCompleteCallback=" + addTransactionComplete);
            }
            mRtNextFrameReportedConsumeWithBlast = true;

            if (hasBlur) {
                mBlurRegionAggregator.dispatchBlurTransactionIfNeeded(frame);
            }

            if (mBlastBufferQueue == null) {
                return;
            }

            if (nextDrawUseBlastSync) {
                // Frame callbacks will always occur after submitting draw requests and before
                // the draw actually occurs. This will ensure that we set the next transaction
                // for the frame that's about to get drawn and not on a previous frame that.
                //
                // This is thread safe since mRtNextFrameReportConsumeWithBlast will only be
                // modified in onFrameDraw and then again in onFrameComplete. This is to ensure the
                // next frame completed should be reported with the blast sync transaction.
                mRtNextFrameReportedConsumeWithBlast = true;

                // We don't need to synchronize mRtBLASTSyncTransaction here since it's not
                // being modified and only sent to BlastBufferQueue.
                mBlastBufferQueue.setNextTransaction(mRtBLASTSyncTransaction);
            if (!addTransactionComplete) {
                return;
            } else if (reportNextDraw) {
                // If we need to report next draw, wait for adapter to flush its shadow queue
                // by processing previously queued buffers so that we can submit the
                // transaction a timely manner.
                mBlastBufferQueue.flushShadowQueue();
            }

            if (addTransactionComplete) {
                mBlastBufferQueue.setTransactionCompleteCallback(frame, frameNumber -> {
                    if (DEBUG_BLAST) {
                        Log.d(mTag, "Received transactionCompleteCallback frameNum=" + frame);
@@ -3959,37 +3989,9 @@ public final class ViewRootImpl implements ViewParent,
                        }
                    });
                });
        };
    }

    private void addFrameCallbackIfNeeded() {
        if (DEBUG_BLAST) {
            if (mNextDrawUseBLASTSyncTransaction || mReportNextDraw) {
                Log.d(mTag, "Creating frameDrawingCallback mNextDrawUseBLASTSyncTransaction="
                        + mNextDrawUseBLASTSyncTransaction + " mReportNextDraw=" + mReportNextDraw);
            }
        }

        if (mNextDrawUseBLASTSyncTransaction) {
            // Frame callbacks will always occur after submitting draw requests and before
            // the draw actually occurs. This will ensure that we set the next transaction
            // for the frame that's about to get drawn and not on a previous frame that.
            //
            // This is thread safe since mRtNextFrameReportConsumeWithBlast will only be
            // modified in onFrameDraw and then again in onFrameComplete. This is to ensure the
            // next frame completed should be reported with the blast sync transaction.
            registerRtFrameCallback(createFrameDrawingCallback(mSendNextFrameToWm));
            mNextDrawUseBLASTSyncTransaction = false;
        } else if (mReportNextDraw) {
            registerRtFrameCallback(frame -> {
                if (mBlastBufferQueue != null) {
                    // If we need to report next draw, wait for adapter to flush its shadow queue
                    // by processing previously queued buffers so that we can submit the
                    // transaction a timely manner.
                    mBlastBufferQueue.flushShadowQueue();
                }
            });
            }
        };
        registerRtFrameCallback(frameDrawingCallback);
    }

    private void performDraw() {
@@ -10070,14 +10072,14 @@ public final class ViewRootImpl implements ViewParent,
        if (!surfaceControl.isValid()) {
            return;
        }
        if (useBLAST()) {
            synchronized (getBlastTransactionLock()) {
                getBLASTSyncTransaction().setBlurRegions(surfaceControl, regionCopy);
            }
        } else {

        SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
        transaction.setBlurRegions(surfaceControl, regionCopy);
            transaction.deferTransactionUntil(surfaceControl, getSurfaceControl(), frameNumber);

        if (useBLAST() && mBlastBufferQueue != null) {
            mBlastBufferQueue.mergeWithNextTransaction(transaction, frameNumber);
        } else {
            transaction.deferTransactionUntil(surfaceControl, surfaceControl, frameNumber);
            transaction.apply();
        }
    }