move ls to a class

This commit is contained in:
vaxerski 2023-04-20 22:02:47 +01:00
parent c84ec9aedd
commit ce2dc8395f
5 changed files with 110 additions and 84 deletions

View File

@ -29,6 +29,8 @@ namespace WallpaperEngine::Render
for (const auto& cur : this->m_output->getViewports ()) for (const auto& cur : this->m_output->getViewports ())
{ {
this->m_driver.makeCurrent(cur.first);
#if !NDEBUG #if !NDEBUG
std::string str = "Rendering to output " + cur.first; std::string str = "Rendering to output " + cur.first;

View File

@ -6,6 +6,6 @@ void CVideoDriver::dispatchEventQueue() const {
// intentionally left blank // intentionally left blank
} }
void CVideoDriver::makeCurrent() const { void CVideoDriver::makeCurrent(const std::string& outputName) const {
// intentionally left blank // intentionally left blank
} }

View File

@ -2,6 +2,7 @@
#include <glm/vec4.hpp> #include <glm/vec4.hpp>
#include <glm/vec2.hpp> #include <glm/vec2.hpp>
#include <string>
namespace WallpaperEngine::Render::Drivers namespace WallpaperEngine::Render::Drivers
{ {
@ -55,6 +56,6 @@ namespace WallpaperEngine::Render::Drivers
/** /**
* Wayland only: make EGL current * Wayland only: make EGL current
*/ */
void makeCurrent() const; void makeCurrent(const std::string& outputName) const;
}; };
} }

View File

