From 13bfbb77425d471c731ce882425f8ca995288355 Mon Sep 17 00:00:00 2001 From: John Reck Date: Thu, 10 Feb 2022 18:15:26 -0500 Subject: [PATCH] Add setBuffer w/ SyncFence Test: atest android.view.cts.SurfaceControlTest Bug: 217776226 Change-Id: Ia40947a8cc056d3fcc5569e522524af61c4e5b1b --- core/api/current.txt | 1 + core/java/android/hardware/SyncFence.java | 10 +++++ core/java/android/view/SurfaceControl.java | 43 +++++++++++++++++++++- core/jni/android_view_SurfaceControl.cpp | 10 +++-- 4 files changed, 59 insertions(+), 5 deletions(-) diff --git a/core/api/current.txt b/core/api/current.txt index 34497d1b01595..95d6132bb3db0 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -49254,6 +49254,7 @@ package android.view { method @NonNull public android.view.SurfaceControl.Transaction reparent(@NonNull android.view.SurfaceControl, @Nullable android.view.SurfaceControl); method @NonNull public android.view.SurfaceControl.Transaction setAlpha(@NonNull android.view.SurfaceControl, @FloatRange(from=0.0, to=1.0) float); method @NonNull public android.view.SurfaceControl.Transaction setBuffer(@NonNull android.view.SurfaceControl, @Nullable android.hardware.HardwareBuffer); + method @NonNull public android.view.SurfaceControl.Transaction setBuffer(@NonNull android.view.SurfaceControl, @Nullable android.hardware.HardwareBuffer, @Nullable android.hardware.SyncFence); method @NonNull public android.view.SurfaceControl.Transaction setBufferSize(@NonNull android.view.SurfaceControl, @IntRange(from=0) int, @IntRange(from=0) int); method @NonNull public android.view.SurfaceControl.Transaction setBufferTransform(@NonNull android.view.SurfaceControl, int); method @NonNull public android.view.SurfaceControl.Transaction setCrop(@NonNull android.view.SurfaceControl, @Nullable android.graphics.Rect); diff --git a/core/java/android/hardware/SyncFence.java b/core/java/android/hardware/SyncFence.java index 693cda7720e46..99791ce3d8ec9 100644 --- a/core/java/android/hardware/SyncFence.java +++ b/core/java/android/hardware/SyncFence.java @@ -214,6 +214,16 @@ public final class SyncFence implements AutoCloseable, Parcelable { return CONTENTS_FILE_DESCRIPTOR; } + /** @hide */ + public Object getLock() { + return mCloser; + } + + /** @hide */ + public long getNativeFence() { + return mNativePtr; + } + /** * Flatten this object into a Parcel. * diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index ce54968658858..c08177e2f71ed 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -46,10 +46,13 @@ import android.graphics.Region; import android.gui.DropInputMode; import android.hardware.DataSpace; import android.hardware.HardwareBuffer; +import android.hardware.SyncFence; import android.hardware.display.DeviceProductInfo; import android.hardware.display.DisplayedContentSample; import android.hardware.display.DisplayedContentSamplingAttributes; import android.hardware.graphics.common.DisplayDecorationSupport; +import android.opengl.EGLDisplay; +import android.opengl.EGLSync; import android.os.Build; import android.os.IBinder; import android.os.Parcel; @@ -209,7 +212,7 @@ public final class SurfaceControl implements Parcelable { private static native void nativeReparent(long transactionObj, long nativeObject, long newParentNativeObject); private static native void nativeSetBuffer(long transactionObj, long nativeObject, - HardwareBuffer buffer); + HardwareBuffer buffer, long fencePtr); private static native void nativeSetBufferTransform(long transactionObj, long nativeObject, int transform); private static native void nativeSetDataSpace(long transactionObj, long nativeObject, @@ -3692,8 +3695,44 @@ public final class SurfaceControl implements Parcelable { */ public @NonNull Transaction setBuffer(@NonNull SurfaceControl sc, @Nullable HardwareBuffer buffer) { + return setBuffer(sc, buffer, null); + } + + /** + * Updates the HardwareBuffer displayed for the SurfaceControl. + * + * Note that the buffer must be allocated with {@link HardwareBuffer#USAGE_COMPOSER_OVERLAY} + * as well as {@link HardwareBuffer#USAGE_GPU_SAMPLED_IMAGE} as the surface control might + * be composited using either an overlay or using the GPU. + * + * A presentation fence may be passed to improve performance by allowing the buffer + * to complete rendering while it is waiting for the transaction to be applied. + * For example, if the buffer is being produced by rendering with OpenGL ES then + * a fence created with + * {@link android.opengl.EGLExt#eglDupNativeFenceFDANDROID(EGLDisplay, EGLSync)} can be + * used to allow the GPU rendering to be concurrent with the transaction. The compositor + * will wait for the fence to be signaled before the buffer is displayed. If multiple + * buffers are set as part of the same transaction, the presentation fences of all of them + * must signal before any buffer is displayed. That is, the entire transaction is delayed + * until all presentation fences have signaled, ensuring the transaction remains consistent. + * + * @param sc The SurfaceControl to update + * @param buffer The buffer to be displayed + * @param fence The presentation fence. If null or invalid, this is equivalent to + * {@link #setBuffer(SurfaceControl, HardwareBuffer)} + * @return this + */ + public @NonNull Transaction setBuffer(@NonNull SurfaceControl sc, + @Nullable HardwareBuffer buffer, @Nullable SyncFence fence) { checkPreconditions(sc); - nativeSetBuffer(mNativeObject, sc.mNativeObject, buffer); + if (fence != null) { + synchronized (fence.getLock()) { + nativeSetBuffer(mNativeObject, sc.mNativeObject, buffer, + fence.getNativeFence()); + } + } else { + nativeSetBuffer(mNativeObject, sc.mNativeObject, buffer, 0); + } return this; } diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index 336161c8c37e2..fb5b5ffaac48c 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -625,12 +625,16 @@ static void nativeSetGeometry(JNIEnv* env, jclass clazz, jlong transactionObj, j } static void nativeSetBuffer(JNIEnv* env, jclass clazz, jlong transactionObj, jlong nativeObject, - jobject bufferObject) { + jobject bufferObject, jlong fencePtr) { auto transaction = reinterpret_cast(transactionObj); SurfaceControl* const ctrl = reinterpret_cast(nativeObject); sp graphicBuffer(GraphicBuffer::fromAHardwareBuffer( android_hardware_HardwareBuffer_getNativeHardwareBuffer(env, bufferObject))); - transaction->setBuffer(ctrl, graphicBuffer); + std::optional> optFence = std::nullopt; + if (fencePtr != 0) { + optFence = sp{reinterpret_cast(fencePtr)}; + } + transaction->setBuffer(ctrl, graphicBuffer, optFence); } static void nativeSetBufferTransform(JNIEnv* env, jclass clazz, jlong transactionObj, @@ -2133,7 +2137,7 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (void*)nativeGetDisplayedContentSample }, {"nativeSetGeometry", "(JJLandroid/graphics/Rect;Landroid/graphics/Rect;J)V", (void*)nativeSetGeometry }, - {"nativeSetBuffer", "(JJLandroid/hardware/HardwareBuffer;)V", + {"nativeSetBuffer", "(JJLandroid/hardware/HardwareBuffer;J)V", (void*)nativeSetBuffer }, {"nativeSetBufferTransform", "(JJI)V", (void*) nativeSetBufferTransform}, {"nativeSetDataSpace", "(JJI)V",