From 5e5e4dbd02d6108d07decf293c1e9af81d34e3e9 Mon Sep 17 00:00:00 2001 From: Window Maker Date: Tue, 2 Jun 2026 12:03:25 +0200 Subject: [PATCH] decompose wl_backend.c: extract wl_shm.c --- src/Makefile.am | 3 +- src/backend/wayland/wl_backend.c | 180 ---------------------------- src/backend/wayland/wl_shm.c | 193 +++++++++++++++++++++++++++++++ src/backend/wayland/wl_types.h | 4 + 4 files changed, 199 insertions(+), 181 deletions(-) create mode 100644 src/backend/wayland/wl_shm.c diff --git a/src/Makefile.am b/src/Makefile.am index e56291c..6d714fb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -175,7 +175,8 @@ wmaker_SOURCES += \ backend/wayland/wl_extensions.c \ backend/wayland/wl_events.c \ backend/wayland/wl_focus.c \ - backend/wayland/wl_screen.c + backend/wayland/wl_screen.c \ + backend/wayland/wl_shm.c endif if USE_NESTED_FUNC diff --git a/src/backend/wayland/wl_backend.c b/src/backend/wayland/wl_backend.c index 12afab5..d5a5ce5 100644 --- a/src/backend/wayland/wl_backend.c +++ b/src/backend/wayland/wl_backend.c @@ -3320,186 +3320,6 @@ wl_event_loop_terminate(void) } } -/* ================================================================== */ -/* Phase 29: WM-owned SHM surfaces (pixman rendering → wlroots scene) */ -/* ================================================================== */ - -/* - * wm_shm_surface — a compositor-owned pixel buffer that plugs into the - * wlroots scene graph. - * - * Memory layout: - * wm_shm_surface embeds a wlr_buffer so wlroots can reference-count and - * upload its pixels as a GPU texture. The pixel array (ARGB8888) is - * malloc'd and wrapped by a pixman_image_t for drawing. - * - * Lifecycle: - * wm_shm_surface_create — alloc + pixman init - * wm_shm_surface_fill — draw into the pixman image (no upload yet) - * wm_shm_surface_commit — create/reposition the wlr_scene_buffer node - * wm_shm_surface_destroy — tear down scene node + drop wlr_buffer ref - * (shm_buf_destroy frees memory when ref = 0) - * - * Update model (Phase 29): surfaces are static after first commit. - * A re-draw path (drop + recreate scene node) will be added in Phase 30 - * once the dock and title-bar code drives it. - */ - -/* struct wm_shm_surface now in wl_types.h */ - -/* ---------- wlr_buffer implementation -------------------------------- */ - -static void -shm_buf_destroy(struct wlr_buffer *buf) -{ - struct wm_shm_surface *s = wl_container_of(buf, s, wlr_buf); - if (s->image) - pixman_image_unref(s->image); - free(s->data); - free(s); -} - -static bool -shm_buf_begin_data_ptr(struct wlr_buffer *buf, uint32_t flags, - void **out_data, uint32_t *out_fmt, size_t *out_stride) -{ - struct wm_shm_surface *s = wl_container_of(buf, s, wlr_buf); - (void)flags; - *out_data = s->data; - *out_fmt = DRM_FORMAT_ARGB8888; - *out_stride = s->stride; - return true; -} - -static void -shm_buf_end_data_ptr(struct wlr_buffer *buf) -{ - (void)buf; -} - -static const struct wlr_buffer_impl wm_shm_buf_impl = { - .destroy = shm_buf_destroy, - .begin_data_ptr_access = shm_buf_begin_data_ptr, - .end_data_ptr_access = shm_buf_end_data_ptr, -}; - -/* ---------- surface API ---------------------------------------------- */ - -struct wm_shm_surface * -wm_shm_surface_create(int width, int height) -{ - if (width <= 0 || height <= 0) - return NULL; - - struct wm_shm_surface *s = calloc(1, sizeof(*s)); - if (!s) - return NULL; - - s->width = width; - s->height = height; - s->stride = (size_t)width * 4; - s->data = calloc(1, (size_t)height * s->stride); - if (!s->data) { - free(s); - return NULL; - } - - /* wlr_buffer init — producer holds one reference */ - wlr_buffer_init(&s->wlr_buf, &wm_shm_buf_impl, width, height); - - /* pixman image wrapping the same memory */ - s->image = pixman_image_create_bits(PIXMAN_a8r8g8b8, - width, height, - (uint32_t *)s->data, - (int)s->stride); - if (!s->image) { - /* wlr_buffer_drop triggers shm_buf_destroy → frees data + s */ - wlr_buffer_drop(&s->wlr_buf); - return NULL; - } - - return s; -} - -/* - * Fill a rectangle with a solid ARGB colour. - * argb: 0xAARRGGBB — e.g. 0xFF4080C0 for opaque steel-blue. - */ -void -wm_shm_surface_fill(struct wm_shm_surface *s, - int x, int y, int w, int h, - uint32_t argb) -{ - if (!s || !s->image) - return; - /* clamp to surface bounds */ - if (x < 0) { w += x; x = 0; } - if (y < 0) { h += y; y = 0; } - if (x + w > s->width) w = s->width - x; - if (y + h > s->height) h = s->height - y; - if (w <= 0 || h <= 0) - return; - - pixman_color_t c = { - .alpha = (uint16_t)(((argb >> 24) & 0xff) * 0x0101), - .red = (uint16_t)(((argb >> 16) & 0xff) * 0x0101), - .green = (uint16_t)(((argb >> 8) & 0xff) * 0x0101), - .blue = (uint16_t)(((argb >> 0) & 0xff) * 0x0101), - }; - pixman_image_t *fill = pixman_image_create_solid_fill(&c); - if (!fill) - return; - pixman_image_composite32(PIXMAN_OP_SRC, fill, NULL, s->image, - 0, 0, 0, 0, x, y, w, h); - pixman_image_unref(fill); -} - -/* - * Commit the surface to the scene graph. - * - * parent — scene-graph parent node (e.g. &wl_state.scene->tree.node) - * x, y — position in the compositor coordinate space - * - * First call creates the scene_buffer node; subsequent calls just - * reposition it (pixel updates are uploaded lazily by wlroots on the - * next wlr_scene_output_commit). - */ -void -wm_shm_surface_commit(struct wm_shm_surface *s, - struct wlr_scene_tree *parent, - int x, int y) -{ - if (!s) - return; - if (!s->scene_buf) { - s->scene_buf = wlr_scene_buffer_create(parent, &s->wlr_buf); - if (!s->scene_buf) { - wwarning("wm_shm_surface_commit: wlr_scene_buffer_create failed"); - return; - } - wwarning("wl_backend: SHM surface %dx%d committed to scene at %d,%d", - s->width, s->height, x, y); - } - wlr_scene_node_set_position(&s->scene_buf->node, x, y); -} - -/* - * Destroy a surface and remove it from the scene graph. - * After this call s is invalid — the memory is freed asynchronously - * by shm_buf_destroy once the scene node releases its lock. - */ -void -wm_shm_surface_destroy(struct wm_shm_surface *s) -{ - if (!s) - return; - if (s->scene_buf) { - wlr_scene_node_destroy(&s->scene_buf->node); - s->scene_buf = NULL; - } - wlr_buffer_drop(&s->wlr_buf); /* producer done; shm_buf_destroy frees s */ -} - /* ================================================================== */ /* Phase 30: WM dock panel (layer-anchored, pixman-rendered) */ /* ================================================================== */ diff --git a/src/backend/wayland/wl_shm.c b/src/backend/wayland/wl_shm.c new file mode 100644 index 0000000..547aa16 --- /dev/null +++ b/src/backend/wayland/wl_shm.c @@ -0,0 +1,193 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include "wl_types.h" + +/* ================================================================== */ +/* Phase 29: WM-owned SHM surfaces (pixman rendering → wlroots scene) */ +/* ================================================================== */ + +/* + * wm_shm_surface — a compositor-owned pixel buffer that plugs into the + * wlroots scene graph. + * + * Memory layout: + * wm_shm_surface embeds a wlr_buffer so wlroots can reference-count and + * upload its pixels as a GPU texture. The pixel array (ARGB8888) is + * malloc'd and wrapped by a pixman_image_t for drawing. + * + * Lifecycle: + * wm_shm_surface_create — alloc + pixman init + * wm_shm_surface_fill — draw into the pixman image (no upload yet) + * wm_shm_surface_commit — create/reposition the wlr_scene_buffer node + * wm_shm_surface_destroy — tear down scene node + drop wlr_buffer ref + * (shm_buf_destroy frees memory when ref = 0) + * + * Update model (Phase 29): surfaces are static after first commit. + * A re-draw path (drop + recreate scene node) will be added in Phase 30 + * once the dock and title-bar code drives it. + */ + +/* struct wm_shm_surface now in wl_types.h */ + +/* ---------- wlr_buffer implementation -------------------------------- */ + +void +shm_buf_destroy(struct wlr_buffer *buf) +{ + struct wm_shm_surface *s = wl_container_of(buf, s, wlr_buf); + if (s->image) + pixman_image_unref(s->image); + free(s->data); + free(s); +} + +bool +shm_buf_begin_data_ptr(struct wlr_buffer *buf, uint32_t flags, + void **out_data, uint32_t *out_fmt, size_t *out_stride) +{ + struct wm_shm_surface *s = wl_container_of(buf, s, wlr_buf); + (void)flags; + *out_data = s->data; + *out_fmt = DRM_FORMAT_ARGB8888; + *out_stride = s->stride; + return true; +} + +void +shm_buf_end_data_ptr(struct wlr_buffer *buf) +{ + (void)buf; +} + +const struct wlr_buffer_impl wm_shm_buf_impl = { + .destroy = shm_buf_destroy, + .begin_data_ptr_access = shm_buf_begin_data_ptr, + .end_data_ptr_access = shm_buf_end_data_ptr, +}; + +/* ---------- surface API ---------------------------------------------- */ + +struct wm_shm_surface * +wm_shm_surface_create(int width, int height) +{ + if (width <= 0 || height <= 0) + return NULL; + + struct wm_shm_surface *s = calloc(1, sizeof(*s)); + if (!s) + return NULL; + + s->width = width; + s->height = height; + s->stride = (size_t)width * 4; + s->data = calloc(1, (size_t)height * s->stride); + if (!s->data) { + free(s); + return NULL; + } + + /* wlr_buffer init — producer holds one reference */ + wlr_buffer_init(&s->wlr_buf, &wm_shm_buf_impl, width, height); + + /* pixman image wrapping the same memory */ + s->image = pixman_image_create_bits(PIXMAN_a8r8g8b8, + width, height, + (uint32_t *)s->data, + (int)s->stride); + if (!s->image) { + /* wlr_buffer_drop triggers shm_buf_destroy → frees data + s */ + wlr_buffer_drop(&s->wlr_buf); + return NULL; + } + + return s; +} + +/* + * Fill a rectangle with a solid ARGB colour. + * argb: 0xAARRGGBB — e.g. 0xFF4080C0 for opaque steel-blue. + */ +void +wm_shm_surface_fill(struct wm_shm_surface *s, + int x, int y, int w, int h, + uint32_t argb) +{ + if (!s || !s->image) + return; + /* clamp to surface bounds */ + if (x < 0) { w += x; x = 0; } + if (y < 0) { h += y; y = 0; } + if (x + w > s->width) w = s->width - x; + if (y + h > s->height) h = s->height - y; + if (w <= 0 || h <= 0) + return; + + pixman_color_t c = { + .alpha = (uint16_t)(((argb >> 24) & 0xff) * 0x0101), + .red = (uint16_t)(((argb >> 16) & 0xff) * 0x0101), + .green = (uint16_t)(((argb >> 8) & 0xff) * 0x0101), + .blue = (uint16_t)(((argb >> 0) & 0xff) * 0x0101), + }; + pixman_image_t *fill = pixman_image_create_solid_fill(&c); + if (!fill) + return; + pixman_image_composite32(PIXMAN_OP_SRC, fill, NULL, s->image, + 0, 0, 0, 0, x, y, w, h); + pixman_image_unref(fill); +} + +/* + * Commit the surface to the scene graph. + * + * parent — scene-graph parent node (e.g. &wl_state.scene->tree.node) + * x, y — position in the compositor coordinate space + * + * First call creates the scene_buffer node; subsequent calls just + * reposition it (pixel updates are uploaded lazily by wlroots on the + * next wlr_scene_output_commit). + */ +void +wm_shm_surface_commit(struct wm_shm_surface *s, + struct wlr_scene_tree *parent, + int x, int y) +{ + if (!s) + return; + if (!s->scene_buf) { + s->scene_buf = wlr_scene_buffer_create(parent, &s->wlr_buf); + if (!s->scene_buf) { + wwarning("wm_shm_surface_commit: wlr_scene_buffer_create failed"); + return; + } + wwarning("wl_backend: SHM surface %dx%d committed to scene at %d,%d", + s->width, s->height, x, y); + } + wlr_scene_node_set_position(&s->scene_buf->node, x, y); +} + +/* + * Destroy a surface and remove it from the scene graph. + * After this call s is invalid — the memory is freed asynchronously + * by shm_buf_destroy once the scene node releases its lock. + */ +void +wm_shm_surface_destroy(struct wm_shm_surface *s) +{ + if (!s) + return; + if (s->scene_buf) { + wlr_scene_node_destroy(&s->scene_buf->node); + s->scene_buf = NULL; + } + wlr_buffer_drop(&s->wlr_buf); /* producer done; shm_buf_destroy frees s */ +} + diff --git a/src/backend/wayland/wl_types.h b/src/backend/wayland/wl_types.h index 0eb1213..54c50b8 100644 --- a/src/backend/wayland/wl_types.h +++ b/src/backend/wayland/wl_types.h @@ -548,3 +548,7 @@ void wl_screen_open(WScreen *scr); void wl_screen_close(WScreen *scr); int wl_screen_init_display(WScreen *scr, int screen_number); int wl_show_crash_dialog(int sig); +struct wm_shm_surface *wm_shm_surface_create(int width, int height); +void wm_shm_surface_fill(struct wm_shm_surface *s, int x, int y, int w, int h, uint32_t argb); +void wm_shm_surface_commit(struct wm_shm_surface *s, struct wlr_scene_tree *parent, int x, int y); +void wm_shm_surface_destroy(struct wm_shm_surface *s);