add surface damage

Signed-off-by: Slendi <slendi@socopon.com>
This commit is contained in:
2025-09-30 22:30:39 +03:00
parent f9dff4265a
commit c6365c0cc1
3 changed files with 97 additions and 0 deletions

View File

@@ -25,6 +25,7 @@ pkg_check_modules(WLROOTS REQUIRED IMPORTED_TARGET wlroots-0.20)
pkg_check_modules(XKBCOMMON REQUIRED IMPORTED_TARGET xkbcommon)
pkg_check_modules(OPENXR REQUIRED IMPORTED_TARGET openxr)
pkg_check_modules(LUA REQUIRED IMPORTED_TARGET lua)
pkg_check_modules(PIXMAN REQUIRED IMPORTED_TARGET pixman-1)
find_program(WAYLAND_SCANNER_EXECUTABLE wayland-scanner REQUIRED)
message(STATUS "Found wayland-scanner at ${WAYLAND_SCANNER_EXECUTABLE}")
@@ -67,6 +68,7 @@ target_link_libraries(${PROJECT_NAME} PUBLIC
PkgConfig::WLROOTS
PkgConfig::OPENXR
PkgConfig::LUA
PkgConfig::PIXMAN
raylib
)

View File

@@ -198,6 +198,7 @@ typedef struct LunarWM {
struct wlr_allocator *allocator;
struct wlr_compositor *compositor;
struct wl_listener new_surface_listener;
struct wlr_subcompositor *subcompositor;
struct wlr_data_device_manager *data_device_manager;

View File

@@ -6,6 +6,7 @@
#include "raylib.h"
#include "vec.h"
#include <pixman.h>
#include <wlr/render/color.h>
#include <wlr/render/pass.h>
@@ -37,6 +38,89 @@ static inline SphericalCoord get_forward_spherical_with_nearest(
return Vector3ToSpherical(vec);
}
struct SurfaceDamageListener {
struct wl_listener client_commit;
struct wl_listener destroy;
};
static void surface_damage_client_commit(struct wl_listener *listener, void *data)
{
(void)listener;
struct wlr_surface *surface = data;
if (!surface) {
return;
}
if (!wlr_surface_state_has_buffer(&surface->pending)) {
return;
}
if (pixman_region32_not_empty(&surface->pending.surface_damage)
|| pixman_region32_not_empty(&surface->pending.buffer_damage)) {
return;
}
int surface_width = surface->pending.width > 0 ? surface->pending.width
: surface->current.width;
int surface_height = surface->pending.height > 0 ? surface->pending.height
: surface->current.height;
int buffer_width = surface->pending.buffer_width > 0
? surface->pending.buffer_width
: surface->current.buffer_width;
int buffer_height = surface->pending.buffer_height > 0
? surface->pending.buffer_height
: surface->current.buffer_height;
if (surface_width <= 0 || surface_height <= 0 || buffer_width <= 0
|| buffer_height <= 0) {
return;
}
pixman_region32_union_rect(&surface->pending.surface_damage,
&surface->pending.surface_damage, 0, 0, surface_width, surface_height);
pixman_region32_union_rect(&surface->pending.buffer_damage,
&surface->pending.buffer_damage, 0, 0, buffer_width, buffer_height);
}
static void surface_damage_destroy(struct wl_listener *listener, void *data)
{
(void)data;
struct SurfaceDamageListener *hook
= wl_container_of(listener, hook, destroy);
wl_list_remove(&hook->client_commit.link);
wl_list_remove(&hook->destroy.link);
free(hook);
}
static void surface_damage_track(struct wlr_surface *surface)
{
if (!surface) {
return;
}
struct SurfaceDamageListener *hook = calloc(1, sizeof(*hook));
if (!hook) {
wlr_log(WLR_ERROR, "Failed to allocate surface damage listener");
return;
}
hook->client_commit.notify = surface_damage_client_commit;
wl_signal_add(&surface->events.client_commit, &hook->client_commit);
hook->destroy.notify = surface_damage_destroy;
wl_signal_add(&surface->events.destroy, &hook->destroy);
}
static void compositor_new_surface_notify(
struct wl_listener *listener, void *data)
{
(void)listener;
struct wlr_surface *surface = data;
if (!surface) {
return;
}
surface_damage_track(surface);
}
struct ExternalTexturePipeline {
bool attempted_init;
bool ready;
@@ -1776,6 +1860,10 @@ bool LunarWM_wayland_init(LunarWM *this)
wlr_log(WLR_ERROR, "Failed to create compositor");
return false;
}
this->wayland.new_surface_listener.notify = compositor_new_surface_notify;
wl_signal_add(&this->wayland.compositor->events.new_surface,
&this->wayland.new_surface_listener);
this->wayland.subcompositor
= wlr_subcompositor_create(this->wayland.display);
@@ -1853,6 +1941,12 @@ void LunarWM_wayland_cleanup(LunarWM *this)
this->wayland.new_output_listener.notify = NULL;
}
if (this->wayland.new_surface_listener.link.prev
|| this->wayland.new_surface_listener.link.next) {
wl_list_remove(&this->wayland.new_surface_listener.link);
this->wayland.new_surface_listener.notify = NULL;
}
if (this->wayland.v_outputs) {
for (size_t i = 0; i < vector_size(this->wayland.v_outputs); ++i) {
destroy_output(this->wayland.v_outputs[i]);