summaryrefslogtreecommitdiff
path: root/src/render/Renderer.hpp
blob: f52b9e3a06b478a47363db080f9ac2e3a677ff60 (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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
#pragma once

#include "../defines.hpp"
#include <cstdint>
#include <hyprgraphics/color/Color.hpp>
#include <hyprutils/math/Box.hpp>
#include <hyprutils/utils/ScopeGuard.hpp>
#include <list>
#include <optional>
#include "OpenGL.hpp"
#include "./SyncFDManager.hpp"
#include "./pass/Pass.hpp"
#include "./pass/BorderPassElement.hpp"
#include "./pass/ClearPassElement.hpp"
#include "./pass/FramebufferElement.hpp"
#include "./pass/RectPassElement.hpp"
#include "./pass/RendererHintsPassElement.hpp"
#include "./pass/ShadowPassElement.hpp"
#include "./pass/SurfacePassElement.hpp"
#include "./pass/TexPassElement.hpp"
#include "./pass/TextureMatteElement.hpp"
#include "types.hpp"
#include "../helpers/Monitor.hpp"
#include "../desktop/view/LayerSurface.hpp"
#include "Renderbuffer.hpp"
#include "../helpers/time/Timer.hpp"
#include "../helpers/math/Math.hpp"
#include "../helpers/time/Time.hpp"
#include "../../protocols/cursor-shape-v1.hpp"
#include "desktop/view/Popup.hpp"
#include "Framebuffer.hpp"
#include "Texture.hpp"

#include <hyprgraphics/resource/resources/TextResource.hpp>

struct SMonitorRule;
class CWorkspace;
class CInputPopup;
class IHLBuffer;
class CEventLoopTimer;
class CToplevelExportProtocolManager;
class CInputManager;
struct SSessionLockSurface;
namespace Screenshare {
    class CScreenshareFrame;
};

namespace Render {
    using CScopeGuard = Hyprutils::Utils::CScopeGuard;

    class IElementRenderer;
    class CRenderPass;

    class IHyprRenderer {
      public:
        IHyprRenderer();
        virtual ~IHyprRenderer();

        enum eType : uint8_t {
            RT_GL = 1,
            RT_VK = 2,
        };

        virtual eType                       type() = 0;
        WP<Render::GL::CHyprOpenGLImpl>     glBackend();

        void                                renderMonitor(PHLMONITOR pMonitor, bool commit = true);
        void                                arrangeLayersForMonitor(const MONITORID&);
        void                                damageSurface(SP<CWLSurfaceResource>, double, double, double scale = 1.0);
        void                                damageWindow(PHLWINDOW, bool forceFull = false);
        void                                damageBox(const 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                                shouldRenderWindow(PHLWINDOW, PHLMONITOR);
        bool                                shouldRenderWindow(PHLWINDOW);
        void                                ensureCursorRenderingMode();
        bool                                shouldRenderCursor();
        void                                setCursorHidden(bool hide);

        std::tuple<float, float, float>     getRenderTimes(PHLMONITOR pMonitor); // avg max min
        void                                ensureLockTexturesRendered(bool load);
        void                                renderLockscreen(PHLMONITOR pMonitor, const Time::steady_tp& now, const CBox& geometry);
        void                                setCursorSurface(SP<Desktop::View::CWLSurface> surf, int hotspotX, int hotspotY, bool force = false);
        void                                setCursorFromName(const std::string& name, bool force = false);
        void                                onRenderbufferDestroy(IRenderbuffer* rb);
        bool                                isNvidia();
        bool                                isIntel();
        bool                                isSoftware();
        bool                                isMgpu();
        void                                addWindowToRenderUnfocused(PHLWINDOW window);
        void                                makeSnapshot(PHLWINDOW);
        void                                makeSnapshot(PHLLS);
        void                                makeSnapshot(WP<Desktop::View::CPopup>);
        void                                renderSnapshot(PHLWINDOW);
        void                                renderSnapshot(PHLLS);
        void                                renderSnapshot(WP<Desktop::View::CPopup>);
        bool                                beginFullFakeRender(PHLMONITOR pMonitor, CRegion& damage, SP<IFramebuffer> fb);
        bool                                beginRenderToBuffer(PHLMONITOR pMonitor, CRegion& damage, SP<IHLBuffer> buffer, bool simple = false);
        virtual void                        startRenderPass() {};
        virtual void                        endRender(const std::function<void()>& renderingDoneCallback = {}) = 0;

        NColorManagement::PImageDescription workBufferImageDescription();
        bool                                m_bBlockSurfaceFeedback = false;
        bool                                m_bRenderingSnapshot    = false;
        PHLMONITORREF                       m_mostHzMonitor;
        bool                                m_directScanoutBlocked = false;

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

        void                                initiateManualCrash();
        const SRenderData&                  renderData();

        bool                                m_crashingInProgress = false;
        float                               m_crashingDistort    = 0.5f;
        wl_event_source*                    m_crashingLoop       = nullptr;
        wl_event_source*                    m_cursorTicker       = nullptr;

        std::vector<CHLBufferReference>     m_usedAsyncBuffers;

        struct {
            int                                          hotspotX      = 0;
            int                                          hotspotY      = 0;
            wpCursorShapeDeviceV1Shape                   shape         = WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT;
            wpCursorShapeDeviceV1Shape                   shapePrevious = WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT;
            CTimer                                       switchedTimer;
            std::optional<SP<Desktop::View::CWLSurface>> surf;
            std::string                                  name;
        } m_lastCursorData;

        CRenderPass  m_renderPass;

        SP<ITexture> renderSplash(const std::function<SP<ITexture>(const int, const int, unsigned char* const)>& handleData, const int fontSize, const int maxWidth = 1024,
                                  const int maxHeight = 1024);

        virtual SP<IRenderbuffer>    getOrCreateRenderbuffer(SP<Aquamarine::IBuffer> buffer, uint32_t fmt); // TODO? move to protected and fix CPointerManager::renderHWCursorBuffer
        bool                         commitPendingAndDoExplicitSync(PHLMONITOR pMonitor);                   // TODO? move to protected and fix CMonitorFrameScheduler::onPresented
        SRenderData                  m_renderData;                                                          // TODO? move to protected and fix CRenderPass
        SP<ITexture>                 m_screencopyDeniedTexture;                                             // TODO? make readonly
        uint                         m_failedAssetsNo     = 0;                                              // TODO? make readonly
        bool                         m_reloadScreenShader = true;                                           // at launch it can be set
        CTimer                       m_globalTimer;

        void                         draw(WP<IPassElement> element, const CRegion& damage = {});
        void                         draw(const CBorderPassElement::SBorderData& data, const CRegion& damage = {});
        void                         draw(const CClearPassElement::SClearData& data, const CRegion& damage = {});
        void                         draw(const CFramebufferElement::SFramebufferElementData& data, const CRegion& damage = {});
        void                         draw(const CRectPassElement::SRectData& data, const CRegion& damage = {});
        void                         draw(const CRendererHintsPassElement::SData& data, const CRegion& damage = {});
        void                         draw(const CShadowPassElement::SShadowData& data, const CRegion& damage = {});
        void                         draw(const CSurfacePassElement::SRenderData& data, const CRegion& damage = {});
        void                         draw(const CTexPassElement::SRenderData& data, const CRegion& damage = {});
        void                         draw(const CTextureMatteElement::STextureMatteData& data, const CRegion& damage = {});
        virtual void                 bindFB(SP<IFramebuffer> fb);
        UP<CScopeGuard>              bindTempFB(SP<IFramebuffer> fb);
        virtual UP<ISyncFDManager>   createSyncFDManager()                                                                                                                     = 0;
        virtual WP<IElementRenderer> elementRenderer()                                                                                                                         = 0;
        virtual SP<ITexture>         createStencilTexture(const int width, const int height)                                                                                   = 0;
        virtual SP<ITexture>         createTexture(bool opaque = false)                                                                                                        = 0;
        virtual SP<ITexture>         createTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size, bool keepDataCopy = false, bool opaque = false) = 0;
        virtual SP<ITexture>         createTexture(const Aquamarine::SDMABUFAttrs&, bool opaque = false)                                                                       = 0;
        virtual SP<ITexture>         createTexture(const int width, const int height, unsigned char* const)                                                                    = 0;
        virtual SP<ITexture>         createTexture(cairo_surface_t* cairo)                                                                                                     = 0;
        virtual SP<ITexture>         createTexture(std::span<const float> lut3D, size_t N)                                                                                     = 0;
        virtual SP<ITexture>         createTexture(const SP<Aquamarine::IBuffer> buffer, bool keepDataCopy = false);
        virtual SP<ITexture>         renderText(const std::string& text, CHyprColor col, int pt, bool italic = false, const std::string& fontFamily = "", int maxWidth = 0,
                                                int weight = 400);
        virtual SP<ITexture>         renderText(Hyprgraphics::CTextResource::STextResourceData&& data);
        SP<ITexture>                 loadAsset(const std::string& filename);
        virtual bool                 shouldUseNewBlurOptimizations(PHLLS pLayer, PHLWINDOW pWindow);
        virtual bool                 explicitSyncSupported()                                                                              = 0;
        virtual std::vector<SDRMFormat> getDRMFormats()                                                                                   = 0;
        virtual std::vector<uint64_t>   getDRMFormatModifiers(DRMFormat format)                                                           = 0;
        virtual SP<IFramebuffer>        createFB(const std::string& name = "")                                                            = 0;
        virtual void                    disableScissor()                                                                                  = 0;
        virtual void                    blend(bool enabled)                                                                               = 0;
        virtual void                    drawShadow(const CBox& box, int round, float roundingPower, int range, CHyprColor color, float a) = 0;
        virtual void                    setViewport(int x, int y, int width, int height)                                                  = 0;

        bool                            preBlurQueued(PHLMONITORREF pMonitor);
        void                            pushMonitorTransformEnabled(bool enabled);
        void                            popMonitorTransformEnabled();
        bool                            monitorTransformEnabled();

        void                            setProjectionType(const Vector2D& fbSize);
        void                            setProjectionType(eRenderProjectionType projectionType);
        Mat3x3                          getBoxProjection(const CBox& box, std::optional<eTransform> transform = std::nullopt);
        Mat3x3                          projectBoxToTarget(const CBox& box, std::optional<eTransform> transform = std::nullopt);

        SP<ITexture>                    blurMainFramebuffer(float a, CRegion* originalDamage);
        virtual SP<ITexture>            blurFramebuffer(SP<IFramebuffer> source, float a, CRegion* originalDamage) = 0;
        void                            preBlurForCurrentMonitor(CRegion* fakeDamage);

        SCMSettings                     getCMSettings(const NColorManagement::PImageDescription imageDescription, const NColorManagement::PImageDescription targetImageDescription,
                                                      SP<CWLSurfaceResource> surface = nullptr, bool modifySDR = false, float sdrMinLuminance = -1.0f, int sdrMaxLuminance = -1,
                                                      bool shouldUseSurface = false);
        void                            clearCMSettingsCache();
        virtual bool                    reloadShaders(const std::string& path = "") = 0;

      protected:
        virtual void              renderOffToMain(SP<IFramebuffer> off)                                         = 0;
        virtual SP<IRenderbuffer> getOrCreateRenderbufferInternal(SP<Aquamarine::IBuffer> buffer, uint32_t fmt) = 0;
        void                      renderMirrored();
        void                      setDamage(const CRegion& damage_, std::optional<CRegion> finalDamage);
        // 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 = {}, SP<IFramebuffer> fb = nullptr,
                                 bool simple = false);

        virtual bool beginRenderInternal(PHLMONITOR pMonitor, CRegion& damage, bool simple = false) {
            return false;
        };
        virtual bool beginFullFakeRenderInternal(PHLMONITOR pMonitor, CRegion& damage, SP<IFramebuffer> fb, bool simple = false) {
            return false;
        };
        virtual void initRender() {};
        virtual bool initRenderBuffer(SP<Aquamarine::IBuffer> buffer, uint32_t fmt) {
            return false;
        };

        SP<ITexture>         getBackground(PHLMONITOR pMonitor);
        virtual SP<ITexture> getBlurTexture(PHLMONITORREF pMonitor);

        struct SCMSettingsCacheEntry {
            uint64_t    srcDescId = 0, dstDescId = 0;
            void*       surfacePtr      = nullptr; // read-only!!
            bool        modifySDR       = false;
            float       sdrMinLuminance = -1.F;
            int         sdrMaxLuminance = -1;
            SCMSettings settings;
        };
        std::vector<SCMSettingsCacheEntry> m_cmSettingsCache;

        SP<ITexture>                       m_lockDeadTexture;
        SP<ITexture>                       m_lockDead2Texture;
        SP<ITexture>                       m_lockTtyTextTexture;
        bool                               m_monitorTransformEnabled = false; // do not modify directly
        std::stack<bool>                   m_monitorTransformStack;

        void                               handleFullscreenSettings(PHLMONITOR pMonitor);

        // old private:
        void arrangeLayerArray(PHLMONITOR, const std::vector<PHLLSREF>&, bool, CBox*);
        void renderWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, const Time::steady_tp& now, const CBox& geometry);
        void renderWorkspaceWindowsFullscreen(PHLMONITOR, PHLWORKSPACE, const Time::steady_tp&); // renders workspace windows (fullscreen) (tiled, floating, pinned, but no special)
        void renderWorkspaceWindows(PHLMONITOR, PHLWORKSPACE, const Time::steady_tp&); // renders workspace windows (no fullscreen) (tiled, floating, pinned, but no special)
        void renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, const Time::steady_tp& now, const Vector2D& translate = {0, 0}, const float& scale = 1.f);
        void renderWindow(PHLWINDOW, PHLMONITOR, const Time::steady_tp&, bool, eRenderPassMode, bool ignorePosition = false, bool standalone = false);
        void renderLayer(PHLLS, PHLMONITOR, const Time::steady_tp&, bool popups = false, bool lockscreen = false);
        void renderSessionLockSurface(WP<SSessionLockSurface>, PHLMONITOR, const Time::steady_tp&);
        void renderDragIcon(PHLMONITOR, const Time::steady_tp&);
        void renderIMEPopup(CInputPopup*, PHLMONITOR, const Time::steady_tp&);
        void sendFrameEventsToWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace,
                                        const Time::steady_tp& now); // sends frame displayed events but doesn't actually render anything
        void renderSessionLockPrimer(PHLMONITOR pMonitor);
        void renderSessionLockMissing(PHLMONITOR pMonitor);
        void renderBackground(PHLMONITOR pMonitor);
        void requestBackgroundResource();
        std::string                       resolveAssetPath(const std::string& file);
        void                              initMissingAssetTexture();
        void                              initAssets();
        SP<ITexture>                      m_missingAssetTexture;
        ASP<Hyprgraphics::CImageResource> m_backgroundResource;
        bool                              m_backgroundResourceFailed = false;

        bool                              shouldBlur(PHLLS ls);
        bool                              shouldBlur(PHLWINDOW w);
        bool                              shouldBlur(WP<Desktop::View::CPopup> p);

        bool                              m_cursorHidden            = false;
        bool                              m_cursorHiddenByCondition = false;
        bool                              m_cursorHasSurface        = false;
        SP<Aquamarine::IBuffer>           m_currentBuffer           = nullptr;
        eRenderMode                       m_renderMode              = RENDER_MODE_NORMAL;
        bool                              m_nvidia                  = false;
        bool                              m_intel                   = false;
        bool                              m_software                = false;
        bool                              m_mgpu                    = false;

        struct {
            bool hiddenOnTouch    = false;
            bool hiddenOnTablet   = false;
            bool hiddenOnTimeout  = false;
            bool hiddenOnKeyboard = false;
        } m_cursorHiddenConditions;

        std::vector<SP<IRenderbuffer>> m_renderbuffers;
        std::vector<PHLWINDOWREF>      m_renderUnfocused;
        SP<CEventLoopTimer>            m_renderUnfocusedTimer;

        friend class CRenderPass;
        friend class Render::GL::CHyprOpenGLImpl;
        friend class CToplevelExportFrame;
        friend class Screenshare::CScreenshareFrame;
        friend class CInputManager;
        friend class CPointerManager;
        friend class CMonitor;
        friend class CMonitorFrameScheduler;

      private:
        void bindOffMain();
        void bindBackOnMain();
    };

}

inline UP<Render::IHyprRenderer> g_pHyprRenderer;