|
|
|
|
@@ -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]);
|
|
|
|
|
|