diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 18:07:22 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 18:07:22 +0000 |
commit | c04dcc2e7d834218ef2d4194331e383402495ae1 (patch) | |
tree | 7333e38d10d75386e60f336b80c2443c1166031d /xbmc/utils/DumbBufferObject.cpp | |
parent | Initial commit. (diff) | |
download | kodi-c04dcc2e7d834218ef2d4194331e383402495ae1.tar.xz kodi-c04dcc2e7d834218ef2d4194331e383402495ae1.zip |
Adding upstream version 2:20.4+dfsg.upstream/2%20.4+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'xbmc/utils/DumbBufferObject.cpp')
-rw-r--r-- | xbmc/utils/DumbBufferObject.cpp | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/xbmc/utils/DumbBufferObject.cpp b/xbmc/utils/DumbBufferObject.cpp new file mode 100644 index 0000000..51e518a --- /dev/null +++ b/xbmc/utils/DumbBufferObject.cpp @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2005-2020 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "DumbBufferObject.h" + +#include "ServiceBroker.h" +#include "utils/BufferObjectFactory.h" +#include "utils/log.h" +#include "windowing/gbm/WinSystemGbm.h" +#include "windowing/gbm/WinSystemGbmEGLContext.h" + +#include <drm_fourcc.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <unistd.h> + +#include "PlatformDefs.h" + +using namespace KODI::WINDOWING::GBM; + +std::unique_ptr<CBufferObject> CDumbBufferObject::Create() +{ + return std::make_unique<CDumbBufferObject>(); +} + +void CDumbBufferObject::Register() +{ + CBufferObjectFactory::RegisterBufferObject(CDumbBufferObject::Create); +} + +CDumbBufferObject::CDumbBufferObject() +{ + auto winSystem = static_cast<CWinSystemGbmEGLContext*>(CServiceBroker::GetWinSystem()); + + m_device = winSystem->GetDrm()->GetFileDescriptor(); +} + +CDumbBufferObject::~CDumbBufferObject() +{ + ReleaseMemory(); + DestroyBufferObject(); +} + +bool CDumbBufferObject::CreateBufferObject(uint32_t format, uint32_t width, uint32_t height) +{ + if (m_fd >= 0) + return true; + + uint32_t bpp; + + switch (format) + { + case DRM_FORMAT_ARGB1555: + case DRM_FORMAT_RGB565: + bpp = 16; + break; + case DRM_FORMAT_ARGB8888: + bpp = 32; + break; + default: + throw std::runtime_error("CDumbBufferObject: pixel format not implemented"); + } + + struct drm_mode_create_dumb create_dumb{}; + create_dumb.height = height; + create_dumb.width = width; + create_dumb.bpp = bpp; + + int ret = drmIoctl(m_device, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb); + if (ret < 0) + { + CLog::Log(LOGERROR, "CDumbBufferObject::{} - ioctl DRM_IOCTL_MODE_CREATE_DUMB failed, errno={}", + __FUNCTION__, strerror(errno)); + return false; + } + + m_size = create_dumb.size; + m_stride = create_dumb.pitch; + + ret = drmPrimeHandleToFD(m_device, create_dumb.handle, 0, &m_fd); + if (ret < 0) + { + CLog::Log(LOGERROR, "CDumbBufferObject::{} - failed to get fd from prime handle, errno={}", + __FUNCTION__, strerror(errno)); + return false; + } + + return true; +} + +void CDumbBufferObject::DestroyBufferObject() +{ + if (m_fd < 0) + return; + + int ret = close(m_fd); + if (ret < 0) + CLog::Log(LOGERROR, "CDumbBufferObject::{} - close failed, errno={}", __FUNCTION__, + strerror(errno)); + + m_fd = -1; + m_stride = 0; + m_size = 0; +} + +uint8_t* CDumbBufferObject::GetMemory() +{ + if (m_fd < 0) + return nullptr; + + if (m_map) + { + CLog::Log(LOGDEBUG, "CDumbBufferObject::{} - already mapped fd={} map={}", __FUNCTION__, m_fd, + fmt::ptr(m_map)); + return m_map; + } + + uint32_t handle; + int ret = drmPrimeFDToHandle(m_device, m_fd, &handle); + if (ret < 0) + { + CLog::Log(LOGERROR, "CDumbBufferObject::{} - failed to get handle from prime fd, errno={}", + __FUNCTION__, strerror(errno)); + return nullptr; + } + + struct drm_mode_map_dumb map_dumb{}; + map_dumb.handle = handle; + + ret = drmIoctl(m_device, DRM_IOCTL_MODE_MAP_DUMB, &map_dumb); + if (ret < 0) + { + CLog::Log(LOGERROR, "CDumbBufferObject::{} - ioctl DRM_IOCTL_MODE_MAP_DUMB failed, errno={}", + __FUNCTION__, strerror(errno)); + return nullptr; + } + + m_offset = map_dumb.offset; + + m_map = static_cast<uint8_t*>(mmap(nullptr, m_size, PROT_WRITE, MAP_SHARED, m_device, m_offset)); + if (m_map == MAP_FAILED) + { + CLog::Log(LOGERROR, "CDumbBufferObject::{} - mmap failed, errno={}", __FUNCTION__, + strerror(errno)); + return nullptr; + } + + return m_map; +} + +void CDumbBufferObject::ReleaseMemory() +{ + if (!m_map) + return; + + int ret = munmap(m_map, m_size); + if (ret < 0) + CLog::Log(LOGERROR, "CDumbBufferObject::{} - munmap failed, errno={}", __FUNCTION__, + strerror(errno)); + + m_map = nullptr; + m_offset = 0; +} |