mirror of https://github.com/mpv-player/mpv
115 lines
3.5 KiB
C
115 lines
3.5 KiB
C
#include "common.h"
|
|
#include "context.h"
|
|
#include "ra_gl.h"
|
|
#include "options/m_config.h"
|
|
#include "libmpv/render_gl.h"
|
|
#include "video/out/gpu/libmpv_gpu.h"
|
|
#include "video/out/gpu/ra.h"
|
|
|
|
struct priv {
|
|
GL *gl;
|
|
struct ra_ctx *ra_ctx;
|
|
};
|
|
|
|
static int init(struct libmpv_gpu_context *ctx, mpv_render_param *params)
|
|
{
|
|
ctx->priv = talloc_zero(NULL, struct priv);
|
|
struct priv *p = ctx->priv;
|
|
|
|
mpv_opengl_init_params *init_params =
|
|
get_mpv_render_param(params, MPV_RENDER_PARAM_OPENGL_INIT_PARAMS, NULL);
|
|
if (!init_params)
|
|
return MPV_ERROR_INVALID_PARAMETER;
|
|
|
|
p->gl = talloc_zero(p, GL);
|
|
|
|
mpgl_load_functions2(p->gl, init_params->get_proc_address,
|
|
init_params->get_proc_address_ctx,
|
|
NULL, ctx->log);
|
|
if (!p->gl->version && !p->gl->es) {
|
|
MP_FATAL(ctx, "OpenGL not initialized.\n");
|
|
return MPV_ERROR_UNSUPPORTED;
|
|
}
|
|
|
|
// initialize a blank ra_ctx to reuse ra_gl_ctx
|
|
p->ra_ctx = talloc_zero(p, struct ra_ctx);
|
|
p->ra_ctx->log = ctx->log;
|
|
p->ra_ctx->global = ctx->global;
|
|
p->ra_ctx->opts = (struct ra_ctx_opts) {
|
|
.allow_sw = true,
|
|
};
|
|
|
|
static const struct ra_swapchain_fns empty_swapchain_fns = {0};
|
|
struct ra_gl_ctx_params gl_params = {
|
|
// vo_libmpv is essentially like a gigantic external swapchain where
|
|
// the user is in charge of presentation / swapping etc. But we don't
|
|
// actually need to provide any of these functions, since we can just
|
|
// not call them to begin with - so just set it to an empty object to
|
|
// signal to ra_gl_p that we don't care about its latency emulation
|
|
// functionality
|
|
.external_swapchain = &empty_swapchain_fns
|
|
};
|
|
|
|
p->gl->SwapInterval = NULL; // we shouldn't randomly change this, so lock it
|
|
if (!ra_gl_ctx_init(p->ra_ctx, p->gl, gl_params))
|
|
return MPV_ERROR_UNSUPPORTED;
|
|
|
|
struct ra_ctx_opts *ctx_opts = mp_get_config_group(ctx, ctx->global, &ra_ctx_conf);
|
|
p->ra_ctx->opts.debug = ctx_opts->debug;
|
|
p->gl->debug_context = ctx_opts->debug;
|
|
ra_gl_set_debug(p->ra_ctx->ra, ctx_opts->debug);
|
|
talloc_free(ctx_opts);
|
|
|
|
ctx->ra_ctx = p->ra_ctx;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int wrap_fbo(struct libmpv_gpu_context *ctx, mpv_render_param *params,
|
|
struct ra_tex **out)
|
|
{
|
|
struct priv *p = ctx->priv;
|
|
|
|
mpv_opengl_fbo *fbo =
|
|
get_mpv_render_param(params, MPV_RENDER_PARAM_OPENGL_FBO, NULL);
|
|
if (!fbo)
|
|
return MPV_ERROR_INVALID_PARAMETER;
|
|
|
|
if (fbo->fbo && !(p->gl->mpgl_caps & MPGL_CAP_FB)) {
|
|
MP_FATAL(ctx, "Rendering to FBO requested, but no FBO extension found!\n");
|
|
return MPV_ERROR_UNSUPPORTED;
|
|
}
|
|
|
|
struct ra_swapchain *sw = p->ra_ctx->swapchain;
|
|
struct ra_fbo target;
|
|
ra_gl_ctx_resize(sw, fbo->w, fbo->h, fbo->fbo);
|
|
ra_gl_ctx_start_frame(sw, &target);
|
|
*out = target.tex;
|
|
return 0;
|
|
}
|
|
|
|
static void done_frame(struct libmpv_gpu_context *ctx, bool ds)
|
|
{
|
|
struct priv *p = ctx->priv;
|
|
|
|
struct ra_swapchain *sw = p->ra_ctx->swapchain;
|
|
struct vo_frame dummy = {.display_synced = ds};
|
|
ra_gl_ctx_submit_frame(sw, &dummy);
|
|
}
|
|
|
|
static void destroy(struct libmpv_gpu_context *ctx)
|
|
{
|
|
struct priv *p = ctx->priv;
|
|
|
|
if (p->ra_ctx)
|
|
ra_gl_ctx_uninit(p->ra_ctx);
|
|
}
|
|
|
|
const struct libmpv_gpu_context_fns libmpv_gpu_context_gl = {
|
|
.api_name = MPV_RENDER_API_TYPE_OPENGL,
|
|
.init = init,
|
|
.wrap_fbo = wrap_fbo,
|
|
.done_frame = done_frame,
|
|
.destroy = destroy,
|
|
};
|