diff options
author | John Stultz <john.stultz@linaro.org> | 2021-12-14 20:23:14 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2021-12-14 20:23:14 +0000 |
commit | 51fd1b6fdeaa34f67484932847855775861701fb (patch) | |
tree | d1cd72ebefd86571daeffd04591a8db7db9a27da | |
parent | 8fada8aa90879628b4ef609a96f1855aa5c7d466 (diff) | |
parent | 42f5da51924788b9416e3359059eaf9374113ab0 (diff) | |
download | drm_hwcomposer-51fd1b6fdeaa34f67484932847855775861701fb.tar.gz |
drm_hwcomposer: Merge remote-tracking branch 'aosp/upstream-main' into HEAD am: 774e5e3432 am: 24ccb88ece am: 42f5da5192
Original change: https://android-review.googlesource.com/c/platform/external/drm_hwcomposer/+/1921343
Change-Id: Iae3684f162cd9e86a0feca58480a2dbcf3f450fe
29 files changed, 659 insertions, 800 deletions
diff --git a/.ci/.common.sh b/.ci/.common.sh index 21c2b28..48cc594 100644 --- a/.ci/.common.sh +++ b/.ci/.common.sh @@ -4,7 +4,7 @@ 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 " +CXXARGS+=" -D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS -Wno-gnu-include-next -Wsign-compare" CXXARGS+=" -fvisibility-inlines-hidden -std=gnu++17 -DHWC2_USE_CPP11 -DHWC2_INCLUDE_STRINGIFICATION -fno-rtti" BUILD_FILES=( @@ -27,13 +27,13 @@ drm/DrmConnector.cpp drm/DrmCrtc.cpp drm/DrmDevice.cpp drm/DrmEncoder.cpp -drm/DrmEventListener.cpp drm/DrmFbImporter.cpp drm/DrmMode.cpp drm/DrmPlane.cpp drm/DrmProperty.cpp DrmHwcTwo.cpp drm/ResourceManager.cpp +drm/UEventListener.cpp drm/VSyncWorker.cpp tests/worker_test.cpp utils/autolock.cpp @@ -95,9 +95,8 @@ cc_defaults { vendor: true, } -cc_library_static { - name: "drm_hwcomposer", - defaults: ["hwcomposer.drm_defaults"], +filegroup { + name: "drm_hwcomposer_common", srcs: [ "DrmHwcTwo.cpp", @@ -112,12 +111,12 @@ cc_library_static { "drm/DrmCrtc.cpp", "drm/DrmDevice.cpp", "drm/DrmEncoder.cpp", - "drm/DrmEventListener.cpp", "drm/DrmFbImporter.cpp", "drm/DrmMode.cpp", "drm/DrmPlane.cpp", "drm/DrmProperty.cpp", "drm/ResourceManager.cpp", + "drm/UEventListener.cpp", "drm/VSyncWorker.cpp", "utils/autolock.cpp", @@ -130,19 +129,30 @@ cc_library_static { ], } +// Kept only for compatibility with older Android version. Please do not use! +cc_library_static { + name: "drm_hwcomposer", + defaults: ["hwcomposer.drm_defaults"], + srcs: [":drm_hwcomposer_common"], +} + cc_library_shared { name: "hwcomposer.drm", defaults: ["hwcomposer.drm_defaults"], - whole_static_libs: ["drm_hwcomposer"], - srcs: ["bufferinfo/legacy/BufferInfoLibdrm.cpp"], + srcs: [ + ":drm_hwcomposer_common", + "bufferinfo/legacy/BufferInfoLibdrm.cpp", + ], + cflags: ["-DUSE_IMAPPER4_METADATA_API"], } cc_library_shared { name: "hwcomposer.drm_minigbm", defaults: ["hwcomposer.drm_defaults"], - whole_static_libs: ["drm_hwcomposer"], - srcs: ["bufferinfo/legacy/BufferInfoMinigbm.cpp"], - include_dirs: ["external/minigbm/cros_gralloc"], + srcs: [ + ":drm_hwcomposer_common", + "bufferinfo/legacy/BufferInfoMinigbm.cpp", + ], } // Used by hwcomposer.drm_imagination diff --git a/DrmHwcTwo.cpp b/DrmHwcTwo.cpp index 6ec8b31..9bf1327 100644 --- a/DrmHwcTwo.cpp +++ b/DrmHwcTwo.cpp @@ -87,11 +87,9 @@ HWC2::Error DrmHwcTwo::Init() { } } - const auto &drm_devices = resource_manager_.getDrmDevices(); - for (const auto &device : drm_devices) { - // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) - device->RegisterHotplugHandler(new DrmHotplugHandler(this, device.get())); - } + resource_manager_.GetUEventListener()->RegisterHotplugHandler( + [this] { HandleHotplugUEvent(); }); + return ret; } @@ -253,7 +251,8 @@ DrmHwcTwo::HwcDisplay::HwcDisplay(ResourceManager *resource_manager, } void DrmHwcTwo::HwcDisplay::ClearDisplay() { - compositor_.ClearDisplay(); + AtomicCommitArgs a_args = {.clear_active_composition = true}; + compositor_.ExecuteAtomicCommit(a_args); } HWC2::Error DrmHwcTwo::HwcDisplay::Init(std::vector<DrmPlane *> *planes) { @@ -342,6 +341,8 @@ HWC2::Error DrmHwcTwo::HwcDisplay::Init(std::vector<DrmPlane *> *planes) { return HWC2::Error::BadDisplay; } + client_layer_.SetLayerBlendMode(HWC2_BLEND_MODE_PREMULTIPLIED); + return ChosePreferredConfig(); } @@ -350,9 +351,9 @@ HWC2::Error DrmHwcTwo::HwcDisplay::ChosePreferredConfig() { uint32_t num_configs = 0; HWC2::Error err = GetDisplayConfigs(&num_configs, nullptr); if (err != HWC2::Error::None || !num_configs) - return err; + return HWC2::Error::BadDisplay; - return SetActiveConfig(connector_->get_preferred_mode_id()); + return SetActiveConfig(preferred_config_id_); } HWC2::Error DrmHwcTwo::HwcDisplay::AcceptDisplayChanges() { @@ -379,13 +380,13 @@ HWC2::Error DrmHwcTwo::HwcDisplay::DestroyLayer(hwc2_layer_t layer) { return HWC2::Error::None; } -HWC2::Error DrmHwcTwo::HwcDisplay::GetActiveConfig(hwc2_config_t *config) { +HWC2::Error DrmHwcTwo::HwcDisplay::GetActiveConfig( + hwc2_config_t *config) const { supported(__func__); - DrmMode const &mode = connector_->active_mode(); - if (mode.id() == 0) + if (hwc_configs_.count(active_config_id_) == 0) return HWC2::Error::BadConfig; - *config = mode.id(); + *config = active_config_id_; return HWC2::Error::None; } @@ -444,46 +445,47 @@ HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayAttribute(hwc2_config_t config, int32_t attribute_in, int32_t *value) { supported(__func__); - auto mode = std::find_if(connector_->modes().begin(), - connector_->modes().end(), - [config](DrmMode const &m) { - return m.id() == config; - }); - if (mode == connector_->modes().end()) { - ALOGE("Could not find active mode for %d", config); + int conf = static_cast<int>(config); + + if (hwc_configs_.count(conf) == 0) { + ALOGE("Could not find active mode for %d", conf); return HWC2::Error::BadConfig; } + auto &hwc_config = hwc_configs_[conf]; + static const int32_t kUmPerInch = 25400; uint32_t mm_width = connector_->mm_width(); uint32_t mm_height = connector_->mm_height(); auto attribute = static_cast<HWC2::Attribute>(attribute_in); switch (attribute) { case HWC2::Attribute::Width: - *value = static_cast<int>(mode->h_display()); + *value = static_cast<int>(hwc_config.mode.h_display()); break; case HWC2::Attribute::Height: - *value = static_cast<int>(mode->v_display()); + *value = static_cast<int>(hwc_config.mode.v_display()); break; case HWC2::Attribute::VsyncPeriod: // in nanoseconds - *value = static_cast<int>(1E9 / mode->v_refresh()); + *value = static_cast<int>(1E9 / hwc_config.mode.v_refresh()); break; case HWC2::Attribute::DpiX: // Dots per 1000 inches - *value = mm_width - ? static_cast<int>(mode->h_display() * kUmPerInch / mm_width) - : -1; + *value = mm_width ? static_cast<int>(hwc_config.mode.h_display() * + kUmPerInch / mm_width) + : -1; break; case HWC2::Attribute::DpiY: // Dots per 1000 inches - *value = mm_height ? static_cast<int>(mode->v_display() * kUmPerInch / - mm_height) + *value = mm_height ? static_cast<int>(hwc_config.mode.v_display() * + kUmPerInch / mm_height) : -1; break; #if PLATFORM_SDK_VERSION > 29 case HWC2::Attribute::ConfigGroup: - *value = 0; /* TODO: Add support for config groups */ + /* Dispite ConfigGroup is a part of HWC2.4 API, framework + * able to request it even if service @2.1 is used */ + *value = hwc_config.group_id; break; #endif default: @@ -507,79 +509,149 @@ HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayConfigs(uint32_t *num_configs, ALOGE("Failed to update display modes %d", ret); return HWC2::Error::BadDisplay; } - } - // Since the upper layers only look at vactive/hactive/refresh, height and - // width, it doesn't differentiate interlaced from progressive and other - // similar modes. Depending on the order of modes we return to SF, it could - // end up choosing a suboptimal configuration and dropping the preferred - // mode. To workaround this, don't offer interlaced modes to SF if there is - // at least one non-interlaced alternative and only offer a single WxH@R - // mode with at least the prefered mode from in DrmConnector::UpdateModes() - - // TODO(nobody): Remove the following block of code until AOSP handles all - // modes - std::vector<DrmMode> sel_modes; - - // Add the preferred mode first to be sure it's not dropped - auto mode = std::find_if(connector_->modes().begin(), - connector_->modes().end(), [&](DrmMode const &m) { - return m.id() == - connector_->get_preferred_mode_id(); - }); - if (mode != connector_->modes().end()) - sel_modes.push_back(*mode); - - // Add the active mode if different from preferred mode - if (connector_->active_mode().id() != connector_->get_preferred_mode_id()) - sel_modes.push_back(connector_->active_mode()); - - // Cycle over the modes and filter out "similar" modes, keeping only the - // first ones in the order given by DRM (from CEA ids and timings order) - for (const DrmMode &mode : connector_->modes()) { - // TODO(nobody): Remove this when 3D Attributes are in AOSP - if (mode.flags() & DRM_MODE_FLAG_3D_MASK) - continue; + hwc_configs_.clear(); + preferred_config_id_ = 0; + int preferred_config_group_id_ = 0; - // TODO(nobody): Remove this when the Interlaced attribute is in AOSP - if (mode.flags() & DRM_MODE_FLAG_INTERLACE) { - auto m = std::find_if(connector_->modes().begin(), - connector_->modes().end(), - [&mode](DrmMode const &m) { - return !(m.flags() & DRM_MODE_FLAG_INTERLACE) && - m.h_display() == mode.h_display() && - m.v_display() == mode.v_display(); - }); - if (m == connector_->modes().end()) - sel_modes.push_back(mode); + if (connector_->modes().empty()) { + ALOGE("No modes reported by KMS"); + return HWC2::Error::BadDisplay; + } - continue; + int last_config_id = 1; + int last_group_id = 1; + + /* Group modes */ + for (const auto &mode : connector_->modes()) { + /* Find group for the new mode or create new group */ + int group_found = 0; + for (auto &hwc_config : hwc_configs_) { + if (mode.h_display() == hwc_config.second.mode.h_display() && + mode.v_display() == hwc_config.second.mode.v_display()) { + group_found = hwc_config.second.group_id; + } + } + if (group_found == 0) { + group_found = last_group_id++; + } + + bool disabled = false; + if (mode.flags() & DRM_MODE_FLAG_3D_MASK) { + ALOGI("Disabling display mode %s (Modes with 3D flag aren't supported)", + mode.name().c_str()); + disabled = true; + } + + /* Add config */ + hwc_configs_[last_config_id] = { + .id = last_config_id, + .group_id = group_found, + .mode = mode, + .disabled = disabled, + }; + + /* Chwck if the mode is preferred */ + if ((mode.type() & DRM_MODE_TYPE_PREFERRED) != 0 && + preferred_config_id_ == 0) { + preferred_config_id_ = last_config_id; + preferred_config_group_id_ = group_found; + } + + last_config_id++; } - // Search for a similar WxH@R mode in the filtered list and drop it if - // another mode with the same WxH@R has already been selected - // TODO(nobody): Remove this when AOSP handles duplicates modes - auto m = std::find_if(sel_modes.begin(), sel_modes.end(), - [&mode](DrmMode const &m) { - return m.h_display() == mode.h_display() && - m.v_display() == mode.v_display() && - m.v_refresh() == mode.v_refresh(); - }); - if (m == sel_modes.end()) - sel_modes.push_back(mode); - } + /* We must have preferred mode. Set first mode as preferred + * in case KMS haven't reported anything. */ + if (preferred_config_id_ == 0) { + preferred_config_id_ = 1; + preferred_config_group_id_ = 1; + } - auto num_modes = static_cast<uint32_t>(sel_modes.size()); - if (!configs) { - *num_configs = num_modes; - return HWC2::Error::None; + for (int group = 1; group < last_group_id; group++) { + bool has_interlaced = false; + bool has_progressive = false; + for (auto &hwc_config : hwc_configs_) { + if (hwc_config.second.group_id != group || hwc_config.second.disabled) { + continue; + } + + if (hwc_config.second.IsInterlaced()) { + has_interlaced = true; + } else { + has_progressive = true; + } + } + + bool has_both = has_interlaced && has_progressive; + if (!has_both) { + continue; + } + + bool group_contains_preferred_interlaced = false; + if (group == preferred_config_group_id_ && + hwc_configs_[preferred_config_id_].IsInterlaced()) { + group_contains_preferred_interlaced = true; + } + + for (auto &hwc_config : hwc_configs_) { + if (hwc_config.second.group_id != group || hwc_config.second.disabled) { + continue; + } + + bool disable = group_contains_preferred_interlaced + ? !hwc_config.second.IsInterlaced() + : hwc_config.second.IsInterlaced(); + + if (disable) { + ALOGI( + "Group %i: Disabling display mode %s (This group should consist " + "of %s modes)", + group, hwc_config.second.mode.name().c_str(), + group_contains_preferred_interlaced ? "interlaced" + : "progressive"); + + hwc_config.second.disabled = true; + } + } + } + + /* Group should not contain 2 modes with FPS delta less than ~1HZ + * otherwise android.graphics.cts.SetFrameRateTest CTS will fail + */ + for (int m1 = 1; m1 < last_config_id; m1++) { + for (int m2 = 1; m2 < last_config_id; m2++) { + if (m1 != m2 && + hwc_configs_[m1].group_id == hwc_configs_[m2].group_id && + !hwc_configs_[m1].disabled && !hwc_configs_[m2].disabled && + fabsf(hwc_configs_[m1].mode.v_refresh() - + hwc_configs_[m2].mode.v_refresh()) < 1.0) { + ALOGI( + "Group %i: Disabling display mode %s (Refresh rate value is " + "too close to existing mode %s)", + hwc_configs_[m2].group_id, hwc_configs_[m2].mode.name().c_str(), + hwc_configs_[m1].mode.name().c_str()); + + hwc_configs_[m2].disabled = true; + } + } + } } uint32_t idx = 0; - for (const DrmMode &mode : sel_modes) { - if (idx >= *num_configs) - break; - configs[idx++] = mode.id(); + for (auto &hwc_config : hwc_configs_) { + if (hwc_config.second.disabled) { + continue; + } + + if (configs != nullptr) { + if (idx >= *num_configs) { + break; + } + configs[idx] = hwc_config.second.id; + } + + idx++; } *num_configs = idx; return HWC2::Error::None; @@ -659,20 +731,7 @@ HWC2::Error DrmHwcTwo::HwcDisplay::GetReleaseFences(uint32_t *num_elements, return HWC2::Error::None; } -void DrmHwcTwo::HwcDisplay::AddFenceToPresentFence(UniqueFd fd) { - if (!fd) { - return; - } - - if (present_fence_) { - present_fence_ = UniqueFd( - sync_merge("dc_present", present_fence_.Get(), fd.Get())); - } else { - present_fence_ = std::move(fd); - } -} - -HWC2::Error DrmHwcTwo::HwcDisplay::CreateComposition(bool test) { +HWC2::Error DrmHwcTwo::HwcDisplay::CreateComposition(AtomicCommitArgs &a_args) { // order the layers by z-order bool use_client_layer = false; uint32_t client_z_order = UINT32_MAX; @@ -711,12 +770,12 @@ HWC2::Error DrmHwcTwo::HwcDisplay::CreateComposition(bool test) { composition_layers.emplace_back(std::move(layer)); } - auto composition = std::make_unique<DrmDisplayComposition>(crtc_, + auto composition = std::make_shared<DrmDisplayComposition>(crtc_, planner_.get()); // TODO(nobody): Don't always assume geometry changed int ret = composition->SetLayers(composition_layers.data(), - composition_layers.size(), true); + composition_layers.size()); if (ret) { ALOGE("Failed to set layers in the composition ret=%d", ret); return HWC2::Error::BadLayer; @@ -740,14 +799,11 @@ HWC2::Error DrmHwcTwo::HwcDisplay::CreateComposition(bool test) { i = overlay_planes.erase(i); } - if (test) { - ret = compositor_.TestComposition(composition.get()); - } else { - ret = compositor_.ApplyComposition(std::move(composition)); - AddFenceToPresentFence(compositor_.TakeOutFence()); - } + a_args.composition = composition; + ret = compositor_.ExecuteAtomicCommit(a_args); + if (ret) { - if (!test) + if (!a_args.test_only) ALOGE("Failed to apply the frame composition ret=%d", ret); return HWC2::Error::BadParameter; } @@ -763,7 +819,9 @@ HWC2::Error DrmHwcTwo::HwcDisplay::PresentDisplay(int32_t *present_fence) { ++total_stats_.total_frames_; - ret = CreateComposition(false); + AtomicCommitArgs a_args{}; + ret = CreateComposition(a_args); + if (ret != HWC2::Error::None) ++total_stats_.failed_kms_present_; @@ -775,7 +833,7 @@ HWC2::Error DrmHwcTwo::HwcDisplay::PresentDisplay(int32_t *present_fence) { if (ret != HWC2::Error::None) return ret; - *present_fence = present_fence_.Release(); + *present_fence = a_args.out_fence.Release(); ++frame_no_; return HWC2::Error::None; @@ -783,35 +841,34 @@ HWC2::Error DrmHwcTwo::HwcDisplay::PresentDisplay(int32_t *present_fence) { HWC2::Error DrmHwcTwo::HwcDisplay::SetActiveConfig(hwc2_config_t config) { supported(__func__); - auto mode = std::find_if(connector_->modes().begin(), - connector_->modes().end(), - [config](DrmMode const &m) { - return m.id() == config; - }); - if (mode == connector_->modes().end()) { - ALOGE("Could not find active mode for %d", config); - return HWC2::Error::BadConfig; - } - auto composition = std::make_unique<DrmDisplayComposition>(crtc_, - planner_.get()); - int ret = composition->SetDisplayMode(*mode); - if (ret) { + int conf = static_cast<int>(config); + + if (hwc_configs_.count(conf) == 0) { + ALOGE("Could not find active mode for %d", conf); return HWC2::Error::BadConfig; } - ret = compositor_.ApplyComposition(std::move(composition)); - if (ret) { - ALOGE("Failed to queue dpms composition on %d", ret); + + auto &mode = hwc_configs_[conf].mode; + + AtomicCommitArgs a_args = { + .display_mode = mode, + .clear_active_composition = true, + }; + + int err = compositor_.ExecuteAtomicCommit(a_args); + if (err != 0) { + ALOGE("Failed to queue mode changing commit %d", err); return HWC2::Error::BadConfig; } - connector_->set_active_mode(*mode); + active_config_id_ = conf; // Setup the client layer's dimensions hwc_rect_t display_frame = {.left = 0, .top = 0, - .right = static_cast<int>(mode->h_display()), - .bottom = static_cast<int>(mode->v_display())}; + .right = static_cast<int>(mode.h_display()), + .bottom = static_cast<int>(mode.v_display())}; client_layer_.SetLayerDisplayFrame(display_frame); return HWC2::Error::None; @@ -883,14 +940,15 @@ HWC2::Error DrmHwcTwo::HwcDisplay::SetOutputBuffer(buffer_handle_t buffer, HWC2::Error DrmHwcTwo::HwcDisplay::SetPowerMode(int32_t mode_in) { supported(__func__); - uint64_t dpms_value = 0; auto mode = static_cast<HWC2::PowerMode>(mode_in); + AtomicCommitArgs a_args{}; + switch (mode) { case HWC2::PowerMode::Off: - dpms_value = DRM_MODE_DPMS_OFF; + a_args.active = false; break; case HWC2::PowerMode::On: - dpms_value = DRM_MODE_DPMS_ON; + a_args.active = true; break; case HWC2::PowerMode::Doze: case HWC2::PowerMode::DozeSuspend: @@ -900,12 +958,9 @@ HWC2::Error DrmHwcTwo::HwcDisplay::SetPowerMode(int32_t mode_in) { return HWC2::Error::BadParameter; }; - auto composition = std::make_unique<DrmDisplayComposition>(crtc_, - planner_.get()); - composition->SetDpmsMode(dpms_value); - int ret = compositor_.ApplyComposition(std::move(composition)); - if (ret) { - ALOGE("Failed to apply the dpms composition ret=%d", ret); + int err = compositor_.ExecuteAtomicCommit(a_args); + if (err) { + ALOGE("Failed to apply the dpms composition err=%d", err); return HWC2::Error::BadParameter; } return HWC2::Error::None; @@ -956,12 +1011,8 @@ HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayConnectionType(uint32_t *outType) { HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayVsyncPeriod( hwc2_vsync_period_t *outVsyncPeriod /* ns */) { supported(__func__); - DrmMode const &mode = connector_->active_mode(); - if (mode.id() == 0) - return HWC2::Error::BadConfig; - - *outVsyncPeriod = static_cast<hwc2_vsync_period_t>(1E9 / mode.v_refresh()); - return HWC2::Error::None; + return GetDisplayAttribute(active_config_id_, HWC2_ATTRIBUTE_VSYNC_PERIOD, + (int32_t *)(outVsyncPeriod)); } HWC2::Error DrmHwcTwo::HwcDisplay::SetActiveConfigWithConstraints( @@ -1279,30 +1330,32 @@ void DrmHwcTwo::HandleInitialHotplugState(DrmDevice *drmDevice) { } } -void DrmHwcTwo::DrmHotplugHandler::HandleEvent(uint64_t timestamp_us) { - for (const auto &conn : drm_->connectors()) { - drmModeConnection old_state = conn->state(); - drmModeConnection cur_state = conn->UpdateModes() - ? DRM_MODE_UNKNOWNCONNECTION - : conn->state(); +void DrmHwcTwo::HandleHotplugUEvent() { + for (const auto &drm : resource_manager_.getDrmDevices()) { + for (const auto &conn : drm->connectors()) { + drmModeConnection old_state = conn->state(); + drmModeConnection cur_state = conn->UpdateModes() + ? DRM_MODE_UNKNOWNCONNECTION + : conn->state(); - if (cur_state == old_state) - continue; + if (cur_state == old_state) + continue; - ALOGI("%s event @%" PRIu64 " for connector %u on display %d", - cur_state == DRM_MODE_CONNECTED ? "Plug" : "Unplug", timestamp_us, - conn->id(), conn->display()); - - int display_id = conn->display(); - if (cur_state == DRM_MODE_CONNECTED) { - auto &display = hwc2_->displays_.at(display_id); - display.ChosePreferredConfig(); - } else { - auto &display = hwc2_->displays_.at(display_id); - display.ClearDisplay(); - } + ALOGI("%s event for connector %u on display %d", + cur_state == DRM_MODE_CONNECTED ? "Plug" : "Unplug", conn->id(), + conn->display()); + + int display_id = conn->display(); + if (cur_state == DRM_MODE_CONNECTED) { + auto &display = displays_.at(display_id); + display.ChosePreferredConfig(); + } else { + auto &display = displays_.at(display_id); + display.ClearDisplay(); + } - hwc2_->HandleDisplayHotplug(display_id, cur_state); + HandleDisplayHotplug(display_id, cur_state); + } } } diff --git a/DrmHwcTwo.h b/DrmHwcTwo.h index 0d213fd..7fd4fbd 100644 --- a/DrmHwcTwo.h +++ b/DrmHwcTwo.h @@ -149,7 +149,7 @@ class DrmHwcTwo : public hwc2_device_t { HwcDisplay(const HwcDisplay &) = delete; HWC2::Error Init(std::vector<DrmPlane *> *planes); - HWC2::Error CreateComposition(bool test); + HWC2::Error CreateComposition(AtomicCommitArgs &a_args); std::vector<DrmHwcTwo::HwcLayer *> GetOrderLayersByZPos(); void ClearDisplay(); @@ -160,7 +160,7 @@ class DrmHwcTwo : public hwc2_device_t { HWC2::Error AcceptDisplayChanges(); HWC2::Error CreateLayer(hwc2_layer_t *layer); HWC2::Error DestroyLayer(hwc2_layer_t layer); - HWC2::Error GetActiveConfig(hwc2_config_t *config); + HWC2::Error GetActiveConfig(hwc2_config_t *config) const; HWC2::Error GetChangedCompositionTypes(uint32_t *num_elements, hwc2_layer_t *layers, int32_t *types); @@ -250,6 +250,22 @@ class DrmHwcTwo : public hwc2_device_t { uint32_t frames_flattened_ = 0; }; + struct HwcDisplayConfig { + int id{}; + int group_id{}; + DrmMode mode; + bool disabled{}; + + bool IsInterlaced() { + return (mode.flags() & DRM_MODE_FLAG_INTERLACE) != 0; + } + }; + + std::map<int /*config_id*/, struct HwcDisplayConfig> hwc_configs_; + + int active_config_id_ = 0; + int preferred_config_id_ = 0; + const Backend *backend() const { return backend_.get(); } @@ -327,8 +343,6 @@ class DrmHwcTwo : public hwc2_device_t { std::atomic_int flattenning_state_{ClientFlattenningState::NotRequired}; VSyncWorker flattening_vsync_worker_; - void AddFenceToPresentFence(UniqueFd fd); - constexpr static size_t MATRIX_SIZE = 16; DrmHwcTwo *hwc2_; @@ -351,7 +365,6 @@ class DrmHwcTwo : public hwc2_device_t { uint32_t layer_idx_ = 0; std::map<hwc2_layer_t, HwcLayer> layers_; HwcLayer client_layer_; - UniqueFd present_fence_; int32_t color_mode_{}; std::array<float, MATRIX_SIZE> color_transform_matrix_{}; android_color_transform_t color_transform_hint_; @@ -362,18 +375,6 @@ class DrmHwcTwo : public hwc2_device_t { std::string DumpDelta(DrmHwcTwo::HwcDisplay::Stats delta); }; - class DrmHotplugHandler : public DrmEventHandler { - public: - DrmHotplugHandler(DrmHwcTwo *hwc2, DrmDevice *drm) - : hwc2_(hwc2), drm_(drm) { - } - void HandleEvent(uint64_t timestamp_us); - - private: - DrmHwcTwo *hwc2_; - DrmDevice *drm_; - }; - private: static DrmHwcTwo *toDrmHwcTwo(hwc2_device_t *dev) { return static_cast<DrmHwcTwo *>(dev); @@ -442,6 +443,8 @@ class DrmHwcTwo : public hwc2_device_t { void HandleDisplayHotplug(hwc2_display_t displayid, int state); void HandleInitialHotplugState(DrmDevice *drmDevice); + void HandleHotplugUEvent(); + ResourceManager resource_manager_; std::map<hwc2_display_t, HwcDisplay> displays_; diff --git a/backend/Backend.cpp b/backend/Backend.cpp index d7eb240..ce606dd 100644 --- a/backend/Backend.cpp +++ b/backend/Backend.cpp @@ -46,8 +46,10 @@ HWC2::Error Backend::ValidateDisplay(DrmHwcTwo::HwcDisplay *display, bool testing_needed = !(client_start == 0 && client_size == layers.size()); + AtomicCommitArgs a_args = {.test_only = true}; + if (testing_needed && - display->CreateComposition(true) != HWC2::Error::None) { + display->CreateComposition(a_args) != HWC2::Error::None) { ++display->total_stats().failed_kms_validate_; client_start = 0; client_size = layers.size(); @@ -70,7 +72,7 @@ std::tuple<int, size_t> Backend::GetClientLayers( int client_start = -1; size_t client_size = 0; - for (int z_order = 0; z_order < layers.size(); ++z_order) { + for (size_t z_order = 0; z_order < layers.size(); ++z_order) { if (IsClientLayer(display, layers[z_order])) { if (client_start < 0) client_start = (int)z_order; @@ -98,7 +100,7 @@ bool Backend::HardwareSupportsLayerType(HWC2::Composition comp_type) { uint32_t Backend::CalcPixOps(const std::vector<DrmHwcTwo::HwcLayer *> &layers, size_t first_z, size_t size) { uint32_t pixops = 0; - for (int z_order = 0; z_order < layers.size(); ++z_order) { + for (size_t z_order = 0; z_order < layers.size(); ++z_order) { if (z_order >= first_z && z_order < first_z + size) { hwc_rect_t df = layers[z_order]->display_frame(); pixops += (df.right - df.left) * (df.bottom - df.top); @@ -109,7 +111,7 @@ uint32_t Backend::CalcPixOps(const std::vector<DrmHwcTwo::HwcLayer *> &layers, void Backend::MarkValidated(std::vector<DrmHwcTwo::HwcLayer *> &layers, size_t client_first_z, size_t client_size) { - for (int z_order = 0; z_order < layers.size(); ++z_order) { + for (size_t z_order = 0; z_order < layers.size(); ++z_order) { if (z_order >= client_first_z && z_order < client_first_z + client_size) layers[z_order]->set_validated_type(HWC2::Composition::Client); else @@ -150,12 +152,12 @@ std::tuple<int, int> Backend::GetExtraClientRange( steps = 1 + layers.size() - extra_client; } - uint32_t gpu_pixops = INT_MAX; - for (int i = 0; i < steps; i++) { + uint32_t gpu_pixops = UINT32_MAX; + for (size_t i = 0; i < steps; i++) { uint32_t po = CalcPixOps(layers, start + i, client_size); if (po < gpu_pixops) { gpu_pixops = po; - client_start = start + i; + client_start = start + int(i); } } } diff --git a/bufferinfo/BufferInfoGetter.cpp b/bufferinfo/BufferInfoGetter.cpp index 7f7f8ae..c284365 100644 --- a/bufferinfo/BufferInfoGetter.cpp +++ b/bufferinfo/BufferInfoGetter.cpp @@ -32,17 +32,17 @@ namespace android { BufferInfoGetter *BufferInfoGetter::GetInstance() { static std::unique_ptr<BufferInfoGetter> inst; - if (inst == nullptr) { -#if PLATFORM_SDK_VERSION >= 30 + if (!inst) { +#if PLATFORM_SDK_VERSION >= 30 && defined(USE_IMAPPER4_METADATA_API) inst.reset(BufferInfoMapperMetadata::CreateInstance()); - if (inst == nullptr) { + if (!inst) { ALOGW( "Generic buffer getter is not available. Falling back to legacy..."); + } #endif + if (!inst) { inst = LegacyBufferInfoGetter::CreateInstance(); -#if PLATFORM_SDK_VERSION >= 30 } -#endif } return inst.get(); diff --git a/bufferinfo/BufferInfoGetter.h b/bufferinfo/BufferInfoGetter.h index 60ca985..7b088df 100644 --- a/bufferinfo/BufferInfoGetter.h +++ b/bufferinfo/BufferInfoGetter.h @@ -49,6 +49,10 @@ class LegacyBufferInfoGetter : public BufferInfoGetter { int Init(); + virtual int ValidateGralloc() { + return 0; + } + int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override = 0; static std::unique_ptr<LegacyBufferInfoGetter> CreateInstance(); @@ -65,9 +69,13 @@ class LegacyBufferInfoGetter : public BufferInfoGetter { LegacyBufferInfoGetter::CreateInstance() { \ auto instance = std::make_unique<getter_>(); \ if (instance) { \ - int ret = instance->Init(); \ - if (ret) { \ - ALOGE("Failed to initialize the " #getter_ " getter %d", ret); \ + int err = instance->Init(); \ + if (err) { \ + ALOGE("Failed to initialize the " #getter_ " getter %d", err); \ + instance.reset(); \ + } \ + err = instance->ValidateGralloc(); \ + if (err) { \ instance.reset(); \ } \ } \ diff --git a/bufferinfo/legacy/BufferInfoImagination.cpp b/bufferinfo/legacy/BufferInfoImagination.cpp index d646072..691dd14 100644 --- a/bufferinfo/legacy/BufferInfoImagination.cpp +++ b/bufferinfo/legacy/BufferInfoImagination.cpp @@ -20,6 +20,8 @@ #include <xf86drm.h> +#include <cerrno> + #include "img_gralloc1_public.h" #include "utils/log.h" diff --git a/bufferinfo/legacy/BufferInfoLibdrm.cpp b/bufferinfo/legacy/BufferInfoLibdrm.cpp index da89eb5..47481b2 100644 --- a/bufferinfo/legacy/BufferInfoLibdrm.cpp +++ b/bufferinfo/legacy/BufferInfoLibdrm.cpp @@ -23,6 +23,8 @@ #include <xf86drm.h> #include <xf86drmMode.h> +#include <mutex> + #include "utils/log.h" #include "utils/properties.h" @@ -64,15 +66,15 @@ static const struct DroidYuvFormat kDroidYuvFormats[] = { #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) -static int get_fourcc_yuv(uint32_t native, enum chroma_order chroma_order, - size_t chroma_step) { +static uint32_t 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 && droid_yuv_format.chroma_step == chroma_step) return droid_yuv_format.fourcc; - return -1; + return UINT32_MAX; } static bool is_yuv(uint32_t native) { @@ -129,7 +131,7 @@ bool BufferInfoLibdrm::GetYuvPlaneInfo(int num_fds, buffer_handle_t handle, /* .chroma_step is the byte distance between the same chroma channel * values of subsequent pixels, assumed to be the same for Cb and Cr. */ bo->format = get_fourcc_yuv(bo->hal_format, chroma_order, ycbcr.chroma_step); - if (bo->format == -1) { + if (bo->format == UINT32_MAX) { ALOGW( "unsupported YUV format, native = %x, chroma_order = %s, chroma_step = " "%d", @@ -202,4 +204,20 @@ int BufferInfoLibdrm::ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) { return 0; } +constexpr char gbm_gralloc_module_name[] = "GBM Memory Allocator"; +constexpr char drm_gralloc_module_name[] = "DRM Memory Allocator"; + +int BufferInfoLibdrm::ValidateGralloc() { + if (strcmp(gralloc_->common.name, drm_gralloc_module_name) != 0 && + strcmp(gralloc_->common.name, gbm_gralloc_module_name) != 0) { + ALOGE( + "Gralloc name isn't valid: Expected: \"%s\" or \"%s\", Actual: \"%s\"", + gbm_gralloc_module_name, drm_gralloc_module_name, + gralloc_->common.name); + return -EINVAL; + } + + return 0; +} + } // namespace android diff --git a/bufferinfo/legacy/BufferInfoLibdrm.h b/bufferinfo/legacy/BufferInfoLibdrm.h index 4d37d00..cad8add 100644 --- a/bufferinfo/legacy/BufferInfoLibdrm.h +++ b/bufferinfo/legacy/BufferInfoLibdrm.h @@ -27,6 +27,7 @@ class BufferInfoLibdrm : public LegacyBufferInfoGetter { public: using LegacyBufferInfoGetter::LegacyBufferInfoGetter; int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override; + int ValidateGralloc() override; private: bool GetYuvPlaneInfo(int num_fds, buffer_handle_t handle, hwc_drm_bo_t *bo); diff --git a/bufferinfo/legacy/BufferInfoMinigbm.cpp b/bufferinfo/legacy/BufferInfoMinigbm.cpp index d030dff..777c2b7 100644 --- a/bufferinfo/legacy/BufferInfoMinigbm.cpp +++ b/bufferinfo/legacy/BufferInfoMinigbm.cpp @@ -21,35 +21,102 @@ #include <xf86drm.h> #include <xf86drmMode.h> -#include "cros_gralloc_handle.h" -#include "utils/log.h" - -#define DRM_FORMAT_YVU420_ANDROID fourcc_code('9', '9', '9', '7') +#include <cerrno> +#include <cstring> +#include "utils/log.h" namespace android { LEGACY_BUFFER_INFO_GETTER(BufferInfoMinigbm); +constexpr int CROS_GRALLOC_DRM_GET_FORMAT = 1; +constexpr int CROS_GRALLOC_DRM_GET_DIMENSIONS = 2; +constexpr int CROS_GRALLOC_DRM_GET_BUFFER_INFO = 4; +constexpr int CROS_GRALLOC_DRM_GET_USAGE = 5; + +struct cros_gralloc0_buffer_info { + uint32_t drm_fourcc; + int num_fds; + int fds[4]; + uint64_t modifier; + int offset[4]; + int stride[4]; +}; + int BufferInfoMinigbm::ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) { - auto *gr_handle = (cros_gralloc_handle *)handle; - if (!gr_handle) + if (handle == nullptr) { + return -EINVAL; + } + + uint32_t width{}; + uint32_t height{}; + if (gralloc_->perform(gralloc_, CROS_GRALLOC_DRM_GET_DIMENSIONS, handle, + &width, &height) != 0) { + ALOGE( + "CROS_GRALLOC_DRM_GET_DIMENSIONS operation has failed. " + "Please ensure you are using the latest minigbm."); + return -EINVAL; + } + + int32_t droid_format{}; + if (gralloc_->perform(gralloc_, CROS_GRALLOC_DRM_GET_FORMAT, handle, + &droid_format) != 0) { + ALOGE( + "CROS_GRALLOC_DRM_GET_FORMAT operation has failed. " + "Please ensure you are using the latest minigbm."); + return -EINVAL; + } + + uint32_t usage{}; + if (gralloc_->perform(gralloc_, CROS_GRALLOC_DRM_GET_USAGE, handle, &usage) != + 0) { + ALOGE( + "CROS_GRALLOC_DRM_GET_USAGE operation has failed. " + "Please ensure you are using the latest minigbm."); return -EINVAL; + } + + struct cros_gralloc0_buffer_info info {}; + if (gralloc_->perform(gralloc_, CROS_GRALLOC_DRM_GET_BUFFER_INFO, handle, + &info) != 0) { + ALOGE( + "CROS_GRALLOC_DRM_GET_BUFFER_INFO operation has failed. " + "Please ensure you are using the latest minigbm."); + return -EINVAL; + } + + bo->width = width; + bo->height = height; + + bo->hal_format = droid_format; + + bo->format = info.drm_fourcc; + bo->usage = usage; - bo->width = gr_handle->width; - bo->height = gr_handle->height; - bo->hal_format = gr_handle->droid_format; + for (int i = 0; i < info.num_fds; i++) { + bo->modifiers[i] = info.modifier; + bo->prime_fds[i] = info.fds[i]; + bo->pitches[i] = info.stride[i]; + bo->offsets[i] = info.offset[i]; + } - bo->format = gr_handle->format; - if (bo->format == DRM_FORMAT_YVU420_ANDROID) - bo->format = DRM_FORMAT_YVU420; + return 0; +} - bo->usage = gr_handle->usage; +constexpr char cros_gralloc_module_name[] = "CrOS Gralloc"; - for (int i = 0; i < gr_handle->num_planes; i++) { - bo->modifiers[i] = gr_handle->format_modifier; - bo->prime_fds[i] = gr_handle->fds[i]; - bo->pitches[i] = gr_handle->strides[i]; - bo->offsets[i] = gr_handle->offsets[i]; +int BufferInfoMinigbm::ValidateGralloc() { + if (strcmp(gralloc_->common.name, cros_gralloc_module_name) != 0) { + ALOGE("Gralloc name isn't valid: Expected: \"%s\", Actual: \"%s\"", + cros_gralloc_module_name, gralloc_->common.name); + return -EINVAL; + } + + if (gralloc_->perform == nullptr) { + ALOGE( + "CrOS gralloc has no perform call implemented. Please upgrade your " + "minigbm."); + return -EINVAL; } return 0; diff --git a/bufferinfo/legacy/BufferInfoMinigbm.h b/bufferinfo/legacy/BufferInfoMinigbm.h index bff9d74..04cc2ae 100644 --- a/bufferinfo/legacy/BufferInfoMinigbm.h +++ b/bufferinfo/legacy/BufferInfoMinigbm.h @@ -27,6 +27,7 @@ class BufferInfoMinigbm : public LegacyBufferInfoGetter { public: using LegacyBufferInfoGetter::LegacyBufferInfoGetter; int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override; + int ValidateGralloc() override; }; } // namespace android diff --git a/compositor/DrmDisplayComposition.cpp b/compositor/DrmDisplayComposition.cpp index c0fbba0..cd95267 100644 --- a/compositor/DrmDisplayComposition.cpp +++ b/compositor/DrmDisplayComposition.cpp @@ -37,41 +37,11 @@ DrmDisplayComposition::DrmDisplayComposition(DrmCrtc *crtc, Planner *planner) planner_(planner) { } -bool DrmDisplayComposition::validate_composition_type(DrmCompositionType des) { - return type_ == DRM_COMPOSITION_TYPE_EMPTY || type_ == des; -} - -int DrmDisplayComposition::SetLayers(DrmHwcLayer *layers, size_t num_layers, - bool geometry_changed) { - if (!validate_composition_type(DRM_COMPOSITION_TYPE_FRAME)) - return -EINVAL; - - geometry_changed_ = geometry_changed; - +int DrmDisplayComposition::SetLayers(DrmHwcLayer *layers, size_t num_layers) { for (size_t layer_index = 0; layer_index < num_layers; layer_index++) { layers_.emplace_back(std::move(layers[layer_index])); } - type_ = DRM_COMPOSITION_TYPE_FRAME; - return 0; -} - -int DrmDisplayComposition::SetDpmsMode(uint32_t dpms_mode) { - if (!validate_composition_type(DRM_COMPOSITION_TYPE_DPMS)) - return -EINVAL; - dpms_mode_ = dpms_mode; - type_ = DRM_COMPOSITION_TYPE_DPMS; - return 0; -} - -int DrmDisplayComposition::SetDisplayMode(const DrmMode &display_mode) { - if (!validate_composition_type(DRM_COMPOSITION_TYPE_MODESET)) { - ALOGE("SetDisplayMode() Failed to validate composition type"); - return -EINVAL; - } - display_mode_ = display_mode; - dpms_mode_ = DRM_MODE_DPMS_ON; - type_ = DRM_COMPOSITION_TYPE_MODESET; return 0; } @@ -87,9 +57,6 @@ int DrmDisplayComposition::AddPlaneComposition(DrmCompositionPlane plane) { int DrmDisplayComposition::Plan(std::vector<DrmPlane *> *primary_planes, std::vector<DrmPlane *> *overlay_planes) { - if (type_ != DRM_COMPOSITION_TYPE_FRAME) - return 0; - std::map<size_t, DrmHwcLayer *> to_composite; for (size_t i = 0; i < layers_.size(); ++i) diff --git a/compositor/DrmDisplayComposition.h b/compositor/DrmDisplayComposition.h index bbac0af..f1958d7 100644 --- a/compositor/DrmDisplayComposition.h +++ b/compositor/DrmDisplayComposition.h @@ -32,13 +32,6 @@ namespace android { class Importer; class Planner; -enum DrmCompositionType { - DRM_COMPOSITION_TYPE_EMPTY, - DRM_COMPOSITION_TYPE_FRAME, - DRM_COMPOSITION_TYPE_DPMS, - DRM_COMPOSITION_TYPE_MODESET, -}; - class DrmCompositionPlane { public: enum class Type : int32_t { @@ -86,11 +79,9 @@ class DrmDisplayComposition { DrmDisplayComposition(DrmCrtc *crtc, Planner *planner); ~DrmDisplayComposition() = default; - int SetLayers(DrmHwcLayer *layers, size_t num_layers, bool geometry_changed); + int SetLayers(DrmHwcLayer *layers, size_t num_layers); int AddPlaneComposition(DrmCompositionPlane plane); int AddPlaneDisable(DrmPlane *plane); - int SetDpmsMode(uint32_t dpms_mode); - int SetDisplayMode(const DrmMode &display_mode); int Plan(std::vector<DrmPlane *> *primary_planes, std::vector<DrmPlane *> *overlay_planes); @@ -103,22 +94,6 @@ class DrmDisplayComposition { return composition_planes_; } - bool geometry_changed() const { - return geometry_changed_; - } - - DrmCompositionType type() const { - return type_; - } - - uint32_t dpms_mode() const { - return dpms_mode_; - } - - const DrmMode &display_mode() const { - return display_mode_; - } - DrmCrtc *crtc() const { return crtc_; } @@ -127,19 +102,10 @@ class DrmDisplayComposition { return planner_; } - UniqueFd out_fence_; - private: - bool validate_composition_type(DrmCompositionType desired); - DrmCrtc *crtc_ = NULL; Planner *planner_ = NULL; - DrmCompositionType type_ = DRM_COMPOSITION_TYPE_EMPTY; - uint32_t dpms_mode_ = DRM_MODE_DPMS_ON; - DrmMode display_mode_; - - bool geometry_changed_ = true; std::vector<DrmHwcLayer> layers_; std::vector<DrmCompositionPlane> composition_planes_; }; diff --git a/compositor/DrmDisplayCompositor.cpp b/compositor/DrmDisplayCompositor.cpp index 576c533..447d75e 100644 --- a/compositor/DrmDisplayCompositor.cpp +++ b/compositor/DrmDisplayCompositor.cpp @@ -40,21 +40,6 @@ namespace android { -DrmDisplayCompositor::DrmDisplayCompositor() - : resource_manager_(nullptr), - display_(-1), - initialized_(false), - active_(false), - use_hw_overlays_(true) { -} - -DrmDisplayCompositor::~DrmDisplayCompositor() { - if (!initialized_) - return; - - active_composition_.reset(); -} - auto DrmDisplayCompositor::Init(ResourceManager *resource_manager, int display) -> int { resource_manager_ = resource_manager; @@ -82,56 +67,30 @@ DrmDisplayCompositor::CreateInitializedComposition() const { return std::make_unique<DrmDisplayComposition>(crtc, planner_.get()); } -std::tuple<uint32_t, uint32_t, int> -DrmDisplayCompositor::GetActiveModeResolution() { - DrmDevice *drm = resource_manager_->GetDrmDevice(display_); - DrmConnector *connector = drm->GetConnectorForDisplay(display_); - if (connector == nullptr) { - ALOGE("Failed to determine display mode: no connector for display %d", - display_); - return std::make_tuple(0, 0, -ENODEV); - } - - const DrmMode &mode = connector->active_mode(); - return std::make_tuple(mode.h_display(), mode.v_display(), 0); -} +auto DrmDisplayCompositor::CommitFrame(AtomicCommitArgs &args) -> int { + ATRACE_CALL(); -int DrmDisplayCompositor::DisablePlanes(DrmDisplayComposition *display_comp) { - auto pset = MakeDrmModeAtomicReqUnique(); - if (!pset) { - ALOGE("Failed to allocate property set"); - return -ENOMEM; + if (args.active && *args.active == active_kms_data.active_state) { + /* Don't set the same state twice */ + args.active.reset(); } - int ret = 0; - std::vector<DrmCompositionPlane> &comp_planes = display_comp - ->composition_planes(); - for (DrmCompositionPlane &comp_plane : comp_planes) { - if (comp_plane.plane()->AtomicDisablePlane(*pset) != 0) { - return -EINVAL; - } - } - DrmDevice *drm = resource_manager_->GetDrmDevice(display_); - ret = drmModeAtomicCommit(drm->fd(), pset.get(), 0, drm); - if (ret) { - ALOGE("Failed to commit pset ret=%d\n", ret); - return ret; + if (!args.HasInputs()) { + /* nothing to do */ + return 0; } - return 0; -} - -int DrmDisplayCompositor::CommitFrame(DrmDisplayComposition *display_comp, - bool test_only) { - ATRACE_CALL(); + if (!active_kms_data.active_state) { + /* Force activate display */ + args.active = true; + } - int ret = 0; + if (args.clear_active_composition && args.composition) { + ALOGE("%s: Invalid arguments", __func__); + return -EINVAL; + } - std::vector<DrmHwcLayer> &layers = display_comp->layers(); - std::vector<DrmCompositionPlane> &comp_planes = display_comp - ->composition_planes(); DrmDevice *drm = resource_manager_->GetDrmDevice(display_); - uint64_t out_fences[drm->crtcs().size()]; DrmConnector *connector = drm->GetConnectorForDisplay(display_); if (!connector) { @@ -150,178 +109,133 @@ int DrmDisplayCompositor::CommitFrame(DrmDisplayComposition *display_comp, return -ENOMEM; } + int64_t out_fence = -1; if (crtc->out_fence_ptr_property() && - !crtc->out_fence_ptr_property() - .AtomicSet(*pset, (uint64_t)&out_fences[crtc->pipe()])) { + !crtc->out_fence_ptr_property().AtomicSet(*pset, (uint64_t)&out_fence)) { return -EINVAL; } - 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(); - - 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", - source_layers.size(), comp_plane.type()); - continue; - } - - 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()); - return -EINVAL; - } - DrmHwcLayer &layer = layers[source_layers.front()]; + DrmModeUserPropertyBlobUnique mode_blob; - if (plane->AtomicSetState(*pset, layer, source_layers.front(), - crtc->id()) != 0) { - return -EINVAL; - } - } else { - if (plane->AtomicDisablePlane(*pset) != 0) { - return -EINVAL; - } + if (args.active) { + if (!crtc->active_property().AtomicSet(*pset, *args.active) || + !connector->crtc_id_property().AtomicSet(*pset, crtc->id())) { + return -EINVAL; } } - if (!ret) { - uint32_t flags = DRM_MODE_ATOMIC_ALLOW_MODESET; - if (test_only) - flags |= DRM_MODE_ATOMIC_TEST_ONLY; + if (args.display_mode) { + mode_blob = args.display_mode.value().CreateModeBlob( + *resource_manager_->GetDrmDevice(display_)); - ret = drmModeAtomicCommit(drm->fd(), pset.get(), flags, drm); - if (ret) { - if (!test_only) - ALOGE("Failed to commit pset ret=%d\n", ret); - return ret; + if (!mode_blob) { + ALOGE("Failed to create mode_blob"); + return -EINVAL; } - } - if (!test_only && mode_.blob) { - /* TODO: Add dpms to the pset when the kernel supports it */ - ret = ApplyDpms(display_comp); - if (ret) { - ALOGE("Failed to apply DPMS after modeset %d\n", ret); - return ret; + if (!crtc->mode_property().AtomicSet(*pset, *mode_blob)) { + return -EINVAL; } - - connector->set_active_mode(mode_.mode); - mode_.old_blob = std::move(mode_.blob); } - if (crtc->out_fence_ptr_property()) { - display_comp->out_fence_ = UniqueFd((int)out_fences[crtc->pipe()]); - } + if (args.composition) { + std::vector<DrmHwcLayer> &layers = args.composition->layers(); + std::vector<DrmCompositionPlane> &comp_planes = args.composition + ->composition_planes(); - return ret; -} + for (DrmCompositionPlane &comp_plane : comp_planes) { + DrmPlane *plane = comp_plane.plane(); + std::vector<size_t> &source_layers = comp_plane.source_layers(); -int DrmDisplayCompositor::ApplyDpms(DrmDisplayComposition *display_comp) { - DrmDevice *drm = resource_manager_->GetDrmDevice(display_); - DrmConnector *conn = drm->GetConnectorForDisplay(display_); - if (!conn) { - ALOGE("Failed to get DrmConnector for display %d", display_); - return -ENODEV; + 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", + source_layers.size(), comp_plane.type()); + continue; + } + + 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()); + return -EINVAL; + } + DrmHwcLayer &layer = layers[source_layers.front()]; + + if (plane->AtomicSetState(*pset, layer, source_layers.front(), + crtc->id()) != 0) { + return -EINVAL; + } + } else { + if (plane->AtomicDisablePlane(*pset) != 0) { + return -EINVAL; + } + } + } } - const DrmProperty &prop = conn->dpms_property(); - int ret = drmModeConnectorSetProperty(drm->fd(), conn->id(), prop.id(), - display_comp->dpms_mode()); - if (ret) { - ALOGE("Failed to set DPMS property for connector %d", conn->id()); - return ret; + if (args.clear_active_composition && active_kms_data.composition) { + auto &comp_planes = active_kms_data.composition->composition_planes(); + for (auto &comp_plane : comp_planes) { + if (comp_plane.plane()->AtomicDisablePlane(*pset) != 0) { + return -EINVAL; + } + } } - return 0; -} -auto DrmDisplayCompositor::CreateModeBlob(const DrmMode &mode) - -> DrmModeUserPropertyBlobUnique { - struct drm_mode_modeinfo drm_mode {}; - mode.ToDrmModeModeInfo(&drm_mode); + uint32_t flags = DRM_MODE_ATOMIC_ALLOW_MODESET; + if (args.test_only) + flags |= DRM_MODE_ATOMIC_TEST_ONLY; - DrmDevice *drm = resource_manager_->GetDrmDevice(display_); - return drm->RegisterUserPropertyBlob(&drm_mode, - sizeof(struct drm_mode_modeinfo)); -} - -void DrmDisplayCompositor::ClearDisplay() { - if (!active_composition_) - return; + int err = drmModeAtomicCommit(drm->fd(), pset.get(), flags, drm); + if (err) { + if (!args.test_only) + ALOGE("Failed to commit pset ret=%d\n", err); + return err; + } - if (DisablePlanes(active_composition_.get())) - return; + if (!args.test_only) { + if (args.display_mode) { + connector->set_active_mode(*args.display_mode); + active_kms_data.mode_blob = std::move(mode_blob); + } - active_composition_.reset(nullptr); -} + if (args.clear_active_composition) { + active_kms_data.composition.reset(); + } -void DrmDisplayCompositor::ApplyFrame( - std::unique_ptr<DrmDisplayComposition> composition, int status) { - int ret = status; + if (args.composition) { + active_kms_data.composition = args.composition; + } - if (!ret) { - ret = CommitFrame(composition.get(), false); - } + if (args.active) { + active_kms_data.active_state = *args.active; + } - if (ret) { - ALOGE("Composite failed for display %d", display_); - // Disable the hw used by the last active composition. This allows us to - // signal the release fences from that composition to avoid hanging. - ClearDisplay(); - return; + if (crtc->out_fence_ptr_property()) { + args.out_fence = UniqueFd((int)out_fence); + } } - active_composition_.swap(composition); + return 0; } -int DrmDisplayCompositor::ApplyComposition( - std::unique_ptr<DrmDisplayComposition> composition) { - int ret = 0; - switch (composition->type()) { - case DRM_COMPOSITION_TYPE_FRAME: - if (composition->geometry_changed()) { - // Send the composition to the kernel to ensure we can commit it. This - // is just a test, it won't actually commit the frame. - ret = CommitFrame(composition.get(), true); - if (ret) { - ALOGE("Commit test failed for display %d, FIXME", display_); - return ret; - } +auto DrmDisplayCompositor::ExecuteAtomicCommit(AtomicCommitArgs &args) -> int { + int err = CommitFrame(args); + + if (!args.test_only) { + if (err) { + ALOGE("Composite failed for display %d", display_); + // Disable the hw used by the last active composition. This allows us to + // signal the release fences from that composition to avoid hanging. + AtomicCommitArgs cl_args = {.clear_active_composition = true}; + if (CommitFrame(cl_args)) { + ALOGE("Failed to clean-up active composition for display %d", display_); } - - ApplyFrame(std::move(composition), ret); - break; - case DRM_COMPOSITION_TYPE_DPMS: - active_ = (composition->dpms_mode() == DRM_MODE_DPMS_ON); - ret = ApplyDpms(composition.get()); - if (ret) - ALOGE("Failed to apply dpms for display %d", display_); - return ret; - case DRM_COMPOSITION_TYPE_MODESET: - mode_.mode = composition->display_mode(); - mode_.blob = CreateModeBlob(mode_.mode); - if (!mode_.blob) { - ALOGE("Failed to create mode blob for display %d", display_); - return -EINVAL; - } - return 0; - default: - ALOGE("Unknown composition type %d", composition->type()); - return -EINVAL; + return err; + } } - return ret; -} - -int DrmDisplayCompositor::TestComposition(DrmDisplayComposition *composition) { - return CommitFrame(composition, true); -} + return err; +} // namespace android } // namespace android diff --git a/compositor/DrmDisplayCompositor.h b/compositor/DrmDisplayCompositor.h index 3227e12..55fe77d 100644 --- a/compositor/DrmDisplayCompositor.h +++ b/compositor/DrmDisplayCompositor.h @@ -34,57 +34,49 @@ namespace android { +struct AtomicCommitArgs { + /* inputs. All fields are optional, but at least one has to be specified */ + bool test_only = false; + std::optional<DrmMode> display_mode; + std::optional<bool> active; + std::shared_ptr<DrmDisplayComposition> composition; + /* 'clear' should never be used together with 'composition' */ + bool clear_active_composition = false; + + /* out */ + UniqueFd out_fence; + + /* helpers */ + auto HasInputs() -> bool { + return display_mode || active || composition || clear_active_composition; + } +}; + class DrmDisplayCompositor { public: - DrmDisplayCompositor(); - ~DrmDisplayCompositor(); - + DrmDisplayCompositor() = default; + ~DrmDisplayCompositor() = default; 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 ClearDisplay(); - UniqueFd TakeOutFence() { - if (!active_composition_) { - return UniqueFd(); - } - return std::move(active_composition_->out_fence_); - } - std::tuple<uint32_t, uint32_t, int> GetActiveModeResolution(); + auto ExecuteAtomicCommit(AtomicCommitArgs &args) -> int; private: - struct ModeState { - DrmMode mode; - DrmModeUserPropertyBlobUnique blob; - DrmModeUserPropertyBlobUnique old_blob; - }; - DrmDisplayCompositor(const DrmDisplayCompositor &) = delete; - int CommitFrame(DrmDisplayComposition *display_comp, bool test_only); - int ApplyDpms(DrmDisplayComposition *display_comp); - int DisablePlanes(DrmDisplayComposition *display_comp); - - void ApplyFrame(std::unique_ptr<DrmDisplayComposition> composition, - int status); - - auto CreateModeBlob(const DrmMode &mode) -> DrmModeUserPropertyBlobUnique; - - ResourceManager *resource_manager_; - int display_; - - std::unique_ptr<DrmDisplayComposition> active_composition_; - - bool initialized_; - bool active_; - bool use_hw_overlays_; + auto CommitFrame(AtomicCommitArgs &args) -> int; - ModeState mode_; + struct { + std::shared_ptr<DrmDisplayComposition> composition; + DrmModeUserPropertyBlobUnique mode_blob; + bool active_state{}; + } active_kms_data; + ResourceManager *resource_manager_ = nullptr; std::unique_ptr<Planner> planner_; + bool initialized_{}; + int display_ = -1; }; } // namespace android diff --git a/drm/DrmConnector.cpp b/drm/DrmConnector.cpp index b3179c7..5b3c697 100644 --- a/drm/DrmConnector.cpp +++ b/drm/DrmConnector.cpp @@ -159,43 +159,27 @@ std::string DrmConnector::name() const { } int DrmConnector::UpdateModes() { - int fd = drm_->fd(); - - drmModeConnectorPtr c = drmModeGetConnector(fd, id_); + drmModeConnectorPtr c = drmModeGetConnector(drm_->fd(), id_); if (!c) { ALOGE("Failed to get connector %d", id_); return -ENODEV; } - state_ = c->connection; - - bool preferred_mode_found = false; - std::vector<DrmMode> new_modes; + modes_.clear(); for (int i = 0; i < c->count_modes; ++i) { bool exists = false; for (const DrmMode &mode : modes_) { if (mode == c->modes[i]) { - new_modes.push_back(mode); exists = true; break; } } + if (!exists) { - DrmMode m(&c->modes[i]); - m.set_id(drm_->next_mode_id()); - new_modes.push_back(m); + modes_.emplace_back(DrmMode(&c->modes[i])); } - // Use only the first DRM_MODE_TYPE_PREFERRED mode found - if (!preferred_mode_found && - (new_modes.back().type() & DRM_MODE_TYPE_PREFERRED)) { - preferred_mode_id_ = new_modes.back().id(); - preferred_mode_found = true; - } - } - modes_.swap(new_modes); - if (!preferred_mode_found && !modes_.empty()) { - preferred_mode_id_ = modes_[0].id(); } + return 0; } diff --git a/drm/DrmConnector.h b/drm/DrmConnector.h index e2789ea..f2305aa 100644 --- a/drm/DrmConnector.h +++ b/drm/DrmConnector.h @@ -82,10 +82,6 @@ class DrmConnector { uint32_t mm_width() const; uint32_t mm_height() const; - uint32_t get_preferred_mode_id() const { - return preferred_mode_id_; - } - private: DrmDevice *drm_; @@ -111,8 +107,6 @@ class DrmConnector { DrmProperty writeback_out_fence_; std::vector<DrmEncoder *> possible_encoders_; - - uint32_t preferred_mode_id_{}; }; } // namespace android diff --git a/drm/DrmDevice.cpp b/drm/DrmDevice.cpp index 1753ddc..0f5f581 100644 --- a/drm/DrmDevice.cpp +++ b/drm/DrmDevice.cpp @@ -111,15 +111,11 @@ static std::vector<DrmConnector *> make_primary_display_candidates( return primary_candidates; } -DrmDevice::DrmDevice() : event_listener_(this) { +DrmDevice::DrmDevice() { self.reset(this); mDrmFbImporter = std::make_unique<DrmFbImporter>(self); } -DrmDevice::~DrmDevice() { - event_listener_.Exit(); -} - std::tuple<int, int> DrmDevice::Init(const char *path, int num_displays) { /* TODO: Use drmOpenControl here instead */ fd_ = UniqueFd(open(path, O_RDWR | O_CLOEXEC)); @@ -326,12 +322,6 @@ std::tuple<int, int> DrmDevice::Init(const char *path, int num_displays) { if (ret) return std::make_tuple(ret, 0); - ret = event_listener_.Init(); - if (ret) { - ALOGE("Can't initialize event listener %d", ret); - return std::make_tuple(ret, 0); - } - for (auto &conn : connectors_) { ret = CreateDisplayPipe(conn.get()); if (ret) { @@ -526,10 +516,6 @@ auto DrmDevice::RegisterUserPropertyBlob(void *data, size_t length) const }); } -DrmEventListener *DrmDevice::event_listener() { - return &event_listener_; -} - int DrmDevice::GetProperty(uint32_t obj_id, uint32_t obj_type, const char *prop_name, DrmProperty *property) const { drmModeObjectPropertiesPtr props = nullptr; diff --git a/drm/DrmDevice.h b/drm/DrmDevice.h index 81c60cd..c08c766 100644 --- a/drm/DrmDevice.h +++ b/drm/DrmDevice.h @@ -25,7 +25,6 @@ #include "DrmConnector.h" #include "DrmCrtc.h" #include "DrmEncoder.h" -#include "DrmEventListener.h" #include "DrmFbImporter.h" #include "DrmPlane.h" #include "utils/UniqueFd.h" @@ -38,7 +37,7 @@ class DrmPlane; class DrmDevice { public: DrmDevice(); - ~DrmDevice(); + ~DrmDevice() = default; std::tuple<int, int> Init(const char *path, int num_displays); @@ -67,7 +66,6 @@ class DrmDevice { DrmConnector *AvailableWritebackConnector(int display) const; DrmCrtc *GetCrtcForDisplay(int display) const; DrmPlane *GetPlane(uint32_t id) const; - DrmEventListener *event_listener(); int GetCrtcProperty(const DrmCrtc &crtc, const char *prop_name, DrmProperty *property) const; @@ -83,9 +81,6 @@ class DrmDevice { -> DrmModeUserPropertyBlobUnique; bool HandlesDisplay(int display) const; - void RegisterHotplugHandler(DrmEventHandler *handler) { - event_listener_.RegisterHotplugHandler(handler); - } bool HasAddFb2ModifiersSupport() const { return HasAddFb2ModifiersSupport_; @@ -114,7 +109,6 @@ class DrmDevice { std::vector<std::unique_ptr<DrmEncoder>> encoders_; std::vector<std::unique_ptr<DrmCrtc>> crtcs_; std::vector<std::unique_ptr<DrmPlane>> planes_; - DrmEventListener event_listener_; std::pair<uint32_t, uint32_t> min_resolution_; std::pair<uint32_t, uint32_t> max_resolution_; diff --git a/drm/DrmFbImporter.cpp b/drm/DrmFbImporter.cpp index 8440093..25f32b7 100644 --- a/drm/DrmFbImporter.cpp +++ b/drm/DrmFbImporter.cpp @@ -41,7 +41,7 @@ auto DrmFbIdHandle::CreateInstance(hwc_drm_bo_t *bo, GemHandle first_gem_handle, int32_t err = 0; /* Framebuffer object creation require gem handle for every used plane */ - for (int i = 1; i < local->gem_handles_.size(); i++) { + for (size_t i = 1; i < local->gem_handles_.size(); i++) { if (bo->prime_fds[i] > 0) { if (bo->prime_fds[i] != bo->prime_fds[0]) { err = drmPrimeFDToHandle(drm->fd(), bo->prime_fds[i], @@ -101,7 +101,7 @@ DrmFbIdHandle::~DrmFbIdHandle() { * request via system properties) */ struct drm_gem_close gem_close {}; - for (int i = 0; i < gem_handles_.size(); i++) { + for (size_t i = 0; i < gem_handles_.size(); i++) { /* Don't close invalid handle. Close handle only once in cases * where several YUV planes located in the single buffer. */ if (gem_handles_[i] == 0 || diff --git a/drm/DrmMode.cpp b/drm/DrmMode.cpp index c714458..1c8bd0f 100644 --- a/drm/DrmMode.cpp +++ b/drm/DrmMode.cpp @@ -49,73 +49,47 @@ bool DrmMode::operator==(const drmModeModeInfo &m) const { v_scan_ == m.vscan && flags_ == m.flags && type_ == m.type; } -void DrmMode::ToDrmModeModeInfo(drm_mode_modeinfo *m) const { - m->clock = clock_; - m->hdisplay = h_display_; - m->hsync_start = h_sync_start_; - m->hsync_end = h_sync_end_; - m->htotal = h_total_; - m->hskew = h_skew_; - m->vdisplay = v_display_; - m->vsync_start = v_sync_start_; - m->vsync_end = v_sync_end_; - m->vtotal = v_total_; - m->vscan = v_scan_; - m->vrefresh = v_refresh_; - m->flags = flags_; - m->type = type_; - strncpy(m->name, name_.c_str(), DRM_DISPLAY_MODE_LEN); -} - -uint32_t DrmMode::id() const { - return id_; -} - -void DrmMode::set_id(uint32_t id) { - id_ = id; -} - uint32_t DrmMode::clock() const { return clock_; } -uint32_t DrmMode::h_display() const { +uint16_t DrmMode::h_display() const { return h_display_; } -uint32_t DrmMode::h_sync_start() const { +uint16_t DrmMode::h_sync_start() const { return h_sync_start_; } -uint32_t DrmMode::h_sync_end() const { +uint16_t DrmMode::h_sync_end() const { return h_sync_end_; } -uint32_t DrmMode::h_total() const { +uint16_t DrmMode::h_total() const { return h_total_; } -uint32_t DrmMode::h_skew() const { +uint16_t DrmMode::h_skew() const { return h_skew_; } -uint32_t DrmMode::v_display() const { +uint16_t DrmMode::v_display() const { return v_display_; } -uint32_t DrmMode::v_sync_start() const { +uint16_t DrmMode::v_sync_start() const { return v_sync_start_; } -uint32_t DrmMode::v_sync_end() const { +uint16_t DrmMode::v_sync_end() const { return v_sync_end_; } -uint32_t DrmMode::v_total() const { +uint16_t DrmMode::v_total() const { return v_total_; } -uint32_t DrmMode::v_scan() const { +uint16_t DrmMode::v_scan() const { return v_scan_; } @@ -133,6 +107,31 @@ uint32_t DrmMode::type() const { } std::string DrmMode::name() const { - return name_; + return name_ + "@" + std::to_string(v_refresh()); +} + +auto DrmMode::CreateModeBlob(const DrmDevice &drm) + -> DrmModeUserPropertyBlobUnique { + struct drm_mode_modeinfo drm_mode = { + .clock = clock_, + .hdisplay = h_display_, + .hsync_start = h_sync_start_, + .hsync_end = h_sync_end_, + .htotal = h_total_, + .hskew = h_skew_, + .vdisplay = v_display_, + .vsync_start = v_sync_start_, + .vsync_end = v_sync_end_, + .vtotal = v_total_, + .vscan = v_scan_, + .vrefresh = v_refresh_, + .flags = flags_, + .type = type_, + }; + strncpy(drm_mode.name, name_.c_str(), DRM_DISPLAY_MODE_LEN); + + return drm.RegisterUserPropertyBlob(&drm_mode, + sizeof(struct drm_mode_modeinfo)); } + } // namespace android diff --git a/drm/DrmMode.h b/drm/DrmMode.h index 313a8ea..41b9e15 100644 --- a/drm/DrmMode.h +++ b/drm/DrmMode.h @@ -17,37 +17,38 @@ #ifndef ANDROID_DRM_MODE_H_ #define ANDROID_DRM_MODE_H_ -#include <stdint.h> +#include <stdio.h> #include <xf86drmMode.h> +#include <cstdint> #include <string> +#include "DrmUnique.h" + namespace android { +class DrmDevice; + class DrmMode { public: DrmMode() = default; DrmMode(drmModeModeInfoPtr m); bool operator==(const drmModeModeInfo &m) const; - void ToDrmModeModeInfo(drm_mode_modeinfo *m) const; - - uint32_t id() const; - void set_id(uint32_t id); uint32_t clock() const; - uint32_t h_display() const; - uint32_t h_sync_start() const; - uint32_t h_sync_end() const; - uint32_t h_total() const; - uint32_t h_skew() const; - - uint32_t v_display() const; - uint32_t v_sync_start() const; - uint32_t v_sync_end() const; - uint32_t v_total() const; - uint32_t v_scan() const; + uint16_t h_display() const; + uint16_t h_sync_start() const; + uint16_t h_sync_end() const; + uint16_t h_total() const; + uint16_t h_skew() const; + + uint16_t v_display() const; + uint16_t v_sync_start() const; + uint16_t v_sync_end() const; + uint16_t v_total() const; + uint16_t v_scan() const; float v_refresh() const; uint32_t flags() const; @@ -55,23 +56,23 @@ class DrmMode { std::string name() const; - private: - uint32_t id_ = 0; + auto CreateModeBlob(const DrmDevice &drm) -> DrmModeUserPropertyBlobUnique; + private: uint32_t clock_ = 0; - uint32_t h_display_ = 0; - uint32_t h_sync_start_ = 0; - uint32_t h_sync_end_ = 0; - uint32_t h_total_ = 0; - uint32_t h_skew_ = 0; - - uint32_t v_display_ = 0; - uint32_t v_sync_start_ = 0; - uint32_t v_sync_end_ = 0; - uint32_t v_total_ = 0; - uint32_t v_scan_ = 0; - uint32_t v_refresh_ = 0; + uint16_t h_display_ = 0; + uint16_t h_sync_start_ = 0; + uint16_t h_sync_end_ = 0; + uint16_t h_total_ = 0; + uint16_t h_skew_ = 0; + + uint16_t v_display_ = 0; + uint16_t v_sync_start_ = 0; + uint16_t v_sync_end_ = 0; + uint16_t v_total_ = 0; + uint16_t v_scan_ = 0; + uint16_t v_refresh_ = 0; uint32_t flags_ = 0; uint32_t type_ = 0; diff --git a/drm/ResourceManager.cpp b/drm/ResourceManager.cpp index c55d6b8..8baa4cb 100644 --- a/drm/ResourceManager.cpp +++ b/drm/ResourceManager.cpp @@ -70,6 +70,12 @@ int ResourceManager::Init() { return -EINVAL; } + ret = uevent_listener_.Init(); + if (ret) { + ALOGE("Can't initialize event listener %d", ret); + return ret; + } + return 0; } diff --git a/drm/ResourceManager.h b/drm/ResourceManager.h index d9e0712..5ffe92c 100644 --- a/drm/ResourceManager.h +++ b/drm/ResourceManager.h @@ -20,6 +20,7 @@ #include <string.h> #include "DrmDevice.h" +#include "UEventListener.h" #include "DrmFbImporter.h" namespace android { @@ -29,6 +30,10 @@ class ResourceManager { ResourceManager(); ResourceManager(const ResourceManager &) = delete; ResourceManager &operator=(const ResourceManager &) = delete; + ~ResourceManager() { + uevent_listener_.Exit(); + } + int Init(); DrmDevice *GetDrmDevice(int display); const std::vector<std::unique_ptr<DrmDevice>> &getDrmDevices() const { @@ -41,6 +46,10 @@ class ResourceManager { return scale_with_gpu_; } + UEventListener *GetUEventListener() { + return &uevent_listener_; + } + private: int AddDrmDevice(std::string const &path); @@ -48,6 +57,8 @@ class ResourceManager { std::vector<std::unique_ptr<DrmDevice>> drms_; bool scale_with_gpu_{}; + + UEventListener uevent_listener_; }; } // namespace android diff --git a/drm/DrmEventListener.cpp b/drm/UEventListener.cpp index 53e7032..eae0608 100644 --- a/drm/DrmEventListener.cpp +++ b/drm/UEventListener.cpp @@ -14,9 +14,9 @@ * limitations under the License. */ -#define LOG_TAG "hwc-drm-event-listener" +#define LOG_TAG "hwc-uevent-listener" -#include "DrmEventListener.h" +#include "UEventListener.h" #include <linux/netlink.h> #include <sys/socket.h> @@ -26,7 +26,6 @@ #include <cerrno> #include <cstring> -#include "DrmDevice.h" #include "utils/log.h" /* Originally defined in system/core/libsystem/include/system/graphics.h */ @@ -34,11 +33,10 @@ namespace android { -DrmEventListener::DrmEventListener(DrmDevice *drm) - : Worker("drm-event-listener", HAL_PRIORITY_URGENT_DISPLAY), drm_(drm) { -} +UEventListener::UEventListener() + : Worker("uevent-listener", HAL_PRIORITY_URGENT_DISPLAY){}; -int DrmEventListener::Init() { +int UEventListener::Init() { uevent_fd_ = UniqueFd( socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT)); if (!uevent_fd_) { @@ -57,44 +55,13 @@ int DrmEventListener::Init() { return -errno; } - // NOLINTNEXTLINE(readability-isolate-declaration) - FD_ZERO(&fds_); - FD_SET(drm_->fd(), &fds_); - FD_SET(uevent_fd_.Get(), &fds_); - max_fd_ = std::max(drm_->fd(), uevent_fd_.Get()); - return InitWorker(); } -void DrmEventListener::RegisterHotplugHandler(DrmEventHandler *handler) { - assert(!hotplug_handler_); - hotplug_handler_.reset(handler); -} - -void DrmEventListener::FlipHandler(int /* fd */, unsigned int /* sequence */, - unsigned int tv_sec, unsigned int tv_usec, - void *user_data) { - auto *handler = (DrmEventHandler *)user_data; - if (!handler) - return; - - handler->HandleEvent((uint64_t)tv_sec * 1000 * 1000 + tv_usec); - delete handler; // NOLINT(cppcoreguidelines-owning-memory) -} - -void DrmEventListener::UEventHandler() { +void UEventListener::Routine() { char buffer[1024]; ssize_t ret = 0; - struct timespec ts {}; - - uint64_t timestamp = 0; - ret = clock_gettime(CLOCK_MONOTONIC, &ts); - if (!ret) - timestamp = ts.tv_sec * 1000 * 1000 * 1000 + ts.tv_nsec; - else - ALOGE("Failed to get monotonic clock on hotplug %zd", ret); - while (true) { ret = read(uevent_fd_.Get(), &buffer, sizeof(buffer)); if (ret == 0) @@ -120,26 +87,9 @@ void DrmEventListener::UEventHandler() { i += strlen(event) + 1; } - if (drm_event && hotplug_event) - hotplug_handler_->HandleEvent(timestamp); - } -} - -void DrmEventListener::Routine() { - int ret = 0; - do { - ret = select(max_fd_ + 1, &fds_, nullptr, nullptr, nullptr); - } while (ret == -1 && errno == EINTR); - - if (FD_ISSET(drm_->fd(), &fds_)) { - drmEventContext event_context = - {.version = 2, - .vblank_handler = nullptr, - .page_flip_handler = DrmEventListener::FlipHandler}; - drmHandleEvent(drm_->fd(), &event_context); + if (drm_event && hotplug_event && hotplug_handler_) { + hotplug_handler_(); + } } - - if (FD_ISSET(uevent_fd_.Get(), &fds_)) - UEventHandler(); } } // namespace android diff --git a/drm/DrmEventListener.h b/drm/UEventListener.h index f1f7310..048eb40 100644 --- a/drm/DrmEventListener.h +++ b/drm/UEventListener.h @@ -14,51 +14,34 @@ * limitations under the License. */ -#ifndef ANDROID_DRM_EVENT_LISTENER_H_ -#define ANDROID_DRM_EVENT_LISTENER_H_ +#ifndef ANDROID_UEVENT_LISTENER_H_ +#define ANDROID_UEVENT_LISTENER_H_ + +#include <functional> #include "utils/UniqueFd.h" #include "utils/Worker.h" namespace android { -class DrmDevice; - -class DrmEventHandler { - public: - DrmEventHandler() { - } - virtual ~DrmEventHandler() { - } - - virtual void HandleEvent(uint64_t timestamp_us) = 0; -}; - -class DrmEventListener : public Worker { +class UEventListener : public Worker { public: - DrmEventListener(DrmDevice *drm); - virtual ~DrmEventListener() { - } + UEventListener(); + virtual ~UEventListener() = default; int Init(); - void RegisterHotplugHandler(DrmEventHandler *handler); - - static void FlipHandler(int fd, unsigned int sequence, unsigned int tv_sec, - unsigned int tv_usec, void *user_data); + void RegisterHotplugHandler(std::function<void()> hotplug_handler) { + hotplug_handler_ = hotplug_handler; + } protected: virtual void Routine(); private: - void UEventHandler(); - - fd_set fds_{}; UniqueFd uevent_fd_; - int max_fd_ = -1; - DrmDevice *drm_; - std::unique_ptr<DrmEventHandler> hotplug_handler_; + std::function<void()> hotplug_handler_; }; } // namespace android diff --git a/tests/Android.bp b/tests/Android.bp index 473c944..20b87a8 100644 --- a/tests/Android.bp +++ b/tests/Android.bp @@ -1,9 +1,9 @@ cc_library_shared { name: "hwcomposer.filegroups_build_test", defaults: ["hwcomposer.drm_defaults"], - whole_static_libs: ["drm_hwcomposer"], srcs: [ + ":drm_hwcomposer_common", ":drm_hwcomposer_platformhisi", ":drm_hwcomposer_platformimagination", ":drm_hwcomposer_platformmediatek", diff --git a/tests/test_include/cros_gralloc_handle.h b/tests/test_include/cros_gralloc_handle.h deleted file mode 100644 index d77d777..0000000 --- a/tests/test_include/cros_gralloc_handle.h +++ /dev/null @@ -1,53 +0,0 @@ -// clang-format off -/* - * Copyright 2016 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef CROS_GRALLOC_HANDLE_H -#define CROS_GRALLOC_HANDLE_H - -#include <cstdint> -#include <cutils/native_handle.h> - -#define DRV_MAX_PLANES 4 -#define DRV_MAX_FDS (DRV_MAX_PLANES + 1) - -struct cros_gralloc_handle : public native_handle_t { - /* - * File descriptors must immediately follow the native_handle_t base and used file - * descriptors must be packed at the beginning of this array to work with - * native_handle_clone(). - * - * This field contains 'num_planes' plane file descriptors followed by an optional metadata - * reserved region file descriptor if 'reserved_region_size' is greater than zero. - */ - int32_t fds[DRV_MAX_FDS]; - uint32_t strides[DRV_MAX_PLANES]; - uint32_t offsets[DRV_MAX_PLANES]; - uint32_t sizes[DRV_MAX_PLANES]; - uint32_t id; - uint32_t width; - uint32_t height; - uint32_t format; /* DRM format */ - uint32_t tiling; - uint64_t format_modifier; - uint64_t use_flags; /* Buffer creation flags */ - uint32_t magic; - uint32_t pixel_stride; - int32_t droid_format; - int32_t usage; /* Android usage. */ - uint32_t num_planes; - uint64_t reserved_region_size; - uint64_t total_size; /* Total allocation size */ - /* - * Name is a null terminated char array located at handle->base.data[handle->name_offset]. - */ - uint32_t name_offset; -} __attribute__((packed)); - -typedef const struct cros_gralloc_handle *cros_gralloc_handle_t; - -#endif -// clang-format on |