Skip to content

Commit 3ebc201

Browse files
author
sparks
committed
vo_libmpv: introduce 'gpu-next' render backend
1 parent 0bbcc91 commit 3ebc201

File tree

11 files changed

+1795
-19
lines changed

11 files changed

+1795
-19
lines changed

include/mpv/render.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,16 @@ typedef enum mpv_render_param_type {
422422
* See MPV_RENDER_PARAM_SW_STRIDE for alignment requirements.
423423
*/
424424
MPV_RENDER_PARAM_SW_POINTER = 20,
425+
/**
426+
* The name of the render backend to use. Valid for mpv_render_context_create().
427+
*
428+
* Type: char*
429+
*
430+
* Defined backends:
431+
* "gpu" (default)
432+
* "gpu-next"
433+
*/
434+
MPV_RENDER_PARAM_BACKEND = 21,
425435
} mpv_render_param_type;
426436

427437
/**

meson.build

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,9 @@ sources = files(
237237
'video/out/gpu/utils.c',
238238
'video/out/gpu/video.c',
239239
'video/out/gpu/video_shaders.c',
240+
'video/out/gpu_next/libmpv_gpu_next.c',
241+
'video/out/gpu_next/ra.c',
242+
'video/out/gpu_next/video.c',
240243
'video/out/libmpv_sw.c',
241244
'video/out/vo.c',
242245
'video/out/vo_gpu.c',

video/out/gpu_next/context.c

Lines changed: 201 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,26 @@
2222
#endif
2323

2424
#ifdef PL_HAVE_OPENGL
25+
#include "mpv/render_gl.h"
2526
#include <libplacebo/opengl.h>
27+
#include "video/out/gpu_next/libmpv_gpu_next.h"
28+
#include "video/out/gpu_next/ra.h"
2629
#endif
2730

2831
#include "context.h"
2932
#include "config.h"
30-
#include "common/common.h"
31-
#include "options/m_config.h"
33+
#include "common/msg.h"
3234
#include "video/out/placebo/utils.h"
33-
#include "video/out/gpu/video.h"
35+
#include <stddef.h>
36+
#include "mpv/client.h"
37+
#include "mpv/render.h"
38+
#include "options/options.h"
39+
#include "ta/ta_talloc.h"
40+
#include "video/out/gpu/context.h"
41+
#include "video/out/libmpv.h"
42+
#include "video/out/opengl/common.h"
43+
#include "video/out/vo.h"
44+
#include "video/out/vulkan/common.h"
3445

3546
#if HAVE_D3D11
3647
#include "osdep/windows_utils.h"
@@ -39,7 +50,6 @@
3950
#endif
4051

4152
#if HAVE_GL
42-
#include "video/out/opengl/context.h"
4353
#include "video/out/opengl/ra_gl.h"
4454
# if HAVE_EGL
4555
#include <EGL/egl.h>
@@ -50,6 +60,19 @@
5060
#include "video/out/vulkan/context.h"
5161
#endif
5262

63+
#if HAVE_GL
64+
// Store Libplacebo OpenGL context information.
65+
struct priv {
66+
pl_log pl_log;
67+
pl_opengl gl;
68+
pl_gpu gpu;
69+
struct ra_next *ra;
70+
71+
// Store a persistent copy of the init params to avoid a dangling pointer.
72+
mpv_opengl_init_params gl_params;
73+
};
74+
#endif
75+
5376
#if HAVE_D3D11
5477
static bool d3d11_pl_init(struct vo *vo, struct gpu_ctx *ctx,
5578
struct ra_ctx_opts *ctx_opts)
@@ -235,3 +258,177 @@ void gpu_ctx_destroy(struct gpu_ctx **ctxp)
235258
talloc_free(ctx);
236259
*ctxp = NULL;
237260
}
261+
262+
#if HAVE_GL && defined(PL_HAVE_OPENGL)
263+
/**
264+
* @brief Callback to make the OpenGL context current.
265+
* @param priv Pointer to the private data (mpv_opengl_init_params).
266+
* @return True on success, false on failure.
267+
*/
268+
static bool pl_callback_makecurrent_gl(void *priv)
269+
{
270+
mpv_opengl_init_params *gl_params = priv;
271+
// The mpv render API contract specifies that the client must make the
272+
// context current inside its get_proc_address callback. We can trigger
273+
// this by calling it with a harmless, common function name.
274+
if (gl_params && gl_params->get_proc_address) {
275+
gl_params->get_proc_address(gl_params->get_proc_address_ctx, "glGetString");
276+
return true;
277+
}
278+
279+
return false;
280+
}
281+
282+
/**
283+
* @brief Callback to release the OpenGL context.
284+
* @param priv Pointer to the private data (mpv_opengl_init_params).
285+
*/
286+
static void pl_callback_releasecurrent_gl(void *priv)
287+
{
288+
}
289+
290+
/**
291+
* @brief Callback to log messages from libplacebo.
292+
* @param log_priv Pointer to the private data (mp_log).
293+
* @param level The log level.
294+
* @param msg The log message.
295+
*/
296+
static void pl_log_cb(void *log_priv, enum pl_log_level level, const char *msg)
297+
{
298+
struct mp_log *log = log_priv;
299+
mp_msg(log, MSGL_WARN, "[gpu-next:pl] %s\n", msg);
300+
}
301+
302+
/**
303+
* @brief Initializes the OpenGL context for the GPU next renderer.
304+
* @param ctx The libmpv_gpu_next_context to initialize.
305+
* @param params The render parameters.
306+
* @return 0 on success, negative error code on failure.
307+
*/
308+
static int libmpv_gpu_next_init_gl(struct libmpv_gpu_next_context *ctx, mpv_render_param *params)
309+
{
310+
ctx->priv = talloc_zero(NULL, struct priv);
311+
struct priv *p = ctx->priv;
312+
313+
mpv_opengl_init_params *gl_params =
314+
get_mpv_render_param(params, MPV_RENDER_PARAM_OPENGL_INIT_PARAMS, NULL);
315+
if (!gl_params || !gl_params->get_proc_address)
316+
return MPV_ERROR_INVALID_PARAMETER;
317+
318+
// Make a persistent copy of the params struct's contents.
319+
p->gl_params = *gl_params;
320+
321+
// Setup libplacebo logging
322+
struct pl_log_params log_params = {
323+
.log_level = PL_LOG_DEBUG
324+
};
325+
326+
// Enable verbose logging if trace is enabled
327+
if (mp_msg_test(ctx->log, MSGL_TRACE)) {
328+
log_params.log_cb = pl_log_cb;
329+
log_params.log_priv = ctx->log;
330+
}
331+
332+
p->pl_log = pl_log_create(PL_API_VER, &log_params);
333+
p->gl = pl_opengl_create(p->pl_log, pl_opengl_params(
334+
.get_proc_addr_ex = (pl_voidfunc_t (*)(void*, const char*))gl_params->get_proc_address,
335+
.proc_ctx = gl_params->get_proc_address_ctx,
336+
.make_current = pl_callback_makecurrent_gl,
337+
.release_current = pl_callback_releasecurrent_gl,
338+
.priv = &p->gl_params // Pass the ADDRESS of our persistent copy
339+
));
340+
341+
if (!p->gl) {
342+
MP_ERR(ctx, "Failed to create libplacebo OpenGL context.\n");
343+
pl_log_destroy(&p->pl_log);
344+
return MPV_ERROR_UNSUPPORTED;
345+
}
346+
p->gpu = p->gl->gpu;
347+
348+
// Pass the libplacebo log to the RA as well.
349+
p->ra = ra_pl_create(p->gpu, ctx->log, p->pl_log);
350+
if (!p->ra) {
351+
pl_opengl_destroy(&p->gl);
352+
pl_log_destroy(&p->pl_log);
353+
return MPV_ERROR_VO_INIT_FAILED;
354+
}
355+
356+
ctx->ra = p->ra;
357+
ctx->gpu = p->gpu;
358+
return 0;
359+
}
360+
361+
/**
362+
* @brief Wraps an OpenGL framebuffer object (FBO) as a libplacebo texture.
363+
* @param ctx The libmpv_gpu_next_context.
364+
* @param params The render parameters.
365+
* @param out_tex Pointer to the output texture.
366+
* @return 0 on success, negative error code on failure.
367+
*/
368+
static int libmpv_gpu_next_wrap_fbo_gl(struct libmpv_gpu_next_context *ctx,
369+
mpv_render_param *params, pl_tex *out_tex)
370+
{
371+
struct priv *p = ctx->priv;
372+
*out_tex = NULL;
373+
374+
// Get the FBO from the render parameters
375+
mpv_opengl_fbo *fbo =
376+
get_mpv_render_param(params, MPV_RENDER_PARAM_OPENGL_FBO, NULL);
377+
if (!fbo)
378+
return MPV_ERROR_INVALID_PARAMETER;
379+
380+
// Wrap the FBO as a libplacebo texture
381+
pl_tex tex = pl_opengl_wrap(p->gpu, pl_opengl_wrap_params(
382+
.framebuffer = fbo->fbo,
383+
.width = fbo->w,
384+
.height = fbo->h,
385+
.iformat = fbo->internal_format
386+
));
387+
388+
if (!tex) {
389+
MP_ERR(ctx, "Failed to wrap provided FBO as a libplacebo texture.\n");
390+
return MPV_ERROR_GENERIC;
391+
}
392+
393+
*out_tex = tex;
394+
return 0;
395+
}
396+
397+
/**
398+
* @brief Callback to mark the end of a frame rendering.
399+
* @param ctx The libmpv_gpu_next_context.
400+
*/
401+
static void libmpv_gpu_next_done_frame_gl(struct libmpv_gpu_next_context *ctx)
402+
{
403+
// Nothing to do (yet), leaving the function empty.
404+
}
405+
406+
/**
407+
* @brief Destroys the OpenGL context for the GPU next renderer.
408+
* @param ctx The libmpv_gpu_next_context to destroy.
409+
*/
410+
static void libmpv_gpu_next_destroy_gl(struct libmpv_gpu_next_context *ctx)
411+
{
412+
struct priv *p = ctx->priv;
413+
if (!p)
414+
return;
415+
416+
if (p->ra) {
417+
ra_pl_destroy(&p->ra);
418+
}
419+
420+
pl_opengl_destroy(&p->gl);
421+
pl_log_destroy(&p->pl_log);
422+
}
423+
424+
/**
425+
* @brief Context functions for the OpenGL GPU next renderer.
426+
*/
427+
const struct libmpv_gpu_next_context_fns libmpv_gpu_next_context_gl = {
428+
.api_name = MPV_RENDER_API_TYPE_OPENGL,
429+
.init = libmpv_gpu_next_init_gl,
430+
.wrap_fbo = libmpv_gpu_next_wrap_fbo_gl,
431+
.done_frame = libmpv_gpu_next_done_frame_gl,
432+
.destroy = libmpv_gpu_next_destroy_gl,
433+
};
434+
#endif

video/out/gpu_next/context.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,20 @@
1717

1818
#pragma once
1919

20-
#include <libplacebo/renderer.h>
20+
#include "libplacebo/gpu.h" // for pl_gpu
21+
#include "libplacebo/log.h" // for pl_log
22+
#include "libplacebo/swapchain.h" // for pl_swapchain
23+
#include "stdbool.h" // for bool
2124

22-
struct mp_log;
23-
struct ra_ctx;
25+
/**
26+
* The rendering abstraction context.
27+
*/
2428
struct ra_ctx_opts;
2529
struct vo;
2630

31+
/**
32+
* The main GPU context structure.
33+
*/
2734
struct gpu_ctx {
2835
struct mp_log *log;
2936
struct ra_ctx *ra_ctx;

0 commit comments

Comments
 (0)