From ee3f000ab14911accf729baeef5bfda0b03b8ec1 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Fri, 21 Apr 2023 01:45:01 +0100 Subject: [PATCH] multimon improvements part 1 --- src/WallpaperEngine/Render/CRenderContext.cpp | 9 +++- .../Render/Drivers/CVideoDriver.cpp | 12 +++++ .../Render/Drivers/CVideoDriver.h | 14 ++++- .../Render/Drivers/CWaylandOpenGLDriver.cpp | 51 ++++++++++++++----- .../Render/Drivers/CWaylandOpenGLDriver.h | 7 ++- 5 files changed, 76 insertions(+), 17 deletions(-) diff --git a/src/WallpaperEngine/Render/CRenderContext.cpp b/src/WallpaperEngine/Render/CRenderContext.cpp index d740797..c871c90 100644 --- a/src/WallpaperEngine/Render/CRenderContext.cpp +++ b/src/WallpaperEngine/Render/CRenderContext.cpp @@ -29,6 +29,9 @@ namespace WallpaperEngine::Render for (const auto& cur : this->m_output->getViewports ()) { + if (!this->m_driver.shouldRenderOutput(cur.first)) + continue; + this->m_driver.makeCurrent(cur.first); #if !NDEBUG @@ -53,6 +56,9 @@ namespace WallpaperEngine::Render #if !NDEBUG glPopDebugGroup (); #endif /* DEBUG */ + + if (this->m_driver.requiresSeparateFlips()) + this->m_driver.swapOutputBuffer(cur.first); } // read the full texture into the image @@ -65,7 +71,8 @@ namespace WallpaperEngine::Render // update the output with the given image this->m_output->updateRender (); // finally swap buffers - this->m_driver.swapBuffers (); + if (!this->m_driver.requiresSeparateFlips()) + this->m_driver.swapBuffers (); } void CRenderContext::setDefaultWallpaper (CWallpaper* wallpaper) diff --git a/src/WallpaperEngine/Render/Drivers/CVideoDriver.cpp b/src/WallpaperEngine/Render/Drivers/CVideoDriver.cpp index df41c8e..268091f 100644 --- a/src/WallpaperEngine/Render/Drivers/CVideoDriver.cpp +++ b/src/WallpaperEngine/Render/Drivers/CVideoDriver.cpp @@ -8,4 +8,16 @@ void CVideoDriver::dispatchEventQueue() const { void CVideoDriver::makeCurrent(const std::string& outputName) const { // intentionally left blank +} + +bool CVideoDriver::shouldRenderOutput(const std::string& outputName) const { + return true; +} + +bool CVideoDriver::requiresSeparateFlips() const { + return false; +} + +void CVideoDriver::swapOutputBuffer(const std::string& outputName) { + // intentionally left blank } \ No newline at end of file diff --git a/src/WallpaperEngine/Render/Drivers/CVideoDriver.h b/src/WallpaperEngine/Render/Drivers/CVideoDriver.h index 06fd057..a5e0c64 100644 --- a/src/WallpaperEngine/Render/Drivers/CVideoDriver.h +++ b/src/WallpaperEngine/Render/Drivers/CVideoDriver.h @@ -56,6 +56,18 @@ namespace WallpaperEngine::Render::Drivers /** * Wayland only: make EGL current */ - void makeCurrent(const std::string& outputName) const; + virtual void makeCurrent(const std::string& outputName) const; + /** + * Wayland only: whether an output should be rendered + */ + virtual bool shouldRenderOutput(const std::string& outputName) const; + /** + * Wayland only: whether requires separate buffer flips on monitors + */ + virtual bool requiresSeparateFlips() const; + /** + * Wayland only: flip output + */ + virtual void swapOutputBuffer(const std::string& outputName); }; } \ No newline at end of file diff --git a/src/WallpaperEngine/Render/Drivers/CWaylandOpenGLDriver.cpp b/src/WallpaperEngine/Render/Drivers/CWaylandOpenGLDriver.cpp index 80b79d1..578a0ac 100644 --- a/src/WallpaperEngine/Render/Drivers/CWaylandOpenGLDriver.cpp +++ b/src/WallpaperEngine/Render/Drivers/CWaylandOpenGLDriver.cpp @@ -266,7 +266,9 @@ static void surfaceFrameCallback(void *data, struct wl_callback *cb, uint32_t ti const auto PLS = (CLayerSurface*)data; wl_callback_destroy(cb); PLS->frameCallback = nullptr; + PLS->output->rendering = true; PLS->output->driver->wallpaperApplication->renderFrame(); + PLS->output->rendering = false; } const struct wl_callback_listener frameListener = { @@ -403,20 +405,7 @@ glm::ivec2 CWaylandOpenGLDriver::getFramebufferSize () const { } void CWaylandOpenGLDriver::swapBuffers () { - for (auto& o : m_outputs) { - if (!o->layerSurface.get()) - continue; - - eglMakeCurrent(eglContext.display, o->layerSurface->eglSurface, o->layerSurface->eglSurface, eglContext.context); - o->layerSurface->frameCallback = wl_surface_frame(o->layerSurface->surface); - wl_callback_add_listener(o->layerSurface->frameCallback, &frameListener, o->layerSurface.get()); - eglSwapBuffers(eglContext.display, o->layerSurface->eglSurface); - wl_surface_set_buffer_scale(o->layerSurface->surface, o->scale); - wl_surface_damage_buffer(o->layerSurface->surface, 0, 0, INT32_MAX, INT32_MAX); - wl_surface_commit(o->layerSurface->surface); - - m_frameCounter++; - } + ; } void CWaylandOpenGLDriver::resizeLSSurfaceEGL(CLayerSurface* layerSurface) { @@ -432,7 +421,9 @@ void CWaylandOpenGLDriver::resizeLSSurfaceEGL(CLayerSurface* layerSurface) { wallpaperApplication->getOutput()->reset(); + layerSurface->output->rendering = true; wallpaperApplication->renderFrame(); + layerSurface->output->rendering = false; } } @@ -465,3 +456,35 @@ CLayerSurface* CWaylandOpenGLDriver::surfaceToLS(wl_surface* surface) { return nullptr; } + +bool CWaylandOpenGLDriver::shouldRenderOutput(const std::string& outputName) const { + for (auto& o : m_outputs) { + if (o->name == outputName) + return o->layerSurface.get() && (o->rendering || !o->layerSurface->callbackInitialized); + } + + return false; +} + +bool CWaylandOpenGLDriver::requiresSeparateFlips() const { + return true; +} + +void CWaylandOpenGLDriver::swapOutputBuffer(const std::string& outputName) { + for (auto& o : m_outputs) { + if (o->name != outputName) + continue; + + o->layerSurface->callbackInitialized = true; + + eglMakeCurrent(eglContext.display, o->layerSurface->eglSurface, o->layerSurface->eglSurface, eglContext.context); + o->layerSurface->frameCallback = wl_surface_frame(o->layerSurface->surface); + wl_callback_add_listener(o->layerSurface->frameCallback, &frameListener, o->layerSurface.get()); + eglSwapBuffers(eglContext.display, o->layerSurface->eglSurface); + wl_surface_set_buffer_scale(o->layerSurface->surface, o->scale); + wl_surface_damage_buffer(o->layerSurface->surface, 0, 0, INT32_MAX, INT32_MAX); + wl_surface_commit(o->layerSurface->surface); + + m_frameCounter++; + } +} diff --git a/src/WallpaperEngine/Render/Drivers/CWaylandOpenGLDriver.h b/src/WallpaperEngine/Render/Drivers/CWaylandOpenGLDriver.h index 34c0278..8eb02b0 100644 --- a/src/WallpaperEngine/Render/Drivers/CWaylandOpenGLDriver.h +++ b/src/WallpaperEngine/Render/Drivers/CWaylandOpenGLDriver.h @@ -37,6 +37,7 @@ namespace WallpaperEngine::Render::Drivers CWaylandOpenGLDriver* driver = nullptr; bool initialized = false; std::unique_ptr layerSurface; + bool rendering = false; }; class CLayerSurface { @@ -54,6 +55,7 @@ namespace WallpaperEngine::Render::Drivers glm::dvec2 mousePos = {0, 0}; wl_cursor* pointer = nullptr; wl_surface* cursorSurface = nullptr; + bool callbackInitialized = false; }; class CWaylandOpenGLDriver : public CVideoDriver @@ -73,7 +75,10 @@ namespace WallpaperEngine::Render::Drivers void swapBuffers () override; uint32_t getFrameCounter () const override; void dispatchEventQueue() const override; - void makeCurrent(const std::string& outputName) const; + void makeCurrent(const std::string& outputName) const override; + bool shouldRenderOutput(const std::string& outputName) const override; + bool requiresSeparateFlips() const override; + void swapOutputBuffer(const std::string& outputName) override; GLFWwindow* getWindow ();