Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions include/mpv/render.h
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,16 @@ typedef enum mpv_render_param_type {
* See MPV_RENDER_PARAM_SW_STRIDE for alignment requirements.
*/
MPV_RENDER_PARAM_SW_POINTER = 20,
/**
* The name of the render backend to use. Valid for mpv_render_context_create().
*
* Type: char*
*
* Defined backends:
* "gpu" (default)
* "gpu-next"
*/
MPV_RENDER_PARAM_BACKEND = 21,
} mpv_render_param_type;

/**
Expand Down
3 changes: 3 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,9 @@ sources = files(
'video/out/gpu/utils.c',
'video/out/gpu/video.c',
'video/out/gpu/video_shaders.c',
'video/out/gpu_next/libmpv_gpu_next.c',
'video/out/gpu_next/ra.c',
'video/out/gpu_next/video.c',
'video/out/libmpv_sw.c',
'video/out/vo.c',
'video/out/vo_gpu.c',
Expand Down
220 changes: 208 additions & 12 deletions video/out/gpu_next/context.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,32 @@
* License along with mpv. If not, see <https://www.gnu.org/licenses/>.
*/

#include <libplacebo/config.h>
#include <libplacebo/config.h> // for PL_HAVE_OPENGL, PL_API_VER

#ifdef PL_HAVE_D3D11
#include <libplacebo/d3d11.h>
#endif

#ifdef PL_HAVE_OPENGL
#include <libplacebo/opengl.h>
#include "mpv/render_gl.h" // for mpv_opengl_init_params
#include <libplacebo/opengl.h> // for pl_opengl_destroy
#include "video/out/gpu_next/libmpv_gpu_next.h" // for libmpv_gpu_next_context
#include "video/out/gpu_next/ra.h" // for ra_pl_create, ra_pl_...
#endif

#include "context.h"
#include "config.h"
#include "common/common.h"
#include "options/m_config.h"
#include "video/out/placebo/utils.h"
#include "video/out/gpu/video.h"
#include <stddef.h> // for NULL
#include "config.h" // for HAVE_GL, HAVE_D3D11
#include "context.h" // for gpu_ctx
#include "common/msg.h" // for MP_ERR, mp_msg, mp_msg_err
#include "mpv/client.h" // for mpv_error
#include "mpv/render.h" // for mpv_render_param
#include "options/options.h" // for mp_vo_opts
#include "ta/ta_talloc.h" // for talloc_zero, talloc_...
#include "video/out/gpu/context.h" // for ra_ctx_opts, ra_ctx
#include "video/out/libmpv.h" // for get_mpv_render_param
#include "video/out/opengl/common.h" // for GL
#include "video/out/placebo/utils.h" // for mppl_log_set_probing
#include "video/out/vo.h" // for vo

#if HAVE_D3D11
#include "osdep/windows_utils.h"
Expand All @@ -39,15 +49,27 @@
#endif

#if HAVE_GL
#include "video/out/opengl/context.h"
#include "video/out/opengl/ra_gl.h"
#include "video/out/opengl/ra_gl.h" // for ra_is_gl, ra_gl_get
# if HAVE_EGL
#include <EGL/egl.h>
#include <EGL/egl.h> // for eglGetCurrentContext
# endif
#endif

#if HAVE_VULKAN
#include "video/out/vulkan/context.h"
#include "video/out/vulkan/context.h" // for ra_vk_ctx_get
#endif

#if HAVE_GL
// Store Libplacebo OpenGL context information.
struct priv {
pl_log pl_log;
pl_opengl gl;
pl_gpu gpu;
struct ra_next *ra;

// Store a persistent copy of the init params to avoid a dangling pointer.
mpv_opengl_init_params gl_params;
};
#endif

#if HAVE_D3D11
Expand Down Expand Up @@ -235,3 +257,177 @@ void gpu_ctx_destroy(struct gpu_ctx **ctxp)
talloc_free(ctx);
*ctxp = NULL;
}

#if HAVE_GL && defined(PL_HAVE_OPENGL)
/**
* @brief Callback to make the OpenGL context current.
* @param priv Pointer to the private data (mpv_opengl_init_params).
* @return True on success, false on failure.
*/
static bool pl_callback_makecurrent_gl(void *priv)
{
mpv_opengl_init_params *gl_params = priv;
// The mpv render API contract specifies that the client must make the
// context current inside its get_proc_address callback. We can trigger
// this by calling it with a harmless, common function name.
if (gl_params && gl_params->get_proc_address) {
gl_params->get_proc_address(gl_params->get_proc_address_ctx, "glGetString");
return true;
}

return false;
}

/**
* @brief Callback to release the OpenGL context.
* @param priv Pointer to the private data (mpv_opengl_init_params).
*/
static void pl_callback_releasecurrent_gl(void *priv)
{
}

/**
* @brief Callback to log messages from libplacebo.
* @param log_priv Pointer to the private data (mp_log).
* @param level The log level.
* @param msg The log message.
*/
static void pl_log_cb(void *log_priv, enum pl_log_level level, const char *msg)
{
struct mp_log *log = log_priv;
mp_msg(log, MSGL_WARN, "[gpu-next:pl] %s\n", msg);
}

