summaryrefslogtreecommitdiff
path: root/src/protocols/DRMSyncobj.hpp
blob: 4d9c2ffcafe382d0cfbf8e3d425058f944b00f4a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#pragma once

#include <vector>
#include "WaylandProtocol.hpp"
#include "../helpers/sync/SyncReleaser.hpp"
#include "linux-drm-syncobj-v1.hpp"
#include "../helpers/signal/Signal.hpp"
#include "types/SurfaceState.hpp"
#include <hyprutils/os/FileDescriptor.hpp>
#include <list>

class CWLSurfaceResource;
class CDRMSyncobjTimelineResource;
class CSyncTimeline;
struct SSurfaceState;

class CDRMSyncPointState {
  public:
    CDRMSyncPointState() = default;
    CDRMSyncPointState(WP<CDRMSyncobjTimelineResource> resource_, uint64_t point_);
    ~CDRMSyncPointState() = default;

    const uint64_t&                                  point();
    WP<CDRMSyncobjTimelineResource>                  resource();
    WP<CSyncTimeline>                                timeline();
    bool                                             expired();
    Hyprutils::Memory::CUniquePointer<CSyncReleaser> createSyncRelease();
    bool                                             addWaiter(const std::function<void()>& waiter);
    bool                                             comitted();
    Hyprutils::OS::CFileDescriptor                   exportAsFD();
    void                                             signal();

  private:
    WP<CDRMSyncobjTimelineResource> m_resource         = {};
    uint64_t                        m_point            = 0;
    WP<CSyncTimeline>               m_timeline         = {};
    bool                            m_acquireCommitted = false;
    bool                            m_releaseTaken     = false;
};

class CDRMSyncobjSurfaceResource {
  public:
    CDRMSyncobjSurfaceResource(UP<CWpLinuxDrmSyncobjSurfaceV1>&& resource_, SP<CWLSurfaceResource> surface_);
    ~CDRMSyncobjSurfaceResource();

    bool protocolError();
    bool good();

  private:
    void                            removeAllWaiters();
    WP<CWLSurfaceResource>          surface;
    UP<CWpLinuxDrmSyncobjSurfaceV1> resource;

    CDRMSyncPointState              pendingAcquire;
    CDRMSyncPointState              pendingRelease;
    std::vector<SP<SSurfaceState>>  pendingStates;

    struct {
        CHyprSignalListener surfacePrecommit;
    } listeners;
};

class CDRMSyncobjTimelineResource {
  public:
    CDRMSyncobjTimelineResource(UP<CWpLinuxDrmSyncobjTimelineV1>&& resource_, Hyprutils::OS::CFileDescriptor&& fd_);
    ~CDRMSyncobjTimelineResource() = default;
    static WP<CDRMSyncobjTimelineResource> fromResource(wl_resource*);

    bool                                   good();

    Hyprutils::OS::CFileDescriptor         fd;
    SP<CSyncTimeline>                      timeline;

  private:
    UP<CWpLinuxDrmSyncobjTimelineV1> resource;
};

class CDRMSyncobjManagerResource {
  public:
    CDRMSyncobjManagerResource(UP<CWpLinuxDrmSyncobjManagerV1>&& resource_);
    ~CDRMSyncobjManagerResource() = default;

    bool good();

  private:
    UP<CWpLinuxDrmSyncobjManagerV1> resource;
};

class CDRMSyncobjProtocol : public IWaylandProtocol {
  public:
    CDRMSyncobjProtocol(const wl_interface* iface, const int& ver, const std::string& name);
    ~CDRMSyncobjProtocol() = default;

    virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id);

  private:
    void destroyResource(CDRMSyncobjManagerResource* resource);
    void destroyResource(CDRMSyncobjTimelineResource* resource);
    void destroyResource(CDRMSyncobjSurfaceResource* resource);

    //
    std::vector<UP<CDRMSyncobjManagerResource>>  m_vManagers;
    std::vector<UP<CDRMSyncobjTimelineResource>> m_vTimelines;
    std::vector<UP<CDRMSyncobjSurfaceResource>>  m_vSurfaces;

    //
    int drmFD = -1;

    friend class CDRMSyncobjManagerResource;
    friend class CDRMSyncobjTimelineResource;
    friend class CDRMSyncobjSurfaceResource;
};

namespace PROTO {
    inline UP<CDRMSyncobjProtocol> sync;
};