mirror of
https://github.com/mpv-player/mpv
synced 2025-01-05 03:06:28 +01: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:
parent
56088ff4dc
commit
3c70c5dc95
@ -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");
|
||||
|
Loading…
Reference in New Issue
Block a user