summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorAlexander Preisinger <alexander.preisinger@gmail.com>2013-09-12 18:13:49 +0200
committerAlexander Preisinger <alexander.preisinger@gmail.com>2013-09-12 18:15:35 +0200
commit71f287c9c045d7909b0f72e5580e3e1167609e02 (patch)
tree35f2722915ef7b32e1a7e2fc0528b395a5df3222 /video
parent63c61500b80643f339339e9515b5491909a9b5a1 (diff)
downloadmpv-71f287c9c045d7909b0f72e5580e3e1167609e02.tar.bz2
mpv-71f287c9c045d7909b0f72e5580e3e1167609e02.tar.xz
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.
Diffstat (limited to 'video')
-rw-r--r--video/out/vo_wayland.c52
1 files changed, 45 insertions, 7 deletions
diff --git a/video/out/vo_wayland.c b/video/out/vo_wayland.c
index 18d99a9507..7a590a87df 100644
--- a/video/out/vo_wayland.c
+++ b/video/out/vo_wayland.c
@@ -138,11 +138,15 @@ struct priv {
struct buffer buffers[MAX_BUFFERS];
struct buffer *front_buffer;
struct buffer *back_buffer;
+ struct buffer tmp_buffer;
struct mp_image *original_image;
int width; // width of the original image
int height;
+ int x, y; // coords for resizing
+ bool resize_attach;
+
// options
int enable_alpha;
int use_default;
@@ -369,6 +373,13 @@ static mp_image_t *get_screenshot(struct priv *p)
static bool resize(struct priv *p)
{
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 y = wl->window.sh_y;
wl->vo->dwidth = wl->window.sh_width;
@@ -406,6 +417,11 @@ static bool resize(struct priv *p)
if (mp_sws_reinit(p->sws) < 0)
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)) {
MP_ERR(wl, "failed to resize buffers\n");
return false;
@@ -424,11 +440,9 @@ static bool resize(struct priv *p)
wl_region_destroy(opaque);
}
- // a redraw should happen at this point
- wl_surface_attach(wl->window.surface, p->front_buffer->wlbuf, x, y);
- wl_surface_damage(wl->window.surface, 0, 0, p->dst_w, p->dst_h);
- wl_surface_commit(wl->window.surface);
-
+ p->x = x;
+ p->y = y;
+ p->resize_attach = true;
p->wl->window.events = 0;
p->vo->want_redraw = true;
return true;
@@ -455,6 +469,26 @@ static void frame_handle_redraw(void *data,
struct vo_wayland_state *wl = p->wl;
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_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 buffer *buf = buffer_get_back(p);
- if (!buf)
+ if (!buf) {
+ MP_WARN(p->wl, "can't draw, back buffer is busy\n");
return;
+ }
struct mp_image src = *mpi;
struct mp_rect src_rc = p->src;
@@ -529,8 +565,10 @@ static void flip_page(struct vo *vo)
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);
+ }
}
static int query_format(struct vo *vo, uint32_t format)