diff options
-rw-r--r-- | video/out/gl_common.c | 76 | ||||
-rw-r--r-- | video/out/gl_common.h | 49 | ||||
-rw-r--r-- | video/out/vo_opengl.c | 4 |
3 files changed, 106 insertions, 23 deletions
diff --git a/video/out/gl_common.c b/video/out/gl_common.c index 012e5d3912..31670ce75a 100644 --- a/video/out/gl_common.c +++ b/video/out/gl_common.c @@ -525,6 +525,7 @@ typedef void (*MPGLSetBackendFn)(MPGLContext *ctx); struct backend { const char *name; MPGLSetBackendFn init; + const struct mpgl_driver *driver; }; static const struct backend backends[] = { @@ -554,8 +555,10 @@ int mpgl_find_backend(const char *name) { if (name == NULL || strcmp(name, "auto") == 0) return -1; - for (const struct backend *entry = backends; entry->name; entry++) { - if (strcmp(entry->name, name) == 0) + for (int n = 0; n < MP_ARRAY_SIZE(backends); n++) { + const struct backend *entry = &backends[n]; + const char *ename = entry->driver ? entry->driver->name : entry->name; + if (strcmp(ename, name) == 0) return entry - backends; } return -2; @@ -567,8 +570,11 @@ int mpgl_validate_backend_opt(struct mp_log *log, const struct m_option *opt, if (bstr_equals0(param, "help")) { mp_info(log, "OpenGL windowing backends:\n"); mp_info(log, " auto (autodetect)\n"); - for (const struct backend *entry = backends; entry->name; entry++) - mp_info(log, " %s\n", entry->name); + for (int n = 0; n < MP_ARRAY_SIZE(backends); n++) { + const struct backend *entry = &backends[n]; + const char *ename = entry->driver ? entry->driver->name : entry->name; + mp_info(log, " %s\n", ename); + } return M_OPT_EXIT - 1; } char s[20]; @@ -576,26 +582,34 @@ int mpgl_validate_backend_opt(struct mp_log *log, const struct m_option *opt, return mpgl_find_backend(s) >= -1 ? 1 : M_OPT_INVALID; } -static MPGLContext *init_backend(struct vo *vo, MPGLSetBackendFn set_backend, +static MPGLContext *init_backend(struct vo *vo, const struct backend *backend, bool probing, int vo_flags) { MPGLContext *ctx = talloc_ptrtype(NULL, ctx); *ctx = (MPGLContext) { .gl = talloc_zero(ctx, GL), .vo = vo, + .driver = backend->driver, + .requested_gl_version = 300, }; bool old_probing = vo->probing; vo->probing = probing; // hack; kill it once backends are separate - set_backend(ctx); - if (!ctx->vo_init(vo)) { - talloc_free(ctx); - return NULL; + if (ctx->driver) { + ctx->priv = talloc_zero_size(ctx, ctx->driver->priv_size); + if (ctx->driver->init(ctx, vo_flags) < 0) { + talloc_free(ctx); + return NULL; + } + } else { + backend->init(ctx); + if (!ctx->vo_init(vo)) { + talloc_free(ctx); + return NULL; + } } vo->probing = old_probing; - ctx->requested_gl_version = 300; - - if (!ctx->config_window(ctx, vo_flags | VOFLAG_HIDDEN)) + if (!ctx->driver && !ctx->config_window(ctx, vo_flags | VOFLAG_HIDDEN)) goto cleanup; if (!ctx->gl->version && !ctx->gl->es) @@ -628,13 +642,13 @@ MPGLContext *mpgl_init(struct vo *vo, const char *backend_name, int vo_flags) MPGLContext *ctx = NULL; int index = mpgl_find_backend(backend_name); if (index == -1) { - for (const struct backend *entry = backends; entry->name; entry++) { - ctx = init_backend(vo, entry->init, true, vo_flags); + for (int n = 0; n < MP_ARRAY_SIZE(backends); n++) { + ctx = init_backend(vo, &backends[n], true, vo_flags); if (ctx) break; } } else if (index >= 0) { - ctx = init_backend(vo, backends[index].init, false, vo_flags); + ctx = init_backend(vo, &backends[index], false, vo_flags); } return ctx; } @@ -642,14 +656,40 @@ MPGLContext *mpgl_init(struct vo *vo, const char *backend_name, int vo_flags) // flags: passed to the backend function bool mpgl_reconfig_window(struct MPGLContext *ctx, int vo_flags) { - return ctx->config_window(ctx, vo_flags); + if (ctx->driver) { + return ctx->driver->reconfig(ctx, vo_flags) >= 0; + } else { + return ctx->config_window(ctx, vo_flags); + } +} + +int mpgl_control(struct MPGLContext *ctx, int *events, int request, void *arg) +{ + if (ctx->driver) { + return ctx->driver->control(ctx, events, request, arg); + } else { + return ctx->vo_control(ctx->vo, events, request, arg); + } +} + +void mpgl_swap_buffers(struct MPGLContext *ctx) +{ + if (ctx->driver) { + ctx->driver->swap_buffers(ctx); + } else { + ctx->swapGlBuffers(ctx); + } } void mpgl_uninit(MPGLContext *ctx) { if (ctx) { - ctx->releaseGlContext(ctx); - ctx->vo_uninit(ctx->vo); + if (ctx->driver) { + ctx->driver->uninit(ctx); + } else { + ctx->releaseGlContext(ctx); + ctx->vo_uninit(ctx->vo); + } } talloc_free(ctx); } diff --git a/video/out/gl_common.h b/video/out/gl_common.h index 7d037cd518..711db271bd 100644 --- a/video/out/gl_common.h +++ b/video/out/gl_common.h @@ -74,9 +74,47 @@ enum { #define MPGL_VER_P(ver) MPGL_VER_GET_MAJOR(ver), MPGL_VER_GET_MINOR(ver) +struct MPGLContext; + +// A backend (like X11, win32, ...), which provides OpenGL rendering. +// This should be preferred for new code, instead of setting the callbacks +// in MPGLContext directly. +struct mpgl_driver { + const char *name; + + // Size of the struct allocated for MPGLContext.priv + int priv_size; + + // Init the GL context and possibly the underlying VO backend. + // Return 0 on success, negative value (-1) on error. + int (*init)(struct MPGLContext *ctx, int vo_flags); + + // Resize the window, or create a new window if there isn't one yet. + // On the first call, it creates a GL context according to what's specified + // in MPGLContext.requested_gl_version. This is just a hint, and if the + // requested version is not available, it may return a completely different + // GL context. (The caller must check if the created GL version is ok. The + // callee must try to fall back to an older version if the requested + // version is not available, and newer versions are incompatible.) + // Currently, there is an unfortunate interaction with ctx->vo, and + // display size etc. are determined by it. + // Return 0 on success, negative value (-1) on error. + int (*reconfig)(struct MPGLContext *ctx, int flags); + + // Present the frame. + void (*swap_buffers)(struct MPGLContext *ctx); + + // This behaves exactly like vo_driver.control(). + int (*control)(struct MPGLContext *ctx, int *events, int request, void *arg); + + // Destroy the GL context and possibly the underlying VO backend. + void (*uninit)(struct MPGLContext *ctx); +}; + typedef struct MPGLContext { GL *gl; struct vo *vo; + const struct mpgl_driver *driver; // Bit size of each component in the created framebuffer. 0 if unknown. int depth_r, depth_g, depth_b; @@ -85,6 +123,12 @@ typedef struct MPGLContext { // (Might be different from the actual version in gl->version.) int requested_gl_version; + // For free use by the mpgl_driver. + void *priv; + + // Warning: all callbacks below are legacy. Newer code should use + // a mpgl_driver struct, which replaces these callbacks. + void (*swapGlBuffers)(struct MPGLContext *); int (*vo_init)(struct vo *vo); void (*vo_uninit)(struct vo *vo); @@ -110,14 +154,13 @@ typedef struct MPGLContext { // with swapGlBuffers(). This returns false if use of the OpenGL context // should be avoided. bool (*start_frame)(struct MPGLContext *); - - // For free use by the backend. - void *priv; } MPGLContext; MPGLContext *mpgl_init(struct vo *vo, const char *backend_name, int vo_flags); void mpgl_uninit(MPGLContext *ctx); bool mpgl_reconfig_window(struct MPGLContext *ctx, int vo_flags); +int mpgl_control(struct MPGLContext *ctx, int *events, int request, void *arg); +void mpgl_swap_buffers(struct MPGLContext *ctx); int mpgl_find_backend(const char *name); diff --git a/video/out/vo_opengl.c b/video/out/vo_opengl.c index 115c0fcebe..bc1abdb0f9 100644 --- a/video/out/vo_opengl.c +++ b/video/out/vo_opengl.c @@ -130,7 +130,7 @@ static void flip_page(struct vo *vo) } p->frame_started = false; - p->glctx->swapGlBuffers(p->glctx); + mpgl_swap_buffers(p->glctx); p->frames_rendered++; if (p->frames_rendered > 5 && !p->use_gl_debug) @@ -375,7 +375,7 @@ static int control(struct vo *vo, uint32_t request, void *data) } int events = 0; - int r = p->glctx->vo_control(vo, &events, request, data); + int r = mpgl_control(p->glctx, &events, request, data); if (events & VO_EVENT_ICC_PROFILE_CHANGED) { get_and_update_icc_profile(p, &events); vo->want_redraw = true; |