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 <derek.foreman@collabora.com>
Tested-by: Connor Abbott <cwabbott0@gmail.com>
This commit is contained in:
Derek Foreman 2024-07-03 13:20:50 -05:00 committed by Marius Vlad
parent 0a483706d9
commit 376b3952a0
8 changed files with 13 additions and 17 deletions

View File

@ -1636,6 +1636,7 @@ struct weston_buffer {
};
int32_t width, height;
int32_t stride;
uint32_t busy_count;
uint32_t passive_count;
enum {

View File

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

View File

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

View File

@ -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 */

View File

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

View File

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

View File

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

View File

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