@ -30,7 +30,8 @@ void mode(void* data, wl_output* output, uint32_t flags, int32_t width, int32_t
PMONITOR->size = {width, height}; PMONITOR->size = {width, height};
PMONITOR->lsSize = {width, height}; PMONITOR->lsSize = {width, height};
PMONITOR->driver->resizeLSSurfaceEGL(); if (PMONITOR->layerSurface.get())
PMONITOR->driver->resizeLSSurfaceEGL(PMONITOR->layerSurface.get());
if (PMONITOR->initialized) if (PMONITOR->initialized)
PMONITOR->driver->wallpaperApplication->getOutput()->reset(); PMONITOR->driver->wallpaperApplication->getOutput()->reset();
@ -47,7 +48,8 @@ void scale(void* data, wl_output* wl_output, int32_t scale) {
PMONITOR->scale = scale; PMONITOR->scale = scale;
PMONITOR->driver->resizeLSSurfaceEGL(); if (PMONITOR->layerSurface.get())
PMONITOR->driver->resizeLSSurfaceEGL(PMONITOR->layerSurface.get());
if (PMONITOR->initialized) if (PMONITOR->initialized)
PMONITOR->driver->wallpaperApplication->getOutput()->reset(); 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) { static void handleLSConfigure(void *data, zwlr_layer_surface_v1 *surface, uint32_t serial, uint32_t w, uint32_t h) {
const auto PDRIVER = (CWaylandOpenGLDriver*)data; const auto PLS = (CLayerSurface*)data;
PDRIVER->waylandContext.layerSurface.size = {w, h}; PLS->size = {w, h};
PDRIVER->resizeLSSurfaceEGL(); PLS->output->driver->resizeLSSurfaceEGL(PLS);
zwlr_layer_surface_v1_ack_configure(surface, serial); zwlr_layer_surface_v1_ack_configure(surface, serial);
} }
static void handleLSClosed(void *data, zwlr_layer_surface_v1 *surface) { static void handleLSClosed(void *data, zwlr_layer_surface_v1 *surface) {
const auto PDRIVER = (CWaylandOpenGLDriver*)data; const auto PLS = (CLayerSurface*)data;
PDRIVER->onLayerClose(); PLS->output->driver->onLayerClose(PLS);
} }
void CWaylandOpenGLDriver::onLayerClose() { void CWaylandOpenGLDriver::onLayerClose(CLayerSurface* layerSurface) {
eglDestroySurface(eglContext.display, waylandContext.layerSurface.eglSurface); eglDestroySurface(eglContext.display, layerSurface->eglSurface);
wl_egl_window_destroy(waylandContext.layerSurface.eglWindow); wl_egl_window_destroy(layerSurface->eglWindow);
zwlr_layer_surface_v1_destroy(waylandContext.layerSurface.layerSurface); zwlr_layer_surface_v1_destroy(layerSurface->layerSurface);
wl_surface_destroy(waylandContext.layerSurface.surface); wl_surface_destroy(layerSurface->surface);
sLog.exception("Compositor closed our LS!"); // todo: handle this? 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) { 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); wl_callback_destroy(cb);
PDRIVER->waylandContext.layerSurface.frameCallback = nullptr; PLS->frameCallback = nullptr;
PDRIVER->wallpaperApplication->renderFrame(); PLS->output->driver->wallpaperApplication->renderFrame();
} }
const struct wl_callback_listener frameListener = { const struct wl_callback_listener frameListener = {
.done = surfaceFrameCallback .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) { CWaylandOpenGLDriver::CWaylandOpenGLDriver(const char* windowTitle, CApplicationContext& context, CWallpaperApplication* app) : m_frameCounter(0) {
wallpaperApplication = app; wallpaperApplication = app;
waylandContext.display = wl_display_connect(NULL); waylandContext.display = wl_display_connect(NULL);
@ -268,38 +304,8 @@ CWaylandOpenGLDriver::CWaylandOpenGLDriver(const char* windowTitle, CApplication
sLog.exception("Failed to get a cursor surface"); sLog.exception("Failed to get a cursor surface");
initEGL(); 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) { const auto PLS = (outputToUse->layerSurface = std::make_unique<CLayerSurface>(this, outputToUse)).get();
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");
}
GLenum result = glewInit (); GLenum result = glewInit ();
@ -346,29 +352,35 @@ void CWaylandOpenGLDriver::hideWindow () {
} }
glm::ivec2 CWaylandOpenGLDriver::getFramebufferSize () const { glm::ivec2 CWaylandOpenGLDriver::getFramebufferSize () const {
return waylandContext.layerSurface.size; return glm::ivec2{0, 0};
} }
void CWaylandOpenGLDriver::swapBuffers () { void CWaylandOpenGLDriver::swapBuffers () {
waylandContext.layerSurface.frameCallback = wl_surface_frame(waylandContext.layerSurface.surface); for (auto& o : m_outputs) {
wl_callback_add_listener(waylandContext.layerSurface.frameCallback, &frameListener, this); if (!o->layerSurface.get())
eglSwapBuffers(eglContext.display, waylandContext.layerSurface.eglSurface); continue;
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);
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() { void CWaylandOpenGLDriver::resizeLSSurfaceEGL(CLayerSurface* layerSurface) {
if (waylandContext.layerSurface.eglWindow) { if (layerSurface->eglWindow) {
waylandContext.layerSurface.output->lsSize = waylandContext.layerSurface.size; 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) { if (layerSurface->frameCallback) {
wl_callback_destroy(waylandContext.layerSurface.frameCallback); wl_callback_destroy(layerSurface->frameCallback);
waylandContext.layerSurface.frameCallback = nullptr; layerSurface->frameCallback = nullptr;
} }
wallpaperApplication->getOutput()->reset(); wallpaperApplication->getOutput()->reset();
@ -387,8 +399,13 @@ GLFWwindow* CWaylandOpenGLDriver::getWindow () {
#include <iostream> #include <iostream>
void CWaylandOpenGLDriver::makeCurrent() const { void CWaylandOpenGLDriver::makeCurrent(const std::string& outputName) const {
if (eglMakeCurrent(eglContext.display, waylandContext.layerSurface.eglSurface, waylandContext.layerSurface.eglSurface, eglContext.context) == EGL_FALSE) { for (auto& o : m_outputs) {
std::cerr << "Couldn't make egl current"; 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";
}
} }
} }

View File

@ -25,6 +25,7 @@ namespace WallpaperEngine::Render::Drivers
{ {
using namespace WallpaperEngine::Application; using namespace WallpaperEngine::Application;
class CWaylandOpenGLDriver; class CWaylandOpenGLDriver;
class CLayerSurface;
struct SWaylandOutput { struct SWaylandOutput {
wl_output* output; wl_output* output;
@ -35,6 +36,21 @@ namespace WallpaperEngine::Render::Drivers
int scale = 1; int scale = 1;
CWaylandOpenGLDriver* driver = nullptr; CWaylandOpenGLDriver* driver = nullptr;
bool initialized = false; bool initialized = false;
std::unique_ptr<CLayerSurface> 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 class CWaylandOpenGLDriver : public CVideoDriver
@ -54,7 +70,7 @@ namespace WallpaperEngine::Render::Drivers
void swapBuffers () override; void swapBuffers () override;
uint32_t getFrameCounter () const override; uint32_t getFrameCounter () const override;
void dispatchEventQueue() const override; void dispatchEventQueue() const override;
void makeCurrent() const; void makeCurrent(const std::string& outputName) const;
GLFWwindow* getWindow (); GLFWwindow* getWindow ();
@ -66,30 +82,15 @@ namespace WallpaperEngine::Render::Drivers
zwlr_layer_shell_v1* layerShell = nullptr; zwlr_layer_shell_v1* layerShell = nullptr;
wl_cursor* pointer = nullptr; wl_cursor* pointer = nullptr;
wl_surface* cursorSurface = 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; } waylandContext;
void onLayerClose(); void onLayerClose(CLayerSurface*);
void resizeLSSurfaceEGL(); void resizeLSSurfaceEGL(CLayerSurface*);
std::vector<std::unique_ptr<SWaylandOutput>> m_outputs; std::vector<std::unique_ptr<SWaylandOutput>> m_outputs;
CWallpaperApplication* wallpaperApplication; CWallpaperApplication* wallpaperApplication;
private:
void initEGL();
void finishEGL();
struct { struct {
EGLDisplay display = nullptr; EGLDisplay display = nullptr;
EGLConfig config = nullptr; EGLConfig config = nullptr;
@ -97,6 +98,11 @@ namespace WallpaperEngine::Render::Drivers
PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC eglCreatePlatformWindowSurfaceEXT = nullptr; PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC eglCreatePlatformWindowSurfaceEXT = nullptr;
} eglContext; } eglContext;
private:
void initEGL();
void finishEGL();
uint32_t m_frameCounter; uint32_t m_frameCounter;
std::chrono::high_resolution_clock::time_point renderStart = std::chrono::high_resolution_clock::now(); std::chrono::high_resolution_clock::time_point renderStart = std::chrono::high_resolution_clock::now();