#pragma once #include "../defines.hpp" #include #include #include #include #include #include #include "OpenGL.hpp" #include "./SyncFDManager.hpp" #include "./pass/Pass.hpp" #include "./pass/BorderPassElement.hpp" #include "./pass/ClearPassElement.hpp" #include "./pass/FramebufferElement.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" #include "types.hpp" #include "../helpers/Monitor.hpp" #include "../desktop/view/LayerSurface.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 struct SMonitorRule; class CWorkspace; class CInputPopup; class IHLBuffer; class CEventLoopTimer; class CToplevelExportProtocolManager; class CInputManager; struct SSessionLockSurface; namespace Screenshare { class CScreenshareFrame; }; namespace Render { using CScopeGuard = Hyprutils::Utils::CScopeGuard; class IElementRenderer; class CRenderPass; class IHyprRenderer { public: IHyprRenderer(); virtual ~IHyprRenderer(); enum eType : uint8_t { RT_GL = 1, RT_VK = 2, }; virtual eType type() = 0; WP glBackend(); void renderMonitor(PHLMONITOR pMonitor, bool commit = true); void arrangeLayersForMonitor(const MONITORID&); void damageSurface(SP, 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); std::tuple 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 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); void renderSnapshot(PHLWINDOW); void renderSnapshot(PHLLS); void renderSnapshot(WP); bool beginFullFakeRender(PHLMONITOR pMonitor, CRegion& damage, SP fb); bool beginRenderToBuffer(PHLMONITOR pMonitor, CRegion& damage, SP buffer, bool simple = false); virtual void startRenderPass() {}; virtual void endRender(const std::function& renderingDoneCallback = {}) = 0; NColorManagement::PImageDescription workBufferImageDescription(); bool m_bBlockSurfaceFeedback = false; bool m_bRenderingSnapshot = false; PHLMONITORREF m_mostHzMonitor; bool m_directScanoutBlocked = false; void setSurfaceScanoutMode(SP 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 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> surf; std::string name; } m_lastCursorData; CRenderPass m_renderPass; SP renderSplash(const std::function(const int, const int, unsigned char* const)>& handleData, const int fontSize, const int maxWidth = 1024, const int maxHeight = 1024); virtual SP getOrCreateRenderbuffer(SP 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 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 element, const CRegion& damage = {}); void draw(const CBorderPassElement::SBorderData& data, const CRegion& damage = {}); void draw(const CClearPassElement::SClearData& data, const CRegion& damage = {}); void draw(const CFramebufferElement::SFramebufferElementData& data, const CRegion& damage = {}); void draw(const CRectPassElement::SRectData& data, const CRegion& damage = {}); void draw(const CRendererHintsPassElement::SData& data, const CRegion& damage = {}); void draw(const CShadowPassElement::SShadowData& data, const CRegion& damage = {}); void draw(const CSurfacePassElement::SRenderData& data, const CRegion& damage = {}); void draw(const CTexPassElement::SRenderData& data, const CRegion& damage = {}); void draw(const CTextureMatteElement::STextureMatteData& data, const CRegion& damage = {}); virtual void bindFB(SP fb); UP bindTempFB(SP fb); virtual UP createSyncFDManager() = 0; virtual WP elementRenderer() = 0; virtual SP createStencilTexture(const int width, const int height) = 0; virtual SP createTexture(bool opaque = false) = 0; virtual SP createTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size, bool keepDataCopy = false, bool opaque = false) = 0; virtual SP createTexture(const Aquamarine::SDMABUFAttrs&, bool opaque = false) = 0; virtual SP createTexture(const int width, const int height, unsigned char* const) = 0; virtual SP createTexture(cairo_surface_t* cairo) = 0; virtual SP createTexture(std::span lut3D, size_t N) = 0; virtual SP createTexture(const SP buffer, bool keepDataCopy = false); virtual SP renderText(const std::string& text, CHyprColor col, int pt, bool italic = false, const std::string& fontFamily = "", int maxWidth = 0, int weight = 400); virtual SP renderText(Hyprgraphics::CTextResource::STextResourceData&& data); SP loadAsset(const std::string& filename); virtual bool shouldUseNewBlurOptimizations(PHLLS pLayer, PHLWINDOW pWindow); virtual bool explicitSyncSupported() = 0; virtual std::vector getDRMFormats() = 0; virtual std::vector getDRMFormatModifiers(DRMFormat format) = 0; virtual SP 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 transform = std::nullopt); Mat3x3 projectBoxToTarget(const CBox& box, std::optional transform = std::nullopt); SP blurMainFramebuffer(float a, CRegion* originalDamage); virtual SP blurFramebuffer(SP source, float a, CRegion* originalDamage) = 0; void preBlurForCurrentMonitor(CRegion* fakeDamage); SCMSettings getCMSettings(const NColorManagement::PImageDescription imageDescription, const NColorManagement::PImageDescription targetImageDescription, SP surface = nullptr, bool modifySDR = false, float sdrMinLuminance = -1.0f, int sdrMaxLuminance = -1, bool shouldUseSurface = false); void clearCMSettingsCache(); virtual bool reloadShaders(const std::string& path = "") = 0; protected: virtual void renderOffToMain(SP off) = 0; virtual SP getOrCreateRenderbufferInternal(SP buffer, uint32_t fmt) = 0; void renderMirrored(); void setDamage(const CRegion& damage_, std::optional 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 buffer = {}, SP 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 fb, bool simple = false) { return false; }; virtual void initRender() {}; virtual bool initRenderBuffer(SP buffer, uint32_t fmt) { return false; }; SP getBackground(PHLMONITOR pMonitor); virtual SP getBlurTexture(PHLMONITORREF pMonitor); struct SCMSettingsCacheEntry { uint64_t srcDescId = 0, dstDescId = 0; void* surfacePtr = nullptr; // read-only!! bool modifySDR = false; float sdrMinLuminance = -1.F; int sdrMaxLuminance = -1; SCMSettings settings; }; std::vector m_cmSettingsCache; SP m_lockDeadTexture; SP m_lockDead2Texture; SP m_lockTtyTextTexture; bool m_monitorTransformEnabled = false; // do not modify directly std::stack m_monitorTransformStack; void handleFullscreenSettings(PHLMONITOR pMonitor); // old private: void arrangeLayerArray(PHLMONITOR, const std::vector&, 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, 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 m_missingAssetTexture; ASP m_backgroundResource; bool m_backgroundResourceFailed = false; bool shouldBlur(PHLLS ls); bool shouldBlur(PHLWINDOW w); bool shouldBlur(WP p); bool m_cursorHidden = false; bool m_cursorHiddenByCondition = false; bool m_cursorHasSurface = false; SP 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> m_renderbuffers; std::vector m_renderUnfocused; SP m_renderUnfocusedTimer; friend class CRenderPass; friend class Render::GL::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(); }; } inline UP g_pHyprRenderer;