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

Commit 019b9be4 authored by Chavi Weingarten's avatar Chavi Weingarten Committed by Android (Google) Code Review
Browse files

Merge "Rework blast sync callback model"

parents f8c82f86 9c137535
Loading
Loading
Loading
Loading
+88 −50
Original line number Original line Diff line number Diff line
@@ -758,6 +758,12 @@ public final class ViewRootImpl implements ViewParent,
     */
     */
    private boolean mWaitForBlastSyncComplete = false;
    private boolean mWaitForBlastSyncComplete = false;


    /**
     * Keeps track of the last frame number that was attempted to draw. Should only be accessed on
     * the RenderThread.
     */
    private long mRtLastAttemptedDrawFrameNum = 0;

    /**
    /**
     * Keeps track of whether a traverse was triggered while the UI thread was paused. This can
     * Keeps track of whether a traverse was triggered while the UI thread was paused. This can
     * occur when the client is waiting on another process to submit the transaction that
     * occur when the client is waiting on another process to submit the transaction that
@@ -3974,16 +3980,60 @@ public final class ViewRootImpl implements ViewParent,
    }
    }


    /**
    /**
     * The callback will run on the render thread.
     * Only call this on the UI Thread.
     */
    void clearBlastSync() {
        mNextDrawUseBlastSync = false;
        mWaitForBlastSyncComplete = false;
        if (DEBUG_BLAST) {
            Log.d(mTag, "Scheduling a traversal=" + mRequestedTraverseWhilePaused
                    + " due to a previous skipped traversal.");
        }
        if (mRequestedTraverseWhilePaused) {
            mRequestedTraverseWhilePaused = false;
            scheduleTraversals();
        }
    }

    /**
     * @hide
     */
     */
    private HardwareRenderer.FrameCompleteCallback createFrameCompleteCallback(Handler handler,
    public boolean isHardwareEnabled() {
            boolean reportNextDraw, ArrayList<Runnable> commitCallbacks) {
        return mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled();
        return frameNr -> {
    }

    private boolean addFrameCompleteCallbackIfNeeded(boolean reportNextDraw) {
        if (!isHardwareEnabled()) {
            return false;
        }

        if (!mNextDrawUseBlastSync && !reportNextDraw) {
            return false;
        }

        if (DEBUG_BLAST) {
            Log.d(mTag, "Creating frameCompleteCallback");
        }

        mAttachInfo.mThreadedRenderer.setFrameCompleteCallback(() -> {
            long frameNr = mBlastBufferQueue.getLastAcquiredFrameNum();
            if (DEBUG_BLAST) {
            if (DEBUG_BLAST) {
                Log.d(mTag, "Received frameCompleteCallback frameNum=" + frameNr);
                Log.d(mTag, "Received frameCompleteCallback "
                        + " lastAcquiredFrameNum=" + frameNr
                        + " lastAttemptedDrawFrameNum=" + mRtLastAttemptedDrawFrameNum);
            }
            }


            handler.postAtFrontOfQueue(() -> {
            boolean frameWasNotDrawn = frameNr != mRtLastAttemptedDrawFrameNum;
            // If frame wasn't drawn, clear out the next transaction so it doesn't affect the next
            // draw attempt. The next transaction and transaction complete callback were only set
            // for the current draw attempt.
            if (frameWasNotDrawn) {
                mBlastBufferQueue.setNextTransaction(null);
                mBlastBufferQueue.setTransactionCompleteCallback(mRtLastAttemptedDrawFrameNum,
                        null);
            }

            mHandler.postAtFrontOfQueue(() -> {
                if (mNextDrawUseBlastSync) {
                if (mNextDrawUseBlastSync) {
                    // We don't need to synchronize mRtBLASTSyncTransaction here since we're
                    // We don't need to synchronize mRtBLASTSyncTransaction here since we're
                    // guaranteed that this is called after onFrameDraw and mNextDrawUseBlastSync
                    // guaranteed that this is called after onFrameDraw and mNextDrawUseBlastSync
@@ -3993,49 +4043,45 @@ public final class ViewRootImpl implements ViewParent,
                }
                }


                if (reportNextDraw) {
                if (reportNextDraw) {
                    // TODO: Use the frame number
                    pendingDrawFinished();
                    pendingDrawFinished();
                }
                }
                if (commitCallbacks != null) {

                    for (int i = 0; i < commitCallbacks.size(); i++) {
                if (frameWasNotDrawn) {
                        commitCallbacks.get(i).run();
                    clearBlastSync();
                    }
                }
                }
            });
            });
        };
        });
    }
        return true;

    /**
     * @hide
     */
    public boolean isHardwareEnabled() {
        return mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled();
    }
    }


    private boolean addFrameCompleteCallbackIfNeeded() {
    private void addFrameCommitCallbackIfNeeded() {
        if (!isHardwareEnabled()) {
        if (!isHardwareEnabled()) {
            return false;
            return;
        }
        }


        ArrayList<Runnable> commitCallbacks = mAttachInfo.mTreeObserver
        ArrayList<Runnable> commitCallbacks = mAttachInfo.mTreeObserver
                .captureFrameCommitCallbacks();
                .captureFrameCommitCallbacks();
        final boolean needFrameCompleteCallback =
        final boolean needFrameCommitCallback =
                mNextDrawUseBlastSync || mReportNextDraw
                (commitCallbacks != null && commitCallbacks.size() > 0);
                        || (commitCallbacks != null && commitCallbacks.size() > 0);
        if (!needFrameCommitCallback) {
        if (needFrameCompleteCallback) {
            return;
            if (DEBUG_BLAST) {
                Log.d(mTag, "Creating frameCompleteCallback"
                        + " mNextDrawUseBlastSync=" + mNextDrawUseBlastSync
                        + " mReportNextDraw=" + mReportNextDraw
                        + " commitCallbacks size="
                        + (commitCallbacks == null ? 0 : commitCallbacks.size()));
            }
            mAttachInfo.mThreadedRenderer.setFrameCompleteCallback(
                    createFrameCompleteCallback(mAttachInfo.mHandler, mReportNextDraw,
                            commitCallbacks));
            return true;
        }
        }
        return false;

        if (DEBUG_DRAW) {
            Log.d(mTag, "Creating frameCommitCallback"
                    + " commitCallbacks size=" + commitCallbacks.size());
        }
        mAttachInfo.mThreadedRenderer.setFrameCommitCallback(didProduceBuffer -> {
            if (DEBUG_DRAW) {
                Log.d(mTag, "Received frameCommitCallback didProduceBuffer=" + didProduceBuffer);
            }

            mHandler.postAtFrontOfQueue(() -> {
                for (int i = 0; i < commitCallbacks.size(); i++) {
                    commitCallbacks.get(i).run();
                }
            });
        });
    }
    }


    private void addFrameCallbackIfNeeded() {
    private void addFrameCallbackIfNeeded() {
@@ -4065,6 +4111,8 @@ public final class ViewRootImpl implements ViewParent,
                        + " Creating transactionCompleteCallback=" + nextDrawUseBlastSync);
                        + " Creating transactionCompleteCallback=" + nextDrawUseBlastSync);
            }
            }


            mRtLastAttemptedDrawFrameNum = frame;

            if (needsCallbackForBlur) {
            if (needsCallbackForBlur) {
                mBlurRegionAggregator
                mBlurRegionAggregator
                    .dispatchBlurTransactionIfNeeded(frame, blurRegionsForFrame, hasBlurUpdates);
                    .dispatchBlurTransactionIfNeeded(frame, blurRegionsForFrame, hasBlurUpdates);
@@ -4087,18 +4135,7 @@ public final class ViewRootImpl implements ViewParent,
                    if (DEBUG_BLAST) {
                    if (DEBUG_BLAST) {
                        Log.d(mTag, "Received transactionCompleteCallback frameNum=" + frame);
                        Log.d(mTag, "Received transactionCompleteCallback frameNum=" + frame);
                    }
                    }
                    mHandler.postAtFrontOfQueue(() -> {
                    mHandler.postAtFrontOfQueue(this::clearBlastSync);
                        mNextDrawUseBlastSync = false;
                        mWaitForBlastSyncComplete = false;
                        if (DEBUG_BLAST) {
                            Log.d(mTag, "Scheduling a traversal=" + mRequestedTraverseWhilePaused
                                    + " due to a previous skipped traversal.");
                        }
                        if (mRequestedTraverseWhilePaused) {
                            mRequestedTraverseWhilePaused = false;
                            scheduleTraversals();
                        }
                    });
                });
                });
            } else if (reportNextDraw) {
            } else if (reportNextDraw) {
                // If we need to report next draw, wait for adapter to flush its shadow queue
                // If we need to report next draw, wait for adapter to flush its shadow queue
@@ -4124,8 +4161,9 @@ public final class ViewRootImpl implements ViewParent,
        mIsDrawing = true;
        mIsDrawing = true;
        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "draw");
        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "draw");


        boolean usingAsyncReport = addFrameCompleteCallbackIfNeeded();
        addFrameCallbackIfNeeded();
        addFrameCallbackIfNeeded();
        addFrameCommitCallbackIfNeeded();
        boolean usingAsyncReport = addFrameCompleteCallbackIfNeeded(mReportNextDraw);


        try {
        try {
            boolean canUseAsync = draw(fullRedrawNeeded);
            boolean canUseAsync = draw(fullRedrawNeeded);
+7 −1
Original line number Original line Diff line number Diff line
@@ -139,6 +139,11 @@ static void nativeSetTransactionCompleteCallback(JNIEnv* env, jclass clazz, jlon
    }
    }
}
}


