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

Commit f648108f authored by John Reck's avatar John Reck
Browse files

Have RT drive window positioning

Bug: 22802885

Change-Id: I6beed5474d3a943b16e9097f7bd61ce3cbd37505
parent 15d21b3a
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -135,6 +135,9 @@ public class RenderNode {
    private RenderNode(String name, View owningView) {
        mNativeRenderNode = nCreate(name);
        mOwningView = owningView;
        if (mOwningView instanceof SurfaceView) {
            nRequestPositionUpdates(mNativeRenderNode, (SurfaceView) mOwningView);
        }
    }

    /**
@@ -854,6 +857,8 @@ public class RenderNode {
    private static native void nOutput(long renderNode);
    private static native int nGetDebugSize(long renderNode);

    private static native void nRequestPositionUpdates(long renderNode, SurfaceView callback);

    ///////////////////////////////////////////////////////////////////////////
    // Animations
    ///////////////////////////////////////////////////////////////////////////
+73 −28
Original line number Diff line number Diff line
@@ -135,7 +135,7 @@ public class SurfaceView extends View {
        }
    };

    final ViewTreeObserver.OnScrollChangedListener mScrollChangedListener
    private final ViewTreeObserver.OnScrollChangedListener mScrollChangedListener
            = new ViewTreeObserver.OnScrollChangedListener() {
                    @Override
                    public void onScrollChanged() {
@@ -143,6 +143,17 @@ public class SurfaceView extends View {
                    }
            };

    private final ViewTreeObserver.OnPreDrawListener mDrawListener =
            new ViewTreeObserver.OnPreDrawListener() {
                @Override
                public boolean onPreDraw() {
                    // reposition ourselves where the surface is
                    mHaveFrame = getWidth() > 0 && getHeight() > 0;
                    updateWindow(false, false);
                    return true;
                }
            };

    boolean mRequestedVisible = false;
    boolean mWindowVisibility = false;
    boolean mViewVisibility = false;
@@ -168,17 +179,9 @@ public class SurfaceView extends View {
    boolean mUpdateWindowNeeded;
    boolean mReportDrawNeeded;
    private Translator mTranslator;
    private int mWindowInsetLeft;
    private int mWindowInsetTop;

    private final ViewTreeObserver.OnPreDrawListener mDrawListener =
            new ViewTreeObserver.OnPreDrawListener() {
                @Override
                public boolean onPreDraw() {
                    // reposition ourselves where the surface is
                    mHaveFrame = getWidth() > 0 && getHeight() > 0;
                    updateWindow(false, false);
                    return true;
                }
            };
    private boolean mGlobalListenersAdded;

    public SurfaceView(Context context) {
@@ -443,17 +446,17 @@ public class SurfaceView extends View {
        int myHeight = mRequestedHeight;
        if (myHeight <= 0) myHeight = getHeight();

        getLocationInWindow(mLocation);
        final boolean creating = mWindow == null;
        final boolean formatChanged = mFormat != mRequestedFormat;
        final boolean sizeChanged = mWindowSpaceWidth != myWidth || mWindowSpaceHeight != myHeight;
        final boolean visibleChanged = mVisible != mRequestedVisible;
        final boolean layoutSizeChanged = getWidth() != mLayout.width
                || getHeight() != mLayout.height;
        final boolean positionChanged = mWindowSpaceLeft != mLocation[0] || mWindowSpaceTop != mLocation[1];

        if (force || creating || formatChanged || sizeChanged || visibleChanged
            || mUpdateWindowNeeded || mReportDrawNeeded || redrawNeeded) {
            getLocationInWindow(mLocation);

            if (DEBUG) Log.i(TAG, "Changes: creating=" + creating
                    + " format=" + formatChanged + " size=" + sizeChanged
                    + " visible=" + visibleChanged
@@ -643,7 +646,11 @@ public class SurfaceView extends View {
                TAG, "Layout: x=" + mLayout.x + " y=" + mLayout.y +
                " w=" + mLayout.width + " h=" + mLayout.height +
                ", frame=" + mSurfaceFrame);
        } else if (positionChanged || layoutSizeChanged) { // Only the position has changed
        } else if (!isHardwareAccelerated()) {
            getLocationInWindow(mLocation);
            final boolean positionChanged = mWindowSpaceLeft != mLocation[0]
                    || mWindowSpaceTop != mLocation[1];
            if (positionChanged || layoutSizeChanged) { // Only the position has changed
                mWindowSpaceLeft = mLocation[0];
                mWindowSpaceTop = mLocation[1];
                // For our size changed check, we keep mLayout.width and mLayout.height
@@ -654,15 +661,53 @@ public class SurfaceView extends View {
                transformFromViewToWindowSpace(mLocation);

                try {
                    Log.d(TAG, String.format("updateWindowPosition UI, " +
                            "postion = [%d, %d, %d, %d]", mWindowSpaceLeft, mWindowSpaceTop,
                            mLocation[0], mLocation[1]));
                    mSession.repositionChild(mWindow, mWindowSpaceLeft, mWindowSpaceTop,
                        mLocation[0], mLocation[1],
                        viewRoot != null ? viewRoot.getNextFrameNumber() : -1,
                        mWinFrame);
                            mLocation[0], mLocation[1], -1, mWinFrame);
                } catch (RemoteException ex) {
                    Log.e(TAG, "Exception from relayout", ex);
                }
            }
        }
    }

    private Rect mRTLastReportedPosition = new Rect();

    /**
     * Called by native on RenderThread to update the window position
     * @hide
     */
    public final void updateWindowPositionRT(long frameNumber,
            int left, int top, int right, int bottom) {
        IWindowSession session = mSession;
        MyWindow window = mWindow;
        if (session == null || window == null) {
            // Guess we got detached, that sucks
            return;
        }
        if (mRTLastReportedPosition.left == left
                && mRTLastReportedPosition.top == top
                && mRTLastReportedPosition.right == right
                && mRTLastReportedPosition.bottom == bottom) {
            return;
        }
        try {
            if (DEBUG) {
                Log.d(TAG, String.format("updateWindowPosition RT, frameNr = %d, " +
                        "postion = [%d, %d, %d, %d]", frameNumber, left, top,
                        right, bottom));
            }
            // Just using mRTLastReportedPosition as a dummy rect here
            session.repositionChild(window, left, top, right, bottom, frameNumber,
                    mRTLastReportedPosition);
            // Now overwrite mRTLastReportedPosition with our values
            mRTLastReportedPosition.set(left, top, right, bottom);
        } catch (RemoteException ex) {
            Log.e(TAG, "Exception from repositionChild", ex);
        }
    }

    private SurfaceHolder.Callback[] getSurfaceCallbacks() {
        SurfaceHolder.Callback callbacks[];
+0 −14
Original line number Diff line number Diff line
@@ -6815,20 +6815,6 @@ 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() {
+72 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
 */

#define LOG_TAG "OpenGLRenderer"
#define ATRACE_TAG ATRACE_TAG_VIEW

#include <EGL/egl.h>

@@ -24,7 +25,10 @@
#include <android_runtime/AndroidRuntime.h>

#include <Animator.h>
#include <DamageAccumulator.h>
#include <Matrix.h>
#include <RenderNode.h>
#include <TreeInfo.h>
#include <Paint.h>

#include "core_jni_helpers.h"
@@ -461,6 +465,69 @@ static void android_view_RenderNode_endAllAnimators(JNIEnv* env, jobject clazz,
    renderNode->animators().endAllStagingAnimators();
}

// ----------------------------------------------------------------------------
// SurfaceView position callback
// ----------------------------------------------------------------------------

jmethodID gSurfaceViewPositionUpdateMethod;

static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
        jlong renderNodePtr, jobject surfaceview) {
    class SurfaceViewPositionUpdater : public RenderNode::PositionListener {
    public:
        SurfaceViewPositionUpdater(JNIEnv* env, jobject surfaceview) {
            env->GetJavaVM(&mVm);
            mWeakRef = env->NewWeakGlobalRef(surfaceview);
        }

        virtual ~SurfaceViewPositionUpdater() {
            jnienv()->DeleteWeakGlobalRef(mWeakRef);
            mWeakRef = nullptr;
        }

        virtual void onPositionUpdated(RenderNode& node, const TreeInfo& info) override {
            if (CC_UNLIKELY(!mWeakRef || !info.updateWindowPositions)) return;
            ATRACE_NAME("Update SurfaceView position");

            JNIEnv* env = jnienv();
            jobject localref = env->NewLocalRef(mWeakRef);
            if (CC_UNLIKELY(!localref)) {
                jnienv()->DeleteWeakGlobalRef(mWeakRef);
                mWeakRef = nullptr;
                return;
            }
            Matrix4 transform;
            info.damageAccumulator->computeCurrentTransform(&transform);
            const RenderProperties& props = node.properties();
            uirenderer::Rect bounds(props.getWidth(), props.getHeight());
            transform.mapRect(bounds);
            bounds.left -= info.windowInsetLeft;
            bounds.right -= info.windowInsetLeft;
            bounds.top -= info.windowInsetTop;
            bounds.bottom -= info.windowInsetTop;
            env->CallVoidMethod(localref, gSurfaceViewPositionUpdateMethod,
                    (jlong) info.frameNumber, (jint) bounds.left, (jint) bounds.top,
                    (jint) bounds.right, (jint) bounds.bottom);
            env->DeleteLocalRef(localref);
        }

    private:
        JNIEnv* jnienv() {
            JNIEnv* env;
            if (mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
                LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", mVm);
            }
            return env;
        }

        JavaVM* mVm;
        jobject mWeakRef;
    };

    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
    renderNode->setPositionListener(new SurfaceViewPositionUpdater(env, surfaceview));
}

// ----------------------------------------------------------------------------
// JNI Glue
// ----------------------------------------------------------------------------
@@ -539,9 +606,14 @@ static const JNINativeMethod gMethods[] = {

    { "nAddAnimator",              "(JJ)V", (void*) android_view_RenderNode_addAnimator },
    { "nEndAllAnimators",          "(J)V", (void*) android_view_RenderNode_endAllAnimators },

    { "nRequestPositionUpdates",   "(JLandroid/view/SurfaceView;)V", (void*) android_view_RenderNode_requestPositionUpdates },
};

int register_android_view_RenderNode(JNIEnv* env) {
    jclass clazz = FindClassOrDie(env, "android/view/SurfaceView");
    gSurfaceViewPositionUpdateMethod = GetMethodIDOrDie(env, clazz,
            "updateWindowPositionRT", "(JIIII)V");
    return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
}

+15 −8
Original line number Diff line number Diff line
@@ -133,7 +133,14 @@ public:

    virtual void prepareTree(TreeInfo& info) {
        info.errorHandler = this;
        // TODO: This is hacky
        info.windowInsetLeft = -stagingProperties().getLeft();
        info.windowInsetTop = -stagingProperties().getTop();
        info.updateWindowPositions = true;
        RenderNode::prepareTree(info);
        info.updateWindowPositions = false;
        info.windowInsetLeft = 0;
        info.windowInsetTop = 0;
        info.errorHandler = NULL;
    }

@@ -368,28 +375,28 @@ static void android_view_ThreadedRenderer_setName(JNIEnv* env, jobject clazz,
static void android_view_ThreadedRenderer_initialize(JNIEnv* env, jobject clazz,
        jlong proxyPtr, jobject jsurface) {
    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    sp<ANativeWindow> window = android_view_Surface_getNativeWindow(env, jsurface);
    proxy->initialize(window);
    sp<Surface> surface = android_view_Surface_getSurface(env, jsurface);
    proxy->initialize(surface);
}

static void android_view_ThreadedRenderer_updateSurface(JNIEnv* env, jobject clazz,
        jlong proxyPtr, jobject jsurface) {
    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    sp<ANativeWindow> window;
    sp<Surface> surface;
    if (jsurface) {
        window = android_view_Surface_getNativeWindow(env, jsurface);
        surface = android_view_Surface_getSurface(env, jsurface);
    }
    proxy->updateSurface(window);
    proxy->updateSurface(surface);
}

static jboolean android_view_ThreadedRenderer_pauseSurface(JNIEnv* env, jobject clazz,
        jlong proxyPtr, jobject jsurface) {
    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    sp<ANativeWindow> window;
    sp<Surface> surface;
    if (jsurface) {
        window = android_view_Surface_getNativeWindow(env, jsurface);
        surface = android_view_Surface_getSurface(env, jsurface);
    }
    return proxy->pauseSurface(window);
    return proxy->pauseSurface(surface);
}

static void android_view_ThreadedRenderer_setup(JNIEnv* env, jobject clazz, jlong proxyPtr,
Loading