diff --git a/src/Hyprpaper.cpp b/src/Hyprpaper.cpp index 6f186fe..d4418ce 100644 --- a/src/Hyprpaper.cpp +++ b/src/Hyprpaper.cpp @@ -43,8 +43,11 @@ void CHyprpaper::init() { void CHyprpaper::tick() { m_mtTickMutex.lock(); - recheckAllMonitors(); preloadAllWallpapersFromConfig(); + ensurePoolBuffersPresent(); + + recheckAllMonitors(); + g_pIPCSocket->mainThreadParseRequest(); m_mtTickMutex.unlock(); @@ -100,6 +103,29 @@ SMonitor* CHyprpaper::getMonitorFromName(const std::string& monname) { return nullptr; } +void CHyprpaper::ensurePoolBuffersPresent() { + for (auto&[file, wt] : m_mWallpaperTargets) { + for (auto& m : m_vMonitors) { + + if (m->size == Vector2D()) + continue; + + auto it = std::find_if(m_vBuffers.begin(), m_vBuffers.end(), [&](const std::unique_ptr& el) { + return el->pTarget == &wt && el->pixelSize == m->size; + }); + + if (it == m_vBuffers.end()) { + // create + const auto PBUFFER = m_vBuffers.emplace_back(std::make_unique()).get(); + + createBuffer(PBUFFER, m->size.x * m->scale, m->size.y * m->scale, WL_SHM_FORMAT_ARGB8888); + + PBUFFER->pTarget = &wt; + } + } + } +} + void CHyprpaper::clearWallpaperFromMonitor(const std::string& monname) { const auto PMONITOR = getMonitorFromName(monname); @@ -271,6 +297,7 @@ void CHyprpaper::createBuffer(SPoolBuffer* pBuffer, int32_t w, int32_t h, uint32 pBuffer->data = DATA; pBuffer->surface = cairo_image_surface_create_for_data((unsigned char*)DATA, CAIRO_FORMAT_ARGB32, w, h, STRIDE); pBuffer->cairo = cairo_create(pBuffer->surface); + pBuffer->pixelSize = Vector2D(w, h); } void CHyprpaper::destroyBuffer(SPoolBuffer* pBuffer) { @@ -282,21 +309,13 @@ void CHyprpaper::destroyBuffer(SPoolBuffer* pBuffer) { pBuffer->buffer = nullptr; } +SPoolBuffer* CHyprpaper::getPoolBuffer(SMonitor* pMonitor, CWallpaperTarget* pWallpaperTarget) { + return std::find_if(m_vBuffers.begin(), m_vBuffers.end(), [&](const std::unique_ptr& el) { + return el->pTarget == pWallpaperTarget && el->pixelSize == pMonitor->size; + })->get(); +} + void CHyprpaper::renderWallpaperForMonitor(SMonitor* pMonitor) { - auto *const PBUFFER = &pMonitor->buffer; - - if (!PBUFFER->buffer) { - createBuffer(PBUFFER, pMonitor->size.x * pMonitor->scale, pMonitor->size.y * pMonitor->scale, WL_SHM_FORMAT_ARGB8888); - } - - const auto PCAIRO = PBUFFER->cairo; - cairo_save(PCAIRO); - cairo_set_operator(PCAIRO, CAIRO_OPERATOR_CLEAR); - cairo_paint(PCAIRO); - cairo_restore(PCAIRO); - - // render - // get wp const auto PWALLPAPERTARGET = m_mMonitorActiveWallpaperTargets[pMonitor]; if (!PWALLPAPERTARGET) { @@ -304,6 +323,14 @@ void CHyprpaper::renderWallpaperForMonitor(SMonitor* pMonitor) { exit(1); } + auto *const PBUFFER = getPoolBuffer(pMonitor, PWALLPAPERTARGET); + + const auto PCAIRO = PBUFFER->cairo; + cairo_save(PCAIRO); + cairo_set_operator(PCAIRO, CAIRO_OPERATOR_CLEAR); + cairo_paint(PCAIRO); + cairo_restore(PCAIRO); + // get scale // we always do cover float scale; @@ -331,6 +358,4 @@ void CHyprpaper::renderWallpaperForMonitor(SMonitor* pMonitor) { wl_surface_set_buffer_scale(pMonitor->pSurface, pMonitor->scale); wl_surface_damage_buffer(pMonitor->pSurface, 0, 0, pMonitor->size.x, pMonitor->size.y); wl_surface_commit(pMonitor->pSurface); - - destroyBuffer(PBUFFER); } \ No newline at end of file diff --git a/src/Hyprpaper.hpp b/src/Hyprpaper.hpp index 4e71c24..6c458ed 100644 --- a/src/Hyprpaper.hpp +++ b/src/Hyprpaper.hpp @@ -25,7 +25,7 @@ public: std::unordered_map m_mWallpaperTargets; std::unordered_map m_mMonitorActiveWallpapers; std::unordered_map m_mMonitorActiveWallpaperTargets; - std::vector> m_mBuffers; + std::vector> m_vBuffers; std::vector> m_vMonitors; void preloadAllWallpapersFromConfig(); @@ -41,9 +41,11 @@ public: SMonitor* getMonitorFromName(const std::string&); bool isPreloaded(const std::string&); void recheckMonitor(SMonitor*); + void ensurePoolBuffersPresent(); + SPoolBuffer* getPoolBuffer(SMonitor*, CWallpaperTarget*); -private: std::mutex m_mtTickMutex; +private: bool m_bShouldExit = false; }; diff --git a/src/events/Events.cpp b/src/events/Events.cpp index 73dbeb6..bc42748 100644 --- a/src/events/Events.cpp +++ b/src/events/Events.cpp @@ -51,11 +51,15 @@ void Events::handleGlobal(void *data, struct wl_registry *registry, uint32_t nam } else if (strcmp(interface, wl_shm_interface.name) == 0) { g_pHyprpaper->m_sSHM = (wl_shm *)wl_registry_bind(registry, name, &wl_shm_interface, 1); } else if (strcmp(interface, wl_output_interface.name) == 0) { + g_pHyprpaper->m_mtTickMutex.lock(); + const auto PMONITOR = g_pHyprpaper->m_vMonitors.emplace_back(std::make_unique()).get(); PMONITOR->wayland_name = name; PMONITOR->name = ""; PMONITOR->output = (wl_output *)wl_registry_bind(registry, name, &wl_output_interface, 4); wl_output_add_listener(PMONITOR->output, &Events::outputListener, PMONITOR); + + g_pHyprpaper->m_mtTickMutex.unlock(); } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { g_pHyprpaper->m_sLayerShell = (zwlr_layer_shell_v1 *)wl_registry_bind(registry, name, &zwlr_layer_shell_v1_interface, 1); } diff --git a/src/helpers/PoolBuffer.hpp b/src/helpers/PoolBuffer.hpp index 35b9703..6b2042e 100644 --- a/src/helpers/PoolBuffer.hpp +++ b/src/helpers/PoolBuffer.hpp @@ -2,10 +2,15 @@ #include "../defines.hpp" +class CWallpaperTarget; + struct SPoolBuffer { wl_buffer* buffer = nullptr; cairo_surface_t* surface = nullptr; cairo_t* cairo = nullptr; void* data = nullptr; size_t size = 0; + + CWallpaperTarget* pTarget = nullptr; + Vector2D pixelSize; }; \ No newline at end of file