video/out: introduce vo_control for gl_common based VOs

Instead of having separate callbacks for each backend-handled feature
(like MPGLContext.fullscreen, MPGLContext.border, etc.), pass the
VOCTRL responsible for this directly to the backend. This allows
removing a bunch of callbacks, that currently must be set even for
optional/lesser features (like VOCTRL_BORDER).

This requires changes to all VOs using gl_common, as well as all
backends that support gl_common.

Also introduce VOCTRL_CHECK_EVENTS. vo.check_events is now optional.
VO backends can use VOCTRL_CHECK_EVENTS instead to implementing
check_events. This has the advantage that the event handling code in
VOs doesn't have to be duplicated if vo_control() is used.
This commit is contained in:
wm4 2013-05-15 18:17:18 +02:00
parent c23bf5311f
commit bf10a4fdfa
18 changed files with 138 additions and 158 deletions

View File

@ -43,6 +43,7 @@ void vo_cocoa_fullscreen(struct vo *vo);
void vo_cocoa_ontop(struct vo *vo);
void vo_cocoa_pause(struct vo *vo);
void vo_cocoa_resume(struct vo *vo);
int vo_cocoa_control(struct vo *vo, int *events, int request, void *arg);
void vo_cocoa_register_resize_callback(struct vo *vo,
void (*cb)(struct vo *vo, int w, int h));

View File

@ -657,6 +657,32 @@ void vo_cocoa_fullscreen(struct vo *vo)
}
}
int vo_cocoa_control(struct vo *vo, int *events, int request, void *arg)
{
switch (request) {
case VOCTRL_CHECK_EVENTS:
*events |= vo_cocoa_check_events(vo);
return VO_TRUE;
case VOCTRL_FULLSCREEN:
vo_cocoa_fullscreen(vo);
*events |= VO_EVENT_RESIZE;
return VO_TRUE;
case VOCTRL_ONTOP:
vo_cocoa_ontop(vo);
return VO_TRUE;
case VOCTRL_UPDATE_SCREENINFO:
vo_cocoa_update_xinerama_info(vo);
return VO_TRUE;
case VOCTRL_PAUSE:
vo_cocoa_pause(vo);
return VO_TRUE;
case VOCTRL_RESUME:
vo_cocoa_resume(vo);
return VO_TRUE;
}
return VO_NOTIMPL;
}
int vo_cocoa_swap_interval(int enabled)
{
[[NSOpenGLContext currentContext] setValues:&enabled

View File

@ -62,14 +62,9 @@ void mpgl_set_backend_cocoa(MPGLContext *ctx)
ctx->releaseGlContext = releaseGlContext_cocoa;
ctx->swapGlBuffers = swapGlBuffers_cocoa;
ctx->check_events = vo_cocoa_check_events;
ctx->update_xinerama_info = vo_cocoa_update_xinerama_info;
ctx->fullscreen = vo_cocoa_fullscreen;
ctx->ontop = vo_cocoa_ontop;
ctx->vo_init = vo_cocoa_init;
ctx->pause = vo_cocoa_pause;
ctx->resume = vo_cocoa_resume;
ctx->register_resize_callback = vo_cocoa_register_resize_callback;
ctx->vo_uninit = vo_cocoa_uninit;
ctx->set_current = set_current_cocoa;
ctx->vo_control = vo_cocoa_control;
ctx->set_current = set_current_cocoa;
}

View File

@ -108,9 +108,9 @@ typedef struct MPGLContext {
void (*swapGlBuffers)(struct MPGLContext *);
int (*check_events)(struct vo *vo);
void (*fullscreen)(struct vo *vo);
int (*vo_init)(struct vo *vo);
void (*vo_uninit)(struct vo *vo);
int (*vo_control)(struct vo *vo, int *events, int request, void *arg);
void (*releaseGlContext)(struct MPGLContext *);
void (*set_current)(struct MPGLContext *, bool current);
@ -124,13 +124,6 @@ typedef struct MPGLContext {
bool (*config_window)(struct MPGLContext *ctx, uint32_t d_width,
uint32_t d_height, uint32_t flags);
// optional
void (*pause)(struct vo *vo);
void (*resume)(struct vo *vo);
void (*ontop)(struct vo *vo);
void (*border)(struct vo *vo);
void (*update_xinerama_info)(struct vo *vo);
// An optional function to register a resize callback in the backend that
// can be called on separate thread to handle resize events immediately
// (without waiting for vo_check_events, which will come later for the

View File

@ -208,11 +208,8 @@ void mpgl_set_backend_w32(MPGLContext *ctx)
ctx->config_window = config_window_w32;
ctx->releaseGlContext = releaseGlContext_w32;
ctx->swapGlBuffers = swapGlBuffers_w32;
ctx->update_xinerama_info = w32_update_xinerama_info;
ctx->border = vo_w32_border;
ctx->check_events = vo_w32_check_events;
ctx->fullscreen = vo_w32_fullscreen;
ctx->ontop = vo_w32_ontop;
ctx->vo_init = vo_w32_init;
ctx->vo_uninit = vo_w32_uninit;
ctx->vo_control = vo_w32_control;
}

View File

@ -244,11 +244,8 @@ void mpgl_set_backend_wayland(MPGLContext *ctx)
ctx->config_window = config_window_wayland;
ctx->releaseGlContext = releaseGlContext_wayland;
ctx->swapGlBuffers = swapGlBuffers_wayland;
ctx->update_xinerama_info = vo_wayland_update_screeninfo;
ctx->border = vo_wayland_border;
ctx->check_events = vo_wayland_check_events;
ctx->fullscreen = vo_wayland_fullscreen;
ctx->ontop = vo_wayland_ontop;
ctx->vo_control = vo_wayland_control;
ctx->vo_init = vo_wayland_init;
ctx->vo_uninit = vo_wayland_uninit;
}

View File

@ -307,11 +307,8 @@ void mpgl_set_backend_x11(MPGLContext *ctx)
ctx->config_window = config_window_x11;
ctx->releaseGlContext = releaseGlContext_x11;
ctx->swapGlBuffers = swapGlBuffers_x11;
ctx->update_xinerama_info = vo_x11_update_screeninfo;
ctx->border = vo_x11_border;
ctx->check_events = vo_x11_check_events;
ctx->fullscreen = vo_x11_fullscreen;
ctx->ontop = vo_x11_ontop;
ctx->vo_init = vo_x11_init;
ctx->vo_uninit = vo_x11_uninit;
ctx->vo_control = vo_x11_control;
}

