aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/render/OpenGL.hpp
blob: fabd3666a074d9c963015b69adc804eed9e11e97 (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
#pragma once

#include "../defines.hpp"
#include "../helpers/Monitor.hpp"
#include "../helpers/Color.hpp"
#include <list>
#include <unordered_map>

#include <cairo/cairo.h>

#include "Shader.hpp"
#include "Texture.hpp"
#include "Framebuffer.hpp"

class CHyprRenderer;

inline const float fullVerts[] = {
    1, 0,  // top right
    0, 0,  // top left
    1, 1,  // bottom right
    0, 1,  // bottom left
};
inline const float fanVertsFull[] = {
    -1.0f, -1.0f,
    1.0f, -1.0f,
    1.0f, 1.0f,
    -1.0f, 1.0f
};

struct SMonitorRenderData {
    CFramebuffer primaryFB;
    CFramebuffer mirrorFB;     // these are used for some effects,
    CFramebuffer mirrorSwapFB; // etc

    CFramebuffer monitorMirrorFB; // used for mirroring outputs

    CTexture     stencilTex;

    CFramebuffer blurFB;
    bool         blurFBDirty = true;

    wlr_box      backgroundTexBox;

    // Shaders
    bool                    m_bShadersInitialized = false;
    CShader                 m_shQUAD;
    CShader                 m_shRGBA;
    CShader                 m_shRGBX;
    CShader                 m_shEXT;
    CShader                 m_shBLUR1;
    CShader                 m_shBLUR2;
    CShader                 m_shSHADOW;
    CShader                 m_shBORDER1;
    //
};

struct SCurrentRenderData {
    CMonitor*   pMonitor = nullptr;
    float       projection[9];

    SMonitorRenderData* pCurrentMonData = nullptr;

    pixman_region32_t* pDamage = nullptr;

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

    wlr_box     clipBox = {};
};

class CGradientValueData;

class CHyprOpenGLImpl {
public:

    CHyprOpenGLImpl();

    void    begin(CMonitor*, pixman_region32_t*, bool fake = false);
    void    end();

    void    renderRect(wlr_box*, const CColor&, int round = 0);
    void    renderRectWithDamage(wlr_box*, const CColor&, pixman_region32_t* damage, int round = 0);
    void    renderTexture(wlr_texture*, wlr_box*, float a, int round = 0, bool allowCustomUV = false);
    void    renderTexture(const CTexture&, wlr_box*, float a, int round = 0, bool discardOpaque = false, bool allowCustomUV = false);
    void    renderTextureWithBlur(const CTexture&, wlr_box*, float a, wlr_surface* pSurface, int round = 0);
    void    renderRoundedShadow(wlr_box*, int round, int range, float a = 1.0);
    void    renderBorder(wlr_box*, const CGradientValueData&, int round, float a = 1.0);

    void    makeWindowSnapshot(CWindow*);
    void    makeRawWindowSnapshot(CWindow*, CFramebuffer*);
    void    makeLayerSnapshot(SLayerSurface*);
    void    renderSnapshot(CWindow**);
    void    renderSnapshot(SLayerSurface**);

    void    clear(const CColor&);
    void    clearWithTex();
    void    scissor(const wlr_box*, bool transform = true);
    void    scissor(const pixman_box32*, bool transform = true);
    void    scissor(const int x, const int y, const int w, const int h, bool transform = true);

    void    destroyMonitorResources(CMonitor*);

    void    markBlurDirtyForMonitor(CMonitor*);

    void    preWindowPass();
    void    preRender(CMonitor*);

    void    saveBufferForMirror();
    void    renderMirrored();

    void    onWindowResizeStart(CWindow*);
    void    onWindowResizeEnd(CWindow*);

    void    applyScreenShader(const std::string& path);

    SCurrentRenderData m_RenderData;

    GLint  m_iCurrentOutputFb = 0;
    GLint  m_iWLROutputFb = 0;

    bool   m_bReloadScreenShader = true; // at launch it can be set

    CWindow* m_pCurrentWindow = nullptr; // hack to get the current rendered window

    pixman_region32_t m_rOriginalDamageRegion; // used for storing the pre-expanded region

    std::unordered_map<CWindow*, CFramebuffer> m_mWindowFramebuffers;
    std::unordered_map<SLayerSurface*, CFramebuffer> m_mLayerFramebuffers;
    std::unordered_map<CMonitor*, SMonitorRenderData> m_mMonitorRenderResources;
    std::unordered_map<CMonitor*, CTexture> m_mMonitorBGTextures;

private:
    std::list<GLuint>       m_lBuffers;
    std::list<GLuint>       m_lTextures;

    int                     m_iDRMFD;
    std::string             m_szExtensions;

    bool                    m_bFakeFrame = false;
    bool                    m_bEndFrame = false;
    bool                    m_bApplyFinalShader = false;

    CShader                 m_sFinalScreenShader;

    GLuint                  createProgram(const std::string&, const std::string&, bool dynamic = false);
    GLuint                  compileShader(const GLuint&, std::string, bool dynamic = false);
    void                    createBGTextureForMonitor(CMonitor*);
    void                    initShaders();

    // returns the out FB, can be either Mirror or MirrorSwap
    CFramebuffer*           blurMainFramebufferWithDamage(float a, wlr_box* pBox, pixman_region32_t* damage);

    void                    renderTextureInternalWithDamage(const CTexture&, wlr_box* pBox, float a, pixman_region32_t* damage, int round = 0, bool discardOpaque = false, bool noAA = false, bool allowCustomUV = false, bool allowDim = false);
    void                    renderSplash(cairo_t *const, cairo_surface_t *const, double);

    void                    preBlurForCurrentMonitor();

    friend class CHyprRenderer;
};

inline std::unique_ptr<CHyprOpenGLImpl> g_pHyprOpenGL;