Merge "common: Do not enable QTI_BSP flag" into display.lnx.3.0-dev
diff --git a/libqdutils/display_config.cpp b/libqdutils/display_config.cpp
index 1470223..3415ac6 100644
--- a/libqdutils/display_config.cpp
+++ b/libqdutils/display_config.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2014 The Linux Foundation. All rights reserved.
+* Copyright (c) 2013-2014, 2016, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -253,6 +253,7 @@
dpyattr.xdpi = outParcel.readFloat();
dpyattr.ydpi = outParcel.readFloat();
dpyattr.panel_type = (char) outParcel.readInt32();
+ dpyattr.is_yuv = outParcel.readInt32();
ALOGI("%s() Received attrs for index %d: xres %d, yres %d",
__FUNCTION__, configIndex, dpyattr.xres, dpyattr.yres);
} else {
diff --git a/libqdutils/display_config.h b/libqdutils/display_config.h
index 05a7f29..15aba94 100644
--- a/libqdutils/display_config.h
+++ b/libqdutils/display_config.h
@@ -85,8 +85,9 @@
float xdpi;
float ydpi;
char panel_type;
+ bool is_yuv;
DisplayAttributes() : vsync_period(0), xres(0), yres(0), xdpi(0.0f),
- ydpi(0.0f), panel_type(0) {}
+ ydpi(0.0f), panel_type(0), is_yuv(false) {}
} DisplayAttributes_t;
//=============================================================================
diff --git a/libqdutils/qdMetaData.cpp b/libqdutils/qdMetaData.cpp
index 79daa14..72edfdf 100644
--- a/libqdutils/qdMetaData.cpp
+++ b/libqdutils/qdMetaData.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -67,7 +67,7 @@
data->bufferDim = *((BufferDim_t *)param);
break;
case UPDATE_REFRESH_RATE:
- data->refreshrate = *((uint32_t *)param);
+ data->refreshrate = *((float *)param);
break;
case UPDATE_COLOR_SPACE:
data->colorSpace = *((ColorSpace_t *)param);
@@ -96,3 +96,106 @@
errno);
return 0;
}
+
+int getMetaData(private_handle_t *handle, DispFetchParamType paramType,
+ void *param) {
+ if (!handle) {
+ ALOGE("%s: Private handle is null!", __func__);
+ return -1;
+ }
+ if (handle->fd_metadata == -1) {
+ ALOGE("%s: Bad fd for extra data!", __func__);
+ return -1;
+ }
+ if (!param) {
+ ALOGE("%s: input param is null!", __func__);
+ return -1;
+ }
+ unsigned long size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
+ void *base = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED,
+ handle->fd_metadata, 0);
+ if (base == reinterpret_cast<void*>(MAP_FAILED)) {
+ ALOGE("%s: mmap() failed: error is %s!", __func__, strerror(errno));
+ return -1;
+ }
+
+ MetaData_t *data = reinterpret_cast <MetaData_t *>(base);
+ data->operation |= paramType;
+ switch (paramType) {
+ case GET_PP_PARAM_INTERLACED:
+ *((int32_t *)param) = data->interlaced;
+ break;
+ case GET_BUFFER_GEOMETRY:
+ *((BufferDim_t *)param) = data->bufferDim;
+ break;
+ case GET_REFRESH_RATE:
+ *((float *)param) = data->refreshrate;
+ break;
+ case GET_COLOR_SPACE:
+ *((ColorSpace_t *)param) = data->colorSpace;
+ break;
+ case GET_MAP_SECURE_BUFFER:
+ *((int32_t *)param) = data->mapSecureBuffer;
+ break;
+ case GET_S3D_FORMAT:
+ *((uint32_t *)param) = data->s3dFormat;
+ break;
+ case GET_LINEAR_FORMAT:
+ *((uint32_t *)param) = data->linearFormat;
+ break;
+ case GET_IGC:
+ *((IGC_t *)param) = data->igc;
+ break;
+ case GET_SINGLE_BUFFER_MODE:
+ *((uint32_t *)param) = data->isSingleBufferMode ;
+ break;
+ default:
+ ALOGE("Unknown paramType %d", paramType);
+ break;
+ }
+ if(munmap(base, size))
+ ALOGE("%s: failed to unmap ptr %p, err %d", __func__, (void*)base,
+ errno);
+ return 0;
+}
+
+int copyMetaData(struct private_handle_t *src, struct private_handle_t *dst) {
+ if (!src || !dst) {
+ ALOGE("%s: Private handle is null!", __func__);
+ return -1;
+ }
+ if (src->fd_metadata == -1) {
+ ALOGE("%s: Bad fd for src extra data!", __func__);
+ return -1;
+ }
+ if (dst->fd_metadata == -1) {
+ ALOGE("%s: Bad fd for dst extra data!", __func__);
+ return -1;
+ }
+
+ unsigned long size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
+
+ void *base_src = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED,
+ src->fd_metadata, 0);
+ if (base_src == reinterpret_cast<void*>(MAP_FAILED)) {
+ ALOGE("%s: src mmap() failed: error is %s!", __func__, strerror(errno));
+ return -1;
+ }
+
+ void *base_dst = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED,
+ dst->fd_metadata, 0);
+ if (base_dst == reinterpret_cast<void*>(MAP_FAILED)) {
+ ALOGE("%s: dst mmap() failed: error is %s!", __func__, strerror(errno));
+ return -1;
+ }
+
+ memcpy(base_dst, base_src, size);
+
+ if(munmap(base_src, size))
+ ALOGE("%s: failed to unmap src ptr %p, err %d", __func__, (void*)base_src,
+ errno);
+ if(munmap(base_dst, size))
+ ALOGE("%s: failed to unmap src ptr %p, err %d", __func__, (void*)base_dst,
+ errno);
+ return 0;
+}
diff --git a/libqdutils/qdMetaData.h b/libqdutils/qdMetaData.h
index a1d9350..fd4f444 100644
--- a/libqdutils/qdMetaData.h
+++ b/libqdutils/qdMetaData.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -61,7 +61,7 @@
int32_t operation;
int32_t interlaced;
struct BufferDim_t bufferDim;
- uint32_t refreshrate;
+ float refreshrate;
enum ColorSpace_t colorSpace;
enum IGC_t igc;
/* Gralloc sets PRIV_SECURE_BUFFER flag to inform that the buffers are from
@@ -99,10 +99,26 @@
SET_SINGLE_BUFFER_MODE = 0x4000,
};
+enum DispFetchParamType {
+ GET_PP_PARAM_INTERLACED = 0x0004,
+ GET_BUFFER_GEOMETRY = 0x0080,
+ GET_REFRESH_RATE = 0x0100,
+ GET_COLOR_SPACE = 0x0200,
+ GET_MAP_SECURE_BUFFER = 0x400,
+ GET_S3D_FORMAT = 0x800,
+ GET_LINEAR_FORMAT = 0x1000,
+ GET_IGC = 0x2000,
+ GET_SINGLE_BUFFER_MODE = 0x4000,
+};
+
struct private_handle_t;
int setMetaData(struct private_handle_t *handle, enum DispParamType paramType,
void *param);
+int getMetaData(struct private_handle_t *handle, enum DispFetchParamType paramType,
+ void *param);
+
+int copyMetaData(struct private_handle_t *src, struct private_handle_t *dst);
#ifdef __cplusplus
}
#endif
diff --git a/sdm/include/core/display_interface.h b/sdm/include/core/display_interface.h
index a74b34b..adb1851 100644
--- a/sdm/include/core/display_interface.h
+++ b/sdm/include/core/display_interface.h
@@ -96,6 +96,7 @@
float y_dpi = 0.0f; //!< Dots per inch in Y-direction.
uint32_t fps = 0; //!< Frame rate per second.
uint32_t vsync_period_ns = 0; //!< VSync period in nanoseconds.
+ bool is_yuv = false; //!< If the display output is in YUV format.
};
/*! @brief Event data associated with VSync event.
diff --git a/sdm/include/private/hw_info_types.h b/sdm/include/private/hw_info_types.h
index 38ccf21..bc5361c 100644
--- a/sdm/include/private/hw_info_types.h
+++ b/sdm/include/private/hw_info_types.h
@@ -455,7 +455,8 @@
(vsync_period_ns != attributes.vsync_period_ns) ||
(v_front_porch != attributes.v_front_porch) ||
(v_back_porch != attributes.v_back_porch) ||
- (v_pulse_width != attributes.v_pulse_width));
+ (v_pulse_width != attributes.v_pulse_width) ||
+ (is_yuv != attributes.is_yuv));
}
bool operator ==(const HWDisplayAttributes &attributes) {
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index 33ee08d..5df06f6 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -52,10 +52,9 @@
hw_panel_info_ = HWPanelInfo();
hw_intf_->GetHWPanelInfo(&hw_panel_info_);
- HWDisplayAttributes display_attrib;
uint32_t active_index = 0;
hw_intf_->GetActiveConfig(&active_index);
- hw_intf_->GetDisplayAttributes(active_index, &display_attrib);
+ hw_intf_->GetDisplayAttributes(active_index, &display_attributes_);
HWScaleLutInfo lut_info = {};
error = comp_manager_->GetScaleLutConfig(&lut_info);
@@ -67,7 +66,7 @@
goto CleanupOnError;
}
- error = comp_manager_->RegisterDisplay(display_type_, display_attrib,
+ error = comp_manager_->RegisterDisplay(display_type_, display_attributes_,
hw_panel_info_, &display_comp_ctx_);
if (error != kErrorNone) {
goto CleanupOnError;
@@ -92,7 +91,7 @@
}
color_mgr_ = ColorManagerProxy::CreateColorManagerProxy(display_type_, hw_intf_,
- display_attrib, hw_panel_info_);
+ display_attributes_, hw_panel_info_);
if (!color_mgr_) {
DLOGW("Unable to create ColorManagerProxy for display = %d", display_type_);
}
@@ -202,6 +201,10 @@
}
}
+ if (one_frame_full_roi_) {
+ ControlPartialUpdate(false, &pending);
+ }
+
// Clean hw layers for reuse.
hw_layers_ = HWLayers();
hw_layers_.info.stack = layer_stack;
@@ -245,6 +248,11 @@
ControlPartialUpdate(true, &pending);
}
+ if (one_frame_full_roi_) {
+ ControlPartialUpdate(true, &pending);
+ one_frame_full_roi_ = false;
+ }
+
return error;
}
@@ -467,6 +475,8 @@
return error;
}
+ hw_intf_->GetHWPanelInfo(&hw_panel_info_);
+
if (display_comp_ctx_) {
comp_manager_->UnregisterDisplay(display_comp_ctx_);
}
@@ -474,6 +484,10 @@
error = comp_manager_->RegisterDisplay(display_type_, attrib, hw_panel_info_,
&display_comp_ctx_);
+ if (error == kErrorNone && partial_update_control_) {
+ one_frame_full_roi_ = true;
+ }
+
return error;
}
diff --git a/sdm/libs/core/display_base.h b/sdm/libs/core/display_base.h
index 7242156..c290e96 100644
--- a/sdm/libs/core/display_base.h
+++ b/sdm/libs/core/display_base.h
@@ -89,6 +89,7 @@
HWDeviceType hw_device_type_;
HWInterface *hw_intf_ = NULL;
HWPanelInfo hw_panel_info_;
+ HWDisplayAttributes display_attributes_;
BufferSyncHandler *buffer_sync_handler_ = NULL;
CompManager *comp_manager_ = NULL;
RotatorInterface *rotator_intf_ = NULL;
@@ -108,6 +109,7 @@
HWEventsInterface *hw_events_intf_ = NULL;
private:
+ bool one_frame_full_roi_ = false;
// Unused
virtual DisplayError GetConfig(DisplayConfigFixedInfo *variable_info) {
return kErrorNone;
diff --git a/sdm/libs/core/display_hdmi.cpp b/sdm/libs/core/display_hdmi.cpp
index 6522377..9a9628a 100644
--- a/sdm/libs/core/display_hdmi.cpp
+++ b/sdm/libs/core/display_hdmi.cpp
@@ -190,12 +190,31 @@
DisplayError DisplayHDMI::GetRefreshRateRange(uint32_t *min_refresh_rate,
uint32_t *max_refresh_rate) {
SCOPE_LOCK(locker_);
- return DisplayBase::GetRefreshRateRange(min_refresh_rate, max_refresh_rate);
+ DisplayError error = kErrorNone;
+
+ if (hw_panel_info_.min_fps && hw_panel_info_.max_fps) {
+ *min_refresh_rate = hw_panel_info_.min_fps;
+ *max_refresh_rate = hw_panel_info_.max_fps;
+ } else {
+ error = DisplayBase::GetRefreshRateRange(min_refresh_rate, max_refresh_rate);
+ }
+
+ return error;
}
DisplayError DisplayHDMI::SetRefreshRate(uint32_t refresh_rate) {
SCOPE_LOCK(locker_);
- return kErrorNotSupported;
+
+ if (!active_) {
+ return kErrorPermission;
+ }
+
+ DisplayError error = hw_intf_->SetRefreshRate(refresh_rate);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ return kErrorNone;
}
bool DisplayHDMI::IsUnderscanSupported() {
@@ -358,9 +377,10 @@
hw_intf_->GetActiveConfig(&active_index);
hw_intf_->GetDisplayAttributes(active_index, &display_attributes);
- if (panel_info != hw_panel_info_) {
+ if (panel_info != hw_panel_info_ || display_attributes != display_attributes_) {
comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes, panel_info);
hw_panel_info_ = panel_info;
+ display_attributes_ = display_attributes;
}
}
diff --git a/sdm/libs/core/fb/hw_hdmi.cpp b/sdm/libs/core/fb/hw_hdmi.cpp
index 73a6a3c..db7a2d9 100644
--- a/sdm/libs/core/fb/hw_hdmi.cpp
+++ b/sdm/libs/core/fb/hw_hdmi.cpp
@@ -260,6 +260,7 @@
}
GetDisplayS3DSupport(index, display_attributes);
+ display_attributes->is_yuv = IS_BIT_SET(timing_mode->pixel_formats, 1);
return kErrorNone;
}
@@ -317,6 +318,8 @@
active_config_index_ = index;
+ frame_rate_ = timing_mode->refresh_rate;
+
// Get the supported s3d modes for current active config index
HWDisplayAttributes attrib;
GetDisplayS3DSupport(index, &attrib);
@@ -696,5 +699,61 @@
return kErrorNone;
}
+DisplayError HWHDMI::SetRefreshRate(uint32_t refresh_rate) {
+ char mode_path[kMaxStringLength] = {0};
+ char node_path[kMaxStringLength] = {0};
+ uint32_t mode = kModeHFP;
+
+ if (refresh_rate == frame_rate_) {
+ return kErrorNone;
+ }
+
+ snprintf(mode_path, sizeof(mode_path), "%s%d/msm_fb_dfps_mode", fb_path_, fb_node_index_);
+ snprintf(node_path, sizeof(node_path), "%s%d/dynamic_fps", fb_path_, fb_node_index_);
+
+ int fd_mode = Sys::open_(mode_path, O_WRONLY);
+ if (fd_mode < 0) {
+ DLOGE("Failed to open %s with error %s", node_path, strerror(errno));
+ return kErrorFileDescriptor;
+ }
+
+ char dfps_mode[kMaxStringLength];
+ snprintf(dfps_mode, sizeof(dfps_mode), "%d", mode);
+ DLOGI_IF(kTagDriverConfig, "Setting dfps_mode = %d", mode);
+ ssize_t len = Sys::pwrite_(fd_mode, dfps_mode, strlen(dfps_mode), 0);
+ if (len < 0) {
+ DLOGE("Failed to enable dfps mode %d with error %s", mode, strerror(errno));
+ Sys::close_(fd_mode);
+ return kErrorUndefined;
+ }
+ Sys::close_(fd_mode);
+
+ int fd_node = Sys::open_(node_path, O_WRONLY);
+ if (fd_node < 0) {
+ DLOGE("Failed to open %s with error %s", node_path, strerror(errno));
+ return kErrorFileDescriptor;
+ }
+
+ char refresh_rate_string[kMaxStringLength];
+ snprintf(refresh_rate_string, sizeof(refresh_rate_string), "%d", refresh_rate);
+ DLOGI_IF(kTagDriverConfig, "Setting refresh rate = %d", refresh_rate);
+ len = Sys::pwrite_(fd_node, refresh_rate_string, strlen(refresh_rate_string), 0);
+ if (len < 0) {
+ DLOGE("Failed to write %d with error %s", refresh_rate, strerror(errno));
+ Sys::close_(fd_node);
+ return kErrorUndefined;
+ }
+ Sys::close_(fd_node);
+
+ DisplayError error = ReadTimingInfo();
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ frame_rate_ = refresh_rate;
+
+ return kErrorNone;
+}
+
} // namespace sdm
diff --git a/sdm/libs/core/fb/hw_hdmi.h b/sdm/libs/core/fb/hw_hdmi.h
index 50bbbaa..aa5e2a0 100644
--- a/sdm/libs/core/fb/hw_hdmi.h
+++ b/sdm/libs/core/fb/hw_hdmi.h
@@ -40,6 +40,18 @@
static DisplayError Destroy(HWInterface *intf);
protected:
+ enum HWFramerateUpdate {
+ // Switch framerate by switch to other standard modes though panel blank/unblank
+ kModeSuspendResume,
+ // Switch framerate by tuning pixel clock
+ kModeClock,
+ // Switch framerate by tuning vertical front porch
+ kModeVFP,
+ // Switch framerate by tuning horizontal front porch
+ kModeHFP,
+ kModeMAX
+ };
+
HWHDMI(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf);
virtual DisplayError Init();
virtual DisplayError Deinit();
@@ -56,6 +68,7 @@
virtual DisplayError GetConfigIndex(uint32_t mode, uint32_t *index);
virtual DisplayError Validate(HWLayers *hw_layers);
virtual DisplayError SetS3DMode(HWS3DMode s3d_mode);
+ virtual DisplayError SetRefreshRate(uint32_t refresh_rate);
private:
DisplayError ReadEDIDInfo();
@@ -80,6 +93,7 @@
std::map<HWS3DMode, msm_hdmi_s3d_mode> s3d_mode_sdm_to_mdp_;
std::vector<HWS3DMode> supported_s3d_modes_;
int active_mdp_s3d_mode_ = HDMI_S3D_NONE;
+ uint32_t frame_rate_ = 0;
};
} // namespace sdm
diff --git a/sdm/libs/hwc/hwc_display.cpp b/sdm/libs/hwc/hwc_display.cpp
index ab9b4a7..29e0c1a 100644
--- a/sdm/libs/hwc/hwc_display.cpp
+++ b/sdm/libs/hwc/hwc_display.cpp
@@ -537,11 +537,7 @@
layer_stack_.flags.cursor_present = true;
}
- if (layer->frame_rate > metadata_refresh_rate_) {
- metadata_refresh_rate_ = SanitizeRefreshRate(layer->frame_rate);
- } else {
- layer->frame_rate = current_refresh_rate_;
- }
+ PrepareDynamicRefreshRate(layer);
layer->input_buffer->buffer_id = reinterpret_cast<uint64_t>(hwc_layer.handle);
}
@@ -1314,21 +1310,6 @@
}
}
-uint32_t HWCDisplay::RoundToStandardFPS(uint32_t fps) {
- static const uint32_t standard_fps[4] = {30, 24, 48, 60};
-
- int count = INT(sizeof(standard_fps) / sizeof(standard_fps[0]));
- for (int i = 0; i < count; i++) {
- if ((standard_fps[i] - fps) < 2) {
- // Most likely used for video, the fps can fluctuate
- // Ex: b/w 29 and 30 for 30 fps clip
- return standard_fps[i];
- }
- }
-
- return fps;
-}
-
void HWCDisplay::ApplyScanAdjustment(hwc_rect_t *display_frame) {
}
@@ -1510,6 +1491,35 @@
return (updating_count == 1);
}
+bool HWCDisplay::SingleVideoLayerUpdating(uint32_t app_layer_count) {
+ uint32_t updating_count = 0;
+
+ for (uint i = 0; i < app_layer_count; i++) {
+ Layer *layer = layer_stack_.layers[i];
+ if (layer->flags.updating && (layer->input_buffer->flags.video == true)) {
+ updating_count++;
+ }
+ }
+
+ return (updating_count == 1);
+}
+
+uint32_t HWCDisplay::RoundToStandardFPS(float fps) {
+ static const uint32_t standard_fps[4] = {30, 24, 48, 60};
+ uint32_t frame_rate = (uint32_t)(fps);
+
+ int count = INT(sizeof(standard_fps) / sizeof(standard_fps[0]));
+ for (int i = 0; i < count; i++) {
+ if ((standard_fps[i] - frame_rate) < 2) {
+ // Most likely used for video, the fps can fluctuate
+ // Ex: b/w 29 and 30 for 30 fps clip
+ return standard_fps[i];
+ }
+ }
+
+ return frame_rate;
+}
+
uint32_t HWCDisplay::SanitizeRefreshRate(uint32_t req_refresh_rate) {
uint32_t refresh_rate = req_refresh_rate;
@@ -1530,4 +1540,12 @@
return display_class_;
}
+void HWCDisplay::PrepareDynamicRefreshRate(Layer *layer) {
+ if (layer->frame_rate > metadata_refresh_rate_) {
+ metadata_refresh_rate_ = SanitizeRefreshRate(layer->frame_rate);
+ } else {
+ layer->frame_rate = current_refresh_rate_;
+ }
+}
+
} // namespace sdm
diff --git a/sdm/libs/hwc/hwc_display.h b/sdm/libs/hwc/hwc_display.h
index 7b14f10..17db165 100644
--- a/sdm/libs/hwc/hwc_display.h
+++ b/sdm/libs/hwc/hwc_display.h
@@ -149,6 +149,9 @@
virtual int CommitLayerStack(hwc_display_contents_1_t *content_list);
virtual int PostCommitLayerStack(hwc_display_contents_1_t *content_list);
virtual void DumpOutputBuffer(const BufferInfo& buffer_info, void *base, int fence);
+ virtual uint32_t RoundToStandardFPS(float fps);
+ virtual uint32_t SanitizeRefreshRate(uint32_t req_refresh_rate);
+ virtual void PrepareDynamicRefreshRate(Layer *layer);
inline void SetRect(const hwc_rect_t &source, LayerRect *target);
inline void SetRect(const hwc_frect_t &source, LayerRect *target);
inline void SetComposition(const int32_t &source, LayerComposition *target);
@@ -160,7 +163,6 @@
const char *GetDisplayString();
void ScaleDisplayFrame(hwc_rect_t *display_frame);
void MarkLayersForGPUBypass(hwc_display_contents_1_t *content_list);
- uint32_t RoundToStandardFPS(uint32_t fps);
virtual void ApplyScanAdjustment(hwc_rect_t *display_frame);
DisplayError SetCSC(ColorSpace_t source, LayerCSC *target);
DisplayError SetIGC(IGC_t source, LayerIGC *target);
@@ -169,7 +171,7 @@
void CacheLayerStackInfo(hwc_display_contents_1_t *content_list);
bool IsLayerUpdating(hwc_display_contents_1_t *content_list, int layer_index);
bool SingleLayerUpdating(uint32_t app_layer_count);
- uint32_t SanitizeRefreshRate(uint32_t req_refresh_rate);
+ bool SingleVideoLayerUpdating(uint32_t app_layer_count);
enum {
INPUT_LAYER_DUMP,
diff --git a/sdm/libs/hwc/hwc_display_external.cpp b/sdm/libs/hwc/hwc_display_external.cpp
index 813b123..a647517 100644
--- a/sdm/libs/hwc/hwc_display_external.cpp
+++ b/sdm/libs/hwc/hwc_display_external.cpp
@@ -49,6 +49,7 @@
HWCDisplay **hwc_display) {
uint32_t external_width = 0;
uint32_t external_height = 0;
+ int drc_enabled = 0;
HWCDisplay *hwc_display_external = new HWCDisplayExternal(core_intf, hwc_procs, qservice);
int status = hwc_display_external->Init();
@@ -80,6 +81,9 @@
return status;
}
+ HWCDebugHandler::Get()->GetProperty("sdm.hdmi.drc_enabled", &(drc_enabled));
+ reinterpret_cast<HWCDisplayExternal *>(hwc_display_external)->drc_enabled_ = drc_enabled;
+
*hwc_display = hwc_display_external;
return status;
@@ -98,6 +102,7 @@
int HWCDisplayExternal::Prepare(hwc_display_contents_1_t *content_list) {
int status = 0;
+ DisplayError error = kErrorNone;
if (secure_display_active_) {
MarkLayersForGPUBypass(content_list);
@@ -119,6 +124,18 @@
return 0;
}
+ bool one_video_updating_layer = SingleVideoLayerUpdating(UINT32(content_list->numHwLayers - 1));
+
+ if (current_refresh_rate_ != metadata_refresh_rate_ && one_video_updating_layer && drc_enabled_) {
+ error = display_intf_->SetRefreshRate(metadata_refresh_rate_);
+ }
+
+ if (error == kErrorNone) {
+ // On success, set current refresh rate to new refresh rate
+ current_refresh_rate_ = metadata_refresh_rate_;
+ }
+
+
status = PrepareLayerStack(content_list);
if (status) {
return status;
@@ -221,5 +238,36 @@
}
}
+uint32_t HWCDisplayExternal::RoundToStandardFPS(float fps) {
+ static const uint32_t standard_fps[] = {23976, 24000, 25000, 29970, 30000, 50000, 59940, 60000};
+ static const uint32_t mapping_fps[] = {59940, 60000, 60000, 59940, 60000, 50000, 59940, 60000};
+ uint32_t frame_rate = (uint32_t)(fps * 1000);
+
+ int count = INT(sizeof(standard_fps) / sizeof(standard_fps[0]));
+ for (int i = 0; i < count; i++) {
+ // Most likely used for video, the fps for frames should be stable from video side.
+ if (standard_fps[i] > frame_rate) {
+ if (i > 0) {
+ if ((standard_fps[i] - frame_rate) > (frame_rate - standard_fps[i-1])) {
+ return mapping_fps[i-1];
+ } else {
+ return mapping_fps[i];
+ }
+ } else {
+ return mapping_fps[i];
+ }
+ }
+ }
+
+ return standard_fps[count - 1];
+}
+
+void HWCDisplayExternal::PrepareDynamicRefreshRate(Layer *layer) {
+ if (layer->input_buffer->flags.video) {
+ metadata_refresh_rate_ = SanitizeRefreshRate(layer->frame_rate);
+ layer->frame_rate = current_refresh_rate_;
+ }
+}
+
} // namespace sdm
diff --git a/sdm/libs/hwc/hwc_display_external.h b/sdm/libs/hwc/hwc_display_external.h
index 436190d..c54f738 100644
--- a/sdm/libs/hwc/hwc_display_external.h
+++ b/sdm/libs/hwc/hwc_display_external.h
@@ -41,6 +41,11 @@
virtual int Commit(hwc_display_contents_1_t *content_list);
virtual void SetSecureDisplay(bool secure_display_active);
+ protected:
+ virtual uint32_t RoundToStandardFPS(float fps);
+ virtual void PrepareDynamicRefreshRate(Layer *layer);
+ int drc_enabled_ = 0;
+
private:
HWCDisplayExternal(CoreInterface *core_intf, hwc_procs_t const **hwc_procs,
qService::QService *qservice);
diff --git a/sdm/libs/hwc/hwc_session.cpp b/sdm/libs/hwc/hwc_session.cpp
index 7928765..9632d71 100644
--- a/sdm/libs/hwc/hwc_session.cpp
+++ b/sdm/libs/hwc/hwc_session.cpp
@@ -939,6 +939,7 @@
output_parcel->writeFloat(attributes.x_dpi);
output_parcel->writeFloat(attributes.y_dpi);
output_parcel->writeInt32(0); // Panel type, unsupported.
+ output_parcel->writeInt32(attributes.is_yuv);
}
}