mirror of https://github.com/mpv-player/mpv
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.
This commit is contained in:
parent
8fb9cc2534
commit
b0cbda84ed
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
gl->VDPAUMapSurfacesNV(1, &surface->registered);
|
||||
surface->mapped = true;
|
||||
ctx->main_fb = surface->fbo;
|
||||
ctx->flip_v = true;
|
||||
}
|
||||
|
||||
static int glx_reconfig(struct MPGLContext *ctx)
|
||||
{
|
||||
vo_x11_config_vo_window(ctx->vo);
|
||||
|
||||
glx_next_framebuffer(ctx); // map initial FBO
|
||||
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_swap_buffers(struct MPGLContext *ctx)
|
||||
{
|
||||
glx_next_framebuffer(ctx);
|
||||
struct priv *p = ctx->priv;
|
||||
struct vdp_functions *vdp = &p->vdp->vdp;
|
||||
VdpStatus vdp_st;
|
||||
GL *gl = ctx->gl;
|
||||
|
||||
struct surface *surface = &p->surfaces[p->current_surface];
|
||||
if (surface->surface == VDP_INVALID_HANDLE)
|
||||
return; // surface alloc probably failed before
|
||||
|
||||
if (surface->mapped)
|
||||
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");
|
||||
|
||||
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,
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue