From ce2dc8395f02d11ad1a195badaf3e66298bede4c Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Thu, 20 Apr 2023 22:02:47 +0100 Subject: [PATCH] move ls to a class --- src/WallpaperEngine/Render/CRenderContext.cpp | 2 + .../Render/Drivers/CVideoDriver.cpp | 2 +- .../Render/Drivers/CVideoDriver.h | 3 +- .../Render/Drivers/CWaylandOpenGLDriver.cpp | 145 ++++++++++-------- .../Render/Drivers/CWaylandOpenGLDriver.h | 42 ++--- 5 files changed, 110 insertions(+), 84 deletions(-) diff --git a/src/WallpaperEngine/Render/CRenderContext.cpp b/src/WallpaperEngine/Render/CRenderContext.cpp index 22803f9..d740797 100644 --- a/src/WallpaperEngine/Render/CRenderContext.cpp +++ b/src/WallpaperEngine/Render/CRenderContext.cpp @@ -29,6 +29,8 @@ namespace WallpaperEngine::Render for (const auto& cur : this->m_output->getViewports ()) { + this->m_driver.makeCurrent(cur.first); + #if !NDEBUG std::string str = "Rendering to output " + cur.first; diff --git a/src/WallpaperEngine/Render/Drivers/CVideoDriver.cpp b/src/WallpaperEngine/Render/Drivers/CVideoDriver.cpp index aa6e6db..df41c8e 100644 --- a/src/WallpaperEngine/Render/Drivers/CVideoDriver.cpp +++ b/src/WallpaperEngine/Render/Drivers/CVideoDriver.cpp @@ -6,6 +6,6 @@ void CVideoDriver::dispatchEventQueue() const { // intentionally left blank } -void CVideoDriver::makeCurrent() const { +void CVideoDriver::makeCurrent(const std::string& outputName) const { // 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 784873e..06fd057 100644 --- a/src/WallpaperEngine/Render/Drivers/CVideoDriver.h +++ b/src/WallpaperEngine/Render/Drivers/CVideoDriver.h @@ -2,6 +2,7 @@ #include #include +#include namespace WallpaperEngine::Render::Drivers { @@ -55,6 +56,6 @@ namespace WallpaperEngine::Render::Drivers /** * Wayland only: make EGL current */ - void makeCurrent() const; + void makeCurrent(const std::string& outputName) const; }; } \ No newline at end of file diff --git a/src/WallpaperEngine/Render/Drivers/CWaylandOpenGLDriver.cpp b/src/WallpaperEngine/Render/Drivers/CWaylandOpenGLDriver.cpp index 5090717..2b401f4 100644 --- a/src/WallpaperEngine/Render/Drivers/CWaylandOpenGLDriver.cpp +++ b/src/WallpaperEngine/Render/Drivers/CWaylandOpenGLDriver.cpp @@ -30,7 +30,8 @@ void mode(void* data, wl_output* output, uint32_t flags, int32_t width, int32_t PMONITOR->size = {width, height}; PMONITOR->lsSize = {width, height}; - PMONITOR->driver->resizeLSSurfaceEGL(); + if (PMONITOR->layerSurface.get()) + PMONITOR->driver->resizeLSSurfaceEGL(PMONITOR->layerSurface.get()); if (PMONITOR->initialized) PMONITOR->driver->wallpaperApplication->getOutput()->reset(); @@ -47,7 +48,8 @@ void scale(void* data, wl_output* wl_output, int32_t scale) { PMONITOR->scale = scale; - PMONITOR->driver->resizeLSSurfaceEGL(); + if (PMONITOR->layerSurface.get()) + PMONITOR->driver->resizeLSSurfaceEGL(PMONITOR->layerSurface.get()); if (PMONITOR->initialized) PMONITOR->driver->wallpaperApplication->getOutput()->reset(); @@ -189,24 +191,24 @@ void CWaylandOpenGLDriver::finishEGL() { static void handleLSConfigure(void *data, zwlr_layer_surface_v1 *surface, uint32_t serial, uint32_t w, uint32_t h) { - const auto PDRIVER = (CWaylandOpenGLDriver*)data; - PDRIVER->waylandContext.layerSurface.size = {w, h}; + const auto PLS = (CLayerSurface*)data; + PLS->size = {w, h}; - PDRIVER->resizeLSSurfaceEGL(); + PLS->output->driver->resizeLSSurfaceEGL(PLS); zwlr_layer_surface_v1_ack_configure(surface, serial); } static void handleLSClosed(void *data, zwlr_layer_surface_v1 *surface) { - const auto PDRIVER = (CWaylandOpenGLDriver*)data; - PDRIVER->onLayerClose(); + const auto PLS = (CLayerSurface*)data; + PLS->output->driver->onLayerClose(PLS); } -void CWaylandOpenGLDriver::onLayerClose() { - eglDestroySurface(eglContext.display, waylandContext.layerSurface.eglSurface); - wl_egl_window_destroy(waylandContext.layerSurface.eglWindow); - zwlr_layer_surface_v1_destroy(waylandContext.layerSurface.layerSurface); - wl_surface_destroy(waylandContext.layerSurface.surface); +void CWaylandOpenGLDriver::onLayerClose(CLayerSurface* layerSurface) { + eglDestroySurface(eglContext.display, layerSurface->eglSurface); + wl_egl_window_destroy(layerSurface->eglWindow); + zwlr_layer_surface_v1_destroy(layerSurface->layerSurface); + wl_surface_destroy(layerSurface->surface); sLog.exception("Compositor closed our LS!"); // todo: handle this? } @@ -216,16 +218,50 @@ const struct zwlr_layer_surface_v1_listener layerSurfaceListener = { }; static void surfaceFrameCallback(void *data, struct wl_callback *cb, uint32_t time) { - const auto PDRIVER = (CWaylandOpenGLDriver*)data; + const auto PLS = (CLayerSurface*)data; wl_callback_destroy(cb); - PDRIVER->waylandContext.layerSurface.frameCallback = nullptr; - PDRIVER->wallpaperApplication->renderFrame(); + PLS->frameCallback = nullptr; + PLS->output->driver->wallpaperApplication->renderFrame(); } const struct wl_callback_listener frameListener = { .done = surfaceFrameCallback }; +CLayerSurface::CLayerSurface(CWaylandOpenGLDriver* pDriver, SWaylandOutput* pOutput) { + surface = wl_compositor_create_surface(pDriver->waylandContext.compositor); + layerSurface = zwlr_layer_shell_v1_get_layer_surface(pDriver->waylandContext.layerShell, surface, output->output, ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND, "linux-wallpaperengine"); + output = pOutput; + + if (!layerSurface) + sLog.exception("Failed to get a layer surface"); + + wl_region* region = wl_compositor_create_region(pDriver->waylandContext.compositor); + + zwlr_layer_surface_v1_set_size(layerSurface, 0, 0); + zwlr_layer_surface_v1_set_anchor(layerSurface, ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM); + zwlr_layer_surface_v1_set_keyboard_interactivity(layerSurface, false); + zwlr_layer_surface_v1_add_listener(layerSurface, &layerSurfaceListener, this); + zwlr_layer_surface_v1_set_exclusive_zone(layerSurface, -1); + wl_surface_set_input_region(surface, region); + wl_surface_commit(surface); + wl_display_roundtrip(pDriver->waylandContext.display); + + eglWindow = wl_egl_window_create(surface, size.x * output->scale, size.y * output->scale); + eglSurface = pDriver->eglContext.eglCreatePlatformWindowSurfaceEXT(pDriver->eglContext.display, pDriver->eglContext.config, eglWindow, nullptr); + output->lsSize = size; + wl_surface_commit(surface); + wl_display_roundtrip(pDriver->waylandContext.display); + wl_display_flush(pDriver->waylandContext.display); + + if (eglMakeCurrent(pDriver->eglContext.display, eglSurface, eglSurface, pDriver->eglContext.context) == EGL_FALSE) + sLog.exception("Failed to make egl current"); +} + +CLayerSurface::~CLayerSurface() { + ; +} + CWaylandOpenGLDriver::CWaylandOpenGLDriver(const char* windowTitle, CApplicationContext& context, CWallpaperApplication* app) : m_frameCounter(0) { wallpaperApplication = app; waylandContext.display = wl_display_connect(NULL); @@ -268,38 +304,8 @@ CWaylandOpenGLDriver::CWaylandOpenGLDriver(const char* windowTitle, CApplication sLog.exception("Failed to get a cursor surface"); initEGL(); - - waylandContext.layerSurface.surface = wl_compositor_create_surface(waylandContext.compositor); - waylandContext.layerSurface.layerSurface = zwlr_layer_shell_v1_get_layer_surface(waylandContext.layerShell, waylandContext.layerSurface.surface, outputToUse->output, ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND, "linux-wallpaperengine"); - waylandContext.layerSurface.output = outputToUse; - if (!waylandContext.layerSurface.layerSurface) { - finishEGL(); - sLog.exception("Failed to get a layer surface"); - } - - wl_region* region = wl_compositor_create_region(waylandContext.compositor); - - zwlr_layer_surface_v1_set_size(waylandContext.layerSurface.layerSurface, 0, 0); - zwlr_layer_surface_v1_set_anchor(waylandContext.layerSurface.layerSurface, ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM); - zwlr_layer_surface_v1_set_keyboard_interactivity(waylandContext.layerSurface.layerSurface, false); - zwlr_layer_surface_v1_add_listener(waylandContext.layerSurface.layerSurface, &layerSurfaceListener, this); - zwlr_layer_surface_v1_set_exclusive_zone(waylandContext.layerSurface.layerSurface, -1); - wl_surface_set_input_region(waylandContext.layerSurface.surface, region); - wl_surface_commit(waylandContext.layerSurface.surface); - wl_display_roundtrip(waylandContext.display); - - waylandContext.layerSurface.eglWindow = wl_egl_window_create(waylandContext.layerSurface.surface, waylandContext.layerSurface.size.x * outputToUse->scale, waylandContext.layerSurface.size.y * outputToUse->scale); - waylandContext.layerSurface.eglSurface = eglContext.eglCreatePlatformWindowSurfaceEXT(eglContext.display, eglContext.config, waylandContext.layerSurface.eglWindow, nullptr); - outputToUse->lsSize = waylandContext.layerSurface.size; - wl_surface_commit(waylandContext.layerSurface.surface); - wl_display_roundtrip(waylandContext.display); - wl_display_flush(waylandContext.display); - - if (eglMakeCurrent(eglContext.display, waylandContext.layerSurface.eglSurface, waylandContext.layerSurface.eglSurface, eglContext.context) == EGL_FALSE) { - finishEGL(); - sLog.exception("Failed to make egl current"); - } + const auto PLS = (outputToUse->layerSurface = std::make_unique(this, outputToUse)).get(); GLenum result = glewInit (); @@ -346,29 +352,35 @@ void CWaylandOpenGLDriver::hideWindow () { } glm::ivec2 CWaylandOpenGLDriver::getFramebufferSize () const { - return waylandContext.layerSurface.size; + return glm::ivec2{0, 0}; } void CWaylandOpenGLDriver::swapBuffers () { - waylandContext.layerSurface.frameCallback = wl_surface_frame(waylandContext.layerSurface.surface); - wl_callback_add_listener(waylandContext.layerSurface.frameCallback, &frameListener, this); - eglSwapBuffers(eglContext.display, waylandContext.layerSurface.eglSurface); - wl_surface_set_buffer_scale(waylandContext.layerSurface.surface, waylandContext.layerSurface.output->scale); - wl_surface_damage_buffer(waylandContext.layerSurface.surface, 0, 0, INT32_MAX, INT32_MAX); - wl_surface_commit(waylandContext.layerSurface.surface); + for (auto& o : m_outputs) { + if (!o->layerSurface.get()) + continue; - m_frameCounter++; + 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, this); + 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() { - if (waylandContext.layerSurface.eglWindow) { - waylandContext.layerSurface.output->lsSize = waylandContext.layerSurface.size; +void CWaylandOpenGLDriver::resizeLSSurfaceEGL(CLayerSurface* layerSurface) { + if (layerSurface->eglWindow) { + layerSurface->output->lsSize = layerSurface->size; - wl_egl_window_resize(waylandContext.layerSurface.eglWindow, waylandContext.layerSurface.size.x * waylandContext.layerSurface.output->scale, waylandContext.layerSurface.size.y * waylandContext.layerSurface.output->scale, 0, 0); + wl_egl_window_resize(layerSurface->eglWindow, layerSurface->size.x * layerSurface->output->scale, layerSurface->size.y * layerSurface->output->scale, 0, 0); - if (waylandContext.layerSurface.frameCallback) { - wl_callback_destroy(waylandContext.layerSurface.frameCallback); - waylandContext.layerSurface.frameCallback = nullptr; + if (layerSurface->frameCallback) { + wl_callback_destroy(layerSurface->frameCallback); + layerSurface->frameCallback = nullptr; } wallpaperApplication->getOutput()->reset(); @@ -387,8 +399,13 @@ GLFWwindow* CWaylandOpenGLDriver::getWindow () { #include -void CWaylandOpenGLDriver::makeCurrent() const { - if (eglMakeCurrent(eglContext.display, waylandContext.layerSurface.eglSurface, waylandContext.layerSurface.eglSurface, eglContext.context) == EGL_FALSE) { - std::cerr << "Couldn't make egl current"; +void CWaylandOpenGLDriver::makeCurrent(const std::string& outputName) const { + for (auto& o : m_outputs) { + if (o->name != outputName) + continue; + + if (eglMakeCurrent(eglContext.display, o->layerSurface->eglSurface, o->layerSurface->eglSurface, eglContext.context) == EGL_FALSE) { + std::cerr << "Couldn't make egl current"; + } } } \ No newline at end of file diff --git a/src/WallpaperEngine/Render/Drivers/CWaylandOpenGLDriver.h b/src/WallpaperEngine/Render/Drivers/CWaylandOpenGLDriver.h index 6ec5bc4..0498720 100644 --- a/src/WallpaperEngine/Render/Drivers/CWaylandOpenGLDriver.h +++ b/src/WallpaperEngine/Render/Drivers/CWaylandOpenGLDriver.h @@ -25,6 +25,7 @@ namespace WallpaperEngine::Render::Drivers { using namespace WallpaperEngine::Application; class CWaylandOpenGLDriver; + class CLayerSurface; struct SWaylandOutput { wl_output* output; @@ -35,6 +36,21 @@ namespace WallpaperEngine::Render::Drivers int scale = 1; CWaylandOpenGLDriver* driver = nullptr; bool initialized = false; + std::unique_ptr layerSurface; + }; + + class CLayerSurface { + public: + CLayerSurface(CWaylandOpenGLDriver*, SWaylandOutput*); + ~CLayerSurface(); + + wl_egl_window* eglWindow = nullptr; + EGLSurface eglSurface = nullptr; + wl_surface* surface = nullptr; + zwlr_layer_surface_v1* layerSurface = nullptr; + glm::ivec2 size; + wl_callback* frameCallback = nullptr; + SWaylandOutput* output = nullptr; }; class CWaylandOpenGLDriver : public CVideoDriver @@ -54,7 +70,7 @@ namespace WallpaperEngine::Render::Drivers void swapBuffers () override; uint32_t getFrameCounter () const override; void dispatchEventQueue() const override; - void makeCurrent() const; + void makeCurrent(const std::string& outputName) const; GLFWwindow* getWindow (); @@ -66,30 +82,15 @@ namespace WallpaperEngine::Render::Drivers zwlr_layer_shell_v1* layerShell = nullptr; wl_cursor* pointer = nullptr; wl_surface* cursorSurface = nullptr; - - struct { - wl_egl_window* eglWindow = nullptr; - EGLSurface eglSurface = nullptr; - wl_surface* surface = nullptr; - zwlr_layer_surface_v1* layerSurface = nullptr; - glm::ivec2 size; - wl_callback* frameCallback = nullptr; - SWaylandOutput* output = nullptr; - } layerSurface; } waylandContext; - void onLayerClose(); - void resizeLSSurfaceEGL(); + void onLayerClose(CLayerSurface*); + void resizeLSSurfaceEGL(CLayerSurface*); std::vector> m_outputs; CWallpaperApplication* wallpaperApplication; - private: - - void initEGL(); - void finishEGL(); - struct { EGLDisplay display = nullptr; EGLConfig config = nullptr; @@ -97,6 +98,11 @@ namespace WallpaperEngine::Render::Drivers PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC eglCreatePlatformWindowSurfaceEXT = nullptr; } eglContext; + private: + + void initEGL(); + void finishEGL(); + uint32_t m_frameCounter; std::chrono::high_resolution_clock::time_point renderStart = std::chrono::high_resolution_clock::now();