Merge "gralloc1: Do not do early validation on Release"
diff --git a/libdrmutils/drm_interface.h b/libdrmutils/drm_interface.h
index ca2f6ff..4ecfcbf 100644
--- a/libdrmutils/drm_interface.h
+++ b/libdrmutils/drm_interface.h
@@ -138,6 +138,12 @@
*/
PLANE_SET_FB_SECURE_MODE,
/*
+ * Op: Sets csc config on this plane.
+ * Arg: uint32_t - Plane ID
+ * uint32_t* - pointer to csc type
+ */
+ PLANE_SET_CSC_CONFIG,
+ /*
* Op: Activate or deactivate a CRTC
* Arg: uint32_t - CRTC ID
* uint32_t - 1 to enable, 0 to disable
@@ -465,6 +471,15 @@
void *payload;
};
+enum DRMCscType {
+ kCscYuv2Rgb601L,
+ kCscYuv2Rgb601FR,
+ kCscYuv2Rgb709L,
+ kCscYuv2Rgb2020L,
+ kCscYuv2Rgb2020FR,
+ kCscTypeMax,
+};
+
struct DRMScalerLUTInfo {
uint32_t dir_lut_size = 0;
uint32_t cir_lut_size = 0;
diff --git a/libgralloc1/gr_buf_mgr.cpp b/libgralloc1/gr_buf_mgr.cpp
index bb37da0..d6753d8 100644
--- a/libgralloc1/gr_buf_mgr.cpp
+++ b/libgralloc1/gr_buf_mgr.cpp
@@ -278,13 +278,6 @@
} else {
private_handle_t *handle = const_cast<private_handle_t *>(hnd);
err = ImportHandleLocked(handle);
- if (err == GRALLOC1_ERROR_NONE) {
- // TODO(user): See bug 35955598
- if (hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
- return GRALLOC1_ERROR_NONE; // Don't map secure buffer
- }
- err = MapBuffer(hnd);
- }
}
return err;
}
@@ -709,6 +702,12 @@
return GRALLOC1_ERROR_BAD_HANDLE;
}
*flag = hnd->flags &private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
+ int linear_format = 0;
+ if (getMetaData(hnd, GET_LINEAR_FORMAT, &linear_format) == 0) {
+ if (!linear_format) {
+ *flag = 0;
+ }
+ }
} break;
case GRALLOC_MODULE_PERFORM_GET_RGB_DATA_ADDRESS: {
diff --git a/libgralloc1/gr_utils.cpp b/libgralloc1/gr_utils.cpp
index 560bb08..d89b8fe 100644
--- a/libgralloc1/gr_utils.cpp
+++ b/libgralloc1/gr_utils.cpp
@@ -357,29 +357,33 @@
bool interlaced = false;
memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
- MetaData_t *metadata = reinterpret_cast<MetaData_t *>(hnd->base_metadata);
// Check if UBWC buffer has been rendered in linear format.
- if (metadata && (metadata->operation & LINEAR_FORMAT)) {
- format = INT(metadata->linearFormat);
+ int linear_format = 0;
+ if (getMetaData(const_cast<private_handle_t *>(hnd),
+ GET_LINEAR_FORMAT, &linear_format) == 0) {
+ format = INT(linear_format);
}
// Check metadata if the geometry has been updated.
- if (metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
+ BufferDim_t buffer_dim;
+ if (getMetaData(const_cast<private_handle_t *>(hnd),
+ GET_BUFFER_GEOMETRY, &buffer_dim) == 0) {
int usage = 0;
-
if (hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
usage = GRALLOC1_PRODUCER_USAGE_PRIVATE_ALLOC_UBWC;
}
- BufferInfo info(metadata->bufferDim.sliceWidth, metadata->bufferDim.sliceHeight, format,
+ BufferInfo info(buffer_dim.sliceWidth, buffer_dim.sliceHeight, format,
prod_usage, cons_usage);
GetAlignedWidthAndHeight(info, &width, &height);
}
// Check metadata for interlaced content.
- if (metadata && (metadata->operation & PP_PARAM_INTERLACED)) {
- interlaced = metadata->interlaced ? true : false;
+ int interlace_flag = 0;
+ if (getMetaData(const_cast<private_handle_t *>(hnd),
+ GET_PP_PARAM_INTERLACED, &interlace_flag) != 0) {
+ interlaced = interlace_flag;
}
// Get the chroma offsets from the handle width/height. We take advantage
diff --git a/libgralloc1/gralloc_priv.h b/libgralloc1/gralloc_priv.h
index 87604c6..2abdd84 100644
--- a/libgralloc1/gralloc_priv.h
+++ b/libgralloc1/gralloc_priv.h
@@ -78,6 +78,7 @@
#define GRALLOC_USAGE_PRIVATE_IOMMU_HEAP GRALLOC1_PRODUCER_USAGE_PRIVATE_IOMMU_HEAP
#define GRALLOC_USAGE_PRIVATE_WFD GRALLOC1_CONSUMER_USAGE_PRIVATE_WFD
#define GRALLOC_USAGE_PRIVATE_CAMERA_HEAP GRALLOC1_PRODUCER_USAGE_PRIVATE_CAMERA_HEAP
+#define GRALLOC_USAGE_PRIVATE_SECURE_DISPLAY GRALLOC1_CONSUMER_USAGE_PRIVATE_SECURE_DISPLAY
#define GRALLOC_USAGE_PRIVATE_MM_HEAP 0x0
diff --git a/sdm/include/core/display_interface.h b/sdm/include/core/display_interface.h
index 524141e..b8e2a9e 100644
--- a/sdm/include/core/display_interface.h
+++ b/sdm/include/core/display_interface.h
@@ -135,6 +135,12 @@
kPortDP, // Display is connected to DP port.
};
+/*! @brief This enum represents the events received by Display HAL. */
+enum DisplayEvent {
+ kIdleTimeout, // Event triggered by Idle Timer.
+ kThermalEvent, // Event triggered by Thermal.
+};
+
/*! @brief This structure defines configuration for fixed properties of a display device.
@sa DisplayInterface::GetConfig
@@ -245,6 +251,9 @@
*/
virtual DisplayError CECMessage(char *message) = 0;
+ /*! @brief Event handler for events received by Display HAL. */
+ virtual DisplayError HandleEvent(DisplayEvent event) = 0;
+
protected:
virtual ~DisplayEventHandler() { }
};
diff --git a/sdm/include/core/sdm_types.h b/sdm/include/core/sdm_types.h
index ce356bf..72ad6b2 100644
--- a/sdm/include/core/sdm_types.h
+++ b/sdm/include/core/sdm_types.h
@@ -56,6 +56,7 @@
kErrorPerfValidation, //!< Bandwidth or Clock requirement validation failure.
kErrorNoAppLayers, //!< No App layer(s) in the draw cycle.
kErrorRotatorValidation, //!< Rotator configuration validation failure.
+ kErrorNotValidated, //!< Draw cycle has not been validated.
};
/*! @brief This structure is defined for client and library compatibility check purpose only. This
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index b76c3d1..538d38e 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -211,6 +211,7 @@
DisplayError DisplayBase::Prepare(LayerStack *layer_stack) {
lock_guard<recursive_mutex> obj(recursive_mutex_);
DisplayError error = kErrorNone;
+ needs_validate_ = true;
if (!active_) {
return kErrorPermission;
@@ -250,7 +251,7 @@
error = hw_intf_->Validate(&hw_layers_);
if (error == kErrorNone) {
// Strategy is successful now, wait for Commit().
- pending_commit_ = true;
+ needs_validate_ = false;
break;
}
if (error == kErrorShutDown) {
@@ -269,7 +270,7 @@
DisplayError error = kErrorNone;
if (!active_) {
- pending_commit_ = false;
+ needs_validate_ = true;
return kErrorPermission;
}
@@ -277,13 +278,11 @@
return kErrorParameters;
}
- if (!pending_commit_) {
+ if (needs_validate_) {
DLOGE("Commit: Corresponding Prepare() is not called for display = %d", display_type_);
- return kErrorUndefined;
+ return kErrorNotValidated;
}
- pending_commit_ = false;
-
// Layer stack attributes has changed, need to Reconfigure, currently in use for Hybrid Comp
if (layer_stack->flags.attributes_changed) {
error = comp_manager_->ReConfigure(display_comp_ctx_, &hw_layers_);
@@ -343,7 +342,7 @@
error = hw_intf_->Flush();
if (error == kErrorNone) {
comp_manager_->Purge(display_comp_ctx_);
- pending_commit_ = false;
+ needs_validate_ = true;
} else {
DLOGW("Unable to flush display = %d", display_type_);
}
diff --git a/sdm/libs/core/display_base.h b/sdm/libs/core/display_base.h
index 4023229..223e5eb 100644
--- a/sdm/libs/core/display_base.h
+++ b/sdm/libs/core/display_base.h
@@ -153,7 +153,7 @@
Handle hw_device_ = 0;
Handle display_comp_ctx_ = 0;
HWLayers hw_layers_;
- bool pending_commit_ = false;
+ bool needs_validate_ = true;
bool vsync_enable_ = false;
uint32_t max_mixer_stages_ = 0;
HWInfoInterface *hw_info_intf_ = NULL;
diff --git a/sdm/libs/core/display_primary.cpp b/sdm/libs/core/display_primary.cpp
index 52b71c7..64a0bcc 100644
--- a/sdm/libs/core/display_primary.cpp
+++ b/sdm/libs/core/display_primary.cpp
@@ -283,6 +283,7 @@
handle_idle_timeout_ = true;
event_handler_->Refresh();
comp_manager_->ProcessIdleTimeout(display_comp_ctx_);
+ event_handler_->HandleEvent(kIdleTimeout);
}
void DisplayPrimary::PingPongTimeout() {
@@ -293,6 +294,7 @@
void DisplayPrimary::ThermalEvent(int64_t thermal_level) {
lock_guard<recursive_mutex> obj(recursive_mutex_);
comp_manager_->ProcessThermalEvent(display_comp_ctx_, thermal_level);
+ event_handler_->HandleEvent(kThermalEvent);
}
void DisplayPrimary::IdlePowerCollapse() {
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index a5ed8a2..fa31a12 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -97,6 +97,7 @@
using sde_drm::DRMPowerMode;
using sde_drm::DRMSecureMode;
using sde_drm::DRMSecurityLevel;
+using sde_drm::DRMCscType;
namespace sdm {
@@ -328,7 +329,6 @@
HWInfoInterface *hw_info_intf)
: hw_info_intf_(hw_info_intf), buffer_sync_handler_(buffer_sync_handler),
registry_(buffer_allocator) {
- device_type_ = kDevicePrimary;
disp_type_ = DRMDisplayType::PERIPHERAL;
device_name_ = "Peripheral Display";
hw_info_intf_ = hw_info_intf;
@@ -343,31 +343,32 @@
drm_master->GetHandle(&dev_fd_);
DRMLibLoader::GetInstance()->FuncGetDRMManager()(dev_fd_, &drm_mgr_intf_);
if (drm_mgr_intf_->RegisterDisplay(disp_type_, &token_)) {
- DLOGE("RegisterDisplay failed for display %d", disp_type_);
+ DLOGE("RegisterDisplay failed for %s", device_name_);
return kErrorResources;
}
drm_mgr_intf_->CreateAtomicReq(token_, &drm_atomic_intf_);
drm_mgr_intf_->GetConnectorInfo(token_.conn_id, &connector_info_);
- InitializeConfigs();
- drm_atomic_intf_->Perform(DRMOps::CRTC_SET_MODE, token_.crtc_id, ¤t_mode_);
-
- drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 1);
// Commit to setup pipeline with mode, which then tells us the topology etc
-
if (!deferred_initialize_) {
+ drm_atomic_intf_->Perform(DRMOps::CRTC_SET_MODE, token_.crtc_id,
+ &connector_info_.modes[current_mode_index_]);
+ drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 1);
if (drm_atomic_intf_->Commit(true /* synchronous */)) {
DRM_LOGI("Setting up CRTC %d, Connector %d for %s failed", token_.crtc_id,
token_.conn_id, device_name_);
return kErrorResources;
}
// Reload connector info for updated info after 1st commit
-
drm_mgr_intf_->GetConnectorInfo(token_.conn_id, &connector_info_);
}
+ InitializeConfigs();
+ } else {
+ display_attributes_.push_back(HWDisplayAttributes());
+ PopulateDisplayAttributes(current_mode_index_);
}
- PopulateDisplayAttributes();
PopulateHWPanelInfo();
UpdateMixerAttributes();
+
hw_info_intf_->GetHWResourceInfo(&hw_resource_);
// TODO(user): In future, remove has_qseed3 member, add version and pass version to constructor
@@ -382,6 +383,7 @@
PowerOff();
delete hw_scale_;
registry_.Clear();
+ display_attributes_ = {};
drm_mgr_intf_->DestroyAtomicReq(drm_atomic_intf_);
drm_atomic_intf_ = {};
drm_mgr_intf_->UnregisterDisplay(token_);
@@ -389,15 +391,27 @@
}
void HWDeviceDRM::InitializeConfigs() {
- // TODO(user): Update modes
- current_mode_ = connector_info_.modes[0];
+ // TODO(user): Choose Best Mode
+ current_mode_index_ = 0;
+ display_attributes_.resize(connector_info_.modes.size());
+
+ uint32_t width = connector_info_.modes[current_mode_index_].hdisplay;
+ uint32_t height = connector_info_.modes[current_mode_index_].vdisplay;
+ for (uint32_t i = 0; i < connector_info_.modes.size(); i++) {
+ auto &mode = connector_info_.modes[i];
+ if (mode.hdisplay != width || mode.vdisplay != height) {
+ resolution_switch_enabled_ = true;
+ }
+ PopulateDisplayAttributes(i);
+ }
}
-DisplayError HWDeviceDRM::PopulateDisplayAttributes() {
+DisplayError HWDeviceDRM::PopulateDisplayAttributes(uint32_t index) {
drmModeModeInfo mode = {};
uint32_t mm_width = 0;
uint32_t mm_height = 0;
DRMTopology topology = DRMTopology::SINGLE_LM;
+ bool dual_display = false;
if (default_mode_) {
DRMResMgr *res_mgr = nullptr;
@@ -410,16 +424,17 @@
res_mgr->GetMode(&mode);
res_mgr->GetDisplayDimInMM(&mm_width, &mm_height);
} else {
- mode = current_mode_;
+ mode = connector_info_.modes[index];
mm_width = connector_info_.mmWidth;
mm_height = connector_info_.mmHeight;
topology = connector_info_.topology;
}
- display_attributes_.x_pixels = mode.hdisplay;
- display_attributes_.y_pixels = mode.vdisplay;
- display_attributes_.fps = mode.vrefresh;
- display_attributes_.vsync_period_ns = UINT32(1000000000L / display_attributes_.fps);
+ display_attributes_[index].x_pixels = mode.hdisplay;
+ display_attributes_[index].y_pixels = mode.vdisplay;
+ display_attributes_[index].fps = mode.vrefresh;
+ display_attributes_[index].vsync_period_ns =
+ UINT32(1000000000L / display_attributes_[index].fps);
/*
Active Front Sync Back
@@ -431,18 +446,19 @@
<-------------------------------- [hv]total ----------------------------->
*/
- display_attributes_.v_front_porch = mode.vsync_start - mode.vdisplay;
- display_attributes_.v_pulse_width = mode.vsync_end - mode.vsync_start;
- display_attributes_.v_back_porch = mode.vtotal - mode.vsync_end;
- display_attributes_.v_total = mode.vtotal;
-
- display_attributes_.h_total = mode.htotal;
+ display_attributes_[index].v_front_porch = mode.vsync_start - mode.vdisplay;
+ display_attributes_[index].v_pulse_width = mode.vsync_end - mode.vsync_start;
+ display_attributes_[index].v_back_porch = mode.vtotal - mode.vsync_end;
+ display_attributes_[index].v_total = mode.vtotal;
+ display_attributes_[index].h_total = mode.htotal;
uint32_t h_blanking = mode.htotal - mode.hdisplay;
- display_attributes_.is_device_split =
+ display_attributes_[index].is_device_split =
(topology == DRMTopology::DUAL_LM || topology == DRMTopology::DUAL_LM_MERGE ||
topology == DRMTopology::DUAL_LM_MERGE_DSC || topology == DRMTopology::DUAL_LM_DSC ||
topology == DRMTopology::DUAL_LM_DSCMERGE);
- display_attributes_.h_total += display_attributes_.is_device_split ? h_blanking : 0;
+ dual_display = (topology == DRMTopology::DUAL_LM || topology == DRMTopology::DUAL_LM_DSC ||
+ topology == DRMTopology::PPSPLIT);
+ display_attributes_[index].h_total += dual_display ? h_blanking : 0;
// If driver doesn't return panel width/height information, default to 320 dpi
if (INT(mm_width) <= 0 || INT(mm_height) <= 0) {
@@ -451,8 +467,17 @@
DLOGW("Driver doesn't report panel physical width and height - defaulting to 320dpi");
}
- display_attributes_.x_dpi = (FLOAT(mode.hdisplay) * 25.4f) / FLOAT(mm_width);
- display_attributes_.y_dpi = (FLOAT(mode.vdisplay) * 25.4f) / FLOAT(mm_height);
+ display_attributes_[index].x_dpi = (FLOAT(mode.hdisplay) * 25.4f) / FLOAT(mm_width);
+ display_attributes_[index].y_dpi = (FLOAT(mode.vdisplay) * 25.4f) / FLOAT(mm_height);
+
+ DLOGI("Display attributes[%d]: WxH: %dx%d, DPI: %fx%f, FPS: %d, LM_SPLIT: %d, V_BACK_PORCH: %d," \
+ " V_FRONT_PORCH: %d, V_PULSE_WIDTH: %d, V_TOTAL: %d, H_TOTAL: %d, TOPOLOGY: %d", index,
+ display_attributes_[index].x_pixels, display_attributes_[index].y_pixels,
+ display_attributes_[index].x_dpi, display_attributes_[index].y_dpi,
+ display_attributes_[index].fps, display_attributes_[index].is_device_split,
+ display_attributes_[index].v_back_porch, display_attributes_[index].v_front_porch,
+ display_attributes_[index].v_pulse_width, display_attributes_[index].v_total,
+ display_attributes_[index].h_total, topology);
return kErrorNone;
}
@@ -462,11 +487,8 @@
snprintf(hw_panel_info_.panel_name, sizeof(hw_panel_info_.panel_name), "%s",
connector_info_.panel_name.c_str());
- hw_panel_info_.split_info.left_split = display_attributes_.x_pixels;
- if (display_attributes_.is_device_split) {
- hw_panel_info_.split_info.left_split = hw_panel_info_.split_info.right_split =
- display_attributes_.x_pixels / 2;
- }
+
+ UpdatePanelSplitInfo();
hw_panel_info_.partial_update = connector_info_.num_roi;
hw_panel_info_.left_roi_count = UINT32(connector_info_.num_roi);
@@ -587,18 +609,25 @@
}
DisplayError HWDeviceDRM::GetActiveConfig(uint32_t *active_config) {
- *active_config = 0;
+ *active_config = current_mode_index_;
return kErrorNone;
}
DisplayError HWDeviceDRM::GetNumDisplayAttributes(uint32_t *count) {
- *count = 1;
+ *count = UINT32(display_attributes_.size());
+ if (*count <= 0) {
+ return kErrorHardware;
+ }
return kErrorNone;
}
DisplayError HWDeviceDRM::GetDisplayAttributes(uint32_t index,
- HWDisplayAttributes *display_attributes) {
- *display_attributes = display_attributes_;
+ HWDisplayAttributes *display_attributes) {
+ if (index >= display_attributes_.size()) {
+ return kErrorParameters;
+ }
+
+ *display_attributes = display_attributes_[index];
return kErrorNone;
}
@@ -608,6 +637,20 @@
}
DisplayError HWDeviceDRM::SetDisplayAttributes(uint32_t index) {
+ if (index >= display_attributes_.size()) {
+ return kErrorParameters;
+ }
+
+ drm_atomic_intf_->Perform(DRMOps::CRTC_SET_MODE, token_.crtc_id, &connector_info_.modes[index]);
+ drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 1);
+
+ current_mode_index_ = index;
+ UpdatePanelSplitInfo();
+ UpdateMixerAttributes();
+
+ DLOGI("Setting mode index %d for CRTC %d, Connector %d display %s is successful", index,
+ token_.crtc_id, token_.conn_id, device_name_);
+
return kErrorNone;
}
@@ -630,7 +673,7 @@
drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_POWER_MODE, token_.conn_id, DRMPowerMode::ON);
int ret = drm_atomic_intf_->Commit(false /* synchronous */);
if (ret) {
- DLOGE("%s failed with error %d", __FUNCTION__, ret);
+ DLOGE("Failed with error: %d", ret);
return kErrorHardware;
}
return kErrorNone;
@@ -646,14 +689,21 @@
drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 0);
int ret = drm_atomic_intf_->Commit(false /* synchronous */);
if (ret) {
- DLOGE("%s failed with error %d", __FUNCTION__, ret);
+ DLOGE("Failed with error: %d", ret);
return kErrorHardware;
}
return kErrorNone;
}
DisplayError HWDeviceDRM::Doze() {
+ drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 1);
drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_POWER_MODE, token_.conn_id, DRMPowerMode::DOZE);
+ int ret = drm_atomic_intf_->Commit(false /* synchronous */);
+ if (ret) {
+ DLOGE("Failed with error: %d", ret);
+ return kErrorHardware;
+ }
+
return kErrorNone;
}
@@ -676,6 +726,7 @@
uint32_t hw_layer_count = UINT32(hw_layer_info.hw_layers.size());
HWQosData &qos_data = hw_layers->qos_data;
DRMSecurityLevel crtc_security_level = DRMSecurityLevel::SECURE_NON_SECURE;
+ uint32_t index = current_mode_index_;
solid_fills_.clear();
@@ -683,8 +734,8 @@
if (hw_panel_info_.partial_update) {
const int kNumMaxROIs = 4;
DRMRect crtc_rects[kNumMaxROIs] = {{0, 0, mixer_attributes_.width, mixer_attributes_.height}};
- DRMRect conn_rects[kNumMaxROIs] = {{0, 0, display_attributes_.x_pixels,
- display_attributes_.y_pixels}};
+ DRMRect conn_rects[kNumMaxROIs] = {{0, 0, display_attributes_[index].x_pixels,
+ display_attributes_[index].y_pixels}};
for (uint32_t i = 0; i < hw_layer_info.left_frame_roi.size(); i++) {
auto &roi = hw_layer_info.left_frame_roi.at(i);
@@ -781,6 +832,10 @@
reinterpret_cast<uint64_t>(&scaler_output.scaler_v2));
}
}
+
+ DRMCscType csc_type = DRMCscType::kCscTypeMax;
+ SelectCscType(layer.input_buffer, &csc_type);
+ drm_atomic_intf_->Perform(DRMOps::PLANE_SET_CSC_CONFIG, pipe_id, &csc_type);
}
}
}
@@ -942,6 +997,12 @@
}
DisplayError HWDeviceDRM::Flush() {
+ int ret = drm_atomic_intf_->Commit(false /* synchronous */);
+ if (ret) {
+ DLOGE("failed with error %d", ret);
+ return kErrorHardware;
+ }
+
return kErrorNone;
}
@@ -968,6 +1029,34 @@
}
}
+void HWDeviceDRM::SelectCscType(const LayerBuffer &input_buffer, DRMCscType *type) {
+ if (type == NULL) {
+ return;
+ }
+
+ *type = DRMCscType::kCscTypeMax;
+ if (input_buffer.format < kFormatYCbCr420Planar) {
+ return;
+ }
+
+ switch (input_buffer.color_metadata.colorPrimaries) {
+ case ColorPrimaries_BT601_6_525:
+ case ColorPrimaries_BT601_6_625:
+ *type = ((input_buffer.color_metadata.range == Range_Full) ?
+ DRMCscType::kCscYuv2Rgb601FR : DRMCscType::kCscYuv2Rgb601L);
+ break;
+ case ColorPrimaries_BT709_5:
+ *type = DRMCscType::kCscYuv2Rgb709L;
+ break;
+ case ColorPrimaries_BT2020:
+ *type = ((input_buffer.color_metadata.range == Range_Full) ?
+ DRMCscType::kCscYuv2Rgb2020FR : DRMCscType::kCscYuv2Rgb2020L);
+ break;
+ default:
+ break;
+ }
+}
+
void HWDeviceDRM::SetRect(const LayerRect &source, DRMRect *target) {
target->left = UINT32(source.left);
target->top = UINT32(source.top);
@@ -985,7 +1074,7 @@
// In no rotation case or inline rotation case, plane will handle flips
// In DRM framework rotation is applied in counter-clockwise direction.
- if (transform.rotation == 90) {
+ if (mode == kRotatorInline && transform.rotation == 90) {
// a) rotate 90 clockwise = rotate 270 counter-clockwise in DRM
// rotate 270 is translated as hflip + vflip + rotate90
// b) rotate 270 clockwise = rotate 90 counter-clockwise in DRM
@@ -1165,20 +1254,26 @@
}
DisplayError HWDeviceDRM::SetMixerAttributes(const HWMixerAttributes &mixer_attributes) {
+ if (IsResolutionSwitchEnabled()) {
+ return kErrorNotSupported;
+ }
+
if (!hw_resource_.hw_dest_scalar_info.count) {
return kErrorNotSupported;
}
- if (mixer_attributes.width > display_attributes_.x_pixels ||
- mixer_attributes.height > display_attributes_.y_pixels) {
+ uint32_t index = current_mode_index_;
+
+ if (mixer_attributes.width > display_attributes_[index].x_pixels ||
+ mixer_attributes.height > display_attributes_[index].y_pixels) {
DLOGW("Input resolution exceeds display resolution! input: res %dx%d display: res %dx%d",
- mixer_attributes.width, mixer_attributes.height, display_attributes_.x_pixels,
- display_attributes_.y_pixels);
+ mixer_attributes.width, mixer_attributes.height, display_attributes_[index].x_pixels,
+ display_attributes_[index].y_pixels);
return kErrorNotSupported;
}
uint32_t max_input_width = hw_resource_.hw_dest_scalar_info.max_input_width;
- if (display_attributes_.is_device_split) {
+ if (display_attributes_[index].is_device_split) {
max_input_width *= 2;
}
@@ -1190,16 +1285,17 @@
float mixer_aspect_ratio = FLOAT(mixer_attributes.width) / FLOAT(mixer_attributes.height);
float display_aspect_ratio =
- FLOAT(display_attributes_.x_pixels) / FLOAT(display_attributes_.y_pixels);
+ FLOAT(display_attributes_[index].x_pixels) / FLOAT(display_attributes_[index].y_pixels);
if (display_aspect_ratio != mixer_aspect_ratio) {
DLOGW("Aspect ratio mismatch! input: res %dx%d display: res %dx%d", mixer_attributes.width,
- mixer_attributes.height, display_attributes_.x_pixels, display_attributes_.y_pixels);
+ mixer_attributes.height, display_attributes_[index].x_pixels,
+ display_attributes_[index].y_pixels);
return kErrorNotSupported;
}
- float scale_x = FLOAT(display_attributes_.x_pixels) / FLOAT(mixer_attributes.width);
- float scale_y = FLOAT(display_attributes_.y_pixels) / FLOAT(mixer_attributes.height);
+ float scale_x = FLOAT(display_attributes_[index].x_pixels) / FLOAT(mixer_attributes.width);
+ float scale_y = FLOAT(display_attributes_[index].y_pixels) / FLOAT(mixer_attributes.height);
float max_scale_up = hw_resource_.hw_dest_scalar_info.max_scale_up;
if (scale_x > max_scale_up || scale_y > max_scale_up) {
DLOGW(
@@ -1213,7 +1309,7 @@
mixer_attributes_ = mixer_attributes;
mixer_attributes_.split_left = mixer_attributes_.width;
- if (display_attributes_.is_device_split) {
+ if (display_attributes_[index].is_device_split) {
mixer_attributes_.split_left = UINT32(FLOAT(mixer_attributes.width) * mixer_split_ratio);
}
@@ -1225,9 +1321,10 @@
return kErrorParameters;
}
- mixer_attributes_.width = display_attributes_.x_pixels;
- mixer_attributes_.height = display_attributes_.y_pixels;
- mixer_attributes_.split_left = display_attributes_.is_device_split
+ uint32_t index = current_mode_index_;
+ mixer_attributes_.width = display_attributes_[index].x_pixels;
+ mixer_attributes_.height = display_attributes_[index].y_pixels;
+ mixer_attributes_.split_left = display_attributes_[index].is_device_split
? hw_panel_info_.split_info.left_split
: mixer_attributes_.width;
*mixer_attributes = mixer_attributes_;
@@ -1241,9 +1338,11 @@
}
void HWDeviceDRM::UpdateMixerAttributes() {
- mixer_attributes_.width = display_attributes_.x_pixels;
- mixer_attributes_.height = display_attributes_.y_pixels;
- mixer_attributes_.split_left = display_attributes_.is_device_split
+ uint32_t index = current_mode_index_;
+
+ mixer_attributes_.width = display_attributes_[index].x_pixels;
+ mixer_attributes_.height = display_attributes_[index].y_pixels;
+ mixer_attributes_.split_left = display_attributes_[index].is_device_split
? hw_panel_info_.split_info.left_split
: mixer_attributes_.width;
}
@@ -1274,4 +1373,13 @@
}
}
+void HWDeviceDRM::UpdatePanelSplitInfo() {
+ uint32_t index = current_mode_index_;
+ hw_panel_info_.split_info.left_split = display_attributes_[index].x_pixels;
+ if (display_attributes_[index].is_device_split) {
+ hw_panel_info_.split_info.left_split = hw_panel_info_.split_info.right_split =
+ display_attributes_[index].x_pixels / 2;
+ }
+}
+
} // namespace sdm
diff --git a/sdm/libs/core/drm/hw_device_drm.h b/sdm/libs/core/drm/hw_device_drm.h
index 391e699..883d605 100644
--- a/sdm/libs/core/drm/hw_device_drm.h
+++ b/sdm/libs/core/drm/hw_device_drm.h
@@ -112,7 +112,7 @@
DisplayError SetFormat(const LayerBufferFormat &source, uint32_t *target);
DisplayError SetStride(HWDeviceType device_type, LayerBufferFormat format, uint32_t width,
uint32_t *target);
- DisplayError PopulateDisplayAttributes();
+ DisplayError PopulateDisplayAttributes(uint32_t index);
void PopulateHWPanelInfo();
void GetHWDisplayPortAndMode();
void GetHWPanelMaxBrightness();
@@ -123,6 +123,7 @@
void AddSolidfillStage(const HWSolidfillStage &sf, uint32_t plane_alpha);
void SetBlending(const LayerBlending &source, sde_drm::DRMBlendType *target);
void SetSrcConfig(const LayerBuffer &input_buffer, uint32_t *config);
+ void SelectCscType(const LayerBuffer &input_buffer, sde_drm::DRMCscType *type);
void SetRect(const LayerRect &source, sde_drm::DRMRect *target);
void SetRotation(LayerTransform transform, const HWRotatorMode &mode, uint32_t* rot_bit_mask);
DisplayError DefaultCommit(HWLayers *hw_layers);
@@ -130,6 +131,8 @@
void SetupAtomic(HWLayers *hw_layers, bool validate);
void SetSecureConfig(const LayerBuffer &input_buffer, sde_drm::DRMSecureMode *fb_secure_mode,
sde_drm::DRMSecurityLevel *security_level);
+ bool IsResolutionSwitchEnabled() const { return resolution_switch_enabled_; }
+ void UpdatePanelSplitInfo();
class Registry {
public:
@@ -167,19 +170,19 @@
sde_drm::DRMDisplayToken token_ = {};
HWResourceInfo hw_resource_ = {};
HWPanelInfo hw_panel_info_ = {};
- HWDeviceType device_type_ = {};
HWScaleDRM *hw_scale_ = {};
sde_drm::DRMManagerInterface *drm_mgr_intf_ = {};
sde_drm::DRMAtomicReqInterface *drm_atomic_intf_ = {};
+ std::vector<HWDisplayAttributes> display_attributes_ = {};
+ uint32_t current_mode_index_ = 0;
sde_drm::DRMConnectorInfo connector_info_ = {};
- drmModeModeInfo current_mode_ = {};
- HWDisplayAttributes display_attributes_ = {};
private:
bool synchronous_commit_ = false;
HWMixerAttributes mixer_attributes_ = {};
std::string interface_str_ = "DSI";
std::vector<sde_drm::DRMSolidfillStage> solid_fills_ {};
+ bool resolution_switch_enabled_ = false;
};
} // namespace sdm
diff --git a/sdm/libs/core/drm/hw_tv_drm.cpp b/sdm/libs/core/drm/hw_tv_drm.cpp
index 67485f1..2659a32 100644
--- a/sdm/libs/core/drm/hw_tv_drm.cpp
+++ b/sdm/libs/core/drm/hw_tv_drm.cpp
@@ -61,7 +61,7 @@
HWTVDRM::HWTVDRM(BufferSyncHandler *buffer_sync_handler, BufferAllocator *buffer_allocator,
HWInfoInterface *hw_info_intf)
- : HWDeviceDRM(buffer_sync_handler, buffer_allocator, hw_info_intf), active_config_index_(0) {
+ : HWDeviceDRM(buffer_sync_handler, buffer_allocator, hw_info_intf) {
disp_type_ = DRMDisplayType::TV;
device_name_ = "TV Display Device";
}
@@ -96,35 +96,13 @@
hw_scale_ = new HWScaleDRM(HWScaleDRM::Version::V2);
}
- if (error != kErrorNone) {
- return error;
- }
-
return error;
}
-
-DisplayError HWTVDRM::GetNumDisplayAttributes(uint32_t *count) {
- *count = UINT32(connector_info_.modes.size());
- if (*count <= 0) {
- return kErrorHardware;
- }
-
- return kErrorNone;
-}
-
-DisplayError HWTVDRM::GetActiveConfig(uint32_t *active_config_index) {
- *active_config_index = active_config_index_;
- return kErrorNone;
-}
-
DisplayError HWTVDRM::SetDisplayAttributes(uint32_t index) {
if (index >= connector_info_.modes.size()) {
return kErrorNotSupported;
}
- active_config_index_ = index;
- current_mode_ = connector_info_.modes[index];
-
drm_atomic_intf_->Perform(DRMOps::CRTC_SET_MODE, token_.crtc_id, &connector_info_.modes[index]);
drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 1);
@@ -139,8 +117,8 @@
drm_mgr_intf_->GetConnectorInfo(token_.conn_id, &connector_info_);
DLOGI("Setup CRTC %d, Connector %d for %s", token_.crtc_id, token_.conn_id, device_name_);
- frame_rate_ = display_attributes_.fps;
- PopulateDisplayAttributes();
+ current_mode_index_ = index;
+ PopulateDisplayAttributes(index);
PopulateHWPanelInfo();
UpdateMixerAttributes();
diff --git a/sdm/libs/core/drm/hw_tv_drm.h b/sdm/libs/core/drm/hw_tv_drm.h
index 7991ae3..fa8012a 100644
--- a/sdm/libs/core/drm/hw_tv_drm.h
+++ b/sdm/libs/core/drm/hw_tv_drm.h
@@ -41,18 +41,12 @@
protected:
virtual DisplayError Init();
- virtual DisplayError GetNumDisplayAttributes(uint32_t *count);
- // Requirement to call this only after the first config has been explicitly set by client
- virtual DisplayError GetActiveConfig(uint32_t *active_config);
virtual DisplayError SetDisplayAttributes(uint32_t index);
virtual DisplayError GetConfigIndex(char *mode, uint32_t *index);
private:
static const int kBitRGB = 20;
static const int kBitYUV = 21;
-
- uint32_t active_config_index_;
- uint32_t frame_rate_ = 0;
};
} // namespace sdm
diff --git a/sdm/libs/core/drm/hw_virtual_drm.cpp b/sdm/libs/core/drm/hw_virtual_drm.cpp
index 5ea76b0..55f38ac 100644
--- a/sdm/libs/core/drm/hw_virtual_drm.cpp
+++ b/sdm/libs/core/drm/hw_virtual_drm.cpp
@@ -55,6 +55,7 @@
}
DisplayError HWVirtualDRM::Init() {
+ display_attributes_.push_back(HWDisplayAttributes());
return kErrorNone;
}
@@ -85,20 +86,19 @@
}
void HWVirtualDRM::InitializeConfigs() {
- current_mode_.hdisplay = current_mode_.hsync_start = current_mode_.hsync_end \
- = current_mode_.htotal = (uint16_t) width_;
- current_mode_.vdisplay = current_mode_.vsync_start = current_mode_.vsync_end \
- = current_mode_.vtotal = (uint16_t) height_;
+ drmModeModeInfo mode = {};
+ mode.hdisplay = mode.hsync_start = mode.hsync_end = mode.htotal = (uint16_t) width_;
+ mode.vdisplay = mode.vsync_start = mode.vsync_end = mode.vtotal = (uint16_t) height_;
// Not sure SF has a way to configure refresh rate. Hardcoding to 60 fps for now.
// TODO(user): Make this configurable.
- current_mode_.vrefresh = 60;
- current_mode_.clock = (current_mode_.htotal * current_mode_.vtotal \
- * current_mode_.vrefresh) / 1000;
+ mode.vrefresh = 60;
+ mode.clock = (mode.htotal * mode.vtotal * mode.vrefresh) / 1000;
+
struct sde_drm_wb_cfg wb_cfg;
wb_cfg.connector_id = token_.conn_id;
wb_cfg.flags |= SDE_DRM_WB_CFG_FLAGS_CONNECTED;
wb_cfg.count_modes = 1;
- wb_cfg.modes = (uint64_t)¤t_mode_;
+ wb_cfg.modes = (uint64_t)&mode;
#ifdef DRM_IOCTL_SDE_WB_CONFIG
int ret = drmIoctl(dev_fd_, DRM_IOCTL_SDE_WB_CONFIG, &wb_cfg);
#endif
@@ -106,7 +106,6 @@
DLOGE("WB config failed\n");
} else {
drm_mgr_intf_->GetConnectorInfo(token_.conn_id, &connector_info_);
- current_mode_ = connector_info_.modes[0];
DumpConfigs();
}
@@ -118,6 +117,7 @@
connector_info_.topology = sde_drm::DRMTopology::DUAL_LM_MERGE;
}
}
+ PopulateDisplayAttributes(current_mode_index_);
}
void HWVirtualDRM::DumpConfigs() {
@@ -160,15 +160,24 @@
return kErrorParameters;
}
- display_attributes_ = display_attributes;
+ uint32_t index = current_mode_index_;
+ width_ = display_attributes.x_pixels;
+ height_ = display_attributes.y_pixels;
- if (display_attributes_.x_pixels > hw_resource_.max_mixer_width) {
- display_attributes_.is_device_split = true;
+ DisplayError error = DeferredInit();
+ if (error != kErrorNone) {
+ width_ = display_attributes_[index].x_pixels;
+ height_ = display_attributes_[index].y_pixels;
+ return error;
}
+ drm_atomic_intf_->Perform(DRMOps::CRTC_SET_MODE, token_.crtc_id, &connector_info_.modes[index]);
+ drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 1);
- width_ = display_attributes_.x_pixels;
- height_ = display_attributes_.y_pixels;
- DeferredInit();
+ display_attributes_[index] = display_attributes;
+ if (display_attributes_[index].x_pixels > hw_resource_.max_mixer_width) {
+ display_attributes_[index].is_device_split = true;
+ }
+ UpdateMixerAttributes();
return kErrorNone;
}
diff --git a/sdm/libs/core/fb/hw_device.cpp b/sdm/libs/core/fb/hw_device.cpp
index fa79f75..eb0d17b 100644
--- a/sdm/libs/core/fb/hw_device.cpp
+++ b/sdm/libs/core/fb/hw_device.cpp
@@ -1367,7 +1367,7 @@
const char* xlog_path = "/data/vendor/display/mdp_xlog";
DLOGD("Dumping debugfs data to %s", xlog_path);
std::ostringstream dst;
- auto file = open(xlog_path, O_CREAT | O_DSYNC | O_RDWR, "w+");
+ auto file = open(xlog_path, O_CREAT | O_TRUNC | O_DSYNC | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP);
if (file < 0) {
DLOGE("Couldn't open file: err:%d (%s)", errno, strerror(errno));
return kErrorResources;
diff --git a/sdm/libs/hwc2/hwc_callbacks.cpp b/sdm/libs/hwc2/hwc_callbacks.cpp
index 3be3bf6..48593f1 100644
--- a/sdm/libs/hwc2/hwc_callbacks.cpp
+++ b/sdm/libs/hwc2/hwc_callbacks.cpp
@@ -54,6 +54,7 @@
if (!vsync_) {
return HWC2::Error::NoResources;
}
+ DTRACE_SCOPED();
vsync_(vsync_data_, display, timestamp);
return HWC2::Error::None;
}
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index cf4d1a2..6106baf 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -53,6 +53,8 @@
namespace sdm {
+std::bitset<kDisplayMax> HWCDisplay::validated_ = 0;
+
// This weight function is needed because the color primaries are not sorted by gamut size
static ColorPrimaries WidestPrimaries(ColorPrimaries p1, ColorPrimaries p2) {
int weight = 10;
@@ -102,11 +104,16 @@
}
HWC2::Error HWCColorMode::SetColorMode(android_color_mode_t mode) {
+ DTRACE_SCOPED();
// first mode in 2D matrix is the mode (identity)
- if (color_mode_transform_map_.find(mode) == color_mode_transform_map_.end()) {
+ if (mode < HAL_COLOR_MODE_NATIVE || mode > HAL_COLOR_MODE_DISPLAY_P3) {
DLOGE("Could not find mode: %d", mode);
return HWC2::Error::BadParameter;
}
+ if (color_mode_transform_map_.find(mode) == color_mode_transform_map_.end()) {
+ return HWC2::Error::Unsupported;
+ }
+
auto status = HandleColorModeTransform(mode, current_color_transform_, color_matrix_);
if (status != HWC2::Error::None) {
DLOGE("failed for mode = %d", mode);
@@ -125,10 +132,12 @@
}
HWC2::Error HWCColorMode::SetColorTransform(const float *matrix, android_color_transform_t hint) {
- if (!matrix) {
+ if (!matrix || (hint < HAL_COLOR_TRANSFORM_IDENTITY ||
+ hint > HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA)) {
return HWC2::Error::BadParameter;
}
+ DTRACE_SCOPED();
double color_matrix[kColorTransformMatrixCount] = {0};
CopyColorTransformMatrix(matrix, color_matrix);
@@ -347,6 +356,7 @@
return -EINVAL;
}
+ validated_.reset();
HWCDebugHandler::Get()->GetProperty("sys.hwc_disable_hdr", &disable_hdr_handling_);
if (disable_hdr_handling_) {
DLOGI("HDR Handling disabled");
@@ -376,6 +386,8 @@
display_intf_->GetRefreshRateRange(&min_refresh_rate_, &max_refresh_rate_);
current_refresh_rate_ = max_refresh_rate_;
+
+ GetUnderScanConfig();
DLOGI("Display created with id: %d", id_);
return 0;
@@ -406,8 +418,8 @@
HWCLayer *layer = *layer_set_.emplace(new HWCLayer(id_, buffer_allocator_));
layer_map_.emplace(std::make_pair(layer->GetId(), layer));
*out_layer_id = layer->GetId();
- validated_ = false;
geometry_changes_ |= GeometryChanges::kAdded;
+ validated_.reset();
return HWC2::Error::None;
}
@@ -437,9 +449,9 @@
break;
}
}
- validated_ = false;
geometry_changes_ |= GeometryChanges::kRemoved;
+ validated_.reset();
return HWC2::Error::None;
}
@@ -596,7 +608,6 @@
DLOGE("[%" PRIu64 "] updateLayerZ failed to find layer", id_);
return HWC2::Error::BadLayer;
}
- validated_ = false;
const auto layer = map_layer->second;
const auto z_range = layer_set_.equal_range(layer);
@@ -625,6 +636,7 @@
HWC2::Error HWCDisplay::SetVsyncEnabled(HWC2::Vsync enabled) {
DLOGV("Display ID: %d enabled: %s", id_, to_string(enabled).c_str());
+ ATRACE_INT("SetVsyncState ", enabled == HWC2::Vsync::Enable ? 1 : 0);
DisplayError error = kErrorNone;
if (shutdown_pending_ || !callbacks_->VsyncCallbackRegistered()) {
@@ -688,7 +700,10 @@
return HWC2::Error::BadParameter;
}
+ ATRACE_INT("SetPowerMode ", state);
DisplayError error = display_intf_->SetDisplayState(state);
+ validated_.reset();
+
if (error == kErrorNone) {
flush_on_error_ = flush_on_error;
} else {
@@ -743,9 +758,18 @@
HWC2::Error HWCDisplay::GetDisplayAttribute(hwc2_config_t config, HWC2::Attribute attribute,
int32_t *out_value) {
DisplayConfigVariableInfo variable_config;
- if (GetDisplayAttributesForConfig(INT(config), &variable_config) != kErrorNone) {
- DLOGE("Get variable config failed");
- return HWC2::Error::BadDisplay;
+ // Get display attributes from config index only if resolution switch is supported.
+ // Otherwise always send mixer attributes. This is to support destination scaler.
+ if (num_configs_ > 1) {
+ if (GetDisplayAttributesForConfig(INT(config), &variable_config) != kErrorNone) {
+ DLOGE("Get variable config failed");
+ return HWC2::Error::BadDisplay;
+ }
+ } else {
+ if (display_intf_->GetFrameBufferConfig(&variable_config) != kErrorNone) {
+ DLOGV("Get variable config failed");
+ return HWC2::Error::BadDisplay;
+ }
}
switch (attribute) {
@@ -853,6 +877,7 @@
return HWC2::Error::BadConfig;
}
+ validated_.reset();
return HWC2::Error::None;
}
@@ -870,6 +895,7 @@
}
DLOGI("num_frame_dump %d, input_layer_dump_enable %d", dump_frame_count_, dump_input_layers_);
+ validated_.reset();
}
HWC2::PowerMode HWCDisplay::GetLastPowerMode() {
@@ -895,6 +921,20 @@
return kErrorNone;
}
+DisplayError HWCDisplay::HandleEvent(DisplayEvent event) {
+ switch (event) {
+ case kIdleTimeout:
+ case kThermalEvent:
+ validated_.reset();
+ break;
+ default:
+ DLOGW("Unknown event: %d", event);
+ break;
+ }
+
+ return kErrorNone;
+}
+
HWC2::Error HWCDisplay::PrepareLayerStack(uint32_t *out_num_types, uint32_t *out_num_requests) {
layer_changes_.clear();
layer_requests_.clear();
@@ -914,6 +954,8 @@
flush_ = true;
}
return HWC2::Error::BadDisplay;
+ } else {
+ validated_.set(type_);
}
} else {
// Skip is not set
@@ -942,10 +984,11 @@
if (requested_composition != device_composition) {
layer_changes_[hwc_layer->GetId()] = device_composition;
}
+ hwc_layer->ResetValidation();
}
*out_num_types = UINT32(layer_changes_.size());
*out_num_requests = UINT32(layer_requests_.size());
- validated_ = true;
+ skip_validate_ = false;
if (*out_num_types > 0) {
return HWC2::Error::HasChanges;
} else {
@@ -958,7 +1001,7 @@
return HWC2::Error::None;
}
- if (!validated_) {
+ if (!validated_.test(type_)) {
return HWC2::Error::NotValidated;
}
@@ -980,10 +1023,11 @@
return HWC2::Error::None;
}
- if (!validated_) {
+ if (!validated_.test(type_)) {
DLOGW("Display is not validated");
return HWC2::Error::NotValidated;
}
+
*out_num_elements = UINT32(layer_changes_.size());
if (out_layers != nullptr && out_types != nullptr) {
int i = 0;
@@ -1013,18 +1057,19 @@
HWC2::Error HWCDisplay::GetDisplayRequests(int32_t *out_display_requests,
uint32_t *out_num_elements, hwc2_layer_t *out_layers,
int32_t *out_layer_requests) {
- // No display requests for now
- // Use for sharing blit buffers and
- // writing wfd buffer directly to output if there is full GPU composition
- // and no color conversion needed
if (layer_set_.empty()) {
return HWC2::Error::None;
}
- if (!validated_) {
+ // No display requests for now
+ // Use for sharing blit buffers and
+ // writing wfd buffer directly to output if there is full GPU composition
+ // and no color conversion needed
+ if (!validated_.test(type_)) {
DLOGW("Display is not validated");
return HWC2::Error::NotValidated;
}
+
*out_display_requests = 0;
*out_num_elements = UINT32(layer_requests_.size());
if (out_layers != nullptr && out_layer_requests != nullptr) {
@@ -1079,8 +1124,12 @@
return HWC2::Error::None;
}
- if (!validated_) {
- DLOGW("Display is not validated");
+ if (skip_validate_ && !CanSkipValidate()) {
+ validated_.reset(type_);
+ }
+
+ if (!validated_.test(type_)) {
+ DLOGV_IF(kTagCompManager, "Display %d is not validated", id_);
return HWC2::Error::NotValidated;
}
@@ -1100,7 +1149,6 @@
}
}
error = display_intf_->Commit(&layer_stack_);
- validated_ = false;
if (error == kErrorNone) {
// A commit is successfully submitted, start flushing on failure now onwards.
@@ -1109,6 +1157,9 @@
if (error == kErrorShutDown) {
shutdown_pending_ = true;
return HWC2::Error::Unsupported;
+ } else if (error == kErrorNotValidated) {
+ validated_.reset(type_);
+ return HWC2::Error::NotValidated;
} else if (error != kErrorPermission) {
DLOGE("Commit failed. Error = %d", error);
// To prevent surfaceflinger infinite wait, flush the previous frame during Commit()
@@ -1118,6 +1169,7 @@
}
}
+ skip_validate_ = true;
return HWC2::Error::None;
}
@@ -1127,6 +1179,7 @@
// Do no call flush on errors, if a successful buffer is never submitted.
if (flush_ && flush_on_error_) {
display_intf_->Flush();
+ validated_.reset();
}
if (tone_mapper_ && tone_mapper_->IsActive()) {
@@ -1174,6 +1227,7 @@
layer_stack_.retire_fence_fd = -1;
}
*out_retire_fence = layer_stack_.retire_fence_fd;
+ layer_stack_.retire_fence_fd = -1;
if (dump_frame_count_) {
dump_frame_count_--;
@@ -1198,6 +1252,7 @@
if (display_intf_) {
error = display_intf_->SetMaxMixerStages(max_mixer_stages);
+ validated_.reset();
}
return error;
@@ -1560,6 +1615,7 @@
if (display_status == kDisplayStatusResume || display_status == kDisplayStatusPause) {
callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
+ validated_.reset();
}
return status;
@@ -1570,9 +1626,18 @@
return HWC2::Error::None;
}
- if (GetHWCLayer(layer) == nullptr) {
+ HWCLayer *hwc_layer = GetHWCLayer(layer);
+ if (hwc_layer == nullptr) {
return HWC2::Error::BadLayer;
}
+ if (hwc_layer->GetDeviceSelectedCompositionType() != HWC2::Composition::Cursor) {
+ return HWC2::Error::None;
+ }
+ if (!skip_validate_ && validated_.test(type_)) {
+ // the device is currently in the middle of the validate/present sequence,
+ // cannot set the Position(as per HWC2 spec)
+ return HWC2::Error::NotValidated;
+ }
DisplayState state;
if (display_intf_->GetDisplayState(&state) == kErrorNone) {
@@ -1581,9 +1646,9 @@
}
}
- if (!validated_) {
- return HWC2::Error::NotValidated;
- }
+ // TODO(user): HWC1.5 was not letting SetCursorPosition before validateDisplay,
+ // but HWC2.0 doesn't let setting cursor position after validate before present.
+ // Need to revisit.
auto error = display_intf_->SetCursorPosition(x, y);
if (error != kErrorNone) {
@@ -1606,6 +1671,7 @@
return -1;
}
+ validated_.reset();
return 0;
}
@@ -1614,7 +1680,7 @@
auto layer = hwc_layer->GetSDMLayer();
layer->composition = kCompositionSDE;
}
- validated_ = true;
+ validated_.set(type_);
}
void HWCDisplay::MarkLayersForClientComposition() {
@@ -1632,10 +1698,12 @@
int HWCDisplay::SetPanelBrightness(int level) {
int ret = 0;
- if (display_intf_)
+ if (display_intf_) {
ret = display_intf_->SetPanelBrightness(level);
- else
+ validated_.reset();
+ } else {
ret = -EINVAL;
+ }
return ret;
}
@@ -1647,6 +1715,7 @@
int HWCDisplay::ToggleScreenUpdates(bool enable) {
display_paused_ = enable ? false : true;
callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
+ validated_.reset();
return 0;
}
@@ -1744,7 +1813,9 @@
}
int HWCDisplay::SetActiveDisplayConfig(uint32_t config) {
- return display_intf_->SetActiveConfig(config) == kErrorNone ? 0 : -1;
+ int status = (display_intf_->SetActiveConfig(config) == kErrorNone) ? 0 : -1;
+ validated_.reset();
+ return status;
}
int HWCDisplay::GetActiveDisplayConfig(uint32_t *config) {
@@ -1862,4 +1933,25 @@
os << "-------------------------------" << std::endl;
return os.str();
}
+
+bool HWCDisplay::CanSkipValidate() {
+ // Layer Stack checks
+ if (layer_stack_.flags.hdr_present && (tone_mapper_ && tone_mapper_->IsActive())) {
+ return false;
+ }
+
+ for (auto hwc_layer : layer_set_) {
+ if (hwc_layer->NeedsValidation()) {
+ return false;
+ }
+
+ // Do not allow Skip Validate, if any layer needs GPU Composition.
+ if (hwc_layer->GetDeviceSelectedCompositionType() == HWC2::Composition::Client) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
} // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h
index e773e91..273b760 100644
--- a/sdm/libs/hwc2/hwc_display.h
+++ b/sdm/libs/hwc2/hwc_display.h
@@ -146,19 +146,6 @@
virtual int GetDisplayConfigCount(uint32_t *count);
virtual int GetDisplayAttributesForConfig(int config,
DisplayConfigVariableInfo *display_attributes);
- template <typename... Args>
- int32_t CallLayerFunction(hwc2_layer_t layer, HWC2::Error (HWCLayer::*member)(Args... ),
- Args... args) {
- auto status = HWC2::Error::BadLayer;
- validated_ = false;
- auto hwc_layer = GetHWCLayer(layer);
- if (hwc_layer != nullptr) {
- status = (hwc_layer->*member)(std::forward<Args>(args)...);
- }
-
- return INT32(status);
- }
-
virtual int SetState(bool connected) {
return kErrorNotSupported;
}
@@ -174,6 +161,8 @@
void BuildLayerStack(void);
void BuildSolidFillStack(void);
HWCLayer *GetHWCLayer(hwc2_layer_t layer);
+ void ResetValidation() { validated_.reset(); }
+ uint32_t GetGeometryChanges() { return geometry_changes_; }
// HWC2 APIs
virtual HWC2::Error AcceptDisplayChanges(void);
@@ -234,6 +223,7 @@
virtual DisplayError VSync(const DisplayEventVSync &vsync);
virtual DisplayError Refresh();
virtual DisplayError CECMessage(char *message);
+ virtual DisplayError HandleEvent(DisplayEvent event);
virtual void DumpOutputBuffer(const BufferInfo &buffer_info, void *base, int fence);
virtual HWC2::Error PrepareLayerStack(uint32_t *out_num_types, uint32_t *out_num_requests);
virtual HWC2::Error CommitLayerStack(void);
@@ -252,12 +242,14 @@
uint32_t SanitizeRefreshRate(uint32_t req_refresh_rate);
virtual void CloseAcquireFds();
virtual void ClearRequestFlags();
+ virtual void GetUnderScanConfig() { }
enum {
INPUT_LAYER_DUMP,
OUTPUT_LAYER_DUMP,
};
+ static std::bitset<kDisplayMax> validated_;
CoreInterface *core_intf_ = nullptr;
HWCCallbacks *callbacks_ = nullptr;
HWCBufferAllocator *buffer_allocator_ = NULL;
@@ -295,7 +287,6 @@
LayerRect solid_fill_rect_ = {};
uint32_t solid_fill_color_ = 0;
LayerRect display_rect_;
- bool validated_ = false;
bool color_tranform_failed_ = false;
HWCColorMode *color_mode_ = NULL;
HWCToneMapper *tone_mapper_ = nullptr;
@@ -304,9 +295,11 @@
private:
void DumpInputBuffers(void);
+ bool CanSkipValidate();
qService::QService *qservice_ = NULL;
DisplayClass display_class_;
uint32_t geometry_changes_ = GeometryChanges::kNone;
+ bool skip_validate_ = false;
};
inline int HWCDisplay::Perform(uint32_t operation, ...) {
diff --git a/sdm/libs/hwc2/hwc_display_external.cpp b/sdm/libs/hwc2/hwc_display_external.cpp
index e89451d..97507ee 100644
--- a/sdm/libs/hwc2/hwc_display_external.cpp
+++ b/sdm/libs/hwc2/hwc_display_external.cpp
@@ -142,20 +142,12 @@
}
void HWCDisplayExternal::ApplyScanAdjustment(hwc_rect_t *display_frame) {
- if (display_intf_->IsUnderscanSupported()) {
+ if ((underscan_width_ <= 0) || (underscan_height_ <= 0)) {
return;
}
- // Read user defined width and height ratio
- int width = 0, height = 0;
- HWCDebugHandler::Get()->GetProperty("sdm.external_action_safe_width", &width);
- float width_ratio = FLOAT(width) / 100.0f;
- HWCDebugHandler::Get()->GetProperty("sdm.external_action_safe_height", &height);
- float height_ratio = FLOAT(height) / 100.0f;
-
- if (width_ratio == 0.0f || height_ratio == 0.0f) {
- return;
- }
+ float width_ratio = FLOAT(underscan_width_) / 100.0f;
+ float height_ratio = FLOAT(underscan_height_) / 100.0f;
uint32_t mixer_width = 0;
uint32_t mixer_height = 0;
@@ -188,6 +180,7 @@
if (secure_display_active_) {
DisplayError error = display_intf_->Flush();
+ validated_.reset();
if (error != kErrorNone) {
DLOGE("Flush failed. Error = %d", error);
}
@@ -241,6 +234,7 @@
display_null_.GetDisplayState(&state);
display_intf_->SetDisplayState(state);
+ validated_.reset();
SetVsyncEnabled(HWC2::Vsync::Enable);
@@ -277,4 +271,12 @@
return 0;
}
+void HWCDisplayExternal::GetUnderScanConfig() {
+ if (!display_intf_->IsUnderscanSupported()) {
+ // Read user defined underscan width and height
+ HWCDebugHandler::Get()->GetProperty("sdm.external_action_safe_width", &underscan_width_);
+ HWCDebugHandler::Get()->GetProperty("sdm.external_action_safe_height", &underscan_height_);
+ }
+}
+
} // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_display_external.h b/sdm/libs/hwc2/hwc_display_external.h
index 7aa84b2..fbee6a3 100644
--- a/sdm/libs/hwc2/hwc_display_external.h
+++ b/sdm/libs/hwc2/hwc_display_external.h
@@ -54,10 +54,13 @@
HWCDisplayExternal(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
HWCCallbacks *callbacks, qService::QService *qservice);
void ApplyScanAdjustment(hwc_rect_t *display_frame);
+ void GetUnderScanConfig();
static void GetDownscaleResolution(uint32_t primary_width, uint32_t primary_height,
uint32_t *virtual_width, uint32_t *virtual_height);
DisplayNull display_null_;
+ int underscan_width_ = 0;
+ int underscan_height_ = 0;
};
} // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_display_primary.cpp b/sdm/libs/hwc2/hwc_display_primary.cpp
index 1094100..4079cbc 100644
--- a/sdm/libs/hwc2/hwc_display_primary.cpp
+++ b/sdm/libs/hwc2/hwc_display_primary.cpp
@@ -217,6 +217,7 @@
// If we do not handle the frame set retireFenceFd to outbufAcquireFenceFd
// Revisit this when validating display_paused
DisplayError error = display_intf_->Flush();
+ validated_.reset();
if (error != kErrorNone) {
DLOGE("Flush failed. Error = %d", error);
}
@@ -252,6 +253,7 @@
}
callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
+ validated_.reset();
return status;
}
@@ -264,6 +266,7 @@
}
callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
+ validated_.reset();
return status;
}
@@ -283,6 +286,7 @@
callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
color_tranform_failed_ = false;
+ validated_.reset();
return status;
}
@@ -324,6 +328,7 @@
return -EINVAL;
}
va_end(args);
+ validated_.reset();
return 0;
}
@@ -410,6 +415,7 @@
void HWCDisplayPrimary::SetIdleTimeoutMs(uint32_t timeout_ms) {
display_intf_->SetIdleTimeoutMs(timeout_ms);
+ validated_.reset();
}
static void SetLayerBuffer(const BufferInfo &output_buffer_info, LayerBuffer *output_buffer) {
@@ -509,6 +515,7 @@
output_buffer_base_ = buffer;
post_processed_output_ = true;
DisablePartialUpdateOneFrame();
+ validated_.reset();
}
int HWCDisplayPrimary::FrameCaptureAsync(const BufferInfo &output_buffer_info,
@@ -553,6 +560,7 @@
if (display_intf_) {
error = display_intf_->SetDetailEnhancerData(de_data);
+ validated_.reset();
}
return error;
}
@@ -562,6 +570,7 @@
if (display_intf_) {
error = display_intf_->ControlPartialUpdate(enable, pending);
+ validated_.reset();
}
return error;
@@ -572,6 +581,7 @@
if (display_intf_) {
error = display_intf_->DisablePartialUpdateOneFrame();
+ validated_.reset();
}
return error;
@@ -579,7 +589,9 @@
DisplayError HWCDisplayPrimary::SetMixerResolution(uint32_t width, uint32_t height) {
- return display_intf_->SetMixerResolution(width, height);
+ DisplayError error = display_intf_->SetMixerResolution(width, height);
+ validated_.reset();
+ return error;
}
DisplayError HWCDisplayPrimary::GetMixerResolution(uint32_t *width, uint32_t *height) {
diff --git a/sdm/libs/hwc2/hwc_display_virtual.cpp b/sdm/libs/hwc2/hwc_display_virtual.cpp
index 8ac9be6..8837ad0 100644
--- a/sdm/libs/hwc2/hwc_display_virtual.cpp
+++ b/sdm/libs/hwc2/hwc_display_virtual.cpp
@@ -131,6 +131,7 @@
auto status = HWC2::Error::None;
if (display_paused_) {
DisplayError error = display_intf_->Flush();
+ validated_.reset();
if (error != kErrorNone) {
DLOGE("Flush failed. Error = %d", error);
}
diff --git a/sdm/libs/hwc2/hwc_layers.cpp b/sdm/libs/hwc2/hwc_layers.cpp
index a45fb1f..a717305 100644
--- a/sdm/libs/hwc2/hwc_layers.cpp
+++ b/sdm/libs/hwc2/hwc_layers.cpp
@@ -84,7 +84,6 @@
close(release_fences_.front());
release_fences_.pop();
}
- close(ion_fd_);
if (layer_) {
delete layer_;
}
@@ -108,13 +107,8 @@
const private_handle_t *handle = static_cast<const private_handle_t *>(buffer);
- // Validate and dup ion fd from surfaceflinger
- // This works around bug 30281222
if (handle->fd < 0) {
return HWC2::Error::BadParameter;
- } else {
- close(ion_fd_);
- ion_fd_ = dup(handle->fd);
}
LayerBuffer *layer_buffer = &layer_->input_buffer;
@@ -125,36 +119,40 @@
AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(handle, aligned_width, aligned_height);
#endif
+ LayerBufferFormat format = GetSDMFormat(handle->format, handle->flags);
+ if ((format != layer_buffer->format) || (UINT32(aligned_width) != layer_buffer->width) ||
+ (UINT32(aligned_height) != layer_buffer->height)) {
+ // Layer buffer geometry has changed.
+ geometry_changes_ |= kBufferGeometry;
+ }
+
+ layer_buffer->format = format;
layer_buffer->width = UINT32(aligned_width);
layer_buffer->height = UINT32(aligned_height);
layer_buffer->unaligned_width = UINT32(handle->unaligned_width);
layer_buffer->unaligned_height = UINT32(handle->unaligned_height);
- layer_buffer->format = GetSDMFormat(handle->format, handle->flags);
if (SetMetaData(const_cast<private_handle_t *>(handle), layer_) != kErrorNone) {
return HWC2::Error::BadLayer;
}
-#ifdef USE_GRALLOC1
- // TODO(user): Clean this up
- if (handle->buffer_type == BUFFER_TYPE_VIDEO) {
-#else
- if (handle->bufferType == BUFFER_TYPE_VIDEO) {
-#endif
- layer_buffer->flags.video = true;
- }
+ layer_buffer->flags.video = (handle->buffer_type == BUFFER_TYPE_VIDEO) ? true : false;
+
// TZ Protected Buffer - L1
- if (handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
- layer_buffer->flags.secure = true;
- if (handle->flags & private_handle_t::PRIV_FLAGS_CAMERA_WRITE) {
- layer_buffer->flags.secure_camera = true;
- }
- }
- if (handle->flags & private_handle_t::PRIV_FLAGS_SECURE_DISPLAY) {
- layer_buffer->flags.secure_display = true;
+ bool secure = (handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER);
+ bool secure_camera = secure && (handle->flags & private_handle_t::PRIV_FLAGS_CAMERA_WRITE);
+ bool secure_display = (handle->flags & private_handle_t::PRIV_FLAGS_SECURE_DISPLAY);
+ if (secure != layer_buffer->flags.secure || secure_camera != layer_buffer->flags.secure_camera ||
+ secure_display != layer_buffer->flags.secure_display) {
+ // Secure attribute of layer buffer has changed.
+ needs_validate_ = true;
}
- layer_buffer->planes[0].fd = ion_fd_;
+ layer_buffer->flags.secure = secure;
+ layer_buffer->flags.secure_camera = secure_camera;
+ layer_buffer->flags.secure_display = secure_display;
+
+ layer_buffer->planes[0].fd = handle->fd;
layer_buffer->planes[0].offset = handle->offset;
layer_buffer->planes[0].stride = UINT32(handle->width);
layer_buffer->acquire_fence_fd = acquire_fence;
@@ -165,6 +163,20 @@
}
HWC2::Error HWCLayer::SetLayerSurfaceDamage(hwc_region_t damage) {
+ // Check if there is an update in SurfaceDamage rects
+ if (layer_->dirty_regions.size() != damage.numRects) {
+ needs_validate_ = true;
+ } else {
+ for (uint32_t j = 0; j < damage.numRects; j++) {
+ LayerRect damage_rect;
+ SetRect(damage.rects[j], &damage_rect);
+ if (damage_rect != layer_->dirty_regions.at(j)) {
+ needs_validate_ = true;
+ break;
+ }
+ }
+ }
+
layer_->dirty_regions.clear();
for (uint32_t i = 0; i < damage.numRects; i++) {
LayerRect rect;
@@ -198,6 +210,9 @@
}
HWC2::Error HWCLayer::SetLayerColor(hwc_color_t color) {
+ if (client_requested_ != HWC2::Composition::SolidColor) {
+ return HWC2::Error::None;
+ }
layer_->solid_fill_color = GetUint32Color(color);
layer_->input_buffer.format = kFormatARGB8888;
DLOGV_IF(kTagCompManager, "[%" PRIu64 "][%" PRIu64 "] Layer color set to %x", display_id_, id_,
@@ -576,20 +591,23 @@
LayerBuffer *layer_buffer = &layer->input_buffer;
private_handle_t *handle = const_cast<private_handle_t *>(pvt_handle);
IGC_t igc = {};
+ LayerIGC layer_igc = layer_buffer->igc;
if (getMetaData(handle, GET_IGC, &igc) == 0) {
- if (SetIGC(igc, &layer_buffer->igc) != kErrorNone) {
+ if (SetIGC(igc, &layer_igc) != kErrorNone) {
return kErrorNotSupported;
}
}
float fps = 0;
- if (getMetaData(handle, GET_REFRESH_RATE , &fps) == 0) {
- layer->frame_rate = RoundToStandardFPS(fps);
+ uint32_t frame_rate = layer->frame_rate;
+ if (getMetaData(handle, GET_REFRESH_RATE, &fps) == 0) {
+ frame_rate = RoundToStandardFPS(fps);
}
int32_t interlaced = 0;
+ bool interlace = layer_buffer->flags.interlace;
if (getMetaData(handle, GET_PP_PARAM_INTERLACED, &interlaced) == 0) {
- layer_buffer->flags.interlace = interlaced ? true : false;
+ interlace = interlaced ? true : false;
}
uint32_t linear_format = 0;
@@ -598,8 +616,19 @@
}
uint32_t s3d = 0;
+ LayerBufferS3DFormat s3d_format = layer_buffer->s3d_format;
if (getMetaData(handle, GET_S3D_FORMAT, &s3d) == 0) {
- layer_buffer->s3d_format = GetS3DFormat(s3d);
+ s3d_format = GetS3DFormat(s3d);
+ }
+
+ if ((layer_igc != layer_buffer->igc) || (interlace != layer_buffer->flags.interlace) ||
+ (frame_rate != layer->frame_rate) || (s3d_format != layer_buffer->s3d_format)) {
+ // Layer buffer metadata has changed.
+ needs_validate_ = true;
+ layer_buffer->igc = layer_igc;
+ layer->frame_rate = frame_rate;
+ layer_buffer->s3d_format = s3d_format;
+ layer_buffer->flags.interlace = interlace;
}
// Check if metadata is set
diff --git a/sdm/libs/hwc2/hwc_layers.h b/sdm/libs/hwc2/hwc_layers.h
index 25ec4dc..e8e6e59 100644
--- a/sdm/libs/hwc2/hwc_layers.h
+++ b/sdm/libs/hwc2/hwc_layers.h
@@ -52,6 +52,7 @@
kZOrder = 0x040,
kAdded = 0x080,
kRemoved = 0x100,
+ kBufferGeometry = 0x200,
};
class HWCLayer {
@@ -87,6 +88,8 @@
int32_t PopReleaseFence(void);
bool ValidateAndSetCSC();
bool SupportLocalConversion(ColorPrimaries working_primaries);
+ void ResetValidation() { needs_validate_ = false; }
+ bool NeedsValidation() { return (needs_validate_ || geometry_changes_); }
private:
Layer *layer_ = nullptr;
@@ -95,11 +98,11 @@
const hwc2_display_t display_id_;
static std::atomic<hwc2_layer_t> next_id_;
std::queue<int32_t> release_fences_;
- int ion_fd_ = -1;
HWCBufferAllocator *buffer_allocator_ = NULL;
int32_t dataspace_ = HAL_DATASPACE_UNKNOWN;
LayerTransform layer_transform_ = {};
LayerRect dst_rect_ = {};
+ bool needs_validate_ = true;
// Composition requested by client(SF)
HWC2::Composition client_requested_ = HWC2::Composition::Device;
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index f7462d1..272b2f6 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -290,10 +290,20 @@
void HWCSession::GetCapabilities(struct hwc2_device *device, uint32_t *outCount,
int32_t *outCapabilities) {
- if (outCapabilities != nullptr && *outCount >= 1) {
- outCapabilities[0] = HWC2_CAPABILITY_SKIP_CLIENT_COLOR_TRANSFORM;
+ int value = 0;
+ bool disable_skip_validate = false;
+ if (Debug::Get()->GetProperty("sdm.debug.disable_skip_validate", &value) == kErrorNone) {
+ disable_skip_validate = (value == 1);
}
- *outCount = 1;
+ uint32_t count = 1 + (disable_skip_validate ? 0 : 1);
+
+ if (outCapabilities != nullptr && (*outCount >= count)) {
+ outCapabilities[0] = HWC2_CAPABILITY_SKIP_CLIENT_COLOR_TRANSFORM;
+ if (!disable_skip_validate) {
+ outCapabilities[1] = HWC2_CAPABILITY_SKIP_VALIDATE;
+ }
+ }
+ *outCount = count;
}
template <typename PFN, typename T>
@@ -344,7 +354,7 @@
int32_t HWCSession::DestroyVirtualDisplay(hwc2_device_t *device, hwc2_display_t display) {
SCOPE_LOCK(locker_);
- if (!device) {
+ if (!device || display != HWC_DISPLAY_VIRTUAL) {
return HWC2_ERROR_BAD_DISPLAY;
}
@@ -633,8 +643,12 @@
return HWC2_ERROR_BAD_DISPLAY;
}
+ if (display != HWC_DISPLAY_VIRTUAL) {
+ return HWC2_ERROR_UNSUPPORTED;
+ }
+
auto *hwc_session = static_cast<HWCSession *>(device);
- if (display == HWC_DISPLAY_VIRTUAL && hwc_session->hwc_display_[display]) {
+ if (hwc_session->hwc_display_[display]) {
auto vds = reinterpret_cast<HWCDisplayVirtual *>(hwc_session->hwc_display_[display]);
auto status = vds->SetOutputBuffer(buffer, releaseFence);
return INT32(status);
@@ -1306,6 +1320,7 @@
HWCColorManager::MarshallStructIntoParcel(resp_payload, output_parcel);
req_payload.DestroyPayload();
resp_payload.DestroyPayload();
+ hwc_display_[display_id]->ResetValidation();
return (ret ? -EINVAL : 0);
}
diff --git a/sdm/libs/hwc2/hwc_session.h b/sdm/libs/hwc2/hwc_session.h
index 288bbba..f09ed0e 100644
--- a/sdm/libs/hwc2/hwc_session.h
+++ b/sdm/libs/hwc2/hwc_session.h
@@ -99,11 +99,18 @@
}
HWCSession *hwc_session = static_cast<HWCSession *>(device);
- int32_t status = INT32(HWC2::Error::BadDisplay);
+ auto status = HWC2::Error::BadDisplay;
if (hwc_session->hwc_display_[display]) {
- status = hwc_session->hwc_display_[display]->CallLayerFunction(layer, member, args...);
+ status = HWC2::Error::BadLayer;
+ auto hwc_layer = hwc_session->hwc_display_[display]->GetHWCLayer(layer);
+ if (hwc_layer != nullptr) {
+ status = (hwc_layer->*member)(std::forward<Args>(args)...);
+ if (hwc_session->hwc_display_[display]->GetGeometryChanges()) {
+ hwc_session->hwc_display_[display]->ResetValidation();
+ }
+ }
}
- return status;
+ return INT32(status);
}
// HWC2 Functions that require a concrete implementation in hwc session
diff --git a/sdm/libs/hwc2/hwc_session_services.cpp b/sdm/libs/hwc2/hwc_session_services.cpp
index 383ec3b..425ffbe 100644
--- a/sdm/libs/hwc2/hwc_session_services.cpp
+++ b/sdm/libs/hwc2/hwc_session_services.cpp
@@ -451,6 +451,7 @@
new_bw_mode_ = true;
need_invalidate_ = true;
+ hwc_display_[HWC_DISPLAY_PRIMARY]->ResetValidation();
return 0;
}