This backend is a special case where the state of the frame (i.e. is it still) needs to be taken into account when flipping the page because it does its own fencing. vo_gpu_next never calls the submit_frame API in ra_swapchain which meant the drm backend wasn't aware of the state of the frames and thus couldn't respond. This is a bit weird though because in vo_gpu we actually want the ra_gl_ctx_submit_frame call after the custom external drm_egl_submit_frame. But we don't want this in vo_gpu_next, we only want the state update. Be lazy and just compare the vo_drivers, but the way this is currently designed feels wrong. Fixes delayed OSD rendering when you play a still image like an audio file with cover art.
Unified · Split
| @@ -241,6 +241,10 @@ bool ra_gl_ctx_submit_frame(struct ra_swapchain *sw, const struct vo_frame *fram · 240 unmodified lines | |||
| 241 | struct priv *p = sw->priv; | 241 | struct priv *p = sw->priv; |
| 242 | GL *gl = p->gl; | 242 | GL *gl = p->gl; |
| 243 | 243 | ||
| 244 | // Dumb hack for drm_egl and vo_gpu_next. | ||
| 245 | if (vo_is_gpu_next(sw->ctx->vo)) | ||
| 246 | return true; | ||
| 247 | |||
| 244 | if (p->opts->use_glfinish) | 248 | if (p->opts->use_glfinish) |
| 245 | gl->Finish(); | 249 | gl->Finish(); |
| 246 | 250 | ||
| @@ -388,20 +388,6 @@ static void wait_fence(struct ra_ctx *ctx) · 387 unmodified lines | |||
| 388 | } | 388 | } |
| 389 | } | 389 | } |
| 390 | 390 | ||
| 391 | static bool drm_egl_start_frame(struct ra_swapchain *sw, struct ra_fbo *out_fbo) | ||
| 392 | { | ||
| 393 | struct ra_ctx *ctx = sw->ctx; | ||
| 394 | struct priv *p = ctx->priv; | ||
| 395 | struct vo_drm_state *drm = ctx->vo->drm; | ||
| 396 | |||
| 397 | if (!drm->atomic_context->request) { | ||
| 398 | drm->atomic_context->request = drmModeAtomicAlloc(); | ||
| 399 | p->drm_params.atomic_request_ptr = &drm->atomic_context->request; | ||
| 400 | } | ||
| 401 | |||
| 402 | return ra_gl_ctx_start_frame(sw, out_fbo); | ||
| 403 | } | ||
| 404 | |||
| 405 | static bool drm_egl_submit_frame(struct ra_swapchain *sw, const struct vo_frame *frame) | 391 | static bool drm_egl_submit_frame(struct ra_swapchain *sw, const struct vo_frame *frame) |
| 406 | { | 392 | { |
| 407 | struct ra_ctx *ctx = sw->ctx; | 393 | struct ra_ctx *ctx = sw->ctx; |
| @@ -419,6 +405,11 @@ static void drm_egl_swap_buffers(struct ra_swapchain *sw) · 11 unmodified lines | |||
| 419 | struct vo_drm_state *drm = ctx->vo->drm; | 405 | struct vo_drm_state *drm = ctx->vo->drm; |
| 420 | const bool drain = drm->paused || drm->still; // True when we need to drain the swapchain | 406 | const bool drain = drm->paused || drm->still; // True when we need to drain the swapchain |
| 421 | 407 | ||
| 408 | if (!drm->atomic_context->request) { | ||
| 409 | drm->atomic_context->request = drmModeAtomicAlloc(); | ||
| 410 | p->drm_params.atomic_request_ptr = &drm->atomic_context->request; | ||
| 411 | } | ||
| 412 | |||
| 422 | if (!drm->active) | 413 | if (!drm->active) |
| 423 | return; | 414 | return; |
| 424 | 415 | ||
| @@ -452,7 +443,6 @@ static void drm_egl_swap_buffers(struct ra_swapchain *sw) · 27 unmodified lines | |||
| 452 | } | 443 | } |
| 453 | 444 | ||
| 454 | static const struct ra_swapchain_fns drm_egl_swapchain = { | 445 | static const struct ra_swapchain_fns drm_egl_swapchain = { |
| 455 | .start_frame = drm_egl_start_frame, | ||
| 456 | .submit_frame = drm_egl_submit_frame, | 446 | .submit_frame = drm_egl_submit_frame, |
| 457 | .swap_buffers = drm_egl_swap_buffers, | 447 | .swap_buffers = drm_egl_swap_buffers, |
| 458 | }; | 448 | }; |
| @@ -860,6 +860,12 @@ bool vo_is_ready_for_frame(struct vo *vo, int64_t next_pts) · 859 unmodified lines | |||
| 860 | return r; | 860 | return r; |
| 861 | } | 861 | } |
| 862 | 862 | ||
| 863 | // Needed by egl_drm | ||
| 864 | bool vo_is_gpu_next(struct vo *vo) | ||
| 865 | { | ||
| 866 | return vo && vo->driver && vo->driver == &video_out_gpu_next; | ||
| 867 | } | ||
| 868 | |||
| 863 | // Check if the VO reports that the mpv window is visible. | 869 | // Check if the VO reports that the mpv window is visible. |
| 864 | bool vo_is_visible(struct vo *vo) | 870 | bool vo_is_visible(struct vo *vo) |
| 865 | { | 871 | { |
| @@ -532,6 +532,7 @@ int vo_reconfig2(struct vo *vo, struct mp_image *img); · 531 unmodified lines | |||
| 532 | 532 | ||
| 533 | int vo_control(struct vo *vo, int request, void *data); | 533 | int vo_control(struct vo *vo, int request, void *data); |
| 534 | void vo_control_async(struct vo *vo, int request, void *data); | 534 | void vo_control_async(struct vo *vo, int request, void *data); |
| 535 | bool vo_is_gpu_next(struct vo *vo); | ||
| 535 | bool vo_is_ready_for_frame(struct vo *vo, int64_t next_pts); | 536 | bool vo_is_ready_for_frame(struct vo *vo, int64_t next_pts); |
| 536 | bool vo_is_visible(struct vo *vo); | 537 | bool vo_is_visible(struct vo *vo); |
| 537 | void vo_queue_frame(struct vo *vo, struct vo_frame *frame); | 538 | void vo_queue_frame(struct vo *vo, struct vo_frame *frame); |
| @@ -1170,6 +1170,7 @@ done: · 1169 unmodified lines | |||
| 1170 | if (!valid) // clear with purple to indicate error | 1170 | if (!valid) // clear with purple to indicate error |
| 1171 | pl_tex_clear(gpu, swframe.fbo, (float[4]){ 0.5, 0.0, 1.0, 1.0 }); | 1171 | pl_tex_clear(gpu, swframe.fbo, (float[4]){ 0.5, 0.0, 1.0, 1.0 }); |
| 1172 | 1172 | ||
| 1173 | sw->fns->submit_frame(sw, frame); // for drm_egl | ||
| 1173 | pl_gpu_flush(gpu); | 1174 | pl_gpu_flush(gpu); |
| 1174 | p->frame_pending = true; | 1175 | p->frame_pending = true; |
| 1175 | return VO_TRUE; | 1176 | return VO_TRUE; |