summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--video/out/gl_common.c76
-rw-r--r--video/out/gl_common.h49
-rw-r--r--video/out/vo_opengl.c4
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;