Merge "hwc2: Allow commit to go through if flush_ flag is set"
diff --git a/gralloc/QtiMapper.cpp b/gralloc/QtiMapper.cpp
index 3848878..14c788e 100644
--- a/gralloc/QtiMapper.cpp
+++ b/gralloc/QtiMapper.cpp
@@ -52,7 +52,7 @@
bool QtiMapper::ValidDescriptor(const BufferDescriptorInfo_2_1 &bd) {
if (bd.width == 0 || bd.height == 0 || (static_cast<int32_t>(bd.format) <= 0) ||
- bd.layerCount != 1) {
+ bd.layerCount <= 0) {
return false;
}
diff --git a/gralloc/gr_buf_mgr.cpp b/gralloc/gr_buf_mgr.cpp
index 3d4bfac..a569184 100644
--- a/gralloc/gr_buf_mgr.cpp
+++ b/gralloc/gr_buf_mgr.cpp
@@ -335,6 +335,7 @@
}
Error BufferManager::Dump(std::ostringstream *os) {
+ std::lock_guard<std::mutex> buffer_lock(buffer_lock_);
for (auto it : handles_map_) {
auto buf = it.second;
auto hnd = buf->handle;
diff --git a/include/display_properties.h b/include/display_properties.h
index ddcde64..9af7ddd 100644
--- a/include/display_properties.h
+++ b/include/display_properties.h
@@ -107,6 +107,7 @@
#define QDCM_DISABLE_TIMEOUT_PROP PERSIST_DISPLAY_PROP("qdcm.disable_timeout")
#define QDCM_MODE_COMBINE_PROP DISPLAY_PROP("qdcm.mode_combine")
#define PREFER_MULTIRECT_PROP DISPLAY_PROP("prefer_multirect")
+#define DROP_SKEWED_VSYNC DISPLAY_PROP("drop_skewed_vsync");
#define ZERO_SWAP_INTERVAL "vendor.debug.egl.swapinterval"
diff --git a/sdm/include/utils/locker.h b/sdm/include/utils/locker.h
index dabeb11..e0d91cb 100755
--- a/sdm/include/utils/locker.h
+++ b/sdm/include/utils/locker.h
@@ -127,15 +127,15 @@
Locker() : sequence_wait_(0) {
pthread_mutex_init(&mutex_, 0);
- pthread_condattr_init(&cond_attr);
- pthread_condattr_setclock(&cond_attr, CLOCK_MONOTONIC);
- pthread_cond_init(&condition_, &cond_attr);
+ pthread_condattr_init(&cond_attr_);
+ pthread_condattr_setclock(&cond_attr_, CLOCK_MONOTONIC);
+ pthread_cond_init(&condition_, &cond_attr_);
}
~Locker() {
pthread_mutex_destroy(&mutex_);
pthread_cond_destroy(&condition_);
- pthread_condattr_destroy(&cond_attr);
+ pthread_condattr_destroy(&cond_attr_);
}
void Lock() { pthread_mutex_lock(&mutex_); }
@@ -157,7 +157,7 @@
private:
pthread_mutex_t mutex_;
pthread_cond_t condition_;
- pthread_condattr_t cond_attr;
+ pthread_condattr_t cond_attr_;
int sequence_wait_; // This flag is set to 1 on sequence entry, 0 on exit, and -1 on cancel.
// Some routines will wait for sequence of function calls to finish
// so that capturing a transitionary snapshot of context is prevented.
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index 6d54b4e..bd238a9 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -98,6 +98,7 @@
int property_value = Debug::GetMaxPipesPerMixer(display_type_);
uint32_t active_index = 0;
+ int drop_vsync = 0;
hw_intf_->GetActiveConfig(&active_index);
hw_intf_->GetDisplayAttributes(active_index, &display_attributes_);
fb_config_ = display_attributes_;
@@ -168,6 +169,9 @@
Debug::GetProperty(DISABLE_HW_RECOVERY_DUMP_PROP, &disable_hw_recovery_dump_);
DLOGI("disable_hw_recovery_dump_ set to %d", disable_hw_recovery_dump_);
+ Debug::Get()->GetProperty("DROP_SKEWED_VSYNC", &drop_vsync);
+ drop_skewed_vsync_ = (drop_vsync == 1);
+
return kErrorNone;
CleanupOnError:
@@ -390,7 +394,10 @@
return error;
}
+ // Stop dropping vsync when first commit is received after idle fallback.
+ drop_hw_vsync_ = false;
DLOGI_IF(kTagDisplay, "Exiting commit for display: %d-%d", display_id_, display_type_);
+
return kErrorNone;
}
@@ -1051,6 +1058,10 @@
if (vsync_enable_ != enable) {
error = hw_intf_->SetVSyncState(enable);
if (error == kErrorNotSupported) {
+ if (drop_skewed_vsync_ && (hw_panel_info_.mode == kModeVideo) &&
+ enable && (current_refresh_rate_ == hw_panel_info_.min_fps)) {
+ drop_hw_vsync_ = true;
+ }
error = hw_events_intf_->SetEventState(HWEvent::VSYNC, enable);
}
if (error == kErrorNone) {
diff --git a/sdm/libs/core/display_base.h b/sdm/libs/core/display_base.h
index e4efb92..27452f4 100644
--- a/sdm/libs/core/display_base.h
+++ b/sdm/libs/core/display_base.h
@@ -211,6 +211,9 @@
bool hw_recovery_logs_captured_ = false;
int disable_hw_recovery_dump_ = 0;
HWQosData default_qos_data_;
+ bool drop_hw_vsync_ = false;
+ uint32_t current_refresh_rate_ = 0;
+ bool drop_skewed_vsync_ = false;
static Locker display_power_reset_lock_;
static bool display_power_reset_pending_;
diff --git a/sdm/libs/core/display_builtin.cpp b/sdm/libs/core/display_builtin.cpp
index e4882b8..3b5ca4b 100644
--- a/sdm/libs/core/display_builtin.cpp
+++ b/sdm/libs/core/display_builtin.cpp
@@ -311,7 +311,7 @@
}
DisplayError DisplayBuiltIn::VSync(int64_t timestamp) {
- if (vsync_enable_) {
+ if (vsync_enable_ && !drop_hw_vsync_) {
DisplayEventVSync vsync;
vsync.timestamp = timestamp;
event_handler_->VSync(vsync);
@@ -322,7 +322,9 @@
void DisplayBuiltIn::IdleTimeout() {
if (hw_panel_info_.mode == kModeVideo) {
- event_handler_->HandleEvent(kIdleTimeout);
+ if (event_handler_->HandleEvent(kIdleTimeout) != kErrorNone) {
+ return;
+ }
handle_idle_timeout_ = true;
event_handler_->Refresh();
lock_guard<recursive_mutex> obj(recursive_mutex_);
diff --git a/sdm/libs/core/display_builtin.h b/sdm/libs/core/display_builtin.h
index d4295fa..599a730 100644
--- a/sdm/libs/core/display_builtin.h
+++ b/sdm/libs/core/display_builtin.h
@@ -95,7 +95,6 @@
bool avr_prop_disabled_ = false;
bool switch_to_cmd_ = false;
bool handle_idle_timeout_ = false;
- uint32_t current_refresh_rate_ = 0;
bool reset_panel_ = false;
bool commit_event_enabled_ = false;
DppsInfo dpps_info_ = {};
diff --git a/sdm/libs/core/strategy.cpp b/sdm/libs/core/strategy.cpp
index 1281545..5098b01 100644
--- a/sdm/libs/core/strategy.cpp
+++ b/sdm/libs/core/strategy.cpp
@@ -150,6 +150,11 @@
Layer layer = *gpu_target_layer;
hw_layers_info_->index.push_back(hw_layers_info_->gpu_target_index);
hw_layers_info_->roi_index.push_back(0);
+ layer.transform.flip_horizontal ^= hw_panel_info_.panel_orientation.flip_horizontal;
+ layer.transform.flip_vertical ^= hw_panel_info_.panel_orientation.flip_vertical;
+ // Flip rect to match transform.
+ TransformHV(src_domain, layer.dst_rect, layer.transform, &layer.dst_rect);
+ // Scale to mixer resolution.
MapRect(src_domain, dst_domain, layer.dst_rect, &layer.dst_rect);
hw_layers_info_->hw_layers.push_back(layer);
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index 6b722d6..f29bb93 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -554,6 +554,7 @@
}
}
+ bool is_secure = false;
const private_handle_t *handle =
reinterpret_cast<const private_handle_t *>(layer->input_buffer.buffer_id);
if (handle) {
@@ -561,17 +562,16 @@
layer_stack_.flags.video_present = true;
}
// TZ Protected Buffer - L1
- if (handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
- layer_stack_.flags.secure_present = true;
- }
// Gralloc Usage Protected Buffer - L3 - which needs to be treated as Secure & avoid fallback
- if (handle->flags & private_handle_t::PRIV_FLAGS_PROTECTED_BUFFER) {
+ if (handle->flags & private_handle_t::PRIV_FLAGS_PROTECTED_BUFFER ||
+ handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
layer_stack_.flags.secure_present = true;
+ is_secure = true;
}
}
- if (layer->flags.skip) {
- layer_stack_.flags.skip_present = true;
+ if (layer->input_buffer.flags.secure_display) {
+ is_secure = true;
}
if (hwc_layer->IsSingleBuffered() &&
@@ -601,6 +601,14 @@
layer_stack_.flags.hdr_present = true;
}
+ if (hwc_layer->IsNonIntegralSourceCrop() && !is_secure && !hdr_layer) {
+ layer->flags.skip = true;
+ }
+
+ if (layer->flags.skip) {
+ layer_stack_.flags.skip_present = true;
+ }
+
// TODO(user): Move to a getter if this is needed at other places
hwc_rect_t scaled_display_frame = {INT(layer->dst_rect.left), INT(layer->dst_rect.top),
INT(layer->dst_rect.right), INT(layer->dst_rect.bottom)};
@@ -624,11 +632,10 @@
layer->src_rect.bottom = layer_buffer->height;
}
- if (layer->frame_rate > metadata_refresh_rate_) {
+ if (hwc_layer->HasMetaDataRefreshRate() && layer->frame_rate > metadata_refresh_rate_) {
metadata_refresh_rate_ = SanitizeRefreshRate(layer->frame_rate);
- } else {
- layer->frame_rate = current_refresh_rate_;
}
+
display_rect_ = Union(display_rect_, layer->dst_rect);
geometry_changes_ |= hwc_layer->GetGeometryChanges();
@@ -1080,7 +1087,17 @@
DisplayError HWCDisplay::HandleEvent(DisplayEvent event) {
switch (event) {
- case kIdleTimeout:
+ case kIdleTimeout: {
+ SCOPE_LOCK(HWCSession::locker_[type_]);
+ if (pending_commit_) {
+ // If idle timeout event comes in between prepare
+ // and commit, drop it since device is not really
+ // idle.
+ return kErrorNotSupported;
+ }
+ validated_ = false;
+ break;
+ }
case kThermalEvent:
case kIdlePowerCollapse:
case kPanelDeadEvent: {
@@ -1118,6 +1135,7 @@
return ((*out_num_types > 0) ? HWC2::Error::HasChanges : HWC2::Error::None);
}
+ UpdateRefreshRate();
DisplayError error = display_intf_->Prepare(&layer_stack_);
if (error != kErrorNone) {
if (error == kErrorShutDown) {
@@ -1306,6 +1324,10 @@
HWC2::Error HWCDisplay::CommitLayerStack(void) {
+ if (flush_) {
+ return HWC2::Error::None;
+ }
+
if (!validated_) {
DLOGV_IF(kTagClient, "Display %d is not validated", id_);
return HWC2::Error::NotValidated;
@@ -1317,37 +1339,35 @@
DumpInputBuffers();
- if (!flush_) {
- DisplayError error = kErrorUndefined;
- int status = 0;
- if (tone_mapper_) {
- if (NeedsToneMap(layer_stack_)) {
- status = tone_mapper_->HandleToneMap(&layer_stack_);
- if (status != 0) {
- DLOGE("Error handling HDR in ToneMapper");
- }
- } else {
- tone_mapper_->Terminate();
+ DisplayError error = kErrorUndefined;
+ int status = 0;
+ if (tone_mapper_) {
+ if (NeedsToneMap(layer_stack_)) {
+ status = tone_mapper_->HandleToneMap(&layer_stack_);
+ if (status != 0) {
+ DLOGE("Error handling HDR in ToneMapper");
}
- }
- error = display_intf_->Commit(&layer_stack_);
-
- if (error == kErrorNone) {
- // A commit is successfully submitted, start flushing on failure now onwards.
- flush_on_error_ = true;
} else {
- if (error == kErrorShutDown) {
- shutdown_pending_ = true;
- return HWC2::Error::Unsupported;
- } else if (error == kErrorNotValidated) {
- validated_ = false;
- 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()
- // so that previous buffer and fences are released, and override the error.
- flush_ = true;
- }
+ tone_mapper_->Terminate();
+ }
+ }
+ error = display_intf_->Commit(&layer_stack_);
+
+ if (error == kErrorNone) {
+ // A commit is successfully submitted, start flushing on failure now onwards.
+ flush_on_error_ = true;
+ } else {
+ if (error == kErrorShutDown) {
+ shutdown_pending_ = true;
+ return HWC2::Error::Unsupported;
+ } else if (error == kErrorNotValidated) {
+ validated_ = false;
+ 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()
+ // so that previous buffer and fences are released, and override the error.
+ flush_ = true;
}
}
@@ -2138,4 +2158,14 @@
return skip_prepare;
}
+void HWCDisplay::UpdateRefreshRate() {
+ for (auto hwc_layer : layer_set_) {
+ if (hwc_layer->HasMetaDataRefreshRate()) {
+ continue;
+ }
+ auto layer = hwc_layer->GetSDMLayer();
+ layer->frame_rate = current_refresh_rate_;
+ }
+}
+
} // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h
index 61e897e..27bed47 100644
--- a/sdm/libs/hwc2/hwc_display.h
+++ b/sdm/libs/hwc2/hwc_display.h
@@ -361,11 +361,12 @@
int disable_hdr_handling_ = 0; // disables HDR handling.
uint32_t display_config_ = 0;
bool config_pending_ = false;
+ bool pending_commit_ = false;
private:
void DumpInputBuffers(void);
bool CanSkipSdmPrepare(uint32_t *num_types, uint32_t *num_requests);
-
+ void UpdateRefreshRate();
qService::QService *qservice_ = NULL;
DisplayClass display_class_;
uint32_t geometry_changes_ = GeometryChanges::kNone;
diff --git a/sdm/libs/hwc2/hwc_display_builtin.cpp b/sdm/libs/hwc2/hwc_display_builtin.cpp
index 7d5b5e1..a11d13e 100644
--- a/sdm/libs/hwc2/hwc_display_builtin.cpp
+++ b/sdm/libs/hwc2/hwc_display_builtin.cpp
@@ -236,6 +236,7 @@
}
status = PrepareLayerStack(out_num_types, out_num_requests);
+ pending_commit_ = true;
return status;
}
@@ -257,6 +258,7 @@
}
CloseFd(&output_buffer_.acquire_fence_fd);
+ pending_commit_ = false;
return status;
}
diff --git a/sdm/libs/hwc2/hwc_display_pluggable.cpp b/sdm/libs/hwc2/hwc_display_pluggable.cpp
index 7d22642..d97c423 100644
--- a/sdm/libs/hwc2/hwc_display_pluggable.cpp
+++ b/sdm/libs/hwc2/hwc_display_pluggable.cpp
@@ -137,6 +137,7 @@
if (layer_set_.empty()) {
flush_ = true;
+ validated_ = true;
return status;
}
diff --git a/sdm/libs/hwc2/hwc_layers.cpp b/sdm/libs/hwc2/hwc_layers.cpp
index 13c3f8d..94f1a61 100644
--- a/sdm/libs/hwc2/hwc_layers.cpp
+++ b/sdm/libs/hwc2/hwc_layers.cpp
@@ -455,6 +455,10 @@
HWC2::Error HWCLayer::SetLayerSourceCrop(hwc_frect_t crop) {
LayerRect src_rect = {};
SetRect(crop, &src_rect);
+ non_integral_source_crop_ = ((crop.left != roundf(crop.left)) ||
+ (crop.top != roundf(crop.top)) ||
+ (crop.right != roundf(crop.right)) ||
+ (crop.bottom != roundf(crop.bottom)));
if (layer_->src_rect != src_rect) {
geometry_changes_ |= kSourceCrop;
layer_->src_rect = src_rect;
@@ -801,13 +805,13 @@
uint32_t frame_rate = layer->frame_rate;
if (getMetaData(handle, GET_REFRESH_RATE, &fps) == 0) {
frame_rate = (fps != 0) ? RoundToStandardFPS(fps) : layer->frame_rate;
+ has_metadata_refresh_rate_ = true;
}
int32_t interlaced = 0;
- bool interlace = layer_buffer->flags.interlace;
- if (getMetaData(handle, GET_PP_PARAM_INTERLACED, &interlaced) == 0) {
- interlace = interlaced ? true : false;
- }
+ getMetaData(handle, GET_PP_PARAM_INTERLACED, &interlaced);
+ bool interlace = interlaced ? true : false;
+
if (interlace != layer_buffer->flags.interlace) {
DLOGI("Layer buffer interlaced metadata has changed. old=%d, new=%d",
layer_buffer->flags.interlace, interlace);
diff --git a/sdm/libs/hwc2/hwc_layers.h b/sdm/libs/hwc2/hwc_layers.h
index 46e83cb..b5d5eaa 100644
--- a/sdm/libs/hwc2/hwc_layers.h
+++ b/sdm/libs/hwc2/hwc_layers.h
@@ -109,6 +109,8 @@
static LayerBufferFormat GetSDMFormat(const int32_t &source, const int flags);
bool IsSurfaceUpdated() { return surface_updated_; }
void SetPartialUpdate(bool enabled) { partial_update_enabled_ = enabled; }
+ bool IsNonIntegralSourceCrop() { return non_integral_source_crop_; }
+ bool HasMetaDataRefreshRate() { return has_metadata_refresh_rate_; }
private:
Layer *layer_ = nullptr;
@@ -127,6 +129,8 @@
bool dataspace_supported_ = false;
bool partial_update_enabled_ = false;
bool surface_updated_ = true;
+ bool non_integral_source_crop_ = false;
+ bool has_metadata_refresh_rate_ = false;
// Composition requested by client(SF)
HWC2::Composition client_requested_ = HWC2::Composition::Device;