Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OpenGL context support for vo_gpu_next #9486

Merged
merged 3 commits into from
Nov 22, 2021
Merged
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
2 changes: 1 addition & 1 deletion DOCS/man/vo.rst
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ Available video output drivers are:
the same set of features as ``--vo=gpu``. See `GPU renderer options`_ for a
list.

Currently, this only supports ``--gpu-api=vulkan``, and no hardware
Currently, this only supports Vulkan, OpenGL and no hardware
decoding. Unlike ``--vo=gpu``, the FBO formats are not tunable, but you can
still set ``--gpu-dumb-mode=yes`` to forcibly disable their use.

Expand Down
3 changes: 2 additions & 1 deletion meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -979,7 +979,8 @@ if libplacebo.found()
features += 'libplacebo-v4'
libplacebo_v4 = true
message('libplacebo v4.170+ found! Enabling vo_gpu_next.')
sources += files('video/out/vo_gpu_next.c')
sources += files('video/out/vo_gpu_next.c',
'video/out/gpu_next/context.c')
else
message('libplacebo v4.170+ not found! Disabling vo_gpu_next.')
endif
Expand Down
143 changes: 143 additions & 0 deletions video/out/gpu_next/context.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/*
* This file is part of mpv.
*
* mpv is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* mpv is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with mpv. If not, see <https://www.gnu.org/licenses/>.
*/

#include <libplacebo/config.h>

#ifdef PL_HAVE_OPENGL
#include <libplacebo/opengl.h>
#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"

#if HAVE_GL
#include "video/out/opengl/context.h"
#include "video/out/opengl/ra_gl.h"
#endif

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

struct priv {
#ifdef PL_HAVE_OPENGL
pl_opengl opengl;
#else
char dummy;
#endif
};

struct gpu_ctx *gpu_ctx_create(struct vo *vo, struct gl_video_opts *gl_opts)
{
struct gpu_ctx *ctx = talloc_zero(NULL, struct gpu_ctx);
ctx->log = vo->log;
ctx->priv = talloc_zero(ctx, struct priv);
struct priv *p = ctx->priv;

struct ra_ctx_opts *ctx_opts = mp_get_config_group(ctx, vo->global, &ra_ctx_conf);
ctx_opts->want_alpha = gl_opts->alpha_mode == ALPHA_YES;
ctx->ra_ctx = ra_ctx_create(vo, *ctx_opts);
if (!ctx->ra_ctx)
goto err_out;

#if HAVE_VULKAN
struct mpvk_ctx *vkctx = ra_vk_ctx_get(ctx->ra_ctx);
if (vkctx) {
ctx->pllog = vkctx->ctx;
ctx->gpu = vkctx->gpu;
ctx->swapchain = vkctx->swapchain;
return ctx;
}
#endif

#if HAVE_GL && defined(PL_HAVE_OPENGL)
if (ra_is_gl(ctx->ra_ctx->ra)) {
ctx->pllog = pl_log_create(PL_API_VER, NULL);
if (!ctx->pllog)
goto err_out;

mppl_ctx_set_log(ctx->pllog, ctx->log, vo->probing);
mp_verbose(ctx->log, "Initialized libplacebo %s (API v%d)\n",
PL_VERSION, PL_API_VER);

p->opengl = pl_opengl_create(ctx->pllog, pl_opengl_params(
.debug = ctx_opts->debug,
.allow_software = ctx_opts->allow_sw,
));
if (!p->opengl)
goto err_out;
ctx->gpu = p->opengl->gpu;

mppl_ctx_set_log(ctx->pllog, ctx->log, false); // disable probing

ctx->swapchain = pl_opengl_create_swapchain(p->opengl, pl_opengl_swapchain_params(
.max_swapchain_depth = vo->opts->swapchain_depth,
));
if (!ctx->swapchain)
goto err_out;

return ctx;
}
#elif HAVE_GL
if (ra_is_gl(ctx->ra_ctx->ra)) {
MP_MSG(ctx, vo->probing ? MSGL_V : MSGL_ERR,
"libplacebo was built without OpenGL support.\n");
}
#endif

err_out:
gpu_ctx_destroy(&ctx);
return NULL;
}

bool gpu_ctx_resize(struct gpu_ctx *ctx, int w, int h)
{
struct priv *p = ctx->priv;

#ifdef PL_HAVE_OPENGL
// The vulkan context handles this on its own, so only for OpenGL here
if (p->opengl)
return pl_swapchain_resize(ctx->swapchain, &w, &h);
#endif

return true;
}
sfan5 marked this conversation as resolved.
Show resolved Hide resolved

