| 
15 | 15 |  * License along with mpv.  If not, see <https://www.gnu.org/licenses/>.  | 
16 | 16 |  */  | 
17 | 17 | 
 
  | 
18 |  | -#include <libplacebo/config.h>  | 
 | 18 | +#include <libplacebo/config.h>                   // for PL_HAVE_OPENGL, PL_API_VER  | 
19 | 19 | 
 
  | 
20 | 20 | #ifdef PL_HAVE_D3D11  | 
21 | 21 | #include <libplacebo/d3d11.h>  | 
22 | 22 | #endif  | 
23 | 23 | 
 
  | 
24 | 24 | #ifdef PL_HAVE_OPENGL  | 
25 |  | -#include <libplacebo/opengl.h>  | 
 | 25 | +#include "mpv/render_gl.h"                       // for mpv_opengl_init_params  | 
 | 26 | +#include <libplacebo/opengl.h>                   // for pl_opengl_destroy  | 
 | 27 | +#include "video/out/gpu_next/libmpv_gpu_next.h"  // for libmpv_gpu_next_context  | 
 | 28 | +#include "video/out/gpu_next/ra.h"               // for ra_pl_create, ra_pl_...  | 
26 | 29 | #endif  | 
27 | 30 | 
 
  | 
28 |  | -#include "context.h"  | 
29 |  | -#include "config.h"  | 
30 |  | -#include "common/common.h"  | 
31 |  | -#include "options/m_config.h"  | 
32 |  | -#include "video/out/placebo/utils.h"  | 
33 |  | -#include "video/out/gpu/video.h"  | 
 | 31 | +#include <stddef.h>                              // for NULL  | 
 | 32 | +#include "config.h"                              // for HAVE_GL, HAVE_D3D11  | 
 | 33 | +#include "context.h"                             // for gpu_ctx  | 
 | 34 | +#include "common/msg.h"                          // for MP_ERR, mp_msg, mp_msg_err  | 
 | 35 | +#include "mpv/client.h"                          // for mpv_error  | 
 | 36 | +#include "mpv/render.h"                          // for mpv_render_param  | 
 | 37 | +#include "options/options.h"                     // for mp_vo_opts  | 
 | 38 | +#include "ta/ta_talloc.h"                        // for talloc_zero, talloc_...  | 
 | 39 | +#include "video/out/gpu/context.h"               // for ra_ctx_opts, ra_ctx  | 
 | 40 | +#include "video/out/libmpv.h"                    // for get_mpv_render_param  | 
 | 41 | +#include "video/out/opengl/common.h"             // for GL  | 
 | 42 | +#include "video/out/placebo/utils.h"             // for mppl_log_set_probing  | 
 | 43 | +#include "video/out/vo.h"                        // for vo  | 
34 | 44 | 
 
  | 
35 | 45 | #if HAVE_D3D11  | 
36 | 46 | #include "osdep/windows_utils.h"  | 
 | 
39 | 49 | #endif  | 
40 | 50 | 
 
  | 
41 | 51 | #if HAVE_GL  | 
42 |  | -#include "video/out/opengl/context.h"  | 
43 |  | -#include "video/out/opengl/ra_gl.h"  | 
 | 52 | +#include "video/out/opengl/ra_gl.h"              // for ra_is_gl, ra_gl_get  | 
44 | 53 | # if HAVE_EGL  | 
45 |  | -#include <EGL/egl.h>  | 
 | 54 | +#include <EGL/egl.h>                             // for eglGetCurrentContext  | 
46 | 55 | # endif  | 
47 | 56 | #endif  | 
48 | 57 | 
 
  | 
