From 910b5253cb2bc81d0aee3efb98af5334f96e2c9c Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 17 May 2020 23:56:26 +0300 Subject: cam: Add DRM helper classes To prepare for viewfinder operation through the DRM/KMS API, add a set of helper classes that encapsulate the libdrm functions. Signed-off-by: Laurent Pinchart Reviewed-by: Paul Elder Reviewed-by: Kieran Bingham --- src/cam/drm.h | 331 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 331 insertions(+) create mode 100644 src/cam/drm.h (limited to 'src/cam/drm.h') diff --git a/src/cam/drm.h b/src/cam/drm.h new file mode 100644 index 00000000..ee230402 --- /dev/null +++ b/src/cam/drm.h @@ -0,0 +1,331 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2021, Ideas on Board Oy + * + * drm.h - DRM/KMS Helpers + */ +#ifndef __CAM_DRM_H__ +#define __CAM_DRM_H__ + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +namespace libcamera { +class FrameBuffer; +class PixelFormat; +class Size; +} /* namespace libcamera */ + +namespace DRM { + +class Device; +class Plane; +class Property; +class PropertyValue; + +class Object +{ +public: + enum Type { + TypeCrtc = DRM_MODE_OBJECT_CRTC, + TypeConnector = DRM_MODE_OBJECT_CONNECTOR, + TypeEncoder = DRM_MODE_OBJECT_ENCODER, + TypeMode = DRM_MODE_OBJECT_MODE, + TypeProperty = DRM_MODE_OBJECT_PROPERTY, + TypeFb = DRM_MODE_OBJECT_FB, + TypeBlob = DRM_MODE_OBJECT_BLOB, + TypePlane = DRM_MODE_OBJECT_PLANE, + TypeAny = DRM_MODE_OBJECT_ANY, + }; + + Object(Device *dev, uint32_t id, Type type); + virtual ~Object(); + + Device *device() const { return dev_; } + uint32_t id() const { return id_; } + Type type() const { return type_; } + + const Property *property(const std::string &name) const; + const PropertyValue *propertyValue(const std::string &name) const; + const std::vector &properties() const { return properties_; } + +protected: + virtual int setup() + { + return 0; + } + + uint32_t id_; + +private: + friend Device; + + Device *dev_; + Type type_; + std::vector properties_; +}; + +class Property : public Object +{ +public: + enum Type { + TypeUnknown = 0, + TypeRange, + TypeEnum, + TypeBlob, + TypeBitmask, + TypeObject, + TypeSignedRange, + }; + + Property(Device *dev, drmModePropertyRes *property); + + Type type() const { return type_; } + const std::string &name() const { return name_; } + + bool isImmutable() const { return flags_ & DRM_MODE_PROP_IMMUTABLE; } + + const std::vector values() const { return values_; } + const std::map &enums() const { return enums_; } + const std::vector blobs() const { return blobs_; } + +private: + Type type_; + std::string name_; + uint32_t flags_; + std::vector values_; + std::map enums_; + std::vector blobs_; +}; + +class PropertyValue +{ +public: + PropertyValue(uint32_t id, uint64_t value) + : id_(id), value_(value) + { + } + + uint32_t id() const { return id_; } + uint32_t value() const { return value_; } + +private: + uint32_t id_; + uint64_t value_; +}; + +class Blob : public Object +{ +public: + Blob(Device *dev, const libcamera::Span &data); + ~Blob(); + + bool isValid() const { return id() != 0; } +}; + +class Mode : public drmModeModeInfo +{ +public: + Mode(const drmModeModeInfo &mode); + + std::unique_ptr toBlob(Device *dev) const; +}; + +class Crtc : public Object +{ +public: + Crtc(Device *dev, const drmModeCrtc *crtc, unsigned int index); + + unsigned int index() const { return index_; } + const std::vector &planes() const { return planes_; } + +private: + friend Device; + + unsigned int index_; + std::vector planes_; +}; + +class Encoder : public Object +{ +public: + Encoder(Device *dev, const drmModeEncoder *encoder); + + uint32_t type() const { return type_; } + + const std::vector &possibleCrtcs() const { return possibleCrtcs_; } + +private: + uint32_t type_; + std::vector possibleCrtcs_; +}; + +class Connector : public Object +{ +public: + enum Status { + Connected, + Disconnected, + Unknown, + }; + + Connector(Device *dev, const drmModeConnector *connector); + + uint32_t type() const { return type_; } + const std::string &name() const { return name_; } + + Status status() const { return status_; } + + const std::vector &encoders() const { return encoders_; } + const std::vector &modes() const { return modes_; } + +private: + uint32_t type_; + std::string name_; + Status status_; + std::vector encoders_; + std::vector modes_; +}; + +class Plane : public Object +{ +public: + enum Type { + TypeOverlay, + TypePrimary, + TypeCursor, + }; + + Plane(Device *dev, const drmModePlane *plane); + + Type type() const { return type_; } + const std::vector &formats() const { return formats_; } + const std::vector &possibleCrtcs() const { return possibleCrtcs_; } + + bool supportsFormat(const libcamera::PixelFormat &format) const; + +protected: + int setup() override; + +private: + friend class Device; + + Type type_; + std::vector formats_; + std::vector possibleCrtcs_; + uint32_t possibleCrtcsMask_; +}; + +class FrameBuffer : public Object +{ +public: + struct Plane { + uint32_t handle; + }; + + ~FrameBuffer(); + +private: + friend class Device; + + FrameBuffer(Device *dev); + + std::vector planes_; +}; + +class AtomicRequest +{ +public: + enum Flags { + FlagAllowModeset = (1 << 0), + FlagAsync = (1 << 1), + }; + + AtomicRequest(Device *dev); + ~AtomicRequest(); + + Device *device() const { return dev_; } + bool isValid() const { return valid_; } + + int addProperty(const Object *object, const std::string &property, + uint64_t value); + int addProperty(const Object *object, const std::string &property, + std::unique_ptr blob); + int commit(unsigned int flags = 0); + +private: + AtomicRequest(const AtomicRequest &) = delete; + AtomicRequest(const AtomicRequest &&) = delete; + AtomicRequest &operator=(const AtomicRequest &) = delete; + AtomicRequest &operator=(const AtomicRequest &&) = delete; + + int addProperty(uint32_t object, uint32_t property, uint64_t value); + + Device *dev_; + bool valid_; + drmModeAtomicReq *request_; + std::list> blobs_; +}; + +class Device +{ +public: + Device(); + ~Device(); + + int init(); + + int fd() const { return fd_; } + + const std::list &crtcs() const { return crtcs_; } + const std::list &encoders() const { return encoders_; } + const std::list &connectors() const { return connectors_; } + const std::list &planes() const { return planes_; } + const std::list &properties() const { return properties_; } + + const Object *object(uint32_t id); + + std::unique_ptr createFrameBuffer( + const libcamera::FrameBuffer &buffer, + const libcamera::PixelFormat &format, + const libcamera::Size &size, unsigned int stride); + + libcamera::Signal requestComplete; + +private: + Device(const Device &) = delete; + Device(const Device &&) = delete; + Device &operator=(const Device &) = delete; + Device &operator=(const Device &&) = delete; + + int getResources(); + + void drmEvent(); + static void pageFlipComplete(int fd, unsigned int sequence, + unsigned int tv_sec, unsigned int tv_usec, + void *user_data); + + int fd_; + + std::list crtcs_; + std::list encoders_; + std::list connectors_; + std::list planes_; + std::list properties_; + + std::map objects_; +}; + +} /* namespace DRM */ + +#endif /* __CAM_DRM_H__ */ -- cgit v1.2.1