diff options
author | Vaxry <[email protected]> | 2023-11-24 10:54:21 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2023-11-24 10:54:21 +0000 |
commit | 2ebfd0c7456eff7e9c03d379d1dfbc611dc26672 (patch) | |
tree | 9fa0d65224283e717ef7a06bb60870a5d319e13e | |
parent | e40e486f61f2643578b9977b86f408799dbc75fd (diff) | |
download | Hyprland-2ebfd0c7456eff7e9c03d379d1dfbc611dc26672.tar.gz Hyprland-2ebfd0c7456eff7e9c03d379d1dfbc611dc26672.zip |
renderer: Move to a full Hyprland GL rendering pipeline (#3920)
Also updates wlroots
-rw-r--r-- | .github/workflows/ci.yaml | 2 | ||||
-rwxr-xr-x | CMakeLists.txt | 2 | ||||
-rw-r--r-- | flake.lock | 8 | ||||
-rw-r--r-- | flake.nix | 2 | ||||
-rw-r--r-- | src/Compositor.cpp | 5 | ||||
-rw-r--r-- | src/Compositor.hpp | 4 | ||||
-rw-r--r-- | src/debug/TracyDefines.hpp | 9 | ||||
-rw-r--r-- | src/events/Events.hpp | 6 | ||||
-rw-r--r-- | src/events/Misc.cpp | 14 | ||||
-rw-r--r-- | src/events/Windows.cpp | 2 | ||||
-rw-r--r-- | src/helpers/Monitor.cpp | 9 | ||||
-rw-r--r-- | src/helpers/Monitor.hpp | 54 | ||||
-rw-r--r-- | src/helpers/Region.cpp | 9 | ||||
-rw-r--r-- | src/helpers/Region.hpp | 2 | ||||
-rw-r--r-- | src/includes.hpp | 4 | ||||
-rw-r--r-- | src/managers/XWaylandManager.cpp | 10 | ||||
-rw-r--r-- | src/protocols/Screencopy.cpp | 24 | ||||
-rw-r--r-- | src/protocols/ToplevelExport.cpp | 62 | ||||
-rw-r--r-- | src/render/Framebuffer.cpp | 15 | ||||
-rw-r--r-- | src/render/Framebuffer.hpp | 1 | ||||
-rw-r--r-- | src/render/OpenGL.cpp | 109 | ||||
-rw-r--r-- | src/render/OpenGL.hpp | 22 | ||||
-rw-r--r-- | src/render/Renderbuffer.cpp | 81 | ||||
-rw-r--r-- | src/render/Renderbuffer.hpp | 25 | ||||
-rw-r--r-- | src/render/Renderer.cpp | 163 | ||||
-rw-r--r-- | src/render/Renderer.hpp | 47 | ||||
m--------- | subprojects/wlroots | 0 | ||||
-rw-r--r-- | subprojects/wlroots.wrap | 2 |
28 files changed, 458 insertions, 235 deletions
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index b8093491..a78b7522 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -40,7 +40,7 @@ jobs: cp ./LICENSE hyprland/ cp build/Hyprland hyprland/ cp build/hyprctl/hyprctl hyprland/ - cp subprojects/wlroots/build/libwlroots.so.12032 hyprland/ + cp subprojects/wlroots/build/libwlroots.so.13032 hyprland/ cp build/Hyprland hyprland/ cp -r example/ hyprland/ cp -r assets/ hyprland/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 3bdbb0da..95d5a297 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,7 +57,7 @@ ExternalProject_Add( wlroots PREFIX ${CMAKE_SOURCE_DIR}/subprojects/wlroots SOURCE_DIR ${CMAKE_SOURCE_DIR}/subprojects/wlroots - PATCH_COMMAND sed -E -i -e "s/(soversion = 12)([^032]|$$)/soversion = 12032/g" meson.build + PATCH_COMMAND sed -E -i -e "s/(soversion = 13)([^032]|$$)/soversion = 13032/g" meson.build CONFIGURE_COMMAND meson setup build --buildtype=${BUILDTYPE_LOWER} -Dwerror=false -Dexamples=false -Drenderers=gles2 $<IF:$<BOOL:${WITH_ASAN}>,-Db_sanitize=address,-Db_sanitize=none> && meson setup build --buildtype=${BUILDTYPE_LOWER} -Dwerror=false -Dexamples=false -Drenderers=gles2 $<IF:$<BOOL:${WITH_ASAN}>,-Db_sanitize=address,-Db_sanitize=none> --reconfigure BUILD_COMMAND ninja -C build BUILD_ALWAYS true @@ -67,18 +67,18 @@ "flake": false, "locked": { "host": "gitlab.freedesktop.org", - "lastModified": 1699292815, - "narHash": "sha256-HXu98PyBMKEWLqiTb8viuLDznud/SdkdJsx5A5CWx7I=", + "lastModified": 1700736101, + "narHash": "sha256-1Fh1xf/JX5zFbGIF9LDaffaleG6JDwwwnKby0LyiXEA=", "owner": "wlroots", "repo": "wlroots", - "rev": "5de9e1a99d6642c2d09d589aa37ff0a8945dcee1", + "rev": "f1762f428b0ef2989c81f57ea9e810403d34d946", "type": "gitlab" }, "original": { "host": "gitlab.freedesktop.org", "owner": "wlroots", "repo": "wlroots", - "rev": "5de9e1a99d6642c2d09d589aa37ff0a8945dcee1", + "rev": "f1762f428b0ef2989c81f57ea9e810403d34d946", "type": "gitlab" } }, @@ -12,7 +12,7 @@ host = "gitlab.freedesktop.org"; owner = "wlroots"; repo = "wlroots"; - rev = "5de9e1a99d6642c2d09d589aa37ff0a8945dcee1"; + rev = "f1762f428b0ef2989c81f57ea9e810403d34d946"; flake = false; }; diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 1b27a0f4..42b620fe 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -225,7 +225,6 @@ void CCompositor::initServer() { m_sWLROutputMgr = wlr_output_manager_v1_create(m_sWLDisplay); - m_sWLRInhibitMgr = wlr_input_inhibit_manager_create(m_sWLDisplay); m_sWLRKbShInhibitMgr = wlr_keyboard_shortcuts_inhibit_v1_create(m_sWLDisplay); m_sWLRPointerConstraints = wlr_pointer_constraints_v1_create(m_sWLDisplay); @@ -283,7 +282,7 @@ void CCompositor::initServer() { void CCompositor::initAllSignals() { addWLSignal(&m_sWLRBackend->events.new_output, &Events::listen_newOutput, m_sWLRBackend, "Backend"); - addWLSignal(&m_sWLRXDGShell->events.new_surface, &Events::listen_newXDGSurface, m_sWLRXDGShell, "XDG Shell"); + addWLSignal(&m_sWLRXDGShell->events.new_surface, &Events::listen_newXDGToplevel, m_sWLRXDGShell, "XDG Shell"); addWLSignal(&m_sWLRCursor->events.motion, &Events::listen_mouseMove, m_sWLRCursor, "WLRCursor"); addWLSignal(&m_sWLRCursor->events.motion_absolute, &Events::listen_mouseMoveAbsolute, m_sWLRCursor, "WLRCursor"); addWLSignal(&m_sWLRCursor->events.button, &Events::listen_mouseButton, m_sWLRCursor, "WLRCursor"); @@ -312,8 +311,6 @@ void CCompositor::initAllSignals() { addWLSignal(&m_sWLROutputLayout->events.change, &Events::listen_change, m_sWLROutputLayout, "OutputLayout"); addWLSignal(&m_sWLROutputMgr->events.apply, &Events::listen_outputMgrApply, m_sWLROutputMgr, "OutputMgr"); addWLSignal(&m_sWLROutputMgr->events.test, &Events::listen_outputMgrTest, m_sWLROutputMgr, "OutputMgr"); - addWLSignal(&m_sWLRInhibitMgr->events.activate, &Events::listen_InhibitActivate, m_sWLRInhibitMgr, "InhibitMgr"); - addWLSignal(&m_sWLRInhibitMgr->events.deactivate, &Events::listen_InhibitDeactivate, m_sWLRInhibitMgr, "InhibitMgr"); addWLSignal(&m_sWLRPointerConstraints->events.new_constraint, &Events::listen_newConstraint, m_sWLRPointerConstraints, "PointerConstraints"); addWLSignal(&m_sWLRXDGDecoMgr->events.new_toplevel_decoration, &Events::listen_NewXDGDeco, m_sWLRXDGDecoMgr, "XDGDecoMgr"); addWLSignal(&m_sWLRVirtPtrMgr->events.new_virtual_pointer, &Events::listen_newVirtPtr, m_sWLRVirtPtrMgr, "VirtPtrMgr"); diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 829b7e79..d39725aa 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -29,7 +29,8 @@ #include "plugins/PluginSystem.hpp" #include "helpers/Watchdog.hpp" -enum eManagersInitStage { +enum eManagersInitStage +{ STAGE_PRIORITY = 0, STAGE_LATE }; @@ -61,7 +62,6 @@ class CCompositor { wlr_virtual_keyboard_manager_v1* m_sWLRVKeyboardMgr; wlr_output_manager_v1* m_sWLROutputMgr; wlr_presentation* m_sWLRPresentation; - 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/TracyDefines.hpp b/src/debug/TracyDefines.hpp index 767b1a20..49d296f6 100644 --- a/src/debug/TracyDefines.hpp +++ b/src/debug/TracyDefines.hpp @@ -13,15 +13,6 @@ inline PFNGLGETQUERYOBJECTUI64VEXTPROC glGetQueryObjectui64v; #include "../../subprojects/tracy/public/tracy/TracyOpenGL.hpp" -inline void loadGLProc(void* pProc, const char* name) { - void* proc = (void*)eglGetProcAddress(name); - if (proc == NULL) { - Debug::log(CRIT, "[Tracy GPU Profiling] eglGetProcAddress({}) failed", name); - abort(); - } - *(void**)pProc = proc; -} - #define TRACY_GPU_CONTEXT TracyGpuContext #define TRACY_GPU_ZONE(e) TracyGpuZone(e) #define TRACY_GPU_COLLECT TracyGpuCollect diff --git a/src/events/Events.hpp b/src/events/Events.hpp index 371586cc..777bdf9f 100644 --- a/src/events/Events.hpp +++ b/src/events/Events.hpp @@ -42,7 +42,7 @@ namespace Events { DYNLISTENFUNC(repositionPopupXDG); // Surface XDG (window) - LISTENER(newXDGSurface); + LISTENER(newXDGToplevel); LISTENER(activateXDG); // Window events @@ -121,10 +121,6 @@ namespace Events { DYNLISTENFUNC(destroyDragIcon); DYNLISTENFUNC(commitDragIcon); - // Inhibit - LISTENER(InhibitActivate); - LISTENER(InhibitDeactivate); - // Deco XDG LISTENER(NewXDGDeco); diff --git a/src/events/Misc.cpp b/src/events/Misc.cpp index 1df4be3a..91a0ebda 100644 --- a/src/events/Misc.cpp +++ b/src/events/Misc.cpp @@ -156,20 +156,6 @@ void Events::listener_commitDragIcon(void* owner, void* data) { Debug::log(LOG, "Drag icon committed."); } -void Events::listener_InhibitActivate(wl_listener* listener, void* data) { - Debug::log(LOG, "Activated exclusive for {:x}.", (uintptr_t)g_pCompositor->m_sSeat.exclusiveClient); - - g_pInputManager->refocus(); - g_pCompositor->m_sSeat.exclusiveClient = g_pCompositor->m_sWLRInhibitMgr->active_client; -} - -void Events::listener_InhibitDeactivate(wl_listener* listener, void* data) { - Debug::log(LOG, "Deactivated exclusive."); - - g_pCompositor->m_sSeat.exclusiveClient = nullptr; - g_pInputManager->refocus(); -} - void Events::listener_RendererDestroy(wl_listener* listener, void* data) { Debug::log(LOG, "!!Renderer destroyed!!"); } diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 39678154..556ec1b5 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -1169,7 +1169,7 @@ void Events::listener_surfaceXWayland(wl_listener* listener, void* data) { PNEWWINDOW->hyprListener_configureX11.initCallback(&XWSURFACE->events.request_configure, &Events::listener_configureX11, PNEWWINDOW, "XWayland Window"); } -void Events::listener_newXDGSurface(wl_listener* listener, void* data) { +void Events::listener_newXDGToplevel(wl_listener* listener, void* data) { // A window got opened const auto XDGSURFACE = (wlr_xdg_surface*)data; diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 20880d8d..833a7a5a 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -643,3 +643,12 @@ void CMonitor::moveTo(const Vector2D& pos) { Vector2D CMonitor::middle() { return vecPosition + vecSize / 2.f; } + +void CMonitor::updateMatrix() { + wlr_matrix_identity(projMatrix.data()); + if (transform != WL_OUTPUT_TRANSFORM_NORMAL) { + wlr_matrix_translate(projMatrix.data(), vecTransformedSize.x / 2.0, vecTransformedSize.y / 2.0); + wlr_matrix_transform(projMatrix.data(), transform); + wlr_matrix_translate(projMatrix.data(), -vecTransformedSize.x / 2.0, -vecTransformedSize.y / 2.0); + } +}
\ No newline at end of file diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 2aa7e7eb..f354ca6d 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -50,32 +50,33 @@ class CMonitor { drmModeModeInfo customDrmMode = {}; // WLR stuff - wlr_damage_ring damage; - wlr_output* output = nullptr; - float refreshRate = 60; - int framesToSkip = 0; - int forceFullFrames = 0; - bool noFrameSchedule = false; - bool scheduledRecalc = false; - wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; - bool gammaChanged = false; - float xwaylandScale = 1.f; - - bool dpmsStatus = true; - bool vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it. - bool enabled10bit = false; // as above, this can be TRUE even if 10 bit failed. - bool createdByUser = false; - uint32_t drmFormat = DRM_FORMAT_INVALID; - bool isUnsafeFallback = false; - - bool pendingFrame = false; // if we schedule a frame during rendering, reschedule it after - bool renderingActive = false; - - wl_event_source* renderTimer = nullptr; // for RAT - bool RATScheduled = false; - CTimer lastPresentationTimer; - - SMonitorRule activeMonitorRule; + wlr_damage_ring damage; + wlr_output* output = nullptr; + float refreshRate = 60; + int framesToSkip = 0; + int forceFullFrames = 0; + bool noFrameSchedule = false; + bool scheduledRecalc = false; + wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; + bool gammaChanged = false; + float xwaylandScale = 1.f; + std::array<float, 9> projMatrix = {0}; + + bool dpmsStatus = true; + bool vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it. + bool enabled10bit = false; // as above, this can be TRUE even if 10 bit failed. + bool createdByUser = false; + uint32_t drmFormat = DRM_FORMAT_INVALID; + bool isUnsafeFallback = false; + + bool pendingFrame = false; // if we schedule a frame during rendering, reschedule it after + bool renderingActive = false; + + wl_event_source* renderTimer = nullptr; // for RAT + bool RATScheduled = false; + CTimer lastPresentationTimer; + + SMonitorRule activeMonitorRule; // mirroring CMonitor* pMirrorOf = nullptr; @@ -123,6 +124,7 @@ class CMonitor { void setSpecialWorkspace(const int& id); void moveTo(const Vector2D& pos); Vector2D middle(); + void updateMatrix(); bool m_bEnabled = false; bool m_bRenderingInitPassed = false; diff --git a/src/helpers/Region.cpp b/src/helpers/Region.cpp index 06b8536c..df7de442 100644 --- a/src/helpers/Region.cpp +++ b/src/helpers/Region.cpp @@ -93,6 +93,15 @@ CRegion& CRegion::translate(const Vector2D& vec) { return *this; } +CRegion& CRegion::transform(const wl_output_transform t, double w, double h) { + wlr_region_transform(&m_rRegion, &m_rRegion, t, w, h); + return *this; +} + +CRegion CRegion::copy() const { + return CRegion(*this); +} + CRegion& CRegion::scale(float scale) { wlr_region_scale(&m_rRegion, &m_rRegion, scale); return *this; diff --git a/src/helpers/Region.hpp b/src/helpers/Region.hpp index 1c6923df..7554aa58 100644 --- a/src/helpers/Region.hpp +++ b/src/helpers/Region.hpp @@ -45,12 +45,14 @@ class CRegion { CRegion& intersect(const CRegion& other); CRegion& intersect(double x, double y, double w, double h); CRegion& translate(const Vector2D& vec); + CRegion& transform(const wl_output_transform t, double w, double h); CRegion& invert(pixman_box32_t* box); CRegion& scale(float scale); CBox getExtents(); bool containsPoint(const Vector2D& vec) const; bool empty() const; Vector2D closestPoint(const Vector2D& vec) const; + CRegion copy() const; std::vector<pixman_box32_t> getRects() const; diff --git a/src/includes.hpp b/src/includes.hpp index a89f0950..611e4a5c 100644 --- a/src/includes.hpp +++ b/src/includes.hpp @@ -70,7 +70,6 @@ extern "C" { #include <wlr/types/wlr_xdg_shell.h> #include <wlr/types/wlr_subcompositor.h> #include <wlr/types/wlr_damage_ring.h> -#include <wlr/types/wlr_input_inhibitor.h> #include <wlr/types/wlr_keyboard_shortcuts_inhibit_v1.h> #include <wlr/types/wlr_virtual_pointer_v1.h> #include <wlr/types/wlr_foreign_toplevel_management_v1.h> @@ -106,6 +105,9 @@ extern "C" { #include <wlr/types/wlr_cursor_shape_v1.h> #include <wlr/types/wlr_tearing_control_v1.h> #include <wlr/util/box.h> +#include <wlr/util/transform.h> +#include <wlr/render/swapchain.h> +#include <wlr/render/egl.h> #include <libdrm/drm_fourcc.h> diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index f13b2cd2..2883f205 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -45,10 +45,11 @@ void CHyprXWaylandManager::activateSurface(wlr_surface* pSurface, bool activate) wlr_xdg_toplevel_set_activated(PSURF->toplevel, activate); } else if (wlr_xwayland_surface_try_from_wlr_surface(pSurface)) { - wlr_xwayland_surface_activate(wlr_xwayland_surface_try_from_wlr_surface(pSurface), activate); + const auto XSURF = wlr_xwayland_surface_try_from_wlr_surface(pSurface); + wlr_xwayland_surface_activate(XSURF, activate); - if (activate) - wlr_xwayland_surface_restack(wlr_xwayland_surface_try_from_wlr_surface(pSurface), nullptr, XCB_STACK_MODE_ABOVE); + if (activate && !XSURF->override_redirect) + wlr_xwayland_surface_restack(XSURF, nullptr, XCB_STACK_MODE_ABOVE); } } @@ -58,7 +59,8 @@ void CHyprXWaylandManager::activateWindow(CWindow* pWindow, bool activate) { if (activate) { wlr_xwayland_surface_set_minimized(pWindow->m_uSurface.xwayland, false); - wlr_xwayland_surface_restack(pWindow->m_uSurface.xwayland, nullptr, XCB_STACK_MODE_ABOVE); + if (!pWindow->m_uSurface.xwayland->override_redirect) + wlr_xwayland_surface_restack(pWindow->m_uSurface.xwayland, nullptr, XCB_STACK_MODE_ABOVE); } wlr_xwayland_surface_activate(pWindow->m_uSurface.xwayland, activate); diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 12170595..cff84fc5 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -448,25 +448,19 @@ bool CScreencopyProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame) { if (!sourceTex) return false; - float glMatrix[9]; - wlr_matrix_identity(glMatrix); - wlr_matrix_translate(glMatrix, -frame->box.x, -frame->box.y); - wlr_matrix_scale(glMatrix, frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y); - - if (!wlr_renderer_begin_with_buffer(g_pCompositor->m_sWLRRenderer, frame->buffer)) { - Debug::log(ERR, "[sc] dmabuf: Client requested a copy to a buffer that failed to pass wlr_renderer_begin_with_buffer"); - wlr_texture_destroy(sourceTex); + CRegion fakeDamage = {0, 0, frame->box.width, frame->box.height}; + + if (!g_pHyprRenderer->beginRender(frame->pMonitor, fakeDamage, RENDER_MODE_TO_BUFFER, frame->buffer)) return false; - } - float color[] = {0, 0, 0, 0}; - wlr_renderer_clear(g_pCompositor->m_sWLRRenderer, color); - // TODO: use hl render methods to use damage - wlr_render_texture_with_matrix(g_pCompositor->m_sWLRRenderer, sourceTex, glMatrix, 1.0f); + CBox monbox = CBox{0, 0, frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y}.translate({-frame->box.x, -frame->box.y}); + g_pHyprOpenGL->setMonitorTransformEnabled(false); + g_pHyprOpenGL->renderTexture(sourceTex, &monbox, 1); + g_pHyprOpenGL->setMonitorTransformEnabled(true); - wlr_texture_destroy(sourceTex); + g_pHyprRenderer->endRender(); - wlr_renderer_end(g_pCompositor->m_sWLRRenderer); + wlr_texture_destroy(sourceTex); return true; } diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index 3f442781..db602396 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -134,7 +134,8 @@ void CToplevelExportProtocolManager::removeFrame(SScreencopyFrame* frame, bool f std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return other == frame; }); wl_resource_set_user_data(frame->resource, nullptr); - wlr_buffer_unlock(frame->buffer); + if (frame->buffer && frame->buffer->n_locks > 0) + wlr_buffer_unlock(frame->buffer); removeClient(frame->client, force); m_lFrames.remove(*frame); } @@ -362,18 +363,14 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times const auto PMONITOR = g_pCompositor->getMonitorFromID(frame->pWindow->m_iMonitorID); CRegion fakeDamage{0, 0, PMONITOR->vecPixelSize.x * 10, PMONITOR->vecPixelSize.y * 10}; - if (frame->overlayCursor) - wlr_output_lock_software_cursors(PMONITOR->output, true); - - if (!wlr_output_attach_render(PMONITOR->output, nullptr)) { - Debug::log(ERR, "[toplevel_export] Couldn't attach render"); + if (!g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE)) { wlr_buffer_end_data_ptr_access(frame->buffer); - if (frame->overlayCursor) - wlr_output_lock_software_cursors(PMONITOR->output, false); return false; } - g_pHyprOpenGL->begin(PMONITOR, &fakeDamage, true); + if (frame->overlayCursor) + wlr_output_lock_software_cursors(PMONITOR->output, true); + g_pHyprOpenGL->clear(CColor(0, 0, 0, 1.0)); // render client at 0,0 @@ -381,46 +378,25 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times g_pHyprRenderer->renderWindow(frame->pWindow, PMONITOR, now, false, RENDER_PASS_ALL, true, true); g_pHyprRenderer->m_bBlockSurfaceFeedback = false; - if (frame->overlayCursor && wlr_renderer_begin(g_pCompositor->m_sWLRRenderer, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y)) { - // hack le massive - wlr_output_cursor* cursor; - const auto OFFSET = frame->pWindow->m_vRealPosition.vec() - PMONITOR->vecPosition; - wl_list_for_each(cursor, &PMONITOR->output->cursors, link) { - if (!cursor->enabled || !cursor->visible || PMONITOR->output->hardware_cursor == cursor) { - continue; - } - cursor->x -= OFFSET.x; - cursor->y -= OFFSET.y; - } - wlr_output_render_software_cursors(PMONITOR->output, NULL); - wl_list_for_each(cursor, &PMONITOR->output->cursors, link) { - if (!cursor->enabled || !cursor->visible || PMONITOR->output->hardware_cursor == cursor) { - continue; - } - cursor->x += OFFSET.x; - cursor->y += OFFSET.y; - } - wlr_renderer_end(g_pCompositor->m_sWLRRenderer); - } + if (frame->overlayCursor) + g_pHyprRenderer->renderSoftwareCursors(PMONITOR, fakeDamage, g_pInputManager->getMouseCoordsInternal() - frame->pWindow->m_vRealPosition.vec()); // copy pixels const auto PFORMAT = gles2FromDRM(format); if (!PFORMAT) { Debug::log(ERR, "[toplevel_export] Cannot read pixels, unsupported format {:x}", (uintptr_t)PFORMAT); - g_pHyprOpenGL->end(); + g_pHyprRenderer->endRender(); wlr_buffer_end_data_ptr_access(frame->buffer); if (frame->overlayCursor) wlr_output_lock_software_cursors(PMONITOR->output, false); return false; } - glBindFramebuffer(GL_FRAMEBUFFER, g_pHyprOpenGL->m_RenderData.pCurrentMonData->primaryFB.m_iFb); + g_pHyprOpenGL->m_RenderData.mainFB->bind(); glReadPixels(0, 0, frame->box.width, frame->box.height, PFORMAT->gl_format, PFORMAT->gl_type, data); - g_pHyprOpenGL->end(); - - wlr_output_rollback(PMONITOR->output); + g_pHyprRenderer->endRender(); wlr_buffer_end_data_ptr_access(frame->buffer); @@ -431,14 +407,12 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times } bool CToplevelExportProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame, timespec* now) { - if (!wlr_renderer_begin_with_buffer(g_pCompositor->m_sWLRRenderer, frame->buffer)) - return false; - const auto PMONITOR = g_pCompositor->getMonitorFromID(frame->pWindow->m_iMonitorID); CRegion fakeDamage{0, 0, INT16_MAX, INT16_MAX}; - g_pHyprOpenGL->begin(PMONITOR, &fakeDamage, true); + if (!g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_TO_BUFFER, frame->buffer)) + return false; g_pHyprOpenGL->clear(CColor(0, 0, 0, 1.0)); @@ -446,14 +420,10 @@ bool CToplevelExportProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame, ti g_pHyprRenderer->renderWindow(frame->pWindow, PMONITOR, now, false, RENDER_PASS_ALL, true, true); g_pHyprRenderer->m_bBlockSurfaceFeedback = false; - g_pHyprOpenGL->bindWlrOutputFb(); - - CBox monbox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y}; - g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_RenderData.pCurrentMonData->primaryFB.m_cTex, &monbox, 1.f); - - g_pHyprOpenGL->end(); + if (frame->overlayCursor) + g_pHyprRenderer->renderSoftwareCursors(PMONITOR, fakeDamage, g_pInputManager->getMouseCoordsInternal() - frame->pWindow->m_vRealPosition.vec()); - wlr_renderer_end(g_pCompositor->m_sWLRRenderer); + g_pHyprRenderer->endRender(); return true; } diff --git a/src/render/Framebuffer.cpp b/src/render/Framebuffer.cpp index 1ebbc585..94b3f64a 100644 --- a/src/render/Framebuffer.cpp +++ b/src/render/Framebuffer.cpp @@ -62,6 +62,21 @@ bool CFramebuffer::alloc(int w, int h, uint32_t drmFormat) { return true; } +void CFramebuffer::addStencil() { + glBindTexture(GL_TEXTURE_2D, m_pStencilTex->m_iTexID); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, m_vSize.x, m_vSize.y, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 0); + + glBindFramebuffer(GL_FRAMEBUFFER, m_iFb); + + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_pStencilTex->m_iTexID, 0); + + auto status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + RASSERT((status == GL_FRAMEBUFFER_COMPLETE), "Failed adding a stencil to fbo!", status); + + glBindTexture(GL_TEXTURE_2D, 0); + glBindFramebuffer(GL_FRAMEBUFFER, g_pHyprOpenGL->m_iCurrentOutputFb); +} + void CFramebuffer::bind() { #ifndef GLES2 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_iFb); diff --git a/src/render/Framebuffer.hpp b/src/render/Framebuffer.hpp index 73b70431..22809158 100644 --- a/src/render/Framebuffer.hpp +++ b/src/render/Framebuffer.hpp @@ -8,6 +8,7 @@ class CFramebuffer { ~CFramebuffer(); bool alloc(int w, int h, uint32_t format = GL_RGBA); + void addStencil(); void bind(); void release(); void reset(); diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 7cfe2c53..119d522b 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -5,6 +5,15 @@ #include "Shaders.hpp" #include <random> +inline void loadGLProc(void* pProc, const char* name) { + void* proc = (void*)eglGetProcAddress(name); + if (proc == NULL) { + Debug::log(CRIT, "[Tracy GPU Profiling] eglGetProcAddress({}) failed", name); + abort(); + } + *(void**)pProc = proc; +} + CHyprOpenGLImpl::CHyprOpenGLImpl() { RASSERT(eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, wlr_egl_get_context(g_pCompositor->m_sWLREGL)), "Couldn't unset current EGL!"); @@ -23,6 +32,9 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() { Debug::log(LOG, "Renderer: {}", (char*)glGetString(GL_RENDERER)); Debug::log(LOG, "Supported extensions size: {}", std::count(m_szExtensions.begin(), m_szExtensions.end(), ' ')); + loadGLProc(&m_sProc.glEGLImageTargetRenderbufferStorageOES, "glEGLImageTargetRenderbufferStorageOES"); + loadGLProc(&m_sProc.eglDestroyImageKHR, "eglDestroyImageKHR"); + #ifdef USE_TRACY_GPU loadGLProc(&glQueryCounter, "glQueryCounterEXT"); @@ -106,11 +118,9 @@ GLuint CHyprOpenGLImpl::compileShader(const GLuint& type, std::string src, bool void CHyprOpenGLImpl::begin(CMonitor* pMonitor, CRegion* pDamage, bool fake) { m_RenderData.pMonitor = pMonitor; - TRACY_GPU_ZONE("RenderBegin"); + static auto* const PBLUR = &g_pConfigManager->getConfigValuePtr("decoration:blur:enabled")->intValue; - if (eglGetCurrentContext() != wlr_egl_get_context(g_pCompositor->m_sWLREGL)) { - eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, wlr_egl_get_context(g_pCompositor->m_sWLREGL)); - } + TRACY_GPU_ZONE("RenderBegin"); glViewport(0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y); @@ -118,19 +128,16 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, CRegion* pDamage, bool fake) { m_RenderData.pCurrentMonData = &m_mMonitorRenderResources[pMonitor]; - glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_iCurrentOutputFb); - m_iWLROutputFb = m_iCurrentOutputFb; - // ensure a framebuffer for the monitor exists - if (!m_mMonitorRenderResources.contains(pMonitor) || m_RenderData.pCurrentMonData->primaryFB.m_vSize != pMonitor->vecPixelSize) { + if (!m_mMonitorRenderResources.contains(pMonitor) || m_RenderData.pCurrentMonData->offloadFB.m_vSize != pMonitor->vecPixelSize) { m_RenderData.pCurrentMonData->stencilTex.allocate(); - m_RenderData.pCurrentMonData->primaryFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex; + m_RenderData.pCurrentMonData->offloadFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex; m_RenderData.pCurrentMonData->mirrorFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex; m_RenderData.pCurrentMonData->mirrorSwapFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex; m_RenderData.pCurrentMonData->offMainFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex; - m_RenderData.pCurrentMonData->primaryFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat); + m_RenderData.pCurrentMonData->offloadFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat); m_RenderData.pCurrentMonData->mirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat); m_RenderData.pCurrentMonData->mirrorSwapFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat); m_RenderData.pCurrentMonData->offMainFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat); @@ -144,19 +151,37 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, CRegion* pDamage, bool fake) { if (!m_RenderData.pCurrentMonData->m_bShadersInitialized) initShaders(); - // bind the primary Hypr Framebuffer - m_RenderData.pCurrentMonData->primaryFB.bind(); - m_RenderData.damage.set(*pDamage); m_bFakeFrame = fake; - m_RenderData.currentFB = &m_RenderData.pCurrentMonData->primaryFB; - if (m_bReloadScreenShader) { m_bReloadScreenShader = false; applyScreenShader(g_pConfigManager->getString("decoration:screen_shader")); } + + const auto PRBO = g_pHyprRenderer->getCurrentRBO(); + + if (m_sFinalScreenShader.program > 0 || m_bFakeFrame || m_RenderData.mouseZoomFactor != 1.0 || pMonitor->vecPixelSize != PRBO->getFB()->m_vSize || + (*PBLUR != 0 && !pMonitor->solitaryClient /* TODO: revisit when possible */)) { + // we have to offload + // bind the primary Hypr Framebuffer + m_RenderData.pCurrentMonData->offloadFB.bind(); + m_RenderData.currentFB = &m_RenderData.pCurrentMonData->offloadFB; + m_bOffloadedFramebuffer = true; + } else { + // we can render to the rbo directly + const auto PFBO = PRBO->getFB(); + m_RenderData.currentFB = PFBO; + if (PFBO->m_pStencilTex != &m_RenderData.pCurrentMonData->stencilTex) { + PFBO->m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex; + PFBO->addStencil(); + } + PRBO->bindFB(); + m_bOffloadedFramebuffer = false; + } + + m_RenderData.mainFB = m_RenderData.currentFB; } void CHyprOpenGLImpl::end() { @@ -164,14 +189,15 @@ void CHyprOpenGLImpl::end() { TRACY_GPU_ZONE("RenderEnd"); + if (!m_RenderData.pMonitor->mirrors.empty()) + saveBufferForMirror(); // save with original damage region + // end the render, copy the data to the WLR framebuffer - if (!m_bFakeFrame) { + if (m_bOffloadedFramebuffer && !m_bFakeFrame) { m_RenderData.damage = m_RenderData.pMonitor->lastFrameDamage; - if (!m_RenderData.pMonitor->mirrors.empty()) - saveBufferForMirror(); // save with original damage region + g_pHyprRenderer->getCurrentRBO()->bindFB(); - glBindFramebuffer(GL_FRAMEBUFFER, m_iWLROutputFb); CBox monbox = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; if (m_RenderData.mouseZoomFactor != 1.f) { @@ -199,9 +225,9 @@ void CHyprOpenGLImpl::end() { blend(false); if (m_sFinalScreenShader.program < 1) - renderTexturePrimitive(m_RenderData.pCurrentMonData->primaryFB.m_cTex, &monbox); + renderTexturePrimitive(m_RenderData.pCurrentMonData->offloadFB.m_cTex, &monbox); else - renderTexture(m_RenderData.pCurrentMonData->primaryFB.m_cTex, &monbox, 1.f); + renderTexture(m_RenderData.pCurrentMonData->offloadFB.m_cTex, &monbox, 1.f); blend(true); @@ -212,15 +238,10 @@ void CHyprOpenGLImpl::end() { // reset our data m_RenderData.pMonitor = nullptr; - m_iWLROutputFb = 0; m_RenderData.mouseZoomFactor = 1.f; m_RenderData.mouseZoomUseMouse = true; } -void CHyprOpenGLImpl::bindWlrOutputFb() { - glBindFramebuffer(GL_FRAMEBUFFER, m_iWLROutputFb); -} - void CHyprOpenGLImpl::initShaders() { GLuint prog = createProgram(QUADVERTSRC, QUADFRAGSRC); m_RenderData.pCurrentMonData->m_shQUAD.program = prog; @@ -501,8 +522,7 @@ void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CColor& col, int round CFramebuffer* POUTFB = blurMainFramebufferWithDamage(blurA, &damage); - // bind primary - m_RenderData.pCurrentMonData->primaryFB.bind(); + m_RenderData.currentFB->bind(); // make a stencil for rounded corners to work with blur scissor((CBox*)nullptr); // allow the entire window and stencil to render @@ -553,7 +573,7 @@ void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CColor& col, CRegion float matrix[9]; wlr_matrix_project_box(matrix, box->pWlr(), wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), 0, - m_RenderData.pMonitor->output->transform_matrix); // TODO: write own, don't use WLR here + m_RenderData.pMonitor->projMatrix.data()); // TODO: write own, don't use WLR here float glMatrix[9]; wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); @@ -640,7 +660,7 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, CBox* // get transform const auto TRANSFORM = wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform); float matrix[9]; - wlr_matrix_project_box(matrix, newBox.pWlr(), TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix); + wlr_matrix_project_box(matrix, newBox.pWlr(), TRANSFORM, 0, m_RenderData.pMonitor->projMatrix.data()); float glMatrix[9]; wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); @@ -801,7 +821,7 @@ void CHyprOpenGLImpl::renderTexturePrimitive(const CTexture& tex, CBox* pBox) { // get transform const auto TRANSFORM = wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform); float matrix[9]; - wlr_matrix_project_box(matrix, newBox.pWlr(), TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix); + wlr_matrix_project_box(matrix, newBox.pWlr(), TRANSFORM, 0, m_RenderData.pMonitor->projMatrix.data()); float glMatrix[9]; wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); @@ -855,7 +875,7 @@ void CHyprOpenGLImpl::renderTextureMatte(const CTexture& tex, CBox* pBox, CFrame // get transform const auto TRANSFORM = wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform); float matrix[9]; - wlr_matrix_project_box(matrix, newBox.pWlr(), TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix); + wlr_matrix_project_box(matrix, newBox.pWlr(), TRANSFORM, 0, m_RenderData.pMonitor->projMatrix.data()); float glMatrix[9]; wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); @@ -914,7 +934,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o const auto TRANSFORM = wlr_output_transform_invert(m_RenderData.pMonitor->transform); float matrix[9]; CBox MONITORBOX = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; - wlr_matrix_project_box(matrix, MONITORBOX.pWlr(), TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix); + wlr_matrix_project_box(matrix, MONITORBOX.pWlr(), TRANSFORM, 0, m_RenderData.pMonitor->projMatrix.data()); float glMatrix[9]; wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); @@ -947,9 +967,9 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o glActiveTexture(GL_TEXTURE0); - glBindTexture(m_RenderData.pCurrentMonData->primaryFB.m_cTex.m_iTarget, m_RenderData.pCurrentMonData->primaryFB.m_cTex.m_iTexID); + glBindTexture(m_RenderData.currentFB->m_cTex.m_iTarget, m_RenderData.currentFB->m_cTex.m_iTexID); - glTexParameteri(m_RenderData.pCurrentMonData->primaryFB.m_cTex.m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(m_RenderData.currentFB->m_cTex.m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glUseProgram(m_RenderData.pCurrentMonData->m_shBLURPREPARE.program); @@ -1225,7 +1245,7 @@ void CHyprOpenGLImpl::preBlurForCurrentMonitor() { renderTextureInternalWithDamage(POUTFB->m_cTex, &wholeMonitor, 1, &fakeDamage, 0, false, true, false); m_bEndFrame = false; - m_RenderData.pCurrentMonData->primaryFB.bind(); + m_RenderData.currentFB->bind(); m_RenderData.pCurrentMonData->blurFBDirty = false; @@ -1321,8 +1341,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, CBox* pBox, flo POUTFB = &m_RenderData.pCurrentMonData->blurFB; } - // bind primary - m_RenderData.pCurrentMonData->primaryFB.bind(); + m_RenderData.currentFB->bind(); // make a stencil for rounded corners to work with blur scissor((CBox*)nullptr); // allow the entire window and stencil to render @@ -1404,7 +1423,7 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in float matrix[9]; wlr_matrix_project_box(matrix, box->pWlr(), wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), 0, - m_RenderData.pMonitor->output->transform_matrix); // TODO: write own, don't use WLR here + m_RenderData.pMonitor->projMatrix.data()); // TODO: write own, don't use WLR here float glMatrix[9]; wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); @@ -1744,7 +1763,7 @@ void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const float matrix[9]; wlr_matrix_project_box(matrix, box->pWlr(), wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), 0, - m_RenderData.pMonitor->output->transform_matrix); // TODO: write own, don't use WLR here + m_RenderData.pMonitor->projMatrix.data()); // TODO: write own, don't use WLR here float glMatrix[9]; wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); @@ -1811,11 +1830,11 @@ void CHyprOpenGLImpl::saveBufferForMirror() { blend(false); - renderTexture(m_RenderData.pCurrentMonData->primaryFB.m_cTex, &monbox, 1.f, 0, false, false); + renderTexture(m_RenderData.currentFB->m_cTex, &monbox, 1.f, 0, false, false); blend(true); - m_RenderData.pCurrentMonData->primaryFB.bind(); + m_RenderData.currentFB->bind(); } void CHyprOpenGLImpl::renderMirrored() { @@ -1974,7 +1993,7 @@ void CHyprOpenGLImpl::destroyMonitorResources(CMonitor* pMonitor) { wlr_output_attach_render(pMonitor->output, nullptr); g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].mirrorFB.release(); - g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].primaryFB.release(); + g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].offloadFB.release(); g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].mirrorSwapFB.release(); g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].monitorMirrorFB.release(); g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].blurFB.release(); @@ -2014,8 +2033,8 @@ void CHyprOpenGLImpl::renderOffToMain(CFramebuffer* off) { } void CHyprOpenGLImpl::bindBackOnMain() { - m_RenderData.pCurrentMonData->primaryFB.bind(); - m_RenderData.currentFB = &m_RenderData.pCurrentMonData->primaryFB; + m_RenderData.mainFB->bind(); + m_RenderData.currentFB = m_RenderData.mainFB; } void CHyprOpenGLImpl::setMonitorTransformEnabled(bool enabled) { diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 8c412302..4311e16c 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -14,6 +14,9 @@ #include "Texture.hpp" #include "Framebuffer.hpp" #include "Transformer.hpp" +#include "Renderbuffer.hpp" + +#include <GLES2/gl2ext.h> #include "../debug/TracyDefines.hpp" @@ -39,7 +42,7 @@ struct SRenderModifData { }; struct SMonitorRenderData { - CFramebuffer primaryFB; + CFramebuffer offloadFB; CFramebuffer mirrorFB; // these are used for some effects, CFramebuffer mirrorSwapFB; // etc CFramebuffer offMainFB; @@ -80,6 +83,7 @@ struct SCurrentRenderData { SMonitorRenderData* pCurrentMonData = nullptr; CFramebuffer* currentFB = nullptr; + CFramebuffer* mainFB = nullptr; CRegion damage; @@ -105,7 +109,6 @@ class CHyprOpenGLImpl { void begin(CMonitor*, CRegion*, bool fake = false); void end(); - void bindWlrOutputFb(); void renderRect(CBox*, const CColor&, int round = 0); void renderRectWithBlur(CBox*, const CColor&, int round = 0, float blurA = 1.f); @@ -157,7 +160,6 @@ class CHyprOpenGLImpl { SCurrentRenderData m_RenderData; GLint m_iCurrentOutputFb = 0; - GLint m_iWLROutputFb = 0; bool m_bReloadScreenShader = true; // at launch it can be set @@ -169,6 +171,11 @@ class CHyprOpenGLImpl { std::unordered_map<CMonitor*, SMonitorRenderData> m_mMonitorRenderResources; std::unordered_map<CMonitor*, CTexture> m_mMonitorBGTextures; + struct { + PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES = nullptr; + PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR = nullptr; + } m_sProc; + private: std::list<GLuint> m_lBuffers; std::list<GLuint> m_lTextures; @@ -176,10 +183,11 @@ class CHyprOpenGLImpl { int m_iDRMFD; std::string m_szExtensions; - bool m_bFakeFrame = false; - bool m_bEndFrame = false; - bool m_bApplyFinalShader = false; - bool m_bBlend = false; + 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; diff --git a/src/render/Renderbuffer.cpp b/src/render/Renderbuffer.cpp new file mode 100644 index 00000000..0643904b --- /dev/null +++ b/src/render/Renderbuffer.cpp @@ -0,0 +1,81 @@ +#include "Renderbuffer.hpp" +#include "OpenGL.hpp" +#include "../Compositor.hpp" + +#include <dlfcn.h> + +CRenderbuffer::~CRenderbuffer() { + if (eglGetCurrentContext() != wlr_egl_get_context(g_pCompositor->m_sWLREGL)) + eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, wlr_egl_get_context(g_pCompositor->m_sWLREGL)); + + m_sFramebuffer.release(); + glDeleteRenderbuffers(1, &m_iRBO); + + g_pHyprOpenGL->m_sProc.eglDestroyImageKHR(wlr_egl_get_display(g_pCompositor->m_sWLREGL), m_iImage); +} + +CRenderbuffer::CRenderbuffer(wlr_buffer* buffer, uint32_t format) : m_pWlrBuffer(buffer) { + + // EVIL, but we can't include a hidden header because nixos is fucking special + static EGLImageKHR (*PWLREGLCREATEIMAGEFROMDMABUF)(wlr_egl*, wlr_dmabuf_attributes*, bool*); + static bool symbolFound = false; + if (!symbolFound) { + PWLREGLCREATEIMAGEFROMDMABUF = reinterpret_cast<EGLImageKHR (*)(wlr_egl*, wlr_dmabuf_attributes*, bool*)>(dlsym(RTLD_DEFAULT, "wlr_egl_create_image_from_dmabuf")); + + symbolFound = true; + + RASSERT(PWLREGLCREATEIMAGEFROMDMABUF, "wlr_egl_create_image_from_dmabuf was not found in wlroots!"); + + Debug::log(LOG, "CRenderbuffer: wlr_egl_create_image_from_dmabuf found at {:x}", (uintptr_t)PWLREGLCREATEIMAGEFROMDMABUF); + } + // end evil hack + + struct wlr_dmabuf_attributes dmabuf = {0}; + if (!wlr_buffer_get_dmabuf(buffer, &dmabuf)) + throw std::runtime_error("wlr_buffer_get_dmabuf failed"); + + bool externalOnly; + m_iImage = PWLREGLCREATEIMAGEFROMDMABUF(g_pCompositor->m_sWLREGL, &dmabuf, &externalOnly); + if (m_iImage == EGL_NO_IMAGE_KHR) + throw std::runtime_error("wlr_egl_create_image_from_dmabuf failed"); + + glGenRenderbuffers(1, &m_iRBO); + glBindRenderbuffer(GL_RENDERBUFFER, m_iRBO); + g_pHyprOpenGL->m_sProc.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, (GLeglImageOES)m_iImage); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + + glGenFramebuffers(1, &m_sFramebuffer.m_iFb); + m_sFramebuffer.m_vSize = {buffer->width, buffer->height}; + m_sFramebuffer.bind(); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_iRBO); + + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + throw std::runtime_error("rbo: glCheckFramebufferStatus failed"); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + hyprListener_destroyBuffer.initCallback( + &buffer->events.destroy, [](void* owner, void* data) { g_pHyprRenderer->onRenderbufferDestroy((CRenderbuffer*)owner); }, this, "CRenderbuffer"); +} + +void CRenderbuffer::bind() { + glBindRenderbuffer(GL_RENDERBUFFER, m_iRBO); + bindFB(); +} + +void CRenderbuffer::bindFB() { + m_sFramebuffer.bind(); +} + +void CRenderbuffer::unbind() { + glBindRenderbuffer(GL_RENDERBUFFER, 0); +#ifndef GLES2 + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); +#else + glBindFramebuffer(GL_FRAMEBUFFER, 0); +#endif +} + +CFramebuffer* CRenderbuffer::getFB() { + return &m_sFramebuffer; +}
\ No newline at end of file diff --git a/src/render/Renderbuffer.hpp b/src/render/Renderbuffer.hpp new file mode 100644 index 00000000..d8df8ca5 --- /dev/null +++ b/src/render/Renderbuffer.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include "Framebuffer.hpp" + +class CMonitor; + +class CRenderbuffer { + public: + CRenderbuffer(wlr_buffer* buffer, uint32_t format); + ~CRenderbuffer(); + + void bind(); + void bindFB(); + void unbind(); + CFramebuffer* getFB(); + + wlr_buffer* m_pWlrBuffer = nullptr; + + DYNLISTENER(destroyBuffer); + + private: + EGLImageKHR m_iImage = 0; + GLuint m_iRBO = 0; + CFramebuffer m_sFramebuffer; +};
\ No newline at end of file diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 73c6ca25..128f36ef 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -845,8 +845,8 @@ bool CHyprRenderer::attemptDirectScanout(CMonitor* pMonitor) { } void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { - static std::chrono::high_resolution_clock::time_point startRender = std::chrono::high_resolution_clock::now(); - static std::chrono::high_resolution_clock::time_point startRenderOverlay = std::chrono::high_resolution_clock::now(); + static std::chrono::high_resolution_clock::time_point renderStart = std::chrono::high_resolution_clock::now(); + static std::chrono::high_resolution_clock::time_point renderStartOverlay = std::chrono::high_resolution_clock::now(); static std::chrono::high_resolution_clock::time_point endRenderOverlay = std::chrono::high_resolution_clock::now(); static auto* const PDEBUGOVERLAY = &g_pConfigManager->getConfigValuePtr("debug:overlay")->intValue; @@ -887,7 +887,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { firstLaunchAnimActive = false; } - startRender = std::chrono::high_resolution_clock::now(); + renderStart = std::chrono::high_resolution_clock::now(); if (*PDEBUGOVERLAY == 1) { g_pDebugOverlay->frameData(pMonitor); @@ -991,7 +991,6 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { // check the damage CRegion damage; bool hasChanged = pMonitor->output->needs_frame || pixman_region32_not_empty(&pMonitor->damage.current); - int bufferAge; if (!hasChanged && *PDAMAGETRACKINGMODE != DAMAGE_TRACKING_NONE && pMonitor->forceFullFrames == 0 && damageBlinkCleanup == 0) return; @@ -1007,16 +1006,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { if (UNLOCK_SC) wlr_output_lock_software_cursors(pMonitor->output, true); - if (!wlr_output_attach_render(pMonitor->output, &bufferAge)) { - Debug::log(ERR, "Couldn't attach render to display {} ???", pMonitor->szName); - - if (UNLOCK_SC) - wlr_output_lock_software_cursors(pMonitor->output, false); - - return; - } - - wlr_damage_ring_get_buffer_damage(&pMonitor->damage, bufferAge, damage.pixman()); + wlr_damage_ring_get_buffer_damage(&pMonitor->damage, m_iLastBufferAge, damage.pixman()); pMonitor->renderingActive = true; @@ -1062,7 +1052,25 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { TRACY_GPU_ZONE("Render"); - g_pHyprOpenGL->begin(pMonitor, &damage); + if (pMonitor == g_pCompositor->getMonitorFromCursor()) + g_pHyprOpenGL->m_RenderData.mouseZoomFactor = std::clamp(*PZOOMFACTOR, 1.f, INFINITY); + else + g_pHyprOpenGL->m_RenderData.mouseZoomFactor = 1.f; + + if (zoomInFactorFirstLaunch > 1.f) { + g_pHyprOpenGL->m_RenderData.mouseZoomFactor = zoomInFactorFirstLaunch; + g_pHyprOpenGL->m_RenderData.mouseZoomUseMouse = false; + g_pHyprOpenGL->m_RenderData.useNearestNeighbor = false; + } + + if (!beginRender(pMonitor, damage, RENDER_MODE_NORMAL)) { + Debug::log(ERR, "renderer: couldn't beginRender()!"); + + if (UNLOCK_SC) + wlr_output_lock_software_cursors(pMonitor->output, false); + + return; + } EMIT_HOOK_EVENT("render", RENDER_BEGIN); @@ -1097,7 +1105,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { // for drawing the debug overlay if (pMonitor == g_pCompositor->m_vMonitors.front().get() && *PDEBUGOVERLAY == 1) { - startRenderOverlay = std::chrono::high_resolution_clock::now(); + renderStartOverlay = std::chrono::high_resolution_clock::now(); g_pDebugOverlay->draw(); endRenderOverlay = std::chrono::high_resolution_clock::now(); } @@ -1118,35 +1126,22 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { renderCursor = renderCursor && shouldRenderCursor(); - if (renderCursor && wlr_renderer_begin(g_pCompositor->m_sWLRRenderer, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y)) { + if (renderCursor) { TRACY_GPU_ZONE("RenderCursor"); bool lockSoftware = pMonitor == g_pCompositor->getMonitorFromCursor() && *PZOOMFACTOR != 1.f; if (lockSoftware) { wlr_output_lock_software_cursors(pMonitor->output, true); - wlr_output_render_software_cursors(pMonitor->output, NULL); + g_pHyprRenderer->renderSoftwareCursors(pMonitor, g_pHyprOpenGL->m_RenderData.damage); wlr_output_lock_software_cursors(pMonitor->output, false); } else - wlr_output_render_software_cursors(pMonitor->output, NULL); - - wlr_renderer_end(g_pCompositor->m_sWLRRenderer); - } - - if (pMonitor == g_pCompositor->getMonitorFromCursor()) - g_pHyprOpenGL->m_RenderData.mouseZoomFactor = std::clamp(*PZOOMFACTOR, 1.f, INFINITY); - else - g_pHyprOpenGL->m_RenderData.mouseZoomFactor = 1.f; - - if (zoomInFactorFirstLaunch > 1.f) { - g_pHyprOpenGL->m_RenderData.mouseZoomFactor = zoomInFactorFirstLaunch; - g_pHyprOpenGL->m_RenderData.mouseZoomUseMouse = false; - g_pHyprOpenGL->m_RenderData.useNearestNeighbor = false; + g_pHyprRenderer->renderSoftwareCursors(pMonitor, g_pHyprOpenGL->m_RenderData.damage); } EMIT_HOOK_EVENT("render", RENDER_LAST_MOMENT); - g_pHyprOpenGL->end(); + endRender(); TRACY_GPU_COLLECT; @@ -1192,12 +1187,12 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { pMonitor->pendingFrame = false; - const float µs = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - startRender).count() / 1000.f; + const float µs = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - renderStart).count() / 1000.f; g_pDebugOverlay->renderData(pMonitor, µs); if (*PDEBUGOVERLAY == 1) { if (pMonitor == g_pCompositor->m_vMonitors.front().get()) { - const float µsNoOverlay = µs - std::chrono::duration_cast<std::chrono::nanoseconds>(endRenderOverlay - startRenderOverlay).count() / 1000.f; + const float µsNoOverlay = µs - std::chrono::duration_cast<std::chrono::nanoseconds>(endRenderOverlay - renderStartOverlay).count() / 1000.f; g_pDebugOverlay->renderDataNoOverlay(pMonitor, µsNoOverlay); } else { g_pDebugOverlay->renderDataNoOverlay(pMonitor, µs); @@ -1957,6 +1952,8 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR pMonitor->vecPixelSize = Vector2D(transformedBox.width, transformedBox.height); } + pMonitor->updateMatrix(); + // update renderer (here because it will call rollback, so we cannot do this before committing) g_pHyprOpenGL->destroyMonitorResources(pMonitor); @@ -2191,3 +2188,99 @@ void CHyprRenderer::recheckSolitaryForMonitor(CMonitor* pMonitor) { // found one! pMonitor->solitaryClient = PCANDIDATE; } + +void CHyprRenderer::renderSoftwareCursors(CMonitor* pMonitor, const CRegion& damage, std::optional<Vector2D> overridePos) { + const auto CURSORPOS = overridePos.value_or(g_pInputManager->getMouseCoordsInternal() - pMonitor->vecPosition); + wlr_output_cursor* cursor; + wl_list_for_each(cursor, &pMonitor->output->cursors, link) { + if (!cursor->enabled || !cursor->visible || pMonitor->output->hardware_cursor == cursor) + continue; + + if (!cursor->texture) + continue; + + CBox cursorBox = CBox{CURSORPOS.x, CURSORPOS.y, cursor->width, cursor->height}.translate({-cursor->hotspot_x, -cursor->hotspot_y}); + + g_pHyprOpenGL->renderTexturePrimitive(cursor->texture, &cursorBox); + } +} + +CRenderbuffer* CHyprRenderer::getOrCreateRenderbuffer(wlr_buffer* buffer, uint32_t fmt) { + auto it = std::find_if(m_vRenderbuffers.begin(), m_vRenderbuffers.end(), [&](const auto& other) { return other->m_pWlrBuffer == buffer; }); + + if (it != m_vRenderbuffers.end()) + return it->get(); + + return m_vRenderbuffers.emplace_back(std::make_unique<CRenderbuffer>(buffer, fmt)).get(); +} + +bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode, wlr_buffer* withBuffer) { + + if (eglGetCurrentContext() != wlr_egl_get_context(g_pCompositor->m_sWLREGL)) + eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, wlr_egl_get_context(g_pCompositor->m_sWLREGL)); + + m_eRenderMode = mode; + + g_pHyprOpenGL->m_RenderData.pMonitor = pMonitor; // has to be set cuz allocs + + if (mode == RENDER_MODE_FULL_FAKE) { + wlr_output_attach_render(pMonitor->output, nullptr); + g_pHyprOpenGL->begin(pMonitor, &damage, true); + return true; + } + + if (!withBuffer) { + if (!wlr_output_configure_primary_swapchain(pMonitor->output, &pMonitor->output->pending, &pMonitor->output->swapchain)) + return false; + + m_pCurrentWlrBuffer = wlr_swapchain_acquire(pMonitor->output->swapchain, &m_iLastBufferAge); + if (!m_pCurrentWlrBuffer) + return false; + } else { + m_pCurrentWlrBuffer = withBuffer; + } + + try { + m_pCurrentRenderbuffer = getOrCreateRenderbuffer(m_pCurrentWlrBuffer, pMonitor->drmFormat); + } catch (std::exception& e) { + wlr_buffer_unlock(m_pCurrentWlrBuffer); + return false; + } + + m_pCurrentRenderbuffer->bind(); + g_pHyprOpenGL->begin(pMonitor, &damage); + + return true; +} + +void CHyprRenderer::endRender() { + const auto PMONITOR = g_pHyprOpenGL->m_RenderData.pMonitor; + + g_pHyprOpenGL->end(); + + if (m_eRenderMode == RENDER_MODE_FULL_FAKE) { + wlr_output_rollback(PMONITOR->output); + return; + } + + glFlush(); + + if (m_eRenderMode == RENDER_MODE_NORMAL) + wlr_output_state_set_buffer(&PMONITOR->output->pending, m_pCurrentWlrBuffer); + + wlr_buffer_unlock(m_pCurrentWlrBuffer); + + m_pCurrentRenderbuffer->unbind(); + + m_pCurrentRenderbuffer = nullptr; + m_pCurrentWlrBuffer = nullptr; + m_iLastBufferAge = 0; +} + +void CHyprRenderer::onRenderbufferDestroy(CRenderbuffer* rb) { + std::erase_if(m_vRenderbuffers, [&](const auto& rbo) { return rbo.get() == rb; }); +} + +CRenderbuffer* CHyprRenderer::getCurrentRBO() { + return m_pCurrentRenderbuffer; +}
\ No newline at end of file diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index f28600b4..6b4f0561 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -6,6 +6,7 @@ #include "../helpers/Workspace.hpp" #include "../Window.hpp" #include "OpenGL.hpp" +#include "Renderbuffer.hpp" #include "../helpers/Timer.hpp" #include "../helpers/Region.hpp" @@ -27,6 +28,13 @@ enum eRenderPassMode RENDER_PASS_POPUP }; +enum eRenderMode +{ + RENDER_MODE_NORMAL = 0, + RENDER_MODE_FULL_FAKE = 1, + RENDER_MODE_TO_BUFFER = 2 +}; + class CToplevelExportProtocolManager; class CInputManager; struct SSessionLockSurface; @@ -58,6 +66,12 @@ class CHyprRenderer { void recheckSolitaryForMonitor(CMonitor* pMonitor); void setCursorSurface(wlr_surface* surf, int hotspotX, int hotspotY); void setCursorFromName(const std::string& name); + void renderSoftwareCursors(CMonitor* pMonitor, const CRegion& damage, std::optional<Vector2D> overridePos = {}); + void onRenderbufferDestroy(CRenderbuffer* rb); + CRenderbuffer* getCurrentRBO(); + + bool beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode = RENDER_MODE_NORMAL, wlr_buffer* withBuffer = nullptr); + void endRender(); bool m_bWindowRequestedCursorHide = false; bool m_bBlockSurfaceFeedback = false; @@ -89,19 +103,26 @@ class CHyprRenderer { } m_sLastCursorData; private: - void arrangeLayerArray(CMonitor*, const std::vector<std::unique_ptr<SLayerSurface>>&, bool, CBox*); - void renderWorkspaceWindowsFullscreen(CMonitor*, CWorkspace*, timespec*); // renders workspace windows (fullscreen) (tiled, floating, pinned, but no special) - void renderWorkspaceWindows(CMonitor*, CWorkspace*, timespec*); // renders workspace windows (no fullscreen) (tiled, floating, pinned, but no special) - void renderWindow(CWindow*, CMonitor*, timespec*, bool, eRenderPassMode, bool ignorePosition = false, bool ignoreAllGeometry = false); - void renderLayer(SLayerSurface*, CMonitor*, timespec*); - void renderSessionLockSurface(SSessionLockSurface*, CMonitor*, timespec*); - void renderDragIcon(CMonitor*, timespec*); - void renderIMEPopup(SIMEPopup*, CMonitor*, timespec*); - void renderWorkspace(CMonitor* pMonitor, CWorkspace* pWorkspace, timespec* now, const CBox& geometry); - void renderAllClientsForWorkspace(CMonitor* pMonitor, CWorkspace* pWorkspace, timespec* now, const Vector2D& translate = {0, 0}, const float& scale = 1.f); - - bool m_bHasARenderedCursor = true; - bool m_bCursorHasSurface = false; + void arrangeLayerArray(CMonitor*, const std::vector<std::unique_ptr<SLayerSurface>>&, bool, CBox*); + void renderWorkspaceWindowsFullscreen(CMonitor*, CWorkspace*, timespec*); // renders workspace windows (fullscreen) (tiled, floating, pinned, but no special) + void renderWorkspaceWindows(CMonitor*, CWorkspace*, timespec*); // renders workspace windows (no fullscreen) (tiled, floating, pinned, but no special) + void renderWindow(CWindow*, CMonitor*, timespec*, bool, eRenderPassMode, bool ignorePosition = false, bool ignoreAllGeometry = false); + void renderLayer(SLayerSurface*, CMonitor*, timespec*); + void renderSessionLockSurface(SSessionLockSurface*, CMonitor*, timespec*); + void renderDragIcon(CMonitor*, timespec*); + void renderIMEPopup(SIMEPopup*, CMonitor*, timespec*); + void renderWorkspace(CMonitor* pMonitor, CWorkspace* pWorkspace, timespec* now, const CBox& geometry); + void renderAllClientsForWorkspace(CMonitor* pMonitor, CWorkspace* pWorkspace, timespec* now, const Vector2D& translate = {0, 0}, const float& scale = 1.f); + + bool m_bHasARenderedCursor = true; + bool m_bCursorHasSurface = false; + CRenderbuffer* m_pCurrentRenderbuffer = nullptr; + wlr_buffer* m_pCurrentWlrBuffer = nullptr; + eRenderMode m_eRenderMode = RENDER_MODE_NORMAL; + int m_iLastBufferAge = 0; + + CRenderbuffer* getOrCreateRenderbuffer(wlr_buffer* buffer, uint32_t fmt); + std::vector<std::unique_ptr<CRenderbuffer>> m_vRenderbuffers; friend class CHyprOpenGLImpl; friend class CToplevelExportProtocolManager; diff --git a/subprojects/wlroots b/subprojects/wlroots -Subproject 5de9e1a99d6642c2d09d589aa37ff0a8945dcee +Subproject f1762f428b0ef2989c81f57ea9e810403d34d94 diff --git a/subprojects/wlroots.wrap b/subprojects/wlroots.wrap index 7df8166b..94757838 100644 --- a/subprojects/wlroots.wrap +++ b/subprojects/wlroots.wrap @@ -1,7 +1,7 @@ [wrap-git] directory = wlroots url = https://gitlab.freedesktop.org/wlroots/wlroots.git -revision = 5de9e1a99d6642c2d09d589aa37ff0a8945dcee1 +revision = f1762f428b0ef2989c81f57ea9e810403d34d946 depth = 1 diff_files = wlroots-meson-build.patch |