summaryrefslogtreecommitdiffstats
path: root/video/out/opengl/video.c
diff options
context:
space:
mode:
Diffstat (limited to 'video/out/opengl/video.c')
-rw-r--r--video/out/opengl/video.c50
1 files changed, 49 insertions, 1 deletions
diff --git a/video/out/opengl/video.c b/video/out/opengl/video.c
index 62bbfd1d05..3b99ba95ca 100644
--- a/video/out/opengl/video.c
+++ b/video/out/opengl/video.c
@@ -217,6 +217,7 @@ struct gl_video {
struct fbotex blend_subs_fbo;
struct fbotex output_fbo;
struct fbosurface surfaces[FBOSURFACES_MAX];
+ struct fbotex vdpau_deinterleave_fbo[2];
int surface_idx;
int surface_now;
@@ -585,6 +586,9 @@ static void uninit_rendering(struct gl_video *p)
for (int n = 0; n < MAX_SAVED_TEXTURES; n++)
fbotex_uninit(&p->hook_fbos[n]);
+ for (int n = 0; n < 2; n++)
+ fbotex_uninit(&p->vdpau_deinterleave_fbo[n]);
+
gl_video_reset_surfaces(p);
gl_video_reset_hooks(p);
@@ -957,7 +961,6 @@ static void render_pass_quad(struct gl_video *p, int vp_w, int vp_h,
debug_check_gl(p, "after rendering");
}
-// flags: see render_pass_quad
static void finish_pass_direct(struct gl_video *p, GLint fbo, int vp_w, int vp_h,
const struct mp_rect *dst)
{
@@ -2917,6 +2920,49 @@ static bool map_image(struct gl_video *p, struct mp_image *mpi)
return true;
}
+// This assumes nv12, with textures set to GL_NEAREST filtering.
+static void reinterleave_vdpau(struct gl_video *p, struct gl_hwdec_frame *frame)
+{
+ struct gl_hwdec_frame res = {0};
+ for (int n = 0; n < 2; n++) {
+ struct fbotex *fbo = &p->vdpau_deinterleave_fbo[n];
+ // This is an array of the 2 to-merge planes.
+ struct gl_hwdec_plane *src = &frame->planes[n * 2];
+ int w = src[0].tex_w;
+ int h = src[0].tex_h;
+ int ids[2];
+ for (int t = 0; t < 2; t++) {
+ ids[t] = pass_bind(p, (struct img_tex){
+ .gl_tex = src[t].gl_texture,
+ .gl_target = src[t].gl_target,
+ .multiplier = 1.0,
+ .transform = identity_trans,
+ .tex_w = w,
+ .tex_h = h,
+ .w = w,
+ .h = h,
+ });
+ }
+
+ GLSLF("color = fract(gl_FragCoord.y / 2) < 0.5\n");
+ GLSLF(" ? texture(texture%d, texcoord%d)\n", ids[0], ids[0]);
+ GLSLF(" : texture(texture%d, texcoord%d);", ids[1], ids[1]);
+
+ fbotex_change(fbo, p->gl, p->log, w, h * 2, n == 0 ? GL_R8 : GL_RG8, 0);
+
+ finish_pass_direct(p, fbo->fbo, fbo->rw, fbo->rh,
+ &(struct mp_rect){0, 0, w, h * 2});
+
+ res.planes[n] = (struct gl_hwdec_plane){
+ .gl_texture = fbo->texture,
+ .gl_target = GL_TEXTURE_2D,
+ .tex_w = w,
+ .tex_h = h * 2,
+ };
+ }
+ *frame = res;
+}
+
// Returns false on failure.
static bool gl_video_upload_image(struct gl_video *p, struct mp_image *mpi)
{
@@ -2943,6 +2989,8 @@ static bool gl_video_upload_image(struct gl_video *p, struct mp_image *mpi)
if (ok) {
struct mp_image layout = {0};
mp_image_set_params(&layout, &p->image_params);
+ if (gl_frame.vdpau_fields)
+ reinterleave_vdpau(p, &gl_frame);
for (int n = 0; n < p->plane_count; n++) {
struct gl_hwdec_plane *plane = &gl_frame.planes[n];
vimg->planes[n] = (struct texplane){