render: replace EGL/OpenGL pipeline with wl_shm shared memory
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: If73c9ac16c2a31e211c2cda2b0ce2c586a6a6964
This commit is contained in:
parent
58861c1ea5
commit
a838f86731
3 changed files with 42 additions and 30 deletions
1
include/chroma.h
vendored
1
include/chroma.h
vendored
|
|
@ -212,6 +212,7 @@ int chroma_surface_create(chroma_state_t *state, chroma_output_t *output);
|
||||||
void chroma_surface_destroy(chroma_output_t *output);
|
void chroma_surface_destroy(chroma_output_t *output);
|
||||||
int chroma_buffer_create(chroma_state_t *state, chroma_output_t *output);
|
int chroma_buffer_create(chroma_state_t *state, chroma_output_t *output);
|
||||||
void chroma_buffer_destroy(chroma_output_t *output);
|
void chroma_buffer_destroy(chroma_output_t *output);
|
||||||
|
void chroma_buffer_unmap(chroma_output_t *output);
|
||||||
int chroma_render_wallpaper(chroma_state_t *state, chroma_output_t *output);
|
int chroma_render_wallpaper(chroma_state_t *state, chroma_output_t *output);
|
||||||
|
|
||||||
// Layer shell functions
|
// Layer shell functions
|
||||||
|
|
|
||||||
|
|
@ -137,9 +137,7 @@ static int assign_wallpaper_to_output(chroma_state_t *state,
|
||||||
old_filter_quality != output->filter_quality ||
|
old_filter_quality != output->filter_quality ||
|
||||||
old_anchor != output->anchor || old_anchor_x != output->anchor_x ||
|
old_anchor != output->anchor || old_anchor_x != output->anchor_x ||
|
||||||
old_anchor_y != output->anchor_y)) {
|
old_anchor_y != output->anchor_y)) {
|
||||||
chroma_log("DEBUG",
|
chroma_log("DEBUG", "Configuration changed for output %u", output->id);
|
||||||
"Configuration changed for output %u",
|
|
||||||
output->id);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
output->config_loaded = false;
|
output->config_loaded = false;
|
||||||
|
|
@ -158,8 +156,8 @@ static int assign_wallpaper_to_output(chroma_state_t *state,
|
||||||
// Render wallpaper
|
// Render wallpaper
|
||||||
int ret = chroma_render_wallpaper(state, output);
|
int ret = chroma_render_wallpaper(state, output);
|
||||||
if (ret != CHROMA_OK) {
|
if (ret != CHROMA_OK) {
|
||||||
chroma_log("ERROR", "Failed to render wallpaper for output %u: %s", output->id,
|
chroma_log("ERROR", "Failed to render wallpaper for output %u: %s",
|
||||||
chroma_error_string(ret));
|
output->id, chroma_error_string(ret));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
63
src/render.c
63
src/render.c
|
|
@ -33,6 +33,22 @@ void chroma_buffer_destroy(chroma_output_t *output) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unmap client-side memory while keeping the wl_buffer proxy alive.
|
||||||
|
// The compositor retains its own fd reference and mapping, so the
|
||||||
|
// wallpaper remains visible after this call.
|
||||||
|
void chroma_buffer_unmap(chroma_output_t *output) {
|
||||||
|
if (!output || !output->shm_data) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (munmap(output->shm_data, output->shm_size) < 0) {
|
||||||
|
chroma_log("WARN", "munmap failed: %s", strerror(errno));
|
||||||
|
}
|
||||||
|
output->shm_data = NULL;
|
||||||
|
output->shm_size = 0;
|
||||||
|
output->shm_stride = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Create shared memory buffer for an output
|
// Create shared memory buffer for an output
|
||||||
int chroma_buffer_create(chroma_state_t *state, chroma_output_t *output) {
|
int chroma_buffer_create(chroma_state_t *state, chroma_output_t *output) {
|
||||||
if (!state || !output || !state->shm) {
|
if (!state || !output || !state->shm) {
|
||||||
|
|
@ -80,8 +96,7 @@ int chroma_buffer_create(chroma_state_t *state, chroma_output_t *output) {
|
||||||
// Fill with black
|
// Fill with black
|
||||||
memset(data, 0, size);
|
memset(data, 0, size);
|
||||||
|
|
||||||
struct wl_shm_pool *pool =
|
struct wl_shm_pool *pool = wl_shm_create_pool(state->shm, fd, (int32_t)size);
|
||||||
wl_shm_create_pool(state->shm, fd, (int32_t)size);
|
|
||||||
if (!pool) {
|
if (!pool) {
|
||||||
chroma_log("ERROR", "wl_shm_create_pool failed");
|
chroma_log("ERROR", "wl_shm_create_pool failed");
|
||||||
munmap(data, size);
|
munmap(data, size);
|
||||||
|
|
@ -109,8 +124,7 @@ int chroma_buffer_create(chroma_state_t *state, chroma_output_t *output) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sample a pixel from image data (grayscale, grayscale+alpha, RGB, or RGBA)
|
// Sample a pixel from image data (grayscale, grayscale+alpha, RGB, or RGBA)
|
||||||
static inline uint32_t sample_pixel(const chroma_image_t *image, int x,
|
static inline uint32_t sample_pixel(const chroma_image_t *image, int x, int y) {
|
||||||
int y) {
|
|
||||||
if (!image || !image->data || x < 0 || y < 0 || x >= image->width ||
|
if (!image || !image->data || x < 0 || y < 0 || x >= image->width ||
|
||||||
y >= image->height) {
|
y >= image->height) {
|
||||||
return 0xFF000000; // black with full alpha
|
return 0xFF000000; // black with full alpha
|
||||||
|
|
@ -147,8 +161,7 @@ static inline uint32_t sample_pixel(const chroma_image_t *image, int x,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw scaled image into the shared memory buffer
|
// Draw scaled image into the shared memory buffer
|
||||||
static void draw_scaled_image(chroma_output_t *output,
|
static void draw_scaled_image(chroma_output_t *output, chroma_image_t *image) {
|
||||||
chroma_image_t *image) {
|
|
||||||
if (!output || !image || !output->shm_data) {
|
if (!output || !image || !output->shm_data) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -263,10 +276,8 @@ static void draw_scaled_image(chroma_output_t *output,
|
||||||
default: {
|
default: {
|
||||||
if (img_w <= out_w && img_h <= out_h) {
|
if (img_w <= out_w && img_h <= out_h) {
|
||||||
// Image fits entirely - position with anchor
|
// Image fits entirely - position with anchor
|
||||||
float offset_x =
|
float offset_x = (anchor_x / 100.0f) * ((float)out_w - (float)img_w);
|
||||||
(anchor_x / 100.0f) * ((float)out_w - (float)img_w);
|
float offset_y = (anchor_y / 100.0f) * ((float)out_h - (float)img_h);
|
||||||
float offset_y =
|
|
||||||
(anchor_y / 100.0f) * ((float)out_h - (float)img_h);
|
|
||||||
|
|
||||||
for (int y = 0; y < img_h; y++) {
|
for (int y = 0; y < img_h; y++) {
|
||||||
for (int x = 0; x < img_w; x++) {
|
for (int x = 0; x < img_w; x++) {
|
||||||
|
|
@ -279,10 +290,8 @@ static void draw_scaled_image(chroma_output_t *output,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Image is larger than output - clip with anchor
|
// Image is larger than output - clip with anchor
|
||||||
float src_offset_x =
|
float src_offset_x = (anchor_x / 100.0f) * ((float)img_w - (float)out_w);
|
||||||
(anchor_x / 100.0f) * ((float)img_w - (float)out_w);
|
float src_offset_y = (anchor_y / 100.0f) * ((float)img_h - (float)out_h);
|
||||||
float src_offset_y =
|
|
||||||
(anchor_y / 100.0f) * ((float)img_h - (float)out_h);
|
|
||||||
|
|
||||||
if (src_offset_x < 0)
|
if (src_offset_x < 0)
|
||||||
src_offset_x = 0;
|
src_offset_x = 0;
|
||||||
|
|
@ -333,19 +342,16 @@ int chroma_surface_create(chroma_state_t *state, chroma_output_t *output) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure layer surface
|
// Configure layer surface
|
||||||
zwlr_layer_surface_v1_set_size(output->layer_surface,
|
zwlr_layer_surface_v1_set_size(output->layer_surface, (uint32_t)output->width,
|
||||||
(uint32_t)output->width,
|
|
||||||
(uint32_t)output->height);
|
(uint32_t)output->height);
|
||||||
zwlr_layer_surface_v1_set_anchor(
|
zwlr_layer_surface_v1_set_anchor(output->layer_surface,
|
||||||
output->layer_surface,
|
ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
|
||||||
ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
|
ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
|
||||||
ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
|
ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM |
|
||||||
ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM |
|
ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT);
|
||||||
ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT);
|
|
||||||
zwlr_layer_surface_v1_set_exclusive_zone(output->layer_surface, -1);
|
zwlr_layer_surface_v1_set_exclusive_zone(output->layer_surface, -1);
|
||||||
zwlr_layer_surface_v1_set_keyboard_interactivity(
|
zwlr_layer_surface_v1_set_keyboard_interactivity(
|
||||||
output->layer_surface,
|
output->layer_surface, ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE);
|
||||||
ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE);
|
|
||||||
|
|
||||||
// Add layer surface listener
|
// Add layer surface listener
|
||||||
zwlr_layer_surface_v1_add_listener(
|
zwlr_layer_surface_v1_add_listener(
|
||||||
|
|
@ -417,11 +423,18 @@ int chroma_render_wallpaper(chroma_state_t *state, chroma_output_t *output) {
|
||||||
wl_surface_damage_buffer(output->surface, 0, 0, output->width,
|
wl_surface_damage_buffer(output->surface, 0, 0, output->width,
|
||||||
output->height);
|
output->height);
|
||||||
wl_surface_commit(output->surface);
|
wl_surface_commit(output->surface);
|
||||||
wl_display_flush(state->display);
|
if (wl_display_flush(state->display) < 0) {
|
||||||
|
chroma_log("ERROR", "Failed to flush Wayland display for output %u: %s",
|
||||||
|
output->id, strerror(errno));
|
||||||
|
return CHROMA_ERROR_WAYLAND;
|
||||||
|
}
|
||||||
|
|
||||||
chroma_log("INFO", "Rendered wallpaper to output %u (%dx%d)", output->id,
|
chroma_log("INFO", "Rendered wallpaper to output %u (%dx%d)", output->id,
|
||||||
output->width, output->height);
|
output->width, output->height);
|
||||||
|
|
||||||
|
// Unmap client-side memory; compositor keeps its own fd reference
|
||||||
|
chroma_buffer_unmap(output);
|
||||||
|
|
||||||
// Release image reference and free CPU data if no longer needed
|
// Release image reference and free CPU data if no longer needed
|
||||||
if (output->image) {
|
if (output->image) {
|
||||||
chroma_image_t *image = output->image;
|
chroma_image_t *image = output->image;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue