drm_hwcomposer: Add statistics on flattening to dump message
We need some way to verify that current composition is not failed to
compose, but instead sent to flatten on GPU.
Dump message shows current flattening state. It also displays how
often do compositor switches into flattening.
Signed-off-by: Roman Kovalivskyi <roman.kovalivskyi@globallogic.com>
diff --git a/compositor/drmdisplaycompositor.cpp b/compositor/drmdisplaycompositor.cpp
index 401af48..1519736 100644
--- a/compositor/drmdisplaycompositor.cpp
+++ b/compositor/drmdisplaycompositor.cpp
@@ -23,6 +23,7 @@
#include <sched.h>
#include <stdlib.h>
#include <time.h>
+#include <array>
#include <sstream>
#include <vector>
@@ -40,6 +41,15 @@
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)];
+}
+
class CompositorVsyncCallback : public VsyncCallback {
public:
CompositorVsyncCallback(DrmDisplayCompositor *compositor)
@@ -64,7 +74,8 @@
dump_last_timestamp_ns_(0),
flatten_countdown_(FLATTEN_COUNTDOWN_INIT),
writeback_fence_(-1),
- flattening_state_(FlatteningState::kNone) {
+ flattening_state_(FlatteningState::kNone),
+ frames_flattened_(0) {
struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts))
return;
@@ -148,6 +159,10 @@
return flattening_state_;
}
+uint32_t DrmDisplayCompositor::GetFlattenedFramesCount() const {
+ return frames_flattened_;
+}
+
bool DrmDisplayCompositor::ShouldFlattenOnClient() const {
return flattening_state_ == FlatteningState::kClientRequested ||
flattening_state_ == FlatteningState::kClientDone;
@@ -616,9 +631,9 @@
flatten_countdown_ = FLATTEN_COUNTDOWN_INIT;
if (flattening_state_ != FlatteningState::kClientRequested) {
- flattening_state_ = FlatteningState::kNone;
+ SetFlattening(FlatteningState::kNone);
} else {
- flattening_state_ = FlatteningState::kClientDone;
+ SetFlattening(FlatteningState::kClientDone);
}
vsync_worker_.VSyncControl(!writeback);
}
@@ -776,6 +791,23 @@
return 0;
}
+void DrmDisplayCompositor::SetFlattening(FlatteningState new_state) {
+ if (flattening_state_ != new_state) {
+ switch (flattening_state_) {
+ case FlatteningState::kClientDone:
+ case FlatteningState::kConcurrent:
+ case FlatteningState::kSerial:
+ ++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;
}
@@ -787,7 +819,7 @@
if (!IsFlatteningNeeded()) {
if (flattening_state_ != FlatteningState::kClientDone) {
ALOGV("Flattening is not needed");
- flattening_state_ = FlatteningState::kNotNeeded;
+ SetFlattening(FlatteningState::kNotNeeded);
}
return -EALREADY;
}
@@ -796,7 +828,7 @@
ALOGV(
"No writeback connector available, "
"falling back to client composition");
- flattening_state_ = FlatteningState::kClientRequested;
+ SetFlattening(FlatteningState::kClientRequested);
refresh_display_cb_(display_);
return 0;
} else {
@@ -822,7 +854,7 @@
return ret;
if (!IsFlatteningNeeded()) {
ALOGV("Flattening is not needed");
- flattening_state_ = FlatteningState::kNotNeeded;
+ SetFlattening(FlatteningState::kNotNeeded);
return -EALREADY;
}
@@ -931,7 +963,7 @@
return ret;
if (!IsFlatteningNeeded()) {
ALOGV("Flattening is not needed");
- flattening_state_ = FlatteningState::kNotNeeded;
+ SetFlattening(FlatteningState::kNotNeeded);
return -EALREADY;
}
DrmCrtc *crtc = active_composition_->crtc();
@@ -1007,10 +1039,10 @@
}
if (writeback_conn->display() != display_) {
- flattening_state_ = FlatteningState::kConcurrent;
+ SetFlattening(FlatteningState::kConcurrent);
return FlattenConcurrent(writeback_conn);
} else {
- flattening_state_ = FlatteningState::kSerial;
+ SetFlattening(FlatteningState::kSerial);
return FlattenSerial(writeback_conn);
}
diff --git a/drmhwctwo.cpp b/drmhwctwo.cpp
index a4a8187..605406b 100644
--- a/drmhwctwo.cpp
+++ b/drmhwctwo.cpp
@@ -142,6 +142,7 @@
<< ((delta.failed_kms_present_ > 0)
? " !!! Internal failure, FIX it please\n"
: "")
+ << " Flattened frames: " << delta.frames_flattened_ << "\n"
<< " Pixel operations (free units)"
<< " : [TOTAL: " << delta.total_pixops_
<< " / GPU: " << delta.gpu_pixops_ << "]\n"
@@ -152,6 +153,8 @@
std::string DrmHwcTwo::HwcDisplay::Dump() {
auto out = (std::stringstream()
<< "- Display on: " << connector_->name() << "\n"
+ << " Flattening state: " << compositor_.GetFlatteningState()
+ << "\n"
<< "Statistics since system boot:\n"
<< DumpDelta(total_stats_) << "\n\n"
<< "Statistics since last dumpsys request:\n"
@@ -970,6 +973,7 @@
*num_types = client_size;
+ total_stats_.frames_flattened_ = compositor_.GetFlattenedFramesCount();
total_stats_.gpu_pixops_ += gpu_pixops;
total_stats_.total_pixops_ += total_pixops;
diff --git a/include/drmdisplaycompositor.h b/include/drmdisplaycompositor.h
index cfd8f4a..26e2572 100644
--- a/include/drmdisplaycompositor.h
+++ b/include/drmdisplaycompositor.h
@@ -50,6 +50,8 @@
kConcurrent
};
+std::ostream &operator<<(std::ostream &str, FlatteningState state);
+
class DrmDisplayCompositor {
public:
DrmDisplayCompositor();
@@ -77,6 +79,7 @@
}
FlatteningState GetFlatteningState() const;
+ uint32_t GetFlattenedFramesCount() const;
bool ShouldFlattenOnClient() const;
std::tuple<uint32_t, uint32_t, int> GetActiveModeResolution();
@@ -108,6 +111,7 @@
void ApplyFrame(std::unique_ptr<DrmDisplayComposition> composition,
int status, bool writeback = false);
+ void SetFlattening(FlatteningState new_state);
bool IsFlatteningNeeded() const;
int FlattenActiveComposition();
int FlattenOnClient();
@@ -148,6 +152,7 @@
int writeback_fence_;
FlatteningState flattening_state_;
+ uint32_t frames_flattened_;
std::function<void(int)> refresh_display_cb_;
};
diff --git a/include/drmhwctwo.h b/include/drmhwctwo.h
index 43f1fce..2bbe334 100644
--- a/include/drmhwctwo.h
+++ b/include/drmhwctwo.h
@@ -260,9 +260,11 @@
struct Stats {
Stats minus(Stats b) {
return {total_frames_ - b.total_frames_,
- total_pixops_ - b.total_pixops_, gpu_pixops_ - b.gpu_pixops_,
+ total_pixops_ - b.total_pixops_,
+ gpu_pixops_ - b.gpu_pixops_,
failed_kms_validate_ - b.failed_kms_validate_,
- failed_kms_present_ - b.failed_kms_present_};
+ failed_kms_present_ - b.failed_kms_present_,
+ frames_flattened_ - b.frames_flattened_};
}
uint32_t total_frames_ = 0;
@@ -270,6 +272,7 @@
uint64_t gpu_pixops_ = 0;
uint32_t failed_kms_validate_ = 0;
uint32_t failed_kms_present_ = 0;
+ uint32_t frames_flattened_ = 0;
} total_stats_, prev_stats_;
std::string DumpDelta(DrmHwcTwo::HwcDisplay::Stats delta);
};