diff options
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | kms++/CMakeLists.txt | 14 | ||||
-rw-r--r-- | kms++/inc/kms++/omap/omapcard.h | 21 | ||||
-rw-r--r-- | kms++/inc/kms++/omap/omapframebuffer.h | 52 | ||||
-rw-r--r-- | kms++/inc/kms++/omap/omapkms++.h | 4 | ||||
-rw-r--r-- | kms++/src/omap/omapcard.cpp | 29 | ||||
-rw-r--r-- | kms++/src/omap/omapframebuffer.cpp | 126 |
7 files changed, 246 insertions, 1 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 482771f..30cb5f5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,6 +59,7 @@ endif() find_package(PkgConfig REQUIRED) pkg_check_modules(LIBDRM libdrm>=2.4.64 REQUIRED) +pkg_check_modules(LIBDRM_OMAP libdrm_omap) enable_testing() diff --git a/kms++/CMakeLists.txt b/kms++/CMakeLists.txt index 51ccc65..10352a2 100644 --- a/kms++/CMakeLists.txt +++ b/kms++/CMakeLists.txt @@ -1,8 +1,20 @@ include_directories(${LIBDRM_INCLUDE_DIRS}) link_directories(${LIBDRM_LIBRARY_DIRS}) +include_directories(${LIBDRM_OMAP_INCLUDE_DIRS}) +link_directories(${LIBDRM_OMAP_LIBRARY_DIRS}) + file(GLOB SRCS "src/*.cpp" "src/*.h") file(GLOB PUB_HDRS "inc/kms++/*.h") + +if(LIBDRM_OMAP_FOUND) + file(GLOB OMAP_SRCS "src/omap/*.cpp" "src/omap/*.h") + file(GLOB OMAP_PUB_HDRS "inc/kms++/omap/*.h") + + set(SRCS ${SRCS} ${OMAP_SRCS}) + set(PUB_HDRS ${PUB_HDRS} ${OMAP_PUB_HDRS}) +endif() + add_library(kms++ ${SRCS} ${PUB_HDRS}) target_include_directories(kms++ PUBLIC @@ -10,7 +22,7 @@ target_include_directories(kms++ PUBLIC $<INSTALL_INTERFACE:include> PRIVATE src) -target_link_libraries(kms++ ${LIBDRM_LIBRARIES}) +target_link_libraries(kms++ ${LIBDRM_LIBRARIES} ${LIBDRM_OMAP_LIBRARIES}) set_target_properties(kms++ PROPERTIES PUBLIC_HEADER "${PUB_HDRS}") diff --git a/kms++/inc/kms++/omap/omapcard.h b/kms++/inc/kms++/omap/omapcard.h new file mode 100644 index 0000000..5c2f3a5 --- /dev/null +++ b/kms++/inc/kms++/omap/omapcard.h @@ -0,0 +1,21 @@ +#pragma once + +#include <kms++/card.h> + +struct omap_device; + +namespace kms +{ +class OmapCard : public Card +{ +public: + OmapCard(); + OmapCard(const std::string& device); + virtual ~OmapCard(); + + struct omap_device* dev() const { return m_omap_dev; } + +private: + struct omap_device* m_omap_dev; +}; +} diff --git a/kms++/inc/kms++/omap/omapframebuffer.h b/kms++/inc/kms++/omap/omapframebuffer.h new file mode 100644 index 0000000..b39ede6 --- /dev/null +++ b/kms++/inc/kms++/omap/omapframebuffer.h @@ -0,0 +1,52 @@ +#pragma once + +#include <kms++/mappedframebuffer.h> +#include <kms++/pixelformats.h> + +struct omap_bo; + +namespace kms +{ +class OmapCard; + +class OmapFramebuffer : public MappedFramebuffer +{ +public: + OmapFramebuffer(OmapCard& card, uint32_t width, uint32_t height, PixelFormat format); + virtual ~OmapFramebuffer(); + + uint32_t width() const { return Framebuffer::width(); } + uint32_t height() const { return Framebuffer::height(); } + + PixelFormat format() const { return m_format; } + unsigned num_planes() const { return m_num_planes; } + + uint32_t handle(unsigned plane) const { return m_planes[plane].handle; } + uint32_t stride(unsigned plane) const { return m_planes[plane].stride; } + uint32_t size(unsigned plane) const { return m_planes[plane].size; } + uint32_t offset(unsigned plane) const { return m_planes[plane].offset; } + uint8_t* map(unsigned plane); + int prime_fd(unsigned plane); + +private: + OmapCard& m_omap_card; + + struct FramebufferPlane { + struct omap_bo* omap_bo; + uint32_t handle; + int prime_fd; + uint32_t size; + uint32_t stride; + uint32_t offset; + uint8_t* map; + }; + + void Create(); + void Destroy(); + + unsigned m_num_planes; + struct FramebufferPlane m_planes[3]; + + PixelFormat m_format; +}; +} diff --git a/kms++/inc/kms++/omap/omapkms++.h b/kms++/inc/kms++/omap/omapkms++.h new file mode 100644 index 0000000..0d86841 --- /dev/null +++ b/kms++/inc/kms++/omap/omapkms++.h @@ -0,0 +1,4 @@ +#pragma once + +#include <kms++/omap/omapcard.h> +#include <kms++/omap/omapframebuffer.h> diff --git a/kms++/src/omap/omapcard.cpp b/kms++/src/omap/omapcard.cpp new file mode 100644 index 0000000..e811b6d --- /dev/null +++ b/kms++/src/omap/omapcard.cpp @@ -0,0 +1,29 @@ + +#include <kms++/omap/omapcard.h> + +extern "C" { +#include <omap_drmif.h> +} + +using namespace std; + +namespace kms +{ +OmapCard::OmapCard() + : OmapCard("/dev/dri/card0") +{ + +} + +OmapCard::OmapCard(const string& device) + : Card(device) +{ + m_omap_dev = omap_device_new(fd()); +} + +OmapCard::~OmapCard() +{ + omap_device_del(m_omap_dev); +} + +} diff --git a/kms++/src/omap/omapframebuffer.cpp b/kms++/src/omap/omapframebuffer.cpp new file mode 100644 index 0000000..a3a696d --- /dev/null +++ b/kms++/src/omap/omapframebuffer.cpp @@ -0,0 +1,126 @@ + +#include <cstring> +#include <stdexcept> +#include <sys/mman.h> +#include <xf86drm.h> +#include <xf86drmMode.h> +#include <fcntl.h> +#include <unistd.h> +#include <drm_fourcc.h> +#include <drm.h> +#include <drm_mode.h> + +#include <kms++/kms++.h> +#include <kms++/omap/omapkms++.h> + +extern "C" { +#include <omap_drmif.h> +} + +using namespace std; + +namespace kms +{ + +OmapFramebuffer::OmapFramebuffer(OmapCard& card, uint32_t width, uint32_t height, PixelFormat format) + : MappedFramebuffer(card, width, height), m_omap_card(card), m_format(format) +{ + Create(); +} + +OmapFramebuffer::~OmapFramebuffer() +{ + Destroy(); +} + +void OmapFramebuffer::Create() +{ + const PixelFormatInfo& format_info = get_pixel_format_info(m_format); + + m_num_planes = format_info.num_planes; + + for (int i = 0; i < format_info.num_planes; ++i) { + const PixelFormatPlaneInfo& pi = format_info.planes[i]; + FramebufferPlane& plane = m_planes[i]; + + uint32_t flags = OMAP_BO_SCANOUT | OMAP_BO_WC; + + uint32_t size = width() * height() * pi.bitspp / 8; + + struct omap_bo* bo = omap_bo_new(m_omap_card.dev(), size, flags); + if (!bo) + throw invalid_argument(string("omap_bo_new failed: ") + strerror(errno)); + + uint32_t stride = width() * pi.bitspp / 8; + + plane.omap_bo = bo; + plane.handle = omap_bo_handle(bo); + plane.stride = stride; + plane.size = omap_bo_size(bo); + plane.offset = 0; + plane.map = 0; + plane.prime_fd = -1; + } + + /* create framebuffer object for the dumb-buffer */ + uint32_t bo_handles[4] = { m_planes[0].handle, m_planes[1].handle }; + uint32_t pitches[4] = { m_planes[0].stride, m_planes[1].stride }; + uint32_t offsets[4] = { m_planes[0].offset, m_planes[1].offset }; + uint32_t id; + int r = drmModeAddFB2(card().fd(), width(), height(), (uint32_t)format(), + bo_handles, pitches, offsets, &id, 0); + if (r) + throw invalid_argument(string("drmModeAddFB2 failed: ") + strerror(errno)); + + set_id(id); +} + +void OmapFramebuffer::Destroy() +{ + drmModeRmFB(card().fd(), id()); + + for (uint i = 0; i < m_num_planes; ++i) { + FramebufferPlane& plane = m_planes[i]; + + /* unmap buffer */ + if (plane.map) + munmap(plane.map, plane.size); + + omap_bo_del(plane.omap_bo); + + if (plane.prime_fd >= 0) + ::close(plane.prime_fd); + } +} + +uint8_t* OmapFramebuffer::map(unsigned plane) +{ + FramebufferPlane& p = m_planes[plane]; + + if (p.map) + return p.map; + + p.map = (uint8_t*)omap_bo_map(p.omap_bo); + if (p.map == MAP_FAILED) + throw invalid_argument(string("mmap failed: ") + strerror(errno)); + + return p.map; +} + +int OmapFramebuffer::prime_fd(unsigned int plane) +{ + FramebufferPlane& p = m_planes[plane]; + + if (p.prime_fd >= 0) + return p.prime_fd; + + int fd = omap_bo_dmabuf(p.omap_bo); + if (fd < 0) + throw std::runtime_error("omap_bo_dmabuf failed\n"); + + p.prime_fd = fd; + + return fd; +} + +} |