summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSushil Chauhan <sushilchauhan@codeaurora.org>2017-06-12 17:43:25 -0700
committerSushil Chauhan <sushilchauhan@codeaurora.org>2017-08-09 18:05:09 -0700
commit409e8446488f9de3203cb28767b90827982bbb49 (patch)
treee29c0b80cb8a23352c9b785c241943cac6cf06df
parent2468fea2b8cacd952f704be320dcdbc61c70656b (diff)
downloaddisplay-409e8446488f9de3203cb28767b90827982bbb49.tar.gz
sdm: hwc2: Support Skip Validate feature
1. Set HWC2_CAPABILITY_SKIP_VALIDATE cap in GetCapabilities api. 2. If HWC2_CAPABILITY_SKIP_VALIDATE cap is exposed by HWC HAL, then SF just calls PresentDisplay api. It is the responsibility of HWC HAL to request for ValidateDisplay, if it is required. If the cap is not exposed by HWC HAL, then there will be ValidateDisplay call followed by PresentDisplay. 3. In case of Surface Damage update on a layer, SDM needs a Validate call to program SDE driver for Partial Update feature. 4. SDM needs Validate call to enter in safe Mode for use cases like Idle / Thermal fallback, HDMI and Virtual Connect/Disconnet, etc. 5. In case of layer buffer geometry, metadata or secure attributes change, SDM needs Validate call to program the SDE driver. 6. SDM needs Validate call if GPU tonemapping is required on a layer during HDR Video playback. 7. Read user defined underscan width and height, when the External display gets created and initialized. 8. SDM needs Validate call for few APIs which are exposed by the Binder Interface or by HWComposer APIs, since they need re-configuration of SDE driver or they modify Panel / LayerMixer / Display configuration. 9. The feature is enabled by default. "sdm.debug.disable_skip_validate" system property can be set to '1' to disable the feature. CRs-Fixed: 2071632 Change-Id: I68f0db3af16afa4ad4eb789cd1f6b12caf6381e4
-rw-r--r--sdm/include/core/display_interface.h9
-rw-r--r--sdm/include/core/sdm_types.h1
-rw-r--r--sdm/libs/core/display_base.cpp13
-rw-r--r--sdm/libs/core/display_base.h2
-rw-r--r--sdm/libs/core/display_primary.cpp2
-rw-r--r--sdm/libs/hwc2/hwc_display.cpp90
-rw-r--r--sdm/libs/hwc2/hwc_display.h8
-rw-r--r--sdm/libs/hwc2/hwc_display_external.cpp24
-rw-r--r--sdm/libs/hwc2/hwc_display_external.h3
-rw-r--r--sdm/libs/hwc2/hwc_display_primary.cpp14
-rw-r--r--sdm/libs/hwc2/hwc_display_virtual.cpp1
-rw-r--r--sdm/libs/hwc2/hwc_layers.cpp76
-rw-r--r--sdm/libs/hwc2/hwc_layers.h4
-rw-r--r--sdm/libs/hwc2/hwc_session.cpp15
-rw-r--r--sdm/libs/hwc2/hwc_session.h3
-rw-r--r--sdm/libs/hwc2/hwc_session_services.cpp1
16 files changed, 209 insertions, 57 deletions
diff --git a/sdm/include/core/display_interface.h b/sdm/include/core/display_interface.h
index 524141ec..b8e2a9e3 100644
--- a/sdm/include/core/display_interface.h
+++ b/sdm/include/core/display_interface.h
@@ -135,6 +135,12 @@ enum DisplayPort {
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 @@ class DisplayEventHandler {
*/
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 ce356bfa..72ad6b24 100644
--- a/sdm/include/core/sdm_types.h
+++ b/sdm/include/core/sdm_types.h
@@ -56,6 +56,7 @@ enum DisplayError {
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 b76c3d1b..538d38e6 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -211,6 +211,7 @@ DisplayError DisplayBase::ValidateGPUTargetParams() {
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 @@ DisplayError DisplayBase::Prepare(LayerStack *layer_stack) {
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 DisplayBase::Commit(LayerStack *layer_stack) {
DisplayError error = kErrorNone;
if (!active_) {
- pending_commit_ = false;
+ needs_validate_ = true;
return kErrorPermission;
}
@@ -277,13 +278,11 @@ DisplayError DisplayBase::Commit(LayerStack *layer_stack) {
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 @@ DisplayError DisplayBase::Flush() {
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 40232294..223e5eb4 100644
--- a/sdm/libs/core/display_base.h
+++ b/sdm/libs/core/display_base.h
@@ -153,7 +153,7 @@ class DisplayBase : public DisplayInterface, DumpImpl {
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 52b71c73..64a0bccf 100644
--- a/sdm/libs/core/display_primary.cpp
+++ b/sdm/libs/core/display_primary.cpp
@@ -283,6 +283,7 @@ void DisplayPrimary::IdleTimeout() {
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::PingPongTimeout() {
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/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index 43c53fde..5be9bcf8 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;
@@ -354,6 +356,7 @@ int HWCDisplay::Init() {
return -EINVAL;
}
+ validated_.reset();
HWCDebugHandler::Get()->GetProperty("sys.hwc_disable_hdr", &disable_hdr_handling_);
if (disable_hdr_handling_) {
DLOGI("HDR Handling disabled");
@@ -383,6 +386,8 @@ int HWCDisplay::Init() {
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;
@@ -414,6 +419,7 @@ HWC2::Error HWCDisplay::CreateLayer(hwc2_layer_t *out_layer_id) {
layer_map_.emplace(std::make_pair(layer->GetId(), layer));
*out_layer_id = layer->GetId();
geometry_changes_ |= GeometryChanges::kAdded;
+ validated_.reset();
return HWC2::Error::None;
}
@@ -445,6 +451,7 @@ HWC2::Error HWCDisplay::DestroyLayer(hwc2_layer_t layer_id) {
}
geometry_changes_ |= GeometryChanges::kRemoved;
+ validated_.reset();
return HWC2::Error::None;
}
@@ -695,6 +702,8 @@ HWC2::Error HWCDisplay::SetPowerMode(HWC2::PowerMode mode) {
ATRACE_INT("SetPowerMode ", state);
DisplayError error = display_intf_->SetDisplayState(state);
+ validated_.reset();
+
if (error == kErrorNone) {
flush_on_error_ = flush_on_error;
} else {
@@ -859,6 +868,7 @@ HWC2::Error HWCDisplay::SetActiveConfig(hwc2_config_t config) {
return HWC2::Error::BadConfig;
}
+ validated_.reset();
return HWC2::Error::None;
}
@@ -876,6 +886,7 @@ void HWCDisplay::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type
}
DLOGI("num_frame_dump %d, input_layer_dump_enable %d", dump_frame_count_, dump_input_layers_);
+ validated_.reset();
}
HWC2::PowerMode HWCDisplay::GetLastPowerMode() {
@@ -901,6 +912,20 @@ DisplayError HWCDisplay::CECMessage(char *message) {
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();
@@ -920,6 +945,8 @@ HWC2::Error HWCDisplay::PrepareLayerStack(uint32_t *out_num_types, uint32_t *out
flush_ = true;
}
return HWC2::Error::BadDisplay;
+ } else {
+ validated_.set(type_);
}
} else {
// Skip is not set
@@ -948,10 +975,11 @@ HWC2::Error HWCDisplay::PrepareLayerStack(uint32_t *out_num_types, uint32_t *out
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 {
@@ -964,7 +992,7 @@ HWC2::Error HWCDisplay::AcceptDisplayChanges() {
return HWC2::Error::None;
}
- if (!validated_) {
+ if (!validated_.test(type_)) {
return HWC2::Error::NotValidated;
}
@@ -986,7 +1014,7 @@ HWC2::Error HWCDisplay::GetChangedCompositionTypes(uint32_t *out_num_elements,
return HWC2::Error::None;
}
- if (!validated_) {
+ if (!validated_.test(type_)) {
DLOGW("Display is not validated");
return HWC2::Error::NotValidated;
}
@@ -1028,7 +1056,7 @@ HWC2::Error HWCDisplay::GetDisplayRequests(int32_t *out_display_requests,
// 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_) {
+ if (!validated_.test(type_)) {
DLOGW("Display is not validated");
return HWC2::Error::NotValidated;
}
@@ -1087,8 +1115,12 @@ HWC2::Error HWCDisplay::CommitLayerStack(void) {
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;
}
@@ -1108,7 +1140,6 @@ HWC2::Error HWCDisplay::CommitLayerStack(void) {
}
}
error = display_intf_->Commit(&layer_stack_);
- validated_ = false;
if (error == kErrorNone) {
// A commit is successfully submitted, start flushing on failure now onwards.
@@ -1117,6 +1148,9 @@ HWC2::Error HWCDisplay::CommitLayerStack(void) {
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()
@@ -1126,6 +1160,7 @@ HWC2::Error HWCDisplay::CommitLayerStack(void) {
}
}
+ skip_validate_ = true;
return HWC2::Error::None;
}
@@ -1135,6 +1170,7 @@ HWC2::Error HWCDisplay::PostCommitLayerStack(int32_t *out_retire_fence) {
// 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()) {
@@ -1182,6 +1218,7 @@ HWC2::Error HWCDisplay::PostCommitLayerStack(int32_t *out_retire_fence) {
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_--;
@@ -1206,6 +1243,7 @@ DisplayError HWCDisplay::SetMaxMixerStages(uint32_t max_mixer_stages) {
if (display_intf_) {
error = display_intf_->SetMaxMixerStages(max_mixer_stages);
+ validated_.reset();
}
return error;
@@ -1568,6 +1606,7 @@ int HWCDisplay::SetDisplayStatus(DisplayStatus display_status) {
if (display_status == kDisplayStatusResume || display_status == kDisplayStatusPause) {
callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
+ validated_.reset();
}
return status;
@@ -1585,7 +1624,7 @@ HWC2::Error HWCDisplay::SetCursorPosition(hwc2_layer_t layer, int x, int y) {
if (hwc_layer->GetDeviceSelectedCompositionType() != HWC2::Composition::Cursor) {
return HWC2::Error::None;
}
- if (validated_ == true) {
+ 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;
@@ -1623,6 +1662,7 @@ int HWCDisplay::OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) {
return -1;
}
+ validated_.reset();
return 0;
}
@@ -1631,7 +1671,7 @@ void HWCDisplay::MarkLayersForGPUBypass() {
auto layer = hwc_layer->GetSDMLayer();
layer->composition = kCompositionSDE;
}
- validated_ = true;
+ validated_.set(type_);
}
void HWCDisplay::MarkLayersForClientComposition() {
@@ -1649,10 +1689,12 @@ void HWCDisplay::ApplyScanAdjustment(hwc_rect_t *display_frame) {
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;
}
@@ -1664,6 +1706,7 @@ int HWCDisplay::GetPanelBrightness(int *level) {
int HWCDisplay::ToggleScreenUpdates(bool enable) {
display_paused_ = enable ? false : true;
callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
+ validated_.reset();
return 0;
}
@@ -1761,7 +1804,9 @@ void HWCDisplay::SetSecureDisplay(bool secure_display_active) {
}
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) {
@@ -1879,4 +1924,25 @@ std::string HWCDisplay::Dump() {
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 55e1eb3c..273b7600 100644
--- a/sdm/libs/hwc2/hwc_display.h
+++ b/sdm/libs/hwc2/hwc_display.h
@@ -161,6 +161,8 @@ class HWCDisplay : public DisplayEventHandler {
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);
@@ -221,6 +223,7 @@ class HWCDisplay : public DisplayEventHandler {
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);
@@ -239,12 +242,14 @@ class HWCDisplay : public DisplayEventHandler {
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;
@@ -282,7 +287,6 @@ class HWCDisplay : public DisplayEventHandler {
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;
@@ -291,9 +295,11 @@ class HWCDisplay : public DisplayEventHandler {
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 e89451d5..97507ee1 100644
--- a/sdm/libs/hwc2/hwc_display_external.cpp
+++ b/sdm/libs/hwc2/hwc_display_external.cpp
@@ -142,20 +142,12 @@ HWC2::Error HWCDisplayExternal::Present(int32_t *out_retire_fence) {
}
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 @@ void HWCDisplayExternal::SetSecureDisplay(bool secure_display_active) {
if (secure_display_active_) {
DisplayError error = display_intf_->Flush();
+ validated_.reset();
if (error != kErrorNone) {
DLOGE("Flush failed. Error = %d", error);
}
@@ -241,6 +234,7 @@ int HWCDisplayExternal::SetState(bool connected) {
display_null_.GetDisplayState(&state);
display_intf_->SetDisplayState(state);
+ validated_.reset();
SetVsyncEnabled(HWC2::Vsync::Enable);
@@ -277,4 +271,12 @@ int HWCDisplayExternal::SetState(bool connected) {
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 7aa84b2c..fbee6a3d 100644
--- a/sdm/libs/hwc2/hwc_display_external.h
+++ b/sdm/libs/hwc2/hwc_display_external.h
@@ -54,10 +54,13 @@ class HWCDisplayExternal : public HWCDisplay {
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 10941008..4079cbcd 100644
--- a/sdm/libs/hwc2/hwc_display_primary.cpp
+++ b/sdm/libs/hwc2/hwc_display_primary.cpp
@@ -217,6 +217,7 @@ HWC2::Error HWCDisplayPrimary::Present(int32_t *out_retire_fence) {
// 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 @@ HWC2::Error HWCDisplayPrimary::SetColorMode(android_color_mode_t mode) {
}
callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
+ validated_.reset();
return status;
}
@@ -264,6 +266,7 @@ HWC2::Error HWCDisplayPrimary::SetColorModeById(int32_t color_mode_id) {
}
callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
+ validated_.reset();
return status;
}
@@ -283,6 +286,7 @@ HWC2::Error HWCDisplayPrimary::SetColorTransform(const float *matrix,
callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
color_tranform_failed_ = false;
+ validated_.reset();
return status;
}
@@ -324,6 +328,7 @@ int HWCDisplayPrimary::Perform(uint32_t operation, ...) {
return -EINVAL;
}
va_end(args);
+ validated_.reset();
return 0;
}
@@ -410,6 +415,7 @@ DisplayError HWCDisplayPrimary::Refresh() {
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 @@ void HWCDisplayPrimary::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_lay
output_buffer_base_ = buffer;
post_processed_output_ = true;
DisablePartialUpdateOneFrame();
+ validated_.reset();
}
int HWCDisplayPrimary::FrameCaptureAsync(const BufferInfo &output_buffer_info,
@@ -553,6 +560,7 @@ DisplayError HWCDisplayPrimary::SetDetailEnhancerConfig
if (display_intf_) {
error = display_intf_->SetDetailEnhancerData(de_data);
+ validated_.reset();
}
return error;
}
@@ -562,6 +570,7 @@ DisplayError HWCDisplayPrimary::ControlPartialUpdate(bool enable, uint32_t *pend
if (display_intf_) {
error = display_intf_->ControlPartialUpdate(enable, pending);
+ validated_.reset();
}
return error;
@@ -572,6 +581,7 @@ DisplayError HWCDisplayPrimary::DisablePartialUpdateOneFrame() {
if (display_intf_) {
error = display_intf_->DisablePartialUpdateOneFrame();
+ validated_.reset();
}
return error;
@@ -579,7 +589,9 @@ DisplayError HWCDisplayPrimary::DisablePartialUpdateOneFrame() {
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 8ac9be67..8837ad07 100644
--- a/sdm/libs/hwc2/hwc_display_virtual.cpp
+++ b/sdm/libs/hwc2/hwc_display_virtual.cpp
@@ -131,6 +131,7 @@ HWC2::Error HWCDisplayVirtual::Present(int32_t *out_retire_fence) {
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 dba00b4f..4e6dba28 100644
--- a/sdm/libs/hwc2/hwc_layers.cpp
+++ b/sdm/libs/hwc2/hwc_layers.cpp
@@ -125,35 +125,39 @@ HWC2::Error HWCLayer::SetLayerBuffer(buffer_handle_t buffer, int32_t acquire_fen
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->flags.secure = secure;
+ layer_buffer->flags.secure_camera = secure_camera;
+ layer_buffer->flags.secure_display = secure_display;
+
layer_buffer->planes[0].fd = ion_fd_;
layer_buffer->planes[0].offset = handle->offset;
layer_buffer->planes[0].stride = UINT32(handle->width);
@@ -165,6 +169,20 @@ HWC2::Error HWCLayer::SetLayerBuffer(buffer_handle_t buffer, int32_t acquire_fen
}
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;
@@ -579,20 +597,23 @@ DisplayError HWCLayer::SetMetaData(const private_handle_t *pvt_handle, Layer *la
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;
@@ -601,8 +622,19 @@ DisplayError HWCLayer::SetMetaData(const private_handle_t *pvt_handle, Layer *la
}
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 25ec4dc5..0260fd05 100644
--- a/sdm/libs/hwc2/hwc_layers.h
+++ b/sdm/libs/hwc2/hwc_layers.h
@@ -52,6 +52,7 @@ enum GeometryChanges {
kZOrder = 0x040,
kAdded = 0x080,
kRemoved = 0x100,
+ kBufferGeometry = 0x200,
};
class HWCLayer {
@@ -87,6 +88,8 @@ class HWCLayer {
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;
@@ -100,6 +103,7 @@ class HWCLayer {
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 3fce394e..272b2f6d 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -290,10 +290,20 @@ int HWCSession::Close(hw_device_t *device) {
void HWCSession::GetCapabilities(struct hwc2_device *device, uint32_t *outCount,
int32_t *outCapabilities) {
- if (outCapabilities != nullptr && *outCount >= 1) {
+ int value = 0;
+ bool disable_skip_validate = false;
+ if (Debug::Get()->GetProperty("sdm.debug.disable_skip_validate", &value) == kErrorNone) {
+ disable_skip_validate = (value == 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 = 1;
+ *outCount = count;
}
template <typename PFN, typename T>
@@ -1310,6 +1320,7 @@ android::status_t HWCSession::QdcmCMDHandler(const android::Parcel *input_parcel
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 6c45134c..f09ed0ef 100644
--- a/sdm/libs/hwc2/hwc_session.h
+++ b/sdm/libs/hwc2/hwc_session.h
@@ -105,6 +105,9 @@ class HWCSession : hwc2_device_t, HWCUEventListener, IDisplayConfig, public qCli
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 INT32(status);
diff --git a/sdm/libs/hwc2/hwc_session_services.cpp b/sdm/libs/hwc2/hwc_session_services.cpp
index 383ec3bd..425ffbe9 100644
--- a/sdm/libs/hwc2/hwc_session_services.cpp
+++ b/sdm/libs/hwc2/hwc_session_services.cpp
@@ -451,6 +451,7 @@ Return<int32_t> HWCSession::setCameraLaunchStatus(uint32_t on) {
new_bw_mode_ = true;
need_invalidate_ = true;
+ hwc_display_[HWC_DISPLAY_PRIMARY]->ResetValidation();
return 0;
}