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

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

Merge "Send syncStatus and return FrameCommitCallback in FrameCallback"

parents cb60d919 b680371f
Loading
Loading
Loading
Loading
+38 −3
Original line number Diff line number Diff line
@@ -477,6 +477,19 @@ public final class ThreadedRenderer extends HardwareRenderer {
        mNextRtFrameCallbacks.add(callback);
    }

    /**
     * Remove a frame drawing callback that was added via
     * {@link #registerRtFrameCallback(FrameDrawingCallback)}
     *
     * @param callback The callback to unregister.
     */
    void unregisterRtFrameCallback(@NonNull FrameDrawingCallback callback) {
        if (mNextRtFrameCallbacks == null) {
            return;
        }
        mNextRtFrameCallbacks.remove(callback);
    }

    /**
     * Destroys all hardware rendering resources associated with the specified
     * view hierarchy.
@@ -679,9 +692,31 @@ public final class ThreadedRenderer extends HardwareRenderer {
        if (mNextRtFrameCallbacks != null) {
            final ArrayList<FrameDrawingCallback> frameCallbacks = mNextRtFrameCallbacks;
            mNextRtFrameCallbacks = null;
            setFrameCallback(frame -> {
            setFrameCallback(new FrameDrawingCallback() {
                @Override
                public void onFrameDraw(long frame) {
                }

                @Override
                public FrameCommitCallback onFrameDraw(int syncResult, long frame) {
                    ArrayList<FrameCommitCallback> frameCommitCallbacks = new ArrayList<>();
                    for (int i = 0; i < frameCallbacks.size(); ++i) {
                    frameCallbacks.get(i).onFrameDraw(frame);
                        FrameCommitCallback frameCommitCallback = frameCallbacks.get(i)
                                .onFrameDraw(syncResult, frame);
                        if (frameCommitCallback != null) {
                            frameCommitCallbacks.add(frameCommitCallback);
                        }
                    }

                    if (frameCommitCallbacks.isEmpty()) {
                        return null;
                    }

                    return didProduceBuffer -> {
                        for (int i = 0; i < frameCommitCallbacks.size(); ++i) {
                            frameCommitCallbacks.get(i).onFrameCommit(didProduceBuffer);
                        }
                    };
                }
            });
        }
+119 −78
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package android.view;

import static android.graphics.HardwareRenderer.SYNC_CONTEXT_IS_STOPPED;
import static android.graphics.HardwareRenderer.SYNC_LOST_SURFACE_REWARD_IF_FOUND;
import static android.os.IInputConstants.INVALID_INPUT_EVENT_ID;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
@@ -1392,12 +1394,21 @@ public final class ViewRootImpl implements ViewParent,
     */
    public void registerRtFrameCallback(@NonNull FrameDrawingCallback callback) {
        if (mAttachInfo.mThreadedRenderer != null) {
            mAttachInfo.mThreadedRenderer.registerRtFrameCallback(frame -> {
            mAttachInfo.mThreadedRenderer.registerRtFrameCallback(new FrameDrawingCallback() {
                @Override
                public void onFrameDraw(long frame) {
                }

                @Override
                public HardwareRenderer.FrameCommitCallback onFrameDraw(int syncResult,
                        long frame) {
                    try {
                    callback.onFrameDraw(frame);
                        return callback.onFrameDraw(syncResult, frame);
                    } catch (Exception e) {
                        Log.e(TAG, "Exception while executing onFrameDraw", e);
                    }
                    return null;
                }
            });
        }
    }
@@ -4020,36 +4031,49 @@ public final class ViewRootImpl implements ViewParent,
        return mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled();
    }

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

        if (!useBlastSync && !reportNextDraw) {
            return false;
        ArrayList<Runnable> commitCallbacks = mAttachInfo.mTreeObserver
                .captureFrameCommitCallbacks();
        final boolean needFrameCommitCallback =
                (commitCallbacks != null && commitCallbacks.size() > 0);
        if (!needFrameCommitCallback) {
            return;
        }

        if (DEBUG_BLAST) {
            Log.d(mTag, "Creating frameCompleteCallback");
        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);
            }

        final Consumer<SurfaceControl.Transaction> blastSyncConsumer = mBLASTDrawConsumer;
        mBLASTDrawConsumer = null;
            mHandler.postAtFrontOfQueue(() -> {
                for (int i = 0; i < commitCallbacks.size(); i++) {
                    commitCallbacks.get(i).run();
                }
            });
        });
    }

        mAttachInfo.mThreadedRenderer.setFrameCompleteCallback(() -> {
            long frameNr = mBlastBufferQueue.getLastAcquiredFrameNum();
    private HardwareRenderer.FrameCommitCallback createFrameCommitCallbackForSync(
            boolean useBlastSync, boolean reportNextDraw, Consumer<Transaction> blastSyncConsumer) {
        return didProduceBuffer -> {
            if (DEBUG_BLAST) {
                Log.d(mTag, "Received frameCompleteCallback "
                        + " lastAcquiredFrameNum=" + frameNr
                        + " lastAttemptedDrawFrameNum=" + mRtLastAttemptedDrawFrameNum);
                Log.d(mTag, "Received frameCommittedCallback "
                        + " lastAttemptedDrawFrameNum=" + mRtLastAttemptedDrawFrameNum
                        + " didProduceBuffer=" + didProduceBuffer);
            }

            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) {
            if (!didProduceBuffer) {
                mBlastBufferQueue.setSyncTransaction(null);
                // Apply the transactions that were sent to mergeWithNextTransaction since the
                // frame didn't draw on this vsync. It's possible the frame will draw later, but
@@ -4059,6 +4083,11 @@ public final class ViewRootImpl implements ViewParent,

            Transaction tmpTransaction = new Transaction();
            tmpTransaction.merge(mRtBLASTSyncTransaction);
            // Post at front of queue so the buffer can be processed immediately and allow RT
            // to continue processing new buffers. If RT tries to process buffers before the sync
            // buffer is applied, the new buffers will not get acquired and could result in a
            // deadlock. UI thread would wait on RT, but RT would be blocked waiting for a free
            // buffer.
            mHandler.postAtFrontOfQueue(() -> {
                if (useBlastSync) {
                    mSurfaceChangedTransaction.merge(tmpTransaction);
@@ -4071,85 +4100,92 @@ public final class ViewRootImpl implements ViewParent,
                    pendingDrawFinished();
                }
            });
        });
        return true;
        };
    }

    private void addFrameCommitCallbackIfNeeded() {
    @Nullable
    private FrameDrawingCallback createFrameDrawingCallbackIfNeeded(boolean useBlastSync,
            boolean reportNextDraw) {
        if (!isHardwareEnabled()) {
            return;
        }

        ArrayList<Runnable> commitCallbacks = mAttachInfo.mTreeObserver
                .captureFrameCommitCallbacks();
        final boolean needFrameCommitCallback =
                (commitCallbacks != null && commitCallbacks.size() > 0);
        if (!needFrameCommitCallback) {
            return;
        }

        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();
                }
            });
        });
            return null;
        }

    private void addFrameCallbackIfNeeded(boolean useBlastSync) {
        final boolean hasBlurUpdates = mBlurRegionAggregator.hasUpdates();
        final boolean needsCallbackForBlur = hasBlurUpdates || mBlurRegionAggregator.hasRegions();

        if (!useBlastSync && !needsCallbackForBlur) {
            return;
        if (!useBlastSync && !needsCallbackForBlur && !reportNextDraw) {
            return null;
        }

        final Consumer<SurfaceControl.Transaction> blastSyncConsumer = mBLASTDrawConsumer;
        mBLASTDrawConsumer = null;

        if (DEBUG_BLAST) {
            Log.d(mTag, "Creating frameDrawingCallback"
                    + " nextDrawUseBlastSync=" + useBlastSync
                    + " hasBlurUpdates=" + hasBlurUpdates);
                    + " reportNextDraw=" + reportNextDraw
                    + " hasBlurUpdates=" + hasBlurUpdates
                    + " hasBlastSyncConsumer=" + (blastSyncConsumer != null));
        }

        final BackgroundBlurDrawable.BlurRegion[] blurRegionsForFrame =
                needsCallbackForBlur ?  mBlurRegionAggregator.getBlurRegionsCopyForRT() : null;

        // The callback will run on the render thread.
        HardwareRenderer.FrameDrawingCallback frameDrawingCallback = frame -> {
        return new FrameDrawingCallback() {
            @Override
            public void onFrameDraw(long frame) {
            }

            @Override
            public HardwareRenderer.FrameCommitCallback onFrameDraw(int syncResult, long frame) {
                if (DEBUG_BLAST) {
                Log.d(mTag, "Received frameDrawingCallback frameNum=" + frame + "."
                        + " Creating transactionCompleteCallback=" + useBlastSync);
                    Log.d(mTag,
                            "Received frameDrawingCallback syncResult=" + syncResult + " frameNum="
                                    + frame + ".");
                }

                mRtLastAttemptedDrawFrameNum = frame;

                if (needsCallbackForBlur) {
                mBlurRegionAggregator
                    .dispatchBlurTransactionIfNeeded(frame, blurRegionsForFrame, hasBlurUpdates);
                    mBlurRegionAggregator.dispatchBlurTransactionIfNeeded(frame,
                            blurRegionsForFrame, hasBlurUpdates);
                }

                if (mBlastBufferQueue == null) {
                return;
                    return null;
                }

                if (!useBlastSync && !reportNextDraw) {
                    return null;
                }

                // If the syncResults are SYNC_LOST_SURFACE_REWARD_IF_FOUND or
                // SYNC_CONTEXT_IS_STOPPED it means nothing will draw. There's no need to set up
                // any blast sync or commit callback, and the code should directly call
                // pendingDrawFinished.
                if ((syncResult
                        & (SYNC_LOST_SURFACE_REWARD_IF_FOUND | SYNC_CONTEXT_IS_STOPPED)) != 0) {
                    if (reportNextDraw) {
                        mHandler.postAtFrontOfQueue(() -> pendingDrawFinished());
                    }
                    return null;
                }

                if (DEBUG_BLAST) {
                    Log.d(mTag, "Setting up sync and frameCommitCallback");
                }

                if (useBlastSync) {
                    // Frame callbacks will always occur after submitting draw requests and before
                    // the draw actually occurs. This will ensure that we set the next transaction
                // for the frame that's about to get drawn and not on a previous frame that.

                // We don't need to synchronize mRtBLASTSyncTransaction here since it's not
                // being modified and only sent to BlastBufferQueue.
                    // for the frame that's about to get drawn and not on a previous frame.
                    mBlastBufferQueue.setSyncTransaction(mRtBLASTSyncTransaction);
                }

                return createFrameCommitCallbackForSync(useBlastSync, reportNextDraw,
                        blastSyncConsumer);
            }
        };
        registerRtFrameCallback(frameDrawingCallback);
    }

    private void performDraw(boolean useBlastSync) {
@@ -4165,15 +4201,20 @@ public final class ViewRootImpl implements ViewParent,
        mIsDrawing = true;
        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "draw");

        addFrameCallbackIfNeeded(useBlastSync);
        FrameDrawingCallback frameDrawingCallback = createFrameDrawingCallbackIfNeeded(useBlastSync,
                mReportNextDraw);
        if (frameDrawingCallback != null) {
            mAttachInfo.mThreadedRenderer.registerRtFrameCallback(frameDrawingCallback);
        }
        addFrameCommitCallbackIfNeeded();
        boolean usingAsyncReport = addFrameCompleteCallbackIfNeeded(useBlastSync, mReportNextDraw);
        boolean usingAsyncReport = isHardwareEnabled() && (useBlastSync || mReportNextDraw);

        try {
            boolean canUseAsync = draw(fullRedrawNeeded);
            if (usingAsyncReport && !canUseAsync) {
                mAttachInfo.mThreadedRenderer.setFrameCompleteCallback(null);
                mAttachInfo.mThreadedRenderer.setFrameCallback(null);
                usingAsyncReport = false;
                mAttachInfo.mThreadedRenderer.unregisterRtFrameCallback(frameDrawingCallback);
            }
        } finally {
            mIsDrawing = false;
+14 −0
Original line number Diff line number Diff line
@@ -902,6 +902,20 @@ public class HardwareRenderer {
         * @param frame The id of the frame being drawn.
         */
        void onFrameDraw(long frame);

        /**
         * Invoked during a frame drawing.
         *
         * @param syncResult The result of the draw. Should be a value or a combination of values
         *                   from {@link SyncAndDrawResult}
         * @param frame The id of the frame being drawn.
         *
         * @return A {@link FrameCommitCallback} that will report back if the current vsync draws.
         */
        default FrameCommitCallback onFrameDraw(@SyncAndDrawResult int syncResult, long frame) {
            onFrameDraw(frame);
            return null;
        }
    }

    /**
+16 −6
Original line number Diff line number Diff line
@@ -609,10 +609,19 @@ static void android_view_ThreadedRenderer_setFrameCallback(JNIEnv* env,
        LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&vm) != JNI_OK, "Unable to get Java VM");
        auto globalCallbackRef = std::make_shared<JGlobalRefHolder>(vm,
                env->NewGlobalRef(frameCallback));
        proxy->setFrameCallback([globalCallbackRef](int64_t frameNr) {
        proxy->setFrameCallback([globalCallbackRef](int32_t syncResult,
                                                    int64_t frameNr) -> std::function<void(bool)> {
            JNIEnv* env = getenv(globalCallbackRef->vm());
            env->CallVoidMethod(globalCallbackRef->object(), gFrameDrawingCallback.onFrameDraw,
                    static_cast<jlong>(frameNr));
            ScopedLocalRef<jobject> frameCommitCallback(
                    env, env->CallObjectMethod(
                                 globalCallbackRef->object(), gFrameDrawingCallback.onFrameDraw,
                                 static_cast<jint>(syncResult), static_cast<jlong>(frameNr)));
            if (frameCommitCallback == nullptr) {
                return nullptr;
            }
            sp<FrameCommitWrapper> wrapper =
                    sp<FrameCommitWrapper>::make(env, frameCommitCallback.get());
            return [wrapper](bool didProduceBuffer) { wrapper->onFrameCommit(didProduceBuffer); };
        });
    }
}
@@ -623,7 +632,7 @@ static void android_view_ThreadedRenderer_setFrameCommitCallback(JNIEnv* env, jo
    if (!callback) {
        proxy->setFrameCommitCallback(nullptr);
    } else {
        sp<FrameCommitWrapper> wrapper = new FrameCommitWrapper{env, callback};
        sp<FrameCommitWrapper> wrapper = sp<FrameCommitWrapper>::make(env, callback);
        proxy->setFrameCommitCallback(
                [wrapper](bool didProduceBuffer) { wrapper->onFrameCommit(didProduceBuffer); });
    }
@@ -1003,8 +1012,9 @@ int register_android_view_ThreadedRenderer(JNIEnv* env) {

    jclass frameCallbackClass = FindClassOrDie(env,
            "android/graphics/HardwareRenderer$FrameDrawingCallback");
    gFrameDrawingCallback.onFrameDraw = GetMethodIDOrDie(env, frameCallbackClass,
            "onFrameDraw", "(J)V");
    gFrameDrawingCallback.onFrameDraw =
            GetMethodIDOrDie(env, frameCallbackClass, "onFrameDraw",
                             "(IJ)Landroid/graphics/HardwareRenderer$FrameCommitCallback;");

    jclass frameCommitClass =
            FindClassOrDie(env, "android/graphics/HardwareRenderer$FrameCommitCallback");
+9 −3
Original line number Diff line number Diff line
@@ -158,7 +158,8 @@ void DrawFrameTask::run() {

    // Grab a copy of everything we need
    CanvasContext* context = mContext;
    std::function<void(int64_t)> frameCallback = std::move(mFrameCallback);
    std::function<std::function<void(bool)>(int32_t, int64_t)> frameCallback =
            std::move(mFrameCallback);
    std::function<void()> frameCompleteCallback = std::move(mFrameCompleteCallback);
    mFrameCallback = nullptr;
    mFrameCompleteCallback = nullptr;
@@ -173,8 +174,13 @@ void DrawFrameTask::run() {

    // Even if we aren't drawing this vsync pulse the next frame number will still be accurate
    if (CC_UNLIKELY(frameCallback)) {
        context->enqueueFrameWork(
                [frameCallback, frameNr = context->getFrameNumber()]() { frameCallback(frameNr); });
        context->enqueueFrameWork([frameCallback, context, syncResult = mSyncResult,
                                   frameNr = context->getFrameNumber()]() {
            auto frameCommitCallback = std::move(frameCallback(syncResult, frameNr));
            if (frameCommitCallback) {
                context->addFrameCommitListener(std::move(frameCommitCallback));
            }
        });
    }

    nsecs_t dequeueBufferDuration = 0;
Loading