#pragma once #include "../defines.hpp" #include "../helpers/Monitor.hpp" #include "../helpers/Color.hpp" #include "../helpers/time/Timer.hpp" #include "../helpers/math/Math.hpp" #include "../helpers/Format.hpp" #include "../helpers/sync/SyncTimeline.hpp" #include #include #include #include #include #include #include #include "render/SyncFDManager.hpp" #include "types.hpp" #include "Shader.hpp" #include "Texture.hpp" #include "Framebuffer.hpp" #include "Renderbuffer.hpp" #include "../desktop/DesktopTypes.hpp" #include "pass/Pass.hpp" #include #include #include #include #include #include #include "../debug/TracyDefines.hpp" #include "../protocols/core/Compositor.hpp" #include "ShaderLoader.hpp" #include "gl/GLFramebuffer.hpp" #include "gl/GLRenderbuffer.hpp" #include "pass/TexPassElement.hpp" #define GLFB(ifb) dc(ifb.get()) struct gbm_device; namespace Render { class IHyprRenderer; } namespace Config { class CGradientValueData; } namespace Render::GL { struct SVertex { float x, y; // position float u, v; // uv }; constexpr std::array fullVerts = {{ {0.0f, 0.0f, 0.0f, 0.0f}, // top-left {0.0f, 1.0f, 0.0f, 1.0f}, // bottom-left {1.0f, 0.0f, 1.0f, 0.0f}, // top-right {1.0f, 1.0f, 1.0f, 1.0f}, // bottom-right }}; inline const float fanVertsFull[] = {-1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f}; enum eMonitorRenderFBs : uint8_t { FB_MONITOR_RENDER_MAIN = 0, FB_MONITOR_RENDER_CURRENT = 1, FB_MONITOR_RENDER_OUT = 2, }; enum eMonitorExtraRenderFBs : uint8_t { FB_MONITOR_RENDER_EXTRA_OFFLOAD = 0, FB_MONITOR_RENDER_EXTRA_MIRROR, FB_MONITOR_RENDER_EXTRA_MIRROR_SWAP, FB_MONITOR_RENDER_EXTRA_OFF_MAIN, FB_MONITOR_RENDER_EXTRA_MONITOR_MIRROR, FB_MONITOR_RENDER_EXTRA_BLUR, }; struct SFragShaderDesc { Render::ePreparedFragmentShader id; const char* file; }; struct SPreparedShaders { std::string TEXVERTSRC; std::string TEXVERTSRC320; std::array>, Render::SH_FRAG_LAST> fragVariants; }; struct SCurrentRenderData { PHLMONITORREF pMonitor; Mat3x3 projection; Mat3x3 savedProjection; Mat3x3 monitorProjection; SP currentFB = nullptr; // current rendering to SP mainFB = nullptr; // main to render to SP outFB = nullptr; // out to render to (if offloaded, etc) CRegion damage; CRegion finalDamage; // damage used for funal off -> main Render::SRenderModifData renderModif; float mouseZoomFactor = 1.f; bool mouseZoomUseMouse = true; // true by default bool useNearestNeighbor = false; bool blockScreenShader = false; bool simplePass = false; bool transformDamage = true; bool noSimplify = false; Vector2D primarySurfaceUVTopLeft = Vector2D(-1, -1); Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1); CBox clipBox = {}; // scaled coordinates CRegion clipRegion; uint32_t discardMode = DISCARD_OPAQUE; float discardOpacity = 0.f; PHLLSREF currentLS; PHLWINDOWREF currentWindow; WP surface; }; class CEGLSync : public ISyncFDManager { public: static UP create(); ~CEGLSync() override; bool isValid() override; private: CEGLSync() : ISyncFDManager() {}; EGLSyncKHR m_sync = EGL_NO_SYNC_KHR; friend class CHyprOpenGLImpl; }; class CHyprOpenGLImpl { public: CHyprOpenGLImpl(); ~CHyprOpenGLImpl(); struct SRectRenderData { const CRegion* damage = nullptr; int round = 0; float roundingPower = 2.F; bool blur = false; float blurA = 1.F; bool xray = false; }; struct STextureRenderData { bool blur = false; float blurA = 1.F, overallA = 1.F; bool blockBlurOptimization = false; SP blurredBG; const CRegion* damage = nullptr; SP surface = nullptr; float a = 1.F; int round = 0; float roundingPower = 2.F; bool discardActive = false; bool allowCustomUV = false; bool allowDim = true; bool noAA = false; // unused GLenum wrapX = GL_CLAMP_TO_EDGE, wrapY = GL_CLAMP_TO_EDGE; bool cmBackToSRGB = false; bool finalMonitorCM = false; uint32_t discardMode = DISCARD_OPAQUE; float discardOpacity = 0.f; CRegion clipRegion; PHLLSREF currentLS; Vector2D primarySurfaceUVTopLeft = Vector2D(-1, -1); Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1); }; struct SBorderRenderData { int round = 0; float roundingPower = 2.F; int borderSize = 1; float a = 1.0; int outerRound = -1; /* use round */ }; void makeEGLCurrent(); void begin(PHLMONITOR, const CRegion& damage, SP fb = nullptr, std::optional finalDamage = {}); void beginSimple(PHLMONITOR, const CRegion& damage, SP rb = nullptr, SP fb = nullptr); void end(); void renderRect(const CBox&, const CHyprColor&, SRectRenderData data); void renderTexture(SP, const CBox&, STextureRenderData data); void renderRoundedShadow(const CBox&, int round, float roundingPower, int range, const CHyprColor& color, float a = 1.0); void renderInnerGlow(const CBox&, int round, float roundingPower, int range, const CHyprColor& color, int glowPower, float a = 1.0); void renderBorder(const CBox&, const Config::CGradientValueData&, SBorderRenderData data); void renderBorder(const CBox&, const Config::CGradientValueData&, const Config::CGradientValueData&, float lerp, SBorderRenderData data); void renderTextureMatte(SP tex, const CBox& pBox, SP matte); void renderTexturePrimitive(SP tex, const CBox& box); void setViewport(GLint x, GLint y, GLsizei width, GLsizei height); void setCapStatus(int cap, bool status); void blend(bool enabled); 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(PHLMONITORREF); void preRender(PHLMONITOR); void saveBufferForMirror(const CBox&); void applyScreenShader(const std::string& path); void renderOffToMain(SP off); std::vector getDRMFormats(); std::vector getDRMFormatModifiers(DRMFormat format); EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs); bool initShaders(const std::string& path = ""); WP useShader(WP prog); bool explicitSyncSupported(); WP getShaderVariant(Render::ePreparedFragmentShader frag, Render::ShaderFeatureFlags features = 0); bool m_shadersInitialized = false; SP m_shaders; Hyprutils::OS::CFileDescriptor m_gbmFD; gbm_device* m_gbmDevice = nullptr; EGLContext m_eglContext = nullptr; EGLDisplay m_eglDisplay = nullptr; EGLDeviceEXT m_eglDevice = nullptr; std::map> m_monitorBGFBs; 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_proc; struct { bool EXT_read_format_bgra = false; bool EXT_image_dma_buf_import = false; bool EXT_image_dma_buf_import_modifiers = false; bool KHR_context_flush_control = false; bool KHR_display_reference = false; bool IMG_context_priority = false; bool EXT_create_context_robustness = false; bool EGL_ANDROID_native_fence_sync_ext = false; } m_exts; enum eEGLContextVersion : uint8_t { EGL_CONTEXT_GLES_2_0 = 0, EGL_CONTEXT_GLES_3_0, EGL_CONTEXT_GLES_3_2, }; eEGLContextVersion m_eglContextVersion = EGL_CONTEXT_GLES_3_2; enum eCachedCapStatus : uint8_t { CAP_STATUS_BLEND = 0, CAP_STATUS_SCISSOR_TEST, CAP_STATUS_STENCIL_TEST, CAP_STATUS_END }; private: struct { GLint x = 0; GLint y = 0; GLsizei width = 0; GLsizei height = 0; } m_lastViewport; std::array m_capStatus = {}; std::vector m_drmFormats; bool m_hasModifiers = false; int m_drmFD = -1; std::string m_extensions; bool m_fakeFrame = false; bool m_applyFinalShader = false; bool m_blend = false; bool m_offloadedFramebuffer = false; bool m_cmSupported = true; SP m_finalScreenShader; GLuint m_currentProgram; void initDRMFormats(); void initEGL(bool gbm); EGLDeviceEXT eglDeviceFromDRMFD(int drmFD); // for the final shader std::array m_pressedHistoryTimers = {}; std::array m_pressedHistoryPositions = {}; GLint m_pressedHistoryKilled = 0; GLint m_pressedHistoryTouched = 0; // std::optional> getModsForFormat(EGLint format); // returns the out FB, can be either Mirror or MirrorSwap SP blurFramebufferWithDamage(float a, CRegion* damage, CGLFramebuffer& source); void passCMUniforms(WP, const NColorManagement::PImageDescription imageDescription, const NColorManagement::PImageDescription targetImageDescription, bool modifySDR, float sdrMinLuminance, int sdrMaxLuminance, const SCMSettings& settings); void passCMUniforms(WP, const NColorManagement::PImageDescription imageDescription, const NColorManagement::PImageDescription targetImageDescription, bool modifySDR = false, float sdrMinLuminance = -1.0f, int sdrMaxLuminance = -1); void passCMUniforms(WP, const NColorManagement::PImageDescription imageDescription); void passCMUniforms(WP, const NColorManagement::PImageDescription imageDescription, const SCMSettings& settings); void renderRectInternal(const CBox&, const CHyprColor&, const SRectRenderData& data); void renderRectWithBlurInternal(const CBox&, const CHyprColor&, const SRectRenderData& data); void renderRectWithDamageInternal(const CBox&, const CHyprColor&, const SRectRenderData& data); WP renderToOutputInternal(); WP renderToFBInternal(SP tex, const STextureRenderData& data, eTextureType texType, const CBox& newBox); void renderTextureInternal(SP, const CBox&, const STextureRenderData& data); void renderTextureWithBlurInternal(SP, const CBox&, const STextureRenderData& data); friend class IHyprRenderer; friend class CHyprGLRenderer; friend class CGLElementRenderer; friend class CTexPassElement; friend class CPreBlurElement; friend class CSurfacePassElement; }; inline UP g_pHyprOpenGL; }