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

Commit e12e5189 authored by chaviw's avatar chaviw
Browse files

Add gatherPendingTransactions in BBQ

Instead of applying the pending transactions when a frame wasn't
rendered, we gather the transactions and merge them with the transaction
that will be used to sync. This is to ensure these frames are sent to
the caller that requested the sync so they can ensure it's applied at
the correct time.

Test: Builds and run
Bug: 200284684
Change-Id: I087c67138f31cc93e79df42c29464ab4f7989d52
parent 083297ec
Loading
Loading
Loading
Loading
+7 −3
Original line number Diff line number Diff line
@@ -2730,9 +2730,13 @@ public final class SurfaceControl implements Parcelable {
         * is allowed as a convenience.
         */
        public Transaction() {
            mNativeObject = nativeCreateTransaction();
            mFreeNativeResources
                = sRegistry.registerNativeAllocation(this, mNativeObject);
            this(nativeCreateTransaction());
        }

        private Transaction(long nativeObject) {
            mNativeObject = nativeObject;
            mFreeNativeResources =
                    sRegistry.registerNativeAllocation(this, mNativeObject);
        }

        private Transaction(Parcel in) {
+7 −4
Original line number Diff line number Diff line
@@ -4159,19 +4159,22 @@ public final class ViewRootImpl implements ViewParent,
                        + " didProduceBuffer=" + didProduceBuffer);
            }

            Transaction tmpTransaction = new Transaction();
            tmpTransaction.merge(mRtBLASTSyncTransaction);

            // 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 (!didProduceBuffer) {
                mBlastBufferQueue.setSyncTransaction(null);
                // Apply the transactions that were sent to mergeWithNextTransaction since the
                // Get 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
                // it's better to not be sync than to block on a frame that may never come.
                mBlastBufferQueue.applyPendingTransactions(mRtLastAttemptedDrawFrameNum);
                Transaction pendingTransactions = mBlastBufferQueue.gatherPendingTransactions(
                        mRtLastAttemptedDrawFrameNum);
                tmpTransaction.merge(pendingTransactions);
            }

            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
+19 −0
Original line number Diff line number Diff line
@@ -30,6 +30,11 @@

namespace android {

static struct {
    jclass clazz;
    jmethodID ctor;
} gTransactionClassInfo;

static jlong nativeCreate(JNIEnv* env, jclass clazz, jstring jName) {
    ScopedUtfChars name(env, jName);
    sp<BLASTBufferQueue> queue = new BLASTBufferQueue(name.c_str());
@@ -86,6 +91,14 @@ static bool nativeIsSameSurfaceControl(JNIEnv* env, jclass clazz, jlong ptr, jlo
    return queue->isSameSurfaceControl(reinterpret_cast<SurfaceControl*>(surfaceControl));
}

static jobject nativeGatherPendingTransactions(JNIEnv* env, jclass clazz, jlong ptr,
                                               jlong frameNum) {
    sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr);
    SurfaceComposerClient::Transaction* transaction = queue->gatherPendingTransactions(frameNum);
    return env->NewObject(gTransactionClassInfo.clazz, gTransactionClassInfo.ctor,
                          reinterpret_cast<jlong>(transaction));
}

static const JNINativeMethod gMethods[] = {
        /* name, signature, funcPtr */
        // clang-format off
@@ -98,6 +111,7 @@ static const JNINativeMethod gMethods[] = {
        {"nativeGetLastAcquiredFrameNum", "(J)J", (void*)nativeGetLastAcquiredFrameNum},
        {"nativeApplyPendingTransactions", "(JJ)V", (void*)nativeApplyPendingTransactions},
        {"nativeIsSameSurfaceControl", "(JJ)Z", (void*)nativeIsSameSurfaceControl},
        {"nativeGatherPendingTransactions", "(JJ)Landroid/view/SurfaceControl$Transaction;", (void*)nativeGatherPendingTransactions}
        // clang-format on
};

@@ -105,6 +119,11 @@ int register_android_graphics_BLASTBufferQueue(JNIEnv* env) {
    int res = jniRegisterNativeMethods(env, "android/graphics/BLASTBufferQueue",
            gMethods, NELEM(gMethods));
    LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods.");

    jclass transactionClazz = FindClassOrDie(env, "android/view/SurfaceControl$Transaction");
    gTransactionClassInfo.clazz = MakeGlobalRefOrDie(env, transactionClazz);
    gTransactionClassInfo.ctor =
            GetMethodIDOrDie(env, gTransactionClassInfo.clazz, "<init>", "(J)V");
    return 0;
}

+15 −0
Original line number Diff line number Diff line
@@ -39,6 +39,8 @@ public final class BLASTBufferQueue {
    private static native long nativeGetLastAcquiredFrameNum(long ptr);
    private static native void nativeApplyPendingTransactions(long ptr, long frameNumber);
    private static native boolean nativeIsSameSurfaceControl(long ptr, long surfaceControlPtr);
    private static native SurfaceControl.Transaction nativeGatherPendingTransactions(long ptr,
            long frameNumber);

    /** Create a new connection with the surface flinger. */
    public BLASTBufferQueue(String name, SurfaceControl sc, int width, int height,
@@ -159,4 +161,17 @@ public final class BLASTBufferQueue {
    public boolean isSameSurfaceControl(SurfaceControl sc) {
        return nativeIsSameSurfaceControl(mNativeObject, sc.mNativeObject);
    }

    /**
     * Get any transactions that were passed to {@link #mergeWithNextTransaction} with the
     * specified frameNumber. This is intended to ensure transactions don't get stuck as pending
     * if the specified frameNumber is never drawn.
     *
     * @param frameNumber The frameNumber used to determine which transactions to apply.
     * @return a Transaction that contains the merge of all the transactions that were sent to
     *         mergeWithNextTransaction
     */
    public SurfaceControl.Transaction gatherPendingTransactions(long frameNumber) {
        return nativeGatherPendingTransactions(mNativeObject, frameNumber);
    }
}