diff options
author | Uoti Urpala <uau@glyph.nonexistent.invalid> | 2009-09-19 00:00:42 +0300 |
---|---|---|
committer | Uoti Urpala <uau@glyph.nonexistent.invalid> | 2009-09-19 00:00:42 +0300 |
commit | 3c70c5dc955bb0d5b67e831d98d1db95fbb03f9e (patch) | |
tree | 270a782ac99712e4209a4a37dfe106dc387dc25f /libvo/vo_vdpau.c | |
parent | 56088ff4dc5180e95ea0c60f86a4b5ffc5c76611 (diff) | |
download | mpv-3c70c5dc955bb0d5b67e831d98d1db95fbb03f9e.tar.bz2 mpv-3c70c5dc955bb0d5b67e831d98d1db95fbb03f9e.tar.xz |
vo_vdpau: Fix X event handling bugs
check_events() first checked for a RESIZE event and called resize() if
needed, and then queued a frame to be reshown if in pause state and
the event was either RESIZE or EXPOSE. The most obvious problems with
the code were:
- resize() already called flip_page() internally, so the code in
check_events could lead to _two_ frames being queued.
- The call in resize() didn't depend on pause status, so the
behavior was inconsistent.
- The code in check_events() actually queued the wrong output
surface. It showed the same surface as flip_page() would show
_next_, while it should have shown the previously shown one. This
typically led to the screen contents changing to a previous
state, as the new surface had not been initialized and had
contents from a previous use.
Fix the double update. Make resize() also only immediately update the
video if paused (this also affects changing to/from fullscreen) and
otherwise leave the old window contents be until the next frame. Queue
the right frame in check_events(). Also make resize() a bit more
careful to only show contents if they were successfully updated
(though a case where we're paused without content to show shouldn't
normally happen).
Diffstat (limited to 'libvo/vo_vdpau.c')
-rw-r--r-- | libvo/vo_vdpau.c | 18 |
1 files changed, 10 insertions, 8 deletions
diff --git a/libvo/vo_vdpau.c b/libvo/vo_vdpau.c index bf760750cc..e613205834 100644 --- a/libvo/vo_vdpau.c +++ b/libvo/vo_vdpau.c @@ -178,14 +178,14 @@ struct vdpctx { static void flip_page(struct vo *vo); -static void video_to_output_surface(struct vo *vo) +static int video_to_output_surface(struct vo *vo) { struct vdpctx *vc = vo->priv; struct vdp_functions *vdp = vc->vdp; VdpTime dummy; VdpStatus vdp_st; if (vc->deint_queue_pos < 0) - return; + return -1; int field = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME; unsigned int dp = vc->deint_queue_pos; @@ -214,6 +214,7 @@ static void video_to_output_surface(struct vo *vo) &vc->src_rect_vid, output_surface, NULL, &vc->out_rect_vid, 0, NULL); CHECK_ST_WARNING("Error when calling vdp_video_mixer_render"); + return 0; } static void add_new_video_surface(struct vo *vo, VdpVideoSurface surface, @@ -315,9 +316,9 @@ static void resize(struct vo *vo) vc->output_surfaces[i]); } } - video_to_output_surface(vo); - if (vc->visible_buf) - flip_page(vo); + if (vc->paused && vc->visible_buf) + if (video_to_output_surface(vo) >= 0) + flip_page(vo); } static void preemption_callback(VdpDevice device, void *context) @@ -737,14 +738,15 @@ static void check_events(struct vo *vo) if (e & VO_EVENT_RESIZE) resize(vo); - - if ((e & VO_EVENT_EXPOSE || e & VO_EVENT_RESIZE) && vc->paused) { + else if (e & VO_EVENT_EXPOSE && vc->paused) { /* did we already draw a buffer */ if (vc->visible_buf) { /* redraw the last visible buffer */ VdpStatus vdp_st; + int last_surface = (vc->surface_num + NUM_OUTPUT_SURFACES - 1) + % NUM_OUTPUT_SURFACES; vdp_st = vdp->presentation_queue_display(vc->flip_queue, - vc->output_surfaces[vc->surface_num], + vc->output_surfaces[last_surface], vo->dwidth, vo->dheight, 0); CHECK_ST_WARNING("Error when calling " "vdp_presentation_queue_display"); |