summaryrefslogtreecommitdiffstats
path: root/libvo
diff options
context:
space:
mode:
authorUoti Urpala <uau@glyph.nonexistent.invalid>2009-09-19 00:00:42 +0300
committerUoti Urpala <uau@glyph.nonexistent.invalid>2009-09-19 00:00:42 +0300
commit3c70c5dc955bb0d5b67e831d98d1db95fbb03f9e (patch)
tree270a782ac99712e4209a4a37dfe106dc387dc25f /libvo
parent56088ff4dc5180e95ea0c60f86a4b5ffc5c76611 (diff)
downloadmpv-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')
-rw-r--r--libvo/vo_vdpau.c18
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");