Files
BPI-CM9-Linux/aml-comp/vendor/amlogic/meson_display/common/base/DrmSync.cpp
T
2026-08-24 10:03:24 +08:00

169 lines
4.3 KiB
C++

/*
* Copyright (c) 2017 Amlogic, Inc. All rights reserved.
*
* This source code is subject to the terms and conditions defined in the
* file 'LICENSE' which is part of this source code package.
*
* Description:
*/
#include <drm.h>
#include <drm_fourcc.h>
#include <DrmSync.h>
#include <unistd.h>
#include <sync.h>
#include <sys/types.h>
#include <string.h>
#include <errno.h>
#include <MesonLog.h>
#ifdef __ANDROID__
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
#include <utils/Trace.h>
#endif
#define DRM_IOCTL_MESON_CREATE_FENCE DRM_IOWR(DRM_COMMAND_BASE + \
0x21, struct meson_drm_create_fence)
#define DRM_IOCTL_MESON_SIGNAL_FENCE DRM_IOWR(DRM_COMMAND_BASE + \
0x22, struct meson_drm_signal_fence)
typedef struct meson_drm_create_fence {
uint64_t context_id;
uint64_t seqno;
uint32_t fence_fd; /* out */
uint32_t flags;
} meson_drm_create_fence_t;
typedef struct meson_drm_signal_fence {
uint32_t fence_fd; /* in */
uint32_t flags;
} meson_drm_signal_fence_t;
const std::shared_ptr<DrmFence> DrmFence::NO_FENCE =
std::make_shared<DrmFence>(-1);
int32_t DrmFence::drmDevFd = -1;
DrmFence::DrmFence(int32_t fd) {
mFenceFd = fd;
}
DrmFence::~DrmFence() {
if (mFenceFd >= 0) {
close(mFenceFd);
mFenceFd = -1;
}
}
int32_t DrmFence::wait(int timeout) {
#ifdef __ANDROID__
ATRACE_CALL();
#endif
if (mFenceFd == -1) {
return 0;
}
int err = sync_wait(mFenceFd, timeout);
return err < 0 ? -errno : 0;
}
int32_t DrmFence::waitForever(const char* logname) {
#ifdef __ANDROID__
ATRACE_CALL();
#endif
if (mFenceFd == -1) {
return 0;
}
int warningTimeout = 3000;
int err = sync_wait(mFenceFd, warningTimeout);
if (err < 0 && errno == ETIME) {
MESON_LOGE("%s: fence %d didn't signal in %u ms", logname, mFenceFd,
warningTimeout);
err = sync_wait(mFenceFd, -1);
}
return err < 0 ? -errno : 0;
}
std::shared_ptr<DrmFence> DrmFence::merge(const char * name,
const std::shared_ptr<DrmFence> &f1,
const std::shared_ptr<DrmFence> &f2) {
int result;
// Merge the two fences. In the case where one of the fences is not a
// valid fence (e.g. NO_FENCE) we merge the one valid fence with itself so
// that a new fence with the given name is created.
if (f1->isValid() && f2->isValid()) {
result = sync_merge(name, f1->mFenceFd, f2->mFenceFd);
} else if (f1->isValid()) {
result = sync_merge(name, f1->mFenceFd, f1->mFenceFd);
} else if (f2->isValid()) {
result = sync_merge(name, f2->mFenceFd, f2->mFenceFd);
} else {
return NO_FENCE;
}
if (result == -1) {
int err = -errno;
MESON_LOGE("merge: sync_merge(\"%s\", %d, %d) returned an error: %s (%d)",
name, f1->mFenceFd, f2->mFenceFd,
strerror(-err), err);
return NO_FENCE;
}
return std::shared_ptr<DrmFence>(new DrmFence(result));
}
int32_t DrmFence::dup() const{
if (-1 == mFenceFd) {
return -1;
}
int32_t dupFence = ::dup(mFenceFd);
if (dupFence < 0) {
MESON_LOGE("fence %d dup failed: %s! please check it immediately!",
mFenceFd, strerror(errno));
}
return dupFence;
}
/**
* Create a private fence.
*
* @param fence [out] File descriptor of the created fence on success
* @return 0 on success, negative error code on failure
*/
int32_t DrmFence::create_private_fence(int32_t &fence) {
meson_drm_create_fence_t drmFence;
drmFence.context_id = 0xFF;
drmFence.seqno = 0xFF;
auto ret = ioctl(drmDevFd, DRM_IOCTL_MESON_CREATE_FENCE, &drmFence);
if (ret) {
fence = -1;
MESON_LOGE("%s failed, ret: %d", __func__, ret);
} else {
fence = drmFence.fence_fd;
}
return ret;
}
/**
* Signal a private fence to indicate completion.
*
* @param fence File descriptor of the fence to signal
* @return 0 on success, negative error code on failure
*/
int32_t DrmFence::signal_private_fence(int32_t fence) {
if (fence < 0) {
MESON_LOGV("%s is invalid!", __func__);
return -1;
}
meson_drm_signal_fence_t drmFence;
drmFence.fence_fd = fence;
auto ret = ioctl(drmDevFd, DRM_IOCTL_MESON_SIGNAL_FENCE, &drmFence);
if (ret) {
MESON_LOGE("%s failed, ret: %d, errno: %d", __func__, ret, errno);
}
return ret;
}