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

#include "../defines.hpp"
#include "../helpers/Monitor.hpp"
#include "../helpers/Color.hpp"
#include "../helpers/Timer.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};

enum eDiscardMode
{
    DISCARD_OPAQUE    = 1,
    DISCARD_ALPHAZERO = 1 << 1
};

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;
    bool         blurFBShouldRender = false;

    wlr_box      backgroundTexBox;

    // Shaders
    bool    m_bShadersInitialized = false;
    CShader m_shQUAD;
    CShader m_shRGBA;
    CShader m_shPASSTHRURGBA;
    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 = {};

    uint32_t            discardMode = DISCARD_OPAQUE;
};

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 discardActive = false, bool allowCustomUV = false);
    void                                       renderTextureWithBlur(const CTexture&, wlr_box*, float a, wlr_surface* pSurface, int round = 0, bool blockBlurOptimization = false);
    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                                       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;
    CTimer            m_tGlobalTimer;

    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;