diff options
| author | 2024-02-16 03:35:35 +0000 | |
|---|---|---|
| committer | 2024-02-16 03:35:35 +0000 | |
| commit | eace4c0fe4b0d43c63788f04f8d8dba350ab9af4 (patch) | |
| tree | 23bcc438d260176812054f82bd6c008bf4d6ac8b | |
| parent | 9701174caf3bce36c6626212f3a8eb81c3bd4059 (diff) | |
| parent | f5b4b66ae1f8426a328a5e20a3aa288e3b4e42b8 (diff) | |
Merge "Allow for restricting HDR headroom for SurfaceControl and SurfaceView" into main
| -rw-r--r-- | core/api/current.txt | 2 | ||||
| -rw-r--r-- | core/java/android/view/SurfaceControl.java | 46 | ||||
| -rw-r--r-- | core/java/android/view/SurfaceView.java | 53 | ||||
| -rw-r--r-- | core/jni/android_view_SurfaceControl.cpp | 11 | ||||
| -rw-r--r-- | native/android/libandroid.map.txt | 1 | ||||
| -rw-r--r-- | native/android/surface_control.cpp | 18 |
6 files changed, 129 insertions, 2 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index 22420faa5604..e8a342d0c411 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -52258,6 +52258,7 @@ package android.view { method @NonNull public android.view.SurfaceControl.Transaction setCrop(@NonNull android.view.SurfaceControl, @Nullable android.graphics.Rect); method @NonNull public android.view.SurfaceControl.Transaction setDamageRegion(@NonNull android.view.SurfaceControl, @Nullable android.graphics.Region); method @NonNull public android.view.SurfaceControl.Transaction setDataSpace(@NonNull android.view.SurfaceControl, int); + method @FlaggedApi("com.android.graphics.hwui.flags.limited_hdr") @NonNull public android.view.SurfaceControl.Transaction setDesiredHdrHeadroom(@NonNull android.view.SurfaceControl, @FloatRange(from=0.0f) float); method @FlaggedApi("com.android.window.flags.sdk_desired_present_time") @NonNull public android.view.SurfaceControl.Transaction setDesiredPresentTimeNanos(long); method @NonNull public android.view.SurfaceControl.Transaction setExtendedRangeBrightness(@NonNull android.view.SurfaceControl, float, float); method @NonNull public android.view.SurfaceControl.Transaction setFrameRate(@NonNull android.view.SurfaceControl, @FloatRange(from=0.0) float, int); @@ -52361,6 +52362,7 @@ package android.view { method @Nullable public android.os.IBinder getHostToken(); method public android.view.SurfaceControl getSurfaceControl(); method public void setChildSurfacePackage(@NonNull android.view.SurfaceControlViewHost.SurfacePackage); + method @FlaggedApi("com.android.graphics.hwui.flags.limited_hdr") public void setDesiredHdrHeadroom(@FloatRange(from=0.0f, to=10000.0) float); method public void setSecure(boolean); method public void setSurfaceLifecycle(int); method public void setZOrderMediaOverlay(boolean); diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index 3c0ac06ae13f..eff35c0c0f03 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -224,6 +224,8 @@ public final class SurfaceControl implements Parcelable { @DataSpace.NamedDataSpace int dataSpace); private static native void nativeSetExtendedRangeBrightness(long transactionObj, long nativeObject, float currentBufferRatio, float desiredRatio); + private static native void nativeSetDesiredHdrHeadroom(long transactionObj, + long nativeObject, float desiredRatio); private static native void nativeSetCachingHint(long transactionObj, long nativeObject, int cachingHint); @@ -4148,6 +4150,50 @@ public final class SurfaceControl implements Parcelable { } /** + * Sets the desired hdr headroom for the layer. + * + * <p>Prefer using this API over {@link #setExtendedRangeBrightness} for formats that + *. conform to HDR video standards like HLG or HDR10 which do not communicate a HDR/SDR + * ratio as part of generating the buffer. + * + * @param sc The layer whose desired hdr headroom is being specified + * + * @param desiredRatio The desired hdr/sdr ratio. This can be used to communicate the max + * desired brightness range. This is similar to the "max luminance" + * value in other HDR metadata formats, but represented as a ratio of + * the target SDR whitepoint to the max display brightness. The system + * may not be able to, or may choose not to, deliver the + * requested range. + * + * <p>Default value is 0.0f and indicates that the system will choose + * the best headroom for this surface control's content. Typically, + * this means that HLG/PQ encoded content will be displayed with some + * HDR headroom greater than 1.0. + * + * <p>When called after {@link #setExtendedRangeBrightness}, the + * desiredHeadroom will override the desiredRatio provided by + * {@link #setExtendedRangeBrightness}. Conversely, when called + * before {@link #setExtendedRangeBrightness}, the desiredRatio provided + * by {@link #setExtendedRangeBrightness} will override the + * desiredHeadroom. + * + * <p>Must be finite && >= 1.0f or 0.0f. + * @return this + * @see #setExtendedRangeBrightness + **/ + @FlaggedApi(com.android.graphics.hwui.flags.Flags.FLAG_LIMITED_HDR) + public @NonNull Transaction setDesiredHdrHeadroom(@NonNull SurfaceControl sc, + @FloatRange(from = 0.0f) float desiredRatio) { + checkPreconditions(sc); + if (!Float.isFinite(desiredRatio) || (desiredRatio != 0 && desiredRatio < 1.0f)) { + throw new IllegalArgumentException( + "desiredRatio must be finite && >= 1.0f or 0; got " + desiredRatio); + } + nativeSetDesiredHdrHeadroom(mNativeObject, sc.mNativeObject, desiredRatio); + return this; + } + + /** * Sets the caching hint for the layer. By default, the caching hint is * {@link CACHING_ENABLED}. * diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 9caf7a61bfbc..d494e2811747 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -21,6 +21,8 @@ import static android.view.WindowManagerPolicyConstants.APPLICATION_MEDIA_OVERLA import static android.view.WindowManagerPolicyConstants.APPLICATION_MEDIA_SUBLAYER; import static android.view.WindowManagerPolicyConstants.APPLICATION_PANEL_SUBLAYER; +import android.annotation.FlaggedApi; +import android.annotation.FloatRange; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -187,6 +189,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall final Rect mScreenRect = new Rect(); private final SurfaceSession mSurfaceSession = new SurfaceSession(); + private final boolean mLimitedHdrEnabled = Flags.limitedHdr(); SurfaceControl mSurfaceControl; SurfaceControl mBackgroundControl; @@ -197,6 +200,9 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall @SurfaceLifecycleStrategy private int mSurfaceLifecycleStrategy = SURFACE_LIFECYCLE_DEFAULT; + private float mRequestedHdrHeadroom = 0.f; + private float mHdrHeadroom = 0.f; + /** * We use this lock to protect access to mSurfaceControl. Both are accessed on the UI * thread and the render thread via RenderNode.PositionUpdateListener#positionLost. @@ -821,6 +827,45 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall updateSurface(); } + + /** + * Sets the desired amount of HDR headroom to be used when HDR content is presented on this + * SurfaceView. + * + * <p>By default the system will choose an amount of HDR headroom that is appropriate + * for the underlying device capabilities & bit-depth of the panel. However, for some types + * of content this can end up being more headroom than necessary or desired. An example + * would be a messaging app or gallery thumbnail view where some amount of HDR pop is desired + * without overly influencing the perceived brightness of the majority SDR content. This can + * also be used to animate in/out of an HDR range for smoother transitions.</p> + * + * <p>Note: The actual amount of HDR headroom that will be given is subject to a variety + * of factors such as ambient conditions, display capabilities, or bit-depth limitations. + * See {@link Display#getHdrSdrRatio()} for more information as well as how to query the + * current value.</p> + * + * @param desiredHeadroom The amount of HDR headroom that is desired. Must be >= 1.0 (no HDR) + * and <= 10,000.0. Passing 0.0 will reset to the default, automatically + * chosen value. + * @see Display#getHdrSdrRatio() + */ + @FlaggedApi(com.android.graphics.hwui.flags.Flags.FLAG_LIMITED_HDR) + public void setDesiredHdrHeadroom( + @FloatRange(from = 0.0f, to = 10000.0) float desiredHeadroom) { + if (!Float.isFinite(desiredHeadroom)) { + throw new IllegalArgumentException("desiredHeadroom must be finite: " + + desiredHeadroom); + } + if (desiredHeadroom != 0 && (desiredHeadroom < 1.0f || desiredHeadroom > 10000.0f)) { + throw new IllegalArgumentException( + "desiredHeadroom must be 0.0 or in the range [1.0, 10000.0f], received: " + + desiredHeadroom); + } + mRequestedHdrHeadroom = desiredHeadroom; + updateSurface(); + invalidate(); + } + private void updateOpaqueFlag() { if (!PixelFormat.formatHasAlpha(mRequestedFormat)) { mSurfaceFlags |= SurfaceControl.OPAQUE; @@ -941,6 +986,10 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall updateBackgroundVisibility(surfaceUpdateTransaction); updateBackgroundColor(surfaceUpdateTransaction); + if (mLimitedHdrEnabled) { + surfaceUpdateTransaction.setDesiredHdrHeadroom( + mBlastSurfaceControl, mHdrHeadroom); + } if (isAboveParent()) { float alpha = getAlpha(); surfaceUpdateTransaction.setAlpha(mSurfaceControl, alpha); @@ -1085,11 +1134,12 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall final boolean relativeZChanged = mSubLayer != mRequestedSubLayer; final boolean surfaceLifecycleStrategyChanged = mSurfaceLifecycleStrategy != mRequestedSurfaceLifecycleStrategy; + final boolean hdrHeadroomChanged = mHdrHeadroom != mRequestedHdrHeadroom; if (creating || formatChanged || sizeChanged || visibleChanged || alphaChanged || windowVisibleChanged || positionChanged || layoutSizeChanged || hintChanged || relativeZChanged || !mAttachedToWindow - || surfaceLifecycleStrategyChanged) { + || surfaceLifecycleStrategyChanged || hdrHeadroomChanged) { if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + "Changes: creating=" + creating @@ -1117,6 +1167,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall final int previousSurfaceLifecycleStrategy = mSurfaceLifecycleStrategy; mSurfaceLifecycleStrategy = mRequestedSurfaceLifecycleStrategy; + mHdrHeadroom = mRequestedHdrHeadroom; mScreenRect.left = mWindowSpaceLeft; mScreenRect.top = mWindowSpaceTop; diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index 98f409a334dc..6fec527aaa16 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -716,6 +716,13 @@ static void nativeSetExtendedRangeBrightness(JNIEnv* env, jclass clazz, jlong tr transaction->setExtendedRangeBrightness(ctrl, currentBufferRatio, desiredRatio); } +static void nativeSetDesiredHdrHeadroom(JNIEnv* env, jclass clazz, jlong transactionObj, + jlong nativeObject, float desiredRatio) { + auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj); + SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl*>(nativeObject); + transaction->setDesiredHdrHeadroom(ctrl, desiredRatio); +} + static void nativeSetCachingHint(JNIEnv* env, jclass clazz, jlong transactionObj, jlong nativeObject, jint cachingHint) { auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj); @@ -2340,7 +2347,9 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (void*)nativeSetDataSpace }, {"nativeSetExtendedRangeBrightness", "(JJFF)V", (void*)nativeSetExtendedRangeBrightness }, - {"nativeSetCachingHint", "(JJI)V", + {"nativeSetDesiredHdrHeadroom", "(JJF)V", + (void*)nativeSetDesiredHdrHeadroom }, + {"nativeSetCachingHint", "(JJI)V", (void*)nativeSetCachingHint }, {"nativeAddWindowInfosReportedListener", "(JLjava/lang/Runnable;)V", (void*)nativeAddWindowInfosReportedListener }, diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt index 3302265fb80c..35e37b2a6893 100644 --- a/native/android/libandroid.map.txt +++ b/native/android/libandroid.map.txt @@ -277,6 +277,7 @@ LIBANDROID { ASurfaceTransaction_setHdrMetadata_cta861_3; # introduced=29 ASurfaceTransaction_setHdrMetadata_smpte2086; # introduced=29 ASurfaceTransaction_setExtendedRangeBrightness; # introduced=UpsideDownCake + ASurfaceTransaction_setDesiredHdrHeadroom; # introduced=VanillaIceCream ASurfaceTransaction_setOnComplete; # introduced=29 ASurfaceTransaction_setOnCommit; # introduced=31 ASurfaceTransaction_setPosition; # introduced=31 diff --git a/native/android/surface_control.cpp b/native/android/surface_control.cpp index 4b63fbf14d4c..9b1330fc048a 100644 --- a/native/android/surface_control.cpp +++ b/native/android/surface_control.cpp @@ -646,6 +646,24 @@ void ASurfaceTransaction_setExtendedRangeBrightness(ASurfaceTransaction* aSurfac transaction->setExtendedRangeBrightness(surfaceControl, currentBufferRatio, desiredRatio); } +void ASurfaceTransaction_setDesiredHdrHeadroom(ASurfaceTransaction* aSurfaceTransaction, + ASurfaceControl* aSurfaceControl, + float desiredRatio) { + CHECK_NOT_NULL(aSurfaceTransaction); + CHECK_NOT_NULL(aSurfaceControl); + + if (!isfinite(desiredRatio) || (desiredRatio < 1.0f && desiredRatio > 0.0f)) { + LOG_ALWAYS_FATAL("setDesiredHdrHeadroom, desiredRatio isn't finite && >= 1.0f or 0, got %f", + desiredRatio); + return; + } + + sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); + Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); + + transaction->setDesiredHdrHeadroom(surfaceControl, desiredRatio); +} + void ASurfaceTransaction_setColor(ASurfaceTransaction* aSurfaceTransaction, ASurfaceControl* aSurfaceControl, float r, float g, float b, float alpha, |