static jlong nativeGetLastAcquiredFrameNum(JNIEnv* env, jclass clazz, jlong ptr) {
    sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr);
    return queue->getLastAcquiredFrameNum();
}

static const JNINativeMethod gMethods[] = {
static const JNINativeMethod gMethods[] = {
        /* name, signature, funcPtr */
        /* name, signature, funcPtr */
        // clang-format off
        // clang-format off
@@ -151,7 +156,8 @@ static const JNINativeMethod gMethods[] = {
        {"nativeMergeWithNextTransaction", "(JJJ)V", (void*)nativeMergeWithNextTransaction},
        {"nativeMergeWithNextTransaction", "(JJJ)V", (void*)nativeMergeWithNextTransaction},
        {"nativeSetTransactionCompleteCallback",
        {"nativeSetTransactionCompleteCallback",
                "(JJLandroid/graphics/BLASTBufferQueue$TransactionCompleteCallback;)V",
                "(JJLandroid/graphics/BLASTBufferQueue$TransactionCompleteCallback;)V",
                (void*)nativeSetTransactionCompleteCallback}
                (void*)nativeSetTransactionCompleteCallback},
        {"nativeGetLastAcquiredFrameNum", "(J)J", (void*)nativeGetLastAcquiredFrameNum},
        // clang-format on
        // clang-format on
};
};


+4 −0
Original line number Original line Diff line number Diff line
@@ -39,6 +39,7 @@ public final class BLASTBufferQueue {
                                                              long frameNumber);
                                                              long frameNumber);
    private static native void nativeSetTransactionCompleteCallback(long ptr, long frameNumber,
    private static native void nativeSetTransactionCompleteCallback(long ptr, long frameNumber,
            TransactionCompleteCallback callback);
            TransactionCompleteCallback callback);
    private static native long nativeGetLastAcquiredFrameNum(long ptr);


    /**
    /**
     * Callback sent to {@link #setTransactionCompleteCallback(long, TransactionCompleteCallback)}
     * Callback sent to {@link #setTransactionCompleteCallback(long, TransactionCompleteCallback)}
@@ -145,4 +146,7 @@ public final class BLASTBufferQueue {
        nativeMergeWithNextTransaction(mNativeObject, nativeTransaction, frameNumber);
        nativeMergeWithNextTransaction(mNativeObject, nativeTransaction, frameNumber);
    }
    }


    public long getLastAcquiredFrameNum() {
        return nativeGetLastAcquiredFrameNum(mNativeObject);
    }
}
}
+28 −5
Original line number Original line Diff line number Diff line
@@ -388,7 +388,8 @@ public class HardwareRenderer {
         */
         */
        public @NonNull FrameRenderRequest setFrameCommitCallback(@NonNull Executor executor,
        public @NonNull FrameRenderRequest setFrameCommitCallback(@NonNull Executor executor,
                @NonNull Runnable frameCommitCallback) {
                @NonNull Runnable frameCommitCallback) {
            setFrameCompleteCallback(frameNr -> executor.execute(frameCommitCallback));
            nSetFrameCommitCallback(mNativeProxy,
                    didProduceBuffer -> executor.execute(frameCommitCallback));
            return this;
            return this;
        }
        }


