drm_hwcomposer: Move client flattening closer to the frontend
Remove unnecessary code from DrmCompositor.
Drops ~100 LoC.
Signed-off-by: Roman Stratiienko <roman.o.stratiienko@globallogic.com>
diff --git a/DrmHwcTwo.cpp b/DrmHwcTwo.cpp
index 10177e9..6ec8b31 100644
--- a/DrmHwcTwo.cpp
+++ b/DrmHwcTwo.cpp
@@ -140,9 +140,28 @@
}
std::string DrmHwcTwo::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";
+ }
+
std::stringstream ss;
ss << "- Display on: " << connector_->name() << "\n"
- << " Flattening state: " << compositor_.GetFlatteningState() << "\n"
+ << " Flattening state: " << flattening_state_str << "\n"
<< "Statistics since system boot:\n"
<< DumpDelta(total_stats_) << "\n\n"
<< "Statistics since last dumpsys request:\n"
@@ -246,14 +265,7 @@
}
int display = static_cast<int>(handle_);
- int ret = compositor_.Init(resource_manager_, display, [this] {
- /* refresh callback */
- const std::lock_guard<std::mutex> lock(hwc2_->callback_lock_);
- if (hwc2_->refresh_callback_.first != nullptr &&
- hwc2_->refresh_callback_.second != nullptr) {
- hwc2_->refresh_callback_.first(hwc2_->refresh_callback_.second, handle_);
- }
- });
+ int ret = compositor_.Init(resource_manager_, display);
if (ret) {
ALOGE("Failed display compositor init for display %d (%d)", display, ret);
return HWC2::Error::NoResources;
@@ -307,6 +319,23 @@
return HWC2::Error::BadDisplay;
}
+ ret = flattening_vsync_worker_.Init(drm_, display, [this](int64_t /*timestamp*/) {
+ const std::lock_guard<std::mutex> lock(hwc2_->callback_lock_);
+ /* Frontend flattening */
+ 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_);
+ flattening_vsync_worker_.VSyncControl(false);
+ }
+ });
+ if (ret) {
+ ALOGE("Failed to create event worker for d=%d %d\n", display, ret);
+ return HWC2::Error::BadDisplay;
+ }
+
ret = BackendManager::GetInstance().SetBackendForDisplay(this);
if (ret) {
ALOGE("Failed to set backend for d=%d %d\n", display, ret);
diff --git a/DrmHwcTwo.h b/DrmHwcTwo.h
index 19355cd..0d213fd 100644
--- a/DrmHwcTwo.h
+++ b/DrmHwcTwo.h
@@ -293,7 +293,40 @@
return total_stats_;
}
+ /* returns true if composition should be sent to client */
+ bool ProcessClientFlatteningState(bool skip) {
+ 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;
+ }
+
+ flattening_vsync_worker_.VSyncControl(true);
+ flattenning_state_ = ClientFlattenningState::VsyncCountdownMax;
+ return false;
+ }
+
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};
+ VSyncWorker flattening_vsync_worker_;
+
void AddFenceToPresentFence(UniqueFd fd);
constexpr static size_t MATRIX_SIZE = 16;
diff --git a/backend/Backend.cpp b/backend/Backend.cpp
index 312faed..d7eb240 100644
--- a/backend/Backend.cpp
+++ b/backend/Backend.cpp
@@ -34,7 +34,8 @@
int client_start = -1;
size_t client_size = 0;
- if (display->compositor().ShouldFlattenOnClient()) {
+ if (display->ProcessClientFlatteningState(layers.size() <= 1)) {
+ display->total_stats().frames_flattened_++;
client_start = 0;
client_size = layers.size();
MarkValidated(layers, client_start, client_size);
@@ -56,8 +57,6 @@
*num_types = client_size;
- display->total_stats().frames_flattened_ = display->compositor()
- .GetFlattenedFramesCount();
display->total_stats().gpu_pixops_ += CalcPixOps(layers, client_start,
client_size);
display->total_stats().total_pixops_ += CalcPixOps(layers, 0, layers.size());
diff --git a/compositor/DrmDisplayCompositor.cpp b/compositor/DrmDisplayCompositor.cpp
index 5ad2de2..5b16cad 100644
--- a/compositor/DrmDisplayCompositor.cpp
+++ b/compositor/DrmDisplayCompositor.cpp
@@ -40,15 +40,6 @@
namespace android {
-std::ostream &operator<<(std::ostream &str, FlatteningState state) {
- std::array<const char *, 6> flattenting_state_str = {
- "None", "Not needed", "SF Requested", "Squashed by GPU",
- "Serial", "Concurrent",
- };
-
- return str << flattenting_state_str[static_cast<int>(state)];
-}
-
DrmDisplayCompositor::DrmDisplayCompositor()
: resource_manager_(nullptr),
display_(-1),
@@ -56,10 +47,7 @@
active_(false),
use_hw_overlays_(true),
dump_frames_composited_(0),
- dump_last_timestamp_ns_(0),
- flatten_countdown_(FLATTEN_COUNTDOWN_INIT),
- flattening_state_(FlatteningState::kNone),
- frames_flattened_(0) {
+ dump_last_timestamp_ns_(0) {
struct timespec ts {};
if (clock_gettime(CLOCK_MONOTONIC, &ts))
return;
@@ -69,11 +57,6 @@
DrmDisplayCompositor::~DrmDisplayCompositor() {
if (!initialized_)
return;
-
- vsync_worker_.Exit();
- int ret = pthread_mutex_lock(&lock_);
- if (ret)
- ALOGE("Failed to acquire compositor lock %d", ret);
DrmDevice *drm = resource_manager_->GetDrmDevice(display_);
if (mode_.blob_id)
drm->DestroyPropertyBlob(mode_.blob_id);
@@ -81,18 +64,10 @@
drm->DestroyPropertyBlob(mode_.old_blob_id);
active_composition_.reset();
-
- ret = pthread_mutex_unlock(&lock_);
- if (ret)
- ALOGE("Failed to acquire compositor lock %d", ret);
-
- pthread_mutex_destroy(&lock_);
}
-auto DrmDisplayCompositor::Init(ResourceManager *resource_manager, int display,
- std::function<void()> client_refresh_callback)
+auto DrmDisplayCompositor::Init(ResourceManager *resource_manager, int display)
-> int {
- client_refresh_callback_ = std::move(client_refresh_callback);
resource_manager_ = resource_manager;
display_ = display;
DrmDevice *drm = resource_manager_->GetDrmDevice(display);
@@ -100,27 +75,8 @@
ALOGE("Could not find drmdevice for display");
return -EINVAL;
}
- int ret = pthread_mutex_init(&lock_, nullptr);
- if (ret) {
- ALOGE("Failed to initialize drm compositor lock %d\n", ret);
- return ret;
- }
planner_ = Planner::CreateInstance(drm);
- vsync_worker_.Init(drm, display_, [this](int64_t timestamp) {
- AutoLock lock(&lock_, "DrmDisplayCompositor::Init()");
- if (lock.Lock())
- return;
- flatten_countdown_--;
- if (!CountdownExpired())
- return;
- lock.Unlock();
- int ret = FlattenActiveComposition();
- ALOGV("scene flattening triggered for display %d at timestamp %" PRIu64
- " result = %d \n",
- display_, timestamp, ret);
- });
-
initialized_ = true;
return 0;
}
@@ -137,19 +93,6 @@
return std::make_unique<DrmDisplayComposition>(crtc, planner_.get());
}
-FlatteningState DrmDisplayCompositor::GetFlatteningState() const {
- return flattening_state_;
-}
-
-uint32_t DrmDisplayCompositor::GetFlattenedFramesCount() const {
- return frames_flattened_;
-}
-
-bool DrmDisplayCompositor::ShouldFlattenOnClient() const {
- return flattening_state_ == FlatteningState::kClientRequested ||
- flattening_state_ == FlatteningState::kClientDone;
-}
-
std::tuple<uint32_t, uint32_t, int>
DrmDisplayCompositor::GetActiveModeResolution() {
DrmDevice *drm = resource_manager_->GetDrmDevice(display_);
@@ -348,9 +291,6 @@
void DrmDisplayCompositor::ApplyFrame(
std::unique_ptr<DrmDisplayComposition> composition, int status) {
- AutoLock lock(&lock_, __func__);
- if (lock.Lock())
- return;
int ret = status;
if (!ret) {
@@ -367,14 +307,6 @@
++dump_frames_composited_;
active_composition_.swap(composition);
-
- flatten_countdown_ = FLATTEN_COUNTDOWN_INIT;
- if (flattening_state_ != FlatteningState::kClientRequested) {
- SetFlattening(FlatteningState::kNone);
- } else {
- SetFlattening(FlatteningState::kClientDone);
- }
- vsync_worker_.VSyncControl(true);
}
int DrmDisplayCompositor::ApplyComposition(
@@ -424,70 +356,13 @@
return CommitFrame(composition, true);
}
-void DrmDisplayCompositor::SetFlattening(FlatteningState new_state) {
- if (flattening_state_ != new_state) {
- switch (flattening_state_) {
- case FlatteningState::kClientDone:
- ++frames_flattened_;
- break;
- case FlatteningState::kClientRequested:
- case FlatteningState::kNone:
- case FlatteningState::kNotNeeded:
- break;
- }
- }
- flattening_state_ = new_state;
-}
-
-bool DrmDisplayCompositor::IsFlatteningNeeded() const {
- return CountdownExpired() && active_composition_->layers().size() >= 2;
-}
-
-int DrmDisplayCompositor::FlattenOnClient() {
- if (client_refresh_callback_) {
- {
- AutoLock lock(&lock_, __func__);
- if (!IsFlatteningNeeded()) {
- if (flattening_state_ != FlatteningState::kClientDone) {
- ALOGV("Flattening is not needed");
- SetFlattening(FlatteningState::kNotNeeded);
- }
- return -EALREADY;
- }
- }
-
- ALOGV(
- "No writeback connector available, "
- "falling back to client composition");
- SetFlattening(FlatteningState::kClientRequested);
- client_refresh_callback_();
- return 0;
- }
-
- ALOGV("No writeback connector available");
- return -EINVAL;
-}
-
-int DrmDisplayCompositor::FlattenActiveComposition() {
- return FlattenOnClient();
-}
-
-bool DrmDisplayCompositor::CountdownExpired() const {
- return flatten_countdown_ <= 0;
-}
-
void DrmDisplayCompositor::Dump(std::ostringstream *out) const {
- int ret = pthread_mutex_lock(&lock_);
- if (ret)
- return;
-
uint64_t num_frames = dump_frames_composited_;
dump_frames_composited_ = 0;
struct timespec ts {};
- ret = clock_gettime(CLOCK_MONOTONIC, &ts);
+ int ret = clock_gettime(CLOCK_MONOTONIC, &ts);
if (ret) {
- pthread_mutex_unlock(&lock_);
return;
}
@@ -502,7 +377,5 @@
<< " fps=" << fps << "\n";
dump_last_timestamp_ns_ = cur_ts;
-
- pthread_mutex_unlock(&lock_);
}
} // namespace android
diff --git a/compositor/DrmDisplayCompositor.h b/compositor/DrmDisplayCompositor.h
index afdb79e..04c0bae 100644
--- a/compositor/DrmDisplayCompositor.h
+++ b/compositor/DrmDisplayCompositor.h
@@ -32,28 +32,14 @@
#include "drm/VSyncWorker.h"
#include "drmhwcomposer.h"
-// If a scene is still for this number of vblanks flatten it to reduce power
-// consumption.
-#define FLATTEN_COUNTDOWN_INIT 60
-
namespace android {
-enum class FlatteningState {
- kNone,
- kNotNeeded,
- kClientRequested,
- kClientDone,
-};
-
-std::ostream &operator<<(std::ostream &str, FlatteningState state);
-
class DrmDisplayCompositor {
public:
DrmDisplayCompositor();
~DrmDisplayCompositor();
- auto Init(ResourceManager *resource_manager, int display,
- std::function<void()> client_refresh_callback) -> int;
+ auto Init(ResourceManager *resource_manager, int display) -> int;
std::unique_ptr<DrmDisplayComposition> CreateInitializedComposition() const;
int ApplyComposition(std::unique_ptr<DrmDisplayComposition> composition);
@@ -68,14 +54,9 @@
return std::move(active_composition_->out_fence_);
}
- FlatteningState GetFlatteningState() const;
- uint32_t GetFlattenedFramesCount() const;
- bool ShouldFlattenOnClient() const;
-
std::tuple<uint32_t, uint32_t, int> GetActiveModeResolution();
private:
- std::function<void()> client_refresh_callback_;
struct ModeState {
bool needs_modeset = false;
DrmMode mode;
@@ -97,13 +78,6 @@
void ApplyFrame(std::unique_ptr<DrmDisplayComposition> composition,
int status);
- void SetFlattening(FlatteningState new_state);
- bool IsFlatteningNeeded() const;
- int FlattenActiveComposition();
- int FlattenOnClient();
-
- bool CountdownExpired() const;
-
std::tuple<int, uint32_t> CreateModeBlob(const DrmMode &mode);
ResourceManager *resource_manager_;
@@ -117,21 +91,11 @@
ModeState mode_;
- // mutable since we need to acquire in Dump()
- mutable pthread_mutex_t lock_{};
-
// State tracking progress since our last Dump(). These are mutable since
// we need to reset them on every Dump() call.
mutable uint64_t dump_frames_composited_;
mutable uint64_t dump_last_timestamp_ns_;
- VSyncWorker vsync_worker_;
- int64_t flatten_countdown_;
std::unique_ptr<Planner> planner_;
-
- FlatteningState flattening_state_;
- uint32_t frames_flattened_;
-
- std::function<void(int)> refresh_display_cb_;
};
} // namespace android