diff options
author | John Stultz <john.stultz@linaro.org> | 2021-08-25 18:39:06 +0000 |
---|---|---|
committer | John Stultz <john.stultz@linaro.org> | 2021-08-25 18:39:06 +0000 |
commit | 38163fdedc8600cb18c1b5dac2e12b3050565290 (patch) | |
tree | f710c50bff91decd514af8cd690aceb802a0e231 | |
parent | 82288efb3a5e9d08eed5f12b852e419f635c1bc9 (diff) | |
parent | 8514329f7e98dba60c396a8d0cab72daeb78e65e (diff) | |
download | drm_hwcomposer-38163fdedc8600cb18c1b5dac2e12b3050565290.tar.gz |
drm_hwcomposer: Merge remote-tracking branch 'aosp/upstream-main' into HEADandroid-s-beta-5android-s-beta-5
Just updates the branch to match upstream.
This merge contains a number of cleanups as well as
some follow-on fixups.
* aosp/upstream-main:
drm_hwcomposer: Don't close same handle several times.
drm_hwcomposer: Quiet noisy errors when planes don't support various attributes
drm_hwcomposer: Fix sync_file fd leak from "Rework audofd"
drm_hwcomposer: Add links to the HWC2 API description
drm_hwcomposer: Rework autofd
drm_hwcomposer: cleanup hwcutils
drm_hwcomposer: Stop importing native_handle_t into the mapper
drm_hwcomposer: Tracking of the DRM FB objects using RAII
Signed-off-by: John Stultz <john.stultz@linaro.org>
Change-Id: I9f733a6d9adb71b6c8b24d764e881904f66de146
-rw-r--r-- | .ci/.common.sh | 4 | ||||
-rwxr-xr-x | .ci/.gitlab-ci-clang-tidy-fine.sh | 2 | ||||
-rw-r--r-- | Android.bp | 2 | ||||
-rw-r--r-- | DrmHwcTwo.cpp | 61 | ||||
-rw-r--r-- | DrmHwcTwo.h | 45 | ||||
-rw-r--r-- | compositor/DrmDisplayComposition.cpp | 14 | ||||
-rw-r--r-- | compositor/DrmDisplayComposition.h | 12 | ||||
-rw-r--r-- | compositor/DrmDisplayCompositor.cpp | 8 | ||||
-rw-r--r-- | compositor/DrmDisplayCompositor.h | 9 | ||||
-rw-r--r-- | compositor/Planner.cpp | 4 | ||||
-rw-r--r-- | drm/DrmDevice.cpp | 15 | ||||
-rw-r--r-- | drm/DrmDevice.h | 21 | ||||
-rw-r--r-- | drm/DrmEventListener.cpp | 16 | ||||
-rw-r--r-- | drm/DrmEventListener.h | 2 | ||||
-rw-r--r-- | drm/DrmFbImporter.cpp | 154 | ||||
-rw-r--r-- | drm/DrmFbImporter.h | 94 | ||||
-rw-r--r-- | drm/DrmGenericImporter.cpp | 135 | ||||
-rw-r--r-- | drm/DrmGenericImporter.h | 72 | ||||
-rw-r--r-- | drm/DrmPlane.cpp | 2 | ||||
-rw-r--r-- | drm/ResourceManager.cpp | 21 | ||||
-rw-r--r-- | drm/ResourceManager.h | 4 | ||||
-rw-r--r-- | include/autofd.h | 106 | ||||
-rw-r--r-- | include/drmhwcgralloc.h | 3 | ||||
-rw-r--r-- | include/drmhwcomposer.h | 102 | ||||
-rw-r--r-- | utils/UniqueFd.h | 111 | ||||
-rw-r--r-- | utils/hwcutils.cpp | 104 |
26 files changed, 491 insertions, 632 deletions
diff --git a/.ci/.common.sh b/.ci/.common.sh index 93f7f95..0183aba 100644 --- a/.ci/.common.sh +++ b/.ci/.common.sh @@ -5,7 +5,7 @@ CLANG_TIDY="clang-tidy-11" 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+=" -fvisibility-inlines-hidden -std=gnu++17 -DHWC2_USE_CPP11 -DHWC2_INCLUDE_STRINGIFICATION -fexceptions -fno-rtti" +CXXARGS+=" -fvisibility-inlines-hidden -std=gnu++17 -DHWC2_USE_CPP11 -DHWC2_INCLUDE_STRINGIFICATION -fno-rtti" BUILD_FILES=( backend/BackendClient.cpp @@ -28,7 +28,7 @@ drm/DrmCrtc.cpp drm/DrmDevice.cpp drm/DrmEncoder.cpp drm/DrmEventListener.cpp -drm/DrmGenericImporter.cpp +drm/DrmFbImporter.cpp drm/DrmMode.cpp drm/DrmPlane.cpp drm/DrmProperty.cpp diff --git a/.ci/.gitlab-ci-clang-tidy-fine.sh b/.ci/.gitlab-ci-clang-tidy-fine.sh index 644f621..c1805e8 100755 --- a/.ci/.gitlab-ci-clang-tidy-fine.sh +++ b/.ci/.gitlab-ci-clang-tidy-fine.sh @@ -3,6 +3,8 @@ . ./.ci/.common.sh TIDY_FILES=( +drm/DrmFbImporter.h +utils/UniqueFd.h utils/log.h utils/properties.h ) @@ -113,7 +113,7 @@ cc_library_static { "drm/DrmDevice.cpp", "drm/DrmEncoder.cpp", "drm/DrmEventListener.cpp", - "drm/DrmGenericImporter.cpp", + "drm/DrmFbImporter.cpp", "drm/DrmMode.cpp", "drm/DrmPlane.cpp", "drm/DrmProperty.cpp", diff --git a/DrmHwcTwo.cpp b/DrmHwcTwo.cpp index 8b2abfd..02667cf 100644 --- a/DrmHwcTwo.cpp +++ b/DrmHwcTwo.cpp @@ -19,9 +19,11 @@ #include "DrmHwcTwo.h" +#include <fcntl.h> #include <hardware/hardware.h> #include <hardware/hwcomposer2.h> #include <sync/sync.h> +#include <unistd.h> #include <cinttypes> #include <iostream> @@ -47,14 +49,13 @@ DrmHwcTwo::DrmHwcTwo() : hwc2_device() { HWC2::Error DrmHwcTwo::CreateDisplay(hwc2_display_t displ, HWC2::DisplayType type) { DrmDevice *drm = resource_manager_.GetDrmDevice(displ); - std::shared_ptr<Importer> importer = resource_manager_.GetImporter(displ); - if (!drm || !importer) { - ALOGE("Failed to get a valid drmresource and importer"); + if (!drm) { + ALOGE("Failed to get a valid drmresource"); return HWC2::Error::NoResources; } displays_.emplace(std::piecewise_construct, std::forward_as_tuple(displ), - std::forward_as_tuple(&resource_manager_, drm, importer, - displ, type)); + std::forward_as_tuple(&resource_manager_, drm, displ, + type)); DrmCrtc *crtc = drm->GetCrtcForDisplay(static_cast<int>(displ)); if (!crtc) { @@ -209,12 +210,10 @@ HWC2::Error DrmHwcTwo::RegisterCallback(int32_t descriptor, } DrmHwcTwo::HwcDisplay::HwcDisplay(ResourceManager *resource_manager, - DrmDevice *drm, - std::shared_ptr<Importer> importer, - hwc2_display_t handle, HWC2::DisplayType type) + DrmDevice *drm, hwc2_display_t handle, + HWC2::DisplayType type) : resource_manager_(resource_manager), drm_(drm), - importer_(std::move(importer)), handle_(handle), type_(type), color_transform_hint_(HAL_COLOR_TRANSFORM_IDENTITY) { @@ -583,6 +582,9 @@ HWC2::Error DrmHwcTwo::HwcDisplay::GetHdrCapabilities( return HWC2::Error::None; } +/* Find API details at: + * https://cs.android.com/android/platform/superproject/+/android-11.0.0_r3:hardware/libhardware/include/hardware/hwcomposer2.h;l=1767 + */ HWC2::Error DrmHwcTwo::HwcDisplay::GetReleaseFences(uint32_t *num_elements, hwc2_layer_t *layers, int32_t *fences) { @@ -600,22 +602,22 @@ HWC2::Error DrmHwcTwo::HwcDisplay::GetReleaseFences(uint32_t *num_elements, } layers[num_layers - 1] = l.first; - fences[num_layers - 1] = l.second.take_release_fence(); + fences[num_layers - 1] = l.second.release_fence_.Release(); } *num_elements = num_layers; return HWC2::Error::None; } -void DrmHwcTwo::HwcDisplay::AddFenceToPresentFence(int fd) { - if (fd < 0) +void DrmHwcTwo::HwcDisplay::AddFenceToPresentFence(UniqueFd fd) { + if (!fd) { return; + } - if (present_fence_.get() >= 0) { - int old_fence = present_fence_.get(); - present_fence_.Set(sync_merge("dc_present", old_fence, fd)); - close(fd); + if (present_fence_) { + present_fence_ = UniqueFd( + sync_merge("dc_present", present_fence_.Get(), fd.Get())); } else { - present_fence_.Set(fd); + present_fence_ = std::move(fd); } } @@ -650,7 +652,7 @@ HWC2::Error DrmHwcTwo::HwcDisplay::CreateComposition(bool test) { for (std::pair<const uint32_t, DrmHwcTwo::HwcLayer *> &l : z_map) { DrmHwcLayer layer; l.second->PopulateDrmLayer(&layer); - int ret = layer.ImportBuffer(importer_.get()); + int ret = layer.ImportBuffer(drm_); if (ret) { ALOGE("Failed to import layer, ret=%d", ret); return HWC2::Error::NoResources; @@ -673,7 +675,7 @@ HWC2::Error DrmHwcTwo::HwcDisplay::CreateComposition(bool test) { std::vector<DrmPlane *> overlay_planes(overlay_planes_); ret = composition->Plan(&primary_planes, &overlay_planes); if (ret) { - ALOGE("Failed to plan the composition ret=%d", ret); + ALOGV("Failed to plan the composition ret=%d", ret); return HWC2::Error::BadConfig; } @@ -701,6 +703,9 @@ HWC2::Error DrmHwcTwo::HwcDisplay::CreateComposition(bool test) { return HWC2::Error::None; } +/* Find API details at: + * https://cs.android.com/android/platform/superproject/+/android-11.0.0_r3:hardware/libhardware/include/hardware/hwcomposer2.h;l=1805 + */ HWC2::Error DrmHwcTwo::HwcDisplay::PresentDisplay(int32_t *present_fence) { supported(__func__); HWC2::Error ret; @@ -761,15 +766,17 @@ HWC2::Error DrmHwcTwo::HwcDisplay::SetActiveConfig(hwc2_config_t config) { return HWC2::Error::None; } +/* Find API details at: + * https://cs.android.com/android/platform/superproject/+/android-11.0.0_r3:hardware/libhardware/include/hardware/hwcomposer2.h;l=1861 + */ HWC2::Error DrmHwcTwo::HwcDisplay::SetClientTarget(buffer_handle_t target, int32_t acquire_fence, int32_t dataspace, hwc_region_t /*damage*/) { supported(__func__); - UniqueFd uf(acquire_fence); client_layer_.set_buffer(target); - client_layer_.set_acquire_fence(uf.get()); + client_layer_.acquire_fence_ = UniqueFd(acquire_fence); client_layer_.SetLayerDataspace(dataspace); /* TODO: Do not update source_crop every call. @@ -1047,13 +1054,15 @@ HWC2::Error DrmHwcTwo::HwcLayer::SetLayerBlendMode(int32_t mode) { return HWC2::Error::None; } +/* Find API details at: + * https://cs.android.com/android/platform/superproject/+/android-11.0.0_r3:hardware/libhardware/include/hardware/hwcomposer2.h;l=2314 + */ HWC2::Error DrmHwcTwo::HwcLayer::SetLayerBuffer(buffer_handle_t buffer, int32_t acquire_fence) { supported(__func__); - UniqueFd uf(acquire_fence); set_buffer(buffer); - set_acquire_fence(uf.get()); + acquire_fence_ = UniqueFd(acquire_fence); return HWC2::Error::None; } @@ -1144,11 +1153,9 @@ void DrmHwcTwo::HwcLayer::PopulateDrmLayer(DrmHwcLayer *layer) { break; } - OutputFd release_fence = release_fence_output(); - layer->sf_handle = buffer_; - layer->acquire_fence = acquire_fence_.Release(); - layer->release_fence = std::move(release_fence); + // TODO(rsglobal): Avoid extra fd duplication + layer->acquire_fence = UniqueFd(fcntl(acquire_fence_.Get(), F_DUPFD_CLOEXEC)); layer->display_frame = display_frame_; layer->alpha = lround(65535.0F * alpha_); layer->source_crop = source_crop_; diff --git a/DrmHwcTwo.h b/DrmHwcTwo.h index a0d8cdd..111c664 100644 --- a/DrmHwcTwo.h +++ b/DrmHwcTwo.h @@ -25,7 +25,6 @@ #include "compositor/DrmDisplayCompositor.h" #include "compositor/Planner.h" -#include "drm/DrmGenericImporter.h" #include "drm/ResourceManager.h" #include "drm/VSyncWorker.h" #include "drmhwcomposer.h" @@ -83,27 +82,6 @@ class DrmHwcTwo : public hwc2_device_t { buffer_ = buffer; } - int take_acquire_fence() { - return acquire_fence_.Release(); - } - void set_acquire_fence(int acquire_fence) { - acquire_fence_.Set(dup(acquire_fence)); - } - - int release_fence() { - return release_fence_.get(); - } - int take_release_fence() { - return release_fence_.Release(); - } - void manage_release_fence() { - release_fence_.Set(release_fence_raw_); - release_fence_raw_ = -1; - } - OutputFd release_fence_output() { - return OutputFd(&release_fence_raw_); - } - hwc_rect_t display_frame() { return display_frame_; } @@ -139,6 +117,16 @@ class DrmHwcTwo : public hwc2_device_t { HWC2::Error SetLayerVisibleRegion(hwc_region_t visible); HWC2::Error SetLayerZOrder(uint32_t order); + UniqueFd acquire_fence_; + + /* + * Release fence is not used. + * There is no release fence support available in the DRM/KMS. In case no + * release fence provided application will use this buffer for writing when + * the next frame present fence is signaled. + */ + UniqueFd release_fence_; + private: // sf_type_ stores the initial type given to us by surfaceflinger, // validated_type_ stores the type after running ValidateDisplay @@ -147,9 +135,6 @@ class DrmHwcTwo : public hwc2_device_t { HWC2::BlendMode blending_ = HWC2::BlendMode::None; buffer_handle_t buffer_ = NULL; - UniqueFd acquire_fence_; - int release_fence_raw_ = -1; - UniqueFd release_fence_; hwc_rect_t display_frame_; float alpha_ = 1.0f; hwc_frect_t source_crop_; @@ -164,8 +149,7 @@ class DrmHwcTwo : public hwc2_device_t { class HwcDisplay { public: HwcDisplay(ResourceManager *resource_manager, DrmDevice *drm, - std::shared_ptr<Importer> importer, hwc2_display_t handle, - HWC2::DisplayType type); + hwc2_display_t handle, HWC2::DisplayType type); HwcDisplay(const HwcDisplay &) = delete; HWC2::Error Init(std::vector<DrmPlane *> *planes); @@ -305,10 +289,6 @@ class DrmHwcTwo : public hwc2_device_t { return connector_; } - const std::shared_ptr<Importer> &importer() const { - return importer_; - } - ResourceManager *resource_manager() const { return resource_manager_; } @@ -322,14 +302,13 @@ class DrmHwcTwo : public hwc2_device_t { } private: - void AddFenceToPresentFence(int fd); + void AddFenceToPresentFence(UniqueFd fd); constexpr static size_t MATRIX_SIZE = 16; ResourceManager *resource_manager_; DrmDevice *drm_; DrmDisplayCompositor compositor_; - std::shared_ptr<Importer> importer_; std::unique_ptr<Planner> planner_; std::vector<DrmPlane *> primary_planes_; diff --git a/compositor/DrmDisplayComposition.cpp b/compositor/DrmDisplayComposition.cpp index 7008e9c..49dff0e 100644 --- a/compositor/DrmDisplayComposition.cpp +++ b/compositor/DrmDisplayComposition.cpp @@ -101,7 +101,7 @@ int DrmDisplayComposition::Plan(std::vector<DrmPlane *> *primary_planes, primary_planes, overlay_planes); if (ret) { - ALOGE("Planner failed provisioning planes ret=%d", ret); + ALOGV("Planner failed provisioning planes ret=%d", ret); return ret; } @@ -156,14 +156,10 @@ static const char *DPMSModeToString(int dpms_mode) { } } -static void DumpBuffer(const DrmHwcBuffer &buffer, std::ostringstream *out) { - if (!buffer) { - *out << "buffer=<invalid>"; - return; - } - +static void DumpBuffer(const DrmHwcLayer &layer, std::ostringstream *out) { *out << "buffer[w/h/format]="; - *out << buffer->width << "/" << buffer->height << "/" << buffer->format; + *out << layer.buffer_info.width << "/" << layer.buffer_info.height << "/" + << layer.buffer_info.format; } static void DumpTransform(uint32_t transform, std::ostringstream *out) { @@ -249,7 +245,7 @@ void DrmDisplayComposition::Dump(std::ostringstream *out) const { const DrmHwcLayer &layer = layers_[i]; *out << " [" << i << "] "; - DumpBuffer(layer.buffer, out); + DumpBuffer(layer, out); if (layer.protected_usage()) *out << " protected"; diff --git a/compositor/DrmDisplayComposition.h b/compositor/DrmDisplayComposition.h index 27b34f2..1738630 100644 --- a/compositor/DrmDisplayComposition.h +++ b/compositor/DrmDisplayComposition.h @@ -127,16 +127,10 @@ class DrmDisplayComposition { return planner_; } - int take_out_fence() { - return out_fence_.Release(); - } - - void set_out_fence(int out_fence) { - out_fence_.Set(out_fence); - } - void Dump(std::ostringstream *out) const; + UniqueFd out_fence_; + private: bool validate_composition_type(DrmCompositionType desired); @@ -147,8 +141,6 @@ class DrmDisplayComposition { uint32_t dpms_mode_ = DRM_MODE_DPMS_ON; DrmMode display_mode_; - UniqueFd out_fence_ = -1; - bool geometry_changed_ = true; std::vector<DrmHwcLayer> layers_; std::vector<DrmCompositionPlane> composition_planes_; diff --git a/compositor/DrmDisplayCompositor.cpp b/compositor/DrmDisplayCompositor.cpp index 665446e..a1fe50f 100644 --- a/compositor/DrmDisplayCompositor.cpp +++ b/compositor/DrmDisplayCompositor.cpp @@ -286,12 +286,12 @@ int DrmDisplayCompositor::CommitFrame(DrmDisplayComposition *display_comp, break; } DrmHwcLayer &layer = layers[source_layers.front()]; - if (!layer.buffer) { + if (!layer.FbIdHandle) { ALOGE("Expected a valid framebuffer for pset"); break; } - fb_id = layer.buffer->fb_id; - fence_fd = layer.acquire_fence.get(); + fb_id = layer.FbIdHandle->GetFbId(); + fence_fd = layer.acquire_fence.Get(); display_frame = layer.display_frame; source_crop = layer.source_crop; alpha = layer.alpha; @@ -540,7 +540,7 @@ int DrmDisplayCompositor::CommitFrame(DrmDisplayComposition *display_comp, } if (crtc->out_fence_ptr_property().id()) { - display_comp->set_out_fence((int)out_fences[crtc->pipe()]); + display_comp->out_fence_ = UniqueFd((int)out_fences[crtc->pipe()]); } return ret; diff --git a/compositor/DrmDisplayCompositor.h b/compositor/DrmDisplayCompositor.h index aebb6ff..c0eed0c 100644 --- a/compositor/DrmDisplayCompositor.h +++ b/compositor/DrmDisplayCompositor.h @@ -72,10 +72,11 @@ class DrmDisplayCompositor { void Dump(std::ostringstream *out) const; void Vsync(int display, int64_t timestamp); void ClearDisplay(); - int TakeOutFence() { - if (!active_composition_) - return -1; - return active_composition_->take_out_fence(); + UniqueFd TakeOutFence() { + if (!active_composition_) { + return UniqueFd(); + } + return std::move(active_composition_->out_fence_); } FlatteningState GetFlatteningState() const; diff --git a/compositor/Planner.cpp b/compositor/Planner.cpp index 42259d1..9db03c3 100644 --- a/compositor/Planner.cpp +++ b/compositor/Planner.cpp @@ -60,7 +60,7 @@ std::tuple<int, std::vector<DrmCompositionPlane>> Planner::ProvisionPlanes( for (auto &i : stages_) { int ret = i->ProvisionPlanes(&composition, layers, &planes); if (ret) { - ALOGE("Failed provision stage with ret %d", ret); + ALOGV("Failed provision stage with ret %d", ret); return std::make_tuple(ret, std::vector<DrmCompositionPlane>()); } } @@ -105,7 +105,7 @@ int PlanStageGreedy::ProvisionPlanes( break; if (ret) { - ALOGE("Failed to emplace layer %zu, dropping it", i->first); + ALOGV("Failed to emplace layer %zu, dropping it", i->first); return ret; } } diff --git a/drm/DrmDevice.cpp b/drm/DrmDevice.cpp index 150aa01..abc8edc 100644 --- a/drm/DrmDevice.cpp +++ b/drm/DrmDevice.cpp @@ -112,6 +112,8 @@ static std::vector<DrmConnector *> make_primary_display_candidates( } DrmDevice::DrmDevice() : event_listener_(this) { + self.reset(this); + mDrmFbImporter = std::make_unique<DrmFbImporter>(self); } DrmDevice::~DrmDevice() { @@ -120,7 +122,7 @@ DrmDevice::~DrmDevice() { std::tuple<int, int> DrmDevice::Init(const char *path, int num_displays) { /* TODO: Use drmOpenControl here instead */ - fd_.Set(open(path, O_RDWR | O_CLOEXEC)); + fd_ = UniqueFd(open(path, O_RDWR | O_CLOEXEC)); if (fd() < 0) { ALOGE("Failed to open dri %s: %s", path, strerror(errno)); return std::make_tuple(-ENODEV, 0); @@ -146,6 +148,13 @@ std::tuple<int, int> DrmDevice::Init(const char *path, int num_displays) { } #endif + uint64_t cap_value = 0; + if (drmGetCap(fd(), DRM_CAP_ADDFB2_MODIFIERS, &cap_value)) { + ALOGW("drmGetCap failed. Fallback to no modifier support."); + cap_value = 0; + } + HasAddFb2ModifiersSupport_ = cap_value != 0; + drmSetMaster(fd()); if (!drmIsMaster(fd())) { ALOGE("DRM/KMS master access required"); @@ -576,9 +585,9 @@ int DrmDevice::GetConnectorProperty(const DrmConnector &connector, } std::string DrmDevice::GetName() const { - auto *ver = drmGetVersion(fd_.get()); + auto *ver = drmGetVersion(fd()); if (!ver) { - ALOGW("Failed to get drm version for fd=%d", fd_.get()); + ALOGW("Failed to get drm version for fd=%d", fd()); return "generic"; } diff --git a/drm/DrmDevice.h b/drm/DrmDevice.h index d8f347f..dfca263 100644 --- a/drm/DrmDevice.h +++ b/drm/DrmDevice.h @@ -26,10 +26,15 @@ #include "DrmCrtc.h" #include "DrmEncoder.h" #include "DrmEventListener.h" +#include "DrmFbImporter.h" #include "DrmPlane.h" +#include "utils/UniqueFd.h" namespace android { +class DrmFbImporter; +class DrmPlane; + class DrmDevice { public: DrmDevice(); @@ -38,7 +43,7 @@ class DrmDevice { std::tuple<int, int> Init(const char *path, int num_displays); int fd() const { - return fd_.get(); + return fd_.Get(); } const std::vector<std::unique_ptr<DrmConnector>> &connectors() const { @@ -83,6 +88,14 @@ class DrmDevice { event_listener_.RegisterHotplugHandler(handler); } + bool HasAddFb2ModifiersSupport() const { + return HasAddFb2ModifiersSupport_; + } + + DrmFbImporter &GetDrmFbImporter() { + return *mDrmFbImporter.get(); + } + private: int TryEncoderForDisplay(int display, DrmEncoder *enc); int GetProperty(uint32_t obj_id, uint32_t obj_type, const char *prop_name, @@ -104,6 +117,12 @@ class DrmDevice { std::pair<uint32_t, uint32_t> min_resolution_; std::pair<uint32_t, uint32_t> max_resolution_; std::map<int, int> displays_; + + bool HasAddFb2ModifiersSupport_{}; + + std::shared_ptr<DrmDevice> self; + + std::unique_ptr<DrmFbImporter> mDrmFbImporter; }; } // namespace android diff --git a/drm/DrmEventListener.cpp b/drm/DrmEventListener.cpp index a6eee47..b303653 100644 --- a/drm/DrmEventListener.cpp +++ b/drm/DrmEventListener.cpp @@ -39,11 +39,11 @@ DrmEventListener::DrmEventListener(DrmDevice *drm) } int DrmEventListener::Init() { - uevent_fd_.Set( + uevent_fd_ = UniqueFd( socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT)); - if (uevent_fd_.get() < 0) { + if (!uevent_fd_) { ALOGE("Failed to open uevent socket: %s", strerror(errno)); - return uevent_fd_.get(); + return -errno; } struct sockaddr_nl addr {}; @@ -51,7 +51,7 @@ int DrmEventListener::Init() { addr.nl_pid = 0; addr.nl_groups = 0xFFFFFFFF; - int ret = bind(uevent_fd_.get(), (struct sockaddr *)&addr, sizeof(addr)); + int ret = bind(uevent_fd_.Get(), (struct sockaddr *)&addr, sizeof(addr)); if (ret) { ALOGE("Failed to bind uevent socket: %s", strerror(errno)); return -errno; @@ -60,8 +60,8 @@ int DrmEventListener::Init() { // 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()); + FD_SET(uevent_fd_.Get(), &fds_); + max_fd_ = std::max(drm_->fd(), uevent_fd_.Get()); return InitWorker(); } @@ -96,7 +96,7 @@ void DrmEventListener::UEventHandler() { ALOGE("Failed to get monotonic clock on hotplug %d", ret); while (true) { - ret = read(uevent_fd_.get(), &buffer, sizeof(buffer)); + ret = read(uevent_fd_.Get(), &buffer, sizeof(buffer)); if (ret == 0) return; @@ -139,7 +139,7 @@ void DrmEventListener::Routine() { drmHandleEvent(drm_->fd(), &event_context); } - if (FD_ISSET(uevent_fd_.get(), &fds_)) + if (FD_ISSET(uevent_fd_.Get(), &fds_)) UEventHandler(); } } // namespace android diff --git a/drm/DrmEventListener.h b/drm/DrmEventListener.h index c880a8c..f1f7310 100644 --- a/drm/DrmEventListener.h +++ b/drm/DrmEventListener.h @@ -17,7 +17,7 @@ #ifndef ANDROID_DRM_EVENT_LISTENER_H_ #define ANDROID_DRM_EVENT_LISTENER_H_ -#include "autofd.h" +#include "utils/UniqueFd.h" #include "utils/Worker.h" namespace android { diff --git a/drm/DrmFbImporter.cpp b/drm/DrmFbImporter.cpp new file mode 100644 index 0000000..8440093 --- /dev/null +++ b/drm/DrmFbImporter.cpp @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define LOG_TAG "hwc-platform-drm-generic" + +#include "DrmFbImporter.h" + +#include <hardware/gralloc.h> +#include <xf86drm.h> +#include <xf86drmMode.h> + +#include <cinttypes> +#include <system_error> + +#include "utils/log.h" +#include "utils/properties.h" + +namespace android { + +auto DrmFbIdHandle::CreateInstance(hwc_drm_bo_t *bo, GemHandle first_gem_handle, + const std::shared_ptr<DrmDevice> &drm) + -> std::shared_ptr<DrmFbIdHandle> { + // NOLINTNEXTLINE(cppcoreguidelines-owning-memory): priv. constructor usage + std::shared_ptr<DrmFbIdHandle> local(new DrmFbIdHandle(drm)); + + local->gem_handles_[0] = 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++) { + if (bo->prime_fds[i] > 0) { + if (bo->prime_fds[i] != bo->prime_fds[0]) { + err = drmPrimeFDToHandle(drm->fd(), bo->prime_fds[i], + &local->gem_handles_.at(i)); + if (err != 0) { + ALOGE("failed to import prime fd %d errno=%d", bo->prime_fds[i], + errno); + } + } else { + local->gem_handles_.at(i) = local->gem_handles_[0]; + } + } + } + + bool has_modifiers = bo->modifiers[0] != DRM_FORMAT_MOD_NONE && + bo->modifiers[0] != DRM_FORMAT_MOD_INVALID; + + if (!drm->HasAddFb2ModifiersSupport() && has_modifiers) { + ALOGE("No ADDFB2 with modifier support. Can't import modifier %" PRIu64, + bo->modifiers[0]); + local.reset(); + return local; + } + + /* Create framebuffer object */ + if (!has_modifiers) { + err = drmModeAddFB2(drm->fd(), bo->width, bo->height, bo->format, + &local->gem_handles_[0], &bo->pitches[0], + &bo->offsets[0], &local->fb_id_, 0); + } else { + err = drmModeAddFB2WithModifiers(drm->fd(), bo->width, bo->height, + bo->format, &local->gem_handles_[0], + &bo->pitches[0], &bo->offsets[0], + &bo->modifiers[0], &local->fb_id_, + DRM_MODE_FB_MODIFIERS); + } + if (err != 0) { + ALOGE("could not create drm fb %d", err); + local.reset(); + } + + return local; +} + +DrmFbIdHandle::~DrmFbIdHandle() { + /* Destroy framebuffer object */ + if (drmModeRmFB(drm_->fd(), fb_id_) != 0) { + ALOGE("Failed to rm fb"); + } + + /* Close GEM handles. + * + * WARNING: TODO(nobody): + * From Linux side libweston relies on libgbm to get KMS handle and never + * closes it (handle is closed by libgbm on buffer destruction) + * Probably we should offer similar approach to users (at least on user + * request via system properties) + */ + struct drm_gem_close gem_close {}; + for (int 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 || + (i != 0 && gem_handles_[i] == gem_handles_[0])) { + continue; + } + gem_close.handle = gem_handles_[i]; + int32_t err = drmIoctl(drm_->fd(), DRM_IOCTL_GEM_CLOSE, &gem_close); + if (err != 0) { + ALOGE("Failed to close gem handle %d, errno: %d", gem_handles_[i], errno); + } + } +} + +auto DrmFbImporter::GetOrCreateFbId(hwc_drm_bo_t *bo) + -> std::shared_ptr<DrmFbIdHandle> { + /* Lookup DrmFbIdHandle in cache first. First handle serves as a cache key. */ + GemHandle first_handle = 0; + int32_t err = drmPrimeFDToHandle(drm_->fd(), bo->prime_fds[0], &first_handle); + + if (err != 0) { + ALOGE("Failed to import prime fd %d ret=%d", bo->prime_fds[0], err); + return std::shared_ptr<DrmFbIdHandle>(); + } + + auto drm_fb_id_cached = drm_fb_id_handle_cache_.find(first_handle); + + if (drm_fb_id_cached != drm_fb_id_handle_cache_.end()) { + if (auto drm_fb_id_handle_shared = drm_fb_id_cached->second.lock()) { + return drm_fb_id_handle_shared; + } + drm_fb_id_handle_cache_.erase(drm_fb_id_cached); + } + + /* Cleanup cached empty weak pointers */ + const int minimal_cleanup_size = 128; + if (drm_fb_id_handle_cache_.size() > minimal_cleanup_size) { + CleanupEmptyCacheElements(); + } + + /* No DrmFbIdHandle found in cache, create framebuffer object */ + auto fb_id_handle = DrmFbIdHandle::CreateInstance(bo, first_handle, drm_); + if (fb_id_handle) { + drm_fb_id_handle_cache_[first_handle] = fb_id_handle; + } + + return fb_id_handle; +} + +} // namespace android diff --git a/drm/DrmFbImporter.h b/drm/DrmFbImporter.h new file mode 100644 index 0000000..167aa60 --- /dev/null +++ b/drm/DrmFbImporter.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DRM_DRMFBIMPORTER_H_ +#define DRM_DRMFBIMPORTER_H_ + +#include <drm/drm_fourcc.h> +#include <hardware/gralloc.h> + +#include <array> +#include <map> + +#include "drm/DrmDevice.h" +#include "drmhwcgralloc.h" + +#ifndef DRM_FORMAT_INVALID +#define DRM_FORMAT_INVALID 0 +#endif + +using GemHandle = uint32_t; + +namespace android { + +class DrmFbIdHandle { + public: + static auto CreateInstance(hwc_drm_bo_t *bo, GemHandle first_gem_handle, + const std::shared_ptr<DrmDevice> &drm) + -> std::shared_ptr<DrmFbIdHandle>; + + ~DrmFbIdHandle(); + DrmFbIdHandle(DrmFbIdHandle &&) = delete; + DrmFbIdHandle(const DrmFbIdHandle &) = delete; + auto operator=(const DrmFbIdHandle &) = delete; + auto operator=(DrmFbIdHandle &&) = delete; + + auto GetFbId [[nodiscard]] () const -> uint32_t { + return fb_id_; + } + + private: + explicit DrmFbIdHandle(std::shared_ptr<DrmDevice> drm) + : drm_(std::move(drm)){}; + + const std::shared_ptr<DrmDevice> drm_; + + uint32_t fb_id_{}; + std::array<GemHandle, HWC_DRM_BO_MAX_PLANES> gem_handles_{}; +}; + +class DrmFbImporter { + public: + explicit DrmFbImporter(std::shared_ptr<DrmDevice> drm) + : drm_(std::move(drm)){}; + ~DrmFbImporter() = default; + DrmFbImporter(const DrmFbImporter &) = delete; + DrmFbImporter(DrmFbImporter &&) = delete; + auto operator=(const DrmFbImporter &) = delete; + auto operator=(DrmFbImporter &&) = delete; + + auto GetOrCreateFbId(hwc_drm_bo_t *bo) -> std::shared_ptr<DrmFbIdHandle>; + + private: + void CleanupEmptyCacheElements() { + for (auto it = drm_fb_id_handle_cache_.begin(); + it != drm_fb_id_handle_cache_.end();) { + if (it->second.expired()) { + it = drm_fb_id_handle_cache_.erase(it); + } else { + ++it; + } + } + } + + const std::shared_ptr<DrmDevice> drm_; + + std::map<GemHandle, std::weak_ptr<DrmFbIdHandle>> drm_fb_id_handle_cache_; +}; + +} // namespace android + +#endif diff --git a/drm/DrmGenericImporter.cpp b/drm/DrmGenericImporter.cpp deleted file mode 100644 index 0cbe601..0000000 --- a/drm/DrmGenericImporter.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "hwc-platform-drm-generic" - -#include "DrmGenericImporter.h" - -#include <gralloc_handle.h> -#include <hardware/gralloc.h> -#include <xf86drm.h> -#include <xf86drmMode.h> - -#include <cinttypes> - -#include "utils/log.h" -#include "utils/properties.h" - -namespace android { - -DrmGenericImporter::DrmGenericImporter(DrmDevice *drm) : drm_(drm) { - uint64_t cap_value = 0; - if (drmGetCap(drm_->fd(), DRM_CAP_ADDFB2_MODIFIERS, &cap_value)) { - ALOGE("drmGetCap failed. Fallback to no modifier support."); - cap_value = 0; - } - has_modifier_support_ = cap_value != 0; -} - -int DrmGenericImporter::ImportBuffer(hwc_drm_bo_t *bo) { - int ret = 0; - - for (int i = 0; i < HWC_DRM_BO_MAX_PLANES; i++) { - if (bo->prime_fds[i] > 0) { - if (i == 0 || bo->prime_fds[i] != bo->prime_fds[0]) { - ret = drmPrimeFDToHandle(drm_->fd(), bo->prime_fds[i], - &bo->gem_handles[i]); - if (ret) { - ALOGE("failed to import prime fd %d ret=%d", bo->prime_fds[i], ret); - return ret; - } - } else { - bo->gem_handles[i] = bo->gem_handles[0]; - } - } - } - - bool has_modifiers = bo->modifiers[0] != DRM_FORMAT_MOD_NONE && - bo->modifiers[0] != DRM_FORMAT_MOD_INVALID; - - if (!has_modifier_support_ && has_modifiers) { - ALOGE("No ADDFB2 with modifier support. Can't import modifier %" PRIu64, - bo->modifiers[0]); - return -EINVAL; - } - - if (!has_modifiers) - ret = drmModeAddFB2(drm_->fd(), bo->width, bo->height, bo->format, - bo->gem_handles, bo->pitches, bo->offsets, &bo->fb_id, - 0); - else - ret = drmModeAddFB2WithModifiers(drm_->fd(), bo->width, bo->height, - bo->format, bo->gem_handles, bo->pitches, - bo->offsets, bo->modifiers, &bo->fb_id, - DRM_MODE_FB_MODIFIERS); - - if (ret) { - ALOGE("could not create drm fb %d", ret); - return ret; - } - - for (unsigned int gem_handle : bo->gem_handles) { - if (!gem_handle) - continue; - - ImportHandle(gem_handle); - } - - return ret; -} - -int DrmGenericImporter::ReleaseBuffer(hwc_drm_bo_t *bo) { - if (bo->fb_id) - if (drmModeRmFB(drm_->fd(), bo->fb_id)) - ALOGE("Failed to rm fb"); - - for (unsigned int &gem_handle : bo->gem_handles) { - if (!gem_handle) - continue; - - if (ReleaseHandle(gem_handle)) - ALOGE("Failed to release gem handle %d", gem_handle); - else - gem_handle = 0; - } - return 0; -} - -int DrmGenericImporter::ImportHandle(uint32_t gem_handle) { - gem_refcount_[gem_handle]++; - - return 0; -} - -int DrmGenericImporter::ReleaseHandle(uint32_t gem_handle) { - if (--gem_refcount_[gem_handle]) - return 0; - - gem_refcount_.erase(gem_handle); - - return CloseHandle(gem_handle); -} - -int DrmGenericImporter::CloseHandle(uint32_t gem_handle) { - struct drm_gem_close gem_close {}; - gem_close.handle = gem_handle; - int ret = drmIoctl(drm_->fd(), DRM_IOCTL_GEM_CLOSE, &gem_close); - if (ret) - ALOGE("Failed to close gem handle %d %d", gem_handle, ret); - - return ret; -} -} // namespace android diff --git a/drm/DrmGenericImporter.h b/drm/DrmGenericImporter.h deleted file mode 100644 index 27cfc3b..0000000 --- a/drm/DrmGenericImporter.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_PLATFORM_DRM_GENERIC_H_ -#define ANDROID_PLATFORM_DRM_GENERIC_H_ - -#include <drm/drm_fourcc.h> -#include <hardware/gralloc.h> - -#include <map> - -#include "drm/DrmDevice.h" -#include "drmhwcgralloc.h" - -#ifndef DRM_FORMAT_INVALID -#define DRM_FORMAT_INVALID 0 -#endif - -namespace android { - -class Importer { - public: - virtual ~Importer() = default; - - // Imports the buffer referred to by handle into bo. - // - // Note: This can be called from a different thread than ReleaseBuffer. The - // implementation is responsible for ensuring thread safety. - virtual int ImportBuffer(hwc_drm_bo_t *bo) = 0; - - // Releases the buffer object (ie: does the inverse of ImportBuffer) - // - // Note: This can be called from a different thread than ImportBuffer. The - // implementation is responsible for ensuring thread safety. - virtual int ReleaseBuffer(hwc_drm_bo_t *bo) = 0; -}; - -class DrmGenericImporter : public Importer { - public: - DrmGenericImporter(DrmDevice *drm); - ~DrmGenericImporter() override = default; - - int ImportBuffer(hwc_drm_bo_t *bo) override; - int ReleaseBuffer(hwc_drm_bo_t *bo) override; - int ImportHandle(uint32_t gem_handle); - int ReleaseHandle(uint32_t gem_handle); - - protected: - DrmDevice *drm_; - - private: - int CloseHandle(uint32_t gem_handle); - std::map<uint32_t, int> gem_refcount_; - bool has_modifier_support_; -}; - -} // namespace android - -#endif diff --git a/drm/DrmPlane.cpp b/drm/DrmPlane.cpp index 5443e7e..6433fb6 100644 --- a/drm/DrmPlane.cpp +++ b/drm/DrmPlane.cpp @@ -231,7 +231,7 @@ bool DrmPlane::IsValidForLayer(DrmHwcLayer *layer) { } } - uint32_t format = layer->buffer->format; + uint32_t format = layer->buffer_info.format; if (!IsFormatSupported(format)) { ALOGV("Plane %d does not supports %c%c%c%c format", id_, format, format >> 8, format >> 16, format >> 24); diff --git a/drm/ResourceManager.cpp b/drm/ResourceManager.cpp index f8e9cab..ef44180 100644 --- a/drm/ResourceManager.cpp +++ b/drm/ResourceManager.cpp @@ -74,20 +74,11 @@ int ResourceManager::Init() { (const hw_module_t **)&gralloc_); } -int ResourceManager::AddDrmDevice(std::string const &path) { - std::unique_ptr<DrmDevice> drm = std::make_unique<DrmDevice>(); +int ResourceManager::AddDrmDevice(const std::string &path) { + auto drm = std::make_unique<DrmDevice>(); int displays_added = 0; int ret = 0; std::tie(ret, displays_added) = drm->Init(path.c_str(), num_displays_); - if (ret) - return ret; - std::shared_ptr<Importer> importer; - importer = std::make_shared<DrmGenericImporter>(drm.get()); - if (!importer) { - ALOGE("Failed to create importer instance"); - return -ENODEV; - } - importers_.push_back(importer); drms_.push_back(std::move(drm)); num_displays_ += displays_added; return ret; @@ -139,14 +130,6 @@ DrmDevice *ResourceManager::GetDrmDevice(int display) { return nullptr; } -std::shared_ptr<Importer> ResourceManager::GetImporter(int display) { - for (unsigned int i = 0; i < drms_.size(); i++) { - if (drms_[i]->HandlesDisplay(display)) - return importers_[i]; - } - return nullptr; -} - const gralloc_module_t *ResourceManager::gralloc() { return gralloc_; } diff --git a/drm/ResourceManager.h b/drm/ResourceManager.h index fca6e1f..9b4155b 100644 --- a/drm/ResourceManager.h +++ b/drm/ResourceManager.h @@ -20,7 +20,7 @@ #include <string.h> #include "DrmDevice.h" -#include "DrmGenericImporter.h" +#include "DrmFbImporter.h" namespace android { @@ -31,7 +31,6 @@ class ResourceManager { ResourceManager &operator=(const ResourceManager &) = delete; int Init(); DrmDevice *GetDrmDevice(int display); - std::shared_ptr<Importer> GetImporter(int display); const gralloc_module_t *gralloc(); DrmConnector *AvailableWritebackConnector(int display); const std::vector<std::unique_ptr<DrmDevice>> &getDrmDevices() const { @@ -50,7 +49,6 @@ class ResourceManager { int num_displays_; std::vector<std::unique_ptr<DrmDevice>> drms_; - std::vector<std::shared_ptr<Importer>> importers_; const gralloc_module_t *gralloc_; bool scale_with_gpu_{}; diff --git a/include/autofd.h b/include/autofd.h deleted file mode 100644 index 9af6c22..0000000 --- a/include/autofd.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_AUTO_FD_H_ -#define ANDROID_AUTO_FD_H_ - -#include <unistd.h> - -namespace android { - -class UniqueFd { - public: - UniqueFd() = default; - UniqueFd(int fd) : fd_(fd) { - } - UniqueFd(UniqueFd &&rhs) { - fd_ = rhs.fd_; - rhs.fd_ = -1; - } - - UniqueFd &operator=(UniqueFd &&rhs) { - Set(rhs.Release()); - return *this; - } - - ~UniqueFd() { - if (fd_ >= 0) - close(fd_); - } - - int Release() { - int old_fd = fd_; - fd_ = -1; - return old_fd; - } - - int Set(int fd) { - if (fd_ >= 0) - close(fd_); - fd_ = fd; - return fd_; - } - - void Close() { - if (fd_ >= 0) - close(fd_); - fd_ = -1; - } - - int get() const { - return fd_; - } - - private: - int fd_ = -1; -}; - -struct OutputFd { - OutputFd() = default; - OutputFd(int *fd) : fd_(fd) { - } - OutputFd(OutputFd &&rhs) { - fd_ = rhs.fd_; - rhs.fd_ = NULL; - } - - OutputFd &operator=(OutputFd &&rhs) { - fd_ = rhs.fd_; - rhs.fd_ = NULL; - return *this; - } - - int Set(int fd) { - if (*fd_ >= 0) - close(*fd_); - *fd_ = fd; - return fd; - } - - int get() { - return *fd_; - } - - operator bool() const { - return fd_ != NULL; - } - - private: - int *fd_ = NULL; -}; -} // namespace android - -#endif diff --git a/include/drmhwcgralloc.h b/include/drmhwcgralloc.h index 05b2cf0..db54802 100644 --- a/include/drmhwcgralloc.h +++ b/include/drmhwcgralloc.h @@ -29,11 +29,8 @@ typedef struct hwc_drm_bo { uint32_t pitches[HWC_DRM_BO_MAX_PLANES]; uint32_t offsets[HWC_DRM_BO_MAX_PLANES]; uint32_t prime_fds[HWC_DRM_BO_MAX_PLANES]; - uint32_t gem_handles[HWC_DRM_BO_MAX_PLANES]; uint64_t modifiers[HWC_DRM_BO_MAX_PLANES]; - uint32_t fb_id; int acquire_fence_fd; - void *priv; } hwc_drm_bo_t; #endif // ANDROID_DRMHWCGRALLOC_H_ diff --git a/include/drmhwcomposer.h b/include/drmhwcomposer.h index a04cc29..22af12b 100644 --- a/include/drmhwcomposer.h +++ b/include/drmhwcomposer.h @@ -17,99 +17,20 @@ #ifndef ANDROID_DRM_HWCOMPOSER_H_ #define ANDROID_DRM_HWCOMPOSER_H_ +#include <hardware/hardware.h> +#include <hardware/hwcomposer.h> #include <stdbool.h> #include <stdint.h> #include <vector> -#include <hardware/hardware.h> -#include <hardware/hwcomposer.h> -#include "autofd.h" +#include "drm/DrmFbImporter.h" #include "drmhwcgralloc.h" - -struct hwc_import_context; - -int hwc_import_init(struct hwc_import_context **ctx); -int hwc_import_destroy(struct hwc_import_context *ctx); - -int hwc_import_bo_create(int fd, struct hwc_import_context *ctx, - buffer_handle_t buf, struct hwc_drm_bo *bo); -bool hwc_import_bo_release(int fd, struct hwc_import_context *ctx, - struct hwc_drm_bo *bo); +#include "utils/UniqueFd.h" namespace android { -class Importer; - -class DrmHwcBuffer { - public: - DrmHwcBuffer() = default; - DrmHwcBuffer(const hwc_drm_bo &bo, Importer *importer) - : bo_(bo), importer_(importer) { - } - DrmHwcBuffer(DrmHwcBuffer &&rhs) : bo_(rhs.bo_), importer_(rhs.importer_) { - rhs.importer_ = NULL; - } - - ~DrmHwcBuffer() { - Clear(); - } - - DrmHwcBuffer &operator=(DrmHwcBuffer &&rhs) { - Clear(); - importer_ = rhs.importer_; - rhs.importer_ = NULL; - bo_ = rhs.bo_; - return *this; - } - - operator bool() const { - return importer_ != NULL; - } - - const hwc_drm_bo *operator->() const; - - void Clear(); - - int ImportBuffer(buffer_handle_t handle, Importer *importer); - - private: - hwc_drm_bo bo_; - Importer *importer_ = NULL; -}; - -class DrmHwcNativeHandle { - public: - DrmHwcNativeHandle() = default; - - DrmHwcNativeHandle(native_handle_t *handle) : handle_(handle) { - } - - DrmHwcNativeHandle(DrmHwcNativeHandle &&rhs) { - handle_ = rhs.handle_; - rhs.handle_ = NULL; - } - - ~DrmHwcNativeHandle(); - - DrmHwcNativeHandle &operator=(DrmHwcNativeHandle &&rhs) { - Clear(); - handle_ = rhs.handle_; - rhs.handle_ = NULL; - return *this; - } - - int CopyBufferHandle(buffer_handle_t handle); - - void Clear(); - - buffer_handle_t get() const { - return handle_; - } - - private: - native_handle_t *handle_ = NULL; -}; +class DrmFbIdHandle; enum DrmHwcTransform { kIdentity = 0, @@ -128,9 +49,10 @@ enum class DrmHwcBlending : int32_t { struct DrmHwcLayer { buffer_handle_t sf_handle = NULL; + hwc_drm_bo_t buffer_info{}; + std::shared_ptr<DrmFbIdHandle> FbIdHandle; + int gralloc_buffer_usage = 0; - DrmHwcBuffer buffer; - DrmHwcNativeHandle handle; uint32_t transform; DrmHwcBlending blending = DrmHwcBlending::kNone; uint16_t alpha = 0xffff; @@ -139,17 +61,11 @@ struct DrmHwcLayer { android_dataspace_t dataspace; UniqueFd acquire_fence; - OutputFd release_fence; - int ImportBuffer(Importer *importer); - int InitFromDrmHwcLayer(DrmHwcLayer *layer, Importer *importer); + int ImportBuffer(DrmDevice *drmDevice); void SetTransform(int32_t sf_transform); - buffer_handle_t get_usable_handle() const { - return handle.get() != NULL ? handle.get() : sf_handle; - } - bool protected_usage() const { return (gralloc_buffer_usage & GRALLOC_USAGE_PROTECTED) == GRALLOC_USAGE_PROTECTED; diff --git a/utils/UniqueFd.h b/utils/UniqueFd.h new file mode 100644 index 0000000..1a390ba --- /dev/null +++ b/utils/UniqueFd.h @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2015, 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UNIQUEFD_H_ +#define UNIQUEFD_H_ + +#include <unistd.h> + +#include <memory> + +namespace android { + +/* + * Using UniqueFd: + * 1. Create UniqueFd object: + * auto fd_obj = UniqueFd(open("SomeFile", xxx)); + * + * 2. Check whether the fd_obj is empty: + * if (!fd_obj) { return -errno; } + * + * 3. Accessing the file descriptor: + * int ret = read(fd_obj.Get(), buf, buf_size); + * + * 4. Closing the file: + * FD will be closed once execution leaves fd_obj scope (on any return, + * exception, destruction of class/struct where object is member, etc.). + * User can also force closing the fd_obj by calling: + * fd_obj = UniqueFd(); + * // fd is closed and fd_obj is empty now. + * + * 5. File descriptor may be transferred to the code, which will close it after + * using. This can be done in 2 ways: + * a. Duplicate the fd, in this case both fds should be closed separately: + * int out_fd = dup(fd_obj.Get(); + * ... + * close(out_fd); + * b. Transfer ownership, use this method if you do not need the fd anymore. + * int out_fd = fd_obj.Release(); + * // fd_obj is empty now. + * ... + * close(out_fd); + * + * 6. Transferring fd into another UniqueFD object: + * UniqueFd fd_obj_2 = std::move(fd_obj); + * // fd_obj empty now + */ + +constexpr int kEmptyFd = -1; + +class UniqueFd { + public: + UniqueFd() = default; + explicit UniqueFd(int fd) : fd_(fd){}; + + auto Release [[nodiscard]] () -> int { + return std::exchange(fd_, kEmptyFd); + } + + auto Get [[nodiscard]] () const -> int { + return fd_; + } + + explicit operator bool() const { + return fd_ != kEmptyFd; + } + + ~UniqueFd() { + Set(kEmptyFd); + } + + /* Allow move semantics */ + UniqueFd(UniqueFd &&rhs) noexcept { + Set(rhs.Release()); + } + + auto operator=(UniqueFd &&rhs) noexcept -> UniqueFd & { + Set(rhs.Release()); + return *this; + } + + /* Disable copy semantics */ + UniqueFd(const UniqueFd &) = delete; + auto operator=(const UniqueFd &) = delete; + + private: + void Set(int new_fd) { + if (fd_ != kEmptyFd) { + close(fd_); + } + fd_ = new_fd; + } + + int fd_ = kEmptyFd; +}; + +} // namespace android + +#endif diff --git a/utils/hwcutils.cpp b/utils/hwcutils.cpp index 81097ce..6de6500 100644 --- a/utils/hwcutils.cpp +++ b/utils/hwcutils.cpp @@ -22,118 +22,32 @@ #include <ui/GraphicBufferMapper.h> #include "bufferinfo/BufferInfoGetter.h" -#include "drm/DrmGenericImporter.h" +#include "drm/DrmFbImporter.h" #include "drmhwcomposer.h" #define UNUSED(x) (void)(x) namespace android { -const hwc_drm_bo *DrmHwcBuffer::operator->() const { - if (importer_ == nullptr) { - ALOGE("Access of non-existent BO"); - exit(1); - return nullptr; - } - return &bo_; -} - -void DrmHwcBuffer::Clear() { - if (importer_ != nullptr) { - importer_->ReleaseBuffer(&bo_); - importer_ = nullptr; - } -} +int DrmHwcLayer::ImportBuffer(DrmDevice *drmDevice) { + buffer_info = hwc_drm_bo_t{}; -int DrmHwcBuffer::ImportBuffer(buffer_handle_t handle, Importer *importer) { - hwc_drm_bo tmp_bo{}; - - int ret = BufferInfoGetter::GetInstance()->ConvertBoInfo(handle, &tmp_bo); + int ret = BufferInfoGetter::GetInstance()->ConvertBoInfo(sf_handle, + &buffer_info); if (ret) { ALOGE("Failed to convert buffer info %d", ret); return ret; } - ret = importer->ImportBuffer(&tmp_bo); - if (ret) { - ALOGE("Failed to import buffer %d", ret); - return ret; - } - - if (importer_ != nullptr) { - importer_->ReleaseBuffer(&bo_); + FbIdHandle = drmDevice->GetDrmFbImporter().GetOrCreateFbId(&buffer_info); + if (!FbIdHandle) { + ALOGE("Failed to import buffer"); + return -EINVAL; } - importer_ = importer; - - bo_ = tmp_bo; - return 0; } -int DrmHwcNativeHandle::CopyBufferHandle(buffer_handle_t handle) { - native_handle_t *handle_copy = nullptr; - GraphicBufferMapper &gm(GraphicBufferMapper::get()); - int ret = 0; - - ret = gm.getGrallocMapper().importBuffer(handle, - (buffer_handle_t *)&handle_copy); - - if (ret) { - ALOGE("Failed to import buffer handle %d", ret); - return ret; - } - - Clear(); - - handle_ = handle_copy; - - return 0; -} - -DrmHwcNativeHandle::~DrmHwcNativeHandle() { - Clear(); -} - -void DrmHwcNativeHandle::Clear() { - if (handle_ != nullptr) { - GraphicBufferMapper &gm(GraphicBufferMapper::get()); - int ret = gm.freeBuffer(handle_); - if (ret) { - ALOGE("Failed to free buffer handle %d", ret); - } - handle_ = nullptr; - } -} - -int DrmHwcLayer::ImportBuffer(Importer *importer) { - int ret = buffer.ImportBuffer(sf_handle, importer); - if (ret) - return ret; - - const hwc_drm_bo *bo = buffer.operator->(); - - ret = handle.CopyBufferHandle(sf_handle); - if (ret) - return ret; - - gralloc_buffer_usage = bo->usage; - - return 0; -} - -int DrmHwcLayer::InitFromDrmHwcLayer(DrmHwcLayer *src_layer, - Importer *importer) { - blending = src_layer->blending; - sf_handle = src_layer->sf_handle; - acquire_fence = -1; - display_frame = src_layer->display_frame; - alpha = src_layer->alpha; - source_crop = src_layer->source_crop; - transform = src_layer->transform; - return ImportBuffer(importer); -} - void DrmHwcLayer::SetTransform(int32_t sf_transform) { transform = 0; // 270* and 180* cannot be combined with flips. More specifically, they |