decompose wl_backend.c: extract wl_shm.c
This commit is contained in:
parent
e1c221948c
commit
5e5e4dbd02
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) */
|
||||
/* ================================================================== */
|
||||
|
|
|
|||
|
|
@ -0,0 +1,193 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wayland-server-core.h>
|
||||
#include <wlr/types/wlr_scene.h>
|
||||
#include <wlr/types/wlr_buffer.h>
|
||||
#include <wlr/interfaces/wlr_buffer.h>
|
||||
#include <libdrm/drm_fourcc.h>
|
||||
#include <pixman.h>
|
||||
#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 */
|
||||
}
|
||||
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue