mirror of
https://github.com/hyprwm/Hyprland
synced 2026-05-14 12:18:32 +02:00
359 lines
16 KiB
C++
359 lines
16 KiB
C++
#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 <GLES3/gl32.h>
|
|
#include <cstdint>
|
|
#include <list>
|
|
#include <string>
|
|
#include <stack>
|
|
#include <map>
|
|
|
|
#include <cairo/cairo.h>
|
|
|
|
#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 <EGL/egl.h>
|
|
#include <EGL/eglext.h>
|
|
#include <GLES2/gl2ext.h>
|
|
#include <aquamarine/buffer/Buffer.hpp>
|
|
#include <hyprutils/os/FileDescriptor.hpp>
|
|
#include <hyprgraphics/resource/resources/ImageResource.hpp>
|
|
|
|
#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<CGLFramebuffer*>(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<SVertex, 4> 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<std::map<Render::ShaderFeatureFlags, SP<CShader>>, Render::SH_FRAG_LAST> fragVariants;
|
|
};
|
|
|
|
struct SCurrentRenderData {
|
|
PHLMONITORREF pMonitor;
|
|
Mat3x3 projection;
|
|
Mat3x3 savedProjection;
|
|
Mat3x3 monitorProjection;
|
|
|
|
SP<IFramebuffer> currentFB = nullptr; // current rendering to
|
|
SP<IFramebuffer> mainFB = nullptr; // main to render to
|
|
SP<IFramebuffer> 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<CWLSurfaceResource> surface;
|
|
};
|
|
|
|
class CEGLSync : public ISyncFDManager {
|
|
public:
|
|
static UP<CEGLSync> 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<ITexture> blurredBG;
|
|
|
|
const CRegion* damage = nullptr;
|
|
SP<CWLSurfaceResource> 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<IFramebuffer> fb = nullptr, std::optional<CRegion> finalDamage = {});
|
|
void beginSimple(PHLMONITOR, const CRegion& damage, SP<IRenderbuffer> rb = nullptr, SP<IFramebuffer> fb = nullptr);
|
|
void end();
|
|
|
|
void renderRect(const CBox&, const CHyprColor&, SRectRenderData data);
|
|
void renderTexture(SP<ITexture>, 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<ITexture> tex, const CBox& pBox, SP<IFramebuffer> matte);
|
|
void renderTexturePrimitive(SP<ITexture> 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<IFramebuffer> off);
|
|
|
|
std::vector<SDRMFormat> getDRMFormats();
|
|
std::vector<uint64_t> getDRMFormatModifiers(DRMFormat format);
|
|
EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs);
|
|
|
|
bool initShaders(const std::string& path = "");
|
|
|
|
WP<CShader> useShader(WP<CShader> prog);
|
|
|
|
bool explicitSyncSupported();
|
|
WP<CShader> getShaderVariant(Render::ePreparedFragmentShader frag, Render::ShaderFeatureFlags features = 0);
|
|
|
|
bool m_shadersInitialized = false;
|
|
SP<SPreparedShaders> 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<PHLMONITORREF, SP<IFramebuffer>> 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<bool, CAP_STATUS_END> m_capStatus = {};
|
|
|
|
std::vector<SDRMFormat> 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<CShader> m_finalScreenShader;
|
|
GLuint m_currentProgram;
|
|
|
|
void initDRMFormats();
|
|
void initEGL(bool gbm);
|
|
EGLDeviceEXT eglDeviceFromDRMFD(int drmFD);
|
|
|
|
// for the final shader
|
|
std::array<CTimer, POINTER_PRESSED_HISTORY_LENGTH> m_pressedHistoryTimers = {};
|
|
std::array<Vector2D, POINTER_PRESSED_HISTORY_LENGTH> m_pressedHistoryPositions = {};
|
|
GLint m_pressedHistoryKilled = 0;
|
|
GLint m_pressedHistoryTouched = 0;
|
|
|
|
//
|
|
std::optional<std::vector<uint64_t>> getModsForFormat(EGLint format);
|
|
|
|
// returns the out FB, can be either Mirror or MirrorSwap
|
|
SP<IFramebuffer> blurFramebufferWithDamage(float a, CRegion* damage, CGLFramebuffer& source);
|
|
|
|
void passCMUniforms(WP<CShader>, const NColorManagement::PImageDescription imageDescription, const NColorManagement::PImageDescription targetImageDescription,
|
|
bool modifySDR, float sdrMinLuminance, int sdrMaxLuminance, const SCMSettings& settings);
|
|
void passCMUniforms(WP<CShader>, const NColorManagement::PImageDescription imageDescription, const NColorManagement::PImageDescription targetImageDescription,
|
|
bool modifySDR = false, float sdrMinLuminance = -1.0f, int sdrMaxLuminance = -1);
|
|
void passCMUniforms(WP<CShader>, const NColorManagement::PImageDescription imageDescription);
|
|
void passCMUniforms(WP<CShader>, 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<CShader> renderToOutputInternal();
|
|
WP<CShader> renderToFBInternal(SP<ITexture> tex, const STextureRenderData& data, eTextureType texType, const CBox& newBox);
|
|
void renderTextureInternal(SP<ITexture>, const CBox&, const STextureRenderData& data);
|
|
void renderTextureWithBlurInternal(SP<ITexture>, 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<CHyprOpenGLImpl> g_pHyprOpenGL;
|
|
}
|