Support frame-synchronized clipping on SurfaceView
Bug: 123306815
Test: See ag/9384030, manual test of bubbles expand collapse animation
Change-Id: I5350501667fe729a0c668e8f6edaf30070a2e1ec
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 90e69f3..9acebe1 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -166,6 +166,7 @@
boolean mUseAlpha = false;
float mSurfaceAlpha = 1f;
+ boolean mClipSurfaceToBounds;
@UnsupportedAppUsage
boolean mHaveFrame = false;
@@ -554,9 +555,52 @@
super.dispatchDraw(canvas);
}
+ /**
+ * Control whether the surface is clipped to the same bounds as the View. If true, then
+ * the bounds set by {@link #setClipBounds(Rect)} are applied to the surface as window-crop.
+ *
+ * @param enabled whether to enable surface clipping
+ * @hide
+ */
+ public void setEnableSurfaceClipping(boolean enabled) {
+ mClipSurfaceToBounds = enabled;
+ invalidate();
+ }
+
+ @Override
+ public void setClipBounds(Rect clipBounds) {
+ super.setClipBounds(clipBounds);
+
+ if (!mClipSurfaceToBounds) {
+ return;
+ }
+
+ // When cornerRadius is non-zero, a draw() is required to update
+ // the viewport (rounding the corners of the clipBounds).
+ if (mCornerRadius > 0f && !isAboveParent()) {
+ invalidate();
+ }
+
+ if (mSurfaceControl != null) {
+ if (mClipBounds != null) {
+ mTmpRect.set(mClipBounds);
+ } else {
+ mTmpRect.set(0, 0, mSurfaceWidth, mSurfaceHeight);
+ }
+ SyncRtSurfaceTransactionApplier applier = new SyncRtSurfaceTransactionApplier(this);
+ applier.scheduleApply(
+ new SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(mSurfaceControl)
+ .withWindowCrop(mTmpRect)
+ .build());
+ }
+ }
+
private void clearSurfaceViewPort(Canvas canvas) {
if (mCornerRadius > 0f) {
canvas.getClipBounds(mTmpRect);
+ if (mClipSurfaceToBounds && mClipBounds != null) {
+ mTmpRect.intersect(mClipBounds);
+ }
canvas.drawRoundRect(mTmpRect.left, mTmpRect.top, mTmpRect.right, mTmpRect.bottom,
mCornerRadius, mCornerRadius, mRoundedViewportPaint);
} else {
@@ -582,6 +626,16 @@
}
/**
+ * Returns the corner radius for the SurfaceView.
+
+ * @return the radius of the corners in pixels
+ * @hide
+ */
+ public float getCornerRadius() {
+ return mCornerRadius;
+ }
+
+ /**
* Control whether the surface view's surface is placed on top of another
* regular surface view in the window (but still behind the window itself).
* This is typically used to place overlays on top of an underlying media
@@ -832,7 +886,11 @@
// crop the buffer to the surface size since the buffer producer may
// use SCALING_MODE_SCALE and submit a larger size than the surface
// size.
- mSurfaceControl.setWindowCrop(mSurfaceWidth, mSurfaceHeight);
+ if (mClipSurfaceToBounds && mClipBounds != null) {
+ mSurfaceControl.setWindowCrop(mClipBounds);
+ } else {
+ mSurfaceControl.setWindowCrop(mSurfaceWidth, mSurfaceHeight);
+ }
}
mSurfaceControl.setCornerRadius(mCornerRadius);
if (sizeChanged && !creating) {