/**
* @brief Initializes the OpenGL context for the GPU next renderer.
* @param ctx The libmpv_gpu_next_context to initialize.
* @param params The render parameters.
* @return 0 on success, negative error code on failure.
*/
static int libmpv_gpu_next_init_gl(struct libmpv_gpu_next_context *ctx, mpv_render_param *params)
{
ctx->priv = talloc_zero(NULL, struct priv);
struct priv *p = ctx->priv;

mpv_opengl_init_params *gl_params =
get_mpv_render_param(params, MPV_RENDER_PARAM_OPENGL_INIT_PARAMS, NULL);
if (!gl_params || !gl_params->get_proc_address)
return MPV_ERROR_INVALID_PARAMETER;

// Make a persistent copy of the params struct's contents.
p->gl_params = *gl_params;

// Setup libplacebo logging
struct pl_log_params log_params = {
.log_level = PL_LOG_DEBUG
};

// Enable verbose logging if trace is enabled
if (mp_msg_test(ctx->log, MSGL_TRACE)) {
log_params.log_cb = pl_log_cb;
log_params.log_priv = ctx->log;
}

p->pl_log = pl_log_create(PL_API_VER, &log_params);
p->gl = pl_opengl_create(p->pl_log, pl_opengl_params(
.get_proc_addr_ex = (pl_voidfunc_t (*)(void*, const char*))gl_params->get_proc_address,
.proc_ctx = gl_params->get_proc_address_ctx,
.make_current = pl_callback_makecurrent_gl,
.release_current = pl_callback_releasecurrent_gl,
.priv = &p->gl_params // Pass the ADDRESS of our persistent copy
));

if (!p->gl) {
MP_ERR(ctx, "Failed to create libplacebo OpenGL context.\n");
pl_log_destroy(&p->pl_log);
return MPV_ERROR_UNSUPPORTED;
}
p->gpu = p->gl->gpu;

// Pass the libplacebo log to the RA as well.
p->ra = ra_pl_create(p->gpu, ctx->log, p->pl_log);
if (!p->ra) {
pl_opengl_destroy(&p->gl);
pl_log_destroy(&p->pl_log);
return MPV_ERROR_VO_INIT_FAILED;
}

ctx->ra = p->ra;
ctx->gpu = p->gpu;
return 0;
}

/**
* @brief Wraps an OpenGL framebuffer object (FBO) as a libplacebo texture.
* @param ctx The libmpv_gpu_next_context.
* @param params The render parameters.
* @param out_tex Pointer to the output texture.
* @return 0 on success, negative error code on failure.
*/
static int libmpv_gpu_next_wrap_fbo_gl(struct libmpv_gpu_next_context *ctx,
mpv_render_param *params, pl_tex *out_tex)
{
struct priv *p = ctx->priv;
*out_tex = NULL;

// Get the FBO from the render parameters
mpv_opengl_fbo *fbo =
get_mpv_render_param(params, MPV_RENDER_PARAM_OPENGL_FBO, NULL);
if (!fbo)
return MPV_ERROR_INVALID_PARAMETER;

// Wrap the FBO as a libplacebo texture
pl_tex tex = pl_opengl_wrap(p->gpu, pl_opengl_wrap_params(
.framebuffer = fbo->fbo,
.width = fbo->w,
.height = fbo->h,
.iformat = fbo->internal_format
));

if (!tex) {
MP_ERR(ctx, "Failed to wrap provided FBO as a libplacebo texture.\n");
return MPV_ERROR_GENERIC;
}

*out_tex = tex;
return 0;
}

/**
* @brief Callback to mark the end of a frame rendering.
* @param ctx The libmpv_gpu_next_context.
*/
static void libmpv_gpu_next_done_frame_gl(struct libmpv_gpu_next_context *ctx)
{
// Nothing to do (yet), leaving the function empty.
}

/**
* @brief Destroys the OpenGL context for the GPU next renderer.
* @param ctx The libmpv_gpu_next_context to destroy.
*/
static void libmpv_gpu_next_destroy_gl(struct libmpv_gpu_next_context *ctx)
{
struct priv *p = ctx->priv;
if (!p)
return;

if (p->ra) {
ra_pl_destroy(&p->ra);
}

pl_opengl_destroy(&p->gl);
pl_log_destroy(&p->pl_log);
}

/**
* @brief Context functions for the OpenGL GPU next renderer.
*/
const struct libmpv_gpu_next_context_fns libmpv_gpu_next_context_gl = {
.api_name = MPV_RENDER_API_TYPE_OPENGL,
.init = libmpv_gpu_next_init_gl,
.wrap_fbo = libmpv_gpu_next_wrap_fbo_gl,
.done_frame = libmpv_gpu_next_done_frame_gl,
.destroy = libmpv_gpu_next_destroy_gl,
};
#endif
13 changes: 10 additions & 3 deletions video/out/gpu_next/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,20 @@

#pragma once

#include <libplacebo/renderer.h>
#include "libplacebo/gpu.h" // for pl_gpu
#include "libplacebo/log.h" // for pl_log
#include "libplacebo/swapchain.h" // for pl_swapchain
#include "stdbool.h" // for bool

struct mp_log;
struct ra_ctx;
/**
* The rendering abstraction context.
*/
struct ra_ctx_opts;
struct vo;

/**
* The main GPU context structure.
*/
struct gpu_ctx {
struct mp_log *log;
struct ra_ctx *ra_ctx;
Expand Down
Loading