void gpu_ctx_destroy(struct gpu_ctx **ctxp)
{
struct gpu_ctx *ctx = *ctxp;
if (!ctx)
return;
struct priv *p = ctx->priv;

#if HAVE_GL && defined(PL_HAVE_OPENGL)
if (ra_is_gl(ctx->ra_ctx->ra)) {
pl_swapchain_destroy(&ctx->swapchain);
pl_opengl_destroy(&p->opengl);
pl_log_destroy(&ctx->pllog);
}
#endif

ra_ctx_destroy(&ctx->ra_ctx);

talloc_free(ctx);
*ctxp = NULL;
}
41 changes: 41 additions & 0 deletions video/out/gpu_next/context.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* This file is part of mpv.
*
* mpv is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* mpv is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with mpv. If not, see <https://www.gnu.org/licenses/>.
*/

#pragma once

#include <libplacebo/renderer.h>

struct mp_log;
struct ra_ctx;
struct vo;
struct gl_video_opts;

struct gpu_ctx {
struct mp_log *log;

struct ra_ctx *ra_ctx;

pl_log pllog;
pl_gpu gpu;
pl_swapchain swapchain;

void *priv;
};

struct gpu_ctx *gpu_ctx_create(struct vo *vo, struct gl_video_opts *gl_opts);
bool gpu_ctx_resize(struct gpu_ctx *ctx, int w, int h);
void gpu_ctx_destroy(struct gpu_ctx **ctxp);
2 changes: 2 additions & 0 deletions video/out/opengl/context.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,8 @@ int ra_gl_ctx_color_depth(struct ra_swapchain *sw)
bool ra_gl_ctx_start_frame(struct ra_swapchain *sw, struct ra_fbo *out_fbo)
{
struct priv *p = sw->priv;
if (!out_fbo)
return true;
*out_fbo = (struct ra_fbo) {
.tex = p->wrapped_fb,
.flip = !p->params.flipped, // OpenGL FBs are normally flipped
Expand Down
62 changes: 30 additions & 32 deletions video/out/vo_gpu_next.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,7 @@
#include "gpu/video.h"
#include "gpu/video_shaders.h"
#include "sub/osd.h"

#if HAVE_VULKAN
#include "vulkan/context.h"
#endif
#include "gpu_next/context.h"

struct osd_entry {
pl_tex tex;
Expand Down Expand Up @@ -77,6 +74,7 @@ struct priv {
struct mp_log *log;
struct mpv_global *global;
struct ra_ctx *ra_ctx;
haasn marked this conversation as resolved.
Show resolved Hide resolved
struct gpu_ctx *context;

pl_log pllog;
pl_gpu gpu;
Expand Down Expand Up @@ -211,7 +209,7 @@ static struct mp_image *get_image(struct vo *vo, int imgfmt, int w, int h,

static void write_overlays(struct vo *vo, struct mp_osd_res res, double pts,
int flags, struct osd_state *state,
struct pl_frame *frame)
struct pl_frame *frame, bool flip)
{
struct priv *p = vo->priv;
static const bool subfmt_all[SUBBITMAP_COUNT] = {
Expand Down Expand Up @@ -257,7 +255,7 @@ static void write_overlays(struct vo *vo, struct mp_osd_res res, double pts,
for (int i = 0; i < item->num_parts; i++) {
const struct sub_bitmap *b = &item->parts[i];
uint32_t c = b->libass.color;
MP_TARRAY_APPEND(p, entry->parts, entry->num_parts, (struct pl_overlay_part) {
struct pl_overlay_part part = {
.src = { b->src_x, b->src_y, b->src_x + b->w, b->src_y + b->h },
.dst = { b->x, b->y, b->x + b->dw, b->y + b->dh },
.color = {
Expand All @@ -266,7 +264,13 @@ static void write_overlays(struct vo *vo, struct mp_osd_res res, double pts,
((c >> 8) & 0xFF) / 255.0,
1.0 - (c & 0xFF) / 255.0,
}
});
};
if (flip) {
assert(frame->crop.y0 > frame->crop.y1);
part.dst.y0 = frame->crop.y0 - part.dst.y0;
part.dst.y1 = frame->crop.y0 - part.dst.y1;
}
MP_TARRAY_APPEND(p, entry->parts, entry->num_parts, part);
}

struct pl_overlay *ol = &state->overlays[frame->num_overlays++];
Expand Down Expand Up @@ -459,7 +463,7 @@ static bool map_frame(pl_gpu gpu, pl_tex *tex, const struct pl_source_frame *src
// compensate for anamorphic sources (render subtitles as normal)
.display_par = (float) mpi->params.p_h / mpi->params.p_w,
};
write_overlays(vo, vidres, mpi->pts, OSD_DRAW_SUB_ONLY, &fp->subs, frame);
write_overlays(vo, vidres, mpi->pts, OSD_DRAW_SUB_ONLY, &fp->subs, frame, false);

// Update LUT attached to this frame
update_lut(p, &p->image_lut);
Expand Down Expand Up @@ -656,8 +660,10 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
// Calculate target
struct pl_frame target;
pl_frame_from_swapchain(&target, &swframe);
write_overlays(vo, p->osd_res, 0, OSD_DRAW_OSD_ONLY, &p->osd_state, &target);
write_overlays(vo, p->osd_res, 0, OSD_DRAW_OSD_ONLY, &p->osd_state, &target, swframe.flipped);
target.crop = (struct pl_rect2df) { p->dst.x0, p->dst.y0, p->dst.x1, p->dst.y1 };
if (swframe.flipped)
MPSWAP(float, target.crop.y0, target.crop.y1);

update_lut(p, &p->target_lut);
target.lut = p->target_lut.lut;
Expand Down Expand Up @@ -794,6 +800,7 @@ static void resize(struct vo *vo)
{
struct priv *p = vo->priv;
vo_get_src_dst_rects(vo, &p->src, &p->dst, &p->osd_res);
gpu_ctx_resize(p->context, vo->dwidth, vo->dheight);
vo->want_redraw = true;
}

Expand Down Expand Up @@ -951,7 +958,12 @@ static void uninit(struct vo *vo)
}

pl_renderer_destroy(&p->rr);
ra_ctx_destroy(&p->ra_ctx);

p->ra_ctx = NULL;
p->pllog = NULL;
p->gpu = NULL;
p->sw = NULL;
gpu_ctx_destroy(&p->context);
}

static int preinit(struct vo *vo)
Expand All @@ -963,30 +975,16 @@ static int preinit(struct vo *vo)
p->log = vo->log;

struct gl_video_opts *gl_opts = p->opts_cache->opts;
struct ra_ctx_opts *ctx_opts = mp_get_config_group(p, vo->global, &ra_ctx_conf);
struct ra_ctx_opts opts = *ctx_opts;
opts.context_type = "vulkan";
opts.context_name = NULL;
opts.want_alpha = gl_opts->alpha_mode == ALPHA_YES;
p->ra_ctx = ra_ctx_create(vo, opts);
if (!p->ra_ctx)
goto err_out;

#if HAVE_VULKAN
struct mpvk_ctx *vkctx = ra_vk_ctx_get(p->ra_ctx);
if (vkctx) {
p->pllog = vkctx->ctx;
p->gpu = vkctx->gpu;
p->sw = vkctx->swapchain;
goto done;
}
#endif

// TODO: wrap GL contexts

goto err_out;
p->context = gpu_ctx_create(vo, gl_opts);
if (!p->context)
goto err_out;
// For the time being
p->ra_ctx = p->context->ra_ctx;
p->pllog = p->context->pllog;
p->gpu = p->context->gpu;
p->sw = p->context->swapchain;

done:
p->rr = pl_renderer_create(p->pllog, p->gpu);
p->queue = pl_queue_create(p->gpu);
p->osd_fmt[SUBBITMAP_LIBASS] = pl_find_named_fmt(p->gpu, "r8");
Expand Down
1 change: 1 addition & 0 deletions wscript_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,7 @@ def swift(task):
( "video/out/gpu/utils.c" ),
( "video/out/gpu/video.c" ),
( "video/out/gpu/video_shaders.c" ),
( "video/out/gpu_next/context.c", "libplacebo-v4" ),
( "video/out/hwdec/hwdec_cuda.c", "cuda-interop" ),
( "video/out/hwdec/hwdec_cuda_gl.c", "cuda-interop && gl" ),
( "video/out/hwdec/hwdec_cuda_vk.c", "cuda-interop && vulkan" ),
Expand Down