summaryrefslogtreecommitdiffstats
path: root/xbmc/utils/UDMABufferObject.cpp
diff options
context:
space:
mode:
authormanuel <manuel@mausz.at>2020-10-19 00:52:24 +0200
committermanuel <manuel@mausz.at>2020-10-19 00:52:24 +0200
commitbe933ef2241d79558f91796cc5b3a161f72ebf9c (patch)
treefe3ab2f130e20c99001f2d7a81d610c78c96a3f4 /xbmc/utils/UDMABufferObject.cpp
parent5f8335c1e49ce108ef3481863833c98efa00411b (diff)
downloadkodi-pvr-build-be933ef2241d79558f91796cc5b3a161f72ebf9c.tar.gz
kodi-pvr-build-be933ef2241d79558f91796cc5b3a161f72ebf9c.tar.bz2
kodi-pvr-build-be933ef2241d79558f91796cc5b3a161f72ebf9c.zip
sync with upstream
Diffstat (limited to 'xbmc/utils/UDMABufferObject.cpp')
-rw-r--r--xbmc/utils/UDMABufferObject.cpp201
1 files changed, 201 insertions, 0 deletions
diff --git a/xbmc/utils/UDMABufferObject.cpp b/xbmc/utils/UDMABufferObject.cpp
new file mode 100644
index 0000000..b488d78
--- /dev/null
+++ b/xbmc/utils/UDMABufferObject.cpp
@@ -0,0 +1,201 @@
1/*
2 * Copyright (C) 2005-2020 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
8
9#include "UDMABufferObject.h"
10
11#include "utils/BufferObjectFactory.h"
12#include "utils/log.h"
13
14#include <drm_fourcc.h>
15#include <linux/udmabuf.h>
16#include <sys/ioctl.h>
17#include <sys/mman.h>
18
19namespace
20{
21
22const auto PAGESIZE = getpagesize();
23
24int RoundUp(int num, int factor)
25{
26 return num + factor - 1 - (num - 1) % factor;
27}
28
29} // namespace
30
31std::unique_ptr<CBufferObject> CUDMABufferObject::Create()
32{
33 return std::make_unique<CUDMABufferObject>();
34}
35
36void CUDMABufferObject::Register()
37{
38 int fd = open("/dev/udmabuf", O_RDWR);
39 if (fd < 0)
40 {
41 CLog::Log(LOGDEBUG, "CUDMABufferObject::{} - unable to open /dev/udmabuf: {}", __FUNCTION__,
42 strerror(errno));
43 return;
44 }
45
46 close(fd);
47
48 CBufferObjectFactory::RegisterBufferObject(CUDMABufferObject::Create);
49}
50
51CUDMABufferObject::~CUDMABufferObject()
52{
53 ReleaseMemory();
54 DestroyBufferObject();
55
56 int ret = close(m_udmafd);
57 if (ret < 0)
58 CLog::Log(LOGERROR, "CUDMABufferObject::{} - close /dev/udmabuf failed, errno={}", __FUNCTION__,
59 strerror(errno));
60
61 m_udmafd = -1;
62}
63
64bool CUDMABufferObject::CreateBufferObject(uint32_t format, uint32_t width, uint32_t height)
65{
66 if (m_fd >= 0)
67 return true;
68
69 uint32_t bpp{1};
70
71 switch (format)
72 {
73 case DRM_FORMAT_ARGB8888:
74 bpp = 4;
75 break;
76 case DRM_FORMAT_ARGB1555:
77 case DRM_FORMAT_RGB565:
78 bpp = 2;
79 break;
80 default:
81 throw std::runtime_error("CUDMABufferObject: pixel format not implemented");
82 }
83
84 m_stride = width * bpp;
85
86 return CreateBufferObject(width * height * bpp);
87}
88
89bool CUDMABufferObject::CreateBufferObject(uint64_t size)
90{
91 // Must be rounded to the system page size
92 m_size = RoundUp(size, PAGESIZE);
93
94 m_memfd = memfd_create("kodi", MFD_CLOEXEC | MFD_ALLOW_SEALING);
95 if (m_memfd < 0)
96 {
97 CLog::Log(LOGERROR, "CUDMABufferObject::{} - memfd_create failed: {}", __FUNCTION__,
98 strerror(errno));
99 return false;
100 }
101
102 if (ftruncate(m_memfd, m_size) < 0)
103 {
104 CLog::Log(LOGERROR, "CUDMABufferObject::{} - ftruncate failed: {}", __FUNCTION__,
105 strerror(errno));
106 return false;
107 }
108
109 if (fcntl(m_memfd, F_ADD_SEALS, F_SEAL_SHRINK) < 0)
110 {
111 CLog::Log(LOGERROR, "CUDMABufferObject::{} - fcntl failed: {}", __FUNCTION__, strerror(errno));
112 close(m_memfd);
113 return false;
114 }
115
116 if (m_udmafd < 0)
117 {
118 m_udmafd = open("/dev/udmabuf", O_RDWR);
119 if (m_udmafd < 0)
120 {
121 CLog::Log(LOGERROR, "CUDMABufferObject::{} - unable to open /dev/udmabuf: {}", __FUNCTION__,
122 strerror(errno));
123 close(m_memfd);
124 return false;
125 }
126 }
127
128 struct udmabuf_create_item create = {
129 .memfd = static_cast<uint32_t>(m_memfd),
130 .offset = 0,
131 .size = m_size,
132 };
133
134 m_fd = ioctl(m_udmafd, UDMABUF_CREATE, &create);
135 if (m_fd < 0)
136 {
137 CLog::Log(LOGERROR, "CUDMABufferObject::{} - ioctl UDMABUF_CREATE failed: {}", __FUNCTION__,
138 strerror(errno));
139 close(m_memfd);
140 return false;
141 }
142
143 return true;
144}
145
146void CUDMABufferObject::DestroyBufferObject()
147{
148 if (m_fd < 0)
149 return;
150
151 int ret = close(m_fd);
152 if (ret < 0)
153 CLog::Log(LOGERROR, "CUDMABufferObject::{} - close fd failed, errno={}", __FUNCTION__,
154 strerror(errno));
155
156 ret = close(m_memfd);
157 if (ret < 0)
158 CLog::Log(LOGERROR, "CUDMABufferObject::{} - close memfd failed, errno={}", __FUNCTION__,
159 strerror(errno));
160
161 m_memfd = -1;
162 m_fd = -1;
163 m_stride = 0;
164 m_size = 0;
165}
166
167uint8_t* CUDMABufferObject::GetMemory()
168{
169 if (m_fd < 0)
170 return nullptr;
171
172 if (m_map)
173 {
174 CLog::Log(LOGDEBUG, "CUDMABufferObject::{} - already mapped fd={} map={}", __FUNCTION__, m_fd,
175 fmt::ptr(m_map));
176 return m_map;
177 }
178
179 m_map = static_cast<uint8_t*>(mmap(nullptr, m_size, PROT_WRITE, MAP_SHARED, m_memfd, 0));
180 if (m_map == MAP_FAILED)
181 {
182 CLog::Log(LOGERROR, "CUDMABufferObject::{} - mmap failed, errno={}", __FUNCTION__,
183 strerror(errno));
184 return nullptr;
185 }
186
187 return m_map;
188}
189
190void CUDMABufferObject::ReleaseMemory()
191{
192 if (!m_map)
193 return;
194
195 int ret = munmap(m_map, m_size);
196 if (ret < 0)
197 CLog::Log(LOGERROR, "CUDMABufferObject::{} - munmap failed, errno={}", __FUNCTION__,
198 strerror(errno));
199
200 m_map = nullptr;
201}