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
|
#pragma once
#include "../defines.hpp"
#include "../helpers/Monitor.hpp"
#include "../helpers/Color.hpp"
#include "../helpers/Timer.hpp"
#include "../helpers/math/Math.hpp"
#include "../helpers/Format.hpp"
#include "../helpers/sync/SyncTimeline.hpp"
#include <cstdint>
#include <list>
#include <unordered_map>
#include <map>
#include <cairo/cairo.h>
#include "Shader.hpp"
#include "Texture.hpp"
#include "Framebuffer.hpp"
#include "Transformer.hpp"
#include "Renderbuffer.hpp"
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES2/gl2ext.h>
#include <aquamarine/buffer/Buffer.hpp>
#include "../debug/TracyDefines.hpp"
struct gbm_device;
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_ALPHA = 1 << 1
};
struct SRenderModifData {
enum eRenderModifType {
RMOD_TYPE_SCALE, /* scale by a float */
RMOD_TYPE_SCALECENTER, /* scale by a float from the center */
RMOD_TYPE_TRANSLATE, /* translate by a Vector2D */
RMOD_TYPE_ROTATE, /* rotate by a float in rad from top left */
RMOD_TYPE_ROTATECENTER, /* rotate by a float in rad from center */
};
std::vector<std::pair<eRenderModifType, std::any>> modifs;
void applyToBox(CBox& box);
void applyToRegion(CRegion& rg);
float combinedScale();
bool enabled = true;
};
struct SMonitorRenderData {
CFramebuffer offloadFB;
CFramebuffer mirrorFB; // these are used for some effects,
CFramebuffer mirrorSwapFB; // etc
CFramebuffer offMainFB;
CFramebuffer monitorMirrorFB; // used for mirroring outputs, does not contain artifacts like offloadFB
SP<CTexture> stencilTex = makeShared<CTexture>();
CFramebuffer blurFB;
bool blurFBDirty = true;
bool blurFBShouldRender = false;
// Shaders
bool m_bShadersInitialized = false;
CShader m_shQUAD;
CShader m_shRGBA;
CShader m_shPASSTHRURGBA;
CShader m_shMATTE;
CShader m_shRGBX;
CShader m_shEXT;
CShader m_shBLUR1;
CShader m_shBLUR2;
CShader m_shBLURPREPARE;
CShader m_shBLURFINISH;
CShader m_shSHADOW;
CShader m_shBORDER1;
CShader m_shGLITCH;
//
};
struct SCurrentRenderData {
CMonitor* pMonitor = nullptr;
PHLWORKSPACE pWorkspace = nullptr;
float projection[9];
float savedProjection[9];
std::array<float, 9> monitorProjection;
SMonitorRenderData* pCurrentMonData = nullptr;
CFramebuffer* currentFB = nullptr; // current rendering to
CFramebuffer* mainFB = nullptr; // main to render to
CFramebuffer* 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 forceIntrospection = false; // cleaned in ::end()
bool blockScreenShader = false;
bool simplePass = false;
Vector2D primarySurfaceUVTopLeft = Vector2D(-1, -1);
Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1);
CBox clipBox = {}; // scaled coordinates
uint32_t discardMode = DISCARD_OPAQUE;
float discardOpacity = 0.f;
};
class CEGLSync {
public:
~CEGLSync();
EGLSyncKHR sync = nullptr;
int fd();
bool wait();
private:
CEGLSync() = default;
int m_iFd = -1;
friend class CHyprOpenGLImpl;
};
class CGradientValueData;
class CHyprOpenGLImpl {
public:
CHyprOpenGLImpl();
~CHyprOpenGLImpl();
void begin(CMonitor*, const CRegion& damage, CFramebuffer* fb = nullptr, std::optional<CRegion> finalDamage = {});
void beginSimple(CMonitor*, const CRegion& damage, SP<CRenderbuffer> rb = nullptr, CFramebuffer* fb = nullptr);
void end();
void renderRect(CBox*, const CColor&, int round = 0);
void renderRectWithBlur(CBox*, const CColor&, int round = 0, float blurA = 1.f, bool xray = false);
void renderRectWithDamage(CBox*, const CColor&, CRegion* damage, int round = 0);
void renderTexture(SP<CTexture>, CBox*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false);
void renderTextureWithDamage(SP<CTexture>, CBox*, CRegion* damage, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false,
SP<CSyncTimeline> waitTimeline = nullptr, uint64_t waitPoint = 0);
void renderTextureWithBlur(SP<CTexture>, CBox*, float a, SP<CWLSurfaceResource> pSurface, int round = 0, bool blockBlurOptimization = false, float blurA = 1.f);
void renderRoundedShadow(CBox*, int round, int range, const CColor& color, float a = 1.0);
void renderBorder(CBox*, const CGradientValueData&, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */);
void renderTextureMatte(SP<CTexture> tex, CBox* pBox, CFramebuffer& matte);
void setMonitorTransformEnabled(bool enabled);
void setRenderModifEnabled(bool enabled);
void saveMatrix();
void setMatrixScaleTranslate(const Vector2D& translate, const float& scale);
void restoreMatrix();
void blend(bool enabled);
void makeWindowSnapshot(PHLWINDOW);
void makeRawWindowSnapshot(PHLWINDOW, CFramebuffer*);
void makeLayerSnapshot(PHLLS);
void renderSnapshot(PHLWINDOW);
void renderSnapshot(PHLLS);
bool shouldUseNewBlurOptimizations(PHLLS pLayer, PHLWINDOW pWindow);
void clear(const CColor&);
void clearWithTex();
void scissor(const CBox*, 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();
bool preBlurQueued();
void preRender(CMonitor*);
void saveBufferForMirror(CBox*);
void renderMirrored();
void applyScreenShader(const std::string& path);
void bindOffMain();
void renderOffToMain(CFramebuffer* off);
void bindBackOnMain();
void setDamage(const CRegion& damage, std::optional<CRegion> finalDamage = {});
uint32_t getPreferredReadFormat(CMonitor* pMonitor);
std::vector<SDRMFormat> getDRMFormats();
EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs);
SP<CEGLSync> createEGLSync(int fenceFD);
bool waitForTimelinePoint(SP<CSyncTimeline> timeline, uint64_t point);
SCurrentRenderData m_RenderData;
GLint m_iCurrentOutputFb = 0;
int m_iGBMFD = -1;
gbm_device* m_pGbmDevice = nullptr;
EGLContext m_pEglContext = nullptr;
EGLDisplay m_pEglDisplay = nullptr;
EGLDeviceEXT m_pEglDevice = nullptr;
bool m_bReloadScreenShader = true; // at launch it can be set
PHLWINDOWREF m_pCurrentWindow; // hack to get the current rendered window
PHLLS m_pCurrentLayer; // hack to get the current rendered layer
std::map<PHLWINDOWREF, CFramebuffer> m_mWindowFramebuffers;
std::map<PHLLSREF, CFramebuffer> m_mLayerFramebuffers;
std::unordered_map<CMonitor*, SMonitorRenderData> m_mMonitorRenderResources;
std::unordered_map<CMonitor*, CFramebuffer> m_mMonitorBGFBs;
struct {
PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES = nullptr;
PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES = nullptr;
PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR = nullptr;
PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR = nullptr;
PFNEGLQUERYDMABUFFORMATSEXTPROC eglQueryDmaBufFormatsEXT = nullptr;
PFNEGLQUERYDMABUFMODIFIERSEXTPROC eglQueryDmaBufModifiersEXT = nullptr;
PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT = nullptr;
PFNEGLDEBUGMESSAGECONTROLKHRPROC eglDebugMessageControlKHR = nullptr;
PFNEGLQUERYDEVICESEXTPROC eglQueryDevicesEXT = nullptr;
PFNEGLQUERYDEVICESTRINGEXTPROC eglQueryDeviceStringEXT = nullptr;
PFNEGLQUERYDISPLAYATTRIBEXTPROC eglQueryDisplayAttribEXT = nullptr;
PFNEGLCREATESYNCKHRPROC eglCreateSyncKHR = nullptr;
PFNEGLDESTROYSYNCKHRPROC eglDestroySyncKHR = nullptr;
PFNEGLDUPNATIVEFENCEFDANDROIDPROC eglDupNativeFenceFDANDROID = nullptr;
PFNEGLWAITSYNCKHRPROC eglWaitSyncKHR = nullptr;
} m_sProc;
struct {
bool EXT_read_format_bgra = false;
bool EXT_image_dma_buf_import = false;
bool EXT_image_dma_buf_import_modifiers = false;
bool KHR_display_reference = false;
bool IMG_context_priority = false;
bool EXT_create_context_robustness = false;
} m_sExts;
private:
std::list<GLuint> m_lBuffers;
std::list<GLuint> m_lTextures;
std::vector<SDRMFormat> drmFormats;
bool m_bHasModifiers = false;
int m_iDRMFD = -1;
std::string m_szExtensions;
bool m_bFakeFrame = false;
bool m_bEndFrame = false;
bool m_bApplyFinalShader = false;
bool m_bBlend = false;
bool m_bOffloadedFramebuffer = false;
CShader m_sFinalScreenShader;
CTimer m_tGlobalTimer;
SP<CTexture> m_pBackgroundTexture, m_pLockDeadTexture, m_pLockDead2Texture, m_pLockTtyTextTexture;
void logShaderError(const GLuint&, bool program = false);
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();
void initDRMFormats();
void initEGL(bool gbm);
EGLDeviceEXT eglDeviceFromDRMFD(int drmFD);
SP<CTexture> loadAsset(const std::string& file);
SP<CTexture> renderText(const std::string& text, CColor col, int pt, bool italic = false);
void initAssets();
//
std::optional<std::vector<uint64_t>> getModsForFormat(EGLint format);
// returns the out FB, can be either Mirror or MirrorSwap
CFramebuffer* blurMainFramebufferWithDamage(float a, CRegion* damage);
void renderTextureInternalWithDamage(SP<CTexture>, CBox* pBox, float a, CRegion* damage, int round = 0, bool discardOpaque = false, bool noAA = false,
bool allowCustomUV = false, bool allowDim = false, SP<CSyncTimeline> = nullptr, uint64_t waitPoint = 0);
void renderTexturePrimitive(SP<CTexture> tex, CBox* pBox);
void renderSplash(cairo_t* const, cairo_surface_t* const, double offset, const Vector2D& size);
void preBlurForCurrentMonitor();
bool passRequiresIntrospection(CMonitor* pMonitor);
friend class CHyprRenderer;
};
inline std::unique_ptr<CHyprOpenGLImpl> g_pHyprOpenGL;
|