2 * Copyright (C) 2005-2020 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
9 #include "UDMABufferObject.h"
11 #include "utils/BufferObjectFactory.h"
12 #include "utils/log.h"
14 #include <drm_fourcc.h>
16 #include <linux/udmabuf.h>
17 #include <sys/ioctl.h>
21 #include "PlatformDefs.h"
26 const auto PAGESIZE
= getpagesize();
28 int RoundUp(int num
, int factor
)
30 return num
+ factor
- 1 - (num
- 1) % factor
;
35 std::unique_ptr
<CBufferObject
> CUDMABufferObject::Create()
37 return std::make_unique
<CUDMABufferObject
>();
40 void CUDMABufferObject::Register()
42 int fd
= open("/dev/udmabuf", O_RDWR
);
45 CLog::Log(LOGDEBUG
, "CUDMABufferObject::{} - unable to open /dev/udmabuf: {}", __FUNCTION__
,
52 CBufferObjectFactory::RegisterBufferObject(CUDMABufferObject::Create
);
55 CUDMABufferObject::~CUDMABufferObject()
58 DestroyBufferObject();
60 int ret
= close(m_udmafd
);
62 CLog::Log(LOGERROR
, "CUDMABufferObject::{} - close /dev/udmabuf failed, errno={}", __FUNCTION__
,
68 bool CUDMABufferObject::CreateBufferObject(uint32_t format
, uint32_t width
, uint32_t height
)
77 case DRM_FORMAT_ARGB8888
:
80 case DRM_FORMAT_ARGB1555
:
81 case DRM_FORMAT_RGB565
:
85 throw std::runtime_error("CUDMABufferObject: pixel format not implemented");
88 m_stride
= width
* bpp
;
90 return CreateBufferObject(width
* height
* bpp
);
93 bool CUDMABufferObject::CreateBufferObject(uint64_t size
)
95 // Must be rounded to the system page size
96 m_size
= RoundUp(size
, PAGESIZE
);
98 m_memfd
= memfd_create("kodi", MFD_CLOEXEC
| MFD_ALLOW_SEALING
);
101 CLog::Log(LOGERROR
, "CUDMABufferObject::{} - memfd_create failed: {}", __FUNCTION__
,
106 if (ftruncate(m_memfd
, m_size
) < 0)
108 CLog::Log(LOGERROR
, "CUDMABufferObject::{} - ftruncate failed: {}", __FUNCTION__
,
113 if (fcntl(m_memfd
, F_ADD_SEALS
, F_SEAL_SHRINK
) < 0)
115 CLog::Log(LOGERROR
, "CUDMABufferObject::{} - fcntl failed: {}", __FUNCTION__
, strerror(errno
));
122 m_udmafd
= open("/dev/udmabuf", O_RDWR
);
125 CLog::Log(LOGERROR
, "CUDMABufferObject::{} - unable to open /dev/udmabuf: {}", __FUNCTION__
,
132 struct udmabuf_create_item create
{};
133 create
.memfd
= static_cast<uint32_t>(m_memfd
);
135 create
.size
= m_size
;
137 m_fd
= ioctl(m_udmafd
, UDMABUF_CREATE
, &create
);
140 CLog::Log(LOGERROR
, "CUDMABufferObject::{} - ioctl UDMABUF_CREATE failed: {}", __FUNCTION__
,
149 void CUDMABufferObject::DestroyBufferObject()
154 int ret
= close(m_fd
);
156 CLog::Log(LOGERROR
, "CUDMABufferObject::{} - close fd failed, errno={}", __FUNCTION__
,
159 ret
= close(m_memfd
);
161 CLog::Log(LOGERROR
, "CUDMABufferObject::{} - close memfd failed, errno={}", __FUNCTION__
,
170 uint8_t* CUDMABufferObject::GetMemory()
177 CLog::Log(LOGDEBUG
, "CUDMABufferObject::{} - already mapped fd={} map={}", __FUNCTION__
, m_fd
,
182 m_map
= static_cast<uint8_t*>(mmap(nullptr, m_size
, PROT_WRITE
, MAP_SHARED
, m_memfd
, 0));
183 if (m_map
== MAP_FAILED
)
185 CLog::Log(LOGERROR
, "CUDMABufferObject::{} - mmap failed, errno={}", __FUNCTION__
,
193 void CUDMABufferObject::ReleaseMemory()
198 int ret
= munmap(m_map
, m_size
);
200 CLog::Log(LOGERROR
, "CUDMABufferObject::{} - munmap failed, errno={}", __FUNCTION__
,