drm_hwcomposer: Make flattening thread-based instead of vsync-based
Using vsync means consume some CPU time every frame for
IRQ -> Kernel_Thread -> UserSpace_listener thread transitions.
Framework tries to reduce vsync usage to the minimum, by using timelines
instead.
New flattening controller thread wakes-up only once per second.
This commit also removes flattening info from dumpsys. Practice shows
that it is almost useless. Instead debugging can be done using ALOGV
dumps.
Signed-off-by: Roman Stratiienko <r.stratiienko@gmail.com>
diff --git a/hwc2_device/HwcDisplay.cpp b/hwc2_device/HwcDisplay.cpp
index cdcf518..13da016 100644
--- a/hwc2_device/HwcDisplay.cpp
+++ b/hwc2_device/HwcDisplay.cpp
@@ -50,32 +50,12 @@
}
std::string HwcDisplay::Dump() {
- std::string flattening_state_str;
- switch (flattenning_state_) {
- case ClientFlattenningState::Disabled:
- flattening_state_str = "Disabled";
- break;
- case ClientFlattenningState::NotRequired:
- flattening_state_str = "Not needed";
- break;
- case ClientFlattenningState::Flattened:
- flattening_state_str = "Active";
- break;
- case ClientFlattenningState::ClientRefreshRequested:
- flattening_state_str = "Refresh requested";
- break;
- default:
- flattening_state_str = std::to_string(flattenning_state_) +
- " VSync remains";
- }
-
auto connector_name = IsInHeadlessMode()
? std::string("NULL-DISPLAY")
: GetPipe().connector->Get()->GetName();
std::stringstream ss;
ss << "- Display on: " << connector_name << "\n"
- << " Flattening state: " << flattening_state_str << "\n"
<< "Statistics since system boot:\n"
<< DumpDelta(total_stats_) << "\n\n"
<< "Statistics since last dumpsys request:\n"
@@ -140,6 +120,10 @@
current_plan_.reset();
backend_.reset();
+ if (flatcon_) {
+ flatcon_->StopThread();
+ flatcon_.reset();
+ }
}
if (vsync_worker_) {
@@ -162,14 +146,10 @@
GetDisplayVsyncPeriod(&period_ns);
hwc2_->SendVsyncEventToClient(handle_, timestamp, period_ns);
}
- if (vsync_flattening_en_) {
- ProcessFlatenningVsyncInternal();
- }
if (vsync_tracking_en_) {
last_vsync_ts_ = timestamp;
}
- if (!vsync_event_en_ && !vsync_flattening_en_ &&
- !vsync_tracking_en_) {
+ if (!vsync_event_en_ && !vsync_tracking_en_) {
vsync_worker_->VSyncControl(false);
}
},
@@ -192,6 +172,13 @@
ALOGE("Failed to set backend for d=%d %d\n", int(handle_), ret);
return HWC2::Error::BadDisplay;
}
+ auto flatcbk = (struct FlatConCallbacks){.trigger = [this]() {
+ if (hwc2_->refresh_callback_.first != nullptr &&
+ hwc2_->refresh_callback_.second != nullptr)
+ hwc2_->refresh_callback_.first(hwc2_->refresh_callback_.second,
+ handle_);
+ }};
+ flatcon_ = FlatteningController::CreateInstance(flatcbk);
}
client_layer_.SetLayerBlendMode(HWC2_BLEND_MODE_PREMULTIPLIED);
@@ -1022,37 +1009,4 @@
backend_ = std::move(backend);
}
-/* returns true if composition should be sent to client */
-bool HwcDisplay::ProcessClientFlatteningState(bool skip) {
- const int flattenning_state = flattenning_state_;
- if (flattenning_state == ClientFlattenningState::Disabled) {
- return false;
- }
-
- if (skip) {
- flattenning_state_ = ClientFlattenningState::NotRequired;
- return false;
- }
-
- if (flattenning_state == ClientFlattenningState::ClientRefreshRequested) {
- flattenning_state_ = ClientFlattenningState::Flattened;
- return true;
- }
-
- vsync_flattening_en_ = true;
- vsync_worker_->VSyncControl(true);
- flattenning_state_ = ClientFlattenningState::VsyncCountdownMax;
- return false;
-}
-
-void HwcDisplay::ProcessFlatenningVsyncInternal() {
- if (flattenning_state_ > ClientFlattenningState::ClientRefreshRequested &&
- --flattenning_state_ == ClientFlattenningState::ClientRefreshRequested &&
- hwc2_->refresh_callback_.first != nullptr &&
- hwc2_->refresh_callback_.second != nullptr) {
- hwc2_->refresh_callback_.first(hwc2_->refresh_callback_.second, handle_);
- vsync_flattening_en_ = false;
- }
-}
-
} // namespace android
diff --git a/hwc2_device/HwcDisplay.h b/hwc2_device/HwcDisplay.h
index 653aa4a..bf95c3e 100644
--- a/hwc2_device/HwcDisplay.h
+++ b/hwc2_device/HwcDisplay.h
@@ -23,6 +23,7 @@
#include <sstream>
#include "HwcDisplayConfigs.h"
+#include "compositor/FlatteningController.h"
#include "compositor/LayerData.h"
#include "drm/DrmAtomicStateManager.h"
#include "drm/ResourceManager.h"
@@ -165,10 +166,6 @@
return total_stats_;
}
- /* returns true if composition should be sent to client */
- bool ProcessClientFlatteningState(bool skip);
- void ProcessFlatenningVsyncInternal();
-
/* Headless mode required to keep SurfaceFlinger alive when all display are
* disconnected, Without headless mode Android will continuously crash.
* Only single internal (primary) display is required to be in HEADLESS mode
@@ -181,17 +178,11 @@
void Deinit();
+ auto GetFlatCon() {
+ return flatcon_;
+ }
+
private:
- enum ClientFlattenningState : int32_t {
- Disabled = -3,
- NotRequired = -2,
- Flattened = -1,
- ClientRefreshRequested = 0,
- VsyncCountdownMax = 60, /* 1 sec @ 60FPS */
- };
-
- std::atomic_int flattenning_state_{ClientFlattenningState::NotRequired};
-
HwcDisplayConfigs configs_;
DrmHwcTwo *const hwc2_;
@@ -205,10 +196,10 @@
DrmDisplayPipeline *pipeline_{};
std::unique_ptr<Backend> backend_;
+ std::shared_ptr<FlatteningController> flatcon_;
std::shared_ptr<VSyncWorker> vsync_worker_;
bool vsync_event_en_{};
- bool vsync_flattening_en_{};
bool vsync_tracking_en_{};
int64_t last_vsync_ts_{};