49 | 58 | #if HAVE_VULKAN  | 
50 |  | -#include "video/out/vulkan/context.h"  | 
 | 59 | +#include "video/out/vulkan/context.h"            // for ra_vk_ctx_get  | 
 | 60 | +#endif  | 
 | 61 | + | 
 | 62 | +#if HAVE_GL  | 
 | 63 | +// Store Libplacebo OpenGL context information.  | 
 | 64 | +struct priv {  | 
 | 65 | +    pl_log pl_log;  | 
 | 66 | +    pl_opengl gl;  | 
 | 67 | +    pl_gpu gpu;  | 
 | 68 | +    struct ra_next *ra;  | 
 | 69 | + | 
 | 70 | +    // Store a persistent copy of the init params to avoid a dangling pointer.  | 
 | 71 | +    mpv_opengl_init_params gl_params;  | 
 | 72 | +};  | 
51 | 73 | #endif  | 
52 | 74 | 
 
  | 
53 | 75 | #if HAVE_D3D11  | 
@@ -235,3 +257,177 @@ void gpu_ctx_destroy(struct gpu_ctx **ctxp)  | 
235 | 257 |     talloc_free(ctx);  | 
236 | 258 |     *ctxp = NULL;  | 
237 | 259 | }  | 
 | 260 | + | 
 | 261 | +#if HAVE_GL && defined(PL_HAVE_OPENGL)  | 
 | 262 | +/**  | 
 | 263 | + * @brief Callback to make the OpenGL context current.  | 
 | 264 | + * @param priv Pointer to the private data (mpv_opengl_init_params).  | 
 | 265 | + * @return True on success, false on failure.  | 
 | 266 | + */  | 
 | 267 | +static bool pl_callback_makecurrent_gl(void *priv)  | 
 | 268 | +{  | 
 | 269 | +    mpv_opengl_init_params *gl_params = priv;  | 
 | 270 | +    // The mpv render API contract specifies that the client must make the  | 
 | 271 | +    // context current inside its get_proc_address callback. We can trigger  | 
 | 272 | +    // this by calling it with a harmless, common function name.  | 
 | 273 | +    if (gl_params && gl_params->get_proc_address) {  | 
 | 274 | +        gl_params->get_proc_address(gl_params->get_proc_address_ctx, "glGetString");  | 
 | 275 | +        return true;  | 
 | 276 | +    }  | 
 | 277 | + | 
 | 278 | +    return false;  | 
 | 279 | +}  | 
 | 280 | + | 
 | 281 | +/**  | 
 | 282 | + * @brief Callback to release the OpenGL context.  | 
 | 283 | + * @param priv Pointer to the private data (mpv_opengl_init_params).  | 
 | 284 | + */  | 
 | 285 | +static void pl_callback_releasecurrent_gl(void *priv)  | 
 | 286 | +{  | 
 | 287 | +}  | 
 | 288 | + | 
 | 289 | +/**  | 
 | 290 | + * @brief Callback to log messages from libplacebo.  | 
 | 291 | + * @param log_priv Pointer to the private data (mp_log).  | 
 | 292 | + * @param level The log level.  | 
 | 293 | + * @param msg The log message.  | 
 | 294 | + */  | 
 | 295 | +static void pl_log_cb(void *log_priv, enum pl_log_level level, const char *msg)  | 
 | 296 | +{  | 
 | 297 | +    struct mp_log *log = log_priv;  | 
 | 298 | +    mp_msg(log, MSGL_WARN, "[gpu-next:pl] %s\n", msg);  | 
 | 299 | +}  | 
 | 300 | + | 
 | 301 | +/**  | 
 | 302 | + * @brief Initializes the OpenGL context for the GPU next renderer.  | 
 | 303 | + * @param ctx The libmpv_gpu_next_context to initialize.  | 
 | 304 | + * @param params The render parameters.  | 
 | 305 | + * @return 0 on success, negative error code on failure.  | 
 | 306 | + */  | 
 | 307 | +static int libmpv_gpu_next_init_gl(struct libmpv_gpu_next_context *ctx, mpv_render_param *params)  | 
 | 308 | +{  | 
 | 309 | +    ctx->priv = talloc_zero(NULL, struct priv);  | 
 | 310 | +    struct priv *p = ctx->priv;  | 
 | 311 | + | 
 | 312 | +    mpv_opengl_init_params *gl_params =  | 
 | 313 | +    get_mpv_render_param(params, MPV_RENDER_PARAM_OPENGL_INIT_PARAMS, NULL);  | 
 | 314 | +    if (!gl_params || !gl_params->get_proc_address)  | 
 | 315 | +        return MPV_ERROR_INVALID_PARAMETER;  | 
 | 316 | + | 
 | 317 | +    // Make a persistent copy of the params struct's contents.  | 
 | 318 | +    p->gl_params = *gl_params;  | 
 | 319 | + | 
 | 320 | +    // Setup libplacebo logging  | 
 | 321 | +    struct pl_log_params log_params = {  | 
 | 322 | +        .log_level = PL_LOG_DEBUG  | 
 | 323 | +    };  | 
 | 324 | + | 
 | 325 | +    // Enable verbose logging if trace is enabled  | 
 | 326 | +    if (mp_msg_test(ctx->log, MSGL_TRACE)) {  | 
 | 327 | +        log_params.log_cb = pl_log_cb;  | 
 | 328 | +        log_params.log_priv = ctx->log;  | 
 | 329 | +    }  | 
 | 330 | + | 
 | 331 | +    p->pl_log = pl_log_create(PL_API_VER, &log_params);  | 
 | 332 | +    p->gl = pl_opengl_create(p->pl_log, pl_opengl_params(  | 
 | 333 | +        .get_proc_addr_ex = (pl_voidfunc_t (*)(void*, const char*))gl_params->get_proc_address,  | 
 | 334 | +        .proc_ctx = gl_params->get_proc_address_ctx,  | 
 | 335 | +        .make_current = pl_callback_makecurrent_gl,  | 
 | 336 | +        .release_current = pl_callback_releasecurrent_gl,  | 
 | 337 | +        .priv = &p->gl_params // Pass the ADDRESS of our persistent copy  | 
 | 338 | +    ));  | 
 | 339 | + | 
 | 340 | +    if (!p->gl) {  | 
 | 341 | +        MP_ERR(ctx, "Failed to create libplacebo OpenGL context.\n");  | 
 | 342 | +        pl_log_destroy(&p->pl_log);  | 
 | 343 | +        return MPV_ERROR_UNSUPPORTED;  | 
 | 344 | +    }  | 
 | 345 | +    p->gpu = p->gl->gpu;  | 
 | 346 | + | 
 | 347 | +    // Pass the libplacebo log to the RA as well.  | 
 | 348 | +    p->ra = ra_pl_create(p->gpu, ctx->log, p->pl_log);  | 
 | 349 | +    if (!p->ra) {  | 
 | 350 | +        pl_opengl_destroy(&p->gl);  | 
 | 351 | +        pl_log_destroy(&p->pl_log);  | 
 | 352 | +        return MPV_ERROR_VO_INIT_FAILED;  | 
 | 353 | +    }  | 
 | 354 | + | 
 | 355 | +    ctx->ra = p->ra;  | 
 | 356 | +    ctx->gpu = p->gpu;  | 
 | 357 | +    return 0;  | 
 | 358 | +}  | 
 | 359 | + | 
 | 360 | +/**  | 
 | 361 | + * @brief Wraps an OpenGL framebuffer object (FBO) as a libplacebo texture.  | 
 | 362 | + * @param ctx The libmpv_gpu_next_context.  | 
 | 363 | + * @param params The render parameters.  | 
 | 364 | + * @param out_tex Pointer to the output texture.  | 
 | 365 | + * @return 0 on success, negative error code on failure.  | 
 | 366 | + */  | 
 | 367 | +static int libmpv_gpu_next_wrap_fbo_gl(struct libmpv_gpu_next_context *ctx,  | 
 | 368 | +                    mpv_render_param *params, pl_tex *out_tex)  | 
 | 369 | +{  | 
 | 370 | +    struct priv *p = ctx->priv;  | 
 | 371 | +    *out_tex = NULL;  | 
 | 372 | + | 
 | 373 | +    // Get the FBO from the render parameters  | 
 | 374 | +    mpv_opengl_fbo *fbo =  | 
 | 375 | +        get_mpv_render_param(params, MPV_RENDER_PARAM_OPENGL_FBO, NULL);  | 
 | 376 | +    if (!fbo)  | 
 | 377 | +        return MPV_ERROR_INVALID_PARAMETER;  | 
 | 378 | + | 
 | 379 | +    // Wrap the FBO as a libplacebo texture  | 
 | 380 | +    pl_tex tex = pl_opengl_wrap(p->gpu, pl_opengl_wrap_params(  | 
 | 381 | +        .framebuffer = fbo->fbo,  | 
 | 382 | +        .width = fbo->w,  | 
 | 383 | +        .height = fbo->h,  | 
 | 384 | +        .iformat = fbo->internal_format  | 
 | 385 | +    ));  | 
 | 386 | + | 
 | 387 | +    if (!tex) {  | 
 | 388 | +        MP_ERR(ctx, "Failed to wrap provided FBO as a libplacebo texture.\n");  | 
 | 389 | +        return MPV_ERROR_GENERIC;  | 
 | 390 | +    }  | 
 | 391 | + | 
 | 392 | +    *out_tex = tex;  | 
 | 393 | +    return 0;  | 
 | 394 | +}  | 
 | 395 | + | 
 | 396 | +/**  | 
 | 397 | + * @brief Callback to mark the end of a frame rendering.  | 
 | 398 | + * @param ctx The libmpv_gpu_next_context.  | 
 | 399 | + */  | 
 | 400 | +static void libmpv_gpu_next_done_frame_gl(struct libmpv_gpu_next_context *ctx)  | 
 | 401 | +{  | 
 | 402 | +    // Nothing to do (yet), leaving the function empty.  | 
 | 403 | +}  | 
 | 404 | + | 
 | 405 | +/**  | 
 | 406 | + * @brief Destroys the OpenGL context for the GPU next renderer.  | 
 | 407 | + * @param ctx The libmpv_gpu_next_context to destroy.  | 
 | 408 | + */  | 
 | 409 | +static void libmpv_gpu_next_destroy_gl(struct libmpv_gpu_next_context *ctx)  | 
 | 410 | +{  | 
 | 411 | +    struct priv *p = ctx->priv;  | 
 | 412 | +    if (!p)  | 
 | 413 | +        return;  | 
 | 414 | + | 
 | 415 | +    if (p->ra) {  | 
 | 416 | +        ra_pl_destroy(&p->ra);  | 
 | 417 | +    }  | 
 | 418 | + | 
 | 419 | +    pl_opengl_destroy(&p->gl);  | 
 | 420 | +    pl_log_destroy(&p->pl_log);  | 
 | 421 | +}  | 
 | 422 | + | 
 | 423 | +/**  | 
 | 424 | + * @brief Context functions for the OpenGL GPU next renderer.  | 
 | 425 | + */  | 
 | 426 | +const struct libmpv_gpu_next_context_fns libmpv_gpu_next_context_gl = {  | 
 | 427 | +    .api_name = MPV_RENDER_API_TYPE_OPENGL,  | 
 | 428 | +    .init = libmpv_gpu_next_init_gl,  | 
 | 429 | +    .wrap_fbo = libmpv_gpu_next_wrap_fbo_gl,  | 
 | 430 | +    .done_frame = libmpv_gpu_next_done_frame_gl,  | 
 | 431 | +    .destroy = libmpv_gpu_next_destroy_gl,  | 
 | 432 | +};  | 
 | 433 | +#endif  | 
0 commit comments