android13/hardware/rockchip/hwcomposer/drmhwc2/drm/drmconnector.cpp

1473 lines
48 KiB
C++
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "hwc-drm-connector"
#include "drmconnector.h"
#include "drmdevice.h"
#include "rockchip/utils/drmdebug.h"
#include <errno.h>
#include <stdint.h>
#include <log/log.h>
#include <xf86drmMode.h>
namespace android {
#define GET_BCSH_PROPERTY_VALUE(display_id, func_str, type_str, output_value) \
snprintf(bcsh_property,PROPERTY_VALUE_MAX,func_str,type_str);\
ret = property_get(bcsh_property,bcsh_value,""); \
if(!ret){ \
if(display_id == HWC_DISPLAY_PRIMARY){ \
snprintf(bcsh_property,PROPERTY_VALUE_MAX,func_str,"main"); \
}else{ \
snprintf(bcsh_property,PROPERTY_VALUE_MAX,func_str,"aux"); \
} \
ret = property_get(bcsh_property,bcsh_value,""); \
if(ret){ \
output_value = atoi(bcsh_value); \
exist_suitable_property = true; \
} \
}else{ \
output_value = atoi(bcsh_value); \
exist_suitable_property = true; \
}
#define ALOGI_BEST_MODE_INFO(mode) \
ALOGI("%s,line=%d, Find best mode-id=%d : %dx%d%c%f",\
__FUNCTION__,__LINE__,mode.id(), \
mode.h_display(),mode.v_display(), \
(flags & DRM_MODE_FLAG_INTERLACE) > 0 ? 'c' : 'p', mode.v_refresh())
DrmConnector::DrmConnector(DrmDevice *drm, drmModeConnectorPtr c,
DrmEncoder *current_encoder,
std::vector<DrmEncoder *> &possible_encoders)
: drm_(drm),
id_(c->connector_id),
encoder_(current_encoder),
display_(-1),
type_(c->connector_type),
type_id_(c->connector_type_id),
unique_id_(0),
priority_(0),
state_(c->connection),
mm_width_(c->mmWidth),
mm_height_(c->mmHeight),
possible_encoders_(possible_encoders),
connector_(c),
possible_displays_(0),
bModeReady_(false),
bSupportSt2084_(false),
bSupportHLG_(false),
baseparameter_ready_(false){
}
int DrmConnector::Init() {
int ret = drm_->GetConnectorProperty(*this, "DPMS", &dpms_property_);
if (ret) {
ALOGE("Could not get DPMS property\n");
return ret;
}
ret = drm_->GetConnectorProperty(*this, "CRTC_ID", &crtc_id_property_);
if (ret) {
ALOGE("Could not get CRTC_ID property\n");
return ret;
}
if (writeback()) {
ret = drm_->GetConnectorProperty(*this, "WRITEBACK_PIXEL_FORMATS",
&writeback_pixel_formats_);
if (ret) {
ALOGE("Could not get WRITEBACK_PIXEL_FORMATS connector_id = %d\n", id_);
return ret;
}
ret = drm_->GetConnectorProperty(*this, "WRITEBACK_FB_ID",
&writeback_fb_id_);
if (ret) {
ALOGE("Could not get WRITEBACK_FB_ID connector_id = %d\n", id_);
return ret;
}
ret = drm_->GetConnectorProperty(*this, "WRITEBACK_OUT_FENCE_PTR",
&writeback_out_fence_);
if (ret) {
ALOGE("Could not get WRITEBACK_OUT_FENCE_PTR connector_id = %d\n", id_);
return ret;
}
}
ret = drm_->GetConnectorProperty(*this, "brightness", &brightness_id_property_);
if (ret)
ALOGW("Could not get brightness property\n");
ret = drm_->GetConnectorProperty(*this, "contrast", &contrast_id_property_);
if (ret)
ALOGW("Could not get contrast property\n");
ret = drm_->GetConnectorProperty(*this, "saturation", &saturation_id_property_);
if (ret)
ALOGW("Could not get saturation property\n");
ret = drm_->GetConnectorProperty(*this, "hue", &hue_id_property_);
if (ret)
ALOGW("Could not get hue property\n");
ret = drm_->GetConnectorProperty(*this, "HDR_OUTPUT_METADATA", &hdr_metadata_property_);
if (ret)
ALOGW("Could not get hdr output metadata property\n");
ret = drm_->GetConnectorProperty(*this, "HDR_PANEL_METADATA", &hdr_panel_property_);
if (ret)
ALOGW("Could not get hdr panel metadata property\n");
// Kernel version 5.10 starts using new attribute definitions Colorspace
ret = drm_->GetConnectorProperty(*this, "Colorspace", &colorspace_property_);
if (ret){
ALOGW("Could not get Colorspace property, try to get hdmi_output_colorimetry property.\n");
// Before Kernel version 5.10 starts using old attribute definitions hdmi_output_colorimetry
ret = drm_->GetConnectorProperty(*this, "hdmi_output_colorimetry", &colorspace_property_);
if(ret){
ALOGW("Could not get hdmi_output_colorimetry property.\n");
}
}
// Kernel version 5.10 starts using new attribute definitions color_format
ret = drm_->GetConnectorProperty(*this, "color_format", &color_format_property_);
if (ret) {
ALOGW("Could not get color_format property, try to get hdmi_output_format property.\n");
// Before Kernel version 5.10 using old attribute definitions hdmi_output_format
ret = drm_->GetConnectorProperty(*this, "hdmi_output_format", &color_format_property_);
if(ret){
ALOGW("Could not get hdmi_output_format property.\n");
}
}
// Kernel version 5.10 starts using new attribute definitions color_depth
ret = drm_->GetConnectorProperty(*this, "color_depth", &color_depth_property_);
if (ret) {
ALOGW("Could not get color_depth property, try to get hdmi_output_depth\n");
// Before Kernel version 5.10 using old attribute definitions hdmi_output_depth
ret = drm_->GetConnectorProperty(*this, "hdmi_output_depth", &color_depth_property_);
if(ret){
ALOGW("Could not get hdmi_output_depth property\n");
}
}
// Kernel version 5.10 to get color_format_caps
ret = drm_->GetConnectorProperty(*this, "color_format_caps", &color_format_caps_property_);
if (ret) {
ALOGW("Could not get hdmi_output_format property\n");
}
// Kernel version 5.10 to get color_depth_caps
ret = drm_->GetConnectorProperty(*this, "color_depth_caps", &color_depth_caps_property_);
if (ret) {
ALOGW("Could not get hdmi_output_depth property\n");
}
unique_id_=0;
ret = drm_->GetConnectorProperty(*this, "CONNECTOR_ID", &connector_id_property_);
if (ret) {
ALOGW("Could not get CONNECTOR_ID property\n");
}else{
std::tie(ret,unique_id_) = connector_id_property_.value();
}
drm_->GetHdrPanelMetadata(this,&hdr_metadata_);
bSupportSt2084_ = drm_->is_hdr_panel_support_st2084(this);
bSupportHLG_ = drm_->is_hdr_panel_support_HLG(this);
drmHdr_.clear();
if(bSupportSt2084_){
drmHdr_.push_back(DrmHdr(DRM_HWC_HDR10,
hdr_metadata_.max_display_mastering_luminance,
(hdr_metadata_.max_display_mastering_luminance + hdr_metadata_.min_display_mastering_luminance) / 2,
hdr_metadata_.min_display_mastering_luminance));
}
if(bSupportHLG_){
drmHdr_.push_back(DrmHdr(DRM_HWC_HLG,
hdr_metadata_.max_display_mastering_luminance,
(hdr_metadata_.max_display_mastering_luminance + hdr_metadata_.min_display_mastering_luminance) / 2,
hdr_metadata_.min_display_mastering_luminance));
}
// Update Baseparameter Info
ret = drm_->UpdateConnectorBaseInfo(type_,unique_id_,&baseparameter_);
if(ret){
ALOGI("UpdateConnectorBaseInfo fail, the device may not have a baseparameter.");
baseparameter_ready_=false;
}else{
baseparameter_ready_=true;
}
snprintf(cUniqueName_,30,"%s-%d",drm_->connector_type_str(type_),unique_id_);
bSpiltMode_=false;
ret = drm_->GetConnectorProperty(*this, "USER_SPLIT_MODE", &spilt_mode_property_);
if (ret) {
ALOGW("Could not get USER_SPLIT_MODE property\n");
}else{
std::tie(ret,bSpiltMode_) = spilt_mode_property_.value();
}
return 0;
}
uint32_t DrmConnector::id() const {
return id_;
}
int DrmConnector::display() const {
return display_;
}
void DrmConnector::set_display(int display) {
display_ = display;
}
int DrmConnector::priority() const{
return priority_;
}
void DrmConnector::set_priority(uint32_t priority){
priority_ = priority;
}
uint32_t DrmConnector::possible_displays() const {
return possible_displays_;
}
void DrmConnector::set_possible_displays(uint32_t possible_displays) {
possible_displays_ = possible_displays;
}
bool DrmConnector::internal() const {
if(!possible_displays_){
return type_ == DRM_MODE_CONNECTOR_LVDS || type_ == DRM_MODE_CONNECTOR_eDP ||
type_ == DRM_MODE_CONNECTOR_DSI ||
type_ == DRM_MODE_CONNECTOR_VIRTUAL || type_ == DRM_MODE_CONNECTOR_DPI;
}else{
return (possible_displays_ & HWC_DISPLAY_PRIMARY_BIT) > 0;
}
}
bool DrmConnector::external() const {
if(!possible_displays_){
return type_ == DRM_MODE_CONNECTOR_HDMIA ||
type_ == DRM_MODE_CONNECTOR_DisplayPort ||
type_ == DRM_MODE_CONNECTOR_DVID || type_ == DRM_MODE_CONNECTOR_DVII ||
type_ == DRM_MODE_CONNECTOR_VGA;
}else{
return (possible_displays_ & HWC_DISPLAY_EXTERNAL_BIT) > 0;
}
}
bool DrmConnector::hotplug() const{
return type_ == DRM_MODE_CONNECTOR_HDMIA ||
type_ == DRM_MODE_CONNECTOR_DisplayPort ||
type_ == DRM_MODE_CONNECTOR_DVID || type_ == DRM_MODE_CONNECTOR_DVII ||
type_ == DRM_MODE_CONNECTOR_VGA;
}
bool DrmConnector::writeback() const {
#ifdef DRM_MODE_CONNECTOR_WRITEBACK
return type_ == DRM_MODE_CONNECTOR_WRITEBACK;
#else
return false;
#endif
}
bool DrmConnector::valid_type() const {
return internal() || external() || writeback();
}
int DrmConnector::UpdateModes() {
std::unique_lock<std::recursive_mutex> lock(mRecursiveMutex);
int fd = drm_->fd();
drmModeConnectorPtr c = drmModeGetConnector(fd, id_);
if (!c) {
ALOGE("Failed to get connector %d", id_);
return -ENODEV;
}
drm_->GetHdrPanelMetadata(this, &hdr_metadata_);
//When Plug-in/Plug-out TV panel,some Property of the connector will need be updated.
bSupportSt2084_ = drm_->is_hdr_panel_support_st2084(this);
bSupportHLG_ = drm_->is_hdr_panel_support_HLG(this);
state_ = c->connection;
if (!c->count_modes)
state_ = DRM_MODE_DISCONNECTED;
bool preferred_mode_found = false;
std::vector<DrmMode> new_modes;
for (int i = 0; i < c->count_modes; ++i) {
bool exists = false;
for (const DrmMode &mode : modes_) {
if (mode == c->modes[i]) {
if(type_ == DRM_MODE_CONNECTOR_HDMIA || type_ == DRM_MODE_CONNECTOR_DisplayPort){
//filter mode by /system/usr/share/resolution_white.xml.
if(drm_->mode_verify(mode)){
new_modes.push_back(mode);
exists = true;
break;
}
}else{
new_modes.push_back(mode);
exists = true;
break;
}
}
}
if (exists)
continue;
DrmMode m(&c->modes[i]);
if ((type_ == DRM_MODE_CONNECTOR_HDMIA || type_ == DRM_MODE_CONNECTOR_DisplayPort) && !drm_->mode_verify(m))
continue;
m.set_id(drm_->next_mode_id());
new_modes.push_back(m);
// Use only the first DRM_MODE_TYPE_PREFERRED mode found
if (!preferred_mode_found &&
(new_modes.back().type() & DRM_MODE_TYPE_PREFERRED)) {
preferred_mode_id_ = new_modes.back().id();
preferred_mode_found = true;
}
}
modes_.swap(new_modes);
//Get original mode from connector
std::vector<DrmMode> new_raw_modes;
for (int i = 0; i < c->count_modes; ++i) {
bool exists = false;
for (const DrmMode &mode : modes_) {
if (mode == c->modes[i]) {
new_raw_modes.push_back(mode);
exists = true;
break;
}
}
if (exists)
continue;
DrmMode m(&c->modes[i]);
m.set_id(drm_->next_mode_id());
new_raw_modes.push_back(m);
}
raw_modes_.swap(new_raw_modes);
if (!preferred_mode_found && modes_.size() != 0) {
preferred_mode_id_ = modes_[0].id();
}
bModeReady_ = true;
HWC2_ALOGD_IF_DEBUG("conn=%d state=%d count_modes.size=%d modes_.size=%zu new_raw_modes.size=%zu",
id_, state_,c->count_modes, modes_.size(),raw_modes_.size());
drmModeFreeConnector(c);
// VRR
UpdateVrrModes();
return 0;
}
int DrmConnector::UpdateVrrModes(){
if(!encoder() || !(encoder()->crtc()) || encoder()->crtc()->variable_refresh_rate().id() == 0){
return 0;
}
if(modes_.size() != 1){
return 0;
}
int ret = 0;
vrr_modes_.clear();
DrmCrtc* crtc = encoder()->crtc();
uint64_t min_refresh_rate = 0;
uint64_t max_refresh_rate = 0;
std::tie(ret, min_refresh_rate) = crtc->min_refresh_rate().value();
std::tie(ret, max_refresh_rate) = crtc->max_refresh_rate().value();
if(min_refresh_rate == 0 || max_refresh_rate == 0){
return 0;
}
for(uint64_t fps = max_refresh_rate ; fps >= min_refresh_rate; fps -= 10){
vrr_modes_.push_back(fps);
if(fps < 10)
break;
}
return 0;
}
int DrmConnector::UpdateDisplayMode(int display_id, int update_base_timeline){
std::unique_lock<std::recursive_mutex> lock(mRecursiveMutex);
char resolution_value[PROPERTY_VALUE_MAX]={0};
char resolution_property[PROPERTY_VALUE_MAX]={0};
uint32_t width, height, flags, clock;
uint32_t hsync_start, hsync_end, htotal;
uint32_t vsync_start, vsync_end, vtotal;
bool interlaced;
float vrefresh;
char val;
uint32_t MaxResolution = 0,temp;
snprintf(resolution_property,PROPERTY_VALUE_MAX,"persist.vendor.resolution.%s",cUniqueName_);
property_get(resolution_property, resolution_value, "Unkonw");
ALOGI("%s,line=%d, display=%d %s=%s",__FUNCTION__,__LINE__,display_id,resolution_property,resolution_value);
if(!strcmp(resolution_value,"Unkonw")){
if(display_id == HWC_DISPLAY_PRIMARY){
property_get("persist.vendor.resolution.main", resolution_value, "Unkonw");
}else{
property_get("persist.vendor.resolution.aux", resolution_value, "Unkonw");
}
ALOGI("%s,line=%d, display=%d persist.vendor.resolution.%s=%s",__FUNCTION__,__LINE__,display_id,
display_id == HWC_DISPLAY_PRIMARY ? "main" : "aux",resolution_value);
}
if(strcmp(resolution_value,"Unkonw") != 0){
ALOGI("%s,line=%d, resolution_value=%s",__FUNCTION__,__LINE__,resolution_value);
int len = sscanf(resolution_value, "%dx%d@%f-%d-%d-%d-%d-%d-%d-%x-%d",
&width, &height, &vrefresh, &hsync_start,
&hsync_end, &htotal, &vsync_start,&vsync_end,
&vtotal, &flags, &clock);
// Support clock
if (len == 11 && width != 0 && height != 0) {
for (const DrmMode &conn_mode : modes()) {
if (conn_mode.equal(width, height, hsync_start, hsync_end,
htotal, vsync_start, vsync_end, vtotal, flags, clock)) {
set_best_mode(conn_mode);
ALOGI_BEST_MODE_INFO(conn_mode);
return 0;
}
}
}
// Old resolution format
if (len == 10 && width != 0 && height != 0) {
for (const DrmMode &conn_mode : modes()) {
if (conn_mode.equal(width, height, vrefresh, hsync_start, hsync_end,
htotal, vsync_start, vsync_end, vtotal, flags)) {
set_best_mode(conn_mode);
ALOGI_BEST_MODE_INFO(conn_mode);
return 0;
}
}
}
uint32_t ivrefresh;
len = sscanf(resolution_value, "%dx%d%c%d", &width, &height, &val, &ivrefresh);
if (val == 'i')
interlaced = true;
else
interlaced = false;
if (len == 4 && width != 0 && height != 0) {
for (const DrmMode &conn_mode : modes()) {
if (conn_mode.equal(width, height, ivrefresh, interlaced)) {
set_best_mode(conn_mode);
ALOGI_BEST_MODE_INFO(conn_mode);
return 0;
}
}
}
}else{ // resolution_value is Unkonw
if(baseparameter_ready_ && !strcmp(resolution_value,"Unkonw")){
ALOGI("%s,line=%d, can't find suitable Resolution Property, try to use Baseparameter.",__FUNCTION__,__LINE__);
if(update_base_timeline != iTimeline_){
iTimeline_ = update_base_timeline;
int ret = drm_->UpdateConnectorBaseInfo(type_,unique_id_,&baseparameter_);
if(ret){
ALOGW("%s,line=%d,UpdateConnectorBaseInfo fail, the device may not have a baseparameter.",__FUNCTION__,__LINE__);
}
}
width = baseparameter_.screen_info[0].resolution.hdisplay;
height = baseparameter_.screen_info[0].resolution.vdisplay;
hsync_start = baseparameter_.screen_info[0].resolution.hsync_start;
hsync_end = baseparameter_.screen_info[0].resolution.hsync_end;
htotal = baseparameter_.screen_info[0].resolution.htotal;
vsync_start = baseparameter_.screen_info[0].resolution.vsync_start;
vsync_end = baseparameter_.screen_info[0].resolution.vsync_end;
vtotal = baseparameter_.screen_info[0].resolution.vtotal;
flags = baseparameter_.screen_info[0].resolution.flags;
clock = baseparameter_.screen_info[0].resolution.clock;
// Support clock
if (width != 0 && height != 0) {
for (const DrmMode &conn_mode : modes()) {
if (conn_mode.equal(width, height, hsync_start, hsync_end,
htotal, vsync_start, vsync_end, vtotal, flags, clock)) {
set_best_mode(conn_mode);
ALOGI_BEST_MODE_INFO(conn_mode);
return 0;
}
}
}
}
}
for (const DrmMode &conn_mode : modes()) {
if (conn_mode.type() & DRM_MODE_TYPE_PREFERRED) {
set_best_mode(conn_mode);
ALOGI_BEST_MODE_INFO(conn_mode);
return 0;
}
}
// 20230104: 参考uboot分辨率获取逻辑如果获取不到最佳分辨率则直接使用白名单列表第一个分辨率
for (const DrmMode &conn_mode : modes()) {
set_best_mode(conn_mode);
ALOGI_BEST_MODE_INFO(conn_mode);
return 0;
}
//use raw modes to get mode.
for (const DrmMode &conn_mode : raw_modes()) {
if (conn_mode.type() & DRM_MODE_TYPE_PREFERRED) {
set_best_mode(conn_mode);
ALOGI_BEST_MODE_INFO(conn_mode);
return 0;
}
}
// 20230104: 如果白名单分辨率一个都没有,直接获取分辨率列表第一个分辨率
for (const DrmMode &conn_mode : raw_modes()) {
set_best_mode(conn_mode);
ALOGI_BEST_MODE_INFO(conn_mode);
return 0;
}
ALOGE("Error: Should not get here display=%d %s %d\n", display_id, __FUNCTION__, __LINE__);
DrmMode mode;
set_best_mode(mode);
return 0;
}
int DrmConnector::GetSuitableMode(int display_id, uint64_t max_width, uint64_t dlck){
std::unique_lock<std::recursive_mutex> lock(mRecursiveMutex);
uint32_t flags = 0;
for (const DrmMode &conn_mode : modes()) {
if (conn_mode.type() & DRM_MODE_TYPE_PREFERRED) {
if(conn_mode.h_display() > max_width){
continue;
}
if(conn_mode.h_display() *
conn_mode.v_display() *
(uint64_t)conn_mode.v_refresh() > dlck){
continue;
}
set_best_mode(conn_mode);
set_current_mode(conn_mode);
ALOGI_BEST_MODE_INFO(conn_mode);
return 0;
}
}
// 20230104: 参考uboot分辨率获取逻辑如果获取不到最佳分辨率则直接使用白名单列表第一个分辨率
for (const DrmMode &conn_mode : modes()) {
if(conn_mode.h_display() > max_width){
continue;
}
if(conn_mode.h_display() *
conn_mode.v_display() *
(uint64_t)conn_mode.v_refresh() > dlck){
continue;
}
set_best_mode(conn_mode);
set_current_mode(conn_mode);
ALOGI_BEST_MODE_INFO(conn_mode);
return 0;
}
//use raw modes to get mode.
for (const DrmMode &conn_mode : raw_modes()) {
if (conn_mode.type() & DRM_MODE_TYPE_PREFERRED) {
if(conn_mode.h_display() > max_width){
continue;
}
if(conn_mode.h_display() *
conn_mode.v_display() *
(uint64_t)conn_mode.v_refresh() > dlck){
continue;
}
set_best_mode(conn_mode);
set_current_mode(conn_mode);
ALOGI_BEST_MODE_INFO(conn_mode);
return 0;
}
}
// 20230104: 如果白名单分辨率一个都没有,直接获取分辨率列表第一个分辨率
for (const DrmMode &conn_mode : raw_modes()) {
if(conn_mode.h_display() > max_width){
continue;
}
if(conn_mode.h_display() *
conn_mode.v_display() *
(uint64_t)conn_mode.v_refresh() > dlck){
continue;
}
set_best_mode(conn_mode);
set_current_mode(conn_mode);
ALOGI_BEST_MODE_INFO(conn_mode);
return 0;
}
ALOGE("Error: Should not get here display=%d %s %d\n", display_id, __FUNCTION__, __LINE__);
DrmMode mode;
set_best_mode(mode);
return 0;
}
int DrmConnector::SetDisplayModeInfo(int display_id) {
int ret = 0;
const DrmMode mode = current_mode();
if(baseparameter_ready_){
baseparameter_.screen_info[0].resolution.hdisplay = mode.h_display();
baseparameter_.screen_info[0].resolution.vdisplay = mode.v_display();
baseparameter_.screen_info[0].resolution.vrefresh = static_cast<int>(mode.v_refresh());
baseparameter_.screen_info[0].resolution.hsync_start = mode.h_sync_start();
baseparameter_.screen_info[0].resolution.hsync_end = mode.h_sync_end();
baseparameter_.screen_info[0].resolution.htotal = mode.h_total();
baseparameter_.screen_info[0].resolution.vsync_start = mode.v_sync_start();
baseparameter_.screen_info[0].resolution.vsync_end = mode.v_sync_end();
baseparameter_.screen_info[0].resolution.vtotal = mode.v_total();
baseparameter_.screen_info[0].resolution.flags = mode.flags();
baseparameter_.screen_info[0].resolution.clock = mode.clock();
ret = drm_->SetScreenInfo(type_,unique_id_,0,baseparameter_.screen_info);
if(ret){
ALOGW("%s,line=%d,display-id=%d %s SetScreenInfo fail!",__FUNCTION__,__LINE__,display_id,cUniqueName_);
return ret;
}
}
return ret;
}
int DrmConnector::UpdateOverscan(int display_id, char *overscan_value){
char overscan_property[PROPERTY_VALUE_MAX]={0};
snprintf(overscan_property,PROPERTY_VALUE_MAX,"persist.vendor.overscan.%s",cUniqueName_);
property_get(overscan_property, overscan_value, "Unkonw");
// ALOGI("%s,line=%d, display=%d %s=%s",__FUNCTION__,__LINE__,display_id,overscan_property,overscan_value);
if(!strcmp(overscan_value,"Unkonw")){
if(display_id == HWC_DISPLAY_PRIMARY){
property_get("persist.vendor.overscan.main", overscan_value, "Unkonw");
}else{
property_get("persist.vendor.overscan.aux", overscan_value, "Unkonw");
}
// ALOGI("%s,line=%d, display=%d persist.vendor.overscan.%s=%s",__FUNCTION__,__LINE__,display_id,
// display_id == HWC_DISPLAY_PRIMARY ? "main" : "aux", overscan_value);
}
return 0;
}
int DrmConnector::UpdateBCSH(int display_id, int update_base_timeline){
std::unique_lock<std::recursive_mutex> lock(mRecursiveMutex);
uint32_t brightness=50, contrast=50, saturation=50, hue=50;
int ret = 0;
bool exist_suitable_property=false;
char bcsh_property[PROPERTY_VALUE_MAX]={0};
char bcsh_value[PROPERTY_VALUE_MAX]={0};
GET_BCSH_PROPERTY_VALUE(display_id, "persist.vendor.brightness.%s", cUniqueName_, brightness);
GET_BCSH_PROPERTY_VALUE(display_id, "persist.vendor.contrast.%s", cUniqueName_, contrast);
GET_BCSH_PROPERTY_VALUE(display_id, "persist.vendor.saturation.%s", cUniqueName_, saturation);
GET_BCSH_PROPERTY_VALUE(display_id, "persist.vendor.hue.%s", cUniqueName_, hue);
if(!exist_suitable_property && baseparameter_ready_){
ALOGI("%s,line=%d, %s can't find suitable BCSH Property, try to use Baseparameter.",
__FUNCTION__,__LINE__,cUniqueName_);
if(update_base_timeline != iTimeline_){
iTimeline_ = update_base_timeline;
int ret = drm_->UpdateConnectorBaseInfo(type_,unique_id_,&baseparameter_);
if(ret){
ALOGW("%s,line=%d,%s UpdateConnectorBaseInfo fail, the device may not have a baseparameter.",
__FUNCTION__,__LINE__,cUniqueName_);
}
}
brightness = baseparameter_.bcsh_info.brightness;
contrast = baseparameter_.bcsh_info.contrast;
saturation = baseparameter_.bcsh_info.saturation;
hue = baseparameter_.bcsh_info.hue;
}
ALOGI("%s,line=%d, %s BCSH=[%d,%d,%d,%d]",__FUNCTION__,__LINE__,cUniqueName_,brightness, contrast, saturation, hue);
if(uBrightness_ != brightness || uContrast_ != contrast ||
uSaturation_ != saturation || uHue_ != hue){
drmModeAtomicReqPtr pset = drmModeAtomicAlloc();
if (!pset) {
ALOGE("Failed to allocate property set");
return -ENOMEM;
}
DRM_ATOMIC_ADD_PROP(id(), brightness_id_property().id(),brightness > 100 ? 100 : brightness)
DRM_ATOMIC_ADD_PROP(id(), contrast_id_property().id(),contrast > 100 ? 100 : contrast)
DRM_ATOMIC_ADD_PROP(id(), saturation_id_property().id(),saturation > 100 ? 100 : saturation)
DRM_ATOMIC_ADD_PROP(id(), hue_id_property().id(),hue > 100 ? 100 : hue)
uint32_t flags = 0;
ret = drmModeAtomicCommit(drm_->fd(), pset, flags, this);
if (ret < 0) {
ALOGE("Failed to commit pset ret=%d\n", ret);
drmModeAtomicFree(pset);
pset=NULL;
return ret;
}
drmModeAtomicFree(pset);
pset=NULL;
uBrightness_ = brightness;
uContrast_ = contrast;
uSaturation_ = saturation;
uHue_ = hue;
}
return 0;
}
bool DrmConnector::ParseHdmiOutputFormat(char* strprop, int *format, int *depth) {
if (!strcmp(strprop, "Auto")) {
*format = output_ycbcr_high_subsampling;
*depth = Automatic;
return true;
}
if (!strcmp(strprop, "RGB-8bit")) {
*format = output_rgb;
*depth = depth_24bit;
return true;
}
if (!strcmp(strprop, "RGB-10bit")) {
*format = output_rgb;
*depth = depth_30bit;
return true;
}
if (!strcmp(strprop, "YCBCR444-8bit")) {
*format = output_ycbcr444;
*depth = depth_24bit;
return true;
}
if (!strcmp(strprop, "YCBCR444-10bit")) {
*format = output_ycbcr444;
*depth = depth_30bit;
return true;
}
if (!strcmp(strprop, "YCBCR422-8bit")) {
*format = output_ycbcr422;
*depth = depth_24bit;
return true;
}
if (!strcmp(strprop, "YCBCR422-10bit")) {
*format = output_ycbcr422;
*depth = depth_30bit;
return true;
}
if (!strcmp(strprop, "YCBCR420-8bit")) {
*format = output_ycbcr420;
*depth = depth_24bit;
return true;
}
if (!strcmp(strprop, "YCBCR420-10bit")) {
*format = output_ycbcr420;
*depth = depth_30bit;
return true;
}
ALOGE("hdmi output format is invalid. [%s]", strprop);
return false;
}
int DrmConnector::UpdateOutputFormat(int display_id, int update_base_timeline){
std::unique_lock<std::recursive_mutex> lock(mRecursiveMutex);
if(!(color_format_property().id() > 0 || color_depth_property().id() > 0)){
return 0;
}
int ret = 0;
bool update = false;
int color_format = -1;
int color_depth = -1;
bool need_change_format = false,need_change_depth = false;
bool exist_suitable_property = false;
char output_format_pro[PROPERTY_VALUE_MAX]={0};
char output_format_value[PROPERTY_VALUE_MAX]={0};
snprintf(output_format_pro,PROPERTY_VALUE_MAX,"persist.vendor.color.%s",cUniqueName_);
ret = property_get(output_format_pro,output_format_value,"");
if(!ret){
if(display_id == HWC_DISPLAY_PRIMARY){
snprintf(output_format_pro,PROPERTY_VALUE_MAX,"persist.vendor.color.%s","main");
}else{
snprintf(output_format_pro,PROPERTY_VALUE_MAX,"persist.vendor.color.%s","aux");
}
ret = property_get(output_format_pro,output_format_value,"");
if(ret){
exist_suitable_property = true;
}
}else{
exist_suitable_property = true;
}
if(exist_suitable_property){
ret = ParseHdmiOutputFormat(output_format_value, &color_format, &color_depth);
if (ret == false) {
ALOGE("Get color fail! to use default ");
color_format = output_rgb;
color_depth = depth_24bit;
}
}else if(baseparameter_ready_){
ALOGI("%s,line=%d, %s can't find suitable output format Property, try to use Baseparameter.",
__FUNCTION__,__LINE__,cUniqueName_);
if(update_base_timeline != iTimeline_){
iTimeline_ = update_base_timeline;
int ret = drm_->UpdateConnectorBaseInfo(type_,unique_id_,&baseparameter_);
if(ret){
ALOGW("%s,line=%d,%s UpdateConnectorBaseInfo fail, the device may not have a baseparameter.",
__FUNCTION__,__LINE__,cUniqueName_);
}
}
color_format = baseparameter_.screen_info[0].format;
color_depth = baseparameter_.screen_info[0].depthc;
}else{
color_format = output_ycbcr_high_subsampling;
color_depth = depth_24bit;
}
if(color_format != -1 && uColorFormat_ != color_format) {
update = true;
need_change_format = true;
}
if(color_depth != -1 && uColorDepth_ != color_depth) {
update = true;
need_change_depth = true;
}
if(!update)
return 0;
drmModeAtomicReqPtr pset = drmModeAtomicAlloc();
if (!pset) {
ALOGE("%s:line=%d Failed to allocate property set", __FUNCTION__, __LINE__);
return false;
}
if(need_change_format > 0) {
ALOGI("%s,line=%d %s change hdmi output format: %d", __FUNCTION__,__LINE__, cUniqueName_, color_format);
ret = drmModeAtomicAddProperty(pset, id(), color_format_property().id(), color_format);
if (ret < 0) {
ALOGE("%s:line=%d Failed to add prop[%d] to [%d]", __FUNCTION__, __LINE__, color_format_property().id(), id());
}
}
if(need_change_depth > 0) {
ALOGI("%s,line=%d %s change hdmi output depth: %d", __FUNCTION__,__LINE__, cUniqueName_, color_depth);
ret = drmModeAtomicAddProperty(pset, id(), color_depth_property().id(), color_depth);
if (ret < 0) {
ALOGE("%s:line=%d Failed to add prop[%d] to [%d]", __FUNCTION__, __LINE__, color_depth_property().id(), id());
}
}
ret = drmModeAtomicCommit(drm_->fd(), pset, DRM_MODE_ATOMIC_ALLOW_MODESET, drm_);
if (ret < 0) {
ALOGE("%s:line=%d %s Failed to commit! ret=%d", __FUNCTION__, __LINE__, cUniqueName_, ret);
}else{
uColorFormat_ = color_format;
uColorDepth_ = color_depth;
}
drmModeAtomicFree(pset);
pset = NULL;
return 0;
}
int DrmConnector::UpdateOutputFormat(drmModeAtomicReqPtr pset){
std::unique_lock<std::recursive_mutex> lock(mRecursiveMutex);
if(!(color_format_property().id() > 0 || color_depth_property().id() > 0)){
return 0;
}
int ret = 0;
bool update = false;
int color_format = -1;
int color_depth = -1;
bool need_change_format = false,need_change_depth = false;
bool exist_suitable_property = false;
char output_format_pro[PROPERTY_VALUE_MAX]={0};
char output_format_value[PROPERTY_VALUE_MAX]={0};
snprintf(output_format_pro,PROPERTY_VALUE_MAX,"persist.vendor.color.%s",cUniqueName_);
ret = property_get(output_format_pro,output_format_value,"");
if(!ret){
if(display_ == HWC_DISPLAY_PRIMARY){
snprintf(output_format_pro,PROPERTY_VALUE_MAX,"persist.vendor.color.%s","main");
}else{
snprintf(output_format_pro,PROPERTY_VALUE_MAX,"persist.vendor.color.%s","aux");
}
ret = property_get(output_format_pro,output_format_value,"");
if(ret){
exist_suitable_property = true;
}
}else{
exist_suitable_property = true;
}
if(exist_suitable_property){
ret = ParseHdmiOutputFormat(output_format_value, &color_format, &color_depth);
if (ret == false) {
ALOGE("Get color fail! to use default ");
color_format = output_ycbcr_high_subsampling;
color_depth = depth_24bit;
}
}else if(baseparameter_ready_){
ALOGI("%s,line=%d, %s can't find suitable output format Property, try to use Baseparameter.",
__FUNCTION__,__LINE__,cUniqueName_);
int ret = drm_->UpdateConnectorBaseInfo(type_,unique_id_,&baseparameter_);
if(ret){
ALOGW("%s,line=%d,%s UpdateConnectorBaseInfo fail, the device may not have a baseparameter.",
__FUNCTION__,__LINE__,cUniqueName_);
}
color_format = baseparameter_.screen_info[0].format;
color_depth = baseparameter_.screen_info[0].depthc;
}else{
color_format = output_ycbcr_high_subsampling;
color_depth = depth_24bit;
}
ALOGI("%s,line=%d %s change hdmi output format: %d", __FUNCTION__,__LINE__, cUniqueName_, color_format);
ret = drmModeAtomicAddProperty(pset, id(), color_format_property().id(), color_format);
if (ret < 0) {
ALOGE("%s:line=%d Failed to add prop[%d] to [%d]", __FUNCTION__, __LINE__, color_format_property().id(), id());
}
ALOGI("%s,line=%d %s change hdmi output depth: %d", __FUNCTION__,__LINE__, cUniqueName_, color_depth);
ret = drmModeAtomicAddProperty(pset, id(), color_depth_property().id(), color_depth);
if (ret < 0) {
ALOGE("%s:line=%d Failed to add prop[%d] to [%d]", __FUNCTION__, __LINE__, color_depth_property().id(), id());
}
uColorFormat_ = color_format;
uColorDepth_ = color_depth;
return 0;
}
int DrmConnector::GetFramebufferInfo(int display_id, uint32_t *w, uint32_t *h, uint32_t *fps) {
char framebuffer_value[PROPERTY_VALUE_MAX]={0};
char framebuffer_property[PROPERTY_VALUE_MAX]={0};
uint32_t width=0, height=0, vrefresh=0;
snprintf(framebuffer_property,PROPERTY_VALUE_MAX,"persist.vendor.framebuffer.%s",cUniqueName_);
property_get(framebuffer_property, framebuffer_value, "Unkonw");
ALOGI("%s,line=%d, display=%d %s=%s",__FUNCTION__,__LINE__,display_id,framebuffer_property,framebuffer_value);
if(!strcmp(framebuffer_value,"Unkonw")){
if(display_id == HWC_DISPLAY_PRIMARY){
property_get("persist.vendor.framebuffer.main", framebuffer_value, "Unkonw");
}else{
property_get("persist.vendor.framebuffer.aux", framebuffer_value, "Unkonw");
}
ALOGI("%s,line=%d, display=%d persist.vendor.framebuffer.%s=%s",__FUNCTION__,__LINE__,display_id,
display_id == HWC_DISPLAY_PRIMARY ? "main" : "aux",framebuffer_value);
}
if(!strcmp(framebuffer_value,"Unkonw")){
if(baseparameter_ready_){
*w = baseparameter_.framebuffer_info.framebuffer_width;
*h = baseparameter_.framebuffer_info.framebuffer_height;
*fps = baseparameter_.framebuffer_info.fps;
}else{
*w = 0;
*h = 0;
*fps = 0;
}
}else{
sscanf(framebuffer_value, "%dx%d@%d", &width, &height, &vrefresh);
*w = width;
*h = height;
*fps = vrefresh;
}
return 0;
}
const DrmMode &DrmConnector::active_mode() const {
return active_mode_;
}
const DrmMode &DrmConnector::best_mode() const {
return best_mode_;
}
const DrmMode &DrmConnector::current_mode() const {
return current_mode_;
}
void DrmConnector::set_best_mode(const DrmMode &mode) {
best_mode_ = mode;
}
void DrmConnector::set_active_mode(const DrmMode &mode) {
active_mode_ = mode;
}
void DrmConnector::set_current_mode(const DrmMode &mode) {
current_mode_ = mode;
}
void DrmConnector::SetDpmsMode(uint32_t dpms_mode) {
int ret = drmModeConnectorSetProperty(drm_->fd(), id_, dpms_property_.id(), dpms_mode);
if (ret) {
ALOGE("Failed to set dpms mode %d %d", ret, dpms_mode);
return;
}
}
bool DrmConnector::isExistMode(const DrmMode &in_mode){
for(auto&mode : modes_){
if(mode.equal_no_flag_and_type(in_mode)){
return true;
}
}
return false;
}
const DrmProperty &DrmConnector::dpms_property() const {
return dpms_property_;
}
const DrmProperty &DrmConnector::crtc_id_property() const {
return crtc_id_property_;
}
const DrmProperty &DrmConnector::writeback_pixel_formats() const {
return writeback_pixel_formats_;
}
const DrmProperty &DrmConnector::writeback_fb_id() const {
return writeback_fb_id_;
}
const DrmProperty &DrmConnector::writeback_out_fence() const {
return writeback_out_fence_;
}
DrmEncoder *DrmConnector::encoder() const {
return encoder_;
}
void DrmConnector::set_encoder(DrmEncoder *encoder) {
encoder_ = encoder;
}
drmModeConnection DrmConnector::state() {
return state_;
}
bool DrmConnector::hwc_state_change_and_plug(){
if(plug_){
plug_ = false;
return true;
}
return false;
}
HwcConnnectorStete DrmConnector::hwc_state(){
return hwc_state_;
}
int DrmConnector::set_hwc_state(HwcConnnectorStete state){
if(state == NORMAL &&
(hwc_state_ == NO_CRTC ||
hwc_state_ == RELEASE_CRTC ||
hwc_state_ == MIRROR_CRTC)){
plug_ = true;
}
hwc_state_ = state;
return 0;
}
void DrmConnector::update_hotplug_state(){
std::unique_lock<std::recursive_mutex> lock(mRecursiveMutex);
hotplug_state_ = state_;
}
drmModeConnection DrmConnector::hotplug_state(){
std::unique_lock<std::recursive_mutex> lock(mRecursiveMutex);
return hotplug_state_;
}
uint32_t DrmConnector::mm_width() const {
return mm_width_;
}
uint32_t DrmConnector::mm_height() const {
return mm_height_;
}
bool DrmConnector::is_hdmi_support_hdr() const
{
return (hdr_metadata_property_.id() && bSupportSt2084_) || (hdr_metadata_property_.id() && bSupportHLG_);
}
int DrmConnector::switch_hdmi_hdr_mode(drmModeAtomicReqPtr pset,
android_dataspace_t input_colorspace,
bool is_10bit){
std::unique_lock<std::recursive_mutex> lock(mRecursiveMutex);
HWC2_ALOGD_IF_DEBUG("conn-id=%d, isSupportSt2084 = %d, isSupportHLG = %d , colorspace = %x",
id(),isSupportSt2084(),isSupportHLG(),input_colorspace);
if (!pset) {
ALOGE("%s:line=%d Failed to allocate property set", __FUNCTION__, __LINE__);
return -1;
}
// 释放上一次的 Blob
if (blob_id_){
drm_->DestroyPropertyBlob(blob_id_);
blob_id_ = 0;
}
struct hdr_output_metadata hdr_metadata;
memset(&hdr_metadata, 0, sizeof(struct hdr_output_metadata));
#ifdef ANDROID_S
hdr_metadata_infoframe &hdmi_metadata_type = hdr_metadata.hdmi_metadata_type1;
#elif ANDROID_P
hdr_metadata_infoframe &hdmi_metadata_type = hdr_metadata.hdmi_metadata_type1;
#else
hdr_metadata_infoframe &hdmi_metadata_type = hdr_metadata.hdmi_metadata_type;
#endif
if((input_colorspace & HAL_DATASPACE_TRANSFER_MASK) == HAL_DATASPACE_TRANSFER_ST2084
&& isSupportSt2084()){
HWC2_ALOGD_IF_DEBUG("has st2084");
hdmi_metadata_type.eotf = SMPTE_ST2084;
}else if((input_colorspace & HAL_DATASPACE_TRANSFER_MASK) == HAL_DATASPACE_TRANSFER_HLG
&& isSupportHLG()){
HWC2_ALOGD_IF_DEBUG("has HLG");
hdmi_metadata_type.eotf = HLG;
}else{
hdmi_metadata_type.eotf = TRADITIONAL_GAMMA_SDR;
}
DrmColorspaceType colorspace = DrmColorspaceType::DEFAULT;
int ret = -1;
bool hdr_state_update = false;
if(hdr_metadata_property().id()){
HWC2_ALOGD_IF_DEBUG("hdr_metadata eotf=0x%x", hdmi_metadata_type.eotf);
drm_->CreatePropertyBlob(&hdr_metadata, sizeof(struct hdr_output_metadata), &blob_id_);
ret = drmModeAtomicAddProperty(pset, id(), hdr_metadata_property().id(), blob_id_);
if (ret < 0) {
HWC2_ALOGE("Failed to add prop[%d] to [%d]", hdr_metadata_property().id(), id());
}
}
if(colorspace_property().id()){
if((input_colorspace & HAL_DATASPACE_STANDARD_BT2020) == HAL_DATASPACE_STANDARD_BT2020){
// DrmVersion=3 is Kernel 5.10 Support all DrmColorspaceType
if(drm_->getDrmVersion() == 3){
if(uColorFormat_ == output_rgb){
colorspace = DrmColorspaceType::BT2020_RGB;
} else {
colorspace = DrmColorspaceType::BT2020_YCC;
}
}else{ // Kernel 4.19 only support BT2020_RGB
colorspace = DrmColorspaceType::BT2020_RGB;
}
}
HWC2_ALOGD_IF_DEBUG("change bt2020 colorspace=%d", colorspace);
ret = drmModeAtomicAddProperty(pset, id(), colorspace_property().id(), colorspace);
if (ret < 0) {
HWC2_ALOGE("Failed to add prop[%d] to [%d]", colorspace_property().id(), id());
}
}
int color_depth = depth_24bit;
if(hdmi_metadata_type.eotf == TRADITIONAL_GAMMA_SDR){
UpdateOutputFormat(pset);
}else{
color_depth = is_10bit ? depth_30bit : depth_24bit;
HWC2_ALOGD_IF_DEBUG("change hdmi output format: %d", uColorFormat_);
ret = drmModeAtomicAddProperty(pset, id(), color_format_property().id(), uColorFormat_);
if (ret < 0) {
HWC2_ALOGE("Failed to add prop[%d] to [%d]", color_format_property().id(), id());
}
HWC2_ALOGD_IF_DEBUG("change hdmi output depth: %d", color_depth);
ret = drmModeAtomicAddProperty(pset, id(), color_depth_property().id(), color_depth);
if (ret < 0) {
HWC2_ALOGE("Failed to add prop[%d] to [%d]", color_depth_property().id(), id());
}
}
memcpy(&last_hdr_metadata_, &hdr_metadata, sizeof(struct hdr_output_metadata));
colorspace_ = colorspace;
uColorDepth_ = color_depth;
return 0;
}
int DrmConnector::switch_hdmi_hdr_mode_by_medadata(drmModeAtomicReqPtr pset,
uint32_t color_prim,
hdr_output_metadata *hdr_metadata,
bool is_10bit){
std::unique_lock<std::recursive_mutex> lock(mRecursiveMutex);
HWC2_ALOGD_IF_DEBUG("conn-id=%d 10bit=%d, isSupportSt2084 = %d, isSupportHLG = %d",
id(), is_10bit, isSupportSt2084(), isSupportHLG());
if (!pset) {
ALOGE("%s:line=%d Failed to allocate property set", __FUNCTION__, __LINE__);
return -1;
}
#ifdef ANDROID_S
hdr_metadata_infoframe &hdmi_metadata_type = hdr_metadata->hdmi_metadata_type1;
#elif ANDROID_P
hdr_metadata_infoframe &hdmi_metadata_type = hdr_metadata->hdmi_metadata_type1;
#else
hdr_metadata_infoframe &hdmi_metadata_type = hdr_metadata->hdmi_metadata_type;
#endif
HWC2_ALOGD_IF_DEBUG("hdr_metadata: metadata_type=%d",hdr_metadata->metadata_type);
HWC2_ALOGD_IF_DEBUG("hdr_metadata: color_prim=%x eotf=%d metadata_type=%d \n"
"display_primaries[0][x,y]=[%d,%d][%d,%d][%d,%d]\n"
"white_point[x,y]=[%d,%d]\n"
"max_display_mastering_luminance=%d\n"
"min_display_mastering_luminance=%d\n"
"max_cll=%d\n"
"max_fall=%d\n",
color_prim,
hdmi_metadata_type.eotf,
hdmi_metadata_type.metadata_type,
hdmi_metadata_type.display_primaries[0].x,
hdmi_metadata_type.display_primaries[0].y,
hdmi_metadata_type.display_primaries[1].x,
hdmi_metadata_type.display_primaries[1].y,
hdmi_metadata_type.display_primaries[2].x,
hdmi_metadata_type.display_primaries[2].y,
hdmi_metadata_type.white_point.x,
hdmi_metadata_type.white_point.y,
hdmi_metadata_type.max_display_mastering_luminance,
hdmi_metadata_type.min_display_mastering_luminance,
hdmi_metadata_type.max_cll,
hdmi_metadata_type.max_fall);
#ifdef ANDROID_S
hdr_metadata_infoframe &last_hdmi_metadata_type = last_hdr_metadata_.hdmi_metadata_type1;
#elif ANDROID_P
hdr_metadata_infoframe &last_hdmi_metadata_type = last_hdr_metadata_.hdmi_metadata_type1;
#else
hdr_metadata_infoframe &last_hdmi_metadata_type = last_hdr_metadata_.hdmi_metadata_type;
#endif
DrmColorspaceType colorspace = DrmColorspaceType::DEFAULT;
// DrmVersion=3 is Kernel 5.10 Support all DrmColorspaceType
if(color_prim == COLOR_PRIM_BT2020){
if(drm_->getDrmVersion() == 3){
if(uColorFormat_ == output_rgb){
colorspace = DrmColorspaceType::BT2020_RGB;
} else {
colorspace = DrmColorspaceType::BT2020_YCC;
}
}else{ // Kernel 4.19 only support BT2020_RGB
colorspace = DrmColorspaceType::BT2020_RGB;
}
}else{
colorspace = DrmColorspaceType::DEFAULT;
}
int color_depth = is_10bit ? depth_30bit : depth_24bit;
if(last_hdmi_metadata_type.eotf == hdmi_metadata_type.eotf &&
colorspace_ == colorspace &&
uColorDepth_ == color_depth &&
!memcmp(&last_hdr_metadata_, hdr_metadata, sizeof(struct hdr_output_metadata))){
HWC2_ALOGD_IF_DEBUG("eotf / colorspace / color_depth / hdr_output_metadata is same, skip update.");
return 0;
}
// 释放上一次的 Blob
if (blob_id_){
drm_->DestroyPropertyBlob(blob_id_);
blob_id_ = 0;
}
int ret = -1;
if(hdr_metadata_property().id()){
HWC2_ALOGD_IF_DEBUG("hdr_metadata eotf=0x%x", hdmi_metadata_type.eotf);
drm_->CreatePropertyBlob(hdr_metadata, sizeof(struct hdr_output_metadata), &blob_id_);
ret = drmModeAtomicAddProperty(pset, id(), hdr_metadata_property().id(), blob_id_);
if (ret < 0) {
HWC2_ALOGE("Failed to add prop[%d] to [%d]", hdr_metadata_property().id(), id());
}
}
if(colorspace_property().id()){
HWC2_ALOGD_IF_DEBUG("change %s colorspace=%d",
((colorspace == DrmColorspaceType::DEFAULT) ? "bt709" : "bt2020"), colorspace);
ret = drmModeAtomicAddProperty(pset, id(), colorspace_property().id(), colorspace);
if (ret < 0) {
HWC2_ALOGE("Failed to add prop[%d] to [%d]", colorspace_property().id(), id());
}
}
// TODO: SDR 模式不去修改 color depth
// 2:自动模式: 电视支持 HDR模式播放HDR视频则切换HDR模式否则使用SDR模式
// 1:HDR模式: 等同自动模式
// 0:SDR模式: 电视强制使用SDR模式HDR片源也采用SDR显示
if(hwc_get_int_property("persist.sys.vivid.hdr_mode", "2") == 0 || hdmi_metadata_type.eotf == TRADITIONAL_GAMMA_SDR){
UpdateOutputFormat(pset);
}else{
HWC2_ALOGD_IF_DEBUG("change hdmi output format: %d", uColorFormat_);
ret = drmModeAtomicAddProperty(pset, id(), color_format_property().id(), uColorFormat_);
if (ret < 0) {
HWC2_ALOGE("Failed to add prop[%d] to [%d]", color_format_property().id(), id());
}
HWC2_ALOGD_IF_DEBUG("change hdmi output depth: %d", color_depth);
ret = drmModeAtomicAddProperty(pset, id(), color_depth_property().id(), color_depth);
if (ret < 0) {
HWC2_ALOGE("Failed to add prop[%d] to [%d]", color_depth_property().id(), id());
}
}
memcpy(&last_hdr_metadata_, hdr_metadata, sizeof(struct hdr_output_metadata));
colorspace_ = colorspace;
uColorDepth_ = color_depth;
return 0;
}
const DrmProperty &DrmConnector::brightness_id_property() const {
return brightness_id_property_;
}
const DrmProperty &DrmConnector::contrast_id_property() const {
return contrast_id_property_;
}
const DrmProperty &DrmConnector::saturation_id_property() const {
return saturation_id_property_;
}
const DrmProperty &DrmConnector::hue_id_property() const {
return hue_id_property_;
}
const DrmProperty &DrmConnector::hdr_metadata_property() const {
return hdr_metadata_property_;
}
const DrmProperty &DrmConnector::hdr_panel_property() const {
return hdr_panel_property_;
}
const DrmProperty &DrmConnector::colorspace_property() const {
return colorspace_property_;
}
const DrmProperty &DrmConnector::color_format_property() const {
return color_format_property_;
}
const DrmProperty &DrmConnector::color_depth_property() const {
return color_depth_property_;
}
int DrmConnector::GetSpiltModeId() const {
return (display_ + DRM_CONNECTOR_SPILT_MODE_MASK);
}
bool DrmConnector::isHorizontalSpilt() const {
return bHorizontalSpilt_;
}
int DrmConnector::setHorizontalSpilt(){
bHorizontalSpilt_ = true;
return 0;
}
bool DrmConnector::isCropSpilt() const {
return bCropSpilt_;
}
int DrmConnector::setCropSpiltPrimary(){
bSpiltPrimary_ = true;
return 0;
}
bool DrmConnector::IsSpiltPrimary(){
return bSpiltPrimary_;
}
int DrmConnector::setCropSpilt(int32_t fbWidth,
int32_t fbHeight,
int32_t srcX,
int32_t srcY,
int32_t srcW,
int32_t srcH){
bCropSpilt_ = true;
FbWidth_ = fbWidth;
FbHeight_ = fbHeight;
SrcX_ = srcX;
SrcY_ = srcY;
SrcW_ = srcW;
SrcH_ = srcH;
return 0;
}
int DrmConnector::getCropSpiltFb(int32_t *fbWidth, int32_t *fbHeight){
*fbWidth = FbWidth_;
*fbHeight = FbHeight_;
return 0;
}
int DrmConnector::getCropInfo(int32_t *srcX, int32_t *srcY, int32_t *srcW, int32_t *srcH){
*srcX = SrcX_;
*srcY = SrcY_;
*srcW = SrcW_;
*srcH = SrcH_;
return 0;
}
} // namespace android