/src/mpv/video/out/opengl/libmpv_gl.c
Line | Count | Source |
1 | | #include "common.h" |
2 | | #include "context.h" |
3 | | #include "ra_gl.h" |
4 | | #include "options/m_config.h" |
5 | | #include "mpv/render_gl.h" |
6 | | #include "video/out/gpu/libmpv_gpu.h" |
7 | | #include "video/out/gpu/ra.h" |
8 | | |
9 | | struct priv { |
10 | | GL *gl; |
11 | | struct ra_ctx *ra_ctx; |
12 | | }; |
13 | | |
14 | | static int init(struct libmpv_gpu_context *ctx, mpv_render_param *params) |
15 | 0 | { |
16 | 0 | ctx->priv = talloc_zero(NULL, struct priv); |
17 | 0 | struct priv *p = ctx->priv; |
18 | |
|
19 | 0 | mpv_opengl_init_params *init_params = |
20 | 0 | get_mpv_render_param(params, MPV_RENDER_PARAM_OPENGL_INIT_PARAMS, NULL); |
21 | 0 | if (!init_params) |
22 | 0 | return MPV_ERROR_INVALID_PARAMETER; |
23 | | |
24 | 0 | p->gl = talloc_zero(p, GL); |
25 | |
|
26 | 0 | mpgl_load_functions2(p->gl, init_params->get_proc_address, |
27 | 0 | init_params->get_proc_address_ctx, |
28 | 0 | NULL, ctx->log); |
29 | 0 | if (!p->gl->version && !p->gl->es) { |
30 | 0 | MP_FATAL(ctx, "OpenGL not initialized.\n"); |
31 | 0 | return MPV_ERROR_UNSUPPORTED; |
32 | 0 | } |
33 | | |
34 | | // initialize a blank ra_ctx to reuse ra_gl_ctx |
35 | 0 | p->ra_ctx = talloc_zero(p, struct ra_ctx); |
36 | 0 | p->ra_ctx->log = ctx->log; |
37 | 0 | p->ra_ctx->global = ctx->global; |
38 | 0 | p->ra_ctx->opts = (struct ra_ctx_opts) { |
39 | 0 | .allow_sw = true, |
40 | 0 | }; |
41 | | |
42 | | // vo_libmpv is essentially like a gigantic external swapchain where |
43 | | // the user is in charge of presentation / swapping etc. But we don't |
44 | | // actually need to provide any of these functions, since we can just |
45 | | // not call them to begin with - so just set it to an empty object to |
46 | | // signal to ra_gl_p that we don't care about its latency emulation |
47 | | // functionality |
48 | 0 | struct ra_ctx_params gl_params = {0}; |
49 | 0 | p->gl->SwapInterval = NULL; // we shouldn't randomly change this, so lock it |
50 | 0 | if (!ra_gl_ctx_init(p->ra_ctx, p->gl, gl_params)) |
51 | 0 | return MPV_ERROR_UNSUPPORTED; |
52 | | |
53 | 0 | struct ra_ctx_opts *ctx_opts = mp_get_config_group(ctx, ctx->global, &ra_ctx_conf); |
54 | 0 | p->ra_ctx->opts.debug = ctx_opts->debug; |
55 | 0 | p->gl->debug_context = ctx_opts->debug; |
56 | 0 | ra_gl_set_debug(p->ra_ctx->ra, ctx_opts->debug); |
57 | 0 | talloc_free(ctx_opts); |
58 | |
|
59 | 0 | ctx->ra_ctx = p->ra_ctx; |
60 | |
|
61 | 0 | return 0; |
62 | 0 | } |
63 | | |
64 | | static int wrap_fbo(struct libmpv_gpu_context *ctx, mpv_render_param *params, |
65 | | struct ra_tex **out) |
66 | 0 | { |
67 | 0 | struct priv *p = ctx->priv; |
68 | |
|
69 | 0 | mpv_opengl_fbo *fbo = |
70 | 0 | get_mpv_render_param(params, MPV_RENDER_PARAM_OPENGL_FBO, NULL); |
71 | 0 | if (!fbo) |
72 | 0 | return MPV_ERROR_INVALID_PARAMETER; |
73 | | |
74 | 0 | if (fbo->fbo && !(p->gl->mpgl_caps & MPGL_CAP_FB)) { |
75 | 0 | MP_FATAL(ctx, "Rendering to FBO requested, but no FBO extension found!\n"); |
76 | 0 | return MPV_ERROR_UNSUPPORTED; |
77 | 0 | } |
78 | | |
79 | 0 | struct ra_swapchain *sw = p->ra_ctx->swapchain; |
80 | 0 | struct ra_fbo target; |
81 | 0 | ra_gl_ctx_resize(sw, fbo->w, fbo->h, fbo->fbo); |
82 | 0 | ra_gl_ctx_start_frame(sw, &target); |
83 | 0 | *out = target.tex; |
84 | 0 | return 0; |
85 | 0 | } |
86 | | |
87 | | static void done_frame(struct libmpv_gpu_context *ctx, bool ds) |
88 | 0 | { |
89 | 0 | struct priv *p = ctx->priv; |
90 | |
|
91 | 0 | struct ra_swapchain *sw = p->ra_ctx->swapchain; |
92 | 0 | struct vo_frame dummy = {.display_synced = ds}; |
93 | 0 | ra_gl_ctx_submit_frame(sw, &dummy); |
94 | 0 | } |
95 | | |
96 | | static void destroy(struct libmpv_gpu_context *ctx) |
97 | 0 | { |
98 | 0 | struct priv *p = ctx->priv; |
99 | |
|
100 | 0 | if (p->ra_ctx) |
101 | 0 | ra_gl_ctx_uninit(p->ra_ctx); |
102 | 0 | } |
103 | | |
104 | | const struct libmpv_gpu_context_fns libmpv_gpu_context_gl = { |
105 | | .api_name = MPV_RENDER_API_TYPE_OPENGL, |
106 | | .init = init, |
107 | | .wrap_fbo = wrap_fbo, |
108 | | .done_frame = done_frame, |
109 | | .destroy = destroy, |
110 | | }; |