summaryrefslogtreecommitdiffstats
path: root/video/out/gpu/video.c
diff options
context:
space:
mode:
Diffstat (limited to 'video/out/gpu/video.c')
-rw-r--r--video/out/gpu/video.c103
1 files changed, 82 insertions, 21 deletions
diff --git a/video/out/gpu/video.c b/video/out/gpu/video.c
index 4cdf20dfae..29af4b92b1 100644
--- a/video/out/gpu/video.c
+++ b/video/out/gpu/video.c
@@ -277,8 +277,12 @@ struct gl_video {
struct cached_file *files;
int num_files;
- struct ra_hwdec *hwdec;
+ bool hwdec_interop_loading_done;
+ struct ra_hwdec **hwdecs;
+ int num_hwdecs;
+
struct ra_hwdec_mapper *hwdec_mapper;
+ struct ra_hwdec *hwdec_overlay;
bool hwdec_active;
bool dsi_warned;
@@ -401,6 +405,10 @@ const struct m_sub_options gl_video_conf = {
OPT_INTRANGE("gpu-tex-pad-y", tex_pad_y, 0, 0, 4096),
OPT_SUBSTRUCT("", icc_opts, mp_icc_conf, 0),
OPT_STRING("gpu-shader-cache-dir", shader_cache_dir, 0),
+ OPT_STRING_VALIDATE("gpu-hwdec-interop", hwdec_interop, 0,
+ ra_hwdec_validate_opt),
+ OPT_REPLACED("opengl-hwdec-interop", "gpu-hwdec-interop"),
+ OPT_REPLACED("hwdec-preload", "opengl-hwdec-interop"),
OPT_REPLACED("hdr-tone-mapping", "tone-mapping"),
OPT_REPLACED("opengl-shaders", "glsl-shaders"),
OPT_REPLACED("opengl-shader", "glsl-shader"),
@@ -803,18 +811,27 @@ static void init_video(struct gl_video *p)
{
p->use_integer_conversion = false;
- if (p->hwdec && ra_hwdec_test_format(p->hwdec, p->image_params.imgfmt)) {
- if (p->hwdec->driver->overlay_frame) {
+ struct ra_hwdec *hwdec = NULL;
+ for (int n = 0; n < p->num_hwdecs; n++) {
+ if (ra_hwdec_test_format(p->hwdecs[n], p->image_params.imgfmt)) {
+ hwdec = p->hwdecs[n];
+ break;
+ }
+ }
+
+ if (hwdec) {
+ if (hwdec->driver->overlay_frame) {
MP_WARN(p, "Using HW-overlay mode. No GL filtering is performed "
"on the video!\n");
+ p->hwdec_overlay = hwdec;
} else {
- p->hwdec_mapper = ra_hwdec_mapper_create(p->hwdec, &p->image_params);
+ p->hwdec_mapper = ra_hwdec_mapper_create(hwdec, &p->image_params);
if (!p->hwdec_mapper)
MP_ERR(p, "Initializing texture for hardware decoding failed.\n");
}
if (p->hwdec_mapper)
p->image_params = p->hwdec_mapper->dst_params;
- const char **exts = p->hwdec->glsl_extensions;
+ const char **exts = hwdec->glsl_extensions;
for (int n = 0; exts && exts[n]; n++)
gl_sc_enable_extension(p->sc, (char *)exts[n]);
p->hwdec_active = true;
@@ -957,8 +974,8 @@ static void unref_current_image(struct gl_video *p)
// lead to flickering artifacts.
static void unmap_overlay(struct gl_video *p)
{
- if (p->hwdec_active && p->hwdec->driver->overlay_frame)
- p->hwdec->driver->overlay_frame(p->hwdec, NULL, NULL, NULL, true);
+ if (p->hwdec_overlay)
+ p->hwdec_overlay->driver->overlay_frame(p->hwdec_overlay, NULL, NULL, NULL, true);
}
static void uninit_video(struct gl_video *p)
@@ -981,6 +998,7 @@ static void uninit_video(struct gl_video *p)
p->real_image_params = (struct mp_image_params){0};
p->image_params = p->real_image_params;
p->hwdec_active = false;
+ p->hwdec_overlay = NULL;
ra_hwdec_mapper_free(&p->hwdec_mapper);
}
@@ -3005,15 +3023,15 @@ void gl_video_render_frame(struct gl_video *p, struct vo_frame *frame,
p->ra->fns->clear(p->ra, fbo.tex, color, &target_rc);
}
- if (p->hwdec_active && p->hwdec->driver->overlay_frame) {
+ if (p->hwdec_overlay) {
if (has_frame) {
- float *color = p->hwdec->overlay_colorkey;
+ float *color = p->hwdec_overlay->overlay_colorkey;
p->ra->fns->clear(p->ra, fbo.tex, color, &p->dst_rect);
}
- p->hwdec->driver->overlay_frame(p->hwdec, frame->current,
- &p->src_rect, &p->dst_rect,
- frame->frame_id != p->image.id);
+ p->hwdec_overlay->driver->overlay_frame(p->hwdec_overlay, frame->current,
+ &p->src_rect, &p->dst_rect,
+ frame->frame_id != p->image.id);
if (frame->current)
p->osd_pts = frame->current->pts;
@@ -3507,6 +3525,10 @@ void gl_video_uninit(struct gl_video *p)
uninit_video(p);
+ for (int n = 0; n < p->num_hwdecs; n++)
+ ra_hwdec_uninit(p->hwdecs[n]);
+ p->num_hwdecs = 0;
+
gl_sc_destroy(p->sc);
ra_tex_free(p->ra, &p->lut_3d_texture);
@@ -3561,8 +3583,10 @@ bool gl_video_check_format(struct gl_video *p, int mp_format)
if (ra_get_imgfmt_desc(p->ra, mp_format, &desc) &&
is_imgfmt_desc_supported(p, &desc))
return true;
- if (p->hwdec && ra_hwdec_test_format(p->hwdec, mp_format))
- return true;
+ for (int n = 0; n < p->num_hwdecs; n++) {
+ if (ra_hwdec_test_format(p->hwdecs[n], mp_format))
+ return true;
+ }
return false;
}
@@ -3782,13 +3806,6 @@ void gl_video_set_ambient_lux(struct gl_video *p, int lux)
}
}
-void gl_video_set_hwdec(struct gl_video *p, struct ra_hwdec *hwdec)
-{
- unref_current_image(p);
- ra_hwdec_mapper_free(&p->hwdec_mapper);
- p->hwdec = hwdec;
-}
-
static void *gl_video_dr_alloc_buffer(struct gl_video *p, size_t size)
{
struct ra_buf_params params = {
@@ -3845,3 +3862,47 @@ struct mp_image *gl_video_get_image(struct gl_video *p, int imgfmt, int w, int h
gl_video_dr_free_buffer(p, ptr);
return res;
}
+
+static void load_add_hwdec(struct gl_video *p, struct mp_hwdec_devices *devs,
+ const struct ra_hwdec_driver *drv, bool is_auto)
+{
+ struct ra_hwdec *hwdec =
+ ra_hwdec_load_driver(p->ra, p->log, p->global, devs, drv, is_auto);
+ if (hwdec)
+ MP_TARRAY_APPEND(p, p->hwdecs, p->num_hwdecs, hwdec);
+}
+
+void gl_video_load_hwdecs(struct gl_video *p, struct mp_hwdec_devices *devs,
+ bool load_all_by_default)
+{
+ char *type = p->opts.hwdec_interop;
+ if (!type || !type[0] || strcmp(type, "auto") == 0) {
+ if (!load_all_by_default)
+ return;
+ type = "all";
+ }
+ if (strcmp(type, "no") == 0) {
+ // do nothing, just block further loading
+ } else if (strcmp(type, "all") == 0) {
+ for (int n = 0; ra_hwdec_drivers[n]; n++)
+ load_add_hwdec(p, devs, ra_hwdec_drivers[n], true);
+ } else {
+ for (int n = 0; ra_hwdec_drivers[n]; n++) {
+ const struct ra_hwdec_driver *drv = ra_hwdec_drivers[n];
+ if (strcmp(type, drv->name) == 0) {
+ load_add_hwdec(p, devs, drv, false);
+ break;
+ }
+ }
+ }
+ p->hwdec_interop_loading_done = true;
+}
+
+void gl_video_load_hwdecs_all(struct gl_video *p, struct mp_hwdec_devices *devs)
+{
+ if (!p->hwdec_interop_loading_done) {
+ for (int n = 0; ra_hwdec_drivers[n]; n++)
+ load_add_hwdec(p, devs, ra_hwdec_drivers[n], true);
+ p->hwdec_interop_loading_done = true;
+ }
+}