Merge "composer: Long term large composition hint"
diff --git a/composer/cpuhint.cpp b/composer/cpuhint.cpp
index bccbe33..d33b470 100644
--- a/composer/cpuhint.cpp
+++ b/composer/cpuhint.cpp
@@ -46,13 +46,16 @@
}
if (vendor_ext_lib_.Open(path)) {
- if (!vendor_ext_lib_.Sym("perf_event_offload", reinterpret_cast<void **> \
- (&fn_perf_event_offload_))) {
+ if (!vendor_ext_lib_.Sym("perf_hint_acq_rel_offload",
+ reinterpret_cast<void **>(&fn_perf_hint_acq_rel_offload_)) ||
+ !vendor_ext_lib_.Sym("perf_lock_rel_offload",
+ reinterpret_cast<void **>(&fn_perf_lock_rel_offload_))) {
DLOGW("Failed to load symbols for Vendor Extension Library");
return kErrorNotSupported;
}
DLOGI("Successfully Loaded Vendor Extension Library symbols");
- enabled_ = (fn_perf_event_offload_ != NULL);
+ enabled_ = (fn_perf_hint_acq_rel_offload_ != NULL &&
+ fn_perf_lock_rel_offload_ != NULL);
} else {
DLOGW("Failed to open %s : %s", path, vendor_ext_lib_.Error());
}
@@ -60,13 +63,65 @@
return enabled_ ? kErrorNone : kErrorNotSupported;
}
-void CPUHint::ReqHintsOffload(int hint, int duration) {
+int CPUHint::ReqHintsOffload(int hint, int tid) {
if(enabled_ && hint > 0) {
- int args[] = {0, duration};
- int handle = fn_perf_event_offload_(hint, NULL, 2, args);
- if (handle < 0) {
- DLOGW("Failed to send hint 0x%x. handle = %d", hint, handle);
+ if (large_comp_cycle_.status == kActive) {
+ nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
+ nsecs_t difference = currentTime-large_comp_cycle_.startTime;
+
+ if (nanoseconds_to_seconds(difference) >= 4) {
+ DLOGV_IF(kTagCpuHint, "Renew large composition hint:%d [start_time:%" PRIu64
+ " - current_time:%" PRIu64 " = %" PRIu64 "]", large_comp_cycle_.handleId,
+ large_comp_cycle_.startTime, currentTime, difference);
+
+ large_comp_cycle_.status = kRenew;
+ }
+
+ if (tid != 0 && tid != large_comp_cycle_.tid) {
+ DLOGV_IF(kTagCpuHint, "Renew large composition hint:%d [oldTid:%d newTid:%d]",
+ large_comp_cycle_.handleId, large_comp_cycle_.tid, tid);
+
+ large_comp_cycle_.status = kRenew;
+ }
+ }
+
+ if (large_comp_cycle_.status == kInactive || large_comp_cycle_.status == kRenew) {
+ PerfHintStatus current_status = large_comp_cycle_.status;
+ int handle = fn_perf_hint_acq_rel_offload_(large_comp_cycle_.handleId, hint, nullptr,
+ tid, 0, 0, nullptr);
+ if (handle < 0) {
+ DLOGW("Failed to request large composition hint ret:%d", handle);
+ return -1;
+ }
+
+ large_comp_cycle_.handleId = handle;
+ large_comp_cycle_.tid = (tid != 0) ? tid : large_comp_cycle_.tid;
+ large_comp_cycle_.startTime = systemTime(SYSTEM_TIME_MONOTONIC);
+ large_comp_cycle_.status = kActive;
+ DLOGV_IF(kTagCpuHint, "Successfully %s large comp hint: handle_id:%d type:0x%x startTime:%"
+ PRIu64 " status:%d", (current_status == kInactive) ? "initialized" : "renewed",
+ large_comp_cycle_.handleId, kLargeComposition, large_comp_cycle_.startTime,
+ large_comp_cycle_.status);
}
}
+
+ return 0;
+}
+
+int CPUHint::ReqHintRelease() {
+ if (large_comp_cycle_.status == kActive || large_comp_cycle_.status == kRenew) {
+ int ret = fn_perf_lock_rel_offload_(large_comp_cycle_.handleId);
+ if (ret < 0) {
+ DLOGV_IF(kTagCpuHint, "Failed to release large comp hint ret:%d", ret);
+ return -1;
+ }
+
+ DLOGV_IF(kTagCpuHint, "Release large comp hint ret:%d", ret);
+ large_comp_cycle_.handleId = 0;
+ large_comp_cycle_.tid = 0;
+ large_comp_cycle_.startTime = 0;
+ large_comp_cycle_.status = kInactive;
+ }
+ return 0;
}
} // namespace sdm
diff --git a/composer/cpuhint.h b/composer/cpuhint.h
index 97aad2a..fcc7c95 100644
--- a/composer/cpuhint.h
+++ b/composer/cpuhint.h
@@ -32,20 +32,42 @@
#include <core/sdm_types.h>
#include <utils/sys.h>
+#include <utils/Timers.h>
namespace sdm {
+enum PerfHintStatus {
+ kInactive = 0,
+ kActive,
+ kRenew,
+};
+
+struct LongTermHintInfo {
+ int handleId = 0;
+ int tid = 0;
+ nsecs_t startTime = 0;
+ PerfHintStatus status = kInactive;
+};
+
class HWCDebugHandler;
class CPUHint {
public:
DisplayError Init(HWCDebugHandler *debug_handler);
- void ReqHintsOffload(int hint, int duration);
+ int ReqHintsOffload(int hint, int tid);
+ int ReqHintRelease();
private:
+ const int kLargeComposition = 0x00001097;
+
bool enabled_ = false;
DynLib vendor_ext_lib_;
- int (*fn_perf_event_offload_)(int hint, const char *pkg, int numArgs, int *) = NULL;
+ int (*fn_perf_hint_acq_rel_offload_)(int handle, int hint, const char *pkg, int duration,
+ int type, int numArgs, int list[]) = NULL;
+ int (*fn_perf_lock_rel_offload_)(int handle) = NULL;
+ std::mutex tid_lock_;
+
+ LongTermHintInfo large_comp_cycle_ {};
};
} // namespace sdm
diff --git a/composer/hwc_display_builtin.cpp b/composer/hwc_display_builtin.cpp
index d01cff4..1cd02bd 100644
--- a/composer/hwc_display_builtin.cpp
+++ b/composer/hwc_display_builtin.cpp
@@ -1309,24 +1309,23 @@
return 0;
}
-void HWCDisplayBuiltIn::SetCpuPerfHintLargeCompCycle() {
+bool HWCDisplayBuiltIn::NeedsLargeCompPerfHint() {
if (!cpu_hint_ || !perf_hint_large_comp_cycle_) {
DLOGV_IF(kTagResources, "cpu_hint_:%d not initialized or property:%d not set",
!cpu_hint_, !perf_hint_large_comp_cycle_);
- return;
+
+ return false;
}
if (active_refresh_rate_ < 120) {
- return;
+ return false;
}
// Send hints when the device is in multi-display or when a skip layer is present.
if (layer_stack_.flags.skip_present || is_multi_display_) {
DLOGV_IF(kTagResources, "Found skip_layer:%d or is_multidisplay:%d. Set perf hint for large "
"comp cycle", layer_stack_.flags.skip_present, is_multi_display_);
- int hwc_tid = gettid();
- cpu_hint_->ReqHintsOffload(kPerfHintLargeCompCycle, hwc_tid);
- return;
+ return true;
}
int gpu_layer_count = 0;
@@ -1339,27 +1338,26 @@
// Return immediately if full MDP comp is in use
if (!gpu_layer_count) {
- return;
+ return false;
}
- auto it = mixed_mode_threshold_.find(active_refresh_rate_);
+ auto it = mixed_mode_threshold_.find(active_refresh_rate_);;
if (it != mixed_mode_threshold_.end()) {
if (gpu_layer_count < it->second) {
DLOGV_IF(kTagResources, "Number of GPU layers :%d does not meet mixed mode perf hints "
"threshold:%d for %d fps", gpu_layer_count, it->second, active_refresh_rate_);
- return;
+ return false;
}
} else {
DLOGV_IF(kTagResources, "Mixed mode perf hints is not supported for %d fps",
active_refresh_rate_);
- return;
+ return false;
}
// Send hints when the number of GPU layers reaches the threshold for the active refresh rate.
DLOGV_IF(kTagResources, "Reached max GPU layers for %dfps. Set perf hint for large comp cycle",
active_refresh_rate_);
- int hwc_tid = gettid();
- cpu_hint_->ReqHintsOffload(kPerfHintLargeCompCycle, hwc_tid);
+ return true;
}
HWC2::Error HWCDisplayBuiltIn::PostCommitLayerStack(shared_ptr<Fence> *out_retire_fence) {
@@ -1457,7 +1455,8 @@
auto status = HWCDisplay::CommitOrPrepare(validate_only, out_retire_fence, out_num_types,
out_num_requests, needs_commit);
- SetCpuPerfHintLargeCompCycle();
+ bool needs_hint = NeedsLargeCompPerfHint();
+ HandleLargeCompositionHint(!needs_hint);
return status;
}
@@ -1536,4 +1535,27 @@
return HWC2::Error::None;
}
+void HWCDisplayBuiltIn::HandleLargeCompositionHint(bool release) {
+ int tid = gettid();
+
+ if (release) {
+ num_basic_frames_++;
+
+ if (num_basic_frames_ >= active_refresh_rate_) {
+ cpu_hint_->ReqHintRelease();
+ }
+ return;
+ }
+
+ if (hwc_tid_ != tid) {
+ DLOGV_IF(kTagResources, "HWC's tid:%d is updated to :%d", hwc_tid_, tid);
+ cpu_hint_->ReqHintsOffload(kPerfHintLargeCompCycle, tid);
+ hwc_tid_ = tid;
+ } else {
+ cpu_hint_->ReqHintsOffload(kPerfHintLargeCompCycle, 0);
+ }
+
+ num_basic_frames_ = 0;
+}
+
} // namespace sdm
diff --git a/composer/hwc_display_builtin.h b/composer/hwc_display_builtin.h
index 93d2a7b..87974e1 100644
--- a/composer/hwc_display_builtin.h
+++ b/composer/hwc_display_builtin.h
@@ -166,13 +166,14 @@
void InitStitchTarget();
bool AllocateStitchBuffer();
void PostCommitStitchLayers();
- void SetCpuPerfHintLargeCompCycle();
+ bool NeedsLargeCompPerfHint();
void ValidateUiScaling();
void EnablePartialUpdate();
uint32_t GetUpdatingAppLayersCount();
int ValidateFrameCaptureConfig(const BufferInfo &output_buffer_info,
const CwbTapPoint &cwb_tappoint);
void LoadMixedModePerfHintThreshold();
+ void HandleLargeCompositionHint(bool release);
// SyncTask methods.
void OnTask(const LayerStitchTaskCode &task_code,
@@ -211,6 +212,10 @@
shared_ptr<Fence> retire_fence_ = nullptr;
std::unordered_map<int32_t, int32_t> mixed_mode_threshold_;
int alternate_config_ = -1;
+
+ // Long term large composition hint
+ int hwc_tid_ = 0;
+ uint32_t num_basic_frames_ = 0;
};
} // namespace sdm
diff --git a/sdm/include/core/sdm_types.h b/sdm/include/core/sdm_types.h
index 3618253..ec3f6c9 100644
--- a/sdm/include/core/sdm_types.h
+++ b/sdm/include/core/sdm_types.h
@@ -95,6 +95,7 @@
kTagClient, //!< Debug log is tagged for SDM client.
kTagQOSImpl, //!< Debug log is tagged for Qos library Implementation.
kTagStitchBuffer, //!< Debug log is tagged for Stitch Buffer Implementation.
+ kTagCpuHint, //!< Debug log is tagged for CPU hint Implementation.
};
} // namespace sdm