From cad8e0ca57c268d179730c8ef68edd31350a11d9 Mon Sep 17 00:00:00 2001 From: Roman Stratiienko Date: Mon, 31 Jan 2022 16:40:16 +0200 Subject: drm_hwcomposer: Introduce DrmDisplayPipeline class Create systematic way of binding DRM objects (Crtc,Encoder,Planes...) to the pipeline using RAII. Use it to create the pipeline. + Allow pipeline creation to fail. Closes: https://gitlab.freedesktop.org/drm-hwcomposer/drm-hwcomposer/-/issues/14 Signed-off-by: Roman Stratiienko --- drm/DrmDevice.cpp | 124 +++++++++++++----------------------------------------- 1 file changed, 29 insertions(+), 95 deletions(-) (limited to 'drm/DrmDevice.cpp') diff --git a/drm/DrmDevice.cpp b/drm/DrmDevice.cpp index 29dd95f..ece9437 100644 --- a/drm/DrmDevice.cpp +++ b/drm/DrmDevice.cpp @@ -66,7 +66,6 @@ std::tuple DrmDevice::Init(const char *path, int num_displays) { ret = drmSetClientCap(GetFd(), DRM_CLIENT_CAP_WRITEBACK_CONNECTORS, 1); if (ret != 0) { ALOGI("Failed to set writeback cap %d", ret); - ret = 0; } #endif @@ -125,14 +124,31 @@ std::tuple DrmDevice::Init(const char *path, int num_displays) { } } + auto plane_res = MakeDrmModePlaneResUnique(GetFd()); + if (!plane_res) { + ALOGE("Failed to get plane resources"); + return std::make_tuple(-ENOENT, 0); + } + + for (uint32_t i = 0; i < plane_res->count_planes; ++i) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + auto plane = DrmPlane::CreateInstance(*this, plane_res->planes[i]); + + if (plane) { + planes_.emplace_back(std::move(plane)); + } + } + auto add_displays = [this, &num_displays](bool internal, bool connected) { for (auto &conn : connectors_) { bool is_connected = conn->IsConnected(); if ((internal ? conn->IsInternal() : conn->IsExternal()) && (connected ? is_connected : !is_connected)) { - bound_connectors_[num_displays] = conn.get(); - connectors_to_display_id_[conn.get()] = num_displays; - ++num_displays; + auto pipe = DrmDisplayPipeline::CreatePipeline(*conn); + if (pipe) { + pipelines_[num_displays] = std::move(pipe); + ++num_displays; + } } } }; @@ -145,110 +161,28 @@ std::tuple DrmDevice::Init(const char *path, int num_displays) { add_displays(/*internal = */ true, /*connected = */ false); add_displays(/*internal = */ false, /*connected = */ false); - // Catch-all for the above loops - if (ret != 0) - return std::make_tuple(ret, 0); - - auto plane_res = MakeDrmModePlaneResUnique(GetFd()); - if (!plane_res) { - ALOGE("Failed to get plane resources"); - return std::make_tuple(-ENOENT, 0); - } - - for (uint32_t i = 0; i < plane_res->count_planes; ++i) { - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - auto plane = DrmPlane::CreateInstance(*this, plane_res->planes[i]); - - if (plane) { - planes_.emplace_back(std::move(plane)); - } - } - - for (auto &conn : connectors_) { - ret = CreateDisplayPipe(conn.get()); - if (ret != 0) { - ALOGE("Failed CreateDisplayPipe %d with %d", conn->GetId(), ret); - return std::make_tuple(ret, 0); - } - } - return std::make_tuple(ret, bound_connectors_.size()); + return std::make_tuple(0, pipelines_.size()); } bool DrmDevice::HandlesDisplay(int display) const { - return bound_connectors_.count(display) != 0; + return pipelines_.count(display) != 0; } DrmConnector *DrmDevice::GetConnectorForDisplay(int display) const { - return bound_connectors_.at(display); + return pipelines_.at(display)->connector->Get(); } DrmCrtc *DrmDevice::GetCrtcForDisplay(int display) const { - return bound_crtcs_.at(display); + return pipelines_.at(display)->crtc->Get(); } -int DrmDevice::TryEncoderForDisplay(int display, DrmEncoder *enc) { - /* First try to use the currently-bound crtc */ - auto *crtc = FindCrtcById(enc->GetCurrentCrtcId()); - if (crtc != nullptr && bound_crtcs_.count(display) == 0) { - bound_crtcs_[display] = crtc; - bound_encoders_[crtc] = enc; - return 0; - } - - /* Try to find a possible crtc which will work */ - for (auto &crtc : crtcs_) { - /* Crtc not supported or we've already tried this earlier */ - if (!enc->SupportsCrtc(*crtc) || crtc->GetId() == enc->GetCurrentCrtcId()) { - continue; - } - - if (bound_crtcs_.count(display) == 0) { - bound_crtcs_[display] = crtc.get(); - bound_encoders_[crtc.get()] = enc; - return 0; - } - } - - /* We can't use the encoder, but nothing went wrong, try another one */ - return -EAGAIN; -} - -int DrmDevice::CreateDisplayPipe(DrmConnector *connector) { - int display = connectors_to_display_id_.at(connector); - /* Try to use current setup first */ - auto *enc0 = FindEncoderById(connector->GetCurrentEncoderId()); - if (enc0 != nullptr && encoders_to_display_id_.count(enc0) == 0) { - int ret = TryEncoderForDisplay(display, enc0); - if (ret == 0) { - encoders_to_display_id_[enc0] = display; - return 0; - } - - if (ret != -EAGAIN) { - ALOGE("Could not set mode %d/%d", display, ret); - return ret; - } - } - - for (auto &enc : encoders_) { - if (!connector->SupportsEncoder(*enc) || - encoders_to_display_id_.count(enc.get()) != 0) { - continue; - } - - int ret = TryEncoderForDisplay(display, enc.get()); - if (ret == 0) { - encoders_to_display_id_[enc.get()] = display; - return 0; - } - - if (ret != -EAGAIN) { - ALOGE("Could not set mode %d/%d", display, ret); - return ret; +auto DrmDevice::GetDisplayId(DrmConnector *conn) -> int { + for (auto &dpipe : pipelines_) { + if (dpipe.second->connector->Get() == conn) { + return dpipe.first; } } - ALOGE("Could not find a suitable encoder/crtc for display %d", display); - return -ENODEV; + return -1; } auto DrmDevice::RegisterUserPropertyBlob(void *data, size_t length) const -- cgit v1.2.3