Skip to content

Commit e47541d

Browse files
committed
Optimizes composition strategies for single HDR video layers
Backend::ValidateDisplay Check for a single HDR video layer via IsHDRLayer(). If unique, attempt device composition and validate with a test commit. On success, keep as device; else, fallback to client. For multiple layers including HDR, force HDR to client. HwcDisplay::CreateComposition If single HDR device layer, disable HDR pipeline (identity CTM, no LUTs) for direct scanout. For client or mixed cases, enable full pipeline. Metadata and Capabilities: Use EDID to fetch HDR types/luminance, with fallbacks for edge cases. Sets SDR-like luminance (100 nits) if no HDR support; for specific LG TV models ("LG TV SSCR"), overrides low/invalid max luminance with typical HDR values (1000 nits) to handle EDID bugs. Support HDR10 fully; HLG partially (no LUTs). Tracked-On: OAM-134123 Change-Id: Ice8ed4c5f7bc433add6de7a645a84686b34319bf Signed-off-by: Kanli Hu <kanli.hu@intel.com>
1 parent 92cdd07 commit e47541d

File tree

10 files changed

+169
-58
lines changed

10 files changed

+169
-58
lines changed

backend/Backend.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,8 @@ bool Backend::IsClientLayer(HwcDisplay *display, HwcLayer *layer) {
131131
!layer->IsLayerUsableAsDevice() || display->CtmByGpu() ||
132132
(layer->GetLayerData().pi.RequireScalingOrPhasing() &&
133133
display->GetHwc()->GetResMan().ForcedScalingWithGpu()) ||
134-
(!display->IsInHeadlessMode() && display->GetPipe().device->IsIvshmDev());
134+
(!display->IsInHeadlessMode() && display->GetPipe().device->IsIvshmDev()) ||
135+
(!display->isSingleDeviceHdrLayer().first && layer->IsHDRLayer()); // only single hdrlayer will use device
135136
}
136137

137138
bool Backend::IsVideoLayer(HwcLayer *layer) {

drm/DrmDevice.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
namespace android {
3131

3232
#define DRM_FORMAT_NV12_INTEL fourcc_code('9', '9', '9', '6')
33+
#define DRM_FORMAT_P010_INTEL fourcc_code('P', '0', '0', '9')
3334
class DrmFbImporter;
3435
class DrmPlane;
3536
class ResourceManager;

drm/DrmFbImporter.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,10 @@ auto DrmFbIdHandle::CreateInstance(BufferInfo *bo, GemHandle first_gem_handle,
117117
local->gem_handles_.data(), &bo->pitches[0],
118118
&bo->offsets[0], &local->fb_id_, 0);
119119
} else {
120-
if (bo->format == DRM_FORMAT_NV12_INTEL)
120+
if (bo->format == DRM_FORMAT_NV12_INTEL)
121121
bo->format = DRM_FORMAT_NV12;
122+
if (bo->format == DRM_FORMAT_P010_INTEL)
123+
bo->format = DRM_FORMAT_P010;
122124
err = drmModeAddFB2WithModifiers(*drm.GetFd(), bo->width, bo->height,
123125
bo->format, local->gem_handles_.data(),
124126
&bo->pitches[0], &bo->offsets[0],

drm/HdrPipeline.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ std::vector<drm_color_lut> HdrPipeline::BuildSrgbDegamma(uint64_t size) {
1212
uint16_t v = static_cast<uint16_t>(std::lround(std::clamp(l, 0.0, 1.0) * 65535.0));
1313
lut[i].red = lut[i].green = lut[i].blue = v;
1414
}
15+
// ensure black exactly 0
16+
lut[0].red = lut[0].green = lut[0].blue = 0;
1517
return lut;
1618
}
1719

@@ -86,4 +88,22 @@ std::shared_ptr<drm_color_ctm> HdrPipeline::BuildCtm709To2020() {
8688
}
8789
}
8890
return ctm;
91+
}
92+
93+
std::shared_ptr<drm_color_ctm> HdrPipeline::BuildCtmIdentity() {
94+
double m[3][3] = {
95+
{1.0, 0.0, 0.0},
96+
{0.0, 1.0, 0.0},
97+
{0.0, 0.0, 1.0}
98+
};
99+
auto ctm = std::make_shared<drm_color_ctm>();
100+
for (int i = 0; i < 3; ++i) {
101+
for (int j = 0; j < 3; ++j) {
102+
double v = m[i][j];
103+
int64_t fp = (int64_t)llround(std::fabs(v) * (1LL << 32));
104+
if (v < 0) fp |= (1ULL << 63);
105+
ctm->matrix[i * 3 + j] = (uint64_t)fp;
106+
}
107+
}
108+
return ctm;
89109
}

