0
0
mirror of https://github.com/mpv-player/mpv.git synced 2024-09-20 03:52:22 +02:00

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).
This commit is contained in:
Uoti Urpala 2009-09-19 00:00:42 +03:00
parent 56088ff4dc
commit 3c70c5dc95

View File

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