drm_hwcomposer: Implement getDisplayPhysicalOrientation()
Implement ComposerClient::getDisplayPhysicalOrientation() by querying
the DRM display panel orientation property and translating the result to
the correct common::Transform enum value.
The result is used by SurfaceFlinger to correctly rotate the image
before displaying it to the user.
Signed-off-by: Tim Van Patten <timvp@google.com>
diff --git a/drm/DrmAtomicStateManager.h b/drm/DrmAtomicStateManager.h
index c8736f2..20896ed 100644
--- a/drm/DrmAtomicStateManager.h
+++ b/drm/DrmAtomicStateManager.h
@@ -21,7 +21,7 @@
#include <memory>
#include <optional>
-#include "compositor/ColorInfo.h"
+#include "compositor/DisplayInfo.h"
#include "compositor/DrmKmsPlan.h"
#include "compositor/LayerData.h"
#include "drm/DrmPlane.h"
diff --git a/drm/DrmConnector.cpp b/drm/DrmConnector.cpp
index 5371513..c46effa 100644
--- a/drm/DrmConnector.cpp
+++ b/drm/DrmConnector.cpp
@@ -27,6 +27,7 @@
#include <sstream>
#include "DrmDevice.h"
+#include "compositor/DisplayInfo.h"
#include "utils/log.h"
#ifndef DRM_MODE_CONNECTOR_SPI
@@ -136,6 +137,26 @@
GetConnectorProperty("content type", &content_type_property_,
/*is_optional=*/true);
+ if (GetConnectorProperty("panel orientation", &panel_orientation_,
+ /*is_optional=*/true)) {
+ panel_orientation_
+ .AddEnumToMapReverse("Normal",
+ PanelOrientation::kModePanelOrientationNormal,
+ panel_orientation_enum_map_);
+ panel_orientation_
+ .AddEnumToMapReverse("Upside Down",
+ PanelOrientation::kModePanelOrientationBottomUp,
+ panel_orientation_enum_map_);
+ panel_orientation_
+ .AddEnumToMapReverse("Left Side Up",
+ PanelOrientation::kModePanelOrientationLeftUp,
+ panel_orientation_enum_map_);
+ panel_orientation_
+ .AddEnumToMapReverse("Right Side Up",
+ PanelOrientation::kModePanelOrientationRightUp,
+ panel_orientation_enum_map_);
+ }
+
return true;
}
@@ -241,4 +262,26 @@
return true;
}
+
+std::optional<PanelOrientation> DrmConnector::GetPanelOrientation() {
+ if (!panel_orientation_.GetValue().has_value()) {
+ ALOGW("No panel orientation property available.");
+ return {};
+ }
+
+ /* The value_or(0) satisfies the compiler warning. However,
+ * panel_orientation_.GetValue() is guaranteed to have a value since we check
+ * has_value() and return early otherwise.
+ */
+ uint64_t panel_orientation_value = panel_orientation_.GetValue().value_or(0);
+
+ if (panel_orientation_enum_map_.count(panel_orientation_value) == 1) {
+ return panel_orientation_enum_map_[panel_orientation_value];
+ }
+
+ ALOGE("Unknown panel orientation: panel_orientation = %lu",
+ panel_orientation_value);
+ return {};
+}
+
} // namespace android
diff --git a/drm/DrmConnector.h b/drm/DrmConnector.h
index 9186f07..be84ae3 100644
--- a/drm/DrmConnector.h
+++ b/drm/DrmConnector.h
@@ -26,8 +26,7 @@
#include "DrmMode.h"
#include "DrmProperty.h"
#include "DrmUnique.h"
-
-#include "compositor/ColorInfo.h"
+#include "compositor/DisplayInfo.h"
namespace android {
@@ -118,6 +117,10 @@
return writeback_out_fence_;
}
+ auto &GetPanelOrientationProperty() const {
+ return panel_orientation_;
+ }
+
auto IsConnected() const {
return connector_->connection == DRM_MODE_CONNECTED;
}
@@ -130,11 +133,13 @@
return connector_->mmHeight;
};
+ auto GetPanelOrientation() -> std::optional<PanelOrientation>;
+
private:
DrmConnector(DrmModeConnectorUnique connector, DrmDevice *drm, uint32_t index)
: connector_(std::move(connector)),
drm_(drm),
- index_in_res_array_(index){};
+ index_in_res_array_(index) {};
DrmModeConnectorUnique connector_;
DrmDevice *const drm_;
@@ -157,7 +162,9 @@
DrmProperty writeback_pixel_formats_;
DrmProperty writeback_fb_id_;
DrmProperty writeback_out_fence_;
+ DrmProperty panel_orientation_;
std::map<Colorspace, uint64_t> colorspace_enum_map_;
+ std::map<uint64_t, PanelOrientation> panel_orientation_enum_map_;
};
} // namespace android
diff --git a/drm/DrmProperty.cpp b/drm/DrmProperty.cpp
index 031918a..0ea9143 100644
--- a/drm/DrmProperty.cpp
+++ b/drm/DrmProperty.cpp
@@ -125,4 +125,22 @@
return true;
}
+std::optional<std::string> DrmProperty::GetEnumNameFromValue(
+ uint64_t value) const {
+ if (enums_.empty()) {
+ ALOGE("No enum values for property: %s", name_.c_str());
+ return {};
+ }
+
+ for (const auto &it : enums_) {
+ if (it.value == value) {
+ return it.name;
+ }
+ }
+
+ ALOGE("Property '%s' has no matching enum for value: %lu", name_.c_str(),
+ value);
+ return {};
+}
+
} // namespace android
diff --git a/drm/DrmProperty.h b/drm/DrmProperty.h
index 516518b..2683ad8 100644
--- a/drm/DrmProperty.h
+++ b/drm/DrmProperty.h
@@ -64,10 +64,16 @@
auto AddEnumToMap(const std::string &name, E key, std::map<E, uint64_t> &map)
-> bool;
+ template <class E>
+ auto AddEnumToMapReverse(const std::string &name, E value,
+ std::map<uint64_t, E> &map) -> bool;
+
explicit operator bool() const {
return id_ != 0;
}
+ auto GetEnumNameFromValue(uint64_t value) const -> std::optional<std::string>;
+
private:
class DrmPropertyEnum {
public:
@@ -104,4 +110,18 @@
return false;
}
+template <class E>
+auto DrmProperty::AddEnumToMapReverse(const std::string &name, E value,
+ std::map<uint64_t, E> &map) -> bool {
+ uint64_t enum_value = UINT64_MAX;
+ int err = 0;
+ std::tie(enum_value, err) = GetEnumValueWithName(name);
+ if (err == 0) {
+ map[enum_value] = value;
+ return true;
+ }
+
+ return false;
+}
+
} // namespace android