aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/render/Renderer.hpp
blob: 4524008bdb4b25345ec4c03eb740df8ec8bb2cfb (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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#pragma once

#include "../defines.hpp"
#include <list>
#include "../helpers/Monitor.hpp"
#include "OpenGL.hpp"
#include "Renderbuffer.hpp"
#include "../helpers/Timer.hpp"
#include "../helpers/math/Math.hpp"

struct SMonitorRule;
class CWorkspace;
class CWindow;
class CInputPopup;
class IHLBuffer;
class CEventLoopTimer;

// TODO: add fuller damage tracking for updating only parts of a window
enum DAMAGETRACKINGMODES {
    DAMAGE_TRACKING_INVALID = -1,
    DAMAGE_TRACKING_NONE    = 0,
    DAMAGE_TRACKING_MONITOR,
    DAMAGE_TRACKING_FULL
};

enum eRenderPassMode {
    RENDER_PASS_ALL = 0,
    RENDER_PASS_MAIN,
    RENDER_PASS_POPUP
};

enum eRenderMode {
    RENDER_MODE_NORMAL              = 0,
    RENDER_MODE_FULL_FAKE           = 1,
    RENDER_MODE_TO_BUFFER           = 2,
    RENDER_MODE_TO_BUFFER_READ_ONLY = 3,
};

class CToplevelExportProtocolManager;
class CInputManager;
struct SSessionLockSurface;

struct SExplicitSyncSettings {
    bool explicitEnabled = false, explicitKMSEnabled = false;
};

class CHyprRenderer {
  public:
    CHyprRenderer();
    ~CHyprRenderer();

    void renderMonitor(PHLMONITOR pMonitor);
    void arrangeLayersForMonitor(const MONITORID&);
    void damageSurface(SP<CWLSurfaceResource>, double, double, double scale = 1.0);
    void damageWindow(PHLWINDOW, bool forceFull = false);
    void damageBox(CBox*, bool skipFrameSchedule = false);
    void damageBox(const int& x, const int& y, const int& w, const int& h);
    void damageRegion(const CRegion&);
    void damageMonitor(PHLMONITOR);
    void damageMirrorsWith(PHLMONITOR, const CRegion&);
    bool applyMonitorRule(PHLMONITOR, SMonitorRule*, bool force = false);
    bool shouldRenderWindow(PHLWINDOW, PHLMONITOR);
    bool shouldRenderWindow(PHLWINDOW);
    void ensureCursorRenderingMode();
    bool shouldRenderCursor();
    void setCursorHidden(bool hide);
    void calculateUVForSurface(PHLWINDOW, SP<CWLSurfaceResource>, PHLMONITOR pMonitor, bool main = false, const Vector2D& projSize = {}, const Vector2D& projSizeUnscaled = {},
                               bool fixMisalignedFSV1 = false);
    std::tuple<float, float, float> getRenderTimes(PHLMONITOR pMonitor); // avg max min
    void                            renderLockscreen(PHLMONITOR pMonitor, timespec* now, const CBox& geometry);
    void                            setOccludedForBackLayers(CRegion& region, PHLWORKSPACE pWorkspace);
    void                            setOccludedForMainWorkspace(CRegion& region, PHLWORKSPACE pWorkspace); // TODO: merge occlusion methods
    bool                            canSkipBackBufferClear(PHLMONITOR pMonitor);
    void                            recheckSolitaryForMonitor(PHLMONITOR pMonitor);
    void                            setCursorSurface(SP<CWLSurface> surf, int hotspotX, int hotspotY, bool force = false);
    void                            setCursorFromName(const std::string& name, bool force = false);
    void                            onRenderbufferDestroy(CRenderbuffer* rb);
    SP<CRenderbuffer>               getCurrentRBO();
    bool                            isNvidia();
    void                            makeEGLCurrent();
    void                            unsetEGL();
    SExplicitSyncSettings           getExplicitSyncSettings();
    void                            addWindowToRenderUnfocused(PHLWINDOW window);

    // if RENDER_MODE_NORMAL, provided damage will be written to.
    // otherwise, it will be the one used.
    bool beginRender(PHLMONITOR pMonitor, CRegion& damage, eRenderMode mode = RENDER_MODE_NORMAL, SP<IHLBuffer> buffer = {}, CFramebuffer* fb = nullptr, bool simple = false);
    void endRender();

    bool m_bBlockSurfaceFeedback = false;
    bool m_bRenderingSnapshot    = false;
    PHLMONITORREF m_pMostHzMonitor;
    bool          m_bDirectScanoutBlocked = false;

    DAMAGETRACKINGMODES
    damageTrackingModeFromStr(const std::string&);

    void                                setSurfaceScanoutMode(SP<CWLSurfaceResource> surface, PHLMONITOR monitor); // nullptr monitor resets
    void                                initiateManualCrash();

    bool                                m_bCrashingInProgress = false;
    float                               m_fCrashingDistort    = 0.5f;
    wl_event_source*                    m_pCrashingLoop       = nullptr;
    wl_event_source*                    m_pCursorTicker       = nullptr;

    CTimer                              m_tRenderTimer;

    std::vector<SP<CWLSurfaceResource>> explicitPresented;

    struct {
        int                           hotspotX;
        int                           hotspotY;
        std::optional<SP<CWLSurface>> surf;
        std::string                   name;
    } m_sLastCursorData;

  private:
    void              arrangeLayerArray(PHLMONITOR, const std::vector<PHLLSREF>&, bool, CBox*);
    void              renderWorkspaceWindowsFullscreen(PHLMONITOR, PHLWORKSPACE, timespec*); // renders workspace windows (fullscreen) (tiled, floating, pinned, but no special)
    void              renderWorkspaceWindows(PHLMONITOR, PHLWORKSPACE, timespec*);           // renders workspace windows (no fullscreen) (tiled, floating, pinned, but no special)
    void              renderWindow(PHLWINDOW, PHLMONITOR, timespec*, bool, eRenderPassMode, bool ignorePosition = false, bool ignoreAllGeometry = false);
    void              renderLayer(PHLLS, PHLMONITOR, timespec*, bool popups = false);
    void              renderSessionLockSurface(SSessionLockSurface*, PHLMONITOR, timespec*);
    void              renderDragIcon(PHLMONITOR, timespec*);
    void              renderIMEPopup(CInputPopup*, PHLMONITOR, timespec*);
    void              renderWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const CBox& geometry);
    void              sendFrameEventsToWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, timespec* now); // sends frame displayed events but doesn't actually render anything
    void              renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const Vector2D& translate = {0, 0}, const float& scale = 1.f);
    void              renderSessionLockMissing(PHLMONITOR pMonitor);

    bool              commitPendingAndDoExplicitSync(PHLMONITOR pMonitor);

    bool              m_bCursorHidden        = false;
    bool              m_bCursorHasSurface    = false;
    SP<CRenderbuffer> m_pCurrentRenderbuffer = nullptr;
    SP<Aquamarine::IBuffer> m_pCurrentBuffer;
    eRenderMode             m_eRenderMode = RENDER_MODE_NORMAL;

    bool                    m_bNvidia = false;

    struct {
        bool hiddenOnTouch    = false;
        bool hiddenOnTimeout  = false;
        bool hiddenOnKeyboard = false;
    } m_sCursorHiddenConditions;

    SP<CRenderbuffer>              getOrCreateRenderbuffer(SP<Aquamarine::IBuffer> buffer, uint32_t fmt);
    std::vector<SP<CRenderbuffer>> m_vRenderbuffers;
    std::vector<PHLWINDOWREF>      m_vRenderUnfocused;
    SP<CEventLoopTimer>            m_tRenderUnfocusedTimer;

    friend class CHyprOpenGLImpl;
    friend class CToplevelExportFrame;
    friend class CInputManager;
    friend class CPointerManager;
    friend class CMonitor;
};

inline std::unique_ptr<CHyprRenderer> g_pHyprRenderer;