1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.graphics;
18 
19 import android.annotation.NonNull;
20 import android.view.Surface;
21 import android.view.SurfaceControl;
22 
23 import java.util.function.Consumer;
24 
25 /**
26  * @hide
27  */
28 public final class BLASTBufferQueue {
29     // Note: This field is accessed by native code.
30     public long mNativeObject; // BLASTBufferQueue*
31 
nativeCreate(String name, boolean updateDestinationFrame)32     private static native long nativeCreate(String name, boolean updateDestinationFrame);
nativeDestroy(long ptr)33     private static native void nativeDestroy(long ptr);
nativeGetSurface(long ptr, boolean includeSurfaceControlHandle)34     private static native Surface nativeGetSurface(long ptr, boolean includeSurfaceControlHandle);
nativeSyncNextTransaction(long ptr, Consumer<SurfaceControl.Transaction> callback, boolean acquireSingleBuffer)35     private static native boolean nativeSyncNextTransaction(long ptr,
36             Consumer<SurfaceControl.Transaction> callback, boolean acquireSingleBuffer);
nativeStopContinuousSyncTransaction(long ptr)37     private static native void nativeStopContinuousSyncTransaction(long ptr);
nativeClearSyncTransaction(long ptr)38     private static native void nativeClearSyncTransaction(long ptr);
nativeUpdate(long ptr, long surfaceControl, long width, long height, int format)39     private static native void nativeUpdate(long ptr, long surfaceControl, long width, long height,
40             int format);
nativeMergeWithNextTransaction(long ptr, long transactionPtr, long frameNumber)41     private static native void nativeMergeWithNextTransaction(long ptr, long transactionPtr,
42                                                               long frameNumber);
nativeGetLastAcquiredFrameNum(long ptr)43     private static native long nativeGetLastAcquiredFrameNum(long ptr);
nativeApplyPendingTransactions(long ptr, long frameNumber)44     private static native void nativeApplyPendingTransactions(long ptr, long frameNumber);
nativeIsSameSurfaceControl(long ptr, long surfaceControlPtr)45     private static native boolean nativeIsSameSurfaceControl(long ptr, long surfaceControlPtr);
nativeGatherPendingTransactions(long ptr, long frameNumber)46     private static native SurfaceControl.Transaction nativeGatherPendingTransactions(long ptr,
47             long frameNumber);
nativeSetTransactionHangCallback(long ptr, TransactionHangCallback callback)48     private static native void nativeSetTransactionHangCallback(long ptr,
49             TransactionHangCallback callback);
50 
51     public interface TransactionHangCallback {
onTransactionHang(String reason)52         void onTransactionHang(String reason);
53     }
54 
55     /** Create a new connection with the surface flinger. */
BLASTBufferQueue(String name, SurfaceControl sc, int width, int height, @PixelFormat.Format int format)56     public BLASTBufferQueue(String name, SurfaceControl sc, int width, int height,
57             @PixelFormat.Format int format) {
58         this(name, true /* updateDestinationFrame */);
59         update(sc, width, height, format);
60     }
61 
BLASTBufferQueue(String name, boolean updateDestinationFrame)62     public BLASTBufferQueue(String name, boolean updateDestinationFrame) {
63         mNativeObject = nativeCreate(name, updateDestinationFrame);
64     }
65 
destroy()66     public void destroy() {
67         nativeDestroy(mNativeObject);
68         mNativeObject = 0;
69     }
70 
71     /**
72      * @return a new Surface instance from the IGraphicsBufferProducer of the adapter.
73      */
createSurface()74     public Surface createSurface() {
75         return nativeGetSurface(mNativeObject, false /* includeSurfaceControlHandle */);
76     }
77 
78     /**
79      * @return a new Surface instance from the IGraphicsBufferProducer of the adapter and
80      * the SurfaceControl handle.
81      */
createSurfaceWithHandle()82     public Surface createSurfaceWithHandle() {
83         return nativeGetSurface(mNativeObject, true /* includeSurfaceControlHandle */);
84     }
85 
86     /**
87      * Send a callback that accepts a transaction to BBQ. BBQ will acquire buffers into the a
88      * transaction it created and will eventually send the transaction into the callback
89      * when it is ready.
90      * @param callback The callback invoked when the buffer has been added to the transaction. The
91      *                 callback will contain the transaction with the buffer.
92      * @param acquireSingleBuffer If true, only acquire a single buffer when processing frames. The
93      *                            callback will be cleared once a single buffer has been
94      *                            acquired. If false, continue to acquire all buffers into the
95      *                            transaction until stopContinuousSyncTransaction is called.
96      */
syncNextTransaction(boolean acquireSingleBuffer, @NonNull Consumer<SurfaceControl.Transaction> callback)97     public boolean syncNextTransaction(boolean acquireSingleBuffer,
98             @NonNull Consumer<SurfaceControl.Transaction> callback) {
99         return nativeSyncNextTransaction(mNativeObject, callback, acquireSingleBuffer);
100     }
101 
102     /**
103      * Send a callback that accepts a transaction to BBQ. BBQ will acquire buffers into the a
104      * transaction it created and will eventually send the transaction into the callback
105      * when it is ready.
106      * @param callback The callback invoked when the buffer has been added to the transaction. The
107      *                 callback will contain the transaction with the buffer.
108      */
syncNextTransaction(@onNull Consumer<SurfaceControl.Transaction> callback)109     public boolean syncNextTransaction(@NonNull Consumer<SurfaceControl.Transaction> callback) {
110         return syncNextTransaction(true /* acquireSingleBuffer */, callback);
111     }
112 
113     /**
114      * Tell BBQ to stop acquiring buffers into a single transaction. BBQ will send the sync
115      * transaction callback after this has been called. This should only be used when
116      * syncNextTransaction was called with acquireSingleBuffer set to false.
117      */
stopContinuousSyncTransaction()118     public void stopContinuousSyncTransaction() {
119         nativeStopContinuousSyncTransaction(mNativeObject);
120     }
121 
122     /**
123      * Tell BBQ to clear the sync transaction that was previously set. The callback will not be
124      * invoked when the next frame is acquired.
125      */
clearSyncTransaction()126     public void clearSyncTransaction() {
127         nativeClearSyncTransaction(mNativeObject);
128     }
129 
130     /**
131      * Updates {@link SurfaceControl}, size, and format for a particular BLASTBufferQueue
132      * @param sc The new SurfaceControl that this BLASTBufferQueue will update
133      * @param width The new width for the buffer.
134      * @param height The new height for the buffer.
135      * @param format The new format for the buffer.
136      */
update(SurfaceControl sc, int width, int height, @PixelFormat.Format int format)137     public void update(SurfaceControl sc, int width, int height, @PixelFormat.Format int format) {
138         nativeUpdate(mNativeObject, sc.mNativeObject, width, height, format);
139     }
140 
141     @Override
finalize()142     protected void finalize() throws Throwable {
143         try {
144             if (mNativeObject != 0) {
145                 nativeDestroy(mNativeObject);
146             }
147         } finally {
148             super.finalize();
149         }
150     }
151 
152     /**
153      * Merge the transaction passed in to the next transaction in BlastBufferQueue. The next
154      * transaction will be applied or merged when the next frame with specified frame number
155      * is available.
156      */
mergeWithNextTransaction(SurfaceControl.Transaction t, long frameNumber)157     public void mergeWithNextTransaction(SurfaceControl.Transaction t, long frameNumber) {
158         nativeMergeWithNextTransaction(mNativeObject, t.mNativeObject, frameNumber);
159     }
160 
161     /**
162      * Merge the transaction passed in to the next transaction in BlastBufferQueue.
163      * @param nativeTransaction native handle passed from native c/c++ code.
164      */
mergeWithNextTransaction(long nativeTransaction, long frameNumber)165     public void mergeWithNextTransaction(long nativeTransaction, long frameNumber) {
166         nativeMergeWithNextTransaction(mNativeObject, nativeTransaction, frameNumber);
167     }
168 
169     /**
170      * Apply any transactions that were passed to {@link #mergeWithNextTransaction} with the
171      * specified frameNumber. This is intended to ensure transactions don't get stuck as pending
172      * if the specified frameNumber is never drawn.
173      *
174      * @param frameNumber The frameNumber used to determine which transactions to apply.
175      */
applyPendingTransactions(long frameNumber)176     public void applyPendingTransactions(long frameNumber) {
177         nativeApplyPendingTransactions(mNativeObject, frameNumber);
178     }
179 
getLastAcquiredFrameNum()180     public long getLastAcquiredFrameNum() {
181         return nativeGetLastAcquiredFrameNum(mNativeObject);
182     }
183 
184     /**
185      * @return True if the associated SurfaceControl has the same handle as {@param sc}.
186      */
isSameSurfaceControl(SurfaceControl sc)187     public boolean isSameSurfaceControl(SurfaceControl sc) {
188         return nativeIsSameSurfaceControl(mNativeObject, sc.mNativeObject);
189     }
190 
191     /**
192      * Get any transactions that were passed to {@link #mergeWithNextTransaction} with the
193      * specified frameNumber. This is intended to ensure transactions don't get stuck as pending
194      * if the specified frameNumber is never drawn.
195      *
196      * @param frameNumber The frameNumber used to determine which transactions to apply.
197      * @return a Transaction that contains the merge of all the transactions that were sent to
198      *         mergeWithNextTransaction
199      */
gatherPendingTransactions(long frameNumber)200     public SurfaceControl.Transaction gatherPendingTransactions(long frameNumber) {
201         return nativeGatherPendingTransactions(mNativeObject, frameNumber);
202     }
203 
setTransactionHangCallback(TransactionHangCallback hangCallback)204     public void setTransactionHangCallback(TransactionHangCallback hangCallback) {
205         nativeSetTransactionHangCallback(mNativeObject, hangCallback);
206     }
207 }
208