diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 5d9cfd54..0bf2ffcf 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -17,14 +17,14 @@ CCompositor::CCompositor() { return; } - const auto DRMFD = wlr_backend_get_drm_fd(m_sWLRBackend); - if (DRMFD < 0) { + m_iDRMFD = wlr_backend_get_drm_fd(m_sWLRBackend); + if (m_iDRMFD < 0) { Debug::log(CRIT, "Couldn't query the DRM FD!"); RIP("DRMFD NULL!"); return; } - m_sWLRRenderer = wlr_gles2_renderer_create_with_drm_fd(DRMFD); + m_sWLRRenderer = wlr_gles2_renderer_create_with_drm_fd(m_iDRMFD); if (!m_sWLRRenderer) { Debug::log(CRIT, "m_sWLRRenderer was NULL!"); @@ -133,6 +133,9 @@ void CCompositor::startCompositor() { Debug::log(LOG, "Creating the InputManager!"); g_pInputManager = std::make_unique(); + Debug::log(LOG, "Creating the CHyprOpenGLImpl!"); + g_pHyprOpenGL = std::make_unique(); + Debug::log(LOG, "Creating the HyprRenderer!"); g_pHyprRenderer = std::make_unique(); diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 06daa6f9..1c9a691f 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -18,6 +18,7 @@ #include "helpers/Workspace.hpp" #include "Window.hpp" #include "render/Renderer.hpp" +#include "render/OpenGL.hpp" class CCompositor { public: @@ -46,6 +47,7 @@ public: wlr_input_inhibit_manager* m_sWLRInhibitMgr; wlr_keyboard_shortcuts_inhibit_manager_v1* m_sWLRKbShInhibitMgr; wlr_egl* m_sWLREGL; + int m_iDRMFD; // ------------------------------------------------- // diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 3a19fd19..c9ab5e30 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -12,19 +12,6 @@ #include -std::string getFormat(const char* fmt, ...) { - char buf[2048] = ""; - - va_list args; - va_start(args, fmt); - - vsprintf(buf, fmt , args); - - va_end(args); - - return std::string(buf); -} - std::string monitorsRequest() { std::string result = ""; for (auto& m : g_pCompositor->m_lMonitors) { diff --git a/src/debug/HyprCtl.hpp b/src/debug/HyprCtl.hpp index 1a8851c7..1efe468f 100644 --- a/src/debug/HyprCtl.hpp +++ b/src/debug/HyprCtl.hpp @@ -2,6 +2,7 @@ #include "../Compositor.hpp" #include +#include "../helpers/MiscFunctions.hpp" namespace HyprCtl { void startHyprCtlSocket(); diff --git a/src/defines.hpp b/src/defines.hpp index 004b8121..7eb1b56a 100644 --- a/src/defines.hpp +++ b/src/defines.hpp @@ -31,13 +31,13 @@ #define HYPRATOM(name) {name, 0} #ifndef __INTELLISENSE__ -#define RASSERT(expr, reason) \ +#define RASSERT(expr, reason, ...) \ if (!expr) { \ - Debug::log(CRIT, "\n==========================================================================================\nASSERTION FAILED! \n\n%s\n\nat: line %d in %s", std::string(reason).c_str(), __LINE__, ([]() constexpr->std::string { return std::string(__FILE__).substr(std::string(__FILE__).find_last_of('/') + 1); })().c_str()); \ + Debug::log(CRIT, "\n==========================================================================================\nASSERTION FAILED! \n\n%s\n\nat: line %d in %s", getFormat(reason, ##__VA_ARGS__).c_str(), __LINE__, ([]() constexpr->std::string { return std::string(__FILE__).substr(std::string(__FILE__).find_last_of('/') + 1); })().c_str()); \ RIP("Assertion failed! See the log in /tmp/hypr/hyprland.log for more info."); \ } #else -#define RASSERT(expr, reason) +#define RASSERT(expr, reason, ...) #endif #define ASSERT(expr) RASSERT(expr, "?") \ No newline at end of file diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp index da336106..2bb09941 100644 --- a/src/events/Monitors.cpp +++ b/src/events/Monitors.cpp @@ -108,19 +108,25 @@ void Events::listener_monitorFrame(void* owner, void* data) { timespec now; clock_gettime(CLOCK_MONOTONIC, &now); - const float bgcol[4] = {0.1f, 0.1f, 0.1f, 1.f}; if (!wlr_output_attach_render(PMONITOR->output, nullptr)) return; - wlr_renderer_begin(g_pCompositor->m_sWLRRenderer, PMONITOR->vecSize.x, PMONITOR->vecSize.y); - wlr_renderer_clear(g_pCompositor->m_sWLRRenderer, bgcol); + g_pHyprOpenGL->begin(PMONITOR); + g_pHyprOpenGL->clear(CColor(11, 11, 11, 255)); - g_pHyprRenderer->renderAllClientsForMonitor(PMONITOR->ID, &now); + - wlr_output_render_software_cursors(PMONITOR->output, NULL); + g_pHyprOpenGL->end(); - wlr_renderer_end(g_pCompositor->m_sWLRRenderer); + // wlr_renderer_begin(g_pCompositor->m_sWLRRenderer, PMONITOR->vecSize.x, PMONITOR->vecSize.y); + // wlr_renderer_clear(g_pCompositor->m_sWLRRenderer, bgcol); + + // g_pHyprRenderer->renderAllClientsForMonitor(PMONITOR->ID, &now); + + // wlr_output_render_software_cursors(PMONITOR->output, NULL); + + // wlr_renderer_end(g_pCompositor->m_sWLRRenderer); wlr_output_commit(PMONITOR->output); } diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 9974ab46..ceb457c4 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -42,3 +42,16 @@ void wlr_signal_emit_safe(struct wl_signal *signal, void *data) { wl_list_remove(&cursor.link); wl_list_remove(&end.link); } + +std::string getFormat(const char *fmt, ...) { + char buf[2048] = ""; + + va_list args; + va_start(args, fmt); + + vsprintf(buf, fmt, args); + + va_end(args); + + return std::string(buf); +} \ No newline at end of file diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp index acbd6d25..c71df0b1 100644 --- a/src/helpers/MiscFunctions.hpp +++ b/src/helpers/MiscFunctions.hpp @@ -3,4 +3,5 @@ #include "../includes.hpp" void addWLSignal(wl_signal*, wl_listener*, void* pOwner, std::string ownerString); -void wlr_signal_emit_safe(struct wl_signal *signal, void *data); \ No newline at end of file +void wlr_signal_emit_safe(struct wl_signal *signal, void *data); +std::string getFormat(const char *fmt, ...); // Basically Debug::log to a string \ No newline at end of file diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp new file mode 100644 index 00000000..e4f07512 --- /dev/null +++ b/src/render/OpenGL.cpp @@ -0,0 +1,130 @@ +#include "OpenGL.hpp" +#include "../Compositor.hpp" + +CHyprOpenGLImpl::CHyprOpenGLImpl() { + RASSERT(eglMakeCurrent(g_pCompositor->m_sWLREGL->display, EGL_NO_SURFACE, EGL_NO_SURFACE, g_pCompositor->m_sWLREGL->context), "Couldn't make the EGL current!"); + + auto *const EXTENSIONS = (const char*)glGetString(GL_EXTENSIONS); + + RASSERT(EXTENSIONS, "Couldn't retrieve openGL extensions!"); + + m_iDRMFD = g_pCompositor->m_iDRMFD; + + m_szExtensions = EXTENSIONS; + + Debug::log(LOG, "Creating the Hypr OpenGL Renderer!"); + Debug::log(LOG, "Using: %s", glGetString(GL_VERSION)); + Debug::log(LOG, "Vendor: %s", glGetString(GL_VENDOR)); + Debug::log(LOG, "Renderer: %s", glGetString(GL_RENDERER)); + Debug::log(LOG, "Supported extensions size: %d", std::count(m_szExtensions.begin(), m_szExtensions.end(), ' ')); + + // Init shaders + + GLuint prog = createProgram(QUADVERTSRC, QUADFRAGSRC); + m_qShaderQuad.program = prog; + m_qShaderQuad.proj = glGetUniformLocation(prog, "proj"); + m_qShaderQuad.color = glGetUniformLocation(prog, "color"); + m_qShaderQuad.posAttrib = glGetUniformLocation(prog, "pos"); + + prog = createProgram(TEXVERTSRC, TEXFRAGSRCRGBA); + m_shRGBA.program = prog; + m_shRGBA.proj = glGetUniformLocation(prog, "proj"); + m_shRGBA.tex = glGetUniformLocation(prog, "tex"); + m_shRGBA.alpha = glGetUniformLocation(prog, "alpha"); + m_shRGBA.texAttrib = glGetUniformLocation(prog, "texcoord"); + m_shRGBA.posAttrib = glGetUniformLocation(prog, "pos"); + + prog = createProgram(TEXVERTSRC, TEXFRAGSRCRGBX); + m_shRGBX.program = prog; + m_shRGBX.tex = glGetUniformLocation(prog, "tex"); + m_shRGBX.proj = glGetUniformLocation(prog, "proj"); + m_shRGBX.alpha = glGetUniformLocation(prog, "alpha"); + m_shRGBX.texAttrib = glGetUniformLocation(prog, "texcoord"); + m_shRGBX.posAttrib = glGetUniformLocation(prog, "pos"); + + prog = createProgram(TEXVERTSRC, TEXFRAGSRCEXT); + m_shEXT.program = prog; + m_shEXT.tex = glGetUniformLocation(prog, "tex"); + m_shEXT.proj = glGetUniformLocation(prog, "proj"); + m_shEXT.alpha = glGetUniformLocation(prog, "alpha"); + m_shEXT.posAttrib = glGetUniformLocation(prog, "pos"); + m_shEXT.texAttrib = glGetUniformLocation(prog, "texcoord"); + + Debug::log(LOG, "Shaders initialized successfully."); + + // End shaders + + RASSERT(eglMakeCurrent(g_pCompositor->m_sWLREGL->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT), "Couldn't unset current EGL!"); + + // Done! +} + +GLuint CHyprOpenGLImpl::createProgram(const std::string& vert, const std::string& frag) { + auto vertCompiled = compileShader(GL_VERTEX_SHADER, vert); + RASSERT(vertCompiled, "Compiling shader failed. VERTEX NULL! Shader source:\n\n%s", vert.c_str()); + + auto fragCompiled = compileShader(GL_FRAGMENT_SHADER, frag); + RASSERT(fragCompiled, "Compiling shader failed. FRAGMENT NULL! Shader source:\n\n%s", frag.c_str()); + + auto prog = glCreateProgram(); + glAttachShader(prog, vertCompiled); + glAttachShader(prog, fragCompiled); + glLinkProgram(prog); + + glDetachShader(prog, vertCompiled); + glDetachShader(prog, fragCompiled); + glDeleteShader(vertCompiled); + glDeleteShader(fragCompiled); + + GLint ok; + glGetProgramiv(prog, GL_LINK_STATUS, &ok); + RASSERT(ok != GL_FALSE, "createProgram() failed! GL_LINK_STATUS not OK!"); + + return prog; +} + +GLuint CHyprOpenGLImpl::compileShader(const GLuint& type, std::string src) { + auto shader = glCreateShader(type); + + auto shaderSource = src.c_str(); + + glShaderSource(shader, 1, (const GLchar**)&shaderSource, nullptr); + glCompileShader(shader); + + GLint ok; + glGetShaderiv(shader, GL_COMPILE_STATUS, &ok); + RASSERT(ok != GL_FALSE, "compileShader() failed! GL_COMPILE_STATUS not OK!"); + + return shader; +} + +void CHyprOpenGLImpl::begin(SMonitor* pMonitor) { + m_RenderData.pMonitor = pMonitor; + + glViewport(0, 0, pMonitor->vecSize.x, pMonitor->vecSize.y); + + wlr_matrix_projection(m_RenderData.projection, pMonitor->vecSize.x, pMonitor->vecSize.y, WL_OUTPUT_TRANSFORM_NORMAL); + + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); +} + +void CHyprOpenGLImpl::end() { + m_RenderData.pMonitor = nullptr; +} + +void CHyprOpenGLImpl::clear(const CColor& color) { + RASSERT(m_RenderData.pMonitor, "Tried to render without begin()!"); + + glClearColor(color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f); + glClear(GL_COLOR_BUFFER_BIT); +} + +void CHyprOpenGLImpl::scissor(const wlr_box* pBox) { + if (!pBox) { + glDisable(GL_SCISSOR_TEST); + return; + } + + glScissor(pBox->x, pBox->y, pBox->width, pBox->height); + glEnable(GL_SCISSOR_TEST); +} \ No newline at end of file diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp new file mode 100644 index 00000000..ad6f8d95 --- /dev/null +++ b/src/render/OpenGL.hpp @@ -0,0 +1,48 @@ +#pragma once + +#include "../defines.hpp" +#include "../helpers/Monitor.hpp" +#include "../helpers/Color.hpp" +#include +#include + +#include "Shaders.hpp" +#include "Shader.hpp" + +struct SCurrentRenderData { + SMonitor* pMonitor = nullptr; + float projection[9]; +}; + +class CHyprOpenGLImpl { +public: + + CHyprOpenGLImpl(); + + void begin(SMonitor*); + void end(); + + void clear(const CColor&); + void scissor(const wlr_box*); + + SCurrentRenderData m_RenderData; + +private: + std::list m_lBuffers; + std::list m_lTextures; + + int m_iDRMFD; + std::string m_szExtensions; + + // Shaders + SQuad m_qShaderQuad; + CShader m_shRGBA; + CShader m_shRGBX; + CShader m_shEXT; + // + + GLuint createProgram(const std::string&, const std::string&); + GLuint compileShader(const GLuint&, std::string); +}; + +inline std::unique_ptr g_pHyprOpenGL; \ No newline at end of file diff --git a/src/render/Shader.cpp b/src/render/Shader.cpp new file mode 100644 index 00000000..e69de29b diff --git a/src/render/Shader.hpp b/src/render/Shader.hpp new file mode 100644 index 00000000..630dd32f --- /dev/null +++ b/src/render/Shader.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include "../defines.hpp" + +struct SQuad { + GLuint program; + GLint proj; + GLint color; + GLint posAttrib; +}; + +class CShader { +public: + GLuint program; + GLint proj; + GLint tex; + GLint alpha; + GLint posAttrib; + GLint texAttrib; +}; \ No newline at end of file diff --git a/src/render/Shaders.hpp b/src/render/Shaders.hpp new file mode 100644 index 00000000..a9140aca --- /dev/null +++ b/src/render/Shaders.hpp @@ -0,0 +1,69 @@ +#pragma once + +#include + +inline const std::string QUADVERTSRC = R"#( +uniform mat3 proj; +uniform vec4 color; +attribute vec2 pos; +attribute vec2 texcoord; +varying vec4 v_color; +varying vec2 v_texcoord; + +void main() { + gl_Position = vec4(proj * vec3(pos, 1.0), 1.0); + v_color = color; + v_texcoord = texcoord; +})#"; + +inline const std::string QUADFRAGSRC = R"#( +precision mediump float; +varying vec4 v_color; +varying vec2 v_texcoord; + +void main() { + gl_FragColor = v_color; +})#"; + +inline const std::string TEXVERTSRC = R"#( +uniform mat3 proj; +attribute vec2 pos; +attribute vec2 texcoord; +varying vec2 v_texcoord; + +void main() { + gl_Position = vec4(proj * vec3(pos, 1.0), 1.0); + v_texcoord = texcoord; +})#"; + +inline const std::string TEXFRAGSRCRGBA = R"#( +precision mediump float; +varying vec2 v_texcoord; +uniform sampler2D tex; +uniform float alpha; + +void main() { + gl_FragColor = texture2D(tex, v_texcoord) * alpha; +})#"; + +inline const std::string TEXFRAGSRCRGBX = R"#( +precision mediump float; +varying vec2 v_texcoord; +uniform sampler2D tex; +uniform float alpha; + +void main() { + gl_FragColor = vec4(texture2D(tex, v_texcoord).rgb, 1.0) * alpha; +})#"; + +inline const std::string TEXFRAGSRCEXT = R"#( +#extension GL_OES_EGL_image_external : require + +precision mediump float; +varying vec2 v_texcoord; +uniform samplerExternalOES texture0; +uniform float alpha; + +void main() { + gl_FragColor = texture2D(texture0, v_texcoord) * alpha; +})#";