From b0cbda84ed923c8915642443b7cf5de5a2ba7b26 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 20 Mar 2017 13:37:47 +0100 Subject: vo_opengl: add a backend start_frame callback for context_vdpau Might be useful for other backends too. For context_vdpau, resize handling, presentation, and handling the mapping state becomes somewhat less awkward. --- video/out/opengl/context.c | 6 ++++ video/out/opengl/context.h | 6 ++++ video/out/opengl/context_vdpau.c | 78 ++++++++++++++++++++-------------------- video/out/vo_opengl.c | 2 ++ 4 files changed, 52 insertions(+), 40 deletions(-) diff --git a/video/out/opengl/context.c b/video/out/opengl/context.c index 4985c8a326..6fdc123fb6 100644 --- a/video/out/opengl/context.c +++ b/video/out/opengl/context.c @@ -240,6 +240,12 @@ int mpgl_control(struct MPGLContext *ctx, int *events, int request, void *arg) return ctx->driver->control(ctx, events, request, arg); } +void mpgl_start_frame(struct MPGLContext *ctx) +{ + if (ctx->driver->start_frame) + ctx->driver->start_frame(ctx); +} + void mpgl_swap_buffers(struct MPGLContext *ctx) { ctx->driver->swap_buffers(ctx); diff --git a/video/out/opengl/context.h b/video/out/opengl/context.h index 7eabbd4886..229c5ef54f 100644 --- a/video/out/opengl/context.h +++ b/video/out/opengl/context.h @@ -59,6 +59,11 @@ struct mpgl_driver { // Return 0 on success, negative value (-1) on error. int (*reconfig)(struct MPGLContext *ctx); + // Called when rendering starts. The backend can map or resize the + // framebuffer, or update GL.main_fb. swap_buffers() ends the frame. + // Optional. + void (*start_frame)(struct MPGLContext *ctx); + // Present the frame. void (*swap_buffers)(struct MPGLContext *ctx); @@ -99,6 +104,7 @@ MPGLContext *mpgl_init(struct vo *vo, const char *backend_name, int vo_flags); void mpgl_uninit(MPGLContext *ctx); int mpgl_reconfig_window(struct MPGLContext *ctx); int mpgl_control(struct MPGLContext *ctx, int *events, int request, void *arg); +void mpgl_start_frame(struct MPGLContext *ctx); void mpgl_swap_buffers(struct MPGLContext *ctx); int mpgl_find_backend(const char *name); diff --git a/video/out/opengl/context_vdpau.c b/video/out/opengl/context_vdpau.c index 1d8479e9dc..4d5d2538e2 100644 --- a/video/out/opengl/context_vdpau.c +++ b/video/out/opengl/context_vdpau.c @@ -295,7 +295,8 @@ static int glx_init(struct MPGLContext *ctx, int flags) p->num_surfaces = NUM_SURFACES; for (int n = 0; n < p->num_surfaces; n++) p->surfaces[n].surface = VDP_INVALID_HANDLE; - p->current_surface = -1; + + ctx->flip_v = true; return 0; @@ -304,30 +305,25 @@ uninit: return -1; } -static void glx_next_framebuffer(struct MPGLContext *ctx) +static int glx_reconfig(struct MPGLContext *ctx) +{ + vo_x11_config_vo_window(ctx->vo); + return 0; +} + +static int glx_control(struct MPGLContext *ctx, int *events, int request, + void *arg) +{ + return vo_x11_control(ctx->vo, events, request, arg); +} + +static void glx_start_frame(struct MPGLContext *ctx) { struct priv *p = ctx->priv; struct vdp_functions *vdp = &p->vdp->vdp; VdpStatus vdp_st; GL *gl = ctx->gl; - ctx->main_fb = 0; - - int current_surface = p->current_surface++; - p->current_surface = p->current_surface % p->num_surfaces; - - if (current_surface >= 0) { - struct surface *surface = &p->surfaces[current_surface]; - - if (surface->mapped) - ctx->gl->VDPAUUnmapSurfacesNV(1, &surface->registered); - surface->mapped = false; - - vdp_st = vdp->presentation_queue_display(p->vdp_queue, surface->surface, - 0, 0, 0); - CHECK_VDP_WARNING(ctx, "trying to present vdp surface"); - } - struct surface *surface = &p->surfaces[p->current_surface]; if (surface->surface != VDP_INVALID_HANDLE) { @@ -341,34 +337,35 @@ static void glx_next_framebuffer(struct MPGLContext *ctx) if (surface->w != ctx->vo->dwidth || surface->h != ctx->vo->dheight) recreate_vdpau_surface(ctx, surface); - if (surface->surface == VDP_INVALID_HANDLE) { - p->current_surface = -1; - return; - } - gl->VDPAUMapSurfacesNV(1, &surface->registered); - surface->mapped = true; - ctx->main_fb = surface->fbo; - ctx->flip_v = true; + ctx->main_fb = surface->fbo; // 0 if creating the surface failed + + if (surface->surface != VDP_INVALID_HANDLE) { + gl->VDPAUMapSurfacesNV(1, &surface->registered); + surface->mapped = true; + } } -static int glx_reconfig(struct MPGLContext *ctx) +static void glx_swap_buffers(struct MPGLContext *ctx) { - vo_x11_config_vo_window(ctx->vo); + struct priv *p = ctx->priv; + struct vdp_functions *vdp = &p->vdp->vdp; + VdpStatus vdp_st; + GL *gl = ctx->gl; - glx_next_framebuffer(ctx); // map initial FBO - return 0; -} + struct surface *surface = &p->surfaces[p->current_surface]; + if (surface->surface == VDP_INVALID_HANDLE) + return; // surface alloc probably failed before -static int glx_control(struct MPGLContext *ctx, int *events, int request, - void *arg) -{ - return vo_x11_control(ctx->vo, events, request, arg); -} + if (surface->mapped) + gl->VDPAUUnmapSurfacesNV(1, &surface->registered); + surface->mapped = false; -static void glx_swap_buffers(struct MPGLContext *ctx) -{ - glx_next_framebuffer(ctx); + vdp_st = vdp->presentation_queue_display(p->vdp_queue, surface->surface, + 0, 0, 0); + CHECK_VDP_WARNING(ctx, "trying to present vdp surface"); + + p->current_surface = (p->current_surface + 1) % p->num_surfaces; } static void glx_wakeup(struct MPGLContext *ctx) @@ -386,6 +383,7 @@ const struct mpgl_driver mpgl_driver_vdpauglx = { .priv_size = sizeof(struct priv), .init = glx_init, .reconfig = glx_reconfig, + .start_frame = glx_start_frame, .swap_buffers = glx_swap_buffers, .control = glx_control, .wakeup = glx_wakeup, diff --git a/video/out/vo_opengl.c b/video/out/vo_opengl.c index 88c23fae32..9b3f944e21 100644 --- a/video/out/vo_opengl.c +++ b/video/out/vo_opengl.c @@ -122,6 +122,8 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame) struct gl_priv *p = vo->priv; GL *gl = p->gl; + mpgl_start_frame(p->glctx); + if (gl->FenceSync && p->num_vsync_fences < p->opts.vsync_fences) { GLsync fence = gl->FenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);; if (fence) -- cgit v1.2.3