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 Diff line number Diff line
@@ -758,6 +758,12 @@ public final class ViewRootImpl implements ViewParent,
     */
    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
     * 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,
            boolean reportNextDraw, ArrayList<Runnable> commitCallbacks) {
        return frameNr -> {
    public boolean isHardwareEnabled() {
        return mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled();
    }

    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) {
                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) {
                    // We don't need to synchronize mRtBLASTSyncTransaction here since we're
                    // guaranteed that this is called after onFrameDraw and mNextDrawUseBlastSync
@@ -3993,49 +4043,45 @@ public final class ViewRootImpl implements ViewParent,
                }

                if (reportNextDraw) {
                    // TODO: Use the frame number
                    pendingDrawFinished();
                }
                if (commitCallbacks != null) {
                    for (int i = 0; i < commitCallbacks.size(); i++) {
                        commitCallbacks.get(i).run();
                    }

                if (frameWasNotDrawn) {
                    clearBlastSync();
                }
            });
        };
    }

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

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

        ArrayList<Runnable> commitCallbacks = mAttachInfo.mTreeObserver
                .captureFrameCommitCallbacks();
        final boolean needFrameCompleteCallback =
                mNextDrawUseBlastSync || mReportNextDraw
                        || (commitCallbacks != null && commitCallbacks.size() > 0);
        if (needFrameCompleteCallback) {
            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;
        final boolean needFrameCommitCallback =
                (commitCallbacks != null && commitCallbacks.size() > 0);
        if (!needFrameCommitCallback) {
            return;
        }
        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() {
@@ -4065,6 +4111,8 @@ public final class ViewRootImpl implements ViewParent,
                        + " Creating transactionCompleteCallback=" + nextDrawUseBlastSync);
            }

            mRtLastAttemptedDrawFrameNum = frame;

            if (needsCallbackForBlur) {
                mBlurRegionAggregator
                    .dispatchBlurTransactionIfNeeded(frame, blurRegionsForFrame, hasBlurUpdates);
@@ -4087,18 +4135,7 @@ public final class ViewRootImpl implements ViewParent,
                    if (DEBUG_BLAST) {
                        Log.d(mTag, "Received transactionCompleteCallback frameNum=" + frame);
                    }
                    mHandler.postAtFrontOfQueue(() -> {
                        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();
                        }
                    });
                    mHandler.postAtFrontOfQueue(this::clearBlastSync);
                });
            } else if (reportNextDraw) {
                // 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;
        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "draw");

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

        try {
            boolean canUseAsync = draw(fullRedrawNeeded);
+7 −1
Original line number 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[] = {
        /* name, signature, funcPtr */
        // clang-format off
@@ -151,7 +156,8 @@ static const JNINativeMethod gMethods[] = {
        {"nativeMergeWithNextTransaction", "(JJJ)V", (void*)nativeMergeWithNextTransaction},
        {"nativeSetTransactionCompleteCallback",
                "(JJLandroid/graphics/BLASTBufferQueue$TransactionCompleteCallback;)V",
                (void*)nativeSetTransactionCompleteCallback}
                (void*)nativeSetTransactionCompleteCallback},
        {"nativeGetLastAcquiredFrameNum", "(J)J", (void*)nativeGetLastAcquiredFrameNum},
        // clang-format on
};

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

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

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

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

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

    /** @hide */
    public void setFrameCompleteCallback(FrameCompleteCallback callback) {
        nSetFrameCompleteCallback(mNativeProxy, callback);
@@ -896,13 +902,27 @@ public class HardwareRenderer {
     *
     * @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 nSetFrameCommitCallback(long nativeProxy,
            FrameCommitCallback callback);

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

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

struct {
    jmethodID onFrameCommit;
} gFrameCommitCallback;

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

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

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

    void onFrameComplete(int64_t frameNr) {
    void onFrameCommit(bool didProduceBuffer) {
        if (mObject) {
            ATRACE_FORMAT("frameComplete %" PRId64, frameNr);
            getenv(mVm)->CallVoidMethod(mObject, gFrameCompleteCallback.onFrameComplete, frameNr);
            ATRACE_FORMAT("frameCommit success=%d", didProduceBuffer);
            getenv(mVm)->CallVoidMethod(mObject, gFrameCommitCallback.onFrameCommit,
                                        didProduceBuffer);
            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,
        jobject clazz, jlong proxyPtr, jobject callback) {
    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    if (!callback) {
        proxy->setFrameCompleteCallback(nullptr);
    } else {
        sp<FrameCompleteWrapper> wrapper = new FrameCompleteWrapper{env, callback};
        proxy->setFrameCompleteCallback([wrapper](int64_t frameNr) {
            wrapper->onFrameComplete(frameNr);
        RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
        JavaVM* vm = nullptr;
        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},
        {"nSetFrameCallback", "(JLandroid/graphics/HardwareRenderer$FrameDrawingCallback;)V",
         (void*)android_view_ThreadedRenderer_setFrameCallback},
        {"nSetFrameCommitCallback", "(JLandroid/graphics/HardwareRenderer$FrameCommitCallback;)V",
         (void*)android_view_ThreadedRenderer_setFrameCommitCallback},
        {"nSetFrameCompleteCallback",
         "(JLandroid/graphics/HardwareRenderer$FrameCompleteCallback;)V",
         (void*)android_view_ThreadedRenderer_setFrameCompleteCallback},
@@ -974,10 +997,15 @@ int register_android_view_ThreadedRenderer(JNIEnv* env) {
    gFrameDrawingCallback.onFrameDraw = GetMethodIDOrDie(env, frameCallbackClass,
            "onFrameDraw", "(J)V");

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

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

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