summaryrefslogtreecommitdiff
path: root/src/apps/cam/drm.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/apps/cam/drm.h')
-rw-r--r--src/apps/cam/drm.h334
1 files changed, 334 insertions, 0 deletions
diff --git a/src/apps/cam/drm.h b/src/apps/cam/drm.h
new file mode 100644
index 00000000..ebaea04d
--- /dev/null
+++ b/src/apps/cam/drm.h
@@ -0,0 +1,334 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2021, Ideas on Board Oy
+ *
+ * drm.h - DRM/KMS Helpers
+ */
+
+#pragma once
+
+#include <array>
+#include <list>
+#include <map>
+#include <memory>
+#include <stdint.h>
+#include <string>
+#include <vector>
+
+#include <libcamera/base/signal.h>
+#include <libcamera/base/span.h>
+
+#include <libdrm/drm.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+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<PropertyValue> &properties() const { return properties_; }
+
+protected:
+ virtual int setup()
+ {
+ return 0;
+ }
+
+ uint32_t id_;
+
+private:
+ friend Device;
+
+ Device *dev_;
+ Type type_;
+ std::vector<PropertyValue> 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<uint64_t> values() const { return values_; }
+ const std::map<uint32_t, std::string> &enums() const { return enums_; }
+ const std::vector<uint32_t> blobs() const { return blobs_; }
+
+private:
+ Type type_;
+ std::string name_;
+ uint32_t flags_;
+ std::vector<uint64_t> values_;
+ std::map<uint32_t, std::string> enums_;
+ std::vector<uint32_t> 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<const uint8_t> &data);
+ ~Blob();
+
+ bool isValid() const { return id() != 0; }
+};
+
+class Mode : public drmModeModeInfo
+{
+public:
+ Mode(const drmModeModeInfo &mode);
+
+ std::unique_ptr<Blob> 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<const Plane *> &planes() const { return planes_; }
+
+private:
+ friend Device;
+
+ unsigned int index_;
+ std::vector<const Plane *> planes_;
+};
+
+class Encoder : public Object
+{
+public:
+ Encoder(Device *dev, const drmModeEncoder *encoder);
+
+ uint32_t type() const { return type_; }
+
+ const std::vector<const Crtc *> &possibleCrtcs() const { return possibleCrtcs_; }
+
+private:
+ uint32_t type_;
+ std::vector<const Crtc *> 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<const Encoder *> &encoders() const { return encoders_; }
+ const std::vector<Mode> &modes() const { return modes_; }
+
+private:
+ uint32_t type_;
+ std::string name_;
+ Status status_;
+ std::vector<const Encoder *> encoders_;
+ std::vector<Mode> 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<uint32_t> &formats() const { return formats_; }
+ const std::vector<const Crtc *> &possibleCrtcs() const { return possibleCrtcs_; }
+
+ bool supportsFormat(const libcamera::PixelFormat &format) const;
+
+protected:
+ int setup() override;
+
+private:
+ friend class Device;
+
+ Type type_;
+ std::vector<uint32_t> formats_;
+ std::vector<const Crtc *> possibleCrtcs_;
+ uint32_t possibleCrtcsMask_;
+};
+
+class FrameBuffer : public Object
+{
+public:
+ struct Plane {
+ uint32_t handle;
+ };
+
+ ~FrameBuffer();
+
+private:
+ friend class Device;
+
+ FrameBuffer(Device *dev);
+
+ std::map<int, Plane> planes_;
+};
+
+class AtomicRequest
+{
+public:
+ enum Flags {
+ FlagAllowModeset = (1 << 0),
+ FlagAsync = (1 << 1),
+ FlagTestOnly = (1 << 2),
+ };
+
+ 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> 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<std::unique_ptr<Blob>> blobs_;
+};
+
+class Device
+{
+public:
+ Device();
+ ~Device();
+
+ int init();
+
+ int fd() const { return fd_; }
+
+ const std::list<Crtc> &crtcs() const { return crtcs_; }
+ const std::list<Encoder> &encoders() const { return encoders_; }
+ const std::list<Connector> &connectors() const { return connectors_; }
+ const std::list<Plane> &planes() const { return planes_; }
+ const std::list<Property> &properties() const { return properties_; }
+
+ const Object *object(uint32_t id);
+
+ std::unique_ptr<FrameBuffer> createFrameBuffer(
+ const libcamera::FrameBuffer &buffer,
+ const libcamera::PixelFormat &format,
+ const libcamera::Size &size,
+ const std::array<uint32_t, 4> &strides);
+
+ libcamera::Signal<AtomicRequest *> requestComplete;
+
+private:
+ Device(const Device &) = delete;
+ Device(const Device &&) = delete;
+ Device &operator=(const Device &) = delete;
+ Device &operator=(const Device &&) = delete;
+
+ int openCard();
+ 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<Crtc> crtcs_;
+ std::list<Encoder> encoders_;
+ std::list<Connector> connectors_;
+ std::list<Plane> planes_;
+ std::list<Property> properties_;
+
+ std::map<uint32_t, Object *> objects_;
+};
+
+} /* namespace DRM */