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 ())
{
this->m_driver.makeCurrent(cur.first);
#if !NDEBUG
std::string str = "Rendering to output " + cur.first;

View File

@ -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
}

View File

@ -2,6 +2,7 @@
#include <glm/vec4.hpp>
#include <glm/vec2.hpp>
#include <string>
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;
};
}

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->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);
@ -269,37 +305,7 @@ CWaylandOpenGLDriver::CWaylandOpenGLDriver(const char* windowTitle, CApplication
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<CLayerSurface>(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;
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 <iostream>
void CWaylandOpenGLDriver::makeCurrent() const {
if (eglMakeCurrent(eglContext.display, waylandContext.layerSurface.eglSurface, waylandContext.layerSurface.eglSurface, eglContext.context) == EGL_FALSE) {
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";
}
}
}

View File

@ -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<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
@ -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<std::unique_ptr<SWaylandOutput>> 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();