mirror of https://github.com/mpv-player/mpv
wayland/shm: fix resizing for good (finally)
Problem: I own the buffer and I destroyed while still being displayed. Solution: Add a temporary buffer and destroy it when the next buffer is attached.
This commit is contained in:
parent
63c61500b8
commit
71f287c9c0
|
@ -138,11 +138,15 @@ struct priv {
|
||||||
struct buffer buffers[MAX_BUFFERS];
|
struct buffer buffers[MAX_BUFFERS];
|
||||||
struct buffer *front_buffer;
|
struct buffer *front_buffer;
|
||||||
struct buffer *back_buffer;
|
struct buffer *back_buffer;
|
||||||
|
struct buffer tmp_buffer;
|
||||||
|
|
||||||
struct mp_image *original_image;
|
struct mp_image *original_image;
|
||||||
int width; // width of the original image
|
int width; // width of the original image
|
||||||
int height;
|
int height;
|
||||||
|
|
||||||
|
int x, y; // coords for resizing
|
||||||
|
bool resize_attach;
|
||||||
|
|
||||||
// options
|
// options
|
||||||
int enable_alpha;
|
int enable_alpha;
|
||||||
int use_default;
|
int use_default;
|
||||||
|
@ -369,6 +373,13 @@ static mp_image_t *get_screenshot(struct priv *p)
|
||||||
static bool resize(struct priv *p)
|
static bool resize(struct priv *p)
|
||||||
{
|
{
|
||||||
struct vo_wayland_state *wl = p->wl;
|
struct vo_wayland_state *wl = p->wl;
|
||||||
|
|
||||||
|
// if the newly resized buffer isn't attached, then don't resize again,
|
||||||
|
// because the front buffer might be empty and the temporary buffer might
|
||||||
|
// still be valid
|
||||||
|
if (p->resize_attach)
|
||||||
|
return false;
|
||||||
|
|
||||||
int32_t x = wl->window.sh_x;
|
int32_t x = wl->window.sh_x;
|
||||||
int32_t y = wl->window.sh_y;
|
int32_t y = wl->window.sh_y;
|
||||||
wl->vo->dwidth = wl->window.sh_width;
|
wl->vo->dwidth = wl->window.sh_width;
|
||||||
|
@ -406,6 +417,11 @@ static bool resize(struct priv *p)
|
||||||
if (mp_sws_reinit(p->sws) < 0)
|
if (mp_sws_reinit(p->sws) < 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// copy pointers
|
||||||
|
p->tmp_buffer = *p->front_buffer;
|
||||||
|
p->front_buffer->shm_data = NULL;
|
||||||
|
p->front_buffer->wlbuf = NULL;
|
||||||
|
|
||||||
if (!reinit_shm_buffers(p, p->dst_w, p->dst_h)) {
|
if (!reinit_shm_buffers(p, p->dst_w, p->dst_h)) {
|
||||||
MP_ERR(wl, "failed to resize buffers\n");
|
MP_ERR(wl, "failed to resize buffers\n");
|
||||||
return false;
|
return false;
|
||||||
|
@ -424,11 +440,9 @@ static bool resize(struct priv *p)
|
||||||
wl_region_destroy(opaque);
|
wl_region_destroy(opaque);
|
||||||
}
|
}
|
||||||
|
|
||||||
// a redraw should happen at this point
|
p->x = x;
|
||||||
wl_surface_attach(wl->window.surface, p->front_buffer->wlbuf, x, y);
|
p->y = y;
|
||||||
wl_surface_damage(wl->window.surface, 0, 0, p->dst_w, p->dst_h);
|
p->resize_attach = true;
|
||||||
wl_surface_commit(wl->window.surface);
|
|
||||||
|
|
||||||
p->wl->window.events = 0;
|
p->wl->window.events = 0;
|
||||||
p->vo->want_redraw = true;
|
p->vo->want_redraw = true;
|
||||||
return true;
|
return true;
|
||||||
|
@ -455,6 +469,26 @@ static void frame_handle_redraw(void *data,
|
||||||
struct vo_wayland_state *wl = p->wl;
|
struct vo_wayland_state *wl = p->wl;
|
||||||
struct buffer *buf = buffer_get_front(p);
|
struct buffer *buf = buffer_get_front(p);
|
||||||
|
|
||||||
|
if (p->resize_attach) {
|
||||||
|
wl_surface_attach(wl->window.surface, buf->wlbuf, p->x, p->y);
|
||||||
|
wl_surface_damage(wl->window.surface, 0, 0, p->dst_w, p->dst_h);
|
||||||
|
wl_surface_commit(wl->window.surface);
|
||||||
|
|
||||||
|
if (callback)
|
||||||
|
wl_callback_destroy(callback);
|
||||||
|
|
||||||
|
p->redraw_callback = NULL;
|
||||||
|
buffer_finalise_front(p);
|
||||||
|
p->resize_attach = false;
|
||||||
|
|
||||||
|
destroy_shm_buffer(&p->tmp_buffer);
|
||||||
|
|
||||||
|
// I have to destroy the callback and return early to avoid black flickers
|
||||||
|
// I don't exactly know why this, but I guess the back buffer is still
|
||||||
|
// empty. The callback loop will be restored on the next flip_page call
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
wl_surface_attach(wl->window.surface, buf->wlbuf, 0, 0);
|
wl_surface_attach(wl->window.surface, buf->wlbuf, 0, 0);
|
||||||
wl_surface_damage(wl->window.surface, 0, 0, p->dst_w, p->dst_h);
|
wl_surface_damage(wl->window.surface, 0, 0, p->dst_w, p->dst_h);
|
||||||
|
|
||||||
|
@ -500,8 +534,10 @@ static void draw_image(struct vo *vo, mp_image_t *mpi)
|
||||||
struct priv *p = vo->priv;
|
struct priv *p = vo->priv;
|
||||||
struct buffer *buf = buffer_get_back(p);
|
struct buffer *buf = buffer_get_back(p);
|
||||||
|
|
||||||
if (!buf)
|
if (!buf) {
|
||||||
|
MP_WARN(p->wl, "can't draw, back buffer is busy\n");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
struct mp_image src = *mpi;
|
struct mp_image src = *mpi;
|
||||||
struct mp_rect src_rc = p->src;
|
struct mp_rect src_rc = p->src;
|
||||||
|
@ -529,8 +565,10 @@ static void flip_page(struct vo *vo)
|
||||||
|
|
||||||
buffer_swap(p);
|
buffer_swap(p);
|
||||||
|
|
||||||
if (!p->redraw_callback)
|
if (!p->redraw_callback) {
|
||||||
|
MP_INFO(p->wl, "restart frame callback\n");
|
||||||
frame_handle_redraw(p, NULL, 0);
|
frame_handle_redraw(p, NULL, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int query_format(struct vo *vo, uint32_t format)
|
static int query_format(struct vo *vo, uint32_t format)
|
||||||
|
|
Loading…
Reference in New Issue