From 376b3952a0b778edb6e620524072bd887e730fe0 Mon Sep 17 00:00:00 2001 From: Derek Foreman Date: Wed, 3 Jul 2024 13:20:50 -0500 Subject: [PATCH] libweston: Store shm buffer stride in weston_buffer After c08a6ff8 moved attach to the render loop, we have a bad situation when clients delete an attached shm buffer. We try to query the stride at attach time, but the shm_buffer has been destroyed, and we crash. Instead of carefully fixing that, I've instead stored the stride at buffer creation time (as we already do with buffer width and height). This lets attach succeed in the gl-renderer, keeping the old texture data available for any upcoming rendering. Fixes: #927 Signed-off-by: Derek Foreman Tested-by: Connor Abbott --- include/libweston/libweston.h | 1 + libweston/backend-drm/drm.c | 6 ++---- libweston/backend-vnc/vnc.c | 5 +---- libweston/compositor.c | 1 + libweston/noop-renderer.c | 2 +- libweston/pixman-renderer.c | 4 ++-- libweston/renderer-gl/gl-renderer.c | 9 ++++----- libweston/screenshooter.c | 2 +- 8 files changed, 13 insertions(+), 17 deletions(-) diff --git a/include/libweston/libweston.h b/include/libweston/libweston.h index 2593e894..b5dcfc5f 100644 --- a/include/libweston/libweston.h +++ b/include/libweston/libweston.h @@ -1636,6 +1636,7 @@ struct weston_buffer { }; int32_t width, height; + int32_t stride; uint32_t busy_count; uint32_t passive_count; enum { diff --git a/libweston/backend-drm/drm.c b/libweston/backend-drm/drm.c index adf528cc..0342320f 100644 --- a/libweston/backend-drm/drm.c +++ b/libweston/backend-drm/drm.c @@ -649,7 +649,6 @@ cursor_bo_update(struct drm_output *output, struct weston_view *ev) struct gbm_bo *bo = output->gbm_cursor_fb[output->current_cursor]->bo; struct weston_buffer *buffer = ev->surface->buffer_ref.buffer; uint32_t buf[device->cursor_width * device->cursor_height]; - int32_t stride; uint8_t *s; int i; @@ -659,13 +658,12 @@ cursor_bo_update(struct drm_output *output, struct weston_view *ev) memset(buf, 0, sizeof buf); - stride = wl_shm_buffer_get_stride(buffer->shm_buffer); s = wl_shm_buffer_get_data(buffer->shm_buffer); wl_shm_buffer_begin_access(buffer->shm_buffer); for (i = 0; i < buffer->height; i++) memcpy(buf + i * device->cursor_width, - s + i * stride, + s + i * buffer->stride, buffer->width * 4); wl_shm_buffer_end_access(buffer->shm_buffer); @@ -2887,7 +2885,7 @@ drm_writeback_success_screenshot(struct drm_writeback_state *state) src_stride = state->fb->strides[0]; dst = wl_shm_buffer_get_data(buffer->shm_buffer); - dst_stride = wl_shm_buffer_get_stride(buffer->shm_buffer); + dst_stride = buffer->stride; width = state->fb->width; height = state->fb->height; diff --git a/libweston/backend-vnc/vnc.c b/libweston/backend-vnc/vnc.c index 8503e612..10c840e5 100644 --- a/libweston/backend-vnc/vnc.c +++ b/libweston/backend-vnc/vnc.c @@ -539,7 +539,6 @@ vnc_output_update_cursor(struct vnc_output *output) struct weston_buffer *buffer; struct weston_surface *cursor_surface; struct nvnc_fb *fb; - int32_t stride; uint8_t *src, *dst; int i; @@ -556,8 +555,6 @@ vnc_output_update_cursor(struct vnc_output *output) cursor_surface = output->cursor_surface; buffer = cursor_surface->buffer_ref.buffer; - stride = wl_shm_buffer_get_stride(buffer->shm_buffer); - fb = nvnc_fb_new(buffer->width, buffer->height, DRM_FORMAT_ARGB8888, buffer->width); assert(fb); @@ -567,7 +564,7 @@ vnc_output_update_cursor(struct vnc_output *output) wl_shm_buffer_begin_access(buffer->shm_buffer); for (i = 0; i < buffer->height; i++) - memcpy(dst + i * 4 * buffer->width, src + i * stride, + memcpy(dst + i * 4 * buffer->width, src + i * buffer->stride, 4 * buffer->width); wl_shm_buffer_end_access(buffer->shm_buffer); diff --git a/libweston/compositor.c b/libweston/compositor.c index 2a3aad95..4d18c205 100644 --- a/libweston/compositor.c +++ b/libweston/compositor.c @@ -2839,6 +2839,7 @@ weston_buffer_from_resource(struct weston_compositor *ec, buffer->shm_buffer = shm; buffer->width = wl_shm_buffer_get_width(shm); buffer->height = wl_shm_buffer_get_height(shm); + buffer->stride = wl_shm_buffer_get_stride(shm); buffer->buffer_origin = ORIGIN_TOP_LEFT; /* wl_shm might create a buffer with an unknown format, so check * and reject */ diff --git a/libweston/noop-renderer.c b/libweston/noop-renderer.c index cde9e953..06b4aebc 100644 --- a/libweston/noop-renderer.c +++ b/libweston/noop-renderer.c @@ -95,7 +95,7 @@ noop_renderer_attach(struct weston_paint_node *pnode) shm_buffer = buffer->shm_buffer; data = wl_shm_buffer_get_data(shm_buffer); - stride = wl_shm_buffer_get_stride(shm_buffer); + stride = buffer->stride; height = buffer->height; size = stride * height; diff --git a/libweston/pixman-renderer.c b/libweston/pixman-renderer.c index 4ba336a6..141480d1 100644 --- a/libweston/pixman-renderer.c +++ b/libweston/pixman-renderer.c @@ -594,7 +594,7 @@ pixman_renderer_do_capture(struct weston_buffer *into, pixman_image_t *from) dest = pixman_image_create_bits(into->pixel_format->pixman_format, into->width, into->height, wl_shm_buffer_get_data(shm), - wl_shm_buffer_get_stride(shm)); + into->stride); abort_oom_if_null(dest); pixman_image_composite32(PIXMAN_OP_SRC, from, NULL /* mask */, dest, @@ -798,7 +798,7 @@ pixman_renderer_attach_internal(struct weston_surface *es, ps->image = pixman_image_create_bits(pixel_info->pixman_format, buffer->width, buffer->height, wl_shm_buffer_get_data(shm_buffer), - wl_shm_buffer_get_stride(shm_buffer)); + buffer->stride); ps->buffer_destroy_listener.notify = buffer_state_handle_buffer_destroy; diff --git a/libweston/renderer-gl/gl-renderer.c b/libweston/renderer-gl/gl-renderer.c index daf9895d..62ab128c 100644 --- a/libweston/renderer-gl/gl-renderer.c +++ b/libweston/renderer-gl/gl-renderer.c @@ -760,7 +760,7 @@ gl_renderer_do_capture(struct gl_renderer *gr, struct weston_buffer *into, wl_shm_buffer_begin_access(shm); ret = gl_renderer_do_read_pixels(gr, fmt, wl_shm_buffer_get_data(shm), - wl_shm_buffer_get_stride(shm), rect); + into->stride, rect); wl_shm_buffer_end_access(shm); @@ -980,7 +980,7 @@ gl_renderer_do_capture_tasks(struct gl_renderer *gr, continue; } - if (wl_shm_buffer_get_stride(buffer->shm_buffer) % 4 != 0) { + if (buffer->stride % 4 != 0) { weston_capture_task_retire_failed(ct, "GL: buffer stride not multiple of 4"); continue; } @@ -2576,7 +2576,6 @@ gl_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer) struct gl_renderer *gr = get_renderer(ec); struct gl_surface_state *gs = get_surface_state(es); struct gl_buffer_state *gb; - struct wl_shm_buffer *shm_buffer = buffer->shm_buffer; struct weston_buffer *old_buffer = gs->buffer_ref.buffer; GLenum gl_format[3] = {0, 0, 0}; GLenum gl_pixel_type; @@ -2614,7 +2613,7 @@ gl_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer) */ if (!bpp) bpp = pixel_format_get_info(yuv->plane[0].format)->bpp; - pitch = wl_shm_buffer_get_stride(shm_buffer) / (bpp / 8); + pitch = buffer->stride / (bpp / 8); /* well, they all are so far ... */ gl_pixel_type = GL_UNSIGNED_BYTE; @@ -2655,7 +2654,7 @@ gl_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer) shader_variant = SHADER_VARIANT_RGBA; assert(bpp > 0 && !(bpp & 7)); - pitch = wl_shm_buffer_get_stride(shm_buffer) / (bpp / 8); + pitch = buffer->stride / (bpp / 8); gl_format[0] = buffer->pixel_format->gl_format; gl_pixel_type = buffer->pixel_format->gl_type; diff --git a/libweston/screenshooter.c b/libweston/screenshooter.c index 4e0afc07..f5d46ceb 100644 --- a/libweston/screenshooter.c +++ b/libweston/screenshooter.c @@ -148,7 +148,7 @@ screenshooter_frame_notify(struct wl_listener *listener, void *data) 0, 0, output->current_mode->width, output->current_mode->height); - stride = wl_shm_buffer_get_stride(l->buffer->shm_buffer); + stride = l->buffer->stride; d = wl_shm_buffer_get_data(l->buffer->shm_buffer); s = pixels + stride * (l->buffer->height - 1);