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

Commit 1b152e71 authored by John Reck's avatar John Reck
Browse files

Implement automatic SV clipping

Clip SV to its ancestor clipping bounds. This enables
Z-above SurfaceView + scrolling containers to work more naturally

Replaces the hidden API of setEnableSurfaceClipping

Fixes: 298621623
Test: Sample app
Change-Id: Iaa862598e37065677f5ba163a5ac7a6fab2739ea
parent 57cca107
Loading
Loading
Loading
Loading
+60 −10
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.AttributeSet;
import android.util.Log;
@@ -51,6 +52,7 @@ import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.IAccessibilityEmbeddedConnection;
import android.window.SurfaceSyncGroup;

import com.android.graphics.hwui.flags.Flags;
import com.android.internal.view.SurfaceCallbackHelper;

import java.lang.annotation.Retention;
@@ -326,6 +328,8 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
        }
    };

    private final boolean mRtDrivenClipping = Flags.clipSurfaceviews();

    public SurfaceView(Context context) {
        this(context, null);
    }
@@ -572,6 +576,10 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
    public void setClipBounds(Rect clipBounds) {
        super.setClipBounds(clipBounds);

        if (mRtDrivenClipping && isHardwareAccelerated()) {
            return;
        }

        if (!mClipSurfaceToBounds || mSurfaceControl == null) {
            return;
        }
@@ -915,6 +923,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
            }
            if (sizeChanged || creating || !isHardwareAccelerated()) {

                if (!mRtDrivenClipping || !isHardwareAccelerated()) {
                    // Set a window crop when creating the surface or changing its size to
                    // crop the buffer to the surface size since the buffer producer may
                    // use SCALING_MODE_SCALE and submit a larger size than the surface
@@ -925,6 +934,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
                        surfaceUpdateTransaction.setWindowCrop(mSurfaceControl, mSurfaceWidth,
                                mSurfaceHeight);
                    }
                }

                surfaceUpdateTransaction.setDesintationFrame(mBlastSurfaceControl, mSurfaceWidth,
                            mSurfaceHeight);
