162 lines
4.0 KiB
C++
162 lines
4.0 KiB
C++
/*
|
|
* Copyright (c) 2021 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:
|
|
*/
|
|
|
|
#define LOG_NDEBUG 1
|
|
#define UVM_DETACH_HOLD_MAX_BUFFER (8)
|
|
|
|
#include <MesonLog.h>
|
|
#include "UvmDetach.h"
|
|
|
|
#ifndef LINUX_COMPILE
|
|
#include "HwcConfig.h"
|
|
#endif
|
|
|
|
UvmDetach::UvmDetach(hwc2_layer_t layerId) {
|
|
snprintf(mName, 20, "layer-%d", (int)layerId);
|
|
mUvmBufferQueue.clear();
|
|
mEnable = true;
|
|
}
|
|
|
|
UvmDetach::UvmDetach(int tunnelId) {
|
|
snprintf(mName, 20, "layer-%d", tunnelId);
|
|
mUvmBufferQueue.clear();
|
|
mEnable = true;
|
|
}
|
|
|
|
UvmDetach::~UvmDetach() {
|
|
releaseUvmResource();
|
|
}
|
|
|
|
int32_t UvmDetach::getVideoInfo(struct uvm_fd_info & videoInfo) {
|
|
return UvmDev::getInstance().getVideoInfo(videoInfo);
|
|
}
|
|
|
|
int32_t UvmDetach::setEnable(bool enable) {
|
|
MESON_LOGV("%s, setEnable %s", __func__, enable ? "true" : "false");
|
|
mEnable = enable;
|
|
return 0;
|
|
}
|
|
|
|
int32_t UvmDetach::attachUvmBuffer(int bufferFd) {
|
|
if (bufferFd < 0)
|
|
return -1;
|
|
|
|
#ifndef LINUX_COMPILE
|
|
if (HwcConfig::UvmDetachEnabled() && mEnable) {
|
|
#else
|
|
if (mEnable) {
|
|
#endif
|
|
return UvmDev::getInstance().attachBuffer(bufferFd);
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
int32_t UvmDetach::detachUvmBuffer() {
|
|
#ifndef LINUX_COMPILE
|
|
if (HwcConfig::UvmDetachEnabled() && mEnable) {
|
|
#else
|
|
if (mEnable) {
|
|
#endif
|
|
int signalCount = 0;
|
|
if (mUvmBufferQueue.size() <= 0)
|
|
return -EAGAIN;
|
|
|
|
for (auto it = mUvmBufferQueue.begin(); it != mUvmBufferQueue.end(); it++) {
|
|
auto currentStatus = it->releaseFence->getStatus();
|
|
/* fence was signal */
|
|
if (currentStatus == DrmFence::Status::Invalid ||
|
|
currentStatus == DrmFence::Status::Signaled)
|
|
signalCount ++;
|
|
}
|
|
|
|
MESON_LOGV("%s: %s UvmBufferQueue size:%zu, signalCount:%d",
|
|
__func__, mName, mUvmBufferQueue.size(), signalCount);
|
|
|
|
while (signalCount > 0) {
|
|
auto item = mUvmBufferQueue.front();
|
|
MESON_LOGV("%s: %s bufferFd:%d, fenceStatus:%d",
|
|
__func__, mName, item.bufferFd, item.releaseFence->getStatus());
|
|
|
|
UvmDev::getInstance().detachBuffer(item.bufferFd);
|
|
if (item.bufferFd >= 0)
|
|
close(item.bufferFd);
|
|
|
|
mUvmBufferQueue.pop_front();
|
|
|
|
signalCount --;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int32_t UvmDetach::collectUvmBuffer(const int fd, const int fenceFd) {
|
|
#ifndef LINUX_COMPILE
|
|
if (HwcConfig::UvmDetachEnabled() && mEnable) {
|
|
#else
|
|
if (mEnable) {
|
|
#endif
|
|
if (fd < 0) {
|
|
MESON_LOGV("%s: %s get an invalid fd", __func__, mName);
|
|
if (fenceFd >=0 )
|
|
close(fenceFd);
|
|
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (fenceFd < 0) {
|
|
MESON_LOGV("%s: %s get an invalid fenceFd", __func__, mName);
|
|
UvmDev::getInstance().detachBuffer(fd);
|
|
close(fd);
|
|
return 0;
|
|
}
|
|
|
|
if (mUvmBufferQueue.size() >= UVM_DETACH_HOLD_MAX_BUFFER) {
|
|
int count = mUvmBufferQueue.size() - UVM_DETACH_HOLD_MAX_BUFFER;
|
|
for (int i = 0; i <= count; i++) {
|
|
auto item = mUvmBufferQueue.front();
|
|
if (item.bufferFd >= 0)
|
|
close(item.bufferFd);
|
|
|
|
mUvmBufferQueue.pop_front();
|
|
}
|
|
}
|
|
|
|
UvmBuffer item = {fd, std::move(std::make_shared<DrmFence>(fenceFd))};
|
|
mUvmBufferQueue.push_back(std::move(item));
|
|
} else {
|
|
if (fd >= 0) {
|
|
close(fd);
|
|
}
|
|
if (fenceFd >= 0) {
|
|
close(fenceFd);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int32_t UvmDetach::releaseUvmResource() {
|
|
#ifndef LINUX_COMPILE
|
|
if (HwcConfig::UvmDetachEnabled()) {
|
|
#else
|
|
{
|
|
#endif
|
|
for (auto it = mUvmBufferQueue.begin(); it != mUvmBufferQueue.end(); it++) {
|
|
if (it->bufferFd >= 0)
|
|
close(it->bufferFd);
|
|
}
|
|
mUvmBufferQueue.clear();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|