summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Alec Mouri <alecmouri@google.com> 2024-02-16 03:35:35 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2024-02-16 03:35:35 +0000
commiteace4c0fe4b0d43c63788f04f8d8dba350ab9af4 (patch)
tree23bcc438d260176812054f82bd6c008bf4d6ac8b
parent9701174caf3bce36c6626212f3a8eb81c3bd4059 (diff)
parentf5b4b66ae1f8426a328a5e20a3aa288e3b4e42b8 (diff)
Merge "Allow for restricting HDR headroom for SurfaceControl and SurfaceView" into main
-rw-r--r--core/api/current.txt2
-rw-r--r--core/java/android/view/SurfaceControl.java46
-rw-r--r--core/java/android/view/SurfaceView.java53
-rw-r--r--core/jni/android_view_SurfaceControl.cpp11
-rw-r--r--native/android/libandroid.map.txt1
-rw-r--r--native/android/surface_control.cpp18
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,