@@ -941,7 +951,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
                            mScreenRect.height() / (float) mSurfaceHeight /*postScaleY*/);
                }
                if (DEBUG_POSITION) {
                    Log.d(TAG, String.format(
                    Log.d(TAG, TextUtils.formatSimple(
                            "%d performSurfaceTransaction %s "
                                + "position = [%d, %d, %d, %d] surfaceSize = %dx%d",
                            System.identityHashCode(this),
@@ -1453,6 +1463,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
    }

    private final Rect mRTLastReportedPosition = new Rect();
    private final Rect mRTLastSetCrop = new Rect();

    private class SurfaceViewPositionUpdateListener implements RenderNode.PositionUpdateListener {
        private final int mRtSurfaceWidth;
@@ -1495,6 +1506,45 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
            }
        }

        @Override
        public void positionChanged(long frameNumber, int left, int top, int right, int bottom,
                int clipLeft, int clipTop, int clipRight, int clipBottom) {
            try {
                if (DEBUG_POSITION) {
                    Log.d(TAG, String.format(
                            "%d updateSurfacePosition RenderWorker, frameNr = %d, "
                                    + "position = [%d, %d, %d, %d] clip = [%d, %d, %d, %d] "
                                    + "surfaceSize = %dx%d",
                            System.identityHashCode(SurfaceView.this), frameNumber,
                            left, top, right, bottom, clipLeft, clipTop, clipRight, clipBottom,
                            mRtSurfaceWidth, mRtSurfaceHeight));
                }
                synchronized (mSurfaceControlLock) {
                    if (mSurfaceControl == null) return;

                    mRTLastReportedPosition.set(left, top, right, bottom);
                    onSetSurfacePositionAndScale(mPositionChangedTransaction, mSurfaceControl,
                            mRTLastReportedPosition.left /*positionLeft*/,
                            mRTLastReportedPosition.top /*positionTop*/,
                            mRTLastReportedPosition.width()
                                    / (float) mRtSurfaceWidth /*postScaleX*/,
                            mRTLastReportedPosition.height()
                                    / (float) mRtSurfaceHeight /*postScaleY*/);

                    mRTLastSetCrop.set(clipLeft, clipTop, clipRight, clipBottom);
                    mPositionChangedTransaction.setCrop(mSurfaceControl, mRTLastSetCrop);
                    if (mRTLastSetCrop.isEmpty()) {
                        mPositionChangedTransaction.hide(mSurfaceControl);
                    } else {
                        mPositionChangedTransaction.show(mSurfaceControl);
                    }
                }
                applyOrMergeTransaction(mPositionChangedTransaction, frameNumber);
            } catch (Exception ex) {
                Log.e(TAG, "Exception from repositionChild", ex);
            }
        }

        @Override
        public void applyStretch(long frameNumber, float width, float height,
                float vecX, float vecY, float maxStretchX, float maxStretchY,
+37 −0
Original line number Diff line number Diff line
@@ -271,6 +271,17 @@ public final class RenderNode {
         */
        void positionChanged(long frameNumber, int left, int top, int right, int bottom);

        /**
         * Called by native by a Rendering Worker thread to update window position; includes
         * the local rect that represents the clipped area of the RenderNode's bounds.
         *
         * @hide
         */
        default void positionChanged(long frameNumber, int left, int top, int right, int bottom,
                int clipLeft, int clipTop, int clipRight, int clipBottom) {
            positionChanged(frameNumber, left, top, right, bottom);
        }

        /**
         * Called by JNI
         *
@@ -286,6 +297,23 @@ public final class RenderNode {
            }
        }

        /**
         * Called by JNI
         *
         * @hide */
        static boolean callPositionChanged2(WeakReference<PositionUpdateListener> weakListener,
                long frameNumber, int left, int top, int right, int bottom,
                int clipLeft, int clipTop, int clipRight, int clipBottom) {
            final PositionUpdateListener listener = weakListener.get();
            if (listener != null) {
                listener.positionChanged(frameNumber, left, top, right, bottom, clipLeft,
                        clipTop, clipRight, clipBottom);
                return true;
            } else {
                return false;
            }
        }

        /**
         * Call to apply a stretch effect to any child SurfaceControl layers
         *
@@ -370,6 +398,15 @@ public final class RenderNode {
            }
        }

        @Override
        public void positionChanged(long frameNumber, int left, int top, int right, int bottom,
                int clipLeft, int clipTop, int clipRight, int clipBottom) {
            for (PositionUpdateListener pul : mListeners) {
                pul.positionChanged(frameNumber, left, top, right, bottom, clipLeft, clipTop,
                        clipRight, clipBottom);
            }
        }

        @Override
        public void positionLost(long frameNumber) {
            for (PositionUpdateListener pul : mListeners) {
+1 −0
Original line number Diff line number Diff line
@@ -144,6 +144,7 @@ cc_defaults {
                "libsync",
                "libui",
                "aconfig_text_flags_c_lib",
                "server_configurable_flags",
            ],
            static_libs: [
                "libEGL_blobCache",
+41 −0
Original line number Diff line number Diff line
@@ -242,6 +242,47 @@ void DamageAccumulator::applyRenderNodeTransform(DirtyStack* frame) {
    }
}

SkRect DamageAccumulator::computeClipAndTransform(const SkRect& bounds, Matrix4* outMatrix) const {
    const DirtyStack* frame = mHead;
    Matrix4 transform;
    SkRect pretransformResult = bounds;
    while (true) {
        SkRect currentBounds = pretransformResult;
        pretransformResult.setEmpty();
        switch (frame->type) {
            case TransformRenderNode: {
                const RenderProperties& props = frame->renderNode->properties();
                // Perform clipping
                if (props.getClipDamageToBounds() && !currentBounds.isEmpty()) {
                    if (!currentBounds.intersect(
                                SkRect::MakeIWH(props.getWidth(), props.getHeight()))) {
                        currentBounds.setEmpty();
                    }
                }

                // apply all transforms
                mapRect(props, currentBounds, &pretransformResult);
                frame->renderNode->applyViewPropertyTransforms(transform);
            } break;
            case TransformMatrix4:
                mapRect(frame->matrix4, currentBounds, &pretransformResult);
                transform.multiply(*frame->matrix4);
                break;
            default:
                pretransformResult = currentBounds;
                break;
        }
        if (frame->prev == frame) break;
        frame = frame->prev;
    }
    SkRect result;
    Matrix4 globalToLocal;
    globalToLocal.loadInverse(transform);
    mapRect(&globalToLocal, pretransformResult, &result);
    *outMatrix = transform;
    return result;
}

void DamageAccumulator::dirty(float left, float top, float right, float bottom) {
    mHead->pendingDirty.join({left, top, right, bottom});
}
+2 −0
Original line number Diff line number Diff line
@@ -61,6 +61,8 @@ public:

    void computeCurrentTransform(Matrix4* outMatrix) const;

    SkRect computeClipAndTransform(const SkRect& bounds, Matrix4* outMatrix) const;

    void finish(SkRect* totalDirty);

    struct StretchResult {
Loading