/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2021, Ideas on Board Oy * * drm.h - DRM/KMS Helpers */ #pragma once #include #include #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::map 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, const std::array &strides); 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 */