View File

@ -235,7 +235,9 @@ void vo_check_events(struct vo *vo)
vo->registered_fd = -1;
return;
}
vo->driver->check_events(vo);
if (vo->driver->check_events)
vo->driver->check_events(vo);
vo_control(vo, VOCTRL_CHECK_EVENTS, NULL);
}
// Return the amount of time vo_check_events() should be called in milliseconds.

View File

@ -36,6 +36,8 @@
enum mp_voctrl {
/* signal a device reset seek */
VOCTRL_RESET = 1,
/* Handle input and redraw events, called by vo_check_events() */
VOCTRL_CHECK_EVENTS,
/* used to switch to fullscreen */
VOCTRL_FULLSCREEN,
/* signal a device pause */

View File

@ -138,14 +138,6 @@ static int config(struct vo *vo, uint32_t width, uint32_t height,
return 0;
}
static void check_events(struct vo *vo)
{
struct priv *p = vo->priv;
int e = p->mpglctx->check_events(vo);
if (e & VO_EVENT_RESIZE)
resize(vo);
}
static void prepare_texture(struct vo *vo)
{
struct priv *p = vo->priv;
@ -359,31 +351,11 @@ static int control(struct vo *vo, uint32_t request, void *data)
{
struct priv *p = vo->priv;
switch (request) {
case VOCTRL_ONTOP:
p->mpglctx->ontop(vo);
return VO_TRUE;
case VOCTRL_PAUSE:
if (!p->mpglctx->pause)
break;
p->mpglctx->pause(vo);
return VO_TRUE;
case VOCTRL_RESUME:
if (!p->mpglctx->resume)
break;
p->mpglctx->resume(vo);
return VO_TRUE;
case VOCTRL_FULLSCREEN:
p->mpglctx->fullscreen(vo);
resize(vo);
return VO_TRUE;
case VOCTRL_GET_PANSCAN:
return VO_TRUE;
case VOCTRL_SET_PANSCAN:
resize(vo);
return VO_TRUE;
case VOCTRL_UPDATE_SCREENINFO:
p->mpglctx->update_xinerama_info(vo);
return VO_TRUE;
case VOCTRL_REDRAW_FRAME:
do_render(vo);
return VO_TRUE;
@ -403,7 +375,13 @@ static int control(struct vo *vo, uint32_t request, void *data)
return VO_TRUE;
}
}
return VO_NOTIMPL;
int events = 0;
int r = p->mpglctx->vo_control(vo, &events, request, data);
if (events & VO_EVENT_RESIZE)
resize(vo);
return r;
}
const struct vo_driver video_out_corevideo = {
@ -420,7 +398,6 @@ const struct vo_driver video_out_corevideo = {
.draw_image = draw_image,
.draw_osd = draw_osd,
.flip_page = flip_page,
.check_events = check_events,
.uninit = uninit,
.priv_size = sizeof(struct priv),
};

View File

@ -192,19 +192,6 @@ static int config(struct vo *vo, uint32_t width, uint32_t height,
return 0;
}
static void check_events(struct vo *vo)
{
struct gl_priv *p = vo->priv;
mpgl_lock(p->glctx);
int e = p->glctx->check_events(vo);
if (e & VO_EVENT_RESIZE)
resize(p);
if (e & VO_EVENT_EXPOSE)
vo->want_redraw = true;
mpgl_unlock(p->glctx);
}
static bool reparse_cmdline(struct gl_priv *p, char *args)
{
struct m_config *cfg = NULL;
@ -239,41 +226,6 @@ static int control(struct vo *vo, uint32_t request, void *data)
struct gl_priv *p = vo->priv;
switch (request) {
case VOCTRL_ONTOP:
if (!p->glctx->ontop)
break;
mpgl_lock(p->glctx);
p->glctx->ontop(vo);
mpgl_unlock(p->glctx);
return VO_TRUE;
case VOCTRL_PAUSE:
if (!p->glctx->pause)
break;
mpgl_lock(p->glctx);
p->glctx->pause(vo);
mpgl_unlock(p->glctx);
return VO_TRUE;
case VOCTRL_RESUME:
if (!p->glctx->resume)
break;
mpgl_lock(p->glctx);
p->glctx->resume(vo);
mpgl_unlock(p->glctx);
return VO_TRUE;
case VOCTRL_FULLSCREEN:
mpgl_lock(p->glctx);
p->glctx->fullscreen(vo);
resize(p);
mpgl_unlock(p->glctx);
return VO_TRUE;
case VOCTRL_BORDER:
if (!p->glctx->border)
break;
mpgl_lock(p->glctx);
p->glctx->border(vo);
resize(p);
mpgl_unlock(p->glctx);
return VO_TRUE;
case VOCTRL_GET_PANSCAN:
return VO_TRUE;
case VOCTRL_SET_PANSCAN:
@ -310,13 +262,6 @@ static int control(struct vo *vo, uint32_t request, void *data)
gl_video_get_csp_override(p->renderer, data);
mpgl_unlock(p->glctx);
return VO_TRUE;
case VOCTRL_UPDATE_SCREENINFO:
if (!p->glctx->update_xinerama_info)
break;
mpgl_lock(p->glctx);
p->glctx->update_xinerama_info(vo);
mpgl_unlock(p->glctx);
return VO_TRUE;
case VOCTRL_SCREENSHOT: {
struct voctrl_screenshot_args *args = data;
mpgl_lock(p->glctx);
@ -337,7 +282,17 @@ static int control(struct vo *vo, uint32_t request, void *data)
return reparse_cmdline(p, arg);
}
}
return VO_NOTIMPL;
mpgl_lock(p->glctx);
int events = 0;
int r = p->glctx->vo_control(vo, &events, request, data);
if (events & VO_EVENT_RESIZE)
resize(p);
if (events & VO_EVENT_EXPOSE)
vo->want_redraw = true;
mpgl_unlock(p->glctx);
return r;
}
static void uninit(struct vo *vo)
@ -428,7 +383,6 @@ const struct vo_driver video_out_opengl = {
.draw_image = draw_image,
.draw_osd = draw_osd,
.flip_page = flip_page,
.check_events = check_events,
.uninit = uninit,
.priv_size = sizeof(struct gl_priv),
.options = options,
@ -449,7 +403,6 @@ const struct vo_driver video_out_opengl_hq = {
.draw_image = draw_image,
.draw_osd = draw_osd,
.flip_page = flip_page,
.check_events = check_events,
.uninit = uninit,
.priv_size = sizeof(struct gl_priv),
.options = options,

View File

@ -1750,17 +1750,6 @@ static int config(struct vo *vo, uint32_t width, uint32_t height,
return 0;
}
static void check_events(struct vo *vo)
{
struct gl_priv *p = vo->priv;
int e = p->glctx->check_events(vo);
if (e & VO_EVENT_RESIZE)
resize(vo, vo->dwidth, vo->dheight);
if (e & VO_EVENT_EXPOSE)
vo->want_redraw = true;
}
static void do_render(struct vo *vo)
{
struct gl_priv *p = vo->priv;
@ -2276,21 +2265,6 @@ static int control(struct vo *vo, uint32_t request, void *data)
struct gl_priv *p = vo->priv;
switch (request) {
case VOCTRL_ONTOP:
if (!p->glctx->ontop)
break;
p->glctx->ontop(vo);
return VO_TRUE;
case VOCTRL_FULLSCREEN:
p->glctx->fullscreen(vo);
resize(vo, vo->dwidth, vo->dheight);
return VO_TRUE;
case VOCTRL_BORDER:
if (!p->glctx->border)
break;
p->glctx->border(vo);
resize(vo, vo->dwidth, vo->dheight);
return VO_TRUE;
case VOCTRL_GET_PANSCAN:
return VO_TRUE;
case VOCTRL_SET_PANSCAN:
@ -2325,24 +2299,9 @@ static int control(struct vo *vo, uint32_t request, void *data)
case VOCTRL_GET_YUV_COLORSPACE:
*(struct mp_csp_details *)data = p->colorspace;
return VO_TRUE;
case VOCTRL_UPDATE_SCREENINFO:
if (!p->glctx->update_xinerama_info)
break;
p->glctx->update_xinerama_info(vo);
return VO_TRUE;
case VOCTRL_REDRAW_FRAME:
do_render(vo);
return true;
case VOCTRL_PAUSE:
if (!p->glctx->pause)
break;
p->glctx->pause(vo);
return VO_TRUE;
case VOCTRL_RESUME:
if (!p->glctx->resume)
break;
p->glctx->resume(vo);
return VO_TRUE;
case VOCTRL_SCREENSHOT: {
struct voctrl_screenshot_args *args = data;
if (args->full_window)
@ -2352,7 +2311,15 @@ static int control(struct vo *vo, uint32_t request, void *data)
return true;
}
}
return VO_NOTIMPL;
int events = 0;
int r = p->glctx->vo_control(vo, &events, request, data);
if (events & VO_EVENT_RESIZE)
resize(vo, vo->dwidth, vo->dheight);
if (events & VO_EVENT_EXPOSE)
vo->want_redraw = true;
return r;
}
const struct vo_driver video_out_opengl_old = {
@ -2369,6 +2336,5 @@ const struct vo_driver video_out_opengl_old = {
.draw_image = draw_image,
.draw_osd = draw_osd,
.flip_page = flip_page,
.check_events = check_events,
.uninit = uninit,
};

View File

@ -675,6 +675,30 @@ void vo_w32_ontop(struct vo *vo)
reinit_window_state(vo);
}
int vo_w32_control(struct vo *vo, int *events, int request, void *arg)
{
switch (request) {
case VOCTRL_CHECK_EVENTS:
*events |= vo_w32_check_events(vo);
return VO_TRUE;
case VOCTRL_FULLSCREEN:
vo_w32_fullscreen(vo);
*events |= VO_EVENT_RESIZE;
return VO_TRUE;
case VOCTRL_ONTOP:
vo_w32_ontop(vo);
return VO_TRUE;
case VOCTRL_BORDER:
vo_w32_border(vo);
*events |= VO_EVENT_RESIZE;
return VO_TRUE;
case VOCTRL_UPDATE_SCREENINFO:
w32_update_xinerama_info(vo);
return VO_TRUE;
}
return VO_NOTIMPL;
}
/**
* \brief Uninitialize w32_common framework.
*

View File

@ -56,6 +56,7 @@ void vo_w32_uninit(struct vo *vo);
void vo_w32_ontop(struct vo *vo);
void vo_w32_border(struct vo *vo);
void vo_w32_fullscreen(struct vo *vo);
int vo_w32_control(struct vo *vo, int *events, int request, void *arg);
int vo_w32_check_events(struct vo *vo);
int vo_w32_config(struct vo *vo, uint32_t, uint32_t, uint32_t);
void w32_update_xinerama_info(struct vo *vo);

View File

@ -862,3 +862,26 @@ void vo_wayland_update_window_title(struct vo *vo)
wl_shell_surface_set_title(w->shell_surface, vo_get_window_title(vo));
}
int vo_wayland_control(struct vo *vo, int *events, int request, void *arg)
{
switch (request) {
case VOCTRL_CHECK_EVENTS:
*events |= vo_wayland_check_events(vo);
return VO_TRUE;
case VOCTRL_FULLSCREEN:
vo_wayland_fullscreen(vo);
*events |= VO_EVENT_RESIZE;
return VO_TRUE;
case VOCTRL_ONTOP:
vo_wayland_ontop(vo);
return VO_TRUE;
case VOCTRL_BORDER:
vo_wayland_border(vo);
*events |= VO_EVENT_RESIZE;
return VO_TRUE;
case VOCTRL_UPDATE_SCREENINFO:
vo_wayland_update_screeninfo(vo);
return VO_TRUE;
}
return VO_NOTIMPL;
}

View File

@ -130,6 +130,7 @@ void vo_wayland_fullscreen(struct vo *vo);
void vo_wayland_update_screeninfo(struct vo *vo);
int vo_wayland_check_events(struct vo *vo);
void vo_wayland_update_window_title(struct vo *vo);
int vo_wayland_control(struct vo *vo, int *events, int request, void *arg);
#endif /* MPLAYER_WAYLAND_COMMON_H */

View File

@ -1385,6 +1385,30 @@ void vo_x11_border(struct vo *vo)
vo_x11_decoration(vo, vo->opts->border && !vo->opts->fs);
}
int vo_x11_control(struct vo *vo, int *events, int request, void *arg)
{
switch (request) {
case VOCTRL_CHECK_EVENTS:
*events |= vo_x11_check_events(vo);
return VO_TRUE;
case VOCTRL_FULLSCREEN:
vo_x11_fullscreen(vo);
*events |= VO_EVENT_RESIZE;
return VO_TRUE;
case VOCTRL_ONTOP:
vo_x11_ontop(vo);
return VO_TRUE;
case VOCTRL_BORDER:
vo_x11_border(vo);
*events |= VO_EVENT_RESIZE;
return VO_TRUE;
case VOCTRL_UPDATE_SCREENINFO:
vo_x11_update_screeninfo(vo);
return VO_TRUE;
}
return VO_NOTIMPL;
}
static void xscreensaver_heartbeat(struct vo_x11_state *x11)
{
unsigned int time = GetTimerMS();

View File

@ -143,6 +143,7 @@ void vo_x11_clearwindow(struct vo *vo, Window vo_window);
void vo_x11_ontop(struct vo *vo);
void vo_x11_border(struct vo *vo);
void vo_x11_update_screeninfo(struct vo *vo);
int vo_x11_control(struct vo *vo, int *events, int request, void *arg);
double vo_x11_vm_get_fps(struct vo *vo);