diff options
Diffstat (limited to 'hwc2_device')
-rw-r--r-- | hwc2_device/DrmHwcTwo.cpp | 220 | ||||
-rw-r--r-- | hwc2_device/DrmHwcTwo.h | 49 | ||||
-rw-r--r-- | hwc2_device/HwcDisplay.cpp | 361 | ||||
-rw-r--r-- | hwc2_device/HwcDisplay.h | 95 | ||||
-rw-r--r-- | hwc2_device/HwcDisplayConfigs.cpp | 38 | ||||
-rw-r--r-- | hwc2_device/HwcDisplayConfigs.h | 14 | ||||
-rw-r--r-- | hwc2_device/hwc2_device.cpp | 14 |
7 files changed, 448 insertions, 343 deletions
diff --git a/hwc2_device/DrmHwcTwo.cpp b/hwc2_device/DrmHwcTwo.cpp index a2a093f..e689419 100644 --- a/hwc2_device/DrmHwcTwo.cpp +++ b/hwc2_device/DrmHwcTwo.cpp @@ -18,61 +18,117 @@ #include "DrmHwcTwo.h" +#include <cinttypes> + #include "backend/Backend.h" #include "utils/log.h" namespace android { -DrmHwcTwo::DrmHwcTwo() = default; +DrmHwcTwo::DrmHwcTwo() : resource_manager_(this){}; -HWC2::Error DrmHwcTwo::CreateDisplay(hwc2_display_t displ, - HWC2::DisplayType type) { - DrmDevice *drm = resource_manager_.GetDrmDevice(static_cast<int>(displ)); - if (!drm) { - ALOGE("Failed to get a valid drmresource"); - return HWC2::Error::NoResources; +/* Must be called after every display attach/detach cycle */ +void DrmHwcTwo::FinalizeDisplayBinding() { + if (displays_.count(kPrimaryDisplay) == 0) { + /* Primary display MUST always exist */ + ALOGI("No pipelines available. Creating null-display for headless mode"); + displays_[kPrimaryDisplay] = std::make_unique< + HwcDisplay>(kPrimaryDisplay, HWC2::DisplayType::Physical, this); + /* Initializes null-display */ + displays_[kPrimaryDisplay]->SetPipeline(nullptr); } - displays_.emplace(std::piecewise_construct, std::forward_as_tuple(displ), - std::forward_as_tuple(&resource_manager_, drm, displ, type, - this)); - DrmCrtc *crtc = drm->GetCrtcForDisplay(static_cast<int>(displ)); - if (!crtc) { - ALOGE("Failed to get crtc for display %d", static_cast<int>(displ)); - return HWC2::Error::BadDisplay; + if (displays_[kPrimaryDisplay]->IsInHeadlessMode() && + !display_handles_.empty()) { + /* Reattach first secondary display to take place of the primary */ + auto *pipe = display_handles_.begin()->first; + ALOGI("Primary display was disconnected, reattaching '%s' as new primary", + pipe->connector->Get()->GetName().c_str()); + UnbindDisplay(pipe); + BindDisplay(pipe); } - auto display_planes = std::vector<DrmPlane *>(); - for (const auto &plane : drm->planes()) { - if (plane->GetCrtcSupported(*crtc)) - display_planes.push_back(plane.get()); + + // Finally, send hotplug events to the client + for (auto &dhe : deferred_hotplug_events_) { + SendHotplugEventToClient(dhe.first, dhe.second); } - displays_.at(displ).Init(&display_planes); - return HWC2::Error::None; + deferred_hotplug_events_.clear(); + + /* Wait 0.2s before removing the displays to flush pending HWC2 transactions + */ + auto &mutex = GetResMan().GetMainLock(); + mutex.unlock(); + const int kTimeForSFToDisposeDisplayUs = 200000; + usleep(kTimeForSFToDisposeDisplayUs); + mutex.lock(); + std::vector<std::unique_ptr<HwcDisplay>> for_disposal; + for (auto handle : displays_for_removal_list_) { + for_disposal.emplace_back( + std::unique_ptr<HwcDisplay>(displays_[handle].release())); + displays_.erase(handle); + } + /* Destroy HwcDisplays while unlocked to avoid vsyncworker deadlocks */ + mutex.unlock(); + for_disposal.clear(); + mutex.lock(); } -HWC2::Error DrmHwcTwo::Init() { - int rv = resource_manager_.Init(); - if (rv) { - ALOGE("Can't initialize the resource manager %d", rv); - return HWC2::Error::NoResources; +bool DrmHwcTwo::BindDisplay(DrmDisplayPipeline *pipeline) { + if (display_handles_.count(pipeline) != 0) { + ALOGE("%s, pipeline is already used by another display, FIXME!!!: %p", + __func__, pipeline); + return false; } - HWC2::Error ret = HWC2::Error::None; - for (int i = 0; i < resource_manager_.GetDisplayCount(); i++) { - ret = CreateDisplay(i, HWC2::DisplayType::Physical); - if (ret != HWC2::Error::None) { - ALOGE("Failed to create display %d with error %d", i, ret); - return ret; - } + uint32_t disp_handle = kPrimaryDisplay; + + if (displays_.count(kPrimaryDisplay) != 0 && + !displays_[kPrimaryDisplay]->IsInHeadlessMode()) { + disp_handle = ++last_display_handle_; } - resource_manager_.GetUEventListener()->RegisterHotplugHandler([this] { - const std::lock_guard<std::mutex> lock(GetResMan().GetMainLock()); + if (displays_.count(disp_handle) == 0) { + auto disp = std::make_unique<HwcDisplay>(disp_handle, + HWC2::DisplayType::Physical, this); + displays_[disp_handle] = std::move(disp); + } + + ALOGI("Attaching pipeline '%s' to the display #%d%s", + pipeline->connector->Get()->GetName().c_str(), (int)disp_handle, + disp_handle == kPrimaryDisplay ? " (Primary)" : ""); - HandleHotplugUEvent(); - }); + displays_[disp_handle]->SetPipeline(pipeline); + display_handles_[pipeline] = disp_handle; - return ret; + return true; +} + +bool DrmHwcTwo::UnbindDisplay(DrmDisplayPipeline *pipeline) { + if (display_handles_.count(pipeline) == 0) { + ALOGE("%s, can't find the display, pipeline: %p", __func__, pipeline); + return false; + } + auto handle = display_handles_[pipeline]; + display_handles_.erase(pipeline); + + ALOGI("Detaching the pipeline '%s' from the display #%i%s", + pipeline->connector->Get()->GetName().c_str(), (int)handle, + handle == kPrimaryDisplay ? " (Primary)" : ""); + + if (displays_.count(handle) == 0) { + ALOGE("%s, can't find the display, handle: %" PRIu64, __func__, handle); + return false; + } + displays_[handle]->SetPipeline(nullptr); + + /* We must defer display disposal and removal, since it may still have pending + * HWC_API calls scheduled and waiting until ueventlistener thread releases + * main lock, otherwise transaction may fail and SF may crash + */ + if (handle != kPrimaryDisplay) { + displays_for_removal_list_.emplace_back(handle); + } + return true; } HWC2::Error DrmHwcTwo::CreateVirtualDisplay(uint32_t /*width*/, @@ -99,8 +155,8 @@ void DrmHwcTwo::Dump(uint32_t *outSize, char *outBuffer) { output << "-- drm_hwcomposer --\n\n"; - for (std::pair<const hwc2_display_t, HwcDisplay> &dp : displays_) - output << dp.second.Dump(); + for (auto &disp : displays_) + output << disp.second->Dump(); mDumpString = output.str(); *outSize = static_cast<uint32_t>(mDumpString.size()); @@ -117,9 +173,13 @@ HWC2::Error DrmHwcTwo::RegisterCallback(int32_t descriptor, switch (static_cast<HWC2::Callback>(descriptor)) { case HWC2::Callback::Hotplug: { hotplug_callback_ = std::make_pair(HWC2_PFN_HOTPLUG(function), data); - const auto &drm_devices = resource_manager_.GetDrmDevices(); - for (const auto &device : drm_devices) - HandleInitialHotplugState(device.get()); + if (function != nullptr) { + resource_manager_.Init(); + } else { + resource_manager_.DeInit(); + /* Headless display may still be here, remove it */ + displays_.erase(kPrimaryDisplay); + } break; } case HWC2::Callback::Refresh: { @@ -135,6 +195,11 @@ HWC2::Error DrmHwcTwo::RegisterCallback(int32_t descriptor, vsync_2_4_callback_ = std::make_pair(HWC2_PFN_VSYNC_2_4(function), data); break; } + case HWC2::Callback::VsyncPeriodTimingChanged: { + period_timing_changed_callback_ = std:: + make_pair(HWC2_PFN_VSYNC_PERIOD_TIMING_CHANGED(function), data); + break; + } #endif default: break; @@ -142,7 +207,8 @@ HWC2::Error DrmHwcTwo::RegisterCallback(int32_t descriptor, return HWC2::Error::None; } -void DrmHwcTwo::HandleDisplayHotplug(hwc2_display_t displayid, int state) { +void DrmHwcTwo::SendHotplugEventToClient(hwc2_display_t displayid, + bool connected) { auto &mutex = GetResMan().GetMainLock(); if (mutex.try_lock()) { ALOGE("FIXME!!!: Main mutex must be locked in %s", __func__); @@ -157,52 +223,44 @@ void DrmHwcTwo::HandleDisplayHotplug(hwc2_display_t displayid, int state) { */ mutex.unlock(); hc.first(hc.second, displayid, - state == DRM_MODE_CONNECTED ? HWC2_CONNECTION_CONNECTED - : HWC2_CONNECTION_DISCONNECTED); + connected == DRM_MODE_CONNECTED ? HWC2_CONNECTION_CONNECTED + : HWC2_CONNECTION_DISCONNECTED); mutex.lock(); } } -void DrmHwcTwo::HandleInitialHotplugState(DrmDevice *drmDevice) { - for (const auto &conn : drmDevice->connectors()) { - int display_id = conn->display(); - auto &display = displays_.at(display_id); - - if (conn->state() != DRM_MODE_CONNECTED && !display.IsInHeadlessMode()) - continue; - HandleDisplayHotplug(conn->display(), display.IsInHeadlessMode() - ? DRM_MODE_CONNECTED - : conn->state()); +void DrmHwcTwo::SendVsyncEventToClient( + hwc2_display_t displayid, int64_t timestamp, + [[maybe_unused]] uint32_t vsync_period) const { + /* vsync callback */ +#if PLATFORM_SDK_VERSION > 29 + if (vsync_2_4_callback_.first != nullptr && + vsync_2_4_callback_.second != nullptr) { + vsync_2_4_callback_.first(vsync_2_4_callback_.second, displayid, timestamp, + vsync_period); + } else +#endif + if (vsync_callback_.first != nullptr && + vsync_callback_.second != nullptr) { + vsync_callback_.first(vsync_callback_.second, displayid, timestamp); } } -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; - - 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(); - auto &display = displays_.at(display_id); - display.ChosePreferredConfig(); - if (cur_state != DRM_MODE_CONNECTED) { - display.ClearDisplay(); - } - - HandleDisplayHotplug(display_id, display.IsInHeadlessMode() - ? DRM_MODE_CONNECTED - : cur_state); - } +void DrmHwcTwo::SendVsyncPeriodTimingChangedEventToClient( + [[maybe_unused]] hwc2_display_t displayid, + [[maybe_unused]] int64_t timestamp) const { +#if PLATFORM_SDK_VERSION > 29 + hwc_vsync_period_change_timeline_t timeline = { + .newVsyncAppliedTimeNanos = timestamp, + .refreshRequired = false, + .refreshTimeNanos = 0, + }; + if (period_timing_changed_callback_.first != nullptr && + period_timing_changed_callback_.second != nullptr) { + period_timing_changed_callback_ + .first(period_timing_changed_callback_.second, displayid, &timeline); } +#endif } } // namespace android diff --git a/hwc2_device/DrmHwcTwo.h b/hwc2_device/DrmHwcTwo.h index f38ba05..2b8a74f 100644 --- a/hwc2_device/DrmHwcTwo.h +++ b/hwc2_device/DrmHwcTwo.h @@ -24,27 +24,20 @@ namespace android { -class DrmHwcTwo { +class DrmHwcTwo : public PipelineToFrontendBindingInterface { public: DrmHwcTwo(); - - HWC2::Error Init(); + ~DrmHwcTwo() override = default; 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_{}; + std::pair<HWC2_PFN_VSYNC_PERIOD_TIMING_CHANGED, hwc2_callback_data_t> + period_timing_changed_callback_{}; #endif std::pair<HWC2_PFN_REFRESH, hwc2_callback_data_t> refresh_callback_{}; - static HwcDisplay *GetDisplay(DrmHwcTwo *hwc, hwc2_display_t display_handle) { - auto it = hwc->displays_.find(display_handle); - if (it == hwc->displays_.end()) - return nullptr; - - return &it->second; - } - // Device functions HWC2::Error CreateVirtualDisplay(uint32_t width, uint32_t height, int32_t *format, hwc2_display_t *display); @@ -53,22 +46,44 @@ class DrmHwcTwo { uint32_t GetMaxVirtualDisplayCount(); HWC2::Error RegisterCallback(int32_t descriptor, hwc2_callback_data_t data, hwc2_function_pointer_t function); - HWC2::Error CreateDisplay(hwc2_display_t displ, HWC2::DisplayType type); + + auto GetDisplay(hwc2_display_t display_handle) { + return displays_.count(display_handle) != 0 + ? displays_[display_handle].get() + : nullptr; + } auto &GetResMan() { return resource_manager_; } - private: - void HandleDisplayHotplug(hwc2_display_t displayid, int state); - void HandleInitialHotplugState(DrmDevice *drmDevice); + void ScheduleHotplugEvent(hwc2_display_t displayid, bool connected) { + deferred_hotplug_events_[displayid] = connected; + } + + // PipelineToFrontendBindingInterface + bool BindDisplay(DrmDisplayPipeline *pipeline) override; + bool UnbindDisplay(DrmDisplayPipeline *pipeline) override; + void FinalizeDisplayBinding() override; + + void SendVsyncEventToClient(hwc2_display_t displayid, int64_t timestamp, + uint32_t vsync_period) const; + void SendVsyncPeriodTimingChangedEventToClient(hwc2_display_t displayid, + int64_t timestamp) const; - void HandleHotplugUEvent(); + private: + void SendHotplugEventToClient(hwc2_display_t displayid, bool connected); ResourceManager resource_manager_; - std::map<hwc2_display_t, HwcDisplay> displays_; + std::map<hwc2_display_t, std::unique_ptr<HwcDisplay>> displays_; + std::map<DrmDisplayPipeline *, hwc2_display_t> display_handles_; std::string mDumpString; + + std::map<hwc2_display_t, bool> deferred_hotplug_events_; + std::vector<hwc2_display_t> displays_for_removal_list_; + + uint32_t last_display_handle_ = kPrimaryDisplay; }; } // namespace android diff --git a/hwc2_device/HwcDisplay.cpp b/hwc2_device/HwcDisplay.cpp index 8936136..cedac19 100644 --- a/hwc2_device/HwcDisplay.cpp +++ b/hwc2_device/HwcDisplay.cpp @@ -20,6 +20,7 @@ #include "HwcDisplay.h" #include "DrmHwcTwo.h" +#include "backend/Backend.h" #include "backend/BackendManager.h" #include "bufferinfo/BufferInfoGetter.h" #include "utils/log.h" @@ -68,8 +69,12 @@ std::string HwcDisplay::Dump() { " VSync remains"; } + std::string connector_name = IsInHeadlessMode() + ? "NULL-DISPLAY" + : GetPipe().connector->Get()->GetName(); + std::stringstream ss; - ss << "- Display on: " << connector_->name() << "\n" + ss << "- Display on: " << connector_name << "\n" << " Flattening state: " << flattening_state_str << "\n" << "Statistics since system boot:\n" << DumpDelta(total_stats_) << "\n\n" @@ -80,12 +85,9 @@ std::string HwcDisplay::Dump() { return ss.str(); } -HwcDisplay::HwcDisplay(ResourceManager *resource_manager, DrmDevice *drm, - hwc2_display_t handle, HWC2::DisplayType type, +HwcDisplay::HwcDisplay(hwc2_display_t handle, HWC2::DisplayType type, DrmHwcTwo *hwc2) : hwc2_(hwc2), - resource_manager_(resource_manager), - drm_(drm), handle_(handle), type_(type), color_transform_hint_(HAL_COLOR_TRANSFORM_IDENTITY) { @@ -97,108 +99,72 @@ HwcDisplay::HwcDisplay(ResourceManager *resource_manager, DrmDevice *drm, // clang-format on } -void HwcDisplay::ClearDisplay() { - if (IsInHeadlessMode()) { - ALOGE("%s: Headless mode, should never reach here: ", __func__); - return; - } +HwcDisplay::~HwcDisplay() = default; - AtomicCommitArgs a_args = {.clear_active_composition = true}; - compositor_.ExecuteAtomicCommit(a_args); -} +void HwcDisplay::SetPipeline(DrmDisplayPipeline *pipeline) { + pipeline_ = pipeline; -HWC2::Error HwcDisplay::Init(std::vector<DrmPlane *> *planes) { - int display = static_cast<int>(handle_); - int ret = compositor_.Init(resource_manager_, display); - if (ret) { - ALOGE("Failed display compositor init for display %d (%d)", display, ret); - return HWC2::Error::NoResources; - } - - // Split up the given display planes into primary and overlay to properly - // interface with the composition - char use_overlay_planes_prop[PROPERTY_VALUE_MAX]; - property_get("vendor.hwc.drm.use_overlay_planes", use_overlay_planes_prop, - "1"); - bool use_overlay_planes = strtol(use_overlay_planes_prop, nullptr, 10); - for (auto &plane : *planes) { - if (plane->GetType() == DRM_PLANE_TYPE_PRIMARY) - primary_planes_.push_back(plane); - else if (use_overlay_planes && (plane)->GetType() == DRM_PLANE_TYPE_OVERLAY) - overlay_planes_.push_back(plane); - } - - crtc_ = drm_->GetCrtcForDisplay(display); - if (!crtc_) { - ALOGE("Failed to get crtc for display %d", display); - return HWC2::Error::BadDisplay; - } + if (pipeline != nullptr) { + ChosePreferredConfig(); + Init(); - connector_ = drm_->GetConnectorForDisplay(display); - if (!connector_) { - ALOGE("Failed to get connector for display %d", display); - return HWC2::Error::BadDisplay; + hwc2_->ScheduleHotplugEvent(handle_, /*connected = */ true); + } else { + backend_.reset(); + vsync_worker_.Init(nullptr, [](int64_t) {}); + SetClientTarget(nullptr, -1, 0, {}); + if (handle_ != kPrimaryDisplay) { + hwc2_->ScheduleHotplugEvent(handle_, /*connected = */ false); + } } +} - ret = vsync_worker_.Init(drm_, display, [this](int64_t timestamp) { +HWC2::Error HwcDisplay::Init() { + int ret = vsync_worker_.Init(pipeline_, [this](int64_t timestamp) { const std::lock_guard<std::mutex> lock(hwc2_->GetResMan().GetMainLock()); - /* 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{}; + if (vsync_event_en_) { + uint32_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); + hwc2_->SendVsyncEventToClient(handle_, timestamp, period_ns); + } + if (vsync_flattening_en_) { + ProcessFlatenningVsyncInternal(); + } + if (vsync_tracking_en_) { + last_vsync_ts_ = timestamp; + } + if (!vsync_event_en_ && !vsync_flattening_en_ && !vsync_tracking_en_) { + vsync_worker_.VSyncControl(false); } }); - if (ret) { - ALOGE("Failed to create event worker for d=%d %d\n", display, ret); + if (ret && ret != -EALREADY) { + ALOGE("Failed to create event worker for d=%d %d\n", int(handle_), ret); return HWC2::Error::BadDisplay; } - ret = flattening_vsync_worker_ - .Init(drm_, display, [this](int64_t /*timestamp*/) { - const std::lock_guard<std::mutex> lock( - hwc2_->GetResMan().GetMainLock()); - /* 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; - } - - ret = BackendManager::GetInstance().SetBackendForDisplay(this); - if (ret) { - ALOGE("Failed to set backend for d=%d %d\n", display, ret); - return HWC2::Error::BadDisplay; + if (!IsInHeadlessMode()) { + ret = BackendManager::GetInstance().SetBackendForDisplay(this); + if (ret) { + ALOGE("Failed to set backend for d=%d %d\n", int(handle_), ret); + return HWC2::Error::BadDisplay; + } } client_layer_.SetLayerBlendMode(HWC2_BLEND_MODE_PREMULTIPLIED); - return ChosePreferredConfig(); + return HWC2::Error::None; } HWC2::Error HwcDisplay::ChosePreferredConfig() { - HWC2::Error err = configs_.Update(*connector_); - if (!IsInHeadlessMode() && err != HWC2::Error::None) + HWC2::Error err{}; + if (!IsInHeadlessMode()) { + err = configs_.Update(*pipeline_->connector->Get()); + } else { + configs_.FillHeadless(); + } + if (!IsInHeadlessMode() && err != HWC2::Error::None) { return HWC2::Error::BadDisplay; + } return SetActiveConfig(configs_.preferred_config_id); } @@ -217,18 +183,19 @@ HWC2::Error HwcDisplay::CreateLayer(hwc2_layer_t *layer) { } HWC2::Error HwcDisplay::DestroyLayer(hwc2_layer_t layer) { - if (!get_layer(layer)) + if (!get_layer(layer)) { return HWC2::Error::BadLayer; + } layers_.erase(layer); return HWC2::Error::None; } HWC2::Error HwcDisplay::GetActiveConfig(hwc2_config_t *config) const { - if (configs_.hwc_configs.count(configs_.active_config_id) == 0) + if (configs_.hwc_configs.count(staged_mode_config_id_) == 0) return HWC2::Error::BadConfig; - *config = configs_.active_config_id; + *config = staged_mode_config_id_; return HWC2::Error::None; } @@ -258,12 +225,13 @@ HWC2::Error HwcDisplay::GetChangedCompositionTypes(uint32_t *num_elements, HWC2::Error HwcDisplay::GetClientTargetSupport(uint32_t width, uint32_t height, int32_t /*format*/, int32_t dataspace) { - std::pair<uint32_t, uint32_t> min = drm_->min_resolution(); - std::pair<uint32_t, uint32_t> max = drm_->max_resolution(); if (IsInHeadlessMode()) { return HWC2::Error::None; } + std::pair<uint32_t, uint32_t> min = pipeline_->device->GetMinResolution(); + std::pair<uint32_t, uint32_t> max = pipeline_->device->GetMaxResolution(); + if (width < min.first || height < min.second) return HWC2::Error::Unsupported; @@ -293,7 +261,7 @@ HWC2::Error HwcDisplay::GetDisplayAttribute(hwc2_config_t config, int conf = static_cast<int>(config); if (configs_.hwc_configs.count(conf) == 0) { - ALOGE("Could not find active mode for %d", conf); + ALOGE("Could not find mode #%d", conf); return HWC2::Error::BadConfig; } @@ -330,7 +298,7 @@ HWC2::Error HwcDisplay::GetDisplayAttribute(hwc2_config_t config, case HWC2::Attribute::ConfigGroup: /* 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; + *value = int(hwc_config.group_id); break; #endif default: @@ -363,7 +331,11 @@ HWC2::Error HwcDisplay::GetDisplayConfigs(uint32_t *num_configs, HWC2::Error HwcDisplay::GetDisplayName(uint32_t *size, char *name) { std::ostringstream stream; - stream << "display-" << connector_->id(); + if (IsInHeadlessMode()) { + stream << "null-display"; + } else { + stream << "display-" << GetPipe().connector->Get()->GetId(); + } std::string string = stream.str(); size_t length = string.length(); if (!name) { @@ -441,6 +413,26 @@ HWC2::Error HwcDisplay::CreateComposition(AtomicCommitArgs &a_args) { return HWC2::Error::None; } + int PrevModeVsyncPeriodNs = static_cast<int>( + 1E9 / GetPipe().connector->Get()->GetActiveMode().v_refresh()); + + auto mode_update_commited_ = false; + if (staged_mode_ && + staged_mode_change_time_ <= ResourceManager::GetTimeMonotonicNs()) { + client_layer_.SetLayerDisplayFrame( + (hwc_rect_t){.left = 0, + .top = 0, + .right = static_cast<int>(staged_mode_->h_display()), + .bottom = static_cast<int>(staged_mode_->v_display())}); + + configs_.active_config_id = staged_mode_config_id_; + + a_args.display_mode = *staged_mode_; + if (!a_args.test_only) { + mode_update_commited_ = true; + } + } + // order the layers by z-order bool use_client_layer = false; uint32_t client_z_order = UINT32_MAX; @@ -471,7 +463,7 @@ HWC2::Error HwcDisplay::CreateComposition(AtomicCommitArgs &a_args) { for (std::pair<const uint32_t, HwcLayer *> &l : z_map) { DrmHwcLayer layer; l.second->PopulateDrmLayer(&layer); - int ret = layer.ImportBuffer(drm_); + int ret = layer.ImportBuffer(GetPipe().device); if (ret) { ALOGE("Failed to import layer, ret=%d", ret); return HWC2::Error::NoResources; @@ -479,29 +471,21 @@ HWC2::Error HwcDisplay::CreateComposition(AtomicCommitArgs &a_args) { composition_layers.emplace_back(std::move(layer)); } - auto composition = std::make_shared<DrmDisplayComposition>(crtc_); - - // TODO(nobody): Don't always assume geometry changed - int ret = composition->SetLayers(composition_layers.data(), - composition_layers.size()); - if (ret) { - ALOGE("Failed to set layers in the composition ret=%d", ret); - return HWC2::Error::BadLayer; - } - - std::vector<DrmPlane *> primary_planes(primary_planes_); - std::vector<DrmPlane *> overlay_planes(overlay_planes_); - ret = composition->Plan(&primary_planes, &overlay_planes); - if (ret) { - ALOGV("Failed to plan the composition ret=%d", ret); + /* Store plan to ensure shared planes won't be stolen by other display + * in between of ValidateDisplay() and PresentDisplay() calls + */ + current_plan_ = DrmKmsPlan::CreateDrmKmsPlan(GetPipe(), + std::move(composition_layers)); + if (!current_plan_) { + if (!a_args.test_only) { + ALOGE("Failed to create DrmKmsPlan"); + } return HWC2::Error::BadConfig; } - a_args.composition = composition; - if (staged_mode) { - a_args.display_mode = *staged_mode; - } - ret = compositor_.ExecuteAtomicCommit(a_args); + a_args.composition = current_plan_; + + int ret = GetPipe().atomic_state_manager->ExecuteAtomicCommit(a_args); if (ret) { if (!a_args.test_only) @@ -509,8 +493,13 @@ HWC2::Error HwcDisplay::CreateComposition(AtomicCommitArgs &a_args) { return HWC2::Error::BadParameter; } - if (!a_args.test_only) { - staged_mode.reset(); + if (mode_update_commited_) { + staged_mode_.reset(); + vsync_tracking_en_ = false; + if (last_vsync_ts_ != 0) { + hwc2_->SendVsyncPeriodTimingChangedEventToClient( + handle_, last_vsync_ts_ + PrevModeVsyncPeriodNs); + } } return HWC2::Error::None; @@ -548,30 +537,24 @@ HWC2::Error HwcDisplay::PresentDisplay(int32_t *present_fence) { return HWC2::Error::None; } -HWC2::Error HwcDisplay::SetActiveConfig(hwc2_config_t config) { - int conf = static_cast<int>(config); - - if (configs_.hwc_configs.count(conf) == 0) { - ALOGE("Could not find active mode for %d", conf); +HWC2::Error HwcDisplay::SetActiveConfigInternal(uint32_t config, + int64_t change_time) { + if (configs_.hwc_configs.count(config) == 0) { + ALOGE("Could not find active mode for %u", config); return HWC2::Error::BadConfig; } - auto &mode = configs_.hwc_configs[conf].mode; - - staged_mode = mode; - - configs_.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())}; - client_layer_.SetLayerDisplayFrame(display_frame); + staged_mode_ = configs_.hwc_configs[config].mode; + staged_mode_change_time_ = change_time; + staged_mode_config_id_ = config; return HWC2::Error::None; } +HWC2::Error HwcDisplay::SetActiveConfig(hwc2_config_t config) { + return SetActiveConfigInternal(config, ResourceManager::GetTimeMonotonicNs()); +} + /* Find API details at: * https://cs.android.com/android/platform/superproject/+/android-11.0.0_r3:hardware/libhardware/include/hardware/hwcomposer2.h;l=1861 */ @@ -656,7 +639,7 @@ HWC2::Error HwcDisplay::SetPowerMode(int32_t mode_in) { * true, as the next composition frame will implicitly activate * the display */ - return compositor_.ActivateDisplayUsingDPMS() == 0 + return GetPipe().atomic_state_manager->ActivateDisplayUsingDPMS() == 0 ? HWC2::Error::None : HWC2::Error::BadParameter; break; @@ -668,7 +651,7 @@ HWC2::Error HwcDisplay::SetPowerMode(int32_t mode_in) { return HWC2::Error::BadParameter; }; - int err = compositor_.ExecuteAtomicCommit(a_args); + int err = GetPipe().atomic_state_manager->ExecuteAtomicCommit(a_args); if (err) { ALOGE("Failed to apply the dpms composition err=%d", err); return HWC2::Error::BadParameter; @@ -677,7 +660,10 @@ HWC2::Error HwcDisplay::SetPowerMode(int32_t mode_in) { } HWC2::Error HwcDisplay::SetVsyncEnabled(int32_t enabled) { - vsync_worker_.VSyncControl(HWC2_VSYNC_ENABLE == enabled); + vsync_event_en_ = HWC2_VSYNC_ENABLE == enabled; + if (vsync_event_en_) { + vsync_worker_.VSyncControl(true); + } return HWC2::Error::None; } @@ -706,11 +692,25 @@ std::vector<HwcLayer *> HwcDisplay::GetOrderLayersByZPos() { return ordered_layers; } +HWC2::Error HwcDisplay::GetDisplayVsyncPeriod( + uint32_t *outVsyncPeriod /* ns */) { + return GetDisplayAttribute(configs_.active_config_id, + HWC2_ATTRIBUTE_VSYNC_PERIOD, + (int32_t *)(outVsyncPeriod)); +} + #if PLATFORM_SDK_VERSION > 29 HWC2::Error HwcDisplay::GetDisplayConnectionType(uint32_t *outType) { - if (connector_->internal()) + if (IsInHeadlessMode()) { *outType = static_cast<uint32_t>(HWC2::DisplayConnectionType::Internal); - else if (connector_->external()) + return HWC2::Error::None; + } + /* Primary display should be always internal, + * otherwise SF will be unhappy and will crash + */ + if (GetPipe().connector->Get()->IsInternal() || handle_ == kPrimaryDisplay) + *outType = static_cast<uint32_t>(HWC2::DisplayConnectionType::Internal); + else if (GetPipe().connector->Get()->IsExternal()) *outType = static_cast<uint32_t>(HWC2::DisplayConnectionType::External); else return HWC2::Error::BadConfig; @@ -718,22 +718,38 @@ HWC2::Error HwcDisplay::GetDisplayConnectionType(uint32_t *outType) { return HWC2::Error::None; } -HWC2::Error HwcDisplay::GetDisplayVsyncPeriod( - hwc2_vsync_period_t *outVsyncPeriod /* ns */) { - return GetDisplayAttribute(configs_.active_config_id, - HWC2_ATTRIBUTE_VSYNC_PERIOD, - (int32_t *)(outVsyncPeriod)); -} - HWC2::Error HwcDisplay::SetActiveConfigWithConstraints( - hwc2_config_t /*config*/, + hwc2_config_t config, hwc_vsync_period_change_constraints_t *vsyncPeriodChangeConstraints, hwc_vsync_period_change_timeline_t *outTimeline) { if (vsyncPeriodChangeConstraints == nullptr || outTimeline == nullptr) { return HWC2::Error::BadParameter; } - return HWC2::Error::BadConfig; + uint32_t current_vsync_period{}; + GetDisplayVsyncPeriod(¤t_vsync_period); + + if (vsyncPeriodChangeConstraints->seamlessRequired) { + return HWC2::Error::SeamlessNotAllowed; + } + + outTimeline->refreshTimeNanos = vsyncPeriodChangeConstraints + ->desiredTimeNanos - + current_vsync_period; + auto ret = SetActiveConfigInternal(config, outTimeline->refreshTimeNanos); + if (ret != HWC2::Error::None) { + return ret; + } + + outTimeline->refreshRequired = true; + outTimeline->newVsyncAppliedTimeNanos = vsyncPeriodChangeConstraints + ->desiredTimeNanos; + + last_vsync_ts_ = 0; + vsync_tracking_en_ = true; + vsync_worker_.VSyncControl(true); + + return HWC2::Error::None; } HWC2::Error HwcDisplay::SetAutoLowLatencyMode(bool /*on*/) { @@ -765,11 +781,18 @@ HWC2::Error HwcDisplay::SetContentType(int32_t contentType) { HWC2::Error HwcDisplay::GetDisplayIdentificationData(uint8_t *outPort, uint32_t *outDataSize, uint8_t *outData) { - auto blob = connector_->GetEdidBlob(); + if (IsInHeadlessMode()) { + return HWC2::Error::None; + } + auto blob = GetPipe().connector->Get()->GetEdidBlob(); + + *outPort = handle_ - 1; if (!blob) { - ALOGE("Failed to get edid property value."); - return HWC2::Error::Unsupported; + if (outData == nullptr) { + *outDataSize = 0; + } + return HWC2::Error::None; } if (outData) { @@ -778,7 +801,6 @@ HWC2::Error HwcDisplay::GetDisplayIdentificationData(uint8_t *outPort, } else { *outDataSize = blob->length; } - *outPort = connector_->id(); return HWC2::Error::None; } @@ -851,4 +873,37 @@ void HwcDisplay::set_backend(std::unique_ptr<Backend> backend) { backend_ = std::move(backend); } +/* returns true if composition should be sent to client */ +bool HwcDisplay::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; + } + + vsync_flattening_en_ = true; + vsync_worker_.VSyncControl(true); + flattenning_state_ = ClientFlattenningState::VsyncCountdownMax; + return false; +} + +void HwcDisplay::ProcessFlatenningVsyncInternal() { + 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_); + vsync_flattening_en_ = false; + } +} + } // namespace android diff --git a/hwc2_device/HwcDisplay.h b/hwc2_device/HwcDisplay.h index c3e0f6e..98d8e9b 100644 --- a/hwc2_device/HwcDisplay.h +++ b/hwc2_device/HwcDisplay.h @@ -22,7 +22,7 @@ #include <optional> #include "HwcDisplayConfigs.h" -#include "compositor/DrmDisplayCompositor.h" +#include "drm/DrmAtomicStateManager.h" #include "drm/ResourceManager.h" #include "drm/VSyncWorker.h" #include "drmhwcomposer.h" @@ -33,12 +33,16 @@ namespace android { class Backend; class DrmHwcTwo; +inline constexpr uint32_t kPrimaryDisplay = 0; + class HwcDisplay { public: - HwcDisplay(ResourceManager *resource_manager, DrmDevice *drm, - hwc2_display_t handle, HWC2::DisplayType type, DrmHwcTwo *hwc2); + HwcDisplay(hwc2_display_t handle, HWC2::DisplayType type, DrmHwcTwo *hwc2); HwcDisplay(const HwcDisplay &) = delete; - HWC2::Error Init(std::vector<DrmPlane *> *planes); + ~HwcDisplay(); + + /* SetPipeline should be carefully used only by DrmHwcTwo hotplug handlers */ + void SetPipeline(DrmDisplayPipeline *pipeline); HWC2::Error CreateComposition(AtomicCommitArgs &a_args); std::vector<HwcLayer *> GetOrderLayersByZPos(); @@ -81,7 +85,6 @@ class HwcDisplay { #endif #if PLATFORM_SDK_VERSION > 29 HWC2::Error GetDisplayConnectionType(uint32_t *outType); - HWC2::Error GetDisplayVsyncPeriod(hwc2_vsync_period_t *outVsyncPeriod); HWC2::Error SetActiveConfigWithConstraints( hwc2_config_t config, @@ -94,6 +97,7 @@ class HwcDisplay { HWC2::Error SetContentType(int32_t contentType); #endif + HWC2::Error GetDisplayVsyncPeriod(uint32_t *outVsyncPeriod); HWC2::Error GetDozeSupport(int32_t *support); HWC2::Error GetHdrCapabilities(uint32_t *num_types, int32_t *types, @@ -142,32 +146,16 @@ class HwcDisplay { const Backend *backend() const; void set_backend(std::unique_ptr<Backend> backend); - const std::vector<DrmPlane *> &primary_planes() const { - return primary_planes_; - } - - const std::vector<DrmPlane *> &overlay_planes() const { - return overlay_planes_; + auto GetHwc2() { + return hwc2_; } std::map<hwc2_layer_t, HwcLayer> &layers() { return layers_; } - const DrmDisplayCompositor &compositor() const { - return compositor_; - } - - const DrmDevice *drm() const { - return drm_; - } - - const DrmConnector *connector() const { - return connector_; - } - - ResourceManager *resource_manager() const { - return resource_manager_; + auto &GetPipe() { + return *pipeline_; } android_color_transform_t &color_transform_hint() { @@ -179,26 +167,8 @@ class HwcDisplay { } /* 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; - } + bool ProcessClientFlatteningState(bool skip); + void ProcessFlatenningVsyncInternal(); /* Headless mode required to keep SurfaceFlinger alive when all display are * disconnected, Without headless mode Android will continuously crash. @@ -207,7 +177,7 @@ class HwcDisplay { * https://source.android.com/devices/graphics/hotplug#handling-common-scenarios */ bool IsInHeadlessMode() { - return handle_ == 0 && connector_->state() != DRM_MODE_CONNECTED; + return !pipeline_; } private: @@ -220,41 +190,48 @@ class HwcDisplay { }; std::atomic_int flattenning_state_{ClientFlattenningState::NotRequired}; - VSyncWorker flattening_vsync_worker_; constexpr static size_t MATRIX_SIZE = 16; HwcDisplayConfigs configs_; - DrmHwcTwo *hwc2_; - - std::optional<DrmMode> staged_mode; + DrmHwcTwo *const hwc2_; - ResourceManager *resource_manager_; - DrmDevice *drm_; - DrmDisplayCompositor compositor_; + std::optional<DrmMode> staged_mode_; + int64_t staged_mode_change_time_{}; + uint32_t staged_mode_config_id_{}; - std::vector<DrmPlane *> primary_planes_; - std::vector<DrmPlane *> overlay_planes_; + DrmDisplayPipeline *pipeline_{}; std::unique_ptr<Backend> backend_; VSyncWorker vsync_worker_; - DrmConnector *connector_ = nullptr; - DrmCrtc *crtc_ = nullptr; - hwc2_display_t handle_; + bool vsync_event_en_{}; + bool vsync_flattening_en_{}; + bool vsync_tracking_en_{}; + int64_t last_vsync_ts_{}; + + const hwc2_display_t handle_; HWC2::DisplayType type_; - uint32_t layer_idx_ = 0; + + uint32_t layer_idx_{}; + std::map<hwc2_layer_t, HwcLayer> layers_; HwcLayer client_layer_; int32_t color_mode_{}; std::array<float, MATRIX_SIZE> color_transform_matrix_{}; android_color_transform_t color_transform_hint_; + std::shared_ptr<DrmKmsPlan> current_plan_; + uint32_t frame_no_ = 0; Stats total_stats_; Stats prev_stats_; std::string DumpDelta(HwcDisplay::Stats delta); + + HWC2::Error Init(); + + HWC2::Error SetActiveConfigInternal(uint32_t config, int64_t change_time); }; } // namespace android diff --git a/hwc2_device/HwcDisplayConfigs.cpp b/hwc2_device/HwcDisplayConfigs.cpp index 16f1ed0..6a3ed5a 100644 --- a/hwc2_device/HwcDisplayConfigs.cpp +++ b/hwc2_device/HwcDisplayConfigs.cpp @@ -31,10 +31,10 @@ constexpr uint32_t kHeadlessModeDisplayVRefresh = 60; namespace android { -// NOLINTNEXTLINE (readability-function-cognitive-complexity): Fixme -HWC2::Error HwcDisplayConfigs::Update(DrmConnector &connector) { - /* In case UpdateModes will fail we will still have one mode for headless - * mode*/ +// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) +uint32_t HwcDisplayConfigs::last_config_id = 1; + +void HwcDisplayConfigs::FillHeadless() { hwc_configs.clear(); last_config_id++; @@ -53,7 +53,13 @@ HWC2::Error HwcDisplayConfigs::Update(DrmConnector &connector) { mm_width = kHeadlessModeDisplayWidthMm; mm_height = kHeadlessModeDisplayHeightMm; +} +// NOLINTNEXTLINE (readability-function-cognitive-complexity): Fixme +HWC2::Error HwcDisplayConfigs::Update(DrmConnector &connector) { + /* In case UpdateModes will fail we will still have one mode for headless + * mode*/ + FillHeadless(); /* Read real configs */ int ret = connector.UpdateModes(); if (ret != 0) { @@ -61,25 +67,25 @@ HWC2::Error HwcDisplayConfigs::Update(DrmConnector &connector) { return HWC2::Error::BadDisplay; } - if (connector.modes().empty()) { + if (connector.GetModes().empty()) { ALOGE("No modes reported by KMS"); return HWC2::Error::BadDisplay; } hwc_configs.clear(); - mm_width = connector.mm_width(); - mm_height = connector.mm_height(); + mm_width = connector.GetMmWidth(); + mm_height = connector.GetMmHeight(); preferred_config_id = 0; - int preferred_config_group_id = 0; + uint32_t preferred_config_group_id = 0; - int first_config_id = last_config_id; - int last_group_id = 1; + uint32_t first_config_id = last_config_id; + uint32_t last_group_id = 1; /* Group modes */ - for (const auto &mode : connector.modes()) { + for (const auto &mode : connector.GetModes()) { /* Find group for the new mode or create new group */ - int group_found = 0; + uint32_t 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()) { @@ -122,7 +128,7 @@ HWC2::Error HwcDisplayConfigs::Update(DrmConnector &connector) { preferred_config_group_id = 1; } - for (int group = 1; group < last_group_id; group++) { + for (uint32_t group = 1; group < last_group_id; group++) { bool has_interlaced = false; bool has_progressive = false; for (auto &hwc_config : hwc_configs) { @@ -173,8 +179,8 @@ HWC2::Error HwcDisplayConfigs::Update(DrmConnector &connector) { * otherwise android.graphics.cts.SetFrameRateTest CTS will fail */ constexpr float kMinFpsDelta = 1.0; // FPS - for (int m1 = first_config_id; m1 < last_config_id; m1++) { - for (int m2 = first_config_id; m2 < last_config_id; m2++) { + for (uint32_t m1 = first_config_id; m1 < last_config_id; m1++) { + for (uint32_t m2 = first_config_id; 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() - @@ -190,8 +196,6 @@ HWC2::Error HwcDisplayConfigs::Update(DrmConnector &connector) { } } - /* Set active mode to be valid mode */ - active_config_id = preferred_config_id; return HWC2::Error::None; } diff --git a/hwc2_device/HwcDisplayConfigs.h b/hwc2_device/HwcDisplayConfigs.h index 5bcf696..7c173d6 100644 --- a/hwc2_device/HwcDisplayConfigs.h +++ b/hwc2_device/HwcDisplayConfigs.h @@ -28,8 +28,8 @@ namespace android { class DrmConnector; struct HwcDisplayConfig { - int id{}; - int group_id{}; + uint32_t id{}; + uint32_t group_id{}; DrmMode mode; bool disabled{}; @@ -40,13 +40,15 @@ struct HwcDisplayConfig { struct HwcDisplayConfigs { HWC2::Error Update(DrmConnector &conn); + void FillHeadless(); - std::map<int /*config_id*/, struct HwcDisplayConfig> hwc_configs; + std::map<uint32_t /*config_id*/, struct HwcDisplayConfig> hwc_configs; - int active_config_id = 0; - int preferred_config_id = 0; + uint32_t active_config_id = 0; + uint32_t preferred_config_id = 0; - int last_config_id = 1; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) + static uint32_t last_config_id; uint32_t mm_width = 0; uint32_t mm_height = 0; diff --git a/hwc2_device/hwc2_device.cpp b/hwc2_device/hwc2_device.cpp index 6d258e8..a6dedb4 100644 --- a/hwc2_device/hwc2_device.cpp +++ b/hwc2_device/hwc2_device.cpp @@ -74,8 +74,8 @@ static int32_t DisplayHook(hwc2_device_t *dev, hwc2_display_t display_handle, GetFuncName(__PRETTY_FUNCTION__).c_str()); DrmHwcTwo *hwc = ToDrmHwcTwo(dev); const std::lock_guard<std::mutex> lock(hwc->GetResMan().GetMainLock()); - HwcDisplay *display = DrmHwcTwo::GetDisplay(hwc, display_handle); - if (!display) + auto *display = hwc->GetDisplay(display_handle); + if (display == nullptr) return static_cast<int32_t>(HWC2::Error::BadDisplay); return static_cast<int32_t>((display->*func)(std::forward<Args>(args)...)); @@ -88,8 +88,8 @@ static int32_t LayerHook(hwc2_device_t *dev, hwc2_display_t display_handle, layer_handle, GetFuncName(__PRETTY_FUNCTION__).c_str()); DrmHwcTwo *hwc = ToDrmHwcTwo(dev); const std::lock_guard<std::mutex> lock(hwc->GetResMan().GetMainLock()); - HwcDisplay *display = DrmHwcTwo::GetDisplay(hwc, display_handle); - if (!display) + auto *display = hwc->GetDisplay(display_handle); + if (display == nullptr) return static_cast<int32_t>(HWC2::Error::BadDisplay); HwcLayer *layer = display->get_layer(layer_handle); @@ -390,12 +390,6 @@ static int HookDevOpen(const struct hw_module_t *module, const char *name, ctx->getCapabilities = HookDevGetCapabilities; ctx->getFunction = HookDevGetFunction; - HWC2::Error err = ctx->drmhwctwo.Init(); - if (err != HWC2::Error::None) { - ALOGE("Failed to initialize DrmHwcTwo err=%d\n", err); - return -EINVAL; - } - *dev = &ctx.release()->common; return 0; |