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:
wm4 2017-03-20 13:37:47 +01:00
parent 8fb9cc2534
commit b0cbda84ed
4 changed files with 54 additions and 42 deletions

View File

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

View File

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

View File

@ -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,

View File

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