@@ -608,6 +609,11 @@ public class HardwareRenderer {
        return mOpaque;
        return mOpaque;
    }
    }


    /** @hide */
    public void setFrameCommitCallback(FrameCommitCallback callback) {
        nSetFrameCommitCallback(mNativeProxy, callback);
    }

    /** @hide */
    /** @hide */
    public void setFrameCompleteCallback(FrameCompleteCallback callback) {
    public void setFrameCompleteCallback(FrameCompleteCallback callback) {
        nSetFrameCompleteCallback(mNativeProxy, callback);
        nSetFrameCompleteCallback(mNativeProxy, callback);
@@ -896,13 +902,27 @@ public class HardwareRenderer {
     *
     *
     * @hide
     * @hide
     */
     */
    public interface FrameCompleteCallback {
    public interface FrameCommitCallback {
        /**
         * Invoked after a new frame was drawn
         *
         * @param didProduceBuffer The draw successfully produced a new buffer.
         */
        void onFrameCommit(boolean didProduceBuffer);
    }

    /**
    /**
         * Invoked after a frame draw
     * Interface used to be notified when RenderThread has finished an attempt to draw. This doesn't
     * mean a new frame has drawn, specifically if there's nothing new to draw, but only that
     * RenderThread had a chance to draw a frame.
     *
     *
         * @param frameNr The id of the frame that was drawn.
     * @hide
     */
     */
        void onFrameComplete(long frameNr);
    public interface FrameCompleteCallback {
        /**
         * Invoked after a frame draw was attempted.
         */
        void onFrameComplete();
    }
    }


    /**
    /**
@@ -1391,6 +1411,9 @@ public class HardwareRenderer {


    private static native void nSetFrameCallback(long nativeProxy, FrameDrawingCallback callback);
    private static native void nSetFrameCallback(long nativeProxy, FrameDrawingCallback callback);


    private static native void nSetFrameCommitCallback(long nativeProxy,
            FrameCommitCallback callback);

    private static native void nSetFrameCompleteCallback(long nativeProxy,
    private static native void nSetFrameCompleteCallback(long nativeProxy,
            FrameCompleteCallback callback);
            FrameCompleteCallback callback);


+41 −13
Original line number Original line Diff line number Diff line
@@ -72,6 +72,10 @@ struct {
    jmethodID onFrameDraw;
    jmethodID onFrameDraw;
} gFrameDrawingCallback;
} gFrameDrawingCallback;


struct {
    jmethodID onFrameCommit;
} gFrameCommitCallback;

struct {
struct {
    jmethodID onFrameComplete;
    jmethodID onFrameComplete;
} gFrameCompleteCallback;
} gFrameCompleteCallback;
@@ -101,22 +105,21 @@ private:
    JavaVM* mVm;
    JavaVM* mVm;
};
};


class FrameCompleteWrapper : public LightRefBase<FrameCompleteWrapper> {
class FrameCommitWrapper : public LightRefBase<FrameCommitWrapper> {
public:
public:
    explicit FrameCompleteWrapper(JNIEnv* env, jobject jobject) {
    explicit FrameCommitWrapper(JNIEnv* env, jobject jobject) {
        env->GetJavaVM(&mVm);
        env->GetJavaVM(&mVm);
        mObject = env->NewGlobalRef(jobject);
        mObject = env->NewGlobalRef(jobject);
        LOG_ALWAYS_FATAL_IF(!mObject, "Failed to make global ref");
        LOG_ALWAYS_FATAL_IF(!mObject, "Failed to make global ref");
    }
    }


    ~FrameCompleteWrapper() {
    ~FrameCommitWrapper() { releaseObject(); }
        releaseObject();
    }


    void onFrameComplete(int64_t frameNr) {
    void onFrameCommit(bool didProduceBuffer) {
        if (mObject) {
        if (mObject) {
            ATRACE_FORMAT("frameComplete %" PRId64, frameNr);
            ATRACE_FORMAT("frameCommit success=%d", didProduceBuffer);
            getenv(mVm)->CallVoidMethod(mObject, gFrameCompleteCallback.onFrameComplete, frameNr);
            getenv(mVm)->CallVoidMethod(mObject, gFrameCommitCallback.onFrameCommit,
                                        didProduceBuffer);
            releaseObject();
            releaseObject();
        }
        }
    }
    }
@@ -607,15 +610,33 @@ static void android_view_ThreadedRenderer_setFrameCallback(JNIEnv* env,
    }
    }
}
}


static void android_view_ThreadedRenderer_setFrameCommitCallback(JNIEnv* env, jobject clazz,
                                                                 jlong proxyPtr, jobject callback) {
    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    if (!callback) {
        proxy->setFrameCommitCallback(nullptr);
    } else {
        sp<FrameCommitWrapper> wrapper = new FrameCommitWrapper{env, callback};
        proxy->setFrameCommitCallback(
                [wrapper](bool didProduceBuffer) { wrapper->onFrameCommit(didProduceBuffer); });
    }
}

static void android_view_ThreadedRenderer_setFrameCompleteCallback(JNIEnv* env,
static void android_view_ThreadedRenderer_setFrameCompleteCallback(JNIEnv* env,
        jobject clazz, jlong proxyPtr, jobject callback) {
        jobject clazz, jlong proxyPtr, jobject callback) {
    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    if (!callback) {
    if (!callback) {
        proxy->setFrameCompleteCallback(nullptr);
        proxy->setFrameCompleteCallback(nullptr);
    } else {
    } else {
        sp<FrameCompleteWrapper> wrapper = new FrameCompleteWrapper{env, callback};
        RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
        proxy->setFrameCompleteCallback([wrapper](int64_t frameNr) {
        JavaVM* vm = nullptr;
            wrapper->onFrameComplete(frameNr);
        LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&vm) != JNI_OK, "Unable to get Java VM");
        auto globalCallbackRef =
                std::make_shared<JGlobalRefHolder>(vm, env->NewGlobalRef(callback));
        proxy->setFrameCompleteCallback([globalCallbackRef]() {
            JNIEnv* env = getenv(globalCallbackRef->vm());
            env->CallVoidMethod(globalCallbackRef->object(),
                                gFrameCompleteCallback.onFrameComplete);
        });
        });
    }
    }
}
}
@@ -907,6 +928,8 @@ static const JNINativeMethod gMethods[] = {
         (void*)android_view_ThreadedRenderer_setPrepareSurfaceControlForWebviewCallback},
         (void*)android_view_ThreadedRenderer_setPrepareSurfaceControlForWebviewCallback},
        {"nSetFrameCallback", "(JLandroid/graphics/HardwareRenderer$FrameDrawingCallback;)V",
        {"nSetFrameCallback", "(JLandroid/graphics/HardwareRenderer$FrameDrawingCallback;)V",
         (void*)android_view_ThreadedRenderer_setFrameCallback},
         (void*)android_view_ThreadedRenderer_setFrameCallback},
        {"nSetFrameCommitCallback", "(JLandroid/graphics/HardwareRenderer$FrameCommitCallback;)V",
         (void*)android_view_ThreadedRenderer_setFrameCommitCallback},
        {"nSetFrameCompleteCallback",
        {"nSetFrameCompleteCallback",
         "(JLandroid/graphics/HardwareRenderer$FrameCompleteCallback;)V",
         "(JLandroid/graphics/HardwareRenderer$FrameCompleteCallback;)V",
         (void*)android_view_ThreadedRenderer_setFrameCompleteCallback},
         (void*)android_view_ThreadedRenderer_setFrameCompleteCallback},
@@ -974,10 +997,15 @@ int register_android_view_ThreadedRenderer(JNIEnv* env) {
    gFrameDrawingCallback.onFrameDraw = GetMethodIDOrDie(env, frameCallbackClass,
    gFrameDrawingCallback.onFrameDraw = GetMethodIDOrDie(env, frameCallbackClass,
            "onFrameDraw", "(J)V");
            "onFrameDraw", "(J)V");


    jclass frameCommitClass =
            FindClassOrDie(env, "android/graphics/HardwareRenderer$FrameCommitCallback");
    gFrameCommitCallback.onFrameCommit =
            GetMethodIDOrDie(env, frameCommitClass, "onFrameCommit", "(Z)V");

    jclass frameCompleteClass = FindClassOrDie(env,
    jclass frameCompleteClass = FindClassOrDie(env,
            "android/graphics/HardwareRenderer$FrameCompleteCallback");
            "android/graphics/HardwareRenderer$FrameCompleteCallback");
    gFrameCompleteCallback.onFrameComplete = GetMethodIDOrDie(env, frameCompleteClass,
    gFrameCompleteCallback.onFrameComplete =
            "onFrameComplete", "(J)V");
            GetMethodIDOrDie(env, frameCompleteClass, "onFrameComplete", "()V");


    void* handle_ = dlopen("libandroid.so", RTLD_NOW | RTLD_NODELETE);
    void* handle_ = dlopen("libandroid.so", RTLD_NOW | RTLD_NODELETE);
    fromSurface = (ANW_fromSurface)dlsym(handle_, "ANativeWindow_fromSurface");
    fromSurface = (ANW_fromSurface)dlsym(handle_, "ANativeWindow_fromSurface");
Loading