Merge remote-tracking branch 'aosp/upstream-main' into HEAD am: 97b4f2559e am: 6e792d7aa5 am: fc030f53a5 am: b038ca0b70
Original change: https://android-review.googlesource.com/c/platform/external/drm_hwcomposer/+/1883310
Change-Id: I158aeece6bbfc33e681f5b8f1fa7df05d11e4c1a
diff --git a/.ci/.common.sh b/.ci/.common.sh
index 0183aba..21c2b28 100644
--- a/.ci/.common.sh
+++ b/.ci/.common.sh
@@ -1,7 +1,7 @@
INCLUDE_DIRS="-I. -I../libdrm/include/drm -Iinclude -I/usr/include/libdrm -I./.ci/android_headers -I./tests/test_include"
-CLANG="clang++-11"
-CLANG_TIDY="clang-tidy-11"
+CLANG="clang++-12"
+CLANG_TIDY="clang-tidy-12"
CXXARGS="-fPIC -Wall -Werror -DPLATFORM_SDK_VERSION=30 -D__ANDROID_API__=30 -Wsign-promo -Wimplicit-fallthrough"
CXXARGS+=" -D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS -Wno-gnu-include-next "
diff --git a/.ci/.gitlab-ci-clang-tidy-coarse.sh b/.ci/.gitlab-ci-clang-tidy-coarse.sh
index de0c024..a3afeb9 100755
--- a/.ci/.gitlab-ci-clang-tidy-coarse.sh
+++ b/.ci/.gitlab-ci-clang-tidy-coarse.sh
@@ -17,6 +17,7 @@
TIDY_COARSE_CHECKS+="-google-readability-braces-around-statements,"
TIDY_COARSE_CHECKS+="-google-readability-casting,"
TIDY_COARSE_CHECKS+="misc-*,"
+TIDY_COARSE_CHECKS+="-misc-non-private-member-variables-in-classes",
TIDY_COARSE_CHECKS+="modernize-*,"
TIDY_COARSE_CHECKS+="-modernize-avoid-c-arrays,"
TIDY_COARSE_CHECKS+="-modernize-use-trailing-return-type,"
@@ -24,8 +25,10 @@
TIDY_COARSE_CHECKS+="portability-*,"
TIDY_COARSE_CHECKS+="readability-*,"
TIDY_COARSE_CHECKS+="-readability-braces-around-statements,"
+TIDY_COARSE_CHECKS+="-readability-function-cognitive-complexity,"
TIDY_COARSE_CHECKS+="-readability-convert-member-functions-to-static,"
TIDY_COARSE_CHECKS+="-readability-implicit-bool-conversion,"
+TIDY_COARSE_CHECKS+="-readability-identifier-naming,"
TIDY_COARSE_CHECKS+="-readability-magic-numbers,"
TIDY_COARSE_CHECKS+="-readability-use-anyofallof"
diff --git a/.ci/.gitlab-ci-clang-tidy-fine.sh b/.ci/.gitlab-ci-clang-tidy-fine.sh
index c1805e8..0e3e35b 100755
--- a/.ci/.gitlab-ci-clang-tidy-fine.sh
+++ b/.ci/.gitlab-ci-clang-tidy-fine.sh
@@ -4,6 +4,7 @@
TIDY_FILES=(
drm/DrmFbImporter.h
+drm/DrmUnique.h
utils/UniqueFd.h
utils/log.h
utils/properties.h
diff --git a/.clang-tidy b/.clang-tidy
index 0bb7bf0..221c030 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -6,6 +6,7 @@
*,
-fuchsia*,
-llvm*,
+ -concurrency-mt-unsafe,
-cppcoreguidelines-pro-type-vararg, -hicpp-vararg,
-hicpp-signed-bitwise,
@@ -17,26 +18,49 @@
FormatStyle: google
CheckOptions:
- - { key: readability-identifier-naming.NamespaceCase, value: lower_case }
- - { key: readability-identifier-naming.ClassCase, value: CamelCase }
- - { key: readability-identifier-naming.StructCase, value: CamelCase }
- - { key: readability-identifier-naming.TemplateParameterCase, value: CamelCase }
- - { key: readability-identifier-naming.FunctionCase, value: aNy_CasE }
- - { key: readability-identifier-naming.VariableCase, value: lower_case }
- - { key: readability-identifier-naming.ClassMemberCase, value: lower_case }
- - { key: readability-identifier-naming.ClassMemberSuffix, value: _ }
- - { key: readability-identifier-naming.PrivateMemberSuffix, value: _ }
- - { key: readability-identifier-naming.ProtectedMemberSuffix, value: _ }
- - { key: readability-identifier-naming.EnumConstantCase, value: CamelCase }
- - { key: readability-identifier-naming.EnumConstantPrefix, value: k }
- - { key: readability-identifier-naming.ConstexprVariableCase, value: CamelCase }
- - { key: readability-identifier-naming.ConstexprVariablePrefix, value: k }
- - { key: readability-identifier-naming.GlobalConstantCase, value: CamelCase }
- - { key: readability-identifier-naming.GlobalConstantPrefix, value: k }
- - { key: readability-identifier-naming.MemberConstantCase, value: CamelCase }
- - { key: readability-identifier-naming.MemberConstantPrefix, value: k }
- - { key: readability-identifier-naming.StaticConstantCase, value: CamelCase }
- - { key: readability-identifier-naming.StaticConstantPrefix, value: k }
- - { key: readability-implicit-bool-conversion.AllowIntegerConditions, value: 1 }
- - { key: readability-implicit-bool-conversion.AllowPointerConditions, value: 1 }
- - { key: misc-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic, value: 1 }
+ - key: readability-identifier-naming.ClassCase
+ value: CamelCase
+ - key: readability-identifier-naming.ClassMemberCase
+ value: lower_case
+ - key: readability-identifier-naming.ConstexprVariableCase
+ value: CamelCase
+ - key: readability-identifier-naming.ConstexprVariablePrefix
+ value: k
+ - key: readability-identifier-naming.EnumCase
+ value: CamelCase
+ - key: readability-identifier-naming.EnumConstantCase
+ value: CamelCase
+ - key: readability-identifier-naming.EnumConstantPrefix
+ value: k
+ - key: readability-identifier-naming.FunctionCase
+ value: CamelCase
+ - key: readability-identifier-naming.GlobalConstantCase
+ value: CamelCase
+ - key: readability-identifier-naming.GlobalConstantPrefix
+ value: k
+ - key: readability-identifier-naming.StaticConstantCase
+ value: CamelCase
+ - key: readability-identifier-naming.StaticConstantPrefix
+ value: k
+ - key: readability-identifier-naming.StaticVariableCase
+ value: lower_case
+ - key: readability-identifier-naming.MacroDefinitionCase
+ value: UPPER_CASE
+ - key: readability-identifier-naming.MacroDefinitionIgnoredRegexp
+ value: '^[A-Z]+(_[A-Z]+)*_$'
+ - key: readability-identifier-naming.MemberCase
+ value: lower_case
+ - key: readability-identifier-naming.MemberSuffix
+ value: _
+ - key: readability-identifier-naming.NamespaceCase
+ value: lower_case
+ - key: readability-identifier-naming.ParameterCase
+ value: lower_case
+ - key: readability-identifier-naming.TypeAliasCase
+ value: CamelCase
+ - key: readability-identifier-naming.TypedefCase
+ value: CamelCase
+ - key: readability-identifier-naming.VariableCase
+ value: lower_case
+ - key: readability-identifier-naming.IgnoreMainLikeFunctions
+ value: 1
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 04eb6c5..41d38ba 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,8 +1,11 @@
-image: ubuntu:20.10
+image: ubuntu:21.04
+
+variables:
+ DEBIAN_FRONTEND: noninteractive
before_script:
- apt-get --quiet update --yes >/dev/null
- - apt-get --quiet install --yes clang-11 clang-tidy-11 clang-format-11 git libdrm-dev blueprint-tools libgtest-dev >/dev/null
+ - apt-get --quiet install --yes clang-12 clang-tidy-12 clang-format-12 git libdrm-dev blueprint-tools libgtest-dev >/dev/null
stages:
- build
diff --git a/DrmHwcTwo.cpp b/DrmHwcTwo.cpp
index 02667cf..6ec8b31 100644
--- a/DrmHwcTwo.cpp
+++ b/DrmHwcTwo.cpp
@@ -48,14 +48,14 @@
HWC2::Error DrmHwcTwo::CreateDisplay(hwc2_display_t displ,
HWC2::DisplayType type) {
- DrmDevice *drm = resource_manager_.GetDrmDevice(displ);
+ DrmDevice *drm = resource_manager_.GetDrmDevice(static_cast<int>(displ));
if (!drm) {
ALOGE("Failed to get a valid drmresource");
return HWC2::Error::NoResources;
}
displays_.emplace(std::piecewise_construct, std::forward_as_tuple(displ),
- std::forward_as_tuple(&resource_manager_, drm, displ,
- type));
+ std::forward_as_tuple(&resource_manager_, drm, displ, type,
+ this));
DrmCrtc *crtc = drm->GetCrtcForDisplay(static_cast<int>(displ));
if (!crtc) {
@@ -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"
@@ -183,26 +202,31 @@
hwc2_function_pointer_t function) {
supported(__func__);
+ std::unique_lock<std::mutex> lock(callback_lock_);
+
switch (static_cast<HWC2::Callback>(descriptor)) {
case HWC2::Callback::Hotplug: {
- SetHotplugCallback(data, function);
+ hotplug_callback_ = std::make_pair(HWC2_PFN_HOTPLUG(function), data);
+ lock.unlock();
const auto &drm_devices = resource_manager_.getDrmDevices();
for (const auto &device : drm_devices)
HandleInitialHotplugState(device.get());
break;
}
case HWC2::Callback::Refresh: {
- for (std::pair<const hwc2_display_t, DrmHwcTwo::HwcDisplay> &d :
- displays_)
- d.second.RegisterRefreshCallback(data, function);
+ refresh_callback_ = std::make_pair(HWC2_PFN_REFRESH(function), data);
break;
}
case HWC2::Callback::Vsync: {
- for (std::pair<const hwc2_display_t, DrmHwcTwo::HwcDisplay> &d :
- displays_)
- d.second.RegisterVsyncCallback(data, function);
+ vsync_callback_ = std::make_pair(HWC2_PFN_VSYNC(function), data);
break;
}
+#if PLATFORM_SDK_VERSION > 29
+ case HWC2::Callback::Vsync_2_4: {
+ vsync_2_4_callback_ = std::make_pair(HWC2_PFN_VSYNC_2_4(function), data);
+ break;
+ }
+#endif
default:
break;
}
@@ -211,8 +235,9 @@
DrmHwcTwo::HwcDisplay::HwcDisplay(ResourceManager *resource_manager,
DrmDevice *drm, hwc2_display_t handle,
- HWC2::DisplayType type)
- : resource_manager_(resource_manager),
+ HWC2::DisplayType type, DrmHwcTwo *hwc2)
+ : hwc2_(hwc2),
+ resource_manager_(resource_manager),
drm_(drm),
handle_(handle),
type_(type),
@@ -271,7 +296,41 @@
return HWC2::Error::BadDisplay;
}
- ret = vsync_worker_.Init(drm_, display);
+ ret = vsync_worker_.Init(drm_, display, [this](int64_t timestamp) {
+ const std::lock_guard<std::mutex> lock(hwc2_->callback_lock_);
+ /* vsync callback */
+#if PLATFORM_SDK_VERSION > 29
+ if (hwc2_->vsync_2_4_callback_.first != nullptr &&
+ hwc2_->vsync_2_4_callback_.second != nullptr) {
+ hwc2_vsync_period_t period_ns{};
+ GetDisplayVsyncPeriod(&period_ns);
+ hwc2_->vsync_2_4_callback_.first(hwc2_->vsync_2_4_callback_.second,
+ handle_, timestamp, period_ns);
+ } else
+#endif
+ if (hwc2_->vsync_callback_.first != nullptr &&
+ hwc2_->vsync_callback_.second != nullptr) {
+ hwc2_->vsync_callback_.first(hwc2_->vsync_callback_.second, handle_,
+ timestamp);
+ }
+ });
+ if (ret) {
+ ALOGE("Failed to create event worker for d=%d %d\n", display, ret);
+ 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;
@@ -296,18 +355,6 @@
return SetActiveConfig(connector_->get_preferred_mode_id());
}
-void DrmHwcTwo::HwcDisplay::RegisterVsyncCallback(
- hwc2_callback_data_t data, hwc2_function_pointer_t func) {
- supported(__func__);
- vsync_worker_.RegisterClientCallback(data, func);
-}
-
-void DrmHwcTwo::HwcDisplay::RegisterRefreshCallback(
- hwc2_callback_data_t data, hwc2_function_pointer_t func) {
- supported(__func__);
- compositor_.SetRefreshCallback(data, func);
-}
-
HWC2::Error DrmHwcTwo::HwcDisplay::AcceptDisplayChanges() {
supported(__func__);
for (std::pair<const hwc2_layer_t, DrmHwcTwo::HwcLayer> &l : layers_)
@@ -413,22 +460,26 @@
auto attribute = static_cast<HWC2::Attribute>(attribute_in);
switch (attribute) {
case HWC2::Attribute::Width:
- *value = mode->h_display();
+ *value = static_cast<int>(mode->h_display());
break;
case HWC2::Attribute::Height:
- *value = mode->v_display();
+ *value = static_cast<int>(mode->v_display());
break;
case HWC2::Attribute::VsyncPeriod:
// in nanoseconds
- *value = 1000.0 * 1000.0 * 1000.0 / mode->v_refresh();
+ *value = static_cast<int>(1E9 / mode->v_refresh());
break;
case HWC2::Attribute::DpiX:
// Dots per 1000 inches
- *value = mm_width ? (mode->h_display() * kUmPerInch) / mm_width : -1;
+ *value = mm_width
+ ? static_cast<int>(mode->h_display() * kUmPerInch / mm_width)
+ : -1;
break;
case HWC2::Attribute::DpiY:
// Dots per 1000 inches
- *value = mm_height ? (mode->v_display() * kUmPerInch) / mm_height : -1;
+ *value = mm_height ? static_cast<int>(mode->v_display() * kUmPerInch /
+ mm_height)
+ : -1;
break;
#if PLATFORM_SDK_VERSION > 29
case HWC2::Attribute::ConfigGroup:
@@ -786,8 +837,8 @@
hwc_frect_t source_crop = {.left = 0.0F,
.top = 0.0F,
- .right = bo.width + 0.0F,
- .bottom = bo.height + 0.0F};
+ .right = static_cast<float>(bo.width),
+ .bottom = static_cast<float>(bo.height)};
client_layer_.SetLayerSourceCrop(source_crop);
return HWC2::Error::None;
@@ -909,7 +960,7 @@
if (mode.id() == 0)
return HWC2::Error::BadConfig;
- *outVsyncPeriod = 1E9 / mode.v_refresh();
+ *outVsyncPeriod = static_cast<hwc2_vsync_period_t>(1E9 / mode.v_refresh());
return HWC2::Error::None;
}
@@ -958,9 +1009,9 @@
uint8_t *outPort, uint32_t *outDataSize, uint8_t *outData) {
supported(__func__);
- drmModePropertyBlobPtr blob = nullptr;
+ auto blob = connector_->GetEdidBlob();
- if (connector_->GetEdidBlob(blob)) {
+ if (!blob) {
ALOGE("Failed to get edid property value.");
return HWC2::Error::Unsupported;
}
@@ -1041,16 +1092,29 @@
#endif /* PLATFORM_SDK_VERSION > 27 */
-HWC2::Error DrmHwcTwo::HwcLayer::SetCursorPosition(int32_t x, int32_t y) {
+HWC2::Error DrmHwcTwo::HwcLayer::SetCursorPosition(int32_t /*x*/,
+ int32_t /*y*/) {
supported(__func__);
- cursor_x_ = x;
- cursor_y_ = y;
return HWC2::Error::None;
}
HWC2::Error DrmHwcTwo::HwcLayer::SetLayerBlendMode(int32_t mode) {
supported(__func__);
- blending_ = static_cast<HWC2::BlendMode>(mode);
+ switch (static_cast<HWC2::BlendMode>(mode)) {
+ case HWC2::BlendMode::None:
+ blending_ = DrmHwcBlending::kNone;
+ break;
+ case HWC2::BlendMode::Premultiplied:
+ blending_ = DrmHwcBlending::kPreMult;
+ break;
+ case HWC2::BlendMode::Coverage:
+ blending_ = DrmHwcBlending::kCoverage;
+ break;
+ default:
+ ALOGE("Unknown blending mode b=%d", blending_);
+ blending_ = DrmHwcBlending::kNone;
+ break;
+ }
return HWC2::Error::None;
}
@@ -1066,10 +1130,9 @@
return HWC2::Error::None;
}
-HWC2::Error DrmHwcTwo::HwcLayer::SetLayerColor(hwc_color_t color) {
+HWC2::Error DrmHwcTwo::HwcLayer::SetLayerColor(hwc_color_t /*color*/) {
// TODO(nobody): Put to client composition here?
supported(__func__);
- layer_color_ = color;
return HWC2::Error::None;
}
@@ -1080,7 +1143,34 @@
HWC2::Error DrmHwcTwo::HwcLayer::SetLayerDataspace(int32_t dataspace) {
supported(__func__);
- dataspace_ = static_cast<android_dataspace_t>(dataspace);
+ switch (dataspace & HAL_DATASPACE_STANDARD_MASK) {
+ case HAL_DATASPACE_STANDARD_BT709:
+ color_space_ = DrmHwcColorSpace::kItuRec709;
+ break;
+ case HAL_DATASPACE_STANDARD_BT601_625:
+ case HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED:
+ case HAL_DATASPACE_STANDARD_BT601_525:
+ case HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED:
+ color_space_ = DrmHwcColorSpace::kItuRec601;
+ break;
+ case HAL_DATASPACE_STANDARD_BT2020:
+ case HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE:
+ color_space_ = DrmHwcColorSpace::kItuRec2020;
+ break;
+ default:
+ color_space_ = DrmHwcColorSpace::kUndefined;
+ }
+
+ switch (dataspace & HAL_DATASPACE_RANGE_MASK) {
+ case HAL_DATASPACE_RANGE_FULL:
+ sample_range_ = DrmHwcSampleRange::kFullRange;
+ break;
+ case HAL_DATASPACE_RANGE_LIMITED:
+ sample_range_ = DrmHwcSampleRange::kLimitedRange;
+ break;
+ default:
+ sample_range_ = DrmHwcSampleRange::kUndefined;
+ }
return HWC2::Error::None;
}
@@ -1118,7 +1208,27 @@
HWC2::Error DrmHwcTwo::HwcLayer::SetLayerTransform(int32_t transform) {
supported(__func__);
- transform_ = static_cast<HWC2::Transform>(transform);
+
+ uint32_t l_transform = 0;
+
+ // 270* and 180* cannot be combined with flips. More specifically, they
+ // already contain both horizontal and vertical flips, so those fields are
+ // redundant in this case. 90* rotation can be combined with either horizontal
+ // flip or vertical flip, so treat it differently
+ if (transform == HWC_TRANSFORM_ROT_270) {
+ l_transform = DrmHwcTransform::kRotate270;
+ } else if (transform == HWC_TRANSFORM_ROT_180) {
+ l_transform = DrmHwcTransform::kRotate180;
+ } else {
+ if (transform & HWC_TRANSFORM_FLIP_H)
+ l_transform |= DrmHwcTransform::kFlipH;
+ if (transform & HWC_TRANSFORM_FLIP_V)
+ l_transform |= DrmHwcTransform::kFlipV;
+ if (transform & HWC_TRANSFORM_ROT_90)
+ l_transform |= DrmHwcTransform::kRotate90;
+ }
+
+ transform_ = static_cast<DrmHwcTransform>(l_transform);
return HWC2::Error::None;
}
@@ -1137,40 +1247,28 @@
void DrmHwcTwo::HwcLayer::PopulateDrmLayer(DrmHwcLayer *layer) {
supported(__func__);
- switch (blending_) {
- case HWC2::BlendMode::None:
- layer->blending = DrmHwcBlending::kNone;
- break;
- case HWC2::BlendMode::Premultiplied:
- layer->blending = DrmHwcBlending::kPreMult;
- break;
- case HWC2::BlendMode::Coverage:
- layer->blending = DrmHwcBlending::kCoverage;
- break;
- default:
- ALOGE("Unknown blending mode b=%d", blending_);
- layer->blending = DrmHwcBlending::kNone;
- break;
- }
-
layer->sf_handle = buffer_;
// TODO(rsglobal): Avoid extra fd duplication
layer->acquire_fence = UniqueFd(fcntl(acquire_fence_.Get(), F_DUPFD_CLOEXEC));
layer->display_frame = display_frame_;
layer->alpha = lround(65535.0F * alpha_);
+ layer->blending = blending_;
layer->source_crop = source_crop_;
- layer->SetTransform(static_cast<int32_t>(transform_));
- layer->dataspace = dataspace_;
+ layer->transform = transform_;
+ layer->color_space = color_space_;
+ layer->sample_range = sample_range_;
}
void DrmHwcTwo::HandleDisplayHotplug(hwc2_display_t displayid, int state) {
- const std::lock_guard<std::mutex> lock(hotplug_callback_lock);
+ const std::lock_guard<std::mutex> lock(callback_lock_);
- if (hotplug_callback_hook_ && hotplug_callback_data_)
- hotplug_callback_hook_(hotplug_callback_data_, displayid,
- state == DRM_MODE_CONNECTED
- ? HWC2_CONNECTION_CONNECTED
- : HWC2_CONNECTION_DISCONNECTED);
+ if (hotplug_callback_.first != nullptr &&
+ hotplug_callback_.second != nullptr) {
+ hotplug_callback_.first(hotplug_callback_.second, displayid,
+ state == DRM_MODE_CONNECTED
+ ? HWC2_CONNECTION_CONNECTED
+ : HWC2_CONNECTION_DISCONNECTED);
+ }
}
void DrmHwcTwo::HandleInitialHotplugState(DrmDevice *drmDevice) {
diff --git a/DrmHwcTwo.h b/DrmHwcTwo.h
index 111c664..0d213fd 100644
--- a/DrmHwcTwo.h
+++ b/DrmHwcTwo.h
@@ -42,16 +42,14 @@
HWC2::Error Init();
- hwc2_callback_data_t hotplug_callback_data_ = NULL;
- HWC2_PFN_HOTPLUG hotplug_callback_hook_ = NULL;
- std::mutex hotplug_callback_lock;
+ std::pair<HWC2_PFN_HOTPLUG, hwc2_callback_data_t> hotplug_callback_{};
+ std::pair<HWC2_PFN_VSYNC, hwc2_callback_data_t> vsync_callback_{};
+#if PLATFORM_SDK_VERSION > 29
+ std::pair<HWC2_PFN_VSYNC_2_4, hwc2_callback_data_t> vsync_2_4_callback_{};
+#endif
+ std::pair<HWC2_PFN_REFRESH, hwc2_callback_data_t> refresh_callback_{};
- void SetHotplugCallback(hwc2_callback_data_t data,
- hwc2_function_pointer_t hook) {
- const std::lock_guard<std::mutex> lock(hotplug_callback_lock);
- hotplug_callback_data_ = data;
- hotplug_callback_hook_ = reinterpret_cast<HWC2_PFN_HOTPLUG>(hook);
- }
+ std::mutex callback_lock_;
class HwcLayer {
public:
@@ -102,10 +100,10 @@
}
// Layer hooks
- HWC2::Error SetCursorPosition(int32_t x, int32_t y);
+ HWC2::Error SetCursorPosition(int32_t /*x*/, int32_t /*y*/);
HWC2::Error SetLayerBlendMode(int32_t mode);
HWC2::Error SetLayerBuffer(buffer_handle_t buffer, int32_t acquire_fence);
- HWC2::Error SetLayerColor(hwc_color_t color);
+ HWC2::Error SetLayerColor(hwc_color_t /*color*/);
HWC2::Error SetLayerCompositionType(int32_t type);
HWC2::Error SetLayerDataspace(int32_t dataspace);
HWC2::Error SetLayerDisplayFrame(hwc_rect_t frame);
@@ -133,30 +131,24 @@
HWC2::Composition sf_type_ = HWC2::Composition::Invalid;
HWC2::Composition validated_type_ = HWC2::Composition::Invalid;
- HWC2::BlendMode blending_ = HWC2::BlendMode::None;
buffer_handle_t buffer_ = NULL;
hwc_rect_t display_frame_;
float alpha_ = 1.0f;
hwc_frect_t source_crop_;
- int32_t cursor_x_;
- int32_t cursor_y_;
- hwc_color_t layer_color_;
- HWC2::Transform transform_ = HWC2::Transform::None;
+ DrmHwcTransform transform_ = DrmHwcTransform::kIdentity;
uint32_t z_order_ = 0;
- android_dataspace_t dataspace_ = HAL_DATASPACE_UNKNOWN;
+ DrmHwcBlending blending_ = DrmHwcBlending::kNone;
+ DrmHwcColorSpace color_space_ = DrmHwcColorSpace::kUndefined;
+ DrmHwcSampleRange sample_range_ = DrmHwcSampleRange::kUndefined;
};
class HwcDisplay {
public:
HwcDisplay(ResourceManager *resource_manager, DrmDevice *drm,
- hwc2_display_t handle, HWC2::DisplayType type);
+ hwc2_display_t handle, HWC2::DisplayType type, DrmHwcTwo *hwc2);
HwcDisplay(const HwcDisplay &) = delete;
HWC2::Error Init(std::vector<DrmPlane *> *planes);
- void RegisterVsyncCallback(hwc2_callback_data_t data,
- hwc2_function_pointer_t func);
- void RegisterRefreshCallback(hwc2_callback_data_t data,
- hwc2_function_pointer_t func);
HWC2::Error CreateComposition(bool test);
std::vector<DrmHwcTwo::HwcLayer *> GetOrderLayersByZPos();
@@ -301,11 +293,46 @@
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;
+ DrmHwcTwo *hwc2_;
+
ResourceManager *resource_manager_;
DrmDevice *drm_;
DrmDisplayCompositor compositor_;
diff --git a/README.md b/README.md
index 728bc76..c142266 100644
--- a/README.md
+++ b/README.md
@@ -16,7 +16,7 @@
you with formatting of your patches:
```
- git diff | clang-format-diff-11 -p 1 -style=file
+ git diff | clang-format-diff-12 -p 1 -style=file
```
* Hardware specific changes should be tested on relevant platforms before
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/bufferinfo/BufferInfoMapperMetadata.cpp b/bufferinfo/BufferInfoMapperMetadata.cpp
index 23a9072..a8e95e7 100644
--- a/bufferinfo/BufferInfoMapperMetadata.cpp
+++ b/bufferinfo/BufferInfoMapperMetadata.cpp
@@ -47,30 +47,42 @@
*/
int __attribute__((weak))
BufferInfoMapperMetadata::GetFds(buffer_handle_t handle, hwc_drm_bo_t *bo) {
- int num_fds = handle->numFds;
+ int fd_index = 0;
- if (num_fds >= 1 && num_fds <= 2) {
- if (IsDrmFormatRgb(bo->format)) {
- bo->prime_fds[0] = handle->data[0];
- } else {
- bo->prime_fds[0] = bo->prime_fds[1] = bo->prime_fds[2] = handle->data[0];
- }
- if (bo->prime_fds[0] <= 0) {
- ALOGE("Encountered invalid fd %d", bo->prime_fds[0]);
- return android::BAD_VALUE;
+ if (handle->numFds <= 0) {
+ ALOGE("Handle has no fds");
+ return android::BAD_VALUE;
+ }
+
+ for (int i = 0; i < HWC_DRM_BO_MAX_PLANES; i++) {
+ /* If no size, we're out of usable planes */
+ if (bo->sizes[i] <= 0) {
+ if (i == 0) {
+ ALOGE("Bad handle metadata");
+ return android::BAD_VALUE;
+ }
+ break;
}
- } else if (num_fds >= 3) {
- bo->prime_fds[0] = handle->data[0];
- bo->prime_fds[1] = handle->data[1];
- bo->prime_fds[2] = handle->data[2];
- for (int i = 0; i < 3; i++) {
- if (bo->prime_fds[i] <= 0) {
- ALOGE("Encountered invalid fd %d", bo->prime_fds[i]);
+ /*
+ * If the offset is zero, its multi-buffer
+ * so move to the next fd
+ */
+ if (i != 0 && bo->offsets[i] == 0) {
+ fd_index++;
+ if (fd_index >= handle->numFds) {
+ ALOGE("Handle has no more fds");
return android::BAD_VALUE;
}
}
+
+ bo->prime_fds[i] = handle->data[fd_index];
+ if (bo->prime_fds[i] <= 0) {
+ ALOGE("Invalid prime fd");
+ return android::BAD_VALUE;
+ }
}
+
return 0;
}
@@ -135,6 +147,7 @@
bo->modifiers[i] = bo->modifiers[0];
bo->pitches[i] = layouts[i].strideInBytes;
bo->offsets[i] = layouts[i].offsetInBytes;
+ bo->sizes[i] = layouts[i].totalSizeInBytes;
}
return GetFds(handle, bo);
diff --git a/bufferinfo/legacy/BufferInfoLibdrm.cpp b/bufferinfo/legacy/BufferInfoLibdrm.cpp
index 52f792f..da89eb5 100644
--- a/bufferinfo/legacy/BufferInfoLibdrm.cpp
+++ b/bufferinfo/legacy/BufferInfoLibdrm.cpp
@@ -37,9 +37,9 @@
struct DroidYuvFormat {
/* Lookup keys */
- int native; /* HAL_PIXEL_FORMAT_ */
+ uint32_t native; /* HAL_PIXEL_FORMAT_ */
enum chroma_order chroma_order; /* chroma order is {Cb, Cr} or {Cr, Cb} */
- int chroma_step; /* Distance in bytes between subsequent chroma pixels. */
+ size_t chroma_step; /* Distance in bytes between subsequent chroma pixels. */
/* Result */
int fourcc; /* DRM_FORMAT_ */
@@ -64,8 +64,8 @@
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
-static int get_fourcc_yuv(int native, enum chroma_order chroma_order,
- int chroma_step) {
+static int get_fourcc_yuv(uint32_t native, enum chroma_order chroma_order,
+ size_t chroma_step) {
for (auto droid_yuv_format : kDroidYuvFormats)
if (droid_yuv_format.native == native &&
droid_yuv_format.chroma_order == chroma_order &&
@@ -75,7 +75,7 @@
return -1;
}
-static bool is_yuv(int native) {
+static bool is_yuv(uint32_t native) {
for (auto droid_yuv_format : kDroidYuvFormats)
if (droid_yuv_format.native == native)
return true;
diff --git a/compositor/DrmDisplayComposition.cpp b/compositor/DrmDisplayComposition.cpp
index 49dff0e..c0fbba0 100644
--- a/compositor/DrmDisplayComposition.cpp
+++ b/compositor/DrmDisplayComposition.cpp
@@ -130,155 +130,4 @@
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 DrmHwcLayer &layer, std::ostringstream *out) {
- *out << "buffer[w/h/format]=";
- *out << layer.buffer_info.width << "/" << layer.buffer_info.height << "/"
- << layer.buffer_info.format;
-}
-
-static void DumpTransform(uint32_t transform, std::ostringstream *out) {
- *out << "[";
-
- if (transform == 0)
- *out << "IDENTITY";
-
- bool separator = false;
- if (transform & DrmHwcTransform::kFlipH) {
- *out << "FLIPH";
- separator = true;
- }
- if (transform & DrmHwcTransform::kFlipV) {
- if (separator)
- *out << "|";
- *out << "FLIPV";
- separator = true;
- }
- if (transform & DrmHwcTransform::kRotate90) {
- if (separator)
- *out << "|";
- *out << "ROTATE90";
- separator = true;
- }
- if (transform & DrmHwcTransform::kRotate180) {
- if (separator)
- *out << "|";
- *out << "ROTATE180";
- separator = true;
- }
- if (transform & DrmHwcTransform::kRotate270) {
- if (separator)
- *out << "|";
- *out << "ROTATE270";
- separator = true;
- }
-
- uint32_t valid_bits = DrmHwcTransform::kFlipH | DrmHwcTransform::kFlipV |
- DrmHwcTransform::kRotate90 |
- DrmHwcTransform::kRotate180 |
- DrmHwcTransform::kRotate270;
- if (transform & ~valid_bits) {
- if (separator)
- *out << "|";
- *out << "INVALID";
- }
- *out << "]";
-}
-
-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>";
- }
-}
-
-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 << " Layers: count=" << layers_.size() << "\n";
- for (size_t i = 0; i < layers_.size(); i++) {
- const DrmHwcLayer &layer = layers_[i];
- *out << " [" << i << "] ";
-
- DumpBuffer(layer, out);
-
- if (layer.protected_usage())
- *out << " protected";
-
- *out << " transform=";
- DumpTransform(layer.transform, out);
- *out << " blending[a=" << (int)layer.alpha
- << "]=" << BlendingToString(layer.blending) << "\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)
- << " type=";
- switch (comp_plane.type()) {
- case DrmCompositionPlane::Type::kDisable:
- *out << "DISABLE";
- break;
- case DrmCompositionPlane::Type::kLayer:
- *out << "LAYER";
- break;
- default:
- *out << "<invalid>";
- break;
- }
-
- *out << " source_layer=";
- for (auto i : comp_plane.source_layers()) {
- *out << i << " ";
- }
- *out << "\n";
- }
-}
} // namespace android
diff --git a/compositor/DrmDisplayComposition.h b/compositor/DrmDisplayComposition.h
index 1738630..bbac0af 100644
--- a/compositor/DrmDisplayComposition.h
+++ b/compositor/DrmDisplayComposition.h
@@ -127,8 +127,6 @@
return planner_;
}
- void Dump(std::ostringstream *out) const;
-
UniqueFd out_fence_;
private:
diff --git a/compositor/DrmDisplayCompositor.cpp b/compositor/DrmDisplayCompositor.cpp
index a1fe50f..576c533 100644
--- a/compositor/DrmDisplayCompositor.cpp
+++ b/compositor/DrmDisplayCompositor.cpp
@@ -34,75 +34,29 @@
#include "drm/DrmCrtc.h"
#include "drm/DrmDevice.h"
#include "drm/DrmPlane.h"
+#include "drm/DrmUnique.h"
#include "utils/autolock.h"
#include "utils/log.h"
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:
- explicit CompositorVsyncCallback(DrmDisplayCompositor *compositor)
- : compositor_(compositor) {
- }
-
- void Callback(int display, int64_t timestamp) override {
- compositor_->Vsync(display, timestamp);
- }
-
- private:
- DrmDisplayCompositor *compositor_;
-};
-
DrmDisplayCompositor::DrmDisplayCompositor()
: resource_manager_(nullptr),
display_(-1),
initialized_(false),
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) {
- struct timespec ts {};
- if (clock_gettime(CLOCK_MONOTONIC, &ts))
- return;
- dump_last_timestamp_ns_ = ts.tv_sec * 1000 * 1000 * 1000 + ts.tv_nsec;
+ use_hw_overlays_(true) {
}
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);
- if (mode_.old_blob_id)
- 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_);
}
-int DrmDisplayCompositor::Init(ResourceManager *resource_manager, int display) {
+auto DrmDisplayCompositor::Init(ResourceManager *resource_manager, int display)
+ -> int {
resource_manager_ = resource_manager;
display_ = display;
DrmDevice *drm = resource_manager_->GetDrmDevice(display);
@@ -110,17 +64,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_);
- auto callback = std::make_shared<CompositorVsyncCallback>(this);
- vsync_worker_.RegisterCallback(callback);
-
initialized_ = true;
return 0;
}
@@ -137,19 +82,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_);
@@ -165,7 +97,7 @@
}
int DrmDisplayCompositor::DisablePlanes(DrmDisplayComposition *display_comp) {
- drmModeAtomicReqPtr pset = drmModeAtomicAlloc();
+ auto pset = MakeDrmModeAtomicReqUnique();
if (!pset) {
ALOGE("Failed to allocate property set");
return -ENOMEM;
@@ -175,26 +107,17 @@
std::vector<DrmCompositionPlane> &comp_planes = display_comp
->composition_planes();
for (DrmCompositionPlane &comp_plane : comp_planes) {
- DrmPlane *plane = comp_plane.plane();
- ret = drmModeAtomicAddProperty(pset, plane->id(),
- plane->crtc_property().id(), 0) < 0 ||
- drmModeAtomicAddProperty(pset, plane->id(), plane->fb_property().id(),
- 0) < 0;
- if (ret) {
- ALOGE("Failed to add plane %d disable to pset", plane->id());
- drmModeAtomicFree(pset);
- return ret;
+ if (comp_plane.plane()->AtomicDisablePlane(*pset) != 0) {
+ return -EINVAL;
}
}
DrmDevice *drm = resource_manager_->GetDrmDevice(display_);
- ret = drmModeAtomicCommit(drm->fd(), pset, 0, drm);
+ ret = drmModeAtomicCommit(drm->fd(), pset.get(), 0, drm);
if (ret) {
ALOGE("Failed to commit pset ret=%d\n", ret);
- drmModeAtomicFree(pset);
return ret;
}
- drmModeAtomicFree(pset);
return 0;
}
@@ -221,58 +144,29 @@
return -ENODEV;
}
- drmModeAtomicReqPtr pset = drmModeAtomicAlloc();
+ auto pset = MakeDrmModeAtomicReqUnique();
if (!pset) {
ALOGE("Failed to allocate property set");
return -ENOMEM;
}
- if (crtc->out_fence_ptr_property().id() != 0) {
- ret = drmModeAtomicAddProperty(pset, crtc->id(),
- crtc->out_fence_ptr_property().id(),
- (uint64_t)&out_fences[crtc->pipe()]);
- if (ret < 0) {
- ALOGE("Failed to add OUT_FENCE_PTR property to pset: %d", ret);
- drmModeAtomicFree(pset);
- return ret;
- }
+ if (crtc->out_fence_ptr_property() &&
+ !crtc->out_fence_ptr_property()
+ .AtomicSet(*pset, (uint64_t)&out_fences[crtc->pipe()])) {
+ return -EINVAL;
}
- if (mode_.needs_modeset) {
- ret = drmModeAtomicAddProperty(pset, crtc->id(),
- crtc->active_property().id(), 1);
- if (ret < 0) {
- ALOGE("Failed to add crtc active to pset\n");
- drmModeAtomicFree(pset);
- return ret;
- }
-
- ret = drmModeAtomicAddProperty(pset, crtc->id(), crtc->mode_property().id(),
- mode_.blob_id) < 0 ||
- drmModeAtomicAddProperty(pset, connector->id(),
- connector->crtc_id_property().id(),
- crtc->id()) < 0;
- if (ret) {
- ALOGE("Failed to add blob %d to pset", mode_.blob_id);
- drmModeAtomicFree(pset);
- return ret;
- }
+ if (mode_.blob &&
+ (!crtc->active_property().AtomicSet(*pset, 1) ||
+ !crtc->mode_property().AtomicSet(*pset, *mode_.blob) ||
+ !connector->crtc_id_property().AtomicSet(*pset, crtc->id()))) {
+ return -EINVAL;
}
for (DrmCompositionPlane &comp_plane : comp_planes) {
DrmPlane *plane = comp_plane.plane();
std::vector<size_t> &source_layers = comp_plane.source_layers();
- int fb_id = -1;
- int fence_fd = -1;
- hwc_rect_t display_frame;
- hwc_frect_t source_crop;
- uint64_t rotation = 0;
- uint64_t alpha = 0xFFFF;
- uint64_t blend = UINT64_MAX;
- uint64_t color_encoding = UINT64_MAX;
- uint64_t color_range = UINT64_MAX;
-
if (comp_plane.type() != DrmCompositionPlane::Type::kDisable) {
if (source_layers.size() > 1) {
ALOGE("Can't handle more than one source layer sz=%zu type=%d",
@@ -283,221 +177,17 @@
if (source_layers.empty() || source_layers.front() >= layers.size()) {
ALOGE("Source layer index %zu out of bounds %zu type=%d",
source_layers.front(), layers.size(), comp_plane.type());
- break;
+ return -EINVAL;
}
DrmHwcLayer &layer = layers[source_layers.front()];
- if (!layer.FbIdHandle) {
- ALOGE("Expected a valid framebuffer for pset");
- break;
+
+ if (plane->AtomicSetState(*pset, layer, source_layers.front(),
+ crtc->id()) != 0) {
+ return -EINVAL;
}
- fb_id = layer.FbIdHandle->GetFbId();
- fence_fd = layer.acquire_fence.Get();
- display_frame = layer.display_frame;
- source_crop = layer.source_crop;
- alpha = layer.alpha;
-
- if (plane->blend_property().id()) {
- switch (layer.blending) {
- case DrmHwcBlending::kPreMult:
- std::tie(blend, ret) = plane->blend_property().GetEnumValueWithName(
- "Pre-multiplied");
- break;
- case DrmHwcBlending::kCoverage:
- std::tie(blend, ret) = plane->blend_property().GetEnumValueWithName(
- "Coverage");
- break;
- case DrmHwcBlending::kNone:
- default:
- std::tie(blend, ret) = plane->blend_property().GetEnumValueWithName(
- "None");
- break;
- }
- }
-
- if (plane->zpos_property().id() &&
- !plane->zpos_property().is_immutable()) {
- uint64_t min_zpos = 0;
-
- // Ignore ret and use min_zpos as 0 by default
- std::tie(std::ignore, min_zpos) = plane->zpos_property().range_min();
-
- ret = drmModeAtomicAddProperty(pset, plane->id(),
- plane->zpos_property().id(),
- source_layers.front() + min_zpos) < 0;
- if (ret) {
- ALOGE("Failed to add zpos property %d to plane %d",
- plane->zpos_property().id(), plane->id());
- break;
- }
- }
-
- rotation = 0;
- if (layer.transform & DrmHwcTransform::kFlipH)
- rotation |= DRM_MODE_REFLECT_X;
- if (layer.transform & DrmHwcTransform::kFlipV)
- rotation |= DRM_MODE_REFLECT_Y;
- if (layer.transform & DrmHwcTransform::kRotate90)
- rotation |= DRM_MODE_ROTATE_90;
- else if (layer.transform & DrmHwcTransform::kRotate180)
- rotation |= DRM_MODE_ROTATE_180;
- else if (layer.transform & DrmHwcTransform::kRotate270)
- rotation |= DRM_MODE_ROTATE_270;
- else
- rotation |= DRM_MODE_ROTATE_0;
-
- if (fence_fd >= 0) {
- int prop_id = plane->in_fence_fd_property().id();
- if (prop_id == 0) {
- ALOGE("Failed to get IN_FENCE_FD property id");
- break;
- }
- ret = drmModeAtomicAddProperty(pset, plane->id(), prop_id, fence_fd);
- if (ret < 0) {
- ALOGE("Failed to add IN_FENCE_FD property to pset: %d", ret);
- break;
- }
- }
-
- if (plane->color_encoding_propery().id()) {
- switch (layer.dataspace & HAL_DATASPACE_STANDARD_MASK) {
- case HAL_DATASPACE_STANDARD_BT709:
- std::tie(color_encoding,
- ret) = plane->color_encoding_propery()
- .GetEnumValueWithName("ITU-R BT.709 YCbCr");
- break;
- case HAL_DATASPACE_STANDARD_BT601_625:
- case HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED:
- case HAL_DATASPACE_STANDARD_BT601_525:
- case HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED:
- std::tie(color_encoding,
- ret) = plane->color_encoding_propery()
- .GetEnumValueWithName("ITU-R BT.601 YCbCr");
- break;
- case HAL_DATASPACE_STANDARD_BT2020:
- case HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE:
- std::tie(color_encoding,
- ret) = plane->color_encoding_propery()
- .GetEnumValueWithName("ITU-R BT.2020 YCbCr");
- break;
- }
- }
-
- if (plane->color_range_property().id()) {
- switch (layer.dataspace & HAL_DATASPACE_RANGE_MASK) {
- case HAL_DATASPACE_RANGE_FULL:
- std::tie(color_range,
- ret) = plane->color_range_property()
- .GetEnumValueWithName("YCbCr full range");
- break;
- case HAL_DATASPACE_RANGE_LIMITED:
- std::tie(color_range,
- ret) = plane->color_range_property()
- .GetEnumValueWithName("YCbCr limited range");
- break;
- }
- }
- }
-
- // Disable the plane if there's no framebuffer
- if (fb_id < 0) {
- ret = drmModeAtomicAddProperty(pset, plane->id(),
- plane->crtc_property().id(), 0) < 0 ||
- drmModeAtomicAddProperty(pset, plane->id(),
- plane->fb_property().id(), 0) < 0;
- if (ret) {
- ALOGE("Failed to add plane %d disable to pset", plane->id());
- break;
- }
- continue;
- }
-
- ret = drmModeAtomicAddProperty(pset, plane->id(),
- plane->crtc_property().id(), crtc->id()) < 0;
- ret |= drmModeAtomicAddProperty(pset, plane->id(),
- plane->fb_property().id(), fb_id) < 0;
- ret |= drmModeAtomicAddProperty(pset, plane->id(),
- plane->crtc_x_property().id(),
- display_frame.left) < 0;
- ret |= drmModeAtomicAddProperty(pset, plane->id(),
- plane->crtc_y_property().id(),
- display_frame.top) < 0;
- ret |= drmModeAtomicAddProperty(pset, plane->id(),
- plane->crtc_w_property().id(),
- display_frame.right - display_frame.left) <
- 0;
- ret |= drmModeAtomicAddProperty(pset, plane->id(),
- plane->crtc_h_property().id(),
- display_frame.bottom - display_frame.top) <
- 0;
- ret |= drmModeAtomicAddProperty(pset, plane->id(),
- plane->src_x_property().id(),
- (int)(source_crop.left) << 16) < 0;
- ret |= drmModeAtomicAddProperty(pset, plane->id(),
- plane->src_y_property().id(),
- (int)(source_crop.top) << 16) < 0;
- ret |= drmModeAtomicAddProperty(pset, plane->id(),
- plane->src_w_property().id(),
- (int)(source_crop.right - source_crop.left)
- << 16) < 0;
- ret |= drmModeAtomicAddProperty(pset, plane->id(),
- plane->src_h_property().id(),
- (int)(source_crop.bottom - source_crop.top)
- << 16) < 0;
- if (ret) {
- ALOGE("Failed to add plane %d to set", plane->id());
- break;
- }
-
- if (plane->rotation_property().id()) {
- ret = drmModeAtomicAddProperty(pset, plane->id(),
- plane->rotation_property().id(),
- rotation) < 0;
- if (ret) {
- ALOGE("Failed to add rotation property %d to plane %d",
- plane->rotation_property().id(), plane->id());
- break;
- }
- }
-
- if (plane->alpha_property().id()) {
- ret = drmModeAtomicAddProperty(pset, plane->id(),
- plane->alpha_property().id(), alpha) < 0;
- if (ret) {
- ALOGE("Failed to add alpha property %d to plane %d",
- plane->alpha_property().id(), plane->id());
- break;
- }
- }
-
- if (plane->blend_property().id() && blend != UINT64_MAX) {
- ret = drmModeAtomicAddProperty(pset, plane->id(),
- plane->blend_property().id(), blend) < 0;
- if (ret) {
- ALOGE("Failed to add pixel blend mode property %d to plane %d",
- plane->blend_property().id(), plane->id());
- break;
- }
- }
-
- if (plane->color_encoding_propery().id() && color_encoding != UINT64_MAX) {
- ret = drmModeAtomicAddProperty(pset, plane->id(),
- plane->color_encoding_propery().id(),
- color_encoding) < 0;
- if (ret) {
- ALOGE("Failed to add COLOR_ENCODING property %d to plane %d",
- plane->color_encoding_propery().id(), plane->id());
- break;
- }
- }
-
- if (plane->color_range_property().id() && color_range != UINT64_MAX) {
- ret = drmModeAtomicAddProperty(pset, plane->id(),
- plane->color_range_property().id(),
- color_range) < 0;
- if (ret) {
- ALOGE("Failed to add COLOR_RANGE property %d to plane %d",
- plane->color_range_property().id(), plane->id());
- break;
+ } else {
+ if (plane->AtomicDisablePlane(*pset) != 0) {
+ return -EINVAL;
}
}
}
@@ -507,25 +197,15 @@
if (test_only)
flags |= DRM_MODE_ATOMIC_TEST_ONLY;
- ret = drmModeAtomicCommit(drm->fd(), pset, flags, drm);
+ ret = drmModeAtomicCommit(drm->fd(), pset.get(), flags, drm);
if (ret) {
if (!test_only)
ALOGE("Failed to commit pset ret=%d\n", ret);
- drmModeAtomicFree(pset);
return ret;
}
}
- if (pset)
- drmModeAtomicFree(pset);
- if (!test_only && mode_.needs_modeset) {
- ret = drm->DestroyPropertyBlob(mode_.old_blob_id);
- if (ret) {
- ALOGE("Failed to destroy old mode property blob %" PRIu32 "/%d",
- mode_.old_blob_id, ret);
- return ret;
- }
-
+ if (!test_only && mode_.blob) {
/* TODO: Add dpms to the pset when the kernel supports it */
ret = ApplyDpms(display_comp);
if (ret) {
@@ -534,12 +214,10 @@
}
connector->set_active_mode(mode_.mode);
- mode_.old_blob_id = mode_.blob_id;
- mode_.blob_id = 0;
- mode_.needs_modeset = false;
+ mode_.old_blob = std::move(mode_.blob);
}
- if (crtc->out_fence_ptr_property().id()) {
+ if (crtc->out_fence_ptr_property()) {
display_comp->out_fence_ = UniqueFd((int)out_fences[crtc->pipe()]);
}
@@ -564,21 +242,14 @@
return 0;
}
-std::tuple<int, uint32_t> DrmDisplayCompositor::CreateModeBlob(
- const DrmMode &mode) {
+auto DrmDisplayCompositor::CreateModeBlob(const DrmMode &mode)
+ -> DrmModeUserPropertyBlobUnique {
struct drm_mode_modeinfo drm_mode {};
mode.ToDrmModeModeInfo(&drm_mode);
- uint32_t id = 0;
DrmDevice *drm = resource_manager_->GetDrmDevice(display_);
- int ret = drm->CreatePropertyBlob(&drm_mode, sizeof(struct drm_mode_modeinfo),
- &id);
- if (ret) {
- ALOGE("Failed to create mode property blob %d", ret);
- return std::make_tuple(ret, 0);
- }
- ALOGE("Create blob_id %" PRIu32 "\n", id);
- return std::make_tuple(ret, id);
+ return drm->RegisterUserPropertyBlob(&drm_mode,
+ sizeof(struct drm_mode_modeinfo));
}
void DrmDisplayCompositor::ClearDisplay() {
@@ -593,9 +264,6 @@
void DrmDisplayCompositor::ApplyFrame(
std::unique_ptr<DrmDisplayComposition> composition, int status) {
- AutoLock lock(&lock_, __func__);
- if (lock.Lock())
- return;
int ret = status;
if (!ret) {
@@ -609,17 +277,8 @@
ClearDisplay();
return;
}
- ++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(
@@ -647,15 +306,11 @@
return ret;
case DRM_COMPOSITION_TYPE_MODESET:
mode_.mode = composition->display_mode();
- if (mode_.blob_id)
- resource_manager_->GetDrmDevice(display_)->DestroyPropertyBlob(
- mode_.blob_id);
- std::tie(ret, mode_.blob_id) = CreateModeBlob(mode_.mode);
- if (ret) {
+ mode_.blob = CreateModeBlob(mode_.mode);
+ if (!mode_.blob) {
ALOGE("Failed to create mode blob for display %d", display_);
- return ret;
+ return -EINVAL;
}
- mode_.needs_modeset = true;
return 0;
default:
ALOGE("Unknown composition type %d", composition->type());
@@ -669,99 +324,4 @@
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() {
- const std::lock_guard<std::mutex> lock(refresh_callback_lock);
-
- if (refresh_callback_hook_ && refresh_callback_data_) {
- {
- 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);
- refresh_callback_hook_(refresh_callback_data_, display_);
- return 0;
- }
-
- ALOGV("No writeback connector available");
- return -EINVAL;
-}
-
-int DrmDisplayCompositor::FlattenActiveComposition() {
- return FlattenOnClient();
-}
-
-bool DrmDisplayCompositor::CountdownExpired() const {
- return flatten_countdown_ <= 0;
-}
-
-void DrmDisplayCompositor::Vsync(int display, int64_t timestamp) {
- AutoLock lock(&lock_, __func__);
- 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);
-}
-
-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;
-
- pthread_mutex_unlock(&lock_);
-}
} // namespace android
diff --git a/compositor/DrmDisplayCompositor.h b/compositor/DrmDisplayCompositor.h
index c0eed0c..3227e12 100644
--- a/compositor/DrmDisplayCompositor.h
+++ b/compositor/DrmDisplayCompositor.h
@@ -32,45 +32,19 @@
#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();
- int Init(ResourceManager *resource_manager, int display);
-
- hwc2_callback_data_t refresh_callback_data_ = NULL;
- HWC2_PFN_REFRESH refresh_callback_hook_ = NULL;
- std::mutex refresh_callback_lock;
-
- void SetRefreshCallback(hwc2_callback_data_t data,
- hwc2_function_pointer_t hook) {
- const std::lock_guard<std::mutex> lock(refresh_callback_lock);
- refresh_callback_data_ = data;
- refresh_callback_hook_ = reinterpret_cast<HWC2_PFN_REFRESH>(hook);
- }
+ auto Init(ResourceManager *resource_manager, int display) -> int;
std::unique_ptr<DrmDisplayComposition> CreateInitializedComposition() const;
int ApplyComposition(std::unique_ptr<DrmDisplayComposition> composition);
int TestComposition(DrmDisplayComposition *composition);
int Composite();
- void Dump(std::ostringstream *out) const;
- void Vsync(int display, int64_t timestamp);
void ClearDisplay();
UniqueFd TakeOutFence() {
if (!active_composition_) {
@@ -79,27 +53,17 @@
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:
struct ModeState {
- bool needs_modeset = false;
DrmMode mode;
- uint32_t blob_id = 0;
- uint32_t old_blob_id = 0;
+ DrmModeUserPropertyBlobUnique blob;
+ DrmModeUserPropertyBlobUnique old_blob;
};
DrmDisplayCompositor(const DrmDisplayCompositor &) = delete;
- // We'll wait for acquire fences to fire for kAcquireWaitTimeoutMs,
- // kAcquireWaitTries times, logging a warning in between.
- static const int kAcquireWaitTries = 5;
- static const int kAcquireWaitTimeoutMs = 100;
-
int CommitFrame(DrmDisplayComposition *display_comp, bool test_only);
int ApplyDpms(DrmDisplayComposition *display_comp);
int DisablePlanes(DrmDisplayComposition *display_comp);
@@ -107,14 +71,7 @@
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);
+ auto CreateModeBlob(const DrmMode &mode) -> DrmModeUserPropertyBlobUnique;
ResourceManager *resource_manager_;
int display_;
@@ -127,21 +84,7 @@
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
diff --git a/drm/DrmConnector.cpp b/drm/DrmConnector.cpp
index 0468527..b3179c7 100644
--- a/drm/DrmConnector.cpp
+++ b/drm/DrmConnector.cpp
@@ -90,20 +90,19 @@
return ret;
}
-int DrmConnector::GetEdidBlob(drmModePropertyBlobPtr &blob) {
+auto DrmConnector::GetEdidBlob() -> DrmModePropertyBlobUnique {
uint64_t blob_id = 0;
int ret = UpdateEdidProperty();
- if (ret) {
- return ret;
+ if (ret != 0) {
+ return DrmModePropertyBlobUnique();
}
std::tie(ret, blob_id) = edid_property().value();
- if (ret) {
- return ret;
+ if (ret != 0) {
+ return DrmModePropertyBlobUnique();
}
- blob = drmModeGetPropertyBlob(drm_->fd(), blob_id);
- return !blob;
+ return MakeDrmModePropertyBlobUnique(drm_->fd(), blob_id);
}
uint32_t DrmConnector::id() const {
diff --git a/drm/DrmConnector.h b/drm/DrmConnector.h
index 3bc18c8..e2789ea 100644
--- a/drm/DrmConnector.h
+++ b/drm/DrmConnector.h
@@ -26,6 +26,7 @@
#include "DrmEncoder.h"
#include "DrmMode.h"
#include "DrmProperty.h"
+#include "DrmUnique.h"
namespace android {
@@ -41,7 +42,7 @@
int Init();
int UpdateEdidProperty();
- int GetEdidBlob(drmModePropertyBlobPtr &blob);
+ auto GetEdidBlob() -> DrmModePropertyBlobUnique;
uint32_t id() const;
diff --git a/drm/DrmDevice.cpp b/drm/DrmDevice.cpp
index abc8edc..1753ddc 100644
--- a/drm/DrmDevice.cpp
+++ b/drm/DrmDevice.cpp
@@ -161,7 +161,7 @@
return std::make_tuple(-EACCES, 0);
}
- drmModeResPtr res = drmModeGetResources(fd());
+ auto res = MakeDrmModeResUnique(fd());
if (!res) {
ALOGE("Failed to get DrmDevice resources");
return std::make_tuple(-ENODEV, 0);
@@ -177,15 +177,14 @@
bool found_primary = num_displays != 0;
for (int i = 0; !ret && i < res->count_crtcs; ++i) {
- drmModeCrtcPtr c = drmModeGetCrtc(fd(), res->crtcs[i]);
+ auto c = MakeDrmModeCrtcUnique(fd(), res->crtcs[i]);
if (!c) {
ALOGE("Failed to get crtc %d", res->crtcs[i]);
ret = -ENODEV;
break;
}
- std::unique_ptr<DrmCrtc> crtc(new DrmCrtc(this, c, i));
- drmModeFreeCrtc(c);
+ std::unique_ptr<DrmCrtc> crtc(new DrmCrtc(this, c.get(), i));
ret = crtc->Init();
if (ret) {
@@ -195,9 +194,9 @@
crtcs_.emplace_back(std::move(crtc));
}
- std::vector<int> possible_clones;
+ std::vector<uint32_t> possible_clones;
for (int i = 0; !ret && i < res->count_encoders; ++i) {
- drmModeEncoderPtr e = drmModeGetEncoder(fd(), res->encoders[i]);
+ auto e = MakeDrmModeEncoderUnique(fd(), res->encoders[i]);
if (!e) {
ALOGE("Failed to get encoder %d", res->encoders[i]);
ret = -ENODEV;
@@ -215,9 +214,8 @@
}
std::unique_ptr<DrmEncoder> enc(
- new DrmEncoder(e, current_crtc, possible_crtcs));
+ new DrmEncoder(e.get(), current_crtc, possible_crtcs));
possible_clones.push_back(e->possible_clones);
- drmModeFreeEncoder(e);
encoders_.emplace_back(std::move(enc));
}
@@ -229,7 +227,7 @@
}
for (int i = 0; !ret && i < res->count_connectors; ++i) {
- drmModeConnectorPtr c = drmModeGetConnector(fd(), res->connectors[i]);
+ auto c = MakeDrmModeConnectorUnique(fd(), res->connectors[i]);
if (!c) {
ALOGE("Failed to get connector %d", res->connectors[i]);
ret = -ENODEV;
@@ -248,9 +246,7 @@
}
std::unique_ptr<DrmConnector> conn(
- new DrmConnector(this, c, current_encoder, possible_encoders));
-
- drmModeFreeConnector(c);
+ new DrmConnector(this, c.get(), current_encoder, possible_encoders));
ret = conn->Init();
if (ret) {
@@ -299,30 +295,25 @@
}
}
- if (res)
- drmModeFreeResources(res);
-
// Catch-all for the above loops
if (ret)
return std::make_tuple(ret, 0);
- drmModePlaneResPtr plane_res = drmModeGetPlaneResources(fd());
+ auto plane_res = MakeDrmModePlaneResUnique(fd());
if (!plane_res) {
ALOGE("Failed to get plane resources");
return std::make_tuple(-ENOENT, 0);
}
for (uint32_t i = 0; i < plane_res->count_planes; ++i) {
- drmModePlanePtr p = drmModeGetPlane(fd(), plane_res->planes[i]);
+ auto p = MakeDrmModePlaneUnique(fd(), plane_res->planes[i]);
if (!p) {
ALOGE("Failed to get plane %d", plane_res->planes[i]);
ret = -ENODEV;
break;
}
- std::unique_ptr<DrmPlane> plane(new DrmPlane(this, p));
-
- drmModeFreePlane(p);
+ std::unique_ptr<DrmPlane> plane(new DrmPlane(this, p.get()));
ret = plane->Init();
if (ret) {
@@ -332,7 +323,6 @@
planes_.emplace_back(std::move(plane));
}
- drmModeFreePlaneResources(plane_res);
if (ret)
return std::make_tuple(ret, 0);
@@ -510,8 +500,8 @@
return -EINVAL;
}
-int DrmDevice::CreatePropertyBlob(void *data, size_t length,
- uint32_t *blob_id) const {
+auto DrmDevice::RegisterUserPropertyBlob(void *data, size_t length) const
+ -> DrmModeUserPropertyBlobUnique {
struct drm_mode_create_blob create_blob {};
create_blob.length = length;
create_blob.data = (__u64)data;
@@ -519,24 +509,21 @@
int ret = drmIoctl(fd(), DRM_IOCTL_MODE_CREATEPROPBLOB, &create_blob);
if (ret) {
ALOGE("Failed to create mode property blob %d", ret);
- return ret;
+ return DrmModeUserPropertyBlobUnique();
}
- *blob_id = create_blob.blob_id;
- return 0;
-}
-int DrmDevice::DestroyPropertyBlob(uint32_t blob_id) const {
- if (!blob_id)
- return 0;
-
- struct drm_mode_destroy_blob destroy_blob {};
- destroy_blob.blob_id = (__u32)blob_id;
- int ret = drmIoctl(fd(), DRM_IOCTL_MODE_DESTROYPROPBLOB, &destroy_blob);
- if (ret) {
- ALOGE("Failed to destroy mode property blob %" PRIu32 "/%d", blob_id, ret);
- return ret;
- }
- return 0;
+ return DrmModeUserPropertyBlobUnique(
+ new uint32_t(create_blob.blob_id), [this](const uint32_t *it) {
+ struct drm_mode_destroy_blob destroy_blob {};
+ destroy_blob.blob_id = (__u32)*it;
+ int err = drmIoctl(fd(), DRM_IOCTL_MODE_DESTROYPROPBLOB, &destroy_blob);
+ if (err != 0) {
+ ALOGE("Failed to destroy mode property blob %" PRIu32 "/%d", *it,
+ err);
+ }
+ // NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
+ delete it;
+ });
}
DrmEventListener *DrmDevice::event_listener() {
@@ -557,7 +544,7 @@
for (int i = 0; !found && (size_t)i < props->count_props; ++i) {
drmModePropertyPtr p = drmModeGetProperty(fd(), props->props[i]);
if (!strcmp(p->name, prop_name)) {
- property->Init(p, props->prop_values[i]);
+ property->Init(obj_id, p, props->prop_values[i]);
found = true;
}
drmModeFreeProperty(p);
@@ -567,19 +554,14 @@
return found ? 0 : -ENOENT;
}
-int DrmDevice::GetPlaneProperty(const DrmPlane &plane, const char *prop_name,
- DrmProperty *property) {
- return GetProperty(plane.id(), DRM_MODE_OBJECT_PLANE, prop_name, property);
-}
-
int DrmDevice::GetCrtcProperty(const DrmCrtc &crtc, const char *prop_name,
- DrmProperty *property) {
+ DrmProperty *property) const {
return GetProperty(crtc.id(), DRM_MODE_OBJECT_CRTC, prop_name, property);
}
int DrmDevice::GetConnectorProperty(const DrmConnector &connector,
const char *prop_name,
- DrmProperty *property) {
+ DrmProperty *property) const {
return GetProperty(connector.id(), DRM_MODE_OBJECT_CONNECTOR, prop_name,
property);
}
@@ -595,4 +577,22 @@
drmFreeVersion(ver);
return name;
}
+
+auto DrmDevice::IsKMSDev(const char *path) -> bool {
+ auto fd = UniqueFd(open(path, O_RDWR | O_CLOEXEC));
+ if (!fd) {
+ return false;
+ }
+
+ auto res = MakeDrmModeResUnique(fd.Get());
+ if (!res) {
+ return false;
+ }
+
+ bool is_kms = res->count_crtcs > 0 && res->count_connectors > 0 &&
+ res->count_encoders > 0;
+
+ return is_kms;
+}
+
} // namespace android
diff --git a/drm/DrmDevice.h b/drm/DrmDevice.h
index dfca263..81c60cd 100644
--- a/drm/DrmDevice.h
+++ b/drm/DrmDevice.h
@@ -69,20 +69,19 @@
DrmPlane *GetPlane(uint32_t id) const;
DrmEventListener *event_listener();
- int GetPlaneProperty(const DrmPlane &plane, const char *prop_name,
- DrmProperty *property);
int GetCrtcProperty(const DrmCrtc &crtc, const char *prop_name,
- DrmProperty *property);
+ DrmProperty *property) const;
int GetConnectorProperty(const DrmConnector &connector, const char *prop_name,
- DrmProperty *property);
+ DrmProperty *property) const;
std::string GetName() const;
const std::vector<std::unique_ptr<DrmCrtc>> &crtcs() const;
uint32_t next_mode_id();
- int CreatePropertyBlob(void *data, size_t length, uint32_t *blob_id) const;
- int DestroyPropertyBlob(uint32_t blob_id) const;
+ auto RegisterUserPropertyBlob(void *data, size_t length) const
+ -> DrmModeUserPropertyBlobUnique;
+
bool HandlesDisplay(int display) const;
void RegisterHotplugHandler(DrmEventHandler *handler) {
event_listener_.RegisterHotplugHandler(handler);
@@ -96,11 +95,14 @@
return *mDrmFbImporter.get();
}
- private:
- int TryEncoderForDisplay(int display, DrmEncoder *enc);
+ static auto IsKMSDev(const char *path) -> bool;
+
int GetProperty(uint32_t obj_id, uint32_t obj_type, const char *prop_name,
DrmProperty *property) const;
+ private:
+ int TryEncoderForDisplay(int display, DrmEncoder *enc);
+
int CreateDisplayPipe(DrmConnector *connector);
int AttachWriteback(DrmConnector *display_conn);
diff --git a/drm/DrmEventListener.cpp b/drm/DrmEventListener.cpp
index b303653..53e7032 100644
--- a/drm/DrmEventListener.cpp
+++ b/drm/DrmEventListener.cpp
@@ -84,7 +84,7 @@
void DrmEventListener::UEventHandler() {
char buffer[1024];
- int ret = 0;
+ ssize_t ret = 0;
struct timespec ts {};
@@ -93,7 +93,7 @@
if (!ret)
timestamp = ts.tv_sec * 1000 * 1000 * 1000 + ts.tv_nsec;
else
- ALOGE("Failed to get monotonic clock on hotplug %d", ret);
+ ALOGE("Failed to get monotonic clock on hotplug %zd", ret);
while (true) {
ret = read(uevent_fd_.Get(), &buffer, sizeof(buffer));
@@ -101,7 +101,7 @@
return;
if (ret < 0) {
- ALOGE("Got error reading uevent %d", ret);
+ ALOGE("Got error reading uevent %zd", ret);
return;
}
diff --git a/drm/DrmMode.cpp b/drm/DrmMode.cpp
index dd25758..c714458 100644
--- a/drm/DrmMode.cpp
+++ b/drm/DrmMode.cpp
@@ -121,7 +121,7 @@
float DrmMode::v_refresh() const {
// Always recalculate refresh to report correct float rate
- return clock_ / (float)(v_total_ * h_total_) * 1000.0F;
+ return static_cast<float>(clock_) / (float)(v_total_ * h_total_) * 1000.0F;
}
uint32_t DrmMode::flags() const {
diff --git a/drm/DrmPlane.cpp b/drm/DrmPlane.cpp
index 6433fb6..f6ddad2 100644
--- a/drm/DrmPlane.cpp
+++ b/drm/DrmPlane.cpp
@@ -39,12 +39,11 @@
int DrmPlane::Init() {
DrmProperty p;
- int ret = drm_->GetPlaneProperty(*this, "type", &p);
- if (ret) {
- ALOGE("Could not get plane type property");
- return ret;
+ if (!GetPlaneProperty("type", p)) {
+ return -ENOTSUP;
}
+ int ret = 0;
uint64_t type = 0;
std::tie(ret, type) = p.value();
if (ret) {
@@ -62,95 +61,73 @@
return -EINVAL;
}
- ret = drm_->GetPlaneProperty(*this, "CRTC_ID", &crtc_property_);
- if (ret) {
- ALOGE("Could not get CRTC_ID property");
- return ret;
+ if (!GetPlaneProperty("CRTC_ID", crtc_property_) ||
+ !GetPlaneProperty("FB_ID", fb_property_) ||
+ !GetPlaneProperty("CRTC_X", crtc_x_property_) ||
+ !GetPlaneProperty("CRTC_Y", crtc_y_property_) ||
+ !GetPlaneProperty("CRTC_W", crtc_w_property_) ||
+ !GetPlaneProperty("CRTC_H", crtc_h_property_) ||
+ !GetPlaneProperty("SRC_X", src_x_property_) ||
+ !GetPlaneProperty("SRC_Y", src_y_property_) ||
+ !GetPlaneProperty("SRC_W", src_w_property_) ||
+ !GetPlaneProperty("SRC_H", src_h_property_)) {
+ return -ENOTSUP;
}
- ret = drm_->GetPlaneProperty(*this, "FB_ID", &fb_property_);
- if (ret) {
- ALOGE("Could not get FB_ID property");
- return ret;
+ GetPlaneProperty("zpos", zpos_property_, Presence::kOptional);
+
+ if (GetPlaneProperty("rotation", rotation_property_, Presence::kOptional)) {
+ rotation_property_.AddEnumToMap("rotate-0", DrmHwcTransform::kIdentity,
+ transform_enum_map_);
+ rotation_property_.AddEnumToMap("rotate-90", DrmHwcTransform::kRotate90,
+ transform_enum_map_);
+ rotation_property_.AddEnumToMap("rotate-180", DrmHwcTransform::kRotate180,
+ transform_enum_map_);
+ rotation_property_.AddEnumToMap("rotate-270", DrmHwcTransform::kRotate270,
+ transform_enum_map_);
+ rotation_property_.AddEnumToMap("reflect-x", DrmHwcTransform::kFlipH,
+ transform_enum_map_);
+ rotation_property_.AddEnumToMap("reflect-y", DrmHwcTransform::kFlipV,
+ transform_enum_map_);
}
- ret = drm_->GetPlaneProperty(*this, "CRTC_X", &crtc_x_property_);
- if (ret) {
- ALOGE("Could not get CRTC_X property");
- return ret;
+ GetPlaneProperty("alpha", alpha_property_, Presence::kOptional);
+
+ if (GetPlaneProperty("pixel blend mode", blend_property_,
+ Presence::kOptional)) {
+ blend_property_.AddEnumToMap("Pre-multiplied", DrmHwcBlending::kPreMult,
+ blending_enum_map_);
+ blend_property_.AddEnumToMap("Coverage", DrmHwcBlending::kCoverage,
+ blending_enum_map_);
+ blend_property_.AddEnumToMap("None", DrmHwcBlending::kNone,
+ blending_enum_map_);
}
- ret = drm_->GetPlaneProperty(*this, "CRTC_Y", &crtc_y_property_);
- if (ret) {
- ALOGE("Could not get CRTC_Y property");
- return ret;
- }
-
- ret = drm_->GetPlaneProperty(*this, "CRTC_W", &crtc_w_property_);
- if (ret) {
- ALOGE("Could not get CRTC_W property");
- return ret;
- }
-
- ret = drm_->GetPlaneProperty(*this, "CRTC_H", &crtc_h_property_);
- if (ret) {
- ALOGE("Could not get CRTC_H property");
- return ret;
- }
-
- ret = drm_->GetPlaneProperty(*this, "SRC_X", &src_x_property_);
- if (ret) {
- ALOGE("Could not get SRC_X property");
- return ret;
- }
-
- ret = drm_->GetPlaneProperty(*this, "SRC_Y", &src_y_property_);
- if (ret) {
- ALOGE("Could not get SRC_Y property");
- return ret;
- }
-
- ret = drm_->GetPlaneProperty(*this, "SRC_W", &src_w_property_);
- if (ret) {
- ALOGE("Could not get SRC_W property");
- return ret;
- }
-
- ret = drm_->GetPlaneProperty(*this, "SRC_H", &src_h_property_);
- if (ret) {
- ALOGE("Could not get SRC_H property");
- return ret;
- }
-
- ret = drm_->GetPlaneProperty(*this, "zpos", &zpos_property_);
- if (ret)
- ALOGE("Could not get zpos property for plane %u", id());
-
- ret = drm_->GetPlaneProperty(*this, "rotation", &rotation_property_);
- if (ret)
- ALOGE("Could not get rotation property");
-
- ret = drm_->GetPlaneProperty(*this, "alpha", &alpha_property_);
- if (ret)
- ALOGI("Could not get alpha property");
-
- ret = drm_->GetPlaneProperty(*this, "pixel blend mode", &blend_property_);
- if (ret)
- ALOGI("Could not get pixel blend mode property");
-
- ret = drm_->GetPlaneProperty(*this, "IN_FENCE_FD", &in_fence_fd_property_);
- if (ret)
- ALOGI("Could not get IN_FENCE_FD property");
+ GetPlaneProperty("IN_FENCE_FD", in_fence_fd_property_, Presence::kOptional);
if (HasNonRgbFormat()) {
- ret = drm_->GetPlaneProperty(*this, "COLOR_ENCODING",
- &color_encoding_propery_);
- if (ret)
- ALOGI("Could not get COLOR_ENCODING property");
+ if (GetPlaneProperty("COLOR_ENCODING", color_encoding_propery_,
+ Presence::kOptional)) {
+ color_encoding_propery_.AddEnumToMap("ITU-R BT.709 YCbCr",
+ DrmHwcColorSpace::kItuRec709,
+ color_encoding_enum_map_);
+ color_encoding_propery_.AddEnumToMap("ITU-R BT.601 YCbCr",
+ DrmHwcColorSpace::kItuRec601,
+ color_encoding_enum_map_);
+ color_encoding_propery_.AddEnumToMap("ITU-R BT.2020 YCbCr",
+ DrmHwcColorSpace::kItuRec2020,
+ color_encoding_enum_map_);
+ }
- ret = drm_->GetPlaneProperty(*this, "COLOR_RANGE", &color_range_property_);
- if (ret)
- ALOGI("Could not get COLOR_RANGE property");
+ if (GetPlaneProperty("COLOR_RANGE", color_range_property_,
+ Presence::kOptional)) {
+ color_range_property_.AddEnumToMap("YCbCr full range",
+ DrmHwcSampleRange::kFullRange,
+ color_range_enum_map_);
+ color_range_property_.AddEnumToMap("YCbCr limited range",
+ DrmHwcSampleRange::kLimitedRange,
+ color_range_enum_map_);
+ }
}
return 0;
@@ -165,34 +142,15 @@
}
bool DrmPlane::IsValidForLayer(DrmHwcLayer *layer) {
- if (rotation_property_.id() == 0) {
+ if (!rotation_property_) {
if (layer->transform != DrmHwcTransform::kIdentity) {
- ALOGV("Rotation is not supported on plane %d", id_);
+ ALOGV("No rotation property on plane %d", id_);
return false;
}
} else {
- // For rotation checks, we assume the hardware reports its capabilities
- // consistently (e.g. a 270 degree rotation is a 90 degree rotation + H
- // flip + V flip; it wouldn't make sense to support all of the latter but
- // not the former).
- int ret = 0;
- const std::pair<enum DrmHwcTransform, std::string> transforms[] =
- {{kFlipH, "reflect-x"},
- {kFlipV, "reflect-y"},
- {kRotate90, "rotate-90"},
- {kRotate180, "rotate-180"},
- {kRotate270, "rotate-270"}};
-
- for (const auto &[transform, name] : transforms) {
- if (layer->transform & transform) {
- std::tie(std::ignore,
- ret) = rotation_property_.GetEnumValueWithName(name);
- if (ret) {
- ALOGV("Rotation '%s' is not supported on plane %d", name.c_str(),
- id_);
- return false;
- }
- }
+ if (transform_enum_map_.count(layer->transform) == 0) {
+ ALOGV("Transform is not supported on plane %d", id_);
+ return false;
}
}
@@ -201,34 +159,11 @@
return false;
}
- if (blend_property_.id() == 0) {
- if ((layer->blending != DrmHwcBlending::kNone) &&
- (layer->blending != DrmHwcBlending::kPreMult)) {
- ALOGV("Blending is not supported on plane %d", id_);
- return false;
- }
- } else {
- int ret = 0;
-
- switch (layer->blending) {
- case DrmHwcBlending::kPreMult:
- std::tie(std::ignore,
- ret) = blend_property_.GetEnumValueWithName("Pre-multiplied");
- break;
- case DrmHwcBlending::kCoverage:
- std::tie(std::ignore,
- ret) = blend_property_.GetEnumValueWithName("Coverage");
- break;
- case DrmHwcBlending::kNone:
- default:
- std::tie(std::ignore,
- ret) = blend_property_.GetEnumValueWithName("None");
- break;
- }
- if (ret) {
- ALOGV("Expected a valid blend mode on plane %d", id_);
- return false;
- }
+ if (blending_enum_map_.count(layer->blending) == 0 &&
+ layer->blending != DrmHwcBlending::kNone &&
+ layer->blending != DrmHwcBlending::kPreMult) {
+ ALOGV("Blending is not supported on plane %d", id_);
+ return false;
}
uint32_t format = layer->buffer_info.format;
@@ -257,71 +192,122 @@
}) != std::end(formats_);
}
-const DrmProperty &DrmPlane::crtc_property() const {
- return crtc_property_;
+static uint64_t ToDrmRotation(DrmHwcTransform transform) {
+ uint64_t rotation = 0;
+ if (transform & DrmHwcTransform::kFlipH)
+ rotation |= DRM_MODE_REFLECT_X;
+ if (transform & DrmHwcTransform::kFlipV)
+ rotation |= DRM_MODE_REFLECT_Y;
+ if (transform & DrmHwcTransform::kRotate90)
+ rotation |= DRM_MODE_ROTATE_90;
+ else if (transform & DrmHwcTransform::kRotate180)
+ rotation |= DRM_MODE_ROTATE_180;
+ else if (transform & DrmHwcTransform::kRotate270)
+ rotation |= DRM_MODE_ROTATE_270;
+ else
+ rotation |= DRM_MODE_ROTATE_0;
+
+ return rotation;
}
-const DrmProperty &DrmPlane::fb_property() const {
- return fb_property_;
+auto DrmPlane::AtomicSetState(drmModeAtomicReq &pset, DrmHwcLayer &layer,
+ uint32_t zpos, uint32_t crtc_id) -> int {
+ if (!layer.FbIdHandle) {
+ ALOGE("Expected a valid framebuffer for pset");
+ return -EINVAL;
+ }
+
+ if (zpos_property_ && !zpos_property_.is_immutable()) {
+ uint64_t min_zpos = 0;
+
+ // Ignore ret and use min_zpos as 0 by default
+ std::tie(std::ignore, min_zpos) = zpos_property_.range_min();
+
+ if (!zpos_property_.AtomicSet(pset, zpos + min_zpos)) {
+ return -EINVAL;
+ }
+ }
+
+ if (layer.acquire_fence &&
+ !in_fence_fd_property_.AtomicSet(pset, layer.acquire_fence.Get())) {
+ return -EINVAL;
+ }
+
+ if (!crtc_property_.AtomicSet(pset, crtc_id) ||
+ !fb_property_.AtomicSet(pset, layer.FbIdHandle->GetFbId()) ||
+ !crtc_x_property_.AtomicSet(pset, layer.display_frame.left) ||
+ !crtc_y_property_.AtomicSet(pset, layer.display_frame.top) ||
+ !crtc_w_property_.AtomicSet(pset, layer.display_frame.right -
+ layer.display_frame.left) ||
+ !crtc_h_property_.AtomicSet(pset, layer.display_frame.bottom -
+ layer.display_frame.top) ||
+ !src_x_property_.AtomicSet(pset, (int)(layer.source_crop.left) << 16) ||
+ !src_y_property_.AtomicSet(pset, (int)(layer.source_crop.top) << 16) ||
+ !src_w_property_.AtomicSet(pset, (int)(layer.source_crop.right -
+ layer.source_crop.left)
+ << 16) ||
+ !src_h_property_.AtomicSet(pset, (int)(layer.source_crop.bottom -
+ layer.source_crop.top)
+ << 16)) {
+ return -EINVAL;
+ }
+
+ if (rotation_property_ &&
+ !rotation_property_.AtomicSet(pset, ToDrmRotation(layer.transform))) {
+ return -EINVAL;
+ }
+
+ if (alpha_property_ && !alpha_property_.AtomicSet(pset, layer.alpha)) {
+ return -EINVAL;
+ }
+
+ if (blending_enum_map_.count(layer.blending) != 0 &&
+ !blend_property_.AtomicSet(pset, blending_enum_map_[layer.blending])) {
+ return -EINVAL;
+ }
+
+ if (color_encoding_enum_map_.count(layer.color_space) != 0 &&
+ !color_encoding_propery_
+ .AtomicSet(pset, color_encoding_enum_map_[layer.color_space])) {
+ return -EINVAL;
+ }
+
+ if (color_range_enum_map_.count(layer.sample_range) != 0 &&
+ !color_range_property_
+ .AtomicSet(pset, color_range_enum_map_[layer.sample_range])) {
+ return -EINVAL;
+ }
+
+ return 0;
}
-const DrmProperty &DrmPlane::crtc_x_property() const {
- return crtc_x_property_;
-}
+auto DrmPlane::AtomicDisablePlane(drmModeAtomicReq &pset) -> int {
+ if (!crtc_property_.AtomicSet(pset, 0) || !fb_property_.AtomicSet(pset, 0)) {
+ return -EINVAL;
+ }
-const DrmProperty &DrmPlane::crtc_y_property() const {
- return crtc_y_property_;
-}
-
-const DrmProperty &DrmPlane::crtc_w_property() const {
- return crtc_w_property_;
-}
-
-const DrmProperty &DrmPlane::crtc_h_property() const {
- return crtc_h_property_;
-}
-
-const DrmProperty &DrmPlane::src_x_property() const {
- return src_x_property_;
-}
-
-const DrmProperty &DrmPlane::src_y_property() const {
- return src_y_property_;
-}
-
-const DrmProperty &DrmPlane::src_w_property() const {
- return src_w_property_;
-}
-
-const DrmProperty &DrmPlane::src_h_property() const {
- return src_h_property_;
+ return 0;
}
const DrmProperty &DrmPlane::zpos_property() const {
return zpos_property_;
}
-const DrmProperty &DrmPlane::rotation_property() const {
- return rotation_property_;
+auto DrmPlane::GetPlaneProperty(const char *prop_name, DrmProperty &property,
+ Presence presence) -> bool {
+ int err = drm_->GetProperty(id_, DRM_MODE_OBJECT_PLANE, prop_name, &property);
+ if (err != 0) {
+ if (presence == Presence::kMandatory) {
+ ALOGE("Could not get mandatory property \"%s\" from plane %d", prop_name,
+ id_);
+ } else {
+ ALOGV("Could not get optional property \"%s\" from plane %d", prop_name,
+ id_);
+ }
+ return false;
+ }
+
+ return true;
}
-const DrmProperty &DrmPlane::alpha_property() const {
- return alpha_property_;
-}
-
-const DrmProperty &DrmPlane::blend_property() const {
- return blend_property_;
-}
-
-const DrmProperty &DrmPlane::in_fence_fd_property() const {
- return in_fence_fd_property_;
-}
-
-const DrmProperty &DrmPlane::color_encoding_propery() const {
- return color_encoding_propery_;
-}
-
-const DrmProperty &DrmPlane::color_range_property() const {
- return color_range_property_;
-}
} // namespace android
diff --git a/drm/DrmPlane.h b/drm/DrmPlane.h
index 862a0f3..34bba56 100644
--- a/drm/DrmPlane.h
+++ b/drm/DrmPlane.h
@@ -48,28 +48,20 @@
bool IsFormatSupported(uint32_t format) const;
bool HasNonRgbFormat() const;
- const DrmProperty &crtc_property() const;
- const DrmProperty &fb_property() const;
- const DrmProperty &crtc_x_property() const;
- const DrmProperty &crtc_y_property() const;
- const DrmProperty &crtc_w_property() const;
- const DrmProperty &crtc_h_property() const;
- const DrmProperty &src_x_property() const;
- const DrmProperty &src_y_property() const;
- const DrmProperty &src_w_property() const;
- const DrmProperty &src_h_property() const;
+ auto AtomicSetState(drmModeAtomicReq &pset, DrmHwcLayer &layer, uint32_t zpos,
+ uint32_t crtc_id) -> int;
+ auto AtomicDisablePlane(drmModeAtomicReq &pset) -> int;
const DrmProperty &zpos_property() const;
- const DrmProperty &rotation_property() const;
- const DrmProperty &alpha_property() const;
- const DrmProperty &blend_property() const;
- const DrmProperty &in_fence_fd_property() const;
- const DrmProperty &color_encoding_propery() const;
- const DrmProperty &color_range_property() const;
private:
DrmDevice *drm_;
uint32_t id_;
+ enum class Presence { kOptional, kMandatory };
+
+ auto GetPlaneProperty(const char *prop_name, DrmProperty &property,
+ Presence presence = Presence::kMandatory) -> bool;
+
uint32_t possible_crtc_mask_;
uint32_t type_{};
@@ -93,6 +85,11 @@
DrmProperty in_fence_fd_property_;
DrmProperty color_encoding_propery_;
DrmProperty color_range_property_;
+
+ std::map<DrmHwcBlending, uint64_t> blending_enum_map_;
+ std::map<DrmHwcColorSpace, uint64_t> color_encoding_enum_map_;
+ std::map<DrmHwcSampleRange, uint64_t> color_range_enum_map_;
+ std::map<DrmHwcTransform, uint64_t> transform_enum_map_;
};
} // namespace android
diff --git a/drm/DrmProperty.cpp b/drm/DrmProperty.cpp
index 8e6f7e5..32f1c62 100644
--- a/drm/DrmProperty.cpp
+++ b/drm/DrmProperty.cpp
@@ -14,6 +14,9 @@
* limitations under the License.
*/
+// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
+#define LOG_TAG "hwc-drm-property"
+
#include "DrmProperty.h"
#include <xf86drmMode.h>
@@ -23,6 +26,7 @@
#include <string>
#include "DrmDevice.h"
+#include "utils/log.h"
namespace android {
@@ -30,11 +34,13 @@
: value_(e->value), name_(e->name) {
}
-DrmProperty::DrmProperty(drmModePropertyPtr p, uint64_t value) {
- Init(p, value);
+DrmProperty::DrmProperty(uint32_t obj_id, drmModePropertyPtr p,
+ uint64_t value) {
+ Init(obj_id, p, value);
}
-void DrmProperty::Init(drmModePropertyPtr p, uint64_t value) {
+void DrmProperty::Init(uint32_t obj_id, drmModePropertyPtr p, uint64_t value) {
+ obj_id_ = obj_id;
id_ = p->prop_id;
flags_ = p->flags;
name_ = p->name;
@@ -131,4 +137,19 @@
return std::make_tuple(UINT64_MAX, -EINVAL);
}
+
+auto DrmProperty::AtomicSet(drmModeAtomicReq &pset, uint64_t value) const
+ -> bool {
+ if (id_ == 0) {
+ ALOGE("AtomicSet() is called on non-initialized property!");
+ return false;
+ }
+ if (drmModeAtomicAddProperty(&pset, obj_id_, id_, value) < 0) {
+ ALOGE("Failed to add obj_id: %u, prop_id: %u (%s) to pset", obj_id_, id_,
+ name_.c_str());
+ return false;
+ }
+ return true;
+}
+
} // namespace android
diff --git a/drm/DrmProperty.h b/drm/DrmProperty.h
index 70678fd..68f300f 100644
--- a/drm/DrmProperty.h
+++ b/drm/DrmProperty.h
@@ -20,6 +20,7 @@
#include <stdint.h>
#include <xf86drmMode.h>
+#include <map>
#include <string>
#include <vector>
@@ -37,11 +38,11 @@
class DrmProperty {
public:
DrmProperty() = default;
- DrmProperty(drmModePropertyPtr p, uint64_t value);
+ DrmProperty(uint32_t obj_id, drmModePropertyPtr p, uint64_t value);
DrmProperty(const DrmProperty &) = delete;
DrmProperty &operator=(const DrmProperty &) = delete;
- void Init(drmModePropertyPtr p, uint64_t value);
+ auto Init(uint32_t obj_id, drmModePropertyPtr p, uint64_t value) -> void;
std::tuple<uint64_t, int> GetEnumValueWithName(const std::string &name) const;
uint32_t id() const;
@@ -54,6 +55,17 @@
std::tuple<int, uint64_t> range_min() const;
std::tuple<int, uint64_t> range_max() const;
+ [[nodiscard]] auto AtomicSet(drmModeAtomicReq &pset, uint64_t value) const
+ -> bool;
+
+ template <class E>
+ auto AddEnumToMap(const std::string &name, E key, std::map<E, uint64_t> &map)
+ -> bool;
+
+ operator bool() const {
+ return id_ != 0;
+ }
+
private:
class DrmPropertyEnum {
public:
@@ -64,6 +76,7 @@
std::string name_;
};
+ uint32_t obj_id_ = 0;
uint32_t id_ = 0;
DrmPropertyType type_ = DRM_PROPERTY_TYPE_INVALID;
@@ -75,6 +88,21 @@
std::vector<DrmPropertyEnum> enums_;
std::vector<uint32_t> blob_ids_;
};
+
+template <class E>
+auto DrmProperty::AddEnumToMap(const std::string &name, E key,
+ std::map<E, uint64_t> &map) -> bool {
+ uint64_t enum_value = UINT64_MAX;
+ int err = 0;
+ std::tie(enum_value, err) = GetEnumValueWithName(name);
+ if (err == 0) {
+ map[key] = enum_value;
+ return true;
+ }
+
+ return false;
+}
+
} // namespace android
#endif // ANDROID_DRM_PROPERTY_H_
diff --git a/drm/DrmUnique.h b/drm/DrmUnique.h
new file mode 100644
index 0000000..282528b
--- /dev/null
+++ b/drm/DrmUnique.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef DRM_UNIQUE_H_
+#define DRM_UNIQUE_H_
+
+#include <xf86drmMode.h>
+
+#include <functional>
+#include <memory>
+
+template <typename T>
+using DUniquePtr = std::unique_ptr<T, std::function<void(T *)>>;
+
+using DrmModeAtomicReqUnique = DUniquePtr<drmModeAtomicReq>;
+auto inline MakeDrmModeAtomicReqUnique() {
+ return DrmModeAtomicReqUnique(drmModeAtomicAlloc(), [](drmModeAtomicReq *it) {
+ drmModeAtomicFree(it);
+ });
+};
+
+using DrmModeConnectorUnique = DUniquePtr<drmModeConnector>;
+auto inline MakeDrmModeConnectorUnique(int fd, uint32_t connector_id) {
+ return DrmModeConnectorUnique(drmModeGetConnector(fd, connector_id),
+ [](drmModeConnector *it) {
+ drmModeFreeConnector(it);
+ });
+}
+
+using DrmModeCrtcUnique = DUniquePtr<drmModeCrtc>;
+auto inline MakeDrmModeCrtcUnique(int fd, uint32_t crtc_id) {
+ return DrmModeCrtcUnique(drmModeGetCrtc(fd, crtc_id),
+ [](drmModeCrtc *it) { drmModeFreeCrtc(it); });
+}
+
+using DrmModeEncoderUnique = DUniquePtr<drmModeEncoder>;
+auto inline MakeDrmModeEncoderUnique(int fd, uint32_t encoder_id) {
+ return DrmModeEncoderUnique(drmModeGetEncoder(fd, encoder_id),
+ [](drmModeEncoder *it) {
+ drmModeFreeEncoder(it);
+ });
+}
+
+using DrmModePlaneUnique = DUniquePtr<drmModePlane>;
+auto inline MakeDrmModePlaneUnique(int fd, uint32_t plane_id) {
+ return DrmModePlaneUnique(drmModeGetPlane(fd, plane_id),
+ [](drmModePlane *it) { drmModeFreePlane(it); });
+}
+
+using DrmModePlaneResUnique = DUniquePtr<drmModePlaneRes>;
+auto inline MakeDrmModePlaneResUnique(int fd) {
+ return DrmModePlaneResUnique(drmModeGetPlaneResources(fd),
+ [](drmModePlaneRes *it) {
+ drmModeFreePlaneResources(it);
+ });
+}
+
+using DrmModeUserPropertyBlobUnique = DUniquePtr<uint32_t /*id*/>;
+
+using DrmModePropertyBlobUnique = DUniquePtr<drmModePropertyBlobRes>;
+auto inline MakeDrmModePropertyBlobUnique(int fd, uint32_t blob_id) {
+ return DrmModePropertyBlobUnique(drmModeGetPropertyBlob(fd, blob_id),
+ [](drmModePropertyBlobRes *it) {
+ drmModeFreePropertyBlob(it);
+ });
+}
+
+using DrmModeResUnique = DUniquePtr<drmModeRes>;
+auto inline MakeDrmModeResUnique(int fd) {
+ return DrmModeResUnique(drmModeGetResources(fd),
+ [](drmModeRes *it) { drmModeFreeResources(it); });
+}
+
+#endif
diff --git a/drm/ResourceManager.cpp b/drm/ResourceManager.cpp
index ef44180..c55d6b8 100644
--- a/drm/ResourceManager.cpp
+++ b/drm/ResourceManager.cpp
@@ -29,7 +29,7 @@
namespace android {
-ResourceManager::ResourceManager() : num_displays_(0), gralloc_(nullptr) {
+ResourceManager::ResourceManager() : num_displays_(0) {
}
int ResourceManager::Init() {
@@ -51,7 +51,7 @@
if (stat(path.str().c_str(), &buf))
break;
- if (IsKMSDev(path.str().c_str()))
+ if (DrmDevice::IsKMSDev(path.str().c_str()))
ret = AddDrmDevice(path.str());
}
}
@@ -70,8 +70,7 @@
return -EINVAL;
}
- return hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
- (const hw_module_t **)&gralloc_);
+ return 0;
}
int ResourceManager::AddDrmDevice(const std::string &path) {
@@ -84,44 +83,6 @@
return ret;
}
-DrmConnector *ResourceManager::AvailableWritebackConnector(int display) {
- DrmDevice *drm_device = GetDrmDevice(display);
- DrmConnector *writeback_conn = nullptr;
- if (drm_device) {
- writeback_conn = drm_device->AvailableWritebackConnector(display);
- if (writeback_conn)
- return writeback_conn;
- }
- for (auto &drm : drms_) {
- if (drm.get() == drm_device)
- continue;
- writeback_conn = drm->AvailableWritebackConnector(display);
- if (writeback_conn)
- return writeback_conn;
- }
- return writeback_conn;
-}
-
-bool ResourceManager::IsKMSDev(const char *path) {
- int fd = open(path, O_RDWR | O_CLOEXEC);
- if (fd < 0)
- return false;
-
- auto *res = drmModeGetResources(fd);
- if (!res) {
- close(fd);
- return false;
- }
-
- bool is_kms = res->count_crtcs > 0 && res->count_connectors > 0 &&
- res->count_encoders > 0;
-
- drmModeFreeResources(res);
- close(fd);
-
- return is_kms;
-}
-
DrmDevice *ResourceManager::GetDrmDevice(int display) {
for (auto &drm : drms_) {
if (drm->HandlesDisplay(display))
@@ -129,8 +90,4 @@
}
return nullptr;
}
-
-const gralloc_module_t *ResourceManager::gralloc() {
- return gralloc_;
-}
} // namespace android
diff --git a/drm/ResourceManager.h b/drm/ResourceManager.h
index 9b4155b..d9e0712 100644
--- a/drm/ResourceManager.h
+++ b/drm/ResourceManager.h
@@ -31,8 +31,6 @@
ResourceManager &operator=(const ResourceManager &) = delete;
int Init();
DrmDevice *GetDrmDevice(int display);
- const gralloc_module_t *gralloc();
- DrmConnector *AvailableWritebackConnector(int display);
const std::vector<std::unique_ptr<DrmDevice>> &getDrmDevices() const {
return drms_;
}
@@ -45,11 +43,9 @@
private:
int AddDrmDevice(std::string const &path);
- static bool IsKMSDev(const char *path);
int num_displays_;
std::vector<std::unique_ptr<DrmDevice>> drms_;
- const gralloc_module_t *gralloc_;
bool scale_with_gpu_{};
};
diff --git a/drm/VSyncWorker.cpp b/drm/VSyncWorker.cpp
index 25eeeab..6e92838 100644
--- a/drm/VSyncWorker.cpp
+++ b/drm/VSyncWorker.cpp
@@ -37,27 +37,16 @@
last_timestamp_(-1) {
}
-int VSyncWorker::Init(DrmDevice *drm, int display) {
+auto VSyncWorker::Init(DrmDevice *drm, int display,
+ std::function<void(uint64_t /*timestamp*/)> callback)
+ -> int {
drm_ = drm;
display_ = display;
+ callback_ = std::move(callback);
return InitWorker();
}
-void VSyncWorker::RegisterCallback(std::shared_ptr<VsyncCallback> callback) {
- Lock();
- callback_ = std::move(callback);
- Unlock();
-}
-
-void VSyncWorker::RegisterClientCallback(hwc2_callback_data_t data,
- hwc2_function_pointer_t hook) {
- Lock();
- vsync_callback_data_ = data;
- vsync_callback_hook_ = (HWC2_PFN_VSYNC)hook;
- Unlock();
-}
-
void VSyncWorker::VSyncControl(bool enabled) {
Lock();
enabled_ = enabled;
@@ -104,7 +93,8 @@
ALOGW("Vsync worker active with conn=%p refresh=%f\n", conn,
conn ? conn->active_mode().v_refresh() : 0.0F);
- int64_t phased_timestamp = GetPhasedVSync(kOneSecondNs / refresh,
+ int64_t phased_timestamp = GetPhasedVSync(kOneSecondNs /
+ static_cast<int>(refresh),
vsync.tv_sec * kOneSecondNs +
vsync.tv_nsec);
vsync.tv_sec = phased_timestamp / kOneSecondNs;
@@ -132,7 +122,6 @@
}
int display = display_;
- std::shared_ptr<VsyncCallback> callback(callback_);
Unlock();
DrmCrtc *crtc = drm_->GetCrtcForDisplay(display);
@@ -144,8 +133,9 @@
drmVBlank vblank;
memset(&vblank, 0, sizeof(vblank));
- vblank.request.type = (drmVBlankSeqType)(
- DRM_VBLANK_RELATIVE | (high_crtc & DRM_VBLANK_HIGH_CRTC_MASK));
+ vblank.request.type = (drmVBlankSeqType)(DRM_VBLANK_RELATIVE |
+ (high_crtc &
+ DRM_VBLANK_HIGH_CRTC_MASK));
vblank.request.sequence = 1;
int64_t timestamp = 0;
@@ -165,13 +155,9 @@
if (!enabled_)
return;
- if (callback)
- callback->Callback(display, timestamp);
-
- Lock();
- if (enabled_ && vsync_callback_hook_ && vsync_callback_data_)
- vsync_callback_hook_(vsync_callback_data_, display, timestamp);
- Unlock();
+ if (callback_) {
+ callback_(timestamp);
+ }
last_timestamp_ = timestamp;
}
diff --git a/drm/VSyncWorker.h b/drm/VSyncWorker.h
index b43918c..74ff487 100644
--- a/drm/VSyncWorker.h
+++ b/drm/VSyncWorker.h
@@ -23,6 +23,7 @@
#include <stdint.h>
#include <atomic>
+#include <functional>
#include <map>
#include "DrmDevice.h"
@@ -30,21 +31,13 @@
namespace android {
-class VsyncCallback {
- public:
- virtual ~VsyncCallback() = default;
- virtual void Callback(int display, int64_t timestamp) = 0;
-};
-
class VSyncWorker : public Worker {
public:
VSyncWorker();
~VSyncWorker() override = default;
- int Init(DrmDevice *drm, int display);
- void RegisterCallback(std::shared_ptr<VsyncCallback> callback);
- void RegisterClientCallback(hwc2_callback_data_t data,
- hwc2_function_pointer_t hook);
+ auto Init(DrmDevice *drm, int display,
+ std::function<void(uint64_t /*timestamp*/)> callback) -> int;
void VSyncControl(bool enabled);
@@ -57,17 +50,11 @@
DrmDevice *drm_;
- // shared_ptr since we need to use this outside of the thread lock (to
- // actually call the hook) and we don't want the memory freed until we're
- // done
- std::shared_ptr<VsyncCallback> callback_ = NULL;
+ std::function<void(uint64_t /*timestamp*/)> callback_;
int display_;
std::atomic_bool enabled_;
int64_t last_timestamp_;
-
- hwc2_callback_data_t vsync_callback_data_ = NULL;
- HWC2_PFN_VSYNC vsync_callback_hook_ = NULL;
};
} // namespace android
diff --git a/include/drmhwcgralloc.h b/include/drmhwcgralloc.h
index db54802..09c7499 100644
--- a/include/drmhwcgralloc.h
+++ b/include/drmhwcgralloc.h
@@ -28,7 +28,9 @@
uint32_t usage;
uint32_t pitches[HWC_DRM_BO_MAX_PLANES];
uint32_t offsets[HWC_DRM_BO_MAX_PLANES];
- uint32_t prime_fds[HWC_DRM_BO_MAX_PLANES];
+ /* sizes[] is used only by mapper@4 metadata getter for internal purposes */
+ uint32_t sizes[HWC_DRM_BO_MAX_PLANES];
+ int prime_fds[HWC_DRM_BO_MAX_PLANES];
uint64_t modifiers[HWC_DRM_BO_MAX_PLANES];
int acquire_fence_fd;
} hwc_drm_bo_t;
diff --git a/include/drmhwcomposer.h b/include/drmhwcomposer.h
index 22af12b..d02445b 100644
--- a/include/drmhwcomposer.h
+++ b/include/drmhwcomposer.h
@@ -32,7 +32,20 @@
class DrmFbIdHandle;
-enum DrmHwcTransform {
+enum class DrmHwcColorSpace : int32_t {
+ kUndefined,
+ kItuRec601,
+ kItuRec709,
+ kItuRec2020,
+};
+
+enum class DrmHwcSampleRange : int32_t {
+ kUndefined,
+ kFullRange,
+ kLimitedRange,
+};
+
+enum DrmHwcTransform : uint32_t {
kIdentity = 0,
kFlipH = 1 << 0,
kFlipV = 1 << 1,
@@ -42,9 +55,9 @@
};
enum class DrmHwcBlending : int32_t {
- kNone = HWC_BLENDING_NONE,
- kPreMult = HWC_BLENDING_PREMULT,
- kCoverage = HWC_BLENDING_COVERAGE,
+ kNone,
+ kPreMult,
+ kCoverage,
};
struct DrmHwcLayer {
@@ -53,19 +66,18 @@
std::shared_ptr<DrmFbIdHandle> FbIdHandle;
int gralloc_buffer_usage = 0;
- uint32_t transform;
+ DrmHwcTransform transform{};
DrmHwcBlending blending = DrmHwcBlending::kNone;
uint16_t alpha = 0xffff;
hwc_frect_t source_crop;
hwc_rect_t display_frame;
- android_dataspace_t dataspace;
+ DrmHwcColorSpace color_space;
+ DrmHwcSampleRange sample_range;
UniqueFd acquire_fence;
int ImportBuffer(DrmDevice *drmDevice);
- void SetTransform(int32_t sf_transform);
-
bool protected_usage() const {
return (gralloc_buffer_usage & GRALLOC_USAGE_PROTECTED) ==
GRALLOC_USAGE_PROTECTED;
diff --git a/utils/hwcutils.cpp b/utils/hwcutils.cpp
index 6de6500..5a46e9b 100644
--- a/utils/hwcutils.cpp
+++ b/utils/hwcutils.cpp
@@ -48,23 +48,4 @@
return 0;
}
-void DrmHwcLayer::SetTransform(int32_t sf_transform) {
- transform = 0;
- // 270* and 180* cannot be combined with flips. More specifically, they
- // already contain both horizontal and vertical flips, so those fields are
- // redundant in this case. 90* rotation can be combined with either horizontal
- // flip or vertical flip, so treat it differently
- if (sf_transform == HWC_TRANSFORM_ROT_270) {
- transform = DrmHwcTransform::kRotate270;
- } else if (sf_transform == HWC_TRANSFORM_ROT_180) {
- transform = DrmHwcTransform::kRotate180;
- } else {
- if (sf_transform & HWC_TRANSFORM_FLIP_H)
- transform |= DrmHwcTransform::kFlipH;
- if (sf_transform & HWC_TRANSFORM_FLIP_V)
- transform |= DrmHwcTransform::kFlipV;
- if (sf_transform & HWC_TRANSFORM_ROT_90)
- transform |= DrmHwcTransform::kRotate90;
- }
-}
} // namespace android
diff --git a/utils/properties.h b/utils/properties.h
index 607cbc5..c8ddbae 100644
--- a/utils/properties.h
+++ b/utils/properties.h
@@ -14,13 +14,13 @@
// NOLINTNEXTLINE(readability-identifier-naming)
constexpr int PROPERTY_VALUE_MAX = 92;
+// NOLINTNEXTLINE(readability-identifier-naming)
auto inline property_get(const char *name, char *value,
const char *default_value) -> int {
char *prop = std::getenv(name);
- if (prop == nullptr) {
- snprintf(value, PROPERTY_VALUE_MAX, "%s", default_value);
- }
- return strlen(value);
+ snprintf(value, PROPERTY_VALUE_MAX, "%s",
+ (prop == nullptr) ? default_value : prop);
+ return static_cast<int>(strlen(value));
}
#endif