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

Commit 5d7ae906 authored by Vishnu Nair's avatar Vishnu Nair Committed by Android (Google) Code Review
Browse files

Merge "SurfaceView: Synchronize position updates with fixed size changes" into sc-dev

parents 1a32fc6b befbb69c
Loading
Loading
Loading
Loading
+95 −56
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
import android.graphics.RenderNode;
@@ -236,15 +237,6 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
    private final SurfaceControl.Transaction mFrameCallbackTransaction =
            new SurfaceControl.Transaction();

    /**
     * Transaction that should be used for
     * {@link RenderNode.PositionUpdateListener#positionChanged(long, int, int, int, int)}
     * The callback is invoked from a thread pool so it's not thread safe with other render thread
     * transactions. Keep the transactions for position changed callbacks on its own transaction.
     */
    private final SurfaceControl.Transaction mPositionChangedTransaction =
            new SurfaceControl.Transaction();

    /**
     * A temporary transaction holder that should only be used when applying right away. There
     * should be no assumption about thread safety for this transaction.
@@ -295,7 +287,6 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
            int defStyleRes, boolean disableBackgroundLayer) {
        super(context, attrs, defStyleAttr, defStyleRes);
        mUseBlastAdapter = useBlastAdapter(context);
        mRenderNode.addPositionUpdateListener(mPositionListener);

        setWillNotDraw(true);
        mDisableBackgroundLayer = disableBackgroundLayer;
@@ -943,6 +934,24 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
        }
    }


    // The position update listener is used to safely share the surface size between render thread
    // workers and the UI thread. Both threads need to know the surface size to determine the scale.
    // The parent layer scales the surface size to view size. The child (BBQ) layer scales
    // the buffer to the surface size. Both scales along with the window crop must be applied
    // synchronously otherwise we may see flickers.
    // When the listener is updated, we will get at least a single position update call so we can
    // guarantee any changes we post will be applied.
    private void replacePositionUpdateListener(int surfaceWidth, int surfaceHeight,
            @Nullable Transaction geometryTransaction) {
        if (mPositionListener != null) {
            mRenderNode.removePositionUpdateListener(mPositionListener);
        }
        mPositionListener = new SurfaceViewPositionUpdateListener(surfaceWidth, surfaceHeight,
                geometryTransaction);
        mRenderNode.addPositionUpdateListener(mPositionListener);
    }

    private boolean performSurfaceTransaction(ViewRootImpl viewRoot, Translator translator,
            boolean creating, boolean sizeChanged, boolean hintChanged) {
        boolean realSizeChanged = false;
@@ -985,13 +994,13 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
            // While creating the surface, we will set it's initial
            // geometry. Outside of that though, we should generally
            // leave it to the RenderThread.
            //
            // There is one more case when the buffer size changes we aren't yet
            // prepared to sync (as even following the transaction applying
            // we still need to latch a buffer).
            // b/28866173
            if (sizeChanged || creating || !mRtHandlingPositionUpdates) {
                onSetSurfacePositionAndScaleRT(mTmpTransaction, mSurfaceControl,
            Transaction geometryTransaction = new Transaction();
            geometryTransaction.setCornerRadius(mSurfaceControl, mCornerRadius);
            if ((sizeChanged || hintChanged) && !creating) {
                setBufferSize(geometryTransaction);
            }
            if (sizeChanged || creating || !isHardwareAccelerated()) {
                onSetSurfacePositionAndScaleRT(geometryTransaction, mSurfaceControl,
                        mScreenRect.left, /*positionLeft*/
                        mScreenRect.top /*positionTop*/ ,
                        mScreenRect.width() / (float) mSurfaceWidth /*postScaleX*/,
