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

Commit 64e516f5 authored by Rob Carr's avatar Rob Carr
Browse files

Sync SurfaceView position changes to parent render.

In order to provide pixel perfect movement of SurfaceViews
'within' other views (e.g. scrolling) we need to be able to
synchronize the attached (parent window) painting with the
movement of the SurfaceView (recall, SurfaceViews are positioned
behind their attached windows and the parent must render a
transparent region for the SurfaceView to appear). Provide
a new WindowManager method to reposition an attaching window
(that is to say, a window which has an attached window like
SurfaceView) and defer the transaction until the parent frame.
SurfaceView is hooked up to use this for movement. This is still
'racy' in the hardware accelerated case as the render thread
could be on either side of dequeing the frame we are working on.

Bug: 22802885
Change-Id: I025d2bdcbe15c1c11047cc0dbca2cf2b7d67c632
parent ec034cdb
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -95,6 +95,23 @@ interface IWindowSession {
            out Rect outContentInsets, out Rect outVisibleInsets, out Rect outStableInsets,
            out Rect outOutsets, out Configuration outConfig, out Surface outSurface);

    /**
     *  Position a window relative to it's parent (attached) window without triggering
     *  a full relayout. This action may be deferred until a given frame number
     *  for the parent window appears. This allows for synchronizing movement of a child
     *  to repainting the contents of the parent.
     *
     *  @param window The window being modified. Must be attached to a parent window
     *  or this call will fail.
     *  @param x The new x position
     *  @param y The new y position
     *  @param deferTransactionUntilFrame Frame number from our parent (attached) to
     *  defer this action until.
     *  @param outFrame Rect in which is placed the new position/size on screen.
     */
    void repositionChild(IWindow childWindow, int x, int y, long deferTransactionUntilFrame,
            out Rect outFrame);

    /**
     * If a call to relayout() asked to have the surface destroy deferred,
     * it must call this once it is okay to destroy that surface.
+14 −0
Original line number Diff line number Diff line
@@ -56,6 +56,8 @@ public class Surface implements Parcelable {
    private static native int nativeGetWidth(long nativeObject);
    private static native int nativeGetHeight(long nativeObject);

    private static native long nativeGetNextFrameNumber(long nativeObject);

    public static final Parcelable.Creator<Surface> CREATOR =
            new Parcelable.Creator<Surface>() {
        @Override
@@ -219,6 +221,18 @@ public class Surface implements Parcelable {
        }
    }

    /**
     * Returns the next frame number which will be dequeued for rendering.
     * Intended for use with SurfaceFlinger's deferred transactions API.
     *
     * @hide
     */
    public long getNextFrameNumber() {
        synchronized (mLock) {
            return nativeGetNextFrameNumber(mNativeObject);
        }
    }

    /**
     * Returns true if the consumer of this Surface is running behind the producer.
     *
+11 −0
Original line number Diff line number Diff line
@@ -81,6 +81,9 @@ public class SurfaceControl {
    private static native boolean nativeSetActiveConfig(IBinder displayToken, int id);
    private static native void nativeSetDisplayPowerMode(
            IBinder displayToken, int mode);
    private static native void nativeDeferTransactionUntil(long nativeObject,
            IBinder handle, long frame);
    private static native IBinder nativeGetHandle(long nativeObject);


    private final CloseGuard mCloseGuard = CloseGuard.get();
@@ -358,6 +361,14 @@ public class SurfaceControl {
        nativeCloseTransaction();
    }

    public void deferTransactionUntil(IBinder handle, long frame) {
        nativeDeferTransactionUntil(mNativeObject, handle, frame);
    }

    public IBinder getHandle() {
        return nativeGetHandle(mNativeObject);
    }

    /** flag the transaction as an animation */
    public static void setAnimationTransaction() {
        nativeSetAnimationTransaction();
+12 −2
Original line number Diff line number Diff line
@@ -448,11 +448,10 @@ public class SurfaceView extends View {
        final boolean sizeChanged = mWidth != myWidth || mHeight != myHeight;
        final boolean visibleChanged = mVisible != mRequestedVisible;
        final boolean layoutSizeChanged = getWidth() != mLayout.width || getHeight() != mLayout.height;
        final boolean positionChanged = mLeft != mLocation[0] || mTop != mLocation[1];

        if (force || creating || formatChanged || sizeChanged || visibleChanged
            || mLeft != mLocation[0] || mTop != mLocation[1]
            || mUpdateWindowNeeded || mReportDrawNeeded || redrawNeeded || layoutSizeChanged) {

            if (DEBUG) Log.i(TAG, "Changes: creating=" + creating
                    + " format=" + formatChanged + " size=" + sizeChanged
                    + " visible=" + visibleChanged
@@ -616,11 +615,22 @@ public class SurfaceView extends View {
                    mSession.performDeferredDestroy(mWindow);
                }
            } catch (RemoteException ex) {
                Log.e(TAG, "Exception from relayout", ex);
            }
            if (DEBUG) Log.v(
                TAG, "Layout: x=" + mLayout.x + " y=" + mLayout.y +
                " w=" + mLayout.width + " h=" + mLayout.height +
                ", frame=" + mSurfaceFrame);
        } else if (positionChanged) { // Only the position has changed
            mLeft = mLocation[0];
            mTop = mLocation[1];
            try {
                mSession.repositionChild(mWindow, mLeft, mTop,
                        viewRoot != null ? viewRoot.getNextFrameNumber() : -1,
                        mWinFrame);
            } catch (RemoteException ex) {
                Log.e(TAG, "Exception from relayout", ex);
            }
        }
    }

+14 −0
Original line number Diff line number Diff line
@@ -6607,6 +6607,20 @@ public final class ViewRootImpl implements ViewParent,
        }
    }

    long getNextFrameNumber() {
        long frameNumber = -1;
        if (mSurfaceHolder != null) {
            mSurfaceHolder.mSurfaceLock.lock();
        }
        if (mSurface.isValid()) {
            frameNumber =  mSurface.getNextFrameNumber();
        }
        if (mSurfaceHolder != null) {
            mSurfaceHolder.mSurfaceLock.unlock();
        }
        return frameNumber;
    }

    class TakenSurfaceHolder extends BaseSurfaceHolder {
        @Override
        public boolean onAllowLockCanvas() {
Loading