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

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15462690

Change-Id: If91aa26d1fbfe17f7dd4c2e5e417c58ba03c0874
This commit is contained in:
Vishnu Nair
2021-08-05 04:53:56 +00:00
committed by Automerger Merge Worker

View File

@@ -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);
}
}
mTmpTransaction.setCornerRadius(mSurfaceControl, mCornerRadius);
if ((sizeChanged || hintChanged) && !creating) {
setBufferSize(mTmpTransaction);
}
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);
}
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;