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

Commit 85bb940f authored by Robert Carr's avatar Robert Carr
Browse files

Port SurfaceView deferTransaction usage to BLAST

When the SurfaceView is invalidated (e.g. geometry has changed) we ask
the ViewRootImpl to render the next buffer in to a BLAST transaction which
the SurfaceView will also use from it's RT callbacks in place of deferTransactionUntil

Test: Flip USE_BLAST_BUFFERQUEUE flag. Run SurfaceViewSyncTests.
Bug: 146598493
Change-Id: I43d301f25101afae32ad1c43a3a3210c5aeadd0f
parent f06d584d
Loading
Loading
Loading
Loading
+49 −14
Original line number Diff line number Diff line
@@ -379,9 +379,11 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
                 * This gets called on a RenderThread worker thread, so members accessed here must
                 * be protected by a lock.
                 */
                final boolean useBLAST = ViewRootImpl.USE_BLAST_BUFFERQUEUE;
                viewRoot.registerRtFrameCallback(frame -> {
                    try {
                        final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
                        final SurfaceControl.Transaction t = useBLAST ?
                            viewRoot.getBLASTSyncTransaction() : new SurfaceControl.Transaction();
                        synchronized (mSurfaceControlLock) {
                            if (!parent.isValid()) {
                                if (DEBUG) {
@@ -404,8 +406,10 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
                                        + " updateSurfaceAlpha RT: set alpha=" + alpha);
                            }
                            t.setAlpha(mSurfaceControl, alpha);
                            if (!useBLAST) {
                                t.deferTransactionUntilSurface(mSurfaceControl, parent, frame);
                            }
                        }
                        // It's possible that mSurfaceControl is released in the UI thread before
                        // the transaction completes. If that happens, an exception is thrown, which
                        // must be caught immediately.
@@ -1101,33 +1105,39 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
            Surface viewRootSurface, long nextViewRootFrameNumber) {
    }

    private void applySurfaceTransforms(SurfaceControl surface, Rect position, long frameNumber) {
        if (frameNumber > 0) {
    private void applySurfaceTransforms(SurfaceControl surface, SurfaceControl.Transaction t,
            Rect position, long frameNumber) {
        if (frameNumber > 0 && ViewRootImpl.USE_BLAST_BUFFERQUEUE == false) {
            final ViewRootImpl viewRoot = getViewRootImpl();

            mRtTransaction.deferTransactionUntilSurface(surface, viewRoot.mSurface,
            t.deferTransactionUntilSurface(surface, viewRoot.mSurface,
                    frameNumber);
        }

        mRtTransaction.setPosition(surface, position.left, position.top);
        mRtTransaction.setMatrix(surface,
        t.setPosition(surface, position.left, position.top);
        t.setMatrix(surface,
                position.width() / (float) mSurfaceWidth,
                0.0f, 0.0f,
                position.height() / (float) mSurfaceHeight);
        if (mViewVisibility) {
            mRtTransaction.show(surface);
            t.show(surface);
        }
    }

    private void setParentSpaceRectangle(Rect position, long frameNumber) {
        final boolean useBLAST = ViewRootImpl.USE_BLAST_BUFFERQUEUE;
        final ViewRootImpl viewRoot = getViewRootImpl();
        final SurfaceControl.Transaction t = useBLAST ? viewRoot.getBLASTSyncTransaction() :
            mRtTransaction;

        applySurfaceTransforms(mSurfaceControl, position, frameNumber);
        applySurfaceTransforms(mSurfaceControl, t, position, frameNumber);

        applyChildSurfaceTransaction_renderWorker(mRtTransaction, viewRoot.mSurface,
        applyChildSurfaceTransaction_renderWorker(t, viewRoot.mSurface,
                frameNumber);

        mRtTransaction.apply();
        if (!useBLAST) {
            t.apply();
        }
    }

    private Rect mRTLastReportedPosition = new Rect();
@@ -1176,6 +1186,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall

        @Override
        public void positionLost(long frameNumber) {
            boolean useBLAST = ViewRootImpl.USE_BLAST_BUFFERQUEUE;
            if (DEBUG) {
                Log.d(TAG, String.format("%d windowPositionLost, frameNr = %d",
                        System.identityHashCode(this), frameNumber));
@@ -1187,13 +1198,18 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
            }

            final ViewRootImpl viewRoot = getViewRootImpl();
            if (frameNumber > 0 && viewRoot !=  null) {

            final SurfaceControl.Transaction t = useBLAST ?
                (viewRoot != null ? viewRoot.getBLASTSyncTransaction() : mRtTransaction) :
                mRtTransaction;

            if (frameNumber > 0 && viewRoot !=  null && !useBLAST) {
                if (viewRoot.mSurface.isValid()) {
                    mRtTransaction.deferTransactionUntilSurface(mSurfaceControl, viewRoot.mSurface,
                            frameNumber);
                }
            }
            mRtTransaction.hide(mSurfaceControl);
            t.hide(mSurfaceControl);

            synchronized (mSurfaceControlLock) {
                if (mRtReleaseSurfaces) {
@@ -1206,8 +1222,12 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
                mRtHandlingPositionUpdates = false;
            }

            // If we aren't using BLAST, we apply the transaction locally, otherise we let the ViewRoot apply it for us.
            // If the ViewRoot is null, we behave as if we aren't using BLAST so we need to apply the transaction.
            if (!useBLAST || viewRoot == null) {
                mRtTransaction.apply();
            }
        }
    };

    private SurfaceHolder.Callback[] getSurfaceCallbacks() {
@@ -1496,4 +1516,19 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
        t.setRelativeLayer(mBackgroundControl, viewRoot, Integer.MIN_VALUE);
        t.setRelativeLayer(mSurfaceControl, viewRoot, mSubLayer);
    }

    /**
     * @hide
     * Note: Base class method is @UnsupportedAppUsage
     */
    @Override
    public void invalidate(boolean invalidateCache) {
        super.invalidate(invalidateCache);
        if (ViewRootImpl.USE_BLAST_BUFFERQUEUE == false) {
            return;
        }
        final ViewRootImpl viewRoot = getViewRootImpl();
        if (viewRoot == null) return;
        viewRoot.setUseBLASTSyncTransaction();
    }
}
+31 −1
Original line number Diff line number Diff line
@@ -191,7 +191,10 @@ public final class ViewRootImpl implements ViewParent,
     */
    private static final boolean MT_RENDERER_AVAILABLE = true;

    private static final boolean USE_BLAST_BUFFERQUEUE = false;
    /**
     * @hide
     */
    public static final boolean USE_BLAST_BUFFERQUEUE = false;

    /**
     * If set to 2, the view system will switch from using rectangles retrieved from window to
@@ -632,6 +635,12 @@ public final class ViewRootImpl implements ViewParent,
        int localChanges;
    }

    private boolean mNextDrawUseBLASTSyncTransaction;
    // Be very careful with the threading here. This is used from the render thread while
    // the UI thread is paused and then applied and cleared from the UI thread right after
    // draw returns.
    private SurfaceControl.Transaction mRtBLASTSyncTransaction = new SurfaceControl.Transaction();

    private String mTag = TAG;
    public ViewRootImpl(Context context, Display display) {
        this(context, display, WindowManagerGlobal.getWindowSession());
@@ -3604,6 +3613,7 @@ public final class ViewRootImpl implements ViewParent,
                final Handler handler = mAttachInfo.mHandler;
                mAttachInfo.mThreadedRenderer.setFrameCompleteCallback((long frameNr) ->
                        handler.postAtFrontOfQueue(() -> {
                            finishBLASTSync();
                            // TODO: Use the frame number
                            pendingDrawFinished();
                            if (commitCallbacks != null) {
@@ -3616,6 +3626,7 @@ public final class ViewRootImpl implements ViewParent,
                final Handler handler = mAttachInfo.mHandler;
                mAttachInfo.mThreadedRenderer.setFrameCompleteCallback((long frameNr) ->
                        handler.postAtFrontOfQueue(() -> {
                            finishBLASTSync();
                            for (int i = 0; i < commitCallbacks.size(); i++) {
                                commitCallbacks.get(i).run();
                            }
@@ -3624,10 +3635,14 @@ public final class ViewRootImpl implements ViewParent,
        }

        try {
            if (mNextDrawUseBLASTSyncTransaction) {
                mBlastBufferQueue.setNextTransaction(mRtBLASTSyncTransaction);
            }
            boolean canUseAsync = draw(fullRedrawNeeded);
            if (usingAsyncReport && !canUseAsync) {
                mAttachInfo.mThreadedRenderer.setFrameCompleteCallback(null);
                usingAsyncReport = false;
                finishBLASTSync();
            }
        } finally {
            mIsDrawing = false;
@@ -9421,4 +9436,19 @@ public final class ViewRootImpl implements ViewParent,
            return false;
        }
    }

    void setUseBLASTSyncTransaction() {
        mNextDrawUseBLASTSyncTransaction = true;
    }

    private void finishBLASTSync() {
        if (mNextDrawUseBLASTSyncTransaction) {
            mNextDrawUseBLASTSyncTransaction = false;
            mRtBLASTSyncTransaction.apply();
        }
    }

    SurfaceControl.Transaction getBLASTSyncTransaction() {
        return mRtBLASTSyncTransaction;
    }
}