summaryrefslogtreecommitdiffstats
path: root/xbmc/utils/DumbBufferObject.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/utils/DumbBufferObject.cpp')
-rw-r--r--xbmc/utils/DumbBufferObject.cpp160
1 files changed, 160 insertions, 0 deletions
diff --git a/xbmc/utils/DumbBufferObject.cpp b/xbmc/utils/DumbBufferObject.cpp
new file mode 100644
index 0000000..84d28ea
--- /dev/null
+++ b/xbmc/utils/DumbBufferObject.cpp
@@ -0,0 +1,160 @@
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 "DumbBufferObject.h"
10
11#include "ServiceBroker.h"
12#include "utils/BufferObjectFactory.h"
13#include "utils/log.h"
14#include "windowing/gbm/WinSystemGbm.h"
15#include "windowing/gbm/WinSystemGbmEGLContext.h"
16
17#include <drm_fourcc.h>
18#include <sys/mman.h>
19
20using namespace KODI::WINDOWING::GBM;
21
22std::unique_ptr<CBufferObject> CDumbBufferObject::Create()
23{
24 return std::make_unique<CDumbBufferObject>();
25}
26
27void CDumbBufferObject::Register()
28{
29 CBufferObjectFactory::RegisterBufferObject(CDumbBufferObject::Create);
30}
31
32CDumbBufferObject::CDumbBufferObject()
33{
34 auto winSystem = static_cast<CWinSystemGbmEGLContext*>(CServiceBroker::GetWinSystem());
35
36 m_device = winSystem->GetDrm()->GetFileDescriptor();
37}
38
39CDumbBufferObject::~CDumbBufferObject()
40{
41 ReleaseMemory();
42 DestroyBufferObject();
43}
44
45bool CDumbBufferObject::CreateBufferObject(uint32_t format, uint32_t width, uint32_t height)
46{
47 if (m_fd >= 0)
48 return true;
49
50 uint32_t bpp;
51
52 switch (format)
53 {
54 case DRM_FORMAT_ARGB1555:
55 case DRM_FORMAT_RGB565:
56 bpp = 16;
57 break;
58 case DRM_FORMAT_ARGB8888:
59 bpp = 32;
60 break;
61 default:
62 throw std::runtime_error("CDumbBufferObject: pixel format not implemented");
63 }
64
65 struct drm_mode_create_dumb create_dumb = {.height = height, .width = width, .bpp = bpp};
66
67 int ret = drmIoctl(m_device, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb);
68 if (ret < 0)
69 {
70 CLog::Log(LOGERROR, "CDumbBufferObject::{} - ioctl DRM_IOCTL_MODE_CREATE_DUMB failed, errno={}",
71 __FUNCTION__, strerror(errno));
72 return false;
73 }
74
75 m_size = create_dumb.size;
76 m_stride = create_dumb.pitch;
77
78 ret = drmPrimeHandleToFD(m_device, create_dumb.handle, 0, &m_fd);
79 if (ret < 0)
80 {
81 CLog::Log(LOGERROR, "CDumbBufferObject::{} - failed to get fd from prime handle, errno={}",
82 __FUNCTION__, strerror(errno));
83 return false;
84 }
85
86 return true;
87}
88
89void CDumbBufferObject::DestroyBufferObject()
90{
91 if (m_fd < 0)
92 return;
93
94 int ret = close(m_fd);
95 if (ret < 0)
96 CLog::Log(LOGERROR, "CDumbBufferObject::{} - close failed, errno={}", __FUNCTION__,
97 strerror(errno));
98
99 m_fd = -1;
100 m_stride = 0;
101 m_size = 0;
102}
103
104uint8_t* CDumbBufferObject::GetMemory()
105{
106 if (m_fd < 0)
107 return nullptr;
108
109 if (m_map)
110 {
111 CLog::Log(LOGDEBUG, "CDumbBufferObject::{} - already mapped fd={} map={}", __FUNCTION__, m_fd,
112 fmt::ptr(m_map));
113 return m_map;
114 }
115
116 uint32_t handle;
117 int ret = drmPrimeFDToHandle(m_device, m_fd, &handle);
118 if (ret < 0)
119 {
120 CLog::Log(LOGERROR, "CDumbBufferObject::{} - failed to get handle from prime fd, errno={}",
121 __FUNCTION__, strerror(errno));
122 return nullptr;
123 }
124
125 struct drm_mode_map_dumb map_dumb = {.handle = handle};
126
127 ret = drmIoctl(m_device, DRM_IOCTL_MODE_MAP_DUMB, &map_dumb);
128 if (ret < 0)
129 {
130 CLog::Log(LOGERROR, "CDumbBufferObject::{} - ioctl DRM_IOCTL_MODE_MAP_DUMB failed, errno={}",
131 __FUNCTION__, strerror(errno));
132 return nullptr;
133 }
134
135 m_offset = map_dumb.offset;
136
137 m_map = static_cast<uint8_t*>(mmap(nullptr, m_size, PROT_WRITE, MAP_SHARED, m_device, m_offset));
138 if (m_map == MAP_FAILED)
139 {
140 CLog::Log(LOGERROR, "CDumbBufferObject::{} - mmap failed, errno={}", __FUNCTION__,
141 strerror(errno));
142 return nullptr;
143 }
144
145 return m_map;
146}
147
148void CDumbBufferObject::ReleaseMemory()
149{
150 if (!m_map)
151 return;
152
153 int ret = munmap(m_map, m_size);
154 if (ret < 0)
155 CLog::Log(LOGERROR, "CDumbBufferObject::{} - munmap failed, errno={}", __FUNCTION__,
156 strerror(errno));
157
158 m_map = nullptr;
159 m_offset = 0;
160}