drm_hwcomposer: reimplement Dump for DrmDisplayCompositor
Also fixes hwc_dump sometimes failing to null terminate its output buffer.
TEST=dumpsys SurfaceFlinger
Change-Id: Ibf93cfd496a07a9375d78a8b239c2c7876aff986
diff --git a/drm_hwcomposer.h b/drm_hwcomposer.h
index 1490438..66c2c81 100644
--- a/drm_hwcomposer.h
+++ b/drm_hwcomposer.h
@@ -171,7 +171,7 @@
return *this;
}
- operator bool() {
+ operator bool() const {
return importer_ != NULL;
}
diff --git a/drmdisplaycomposition.cpp b/drmdisplaycomposition.cpp
index b374634..49bacad 100644
--- a/drmdisplaycomposition.cpp
+++ b/drmdisplaycomposition.cpp
@@ -328,4 +328,170 @@
return 0;
}
+
+static const char *DrmCompositionTypeToString(DrmCompositionType type) {
+ switch (type) {
+ case DRM_COMPOSITION_TYPE_EMPTY:
+ return "EMPTY";
+ case DRM_COMPOSITION_TYPE_FRAME:
+ return "FRAME";
+ case DRM_COMPOSITION_TYPE_DPMS:
+ return "DPMS";
+ case DRM_COMPOSITION_TYPE_MODESET:
+ return "MODESET";
+ default:
+ return "<invalid>";
+ }
+}
+
+static const char *DPMSModeToString(int dpms_mode) {
+ switch (dpms_mode) {
+ case DRM_MODE_DPMS_ON:
+ return "ON";
+ case DRM_MODE_DPMS_OFF:
+ return "OFF";
+ default:
+ return "<invalid>";
+ }
+}
+
+static void DumpBuffer(const DrmHwcBuffer &buffer, std::ostringstream *out) {
+ if (!buffer) {
+ *out << "buffer=<invalid>";
+ return;
+ }
+
+ *out << "buffer[w/h/format]=";
+ *out << buffer->width << "/" << buffer->height << "/" << buffer->format;
+}
+
+static const char *TransformToString(DrmHwcTransform transform) {
+ switch (transform) {
+ case DrmHwcTransform::kIdentity:
+ return "IDENTITY";
+ case DrmHwcTransform::kFlipH:
+ return "FLIPH";
+ case DrmHwcTransform::kFlipV:
+ return "FLIPV";
+ case DrmHwcTransform::kRotate90:
+ return "ROTATE90";
+ case DrmHwcTransform::kRotate180:
+ return "ROTATE180";
+ case DrmHwcTransform::kRotate270:
+ return "ROTATE270";
+ default:
+ return "<invalid>";
+ }
+}
+
+static const char *BlendingToString(DrmHwcBlending blending) {
+ switch (blending) {
+ case DrmHwcBlending::kNone:
+ return "NONE";
+ case DrmHwcBlending::kPreMult:
+ return "PREMULT";
+ case DrmHwcBlending::kCoverage:
+ return "COVERAGE";
+ default:
+ return "<invalid>";
+ }
+}
+
+static void DumpRegion(const DrmCompositionRegion ®ion,
+ std::ostringstream *out) {
+ *out << "frame";
+ region.frame.Dump(out);
+ *out << " source_layers=(";
+
+ const std::vector<size_t> &source_layers = region.source_layers;
+ for (size_t i = 0; i < source_layers.size(); i++) {
+ *out << source_layers[i];
+ if (i < source_layers.size() - 1) {
+ *out << " ";
+ }
+ }
+
+ *out << ")";
+}
+
+void DrmDisplayComposition::Dump(std::ostringstream *out) const {
+ *out << "----DrmDisplayComposition"
+ << " crtc=" << (crtc_ ? crtc_->id() : -1)
+ << " type=" << DrmCompositionTypeToString(type_);
+
+ switch (type_) {
+ case DRM_COMPOSITION_TYPE_DPMS:
+ *out << " dpms_mode=" << DPMSModeToString(dpms_mode_);
+ break;
+ case DRM_COMPOSITION_TYPE_MODESET:
+ *out << " display_mode=" << display_mode_.h_display() << "x"
+ << display_mode_.v_display();
+ break;
+ default:
+ break;
+ }
+
+ *out << " timeline[current/squash/pre-comp/done]=" << timeline_current_ << "/"
+ << timeline_squash_done_ << "/" << timeline_pre_comp_done_ << "/"
+ << timeline_ << "\n";
+
+ *out << " Layers: count=" << layers_.size() << "\n";
+ for (size_t i = 0; i < layers_.size(); i++) {
+ const DrmHwcLayer &layer = layers_[i];
+ *out << " [" << i << "] ";
+
+ DumpBuffer(layer.buffer, out);
+
+ *out << " transform=" << TransformToString(layer.transform)
+ << " blending[a=" << (int)layer.alpha
+ << "]=" << BlendingToString(layer.blending) << " source_crop";
+ layer.source_crop.Dump(out);
+ *out << " display_frame";
+ layer.display_frame.Dump(out);
+
+ *out << "\n";
+ }
+
+ *out << " Planes: count=" << composition_planes_.size() << "\n";
+ for (size_t i = 0; i < composition_planes_.size(); i++) {
+ const DrmCompositionPlane &comp_plane = composition_planes_[i];
+ *out << " [" << i << "]"
+ << " plane=" << (comp_plane.plane ? comp_plane.plane->id() : -1)
+ << " source_layer=";
+ if (comp_plane.source_layer <= DrmCompositionPlane::kSourceLayerMax) {
+ *out << comp_plane.source_layer;
+ } else {
+ switch (comp_plane.source_layer) {
+ case DrmCompositionPlane::kSourceNone:
+ *out << "NONE";
+ break;
+ case DrmCompositionPlane::kSourcePreComp:
+ *out << "PRECOMP";
+ break;
+ case DrmCompositionPlane::kSourceSquash:
+ *out << "SQUASH";
+ break;
+ default:
+ *out << "<invalid>";
+ break;
+ }
+ }
+
+ *out << "\n";
+ }
+
+ *out << " Squash Regions: count=" << squash_regions_.size() << "\n";
+ for (size_t i = 0; i < squash_regions_.size(); i++) {
+ *out << " [" << i << "] ";
+ DumpRegion(squash_regions_[i], out);
+ *out << "\n";
+ }
+
+ *out << " Pre-Comp Regions: count=" << pre_comp_regions_.size() << "\n";
+ for (size_t i = 0; i < pre_comp_regions_.size(); i++) {
+ *out << " [" << i << "] ";
+ DumpRegion(pre_comp_regions_[i], out);
+ *out << "\n";
+ }
+}
}
diff --git a/drmdisplaycomposition.h b/drmdisplaycomposition.h
index 814ca24..2ac93e0 100644
--- a/drmdisplaycomposition.h
+++ b/drmdisplaycomposition.h
@@ -23,6 +23,7 @@
#include "glworker.h"
#include "importer.h"
+#include <sstream>
#include <vector>
#include <hardware/gralloc.h>
@@ -123,6 +124,8 @@
return importer_;
}
+ void Dump(std::ostringstream *out) const;
+
private:
bool validate_composition_type(DrmCompositionType desired);
diff --git a/drmdisplaycompositor.cpp b/drmdisplaycompositor.cpp
index 9f349c0..1d22564 100644
--- a/drmdisplaycompositor.cpp
+++ b/drmdisplaycompositor.cpp
@@ -109,6 +109,34 @@
}
}
+void SquashState::Dump(std::ostringstream *out) const {
+ *out << "----SquashState generation=" << generation_number_
+ << " history=" << valid_history_ << "\n"
+ << " Regions: count=" << regions_.size() << "\n";
+ for (size_t i = 0; i < regions_.size(); i++) {
+ const Region ®ion = regions_[i];
+ *out << " [" << i << "]"
+ << " history=" << region.change_history << " rect";
+ region.rect.Dump(out);
+ *out << " layers=(";
+ bool first = true;
+ for (size_t layer_index = 0; layer_index < kMaxLayers; layer_index++) {
+ if ((region.layer_refs &
+ std::bitset<kMaxLayers>((size_t)1 << layer_index))
+ .any()) {
+ if (!first)
+ *out << " ";
+ first = false;
+ *out << layer_index;
+ }
+ }
+ *out << ")";
+ if (region.squashed)
+ *out << " squashed";
+ *out << "\n";
+ }
+}
+
DrmDisplayCompositor::DrmDisplayCompositor()
: drm_(NULL),
display_(-1),
@@ -712,5 +740,33 @@
}
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);
+ if (ret) {
+ pthread_mutex_unlock(&lock_);
+ return;
+ }
+
+ uint64_t cur_ts = ts.tv_sec * 1000 * 1000 * 1000 + ts.tv_nsec;
+ uint64_t num_ms = (cur_ts - dump_last_timestamp_ns_) / (1000 * 1000);
+ float fps = num_ms ? (num_frames * 1000.0f) / (num_ms) : 0.0f;
+
+ *out << "--DrmDisplayCompositor[" << display_
+ << "]: num_frames=" << num_frames << " num_ms=" << num_ms
+ << " fps=" << fps << "\n";
+
+ dump_last_timestamp_ns_ = cur_ts;
+
+ if (active_composition_)
+ active_composition_->Dump(out);
+
+ pthread_mutex_unlock(&lock_);
}
}
diff --git a/drmdisplaycompositor.h b/drmdisplaycompositor.h
index 22e1efc..cacaa66 100644
--- a/drmdisplaycompositor.h
+++ b/drmdisplaycompositor.h
@@ -69,6 +69,8 @@
const std::vector<bool> &changed_regions);
void RecordSquashed(const std::vector<bool> &squashed_regions);
+ void Dump(std::ostringstream *out) const;
+
private:
size_t generation_number_ = 0;
unsigned valid_history_ = 0;
diff --git a/hwcomposer.cpp b/hwcomposer.cpp
index 6a0f4cd..ac7fdac 100644
--- a/hwcomposer.cpp
+++ b/hwcomposer.cpp
@@ -330,7 +330,9 @@
ctx->drm.compositor()->Dump(&out);
std::string out_str = out.str();
- strncpy(buff, out_str.c_str(), std::min((size_t)buff_len, out_str.length()));
+ strncpy(buff, out_str.c_str(),
+ std::min((size_t)buff_len, out_str.length() + 1));
+ buff[buff_len - 1] = '\0';
}
static int hwc_prepare(hwc_composer_device_1_t *dev, size_t num_displays,
diff --git a/seperate_rects.h b/seperate_rects.h
index 1e0a267..0703c97 100644
--- a/seperate_rects.h
+++ b/seperate_rects.h
@@ -18,6 +18,8 @@
#define DRM_HWCOMPOSER_SEPERATE_RECTS_H_
#include <stdint.h>
+
+#include <sstream>
#include <vector>
namespace seperate_rects {
@@ -76,6 +78,11 @@
TFloat area() const {
return width() * height();
}
+
+ void Dump(std::ostringstream *out) const {
+ *out << "[x/y/w/h]=" << left << "/" << top << "/" << width() << "/"
+ << height();
+ }
};
template <typename TUInt>