aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Stratiienko <r.stratiienko@gmail.com>2023-01-16 17:15:53 +0200
committerRoman Stratiienko <r.stratiienko@gmail.com>2023-01-16 20:13:58 +0200
commit76892784ac7c3dde9c7c14d4e88d17960a445740 (patch)
tree02c8eb5f5c25f5a7f436f2c1455c34953220591f
parent2bf68c374976d0a7a0e71c1843cbeae2a3210b74 (diff)
downloaddrm_hwcomposer-76892784ac7c3dde9c7c14d4e88d17960a445740.tar.gz
drm_hwcomposer: Introduce SharedFd, use standard c++ RAII for UniqueFd
We use too much dup() system calls for present fence propagating. Also when propagating acquire fence we use additional logic for skipping such propagation for the validate/test cycle. Both issues can be solved by introducing SharedFd, which will track reference count of fd object. After that the UniqueFd is used very rarely and can be simplified by wrapping it into std::unique_ptr without caring too much of adding an extra malloc/free operation. Signed-off-by: Roman Stratiienko <r.stratiienko@gmail.com>
-rw-r--r--.ci/Makefile1
-rw-r--r--Android.bp2
-rw-r--r--compositor/LayerData.h4
-rw-r--r--drm/DrmAtomicStateManager.cpp28
-rw-r--r--drm/DrmAtomicStateManager.h4
-rw-r--r--drm/DrmConnector.cpp6
-rw-r--r--drm/DrmCrtc.cpp2
-rw-r--r--drm/DrmDevice.cpp34
-rw-r--r--drm/DrmDevice.h8
-rw-r--r--drm/DrmEncoder.cpp2
-rw-r--r--drm/DrmFbImporter.cpp13
-rw-r--r--drm/DrmPlane.cpp4
-rw-r--r--drm/VSyncWorker.cpp4
-rw-r--r--drm/VSyncWorker.h2
-rw-r--r--hwc2_device/HwcDisplay.cpp6
-rw-r--r--hwc2_device/HwcDisplay.h2
-rw-r--r--hwc2_device/HwcLayer.cpp2
-rw-r--r--hwc2_device/HwcLayer.h3
-rw-r--r--meson.build1
-rw-r--r--utils/UEvent.h8
-rw-r--r--utils/UniqueFd.h115
-rw-r--r--utils/fd.cpp52
-rw-r--r--utils/fd.h36
23 files changed, 157 insertions, 182 deletions
diff --git a/.ci/Makefile b/.ci/Makefile
index de5196b..9c82fca 100644
--- a/.ci/Makefile
+++ b/.ci/Makefile
@@ -27,7 +27,6 @@ TIDY_FILES_OVERRIDE := \
hwc2_device/DrmHwcTwo.h:COARSE \
hwc2_device/HwcDisplay.cpp:COARSE \
hwc2_device/HwcDisplay.h:COARSE \
- utils/UniqueFd.h:FINE \
utils/log.h:FINE \
utils/properties.h:FINE \
diff --git a/Android.bp b/Android.bp
index 3ad060c..1e78729 100644
--- a/Android.bp
+++ b/Android.bp
@@ -83,6 +83,8 @@ filegroup {
"hwc2_device/HwcDisplayConfigs.cpp",
"hwc2_device/HwcLayer.cpp",
"hwc2_device/hwc2_device.cpp",
+
+ "utils/fd.cpp",
],
}
diff --git a/compositor/LayerData.h b/compositor/LayerData.h
index 92d4da0..a7e14f9 100644
--- a/compositor/LayerData.h
+++ b/compositor/LayerData.h
@@ -27,7 +27,7 @@
#include "bufferinfo/BufferInfo.h"
#include "drm/DrmFbImporter.h"
-#include "utils/UniqueFd.h"
+#include "utils/fd.h"
namespace android {
@@ -75,7 +75,7 @@ struct LayerData {
std::optional<BufferInfo> bi;
std::shared_ptr<DrmFbIdHandle> fb;
PresentInfo pi;
- UniqueFd acquire_fence;
+ SharedFd acquire_fence;
};
} // namespace android
diff --git a/drm/DrmAtomicStateManager.cpp b/drm/DrmAtomicStateManager.cpp
index b5e4629..58a5523 100644
--- a/drm/DrmAtomicStateManager.cpp
+++ b/drm/DrmAtomicStateManager.cpp
@@ -141,7 +141,7 @@ auto DrmAtomicStateManager::CommitFrame(AtomicCommitArgs &args) -> int {
uint32_t flags = DRM_MODE_ATOMIC_ALLOW_MODESET;
if (args.test_only) {
- return drmModeAtomicCommit(drm->GetFd(), pset.get(),
+ return drmModeAtomicCommit(*drm->GetFd(), pset.get(),
flags | DRM_MODE_ATOMIC_TEST_ONLY, drm);
}
@@ -150,10 +150,10 @@ auto DrmAtomicStateManager::CommitFrame(AtomicCommitArgs &args) -> int {
ATRACE_NAME("WaitPriorFramePresented");
constexpr int kTimeoutMs = 500;
- const int err = sync_wait(last_present_fence_.Get(), kTimeoutMs);
+ const int err = sync_wait(*last_present_fence_, kTimeoutMs);
if (err != 0) {
- ALOGE("sync_wait(fd=%i) returned: %i (errno: %i)",
- last_present_fence_.Get(), err, errno);
+ ALOGE("sync_wait(fd=%i) returned: %i (errno: %i)", *last_present_fence_,
+ err, errno);
}
CleanupPriorFrameResources();
@@ -163,17 +163,19 @@ auto DrmAtomicStateManager::CommitFrame(AtomicCommitArgs &args) -> int {
flags |= DRM_MODE_ATOMIC_NONBLOCK;
}
- auto err = drmModeAtomicCommit(drm->GetFd(), pset.get(), flags, drm);
+ auto err = drmModeAtomicCommit(*drm->GetFd(), pset.get(), flags, drm);
if (err != 0) {
ALOGE("Failed to commit pset ret=%d\n", err);
return err;
}
+ args.out_fence = MakeSharedFd(out_fence);
+
if (nonblock) {
{
const std::unique_lock lock(mutex_);
- last_present_fence_ = UniqueFd::Dup(out_fence);
+ last_present_fence_ = args.out_fence;
staged_frame_state_ = std::move(new_frame_state);
frames_staged_++;
}
@@ -182,8 +184,6 @@ auto DrmAtomicStateManager::CommitFrame(AtomicCommitArgs &args) -> int {
active_frame_state_ = std::move(new_frame_state);
}
- args.out_fence = UniqueFd(out_fence);
-
return 0;
}
@@ -193,7 +193,7 @@ void DrmAtomicStateManager::ThreadFn(
auto &main_mutex = pipe_->device->GetResMan().GetMainLock();
for (;;) {
- UniqueFd present_fence;
+ SharedFd present_fence;
{
std::unique_lock lk(mutex_);
@@ -207,7 +207,7 @@ void DrmAtomicStateManager::ThreadFn(
tracking_at_the_moment = frames_staged_;
- present_fence = UniqueFd::Dup(last_present_fence_.Get());
+ present_fence = last_present_fence_;
if (!present_fence)
continue;
}
@@ -216,10 +216,10 @@ void DrmAtomicStateManager::ThreadFn(
// NOLINTNEXTLINE(misc-const-correctness)
ATRACE_NAME("AsyncWaitForBuffersSwap");
constexpr int kTimeoutMs = 500;
- auto err = sync_wait(present_fence.Get(), kTimeoutMs);
+ auto err = sync_wait(*present_fence, kTimeoutMs);
if (err != 0) {
- ALOGE("sync_wait(fd=%i) returned: %i (errno: %i)", present_fence.Get(),
- err, errno);
+ ALOGE("sync_wait(fd=%i) returned: %i (errno: %i)", *present_fence, err,
+ errno);
}
}
@@ -272,7 +272,7 @@ auto DrmAtomicStateManager::ExecuteAtomicCommit(AtomicCommitArgs &args) -> int {
} // namespace android
auto DrmAtomicStateManager::ActivateDisplayUsingDPMS() -> int {
- return drmModeConnectorSetProperty(pipe_->device->GetFd(),
+ return drmModeConnectorSetProperty(*pipe_->device->GetFd(),
pipe_->connector->Get()->GetId(),
pipe_->connector->Get()
->GetDpmsProperty()
diff --git a/drm/DrmAtomicStateManager.h b/drm/DrmAtomicStateManager.h
index 5f19bcc..e456a91 100644
--- a/drm/DrmAtomicStateManager.h
+++ b/drm/DrmAtomicStateManager.h
@@ -37,7 +37,7 @@ struct AtomicCommitArgs {
std::shared_ptr<DrmKmsPlan> composition;
/* out */
- UniqueFd out_fence;
+ SharedFd out_fence;
/* helpers */
auto HasInputs() -> bool {
@@ -95,7 +95,7 @@ class DrmAtomicStateManager {
void CleanupPriorFrameResources();
KmsState staged_frame_state_;
- UniqueFd last_present_fence_;
+ SharedFd last_present_fence_;
int frames_staged_{};
int frames_tracked_{};
diff --git a/drm/DrmConnector.cpp b/drm/DrmConnector.cpp
index 07c5d74..f625563 100644
--- a/drm/DrmConnector.cpp
+++ b/drm/DrmConnector.cpp
@@ -63,7 +63,7 @@ static bool GetConnectorProperty(const DrmDevice &dev,
auto DrmConnector::CreateInstance(DrmDevice &dev, uint32_t connector_id,
uint32_t index)
-> std::unique_ptr<DrmConnector> {
- auto conn = MakeDrmModeConnectorUnique(dev.GetFd(), connector_id);
+ auto conn = MakeDrmModeConnectorUnique(*dev.GetFd(), connector_id);
if (!conn) {
ALOGE("Failed to get connector %d", connector_id);
return {};
@@ -109,7 +109,7 @@ auto DrmConnector::GetEdidBlob() -> DrmModePropertyBlobUnique {
return {};
}
- return MakeDrmModePropertyBlobUnique(drm_->GetFd(), *blob_id);
+ return MakeDrmModePropertyBlobUnique(*drm_->GetFd(), *blob_id);
}
bool DrmConnector::IsInternal() const {
@@ -158,7 +158,7 @@ std::string DrmConnector::GetName() const {
}
int DrmConnector::UpdateModes() {
- auto conn = MakeDrmModeConnectorUnique(drm_->GetFd(), GetId());
+ auto conn = MakeDrmModeConnectorUnique(*drm_->GetFd(), GetId());
if (!conn) {
ALOGE("Failed to get connector %d", GetId());
return -ENODEV;
diff --git a/drm/DrmCrtc.cpp b/drm/DrmCrtc.cpp
index b54f14b..3b749b1 100644
--- a/drm/DrmCrtc.cpp
+++ b/drm/DrmCrtc.cpp
@@ -35,7 +35,7 @@ static int GetCrtcProperty(const DrmDevice &dev, const DrmCrtc &crtc,
auto DrmCrtc::CreateInstance(DrmDevice &dev, uint32_t crtc_id, uint32_t index)
-> std::unique_ptr<DrmCrtc> {
- auto crtc = MakeDrmModeCrtcUnique(dev.GetFd(), crtc_id);
+ auto crtc = MakeDrmModeCrtcUnique(*dev.GetFd(), crtc_id);
if (!crtc) {
ALOGE("Failed to get CRTC %d", crtc_id);
return {};
diff --git a/drm/DrmDevice.cpp b/drm/DrmDevice.cpp
index 33adf2a..1d6b62e 100644
--- a/drm/DrmDevice.cpp
+++ b/drm/DrmDevice.cpp
@@ -55,46 +55,46 @@ DrmDevice::DrmDevice(ResourceManager *res_man) : res_man_(res_man) {
auto DrmDevice::Init(const char *path) -> int {
/* TODO: Use drmOpenControl here instead */
- fd_ = UniqueFd(open(path, O_RDWR | O_CLOEXEC));
+ fd_ = MakeSharedFd(open(path, O_RDWR | O_CLOEXEC));
if (!fd_) {
// NOLINTNEXTLINE(concurrency-mt-unsafe): Fixme
ALOGE("Failed to open dri %s: %s", path, strerror(errno));
return -ENODEV;
}
- int ret = drmSetClientCap(GetFd(), DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
+ int ret = drmSetClientCap(*GetFd(), DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
if (ret != 0) {
ALOGE("Failed to set universal plane cap %d", ret);
return ret;
}
- ret = drmSetClientCap(GetFd(), DRM_CLIENT_CAP_ATOMIC, 1);
+ ret = drmSetClientCap(*GetFd(), DRM_CLIENT_CAP_ATOMIC, 1);
if (ret != 0) {
ALOGE("Failed to set atomic cap %d", ret);
return ret;
}
#ifdef DRM_CLIENT_CAP_WRITEBACK_CONNECTORS
- ret = drmSetClientCap(GetFd(), DRM_CLIENT_CAP_WRITEBACK_CONNECTORS, 1);
+ ret = drmSetClientCap(*GetFd(), DRM_CLIENT_CAP_WRITEBACK_CONNECTORS, 1);
if (ret != 0) {
ALOGI("Failed to set writeback cap %d", ret);
}
#endif
uint64_t cap_value = 0;
- if (drmGetCap(GetFd(), DRM_CAP_ADDFB2_MODIFIERS, &cap_value) != 0) {
+ if (drmGetCap(*GetFd(), DRM_CAP_ADDFB2_MODIFIERS, &cap_value) != 0) {
ALOGW("drmGetCap failed. Fallback to no modifier support.");
cap_value = 0;
}
HasAddFb2ModifiersSupport_ = cap_value != 0;
- drmSetMaster(GetFd());
- if (drmIsMaster(GetFd()) == 0) {
+ drmSetMaster(*GetFd());
+ if (drmIsMaster(*GetFd()) == 0) {
ALOGE("DRM/KMS master access required");
return -EACCES;
}
- auto res = MakeDrmModeResUnique(GetFd());
+ auto res = MakeDrmModeResUnique(*GetFd());
if (!res) {
ALOGE("Failed to get DrmDevice resources");
return -ENODEV;
@@ -136,7 +136,7 @@ auto DrmDevice::Init(const char *path) -> int {
}
}
- auto plane_res = MakeDrmModePlaneResUnique(GetFd());
+ auto plane_res = MakeDrmModePlaneResUnique(*GetFd());
if (!plane_res) {
ALOGE("Failed to get plane resources");
return -ENOENT;
@@ -161,7 +161,7 @@ auto DrmDevice::RegisterUserPropertyBlob(void *data, size_t length) const
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast)
create_blob.data = (__u64)data;
- auto ret = drmIoctl(GetFd(), DRM_IOCTL_MODE_CREATEPROPBLOB, &create_blob);
+ auto ret = drmIoctl(*GetFd(), DRM_IOCTL_MODE_CREATEPROPBLOB, &create_blob);
if (ret != 0) {
ALOGE("Failed to create mode property blob %d", ret);
return {};
@@ -171,7 +171,7 @@ auto DrmDevice::RegisterUserPropertyBlob(void *data, size_t length) const
new uint32_t(create_blob.blob_id), [this](const uint32_t *it) {
struct drm_mode_destroy_blob destroy_blob {};
destroy_blob.blob_id = (__u32)*it;
- auto err = drmIoctl(GetFd(), DRM_IOCTL_MODE_DESTROYPROPBLOB,
+ auto err = drmIoctl(*GetFd(), DRM_IOCTL_MODE_DESTROYPROPBLOB,
&destroy_blob);
if (err != 0) {
ALOGE("Failed to destroy mode property blob %" PRIu32 "/%d", *it,
@@ -186,7 +186,7 @@ int DrmDevice::GetProperty(uint32_t obj_id, uint32_t obj_type,
const char *prop_name, DrmProperty *property) const {
drmModeObjectPropertiesPtr props = nullptr;
- props = drmModeObjectGetProperties(GetFd(), obj_id, obj_type);
+ props = drmModeObjectGetProperties(*GetFd(), obj_id, obj_type);
if (props == nullptr) {
ALOGE("Failed to get properties for %d/%x", obj_id, obj_type);
return -ENODEV;
@@ -195,7 +195,7 @@ int DrmDevice::GetProperty(uint32_t obj_id, uint32_t obj_type,
bool found = false;
for (int i = 0; !found && (size_t)i < props->count_props; ++i) {
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- drmModePropertyPtr p = drmModeGetProperty(GetFd(), props->props[i]);
+ drmModePropertyPtr p = drmModeGetProperty(*GetFd(), props->props[i]);
if (strcmp(p->name, prop_name) == 0) {
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
property->Init(obj_id, p, props->prop_values[i]);
@@ -209,9 +209,9 @@ int DrmDevice::GetProperty(uint32_t obj_id, uint32_t obj_type,
}
std::string DrmDevice::GetName() const {
- auto *ver = drmGetVersion(GetFd());
+ auto *ver = drmGetVersion(*GetFd());
if (ver == nullptr) {
- ALOGW("Failed to get drm version for fd=%d", GetFd());
+ ALOGW("Failed to get drm version for fd=%d", *GetFd());
return "generic";
}
@@ -221,12 +221,12 @@ std::string DrmDevice::GetName() const {
}
auto DrmDevice::IsKMSDev(const char *path) -> bool {
- auto fd = UniqueFd(open(path, O_RDWR | O_CLOEXEC));
+ auto fd = MakeUniqueFd(open(path, O_RDWR | O_CLOEXEC));
if (!fd) {
return false;
}
- auto res = MakeDrmModeResUnique(fd.Get());
+ auto res = MakeDrmModeResUnique(*fd);
if (!res) {
return false;
}
diff --git a/drm/DrmDevice.h b/drm/DrmDevice.h
index bb515e0..39d0c88 100644
--- a/drm/DrmDevice.h
+++ b/drm/DrmDevice.h
@@ -23,7 +23,7 @@
#include "DrmConnector.h"
#include "DrmCrtc.h"
#include "DrmEncoder.h"
-#include "utils/UniqueFd.h"
+#include "utils/fd.h"
namespace android {
@@ -38,8 +38,8 @@ class DrmDevice {
static auto CreateInstance(std::string const &path, ResourceManager *res_man)
-> std::unique_ptr<DrmDevice>;
- auto GetFd() const {
- return fd_.Get();
+ auto &GetFd() const {
+ return fd_;
}
auto &GetResMan() {
@@ -101,7 +101,7 @@ class DrmDevice {
static auto IsKMSDev(const char *path) -> bool;
- UniqueFd fd_;
+ SharedFd fd_;
std::vector<std::unique_ptr<DrmConnector>> connectors_;
std::vector<std::unique_ptr<DrmConnector>> writeback_connectors_;
diff --git a/drm/DrmEncoder.cpp b/drm/DrmEncoder.cpp
index eed5b5f..21ca693 100644
--- a/drm/DrmEncoder.cpp
+++ b/drm/DrmEncoder.cpp
@@ -29,7 +29,7 @@ namespace android {
auto DrmEncoder::CreateInstance(DrmDevice &dev, uint32_t encoder_id,
uint32_t index) -> std::unique_ptr<DrmEncoder> {
- auto e = MakeDrmModeEncoderUnique(dev.GetFd(), encoder_id);
+ auto e = MakeDrmModeEncoderUnique(*dev.GetFd(), encoder_id);
if (!e) {
ALOGE("Failed to get encoder %d", encoder_id);
return {};
diff --git a/drm/DrmFbImporter.cpp b/drm/DrmFbImporter.cpp
index f0be32f..a91a52b 100644
--- a/drm/DrmFbImporter.cpp
+++ b/drm/DrmFbImporter.cpp
@@ -50,7 +50,7 @@ auto DrmFbIdHandle::CreateInstance(BufferInfo *bo, GemHandle first_gem_handle,
for (size_t i = 1; i < local->gem_handles_.size(); i++) {
if (bo->prime_fds[i] > 0) {
if (bo->prime_fds[i] != bo->prime_fds[0]) {
- err = drmPrimeFDToHandle(drm.GetFd(), bo->prime_fds[i],
+ err = drmPrimeFDToHandle(*drm.GetFd(), 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],
@@ -74,11 +74,11 @@ auto DrmFbIdHandle::CreateInstance(BufferInfo *bo, GemHandle first_gem_handle,
/* Create framebuffer object */
if (!has_modifiers) {
- err = drmModeAddFB2(drm.GetFd(), bo->width, bo->height, bo->format,
+ err = drmModeAddFB2(*drm.GetFd(), bo->width, bo->height, bo->format,
local->gem_handles_.data(), &bo->pitches[0],
&bo->offsets[0], &local->fb_id_, 0);
} else {
- err = drmModeAddFB2WithModifiers(drm.GetFd(), bo->width, bo->height,
+ err = drmModeAddFB2WithModifiers(*drm.GetFd(), bo->width, bo->height,
bo->format, local->gem_handles_.data(),
&bo->pitches[0], &bo->offsets[0],
&bo->modifiers[0], &local->fb_id_,
@@ -97,7 +97,7 @@ DrmFbIdHandle::~DrmFbIdHandle() {
ATRACE_NAME("Close FB and dmabufs");
/* Destroy framebuffer object */
- if (drmModeRmFB(drm_->GetFd(), fb_id_) != 0) {
+ if (drmModeRmFB(*drm_->GetFd(), fb_id_) != 0) {
ALOGE("Failed to rm fb");
}
@@ -118,7 +118,7 @@ DrmFbIdHandle::~DrmFbIdHandle() {
continue;
}
gem_close.handle = gem_handles_[i];
- auto err = drmIoctl(drm_->GetFd(), DRM_IOCTL_GEM_CLOSE, &gem_close);
+ auto err = drmIoctl(*drm_->GetFd(), DRM_IOCTL_GEM_CLOSE, &gem_close);
if (err != 0) {
ALOGE("Failed to close gem handle %d, errno: %d", gem_handles_[i], errno);
}
@@ -129,7 +129,8 @@ auto DrmFbImporter::GetOrCreateFbId(BufferInfo *bo)
-> std::shared_ptr<DrmFbIdHandle> {
/* Lookup DrmFbIdHandle in cache first. First handle serves as a cache key. */
GemHandle first_handle = 0;
- auto err = drmPrimeFDToHandle(drm_->GetFd(), bo->prime_fds[0], &first_handle);
+ auto err = drmPrimeFDToHandle(*drm_->GetFd(), bo->prime_fds[0],
+ &first_handle);
if (err != 0) {
ALOGE("Failed to import prime fd %d ret=%d", bo->prime_fds[0], err);
diff --git a/drm/DrmPlane.cpp b/drm/DrmPlane.cpp
index 4d03840..228e3dd 100644
--- a/drm/DrmPlane.cpp
+++ b/drm/DrmPlane.cpp
@@ -31,7 +31,7 @@ namespace android {
auto DrmPlane::CreateInstance(DrmDevice &dev, uint32_t plane_id)
-> std::unique_ptr<DrmPlane> {
- auto p = MakeDrmModePlaneUnique(dev.GetFd(), plane_id);
+ auto p = MakeDrmModePlaneUnique(*dev.GetFd(), plane_id);
if (!p) {
ALOGE("Failed to get plane %d", plane_id);
return {};
@@ -261,7 +261,7 @@ auto DrmPlane::AtomicSetState(drmModeAtomicReq &pset, LayerData &layer,
}
if (layer.acquire_fence &&
- !in_fence_fd_property_.AtomicSet(pset, layer.acquire_fence.Get())) {
+ !in_fence_fd_property_.AtomicSet(pset, *layer.acquire_fence)) {
return -EINVAL;
}
diff --git a/drm/VSyncWorker.cpp b/drm/VSyncWorker.cpp
index 77b9d98..8a251c7 100644
--- a/drm/VSyncWorker.cpp
+++ b/drm/VSyncWorker.cpp
@@ -40,7 +40,7 @@ auto VSyncWorker::CreateInstance(DrmDisplayPipeline *pipe,
if (pipe != nullptr) {
vsw->high_crtc_ = pipe->crtc->Get()->GetIndexInResArray()
<< DRM_VBLANK_HIGH_CRTC_SHIFT;
- vsw->drm_fd_ = UniqueFd::Dup(pipe->device->GetFd());
+ vsw->drm_fd_ = pipe->device->GetFd();
}
std::thread(&VSyncWorker::ThreadFn, vsw.get(), vsw).detach();
@@ -143,7 +143,7 @@ void VSyncWorker::ThreadFn(const std::shared_ptr<VSyncWorker> &vsw) {
DRM_VBLANK_HIGH_CRTC_MASK));
vblank.request.sequence = 1;
- ret = drmWaitVBlank(drm_fd_.Get(), &vblank);
+ ret = drmWaitVBlank(*drm_fd_, &vblank);
if (ret == -EINTR)
continue;
}
diff --git a/drm/VSyncWorker.h b/drm/VSyncWorker.h
index 2a0b084..031a561 100644
--- a/drm/VSyncWorker.h
+++ b/drm/VSyncWorker.h
@@ -52,7 +52,7 @@ class VSyncWorker {
VSyncWorkerCallbacks callbacks_;
- UniqueFd drm_fd_;
+ SharedFd drm_fd_;
uint32_t high_crtc_ = 0;
bool enabled_ = false;
diff --git a/hwc2_device/HwcDisplay.cpp b/hwc2_device/HwcDisplay.cpp
index 194889e..d957dc3 100644
--- a/hwc2_device/HwcDisplay.cpp
+++ b/hwc2_device/HwcDisplay.cpp
@@ -452,7 +452,7 @@ HWC2::Error HwcDisplay::GetReleaseFences(uint32_t *num_elements,
}
layers[num_layers - 1] = l.first;
- fences[num_layers - 1] = UniqueFd::Dup(present_fence_.Get()).Release();
+ fences[num_layers - 1] = DupFd(present_fence_);
}
*num_elements = num_layers;
@@ -592,8 +592,8 @@ HWC2::Error HwcDisplay::PresentDisplay(int32_t *out_present_fence) {
if (ret != HWC2::Error::None)
return ret;
- this->present_fence_ = UniqueFd::Dup(a_args.out_fence.Get());
- *out_present_fence = a_args.out_fence.Release();
+ this->present_fence_ = a_args.out_fence;
+ *out_present_fence = DupFd(a_args.out_fence);
++frame_no_;
return HWC2::Error::None;
diff --git a/hwc2_device/HwcDisplay.h b/hwc2_device/HwcDisplay.h
index 4ad57b7..6cac60f 100644
--- a/hwc2_device/HwcDisplay.h
+++ b/hwc2_device/HwcDisplay.h
@@ -200,7 +200,7 @@ class HwcDisplay {
DrmHwcTwo *const hwc2_;
- UniqueFd present_fence_;
+ SharedFd present_fence_;
std::optional<DrmMode> staged_mode_;
int64_t staged_mode_change_time_{};
diff --git a/hwc2_device/HwcLayer.cpp b/hwc2_device/HwcLayer.cpp
index 589a0a7..d3936b3 100644
--- a/hwc2_device/HwcLayer.cpp
+++ b/hwc2_device/HwcLayer.cpp
@@ -53,7 +53,7 @@ HWC2::Error HwcLayer::SetLayerBlendMode(int32_t mode) {
*/
HWC2::Error HwcLayer::SetLayerBuffer(buffer_handle_t buffer,
int32_t acquire_fence) {
- acquire_fence_ = UniqueFd(acquire_fence);
+ acquire_fence_ = MakeUniqueFd(acquire_fence);
buffer_handle_ = buffer;
buffer_handle_updated_ = true;
diff --git a/hwc2_device/HwcLayer.h b/hwc2_device/HwcLayer.h
index 627d5ac..7f647a8 100644
--- a/hwc2_device/HwcLayer.h
+++ b/hwc2_device/HwcLayer.h
@@ -86,8 +86,7 @@ class HwcLayer {
uint32_t z_order_ = 0;
LayerData layer_data_;
- /* Should be populated to layer_data_.acquire_fence only before presenting */
- UniqueFd acquire_fence_;
+ SharedFd acquire_fence_;
/* The following buffer data can have 2 sources:
* 1 - Mapper@4 metadata API
diff --git a/meson.build b/meson.build
index 266163e..4328a1e 100644
--- a/meson.build
+++ b/meson.build
@@ -14,6 +14,7 @@ src_common = files(
'backend/BackendManager.cpp',
'backend/Backend.cpp',
'backend/BackendClient.cpp',
+ 'utils/fd.cpp',
)
deps = [
diff --git a/utils/UEvent.h b/utils/UEvent.h
index 64992a1..5b9ecea 100644
--- a/utils/UEvent.h
+++ b/utils/UEvent.h
@@ -24,7 +24,7 @@
#include <optional>
#include <string>
-#include "UniqueFd.h"
+#include "fd.h"
#include "log.h"
namespace android {
@@ -32,7 +32,7 @@ namespace android {
class UEvent {
public:
static auto CreateInstance() -> std::unique_ptr<UEvent> {
- auto fd = UniqueFd(
+ auto fd = MakeUniqueFd(
socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT));
if (!fd) {
@@ -46,7 +46,7 @@ class UEvent {
addr.nl_groups = UINT32_MAX;
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast)
- const int ret = bind(fd.Get(), (struct sockaddr *)&addr, sizeof(addr));
+ const int ret = bind(*fd, (struct sockaddr *)&addr, sizeof(addr));
if (ret != 0) {
ALOGE("Failed to bind uevent socket: errno=%i", errno);
return {};
@@ -59,7 +59,7 @@ class UEvent {
constexpr int kUEventBufferSize = 1024;
char buffer[kUEventBufferSize];
ssize_t ret = 0;
- ret = read(fd_.Get(), &buffer, sizeof(buffer));
+ ret = read(*fd_, &buffer, sizeof(buffer));
if (ret == 0)
return {};
diff --git a/utils/UniqueFd.h b/utils/UniqueFd.h
deleted file mode 100644
index f65bedc..0000000
--- a/utils/UniqueFd.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * 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.
- */
-
-#pragma once
-
-#include <fcntl.h>
-#include <unistd.h>
-
-#include <memory>
-#include <utility>
-
-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_;
- }
-
- static auto Dup(int fd) {
- // NOLINTNEXTLINE(android-cloexec-dup): fcntl has issue (see issue #63)
- return UniqueFd(dup(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
diff --git a/utils/fd.cpp b/utils/fd.cpp
new file mode 100644
index 0000000..395d3b2
--- /dev/null
+++ b/utils/fd.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#include "fd.h"
+
+namespace android {
+
+static void CloseFd(const int *fd) {
+ if (fd != nullptr) {
+ if (*fd >= 0)
+ close(*fd);
+
+ // NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
+ delete fd;
+ }
+}
+
+auto MakeUniqueFd(int fd) -> UniqueFd {
+ if (fd < 0)
+ return {nullptr, CloseFd};
+
+ return {new int(fd), CloseFd};
+}
+
+auto MakeSharedFd(int fd) -> SharedFd {
+ if (fd < 0)
+ return {};
+
+ return {new int(fd), CloseFd};
+}
+
+auto DupFd(SharedFd const &fd) -> int {
+ if (!fd)
+ return -1;
+
+ return fcntl(*fd, F_DUPFD_CLOEXEC, 0);
+}
+
+} // namespace android
diff --git a/utils/fd.h b/utils/fd.h
new file mode 100644
index 0000000..6bfd0fa
--- /dev/null
+++ b/utils/fd.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2015 - 2023 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.
+ */
+
+#pragma once
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <memory>
+#include <utility>
+
+namespace android {
+
+using UniqueFd = std::unique_ptr<int, void (*)(const int *)>;
+using SharedFd = std::shared_ptr<int>;
+
+auto MakeUniqueFd(int fd) -> UniqueFd;
+
+auto MakeSharedFd(int fd) -> SharedFd;
+
+auto DupFd(SharedFd const &fd) -> int;
+
+} // namespace android