Limit HLG to 4.926x SDR
HLG is universally too bright on basically every single platform that
supports HDR. Fix this for Android.
Bug: 362510107
Flag: com.android.graphics.surfaceflinger.flags.begone_bright_hlg
Test: HLG playback
Change-Id: I5d464c016be62b11f6a3cc1ab228e14d198afb15
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
index f6d9a1a..bb01946 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
@@ -26,6 +26,7 @@
#include <ui/FloatRect.h>
#include <ui/HdrRenderTypeUtils.h>
#include <cstdint>
+#include <limits>
#include "system/graphics-base-v1.0.h"
#include <com_android_graphics_libgui_flags.h>
@@ -398,11 +399,22 @@
// For hdr content, treat the white point as the display brightness - HDR content should not be
// boosted or dimmed.
// If the layer explicitly requests to disable dimming, then don't dim either.
- if (hdrRenderType == HdrRenderType::GENERIC_HDR ||
- getOutput().getState().displayBrightnessNits == getOutput().getState().sdrWhitePointNits ||
- getOutput().getState().displayBrightnessNits == 0.f || !layerFEState->dimmingEnabled) {
+ if (getOutput().getState().displayBrightnessNits == getOutput().getState().sdrWhitePointNits ||
+ getOutput().getState().displayBrightnessNits <= 0.f || !layerFEState->dimmingEnabled) {
state.dimmingRatio = 1.f;
state.whitePointNits = getOutput().getState().displayBrightnessNits;
+ } else if (hdrRenderType == HdrRenderType::GENERIC_HDR) {
+ float deviceHeadroom = getOutput().getState().displayBrightnessNits /
+ getOutput().getState().sdrWhitePointNits;
+ float idealizedMaxHeadroom = deviceHeadroom;
+
+ if (FlagManager::getInstance().begone_bright_hlg()) {
+ idealizedMaxHeadroom =
+ std::min(idealizedMaxHeadroom, getIdealizedMaxHeadroom(state.dataspace));
+ }
+
+ state.dimmingRatio = std::min(idealizedMaxHeadroom / deviceHeadroom, 1.0f);
+ state.whitePointNits = getOutput().getState().displayBrightnessNits * state.dimmingRatio;
} else {
float layerBrightnessNits = getOutput().getState().sdrWhitePointNits;
// RANGE_EXTENDED can "self-promote" to HDR, but is still rendered for a particular
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 37b35f2..6499001 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3201,7 +3201,15 @@
snapshot.desiredHdrSdrRatio < 1.f
? std::numeric_limits<float>::infinity()
: snapshot.desiredHdrSdrRatio;
- info.mergeDesiredRatio(desiredHdrSdrRatio);
+
+ float desiredRatio = desiredHdrSdrRatio;
+ if (FlagManager::getInstance().begone_bright_hlg() &&
+ desiredHdrSdrRatio ==
+ std::numeric_limits<float>::infinity()) {
+ desiredRatio = getIdealizedMaxHeadroom(snapshot.dataspace);
+ }
+
+ info.mergeDesiredRatio(desiredRatio);
info.numberOfHdrLayers++;
const auto displayFrame = outputLayer->getState().displayFrame;
const int32_t area =
diff --git a/services/surfaceflinger/common/FlagManager.cpp b/services/surfaceflinger/common/FlagManager.cpp
index b56ee01..a1b53ee 100644
--- a/services/surfaceflinger/common/FlagManager.cpp
+++ b/services/surfaceflinger/common/FlagManager.cpp
@@ -160,6 +160,7 @@
DUMP_READ_ONLY_FLAG(connected_display_hdr);
DUMP_READ_ONLY_FLAG(deprecate_frame_tracker);
DUMP_READ_ONLY_FLAG(skip_invisible_windows_in_input);
+ DUMP_READ_ONLY_FLAG(begone_bright_hlg);
#undef DUMP_READ_ONLY_FLAG
#undef DUMP_SERVER_FLAG
@@ -268,6 +269,7 @@
FLAG_MANAGER_READ_ONLY_FLAG(connected_display_hdr, "");
FLAG_MANAGER_READ_ONLY_FLAG(deprecate_frame_tracker, "");
FLAG_MANAGER_READ_ONLY_FLAG(skip_invisible_windows_in_input, "");
+FLAG_MANAGER_READ_ONLY_FLAG(begone_bright_hlg, "debug.sf.begone_bright_hlg");
/// Trunk stable server flags ///
FLAG_MANAGER_SERVER_FLAG(refresh_rate_overlay_on_external_display, "")
diff --git a/services/surfaceflinger/common/include/common/FlagManager.h b/services/surfaceflinger/common/include/common/FlagManager.h
index 9086537..c1d88ce 100644
--- a/services/surfaceflinger/common/include/common/FlagManager.h
+++ b/services/surfaceflinger/common/include/common/FlagManager.h
@@ -98,6 +98,7 @@
bool connected_display_hdr() const;
bool deprecate_frame_tracker() const;
bool skip_invisible_windows_in_input() const;
+ bool begone_bright_hlg() const;
protected:
// overridden for unit tests
diff --git a/services/surfaceflinger/surfaceflinger_flags_new.aconfig b/services/surfaceflinger/surfaceflinger_flags_new.aconfig
index d4250bc..1188435 100644
--- a/services/surfaceflinger/surfaceflinger_flags_new.aconfig
+++ b/services/surfaceflinger/surfaceflinger_flags_new.aconfig
@@ -35,6 +35,14 @@
} # arr_surfacecontrol_setframerate_api
flag {
+ name: "begone_bright_hlg"
+ namespace: "core_graphics"
+ description: "Caps HLG brightness relative to SDR"
+ bug: "362510107"
+ is_fixed_read_only: true
+} # begone_bright_hlg
+
+flag {
name: "ce_fence_promise"
namespace: "window_surfaces"
description: "Moves logic for buffer release fences into LayerFE"