summaryrefslogtreecommitdiffstats
path: root/xbmc/utils/DMAHeapBufferObject.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/utils/DMAHeapBufferObject.cpp')
-rw-r--r--xbmc/utils/DMAHeapBufferObject.cpp186
1 files changed, 186 insertions, 0 deletions
diff --git a/xbmc/utils/DMAHeapBufferObject.cpp b/xbmc/utils/DMAHeapBufferObject.cpp
new file mode 100644
index 0000000..c9beeb5
--- /dev/null
+++ b/xbmc/utils/DMAHeapBufferObject.cpp
@@ -0,0 +1,186 @@
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 "DMAHeapBufferObject.h"
10
11#include "ServiceBroker.h"
12#include "utils/BufferObjectFactory.h"
13#include "utils/log.h"
14
15#include <array>
16
17#include <drm_fourcc.h>
18#include <linux/dma-heap.h>
19#include <sys/ioctl.h>
20#include <sys/mman.h>
21
22namespace
23{
24
25std::array<const char*, 3> DMA_HEAP_PATHS = {
26 "/dev/dma_heap/reserved",
27 "/dev/dma_heap/linux,cma",
28 "/dev/dma_heap/system",
29};
30
31static const char* DMA_HEAP_PATH;
32
33} // namespace
34
35std::unique_ptr<CBufferObject> CDMAHeapBufferObject::Create()
36{
37 return std::make_unique<CDMAHeapBufferObject>();
38}
39
40void CDMAHeapBufferObject::Register()
41{
42 for (auto path : DMA_HEAP_PATHS)
43 {
44 int fd = open(path, O_RDWR);
45 if (fd < 0)
46 {
47 CLog::Log(LOGDEBUG, "CDMAHeapBufferObject::{} unable to open {}: {}", __FUNCTION__, path,
48 strerror(errno));
49 continue;
50 }
51
52 close(fd);
53 DMA_HEAP_PATH = path;
54 break;
55 }
56
57 if (!DMA_HEAP_PATH)
58 return;
59
60 CLog::Log(LOGDEBUG, "CDMAHeapBufferObject::{} - using {}", __FUNCTION__, DMA_HEAP_PATH);
61
62 CBufferObjectFactory::RegisterBufferObject(CDMAHeapBufferObject::Create);
63}
64
65CDMAHeapBufferObject::~CDMAHeapBufferObject()
66{
67 ReleaseMemory();
68 DestroyBufferObject();
69
70 close(m_dmaheapfd);
71 m_dmaheapfd = -1;
72}
73
74bool CDMAHeapBufferObject::CreateBufferObject(uint32_t format, uint32_t width, uint32_t height)
75{
76 if (m_fd >= 0)
77 return true;
78
79 uint32_t bpp{1};
80
81 switch (format)
82 {
83 case DRM_FORMAT_ARGB8888:
84 bpp = 4;
85 break;
86 case DRM_FORMAT_ARGB1555:
87 case DRM_FORMAT_RGB565:
88 bpp = 2;
89 break;
90 default:
91 throw std::runtime_error("CDMAHeapBufferObject: pixel format not implemented");
92 }
93
94 m_stride = width * bpp;
95
96 return CreateBufferObject(width * height * bpp);
97}
98
99bool CDMAHeapBufferObject::CreateBufferObject(uint64_t size)
100{
101 m_size = size;
102
103 if (m_dmaheapfd < 0)
104 {
105 m_dmaheapfd = open(DMA_HEAP_PATH, O_RDWR);
106 if (m_dmaheapfd < 0)
107 {
108 CLog::LogF(LOGERROR, "failed to open {}:", DMA_HEAP_PATH, strerror(errno));
109 return false;
110 }
111 }
112
113 struct dma_heap_allocation_data allocData = {
114 .len = m_size, .fd_flags = (O_CLOEXEC | O_RDWR), .heap_flags = 0};
115
116 int ret = ioctl(m_dmaheapfd, DMA_HEAP_IOCTL_ALLOC, &allocData);
117 if (ret < 0)
118 {
119 CLog::Log(LOGERROR, "CDMAHeapBufferObject::{} - ioctl DMA_HEAP_IOCTL_ALLOC failed, errno={}",
120 __FUNCTION__, strerror(errno));
121 return false;
122 }
123
124 m_fd = allocData.fd;
125 m_size = allocData.len;
126
127 if (m_fd < 0 || m_size <= 0)
128 {
129 CLog::Log(LOGERROR, "CDMAHeapBufferObject::{} - invalid allocation data: fd={} len={}",
130 __FUNCTION__, m_fd, m_size);
131 return false;
132 }
133
134 return true;
135}
136
137void CDMAHeapBufferObject::DestroyBufferObject()
138{
139 if (m_fd < 0)
140 return;
141
142 int ret = close(m_fd);
143 if (ret < 0)
144 CLog::Log(LOGERROR, "CDMAHeapBufferObject::{} - close failed, errno={}", __FUNCTION__,
145 strerror(errno));
146
147 m_fd = -1;
148 m_stride = 0;
149 m_size = 0;
150}
151
152uint8_t* CDMAHeapBufferObject::GetMemory()
153{
154 if (m_fd < 0)
155 return nullptr;
156
157 if (m_map)
158 {
159 CLog::Log(LOGDEBUG, "CDMAHeapBufferObject::{} - already mapped fd={} map={}", __FUNCTION__,
160 m_fd, fmt::ptr(m_map));
161 return m_map;
162 }
163
164 m_map = static_cast<uint8_t*>(mmap(nullptr, m_size, PROT_WRITE, MAP_SHARED, m_fd, 0));
165 if (m_map == MAP_FAILED)
166 {
167 CLog::Log(LOGERROR, "CDMAHeapBufferObject::{} - mmap failed, errno={}", __FUNCTION__,
168 strerror(errno));
169 return nullptr;
170 }
171
172 return m_map;
173}
174
175void CDMAHeapBufferObject::ReleaseMemory()
176{
177 if (!m_map)
178 return;
179
180 int ret = munmap(m_map, m_size);
181 if (ret < 0)
182 CLog::Log(LOGERROR, "CDMAHeapBufferObject::{} - munmap failed, errno={}", __FUNCTION__,
183 strerror(errno));
184
185 m_map = nullptr;
186}