@@ -1002,17 +1011,31 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
                // use SCALING_MODE_SCALE and submit a larger size than the surface
                // size.
                if (mClipSurfaceToBounds && mClipBounds != null) {
                    mTmpTransaction.setWindowCrop(mSurfaceControl, mClipBounds);
                    geometryTransaction.setWindowCrop(mSurfaceControl, mClipBounds);
                } else {
                    mTmpTransaction.setWindowCrop(mSurfaceControl, mSurfaceWidth,
                    geometryTransaction.setWindowCrop(mSurfaceControl, mSurfaceWidth,
                            mSurfaceHeight);
                }

                boolean applyChangesOnRenderThread =
                        sizeChanged && !creating && isHardwareAccelerated();
                if (isHardwareAccelerated()) {
                    // This will consume the passed in transaction and the transaction will be
                    // applied on a render worker thread.
                    replacePositionUpdateListener(mSurfaceWidth, mSurfaceHeight,
                            applyChangesOnRenderThread ? geometryTransaction : null);
                }
            mTmpTransaction.setCornerRadius(mSurfaceControl, mCornerRadius);
            if ((sizeChanged || hintChanged) && !creating) {
                setBufferSize(mTmpTransaction);
                if (DEBUG_POSITION) {
                    Log.d(TAG, String.format(
                            "%d updateSurfacePosition %s"
                                + "position = [%d, %d, %d, %d] surfaceSize = %dx%d",
                            System.identityHashCode(this),
                            applyChangesOnRenderThread ? "RenderWorker" : "UiThread",
                            mScreenRect.left, mScreenRect.top, mScreenRect.right,
                            mScreenRect.bottom, mSurfaceWidth, mSurfaceHeight));
                }

            }
            mTmpTransaction.merge(geometryTransaction);
            mTmpTransaction.apply();
            updateEmbeddedAccessibilityMatrix();

@@ -1399,19 +1422,6 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
        mTmpTransaction.apply();
    }

    private void applySurfaceTransforms(SurfaceControl surface, SurfaceControl.Transaction t,
            Rect position) {
        onSetSurfacePositionAndScaleRT(t, surface,
                position.left /*positionLeft*/,
                position.top /*positionTop*/,
                position.width() / (float) mSurfaceWidth /*postScaleX*/,
                position.height() / (float) mSurfaceHeight /*postScaleY*/);

        if (mViewVisibility) {
            t.show(surface);
        }
    }

    /**
     * @return The last render position of the backing surface or an empty rect.
     *
@@ -1421,13 +1431,6 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
        return mRTLastReportedPosition;
    }

    private void setParentSpaceRectangle(Rect position, long frameNumber, Transaction t) {
        final ViewRootImpl viewRoot = getViewRootImpl();
        applySurfaceTransforms(mSurfaceControl, t, position);
        applyChildSurfaceTransaction_renderWorker(t, viewRoot.mSurface, frameNumber);
        applyOrMergeTransaction(t, frameNumber);
    }

    private void applyOrMergeTransaction(Transaction t, long frameNumber) {
        final ViewRootImpl viewRoot = getViewRootImpl();
        boolean useBLAST = viewRoot != null && useBLASTSync(viewRoot);
@@ -1440,9 +1443,24 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
    }

    private Rect mRTLastReportedPosition = new Rect();
    private Point mRTLastReportedSurfaceSize = new Point();

    private RenderNode.PositionUpdateListener mPositionListener =
            new RenderNode.PositionUpdateListener() {
    private class SurfaceViewPositionUpdateListener implements RenderNode.PositionUpdateListener {
        int mRtSurfaceWidth = -1;
        int mRtSurfaceHeight = -1;
        private final SurfaceControl.Transaction mPositionChangedTransaction =
                new SurfaceControl.Transaction();
        boolean mPendingTransaction = false;

        SurfaceViewPositionUpdateListener(int surfaceWidth, int surfaceHeight,
                @Nullable Transaction t) {
            mRtSurfaceWidth = surfaceWidth;
            mRtSurfaceHeight = surfaceHeight;
            if (t != null) {
                mPositionChangedTransaction.merge(t);
                mPendingTransaction = true;
            }
        }

        @Override
        public void positionChanged(long frameNumber, int left, int top, int right, int bottom) {
@@ -1464,21 +1482,34 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
            if (mRTLastReportedPosition.left == left
                    && mRTLastReportedPosition.top == top
                    && mRTLastReportedPosition.right == right
                    && mRTLastReportedPosition.bottom == bottom) {
                    && mRTLastReportedPosition.bottom == bottom
                    && mRTLastReportedSurfaceSize.x == mRtSurfaceWidth
                    && mRTLastReportedSurfaceSize.y == mRtSurfaceHeight
                    && !mPendingTransaction) {
                return;
            }
            try {
                if (DEBUG_POSITION) {
                    Log.d(TAG, String.format(
                            "%d updateSurfacePosition RenderWorker, frameNr = %d, "
                                    + "position = [%d, %d, %d, %d]",
                            System.identityHashCode(this), frameNumber,
                            left, top, right, bottom));
                                    + "position = [%d, %d, %d, %d] surfaceSize = %dx%d",
                            System.identityHashCode(SurfaceView.this), frameNumber,
                            left, top, right, bottom, mRtSurfaceWidth, mRtSurfaceHeight));
                }
                mRTLastReportedPosition.set(left, top, right, bottom);
                setParentSpaceRectangle(mRTLastReportedPosition, frameNumber,
                        mPositionChangedTransaction);
                // Now overwrite mRTLastReportedPosition with our values
                mRTLastReportedSurfaceSize.set(mRtSurfaceWidth, mRtSurfaceHeight);
                onSetSurfacePositionAndScaleRT(mPositionChangedTransaction, mSurfaceControl,
                        mRTLastReportedPosition.left /*positionLeft*/,
                        mRTLastReportedPosition.top /*positionTop*/,
                        mRTLastReportedPosition.width() / (float) mRtSurfaceWidth /*postScaleX*/,
                        mRTLastReportedPosition.height() / (float) mRtSurfaceHeight /*postScaleY*/);
                if (mViewVisibility) {
                    mPositionChangedTransaction.show(mSurfaceControl);
                }
                applyChildSurfaceTransaction_renderWorker(mPositionChangedTransaction,
                        getViewRootImpl().mSurface, frameNumber);
                applyOrMergeTransaction(mPositionChangedTransaction, frameNumber);
                mPendingTransaction = false;
            } catch (Exception ex) {
                Log.e(TAG, "Exception from repositionChild", ex);
            }
@@ -1502,7 +1533,13 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
                        System.identityHashCode(this), frameNumber));
            }
            mRTLastReportedPosition.setEmpty();

            mRTLastReportedSurfaceSize.set(-1, -1);
            if (mPendingTransaction) {
                Log.w(TAG, System.identityHashCode(SurfaceView.this)
                        + "Pending transaction cleared.");
                mPositionChangedTransaction.clear();
                mPendingTransaction = false;
            }
            if (mSurfaceControl == null) {
                return;
            }
@@ -1521,7 +1558,9 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
                mRtHandlingPositionUpdates = false;
            }
        }
    };
    }

    private SurfaceViewPositionUpdateListener mPositionListener = null;

    private SurfaceHolder.Callback[] getSurfaceCallbacks() {
        SurfaceHolder.Callback[] callbacks;