drm/HdrPipeline.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
#pragma once
2-
#include <vector>
3-
#include <stdint.h>
42
#include <drm_mode.h>
3+
#include <stdint.h>
4+
#include <vector>
55

66
class HdrPipeline {
7-
public:
8-
7+
public:
98
static std::vector<drm_color_lut> BuildSrgbDegamma(uint64_t size);
109
static std::vector<drm_color_lut> BuildPqGamma(uint64_t size,
11-
float max_luminance, float max_average_luminance,
12-
float min_luminance);
10+
float max_luminance,
11+
float max_average_luminance,
12+
float min_luminance);
1313
static std::shared_ptr<drm_color_ctm> BuildCtm709To2020();
14+
static std::shared_ptr<drm_color_ctm> BuildCtmIdentity();
1415
};

hwc2_device/HwcDisplay.cpp

Lines changed: 62 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -782,6 +782,45 @@ AtomicCommitArgs HwcDisplay::CreateModesetCommit(
782782
return args;
783783
}
784784

785+
auto HwcDisplay::isSingleDeviceHdrLayer() -> std::pair<bool, HwcLayer*> const {
786+
uint32_t hdr_layer_count = 0;
787+
uint32_t total_layer_count = 0;
788+
HwcLayer* hdr_layer = nullptr;
789+
for (auto& pair : layers_) {
790+
auto& layer = pair.second;
791+
total_layer_count++;
792+
if (layer.IsHDRLayer()) {
793+
hdr_layer_count++;
794+
hdr_layer = &layer;
795+
} else {
796+
// Non-HDR layer found, return false immediately
797+
return std::make_pair(false, nullptr);
798+
}
799+
}
800+
return std::make_pair(
801+
(hdr_layer_count == 1) && (total_layer_count == 1),
802+
hdr_layer
803+
);
804+
}
805+
806+
void HwcDisplay::resetHdrPipeLineWhenSingleDeviceHDRLayer(
807+
AtomicCommitArgs &a_args) {
808+
// HDR video layer logic
809+
auto only_hdr_layer = isSingleDeviceHdrLayer();
810+
811+
if (only_hdr_layer.first && only_hdr_layer.second
812+
&& only_hdr_layer.second->GetValidatedType() == HWC2::Composition::Device) {
813+
// Disable all HDR pipeline for direct device scanout
814+
a_args.color_matrix = HdrPipeline::BuildCtmIdentity();
815+
a_args.degamma_lut.reset();
816+
a_args.gamma_lut.reset();
817+
} else {
818+
// Enable HDR pipeline for client composition
819+
// (Assume SetHdrOutputMetadata or similar already set up these)
820+
// If not, you can explicitly set them here as needed.
821+
}
822+
}
823+
785824
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
786825
HWC2::Error HwcDisplay::CreateComposition(AtomicCommitArgs &a_args) {
787826
ATRACE_CALL();
@@ -860,6 +899,7 @@ HWC2::Error HwcDisplay::CreateComposition(AtomicCommitArgs &a_args) {
860899
if (z_map.empty())
861900
return HWC2::Error::BadLayer;
862901

902+
resetHdrPipeLineWhenSingleDeviceHDRLayer(a_args);
863903
std::vector<LayerData> composition_layers;
864904

865905
/* Import & populate */
@@ -1214,22 +1254,33 @@ HWC2::Error HwcDisplay::SetHdrOutputMetadata(ui::Hdr type) {
12141254
m->white_point.y = ToU16ColorValue(whitePoint.y);
12151255

12161256
// build LUT/CTM
1217-
uint64_t gsize1 = 256;
1218-
uint64_t gsize2 = 256;
1257+
uint64_t gsize_gamma = 256;
1258+
uint64_t gsize_degamma = 256;
12191259
if (pipeline_) {
12201260
auto [ret1, sz1] =
12211261
GetPipe().crtc->Get()->GetGammaLutSizeProperty().value();
1222-
if (ret1 == 0 && sz1) gsize1 = sz1;
1262+
if (ret1 == 0 && sz1) gsize_gamma = sz1;
12231263
auto [ret2, sz2] =
12241264
GetPipe().crtc->Get()->GetDeGammaLutSizeProperty().value();
1225-
if (ret2 == 0 && sz2) gsize2 = sz2;
1226-
}
1227-
hdr_degamma_lut_ = std::make_shared<std::vector<drm_color_lut>>(
1228-
HdrPipeline::BuildSrgbDegamma(gsize2));
1229-
hdr_gamma_lut_ = std::make_shared<std::vector<drm_color_lut>>(
1230-
HdrPipeline::BuildPqGamma(gsize1,
1231-
hdr_luminance[0], hdr_luminance[1], hdr_luminance[2]));
1232-
color_matrix_ = HdrPipeline::BuildCtm709To2020();
1265+
if (ret2 == 0 && sz2) gsize_degamma = sz2;
1266+
}
1267+
1268+
if (type == ui::Hdr::HDR10) {
1269+
hdr_degamma_lut_ = std::make_shared<std::vector<drm_color_lut>>(
1270+
HdrPipeline::BuildSrgbDegamma(gsize_degamma));
1271+
hdr_gamma_lut_ = std::make_shared<std::vector<drm_color_lut>>(
1272+
HdrPipeline::BuildPqGamma(gsize_gamma,
1273+
hdr_luminance[0],
1274+
hdr_luminance[1],
1275+
hdr_luminance[2]
1276+
));
1277+
color_matrix_ = HdrPipeline::BuildCtm709To2020();
1278+
} else if (type == ui::Hdr::HLG) {
1279+
hdr_degamma_lut_.reset();
1280+
hdr_gamma_lut_.reset();
1281+
SetColorMatrixToIdentity();
1282+
}
1283+
12331284
return HWC2::Error::None;
12341285
}
12351286

hwc2_device/HwcDisplay.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,9 @@ class HwcDisplay {
252252

253253
bool NeedsClientLayerUpdate() const;
254254

255+
auto isSingleDeviceHdrLayer() -> std::pair<bool, HwcLayer*> const;
256+
void resetHdrPipeLineWhenSingleDeviceHDRLayer(AtomicCommitArgs &a_args);
257+
255258
private:
256259
AtomicCommitArgs CreateModesetCommit(
257260
const HwcDisplayConfig *config,

hwc2_device/HwcLayer.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#define LOG_TAG "drmhwc"
1818
#include <xf86drm.h>
19+
#include <xf86drmMode.h>
1920
#include <linux/dma-buf.h>
2021
#include "HwcLayer.h"
2122

@@ -111,6 +112,12 @@ bool HwcLayer::IsVideoLayer() {
111112
slots_[*active_slot_id_].bi.usage & GRALLOC_USAGE_HW_VIDEO_ENCODER;
112113
}
113114

115+
bool HwcLayer::IsHDRLayer() {
116+
return active_slot_id_.has_value() &&
117+
(slots_[*active_slot_id_].bi.format == DRM_FORMAT_P010_INTEL ||
118+
slots_[*active_slot_id_].bi.format == DRM_FORMAT_P010);
119+
}
120+
114121
void HwcLayer::ImportFb() {
115122
if (!IsLayerUsableAsDevice() || !buffer_updated_ ||
116123
!active_slot_id_.has_value()) {

hwc2_device/HwcLayer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ class HwcLayer {
155155
void PopulateLayerData();
156156
void ClearSlots();
157157
bool IsVideoLayer();
158+
bool IsHDRLayer();
158159
bool IsLayerUsableAsDevice() const {
159160
return !fb_import_failed_ && active_slot_id_.has_value() &&
160161
slots_.count(*active_slot_id_) > 0;

utils/LibdisplayEdidWrapper.cpp

Lines changed: 63 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -45,23 +45,48 @@ void LibdisplayEdidWrapper::GetSupportedHdrTypes(std::vector<ui::Hdr> &types) {
4545
const auto *colorimetries = di_info_get_supported_signal_colorimetry(info_);
4646
if (colorimetries->bt2020_cycc || colorimetries->bt2020_ycc ||
4747
colorimetries->bt2020_rgb) {
48+
#if 0
4849
if (hdr_static_meta->hlg)
4950
types.emplace_back(ui::Hdr::HLG);
51+
#endif
5052
if (hdr_static_meta->pq)
5153
types.emplace_back(ui::Hdr::HDR10);
5254
}
5355
}
5456

55-
void LibdisplayEdidWrapper::GetHdrCapabilities(
56-
std::vector<ui::Hdr> &types, float *max_luminance,
57-
float *max_average_luminance, float *min_luminance) {
57+
void LibdisplayEdidWrapper::GetHdrCapabilities(std::vector<ui::Hdr> &types,
58+
float *max_luminance,
59+
float *max_average_luminance,
60+
float *min_luminance) {
5861
GetSupportedHdrTypes(types);
5962

6063
const auto *hdr_static_meta = di_info_get_hdr_static_metadata(info_);
6164
*max_luminance = hdr_static_meta->desired_content_max_luminance;
6265
*max_average_luminance = hdr_static_meta
6366
->desired_content_max_frame_avg_luminance;
6467
*min_luminance = hdr_static_meta->desired_content_min_luminance;
68+
69+
if (types.empty()) {
70+
// No HDR support, set luminance to SDR values.
71+
*max_luminance = 100.0f;
72+
*max_average_luminance = 100.0f;
73+
*min_luminance = 0.0f;
74+
return;
75+
}
76+
77+
/* hack for LG TV */
78+
char *str = di_info_get_model(info_);
79+
std::string make_str = str ? str : "";
80+
free(str);
81+
if (make_str.find("LG TV SSCR") != std::string::npos) {
82+
if (*max_luminance <= 1.0f) {
83+
// Fallback to typical values if not provided.
84+
*max_luminance = 1000.0f;
85+
*max_average_luminance = 1000.0f;
86+
*min_luminance = 0.0001f;
87+
return;
88+
}
89+
}
6590
}
6691

6792
void LibdisplayEdidWrapper::GetColorModes(std::vector<Colormode> &color_modes) {
@@ -141,44 +166,43 @@ auto LibdisplayEdidWrapper::GetDpi() -> std::pair<int32_t, int32_t> {
141166
dtd->vert_video * kUmPerInch / dtd->vert_image_mm};
142167
}
143168

144-
void LibdisplayEdidWrapper::GetColorGamut(
145-
std::array<float2, 3> &primaries, float2 &whitepoint) {
146-
147-
const struct di_color_primaries *primaries_info;
148-
primaries_info = di_info_get_default_color_primaries(info_);
149-
if (!primaries_info) {
150-
/*
151-
* https://www.w3.org/Graphics/Color/sRGB.html
152-
* ITU-R BT.709 sRGB
153-
*/
154-
primaries[0].x = 0.640;
155-
primaries[0].y = 0.330;
156-
primaries[1].x = 0.300;
157-
primaries[1].y = 0.600;
158-
primaries[2].x = 0.150;
159-
primaries[2].y = 0.060;
160-
161-
whitepoint.x = 0.313;
162-
whitepoint.y = 0.329;
163-
} else {
164-
primaries[0].x = primaries_info->primary[0].x;
165-
primaries[0].y = primaries_info->primary[0].y;
166-
primaries[1].x = primaries_info->primary[1].x;
167-
primaries[1].y = primaries_info->primary[1].y;
168-
primaries[2].x = primaries_info->primary[2].x;
169-
primaries[2].y = primaries_info->primary[2].y;
170-
171-
whitepoint.x = primaries_info->default_white.x;
172-
whitepoint.y = primaries_info->default_white.y;
173-
}
169+
void LibdisplayEdidWrapper::GetColorGamut(std::array<float2, 3> &primaries,
170+
float2 &whitepoint) {
171+
const struct di_color_primaries *primaries_info;
172+
primaries_info = di_info_get_default_color_primaries(info_);
173+
if (!primaries_info) {
174+
/*
175+
* https://www.w3.org/Graphics/Color/sRGB.html
176+
* ITU-R BT.709 sRGB
177+
*/
178+
primaries[0].x = 0.640;
179+
primaries[0].y = 0.330;
180+
primaries[1].x = 0.300;
181+
primaries[1].y = 0.600;
182+
primaries[2].x = 0.150;
183+
primaries[2].y = 0.060;
184+
185+
whitepoint.x = 0.313;
186+
whitepoint.y = 0.329;
187+
} else {
188+
primaries[0].x = primaries_info->primary[0].x;
189+
primaries[0].y = primaries_info->primary[0].y;
190+
primaries[1].x = primaries_info->primary[1].x;
191+
primaries[1].y = primaries_info->primary[1].y;
192+
primaries[2].x = primaries_info->primary[2].x;
193+
primaries[2].y = primaries_info->primary[2].y;
194+
195+
whitepoint.x = primaries_info->default_white.x;
196+
whitepoint.y = primaries_info->default_white.y;
197+
}
174198

175-
ALOGI("print ColorGamut:");
176-
ALOGI(" red %f %f" ,primaries[0].x, primaries[0].y);
177-
ALOGI(" grean %f %f" ,primaries[1].x, primaries[1].y);
178-
ALOGI(" blue %f %f" ,primaries[2].x, primaries[2].y);
179-
ALOGI(" white %f %f" ,whitepoint.x, whitepoint.y);
199+
ALOGI("print ColorGamut:");
200+
ALOGI(" red %f %f", primaries[0].x, primaries[0].y);
201+
ALOGI(" grean %f %f", primaries[1].x, primaries[1].y);
202+
ALOGI(" blue %f %f", primaries[2].x, primaries[2].y);
203+
ALOGI(" white %f %f", whitepoint.x, whitepoint.y);
180204

181-
return;
205+
return;
182206
}
183207

184208
} // namespace android

0 commit comments

Comments
 (0)