summaryrefslogtreecommitdiff
path: root/src/render/Renderer.hpp
blob: 4b65141a1b5f44011f9635b466d5eac641416c70 (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
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
#pragma once

#include "../defines.hpp"
#include <hyprgraphics/color/Color.hpp>
#include <hyprutils/math/Box.hpp>
#include <list>
#include <optional>
#include "../helpers/Monitor.hpp"
#include "../desktop/view/LayerSurface.hpp"
#include "./pass/Pass.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 "pass/BorderPassElement.hpp"
#include "pass/ClearPassElement.hpp"
#include "pass/FramebufferElement.hpp"
#include "pass/PreBlurElement.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"

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

const std::vector<const char*> ASSET_PATHS = {
#ifdef DATAROOTDIR
    DATAROOTDIR,
#endif
    "/usr/share",
    "/usr/local/share",
};
class CToplevelExportProtocolManager;
class CInputManager;
struct SSessionLockSurface;
namespace Screenshare {
    class CScreenshareFrame;
};

enum eDamageTrackingModes : int8_t {
    DAMAGE_TRACKING_INVALID = -1,
    DAMAGE_TRACKING_NONE    = 0,
    DAMAGE_TRACKING_MONITOR,
    DAMAGE_TRACKING_FULL,
};

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

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

struct SRenderWorkspaceUntilData {
    PHLLS     ls;
    PHLWINDOW w;
};

enum eRenderProjectionType : uint8_t {
    RPT_MONITOR,
    RPT_MIRROR,
    RPT_FB,
    RPT_EXPORT,
};

struct SRenderData {
    // can be private
    Mat3x3 targetProjection;

    // ----------------------

    // used by public
    Vector2D              fbSize = {-1, -1};
    PHLMONITORREF         pMonitor;

    eRenderProjectionType projectionType = RPT_MONITOR;

    SP<IFramebuffer>      currentFB = nullptr; // current rendering to
    SP<IFramebuffer>      mainFB    = nullptr; // main to render to
    SP<IFramebuffer>      outFB     = nullptr; // out to render to (if offloaded, etc)

    CRegion               damage;
    CRegion               finalDamage; // damage used for funal off -> main

    SRenderModifData      renderModif;
    float                 mouseZoomFactor    = 1.f;
    bool                  mouseZoomUseMouse  = true; // true by default
    bool                  useNearestNeighbor = false;
    bool                  blockScreenShader  = false;

    Vector2D              primarySurfaceUVTopLeft     = Vector2D(-1, -1);
    Vector2D              primarySurfaceUVBottomRight = Vector2D(-1, -1);

    // TODO remove and pass directly
    CBox                   clipBox = {}; // scaled coordinates
    PHLWINDOWREF           currentWindow;
    WP<CWLSurfaceResource> surface;

    bool                   transformDamage = true;
    bool                   noSimplify      = false;
};

struct STFRange {
    float min = 0;
    float max = 80;
};

struct SCMSettings {
    NColorManagement::eTransferFunction  sourceTF = NColorManagement::CM_TRANSFER_FUNCTION_GAMMA22;
    NColorManagement::eTransferFunction  targetTF = NColorManagement::CM_TRANSFER_FUNCTION_GAMMA22;
    STFRange                             srcTFRange;
    STFRange                             dstTFRange;
    float                                srcRefLuminance = 80;
    float                                dstRefLuminance = 80;
    std::array<std::array<double, 3>, 3> convertMatrix;

    bool                                 needsTonemap    = false;
    float                                maxLuminance    = 80;
    float                                dstMaxLuminance = 80;
    std::array<std::array<double, 3>, 3> dstPrimaries2XYZ;
    bool                                 needsSDRmod             = false;
    float                                sdrSaturation           = 1.0;
    float                                sdrBrightnessMultiplier = 1.0;
};

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

    WP<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);
    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                                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);
    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);
    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);
    virtual bool                    reloadShaders(const std::string& path = "") = 0;

    bool                            needsACopyFB(PHLMONITOR mon);

  protected:
    virtual void              renderOffToMain(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 void         draw(CBorderPassElement* element, const CRegion& damage)   = 0;
    virtual void         draw(CClearPassElement* element, const CRegion& damage)    = 0;
    virtual void         draw(CFramebufferElement* element, const CRegion& damage)  = 0;
    virtual void         draw(CPreBlurElement* element, const CRegion& damage)      = 0;
    virtual void         draw(CRectPassElement* element, const CRegion& damage)     = 0;
    virtual void         draw(CShadowPassElement* element, const CRegion& damage)   = 0;
    virtual void         draw(CTexPassElement* element, const CRegion& damage)      = 0;
    virtual void         draw(CTextureMatteElement* element, const CRegion& damage) = 0;
    virtual SP<ITexture> getBlurTexture(PHLMONITORREF pMonitor);
    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;

    // 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 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();

    void drawRect(CRectPassElement* element, const CRegion& damage);
    void drawHints(CRendererHintsPassElement* element, const CRegion& damage);
    void drawPreBlur(CPreBlurElement* element, const CRegion& damage);
    void drawSurface(CSurfacePassElement* element, const CRegion& damage);
    void preDrawSurface(CSurfacePassElement* element, const CRegion& damage);
    void drawTex(CTexPassElement* element, const CRegion& damage);
    void drawTexMatte(CTextureMatteElement* element, const CRegion& damage);
};

inline UP<IHyprRenderer> g_pHyprRenderer;