[PATCH 13/27] libcamera: software_isp: gbm: Add in a GBM helper class for GPU surface access
Bryan O'Donoghue
bryan.odonoghue at linaro.org
Tue Apr 22 23:59:06 CEST 2025
A helper class to interact with GBM. This will allow us to specify the
internal storage format of the CPU when making a texture for the Debayer
vertext/fragment shaders and thus ensure we receive an uncompressed and
untiled output buffer.
Signed-off-by: Bryan O'Donoghue <bryan.odonoghue at linaro.org>
---
src/libcamera/software_isp/gbm.cpp | 136 +++++++++++++++++++++++++++++
src/libcamera/software_isp/gbm.h | 52 +++++++++++
2 files changed, 188 insertions(+)
create mode 100644 src/libcamera/software_isp/gbm.cpp
create mode 100644 src/libcamera/software_isp/gbm.h
diff --git a/src/libcamera/software_isp/gbm.cpp b/src/libcamera/software_isp/gbm.cpp
new file mode 100644
index 00000000..1be00f1f
--- /dev/null
+++ b/src/libcamera/software_isp/gbm.cpp
@@ -0,0 +1,136 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2024, Linaro Ltd.
+ *
+ * Authors:
+ * Bryan O'Donoghue <bryan.odonoghue at linaro.org>
+ *
+ * egl.cpp - Helper class for managing GBM interactions.
+ */
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <linux/dma-buf.h>
+#include <linux/dma-heap.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+
+#include "gbm.h"
+
+namespace libcamera {
+
+LOG_DEFINE_CATEGORY(GBM)
+
+GBM::GBM() {
+ fd_ = 0;
+};
+
+GBM::~GBM() {
+ if (gbm_surface_)
+ gbm_surface_destroy(gbm_surface_);
+
+ if (gbm_device_)
+ gbm_device_destroy(gbm_device_);
+
+ if (fd_ >= 0)
+ close(fd_);
+};
+
+// this should probably go into its own class to deal with the
+// allocation and deletion of frambuffers attached to GBM devices/objects
+int GBM::initSurface(uint32_t width, uint32_t height)
+{
+ const char *dri_node = "/dev/dri/renderD128"; //TODO: get from an env or config setting
+
+ fd_ = open(dri_node, O_RDWR | O_CLOEXEC); //TODO: CLOEXEC ?
+ if (fd_ < 0) {
+ LOG(GBM, Error) << "Open " << dri_node<< " fail " << fd_;
+ return fd_;
+ }
+
+ gbm_device_ = gbm_create_device(fd_);
+ if (!gbm_device_) {
+ LOG(GBM, Error) << "gbm_crate_device fail";
+ goto fail;
+ }
+
+ // GBM_FORMAT_RGBA8888 is not supported mesa::src/gbm/dri/gbm_dri.c::gbm_dri_visuals_table[]
+ // This means we need to choose XRGB8888 or ARGB8888 as the raw buffer format
+ gbm_surface_ = gbm_surface_create(gbm_device_, width, height, GBM_FORMAT_ARGB8888,
+ GBM_BO_USE_RENDERING | GBM_BO_USE_LINEAR);
+ if (!gbm_surface_) {
+ LOG(GBM, Error) << "Unable to create linear gbm surface";
+ goto fail;
+ }
+
+ format = libcamera::formats::ARGB8888;
+
+ return 0;
+fail:
+ return -ENODEV;
+
+}
+
+int GBM::mapSurface()
+{
+ gbm_bo_ = gbm_surface_lock_front_buffer(gbm_surface_);
+ if (!gbm_bo_) {
+ LOG(GBM, Error) << "GBM input buffer object create fail";
+ return -ENODEV;
+ }
+ gbm_surface_release_buffer(gbm_surface_, gbm_bo_);
+
+ bo_fd_ = gbm_bo_get_fd(gbm_bo_);
+
+ if (!bo_fd_) {
+ gbm_surface_release_buffer(gbm_surface_, gbm_bo_);
+ LOG(GBM, Error) << "Unable to get fd for bo: " << bo_fd_;
+ return -ENODEV;
+ }
+
+ stride_ = gbm_bo_get_stride(gbm_bo_);
+ width_ = gbm_bo_get_width(gbm_bo_);
+ height_ = gbm_bo_get_height(gbm_bo_);
+ offset_ = gbm_bo_get_offset(gbm_bo_, 0);
+ framesize_ = height_ * stride_;
+
+ map_ = mmap(NULL, height_ * stride_, PROT_READ, MAP_SHARED, bo_fd_, 0);
+ if (map_ == MAP_FAILED) {
+ LOG(GBM, Error) << "mmap gbm_bo_ fail";
+ return -ENODEV;
+ }
+
+ LOG(GBM, Debug) << " stride " << stride_
+ << " width " << width_
+ << " height " << height_
+ << " offset " << offset_
+ << " framesize " << framesize_;
+
+ return 0;
+}
+
+int GBM::getFrameBufferData(uint8_t *data, size_t data_len)
+{
+ struct dma_buf_sync sync;
+
+ gbm_surface_lock_front_buffer(gbm_surface_);
+
+ sync.flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_READ;
+ ioctl(bo_fd_, DMA_BUF_IOCTL_SYNC, &sync);
+
+ if (data_len > framesize_) {
+ LOG(GBM, Error) << "Invalid read size " << data_len << " max is " << framesize_;
+ return -EINVAL;
+ }
+
+ memcpy(data, map_, data_len);
+
+ sync.flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_READ;
+ ioctl(bo_fd_, DMA_BUF_IOCTL_SYNC, &sync);
+
+ gbm_surface_release_buffer(gbm_surface_, gbm_bo_);
+
+ return 0;
+}
+}; //namespace libcamera
diff --git a/src/libcamera/software_isp/gbm.h b/src/libcamera/software_isp/gbm.h
new file mode 100644
index 00000000..9ccfb1ba
--- /dev/null
+++ b/src/libcamera/software_isp/gbm.h
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2024, Linaro Ltd.
+ *
+ * Authors:
+ * Bryan O'Donoghue <bryan.odonoghue at linaro.org>
+ *
+ * gbm.h - Helper class for managing GBM interactions.
+ */
+
+#pragma once
+
+#include <gbm.h>
+
+#include <libcamera/base/log.h>
+#include <libcamera/formats.h>
+
+namespace libcamera {
+
+LOG_DECLARE_CATEGORY(GBM)
+
+class GBM {
+public:
+ GBM();
+ ~GBM();
+
+ int initSurface(uint32_t width, uint32_t height);
+ int mapSurface();
+ int getFrameBufferData(uint8_t *data_out, size_t data_len);
+ struct gbm_device *getDevice() { return gbm_device_; };
+ struct gbm_surface *getSurface() { return gbm_surface_; };
+ uint32_t getFrameSize() { return framesize_; };
+ uint32_t getStride() { return stride_; };
+
+ PixelFormat format;
+
+private:
+ int fd_;
+ struct gbm_device *gbm_device_;
+ struct gbm_surface *gbm_surface_;
+
+ struct gbm_bo *gbm_bo_;
+ uint32_t width_;
+ uint32_t height_;
+ uint32_t stride_;
+ uint32_t offset_;
+ uint32_t framesize_;
+ void *map_;
+ int bo_fd_;
+};
+
+};
--
2.49.0
More information about the libcamera-devel
mailing list