summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2015-05-13 23:55:07 +0200
committerwm4 <wm4@nowhere>2015-05-14 00:05:43 +0200
commitdf97c30e0e324a7a51c3cb4a24eb27fcf30462b2 (patch)
tree4ac7c8ebec7cc932ef96c80f128c79a7ce8c3383 /video
parent10de9b091a59e4831bb3fbfc46eb1d3c7558c9d8 (diff)
downloadmpv-df97c30e0e324a7a51c3cb4a24eb27fcf30462b2.tar.bz2
mpv-df97c30e0e324a7a51c3cb4a24eb27fcf30462b2.tar.xz
vo_opengl: create new API for OpenGL VO backends
An attempt to get rid of the weird mix of callbacks that take either struct vo or MPGLCopntext as parameter. This is not perfect, and the API will probably change a bit until all other code is ported to it. the main question is how to separate struct vo completely from the windowing code, which actually needs vo for very little. In the end, the legacy callbacks will be dropped.
Diffstat (limited to 'video')
-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;