summaryrefslogtreecommitdiffstats
path: root/video/out/opengl/hwdec_vdpau.c
diff options
context:
space:
mode:
Diffstat (limited to 'video/out/opengl/hwdec_vdpau.c')
-rw-r--r--video/out/opengl/hwdec_vdpau.c155
1 files changed, 111 insertions, 44 deletions
diff --git a/video/out/opengl/hwdec_vdpau.c b/video/out/opengl/hwdec_vdpau.c
index b1d49622fc..83f664a756 100644
--- a/video/out/opengl/hwdec_vdpau.c
+++ b/video/out/opengl/hwdec_vdpau.c
@@ -36,20 +36,35 @@ struct priv {
struct mp_vdpau_ctx *ctx;
uint64_t preemption_counter;
struct mp_image_params image_params;
- GLuint gl_texture;
+ GLuint gl_textures[4];
bool vdpgl_initialized;
GLvdpauSurfaceNV vdpgl_surface;
VdpOutputSurface vdp_surface;
struct mp_vdpau_mixer *mixer;
+ bool direct_mode;
bool mapped;
};
+static void unmap(struct gl_hwdec *hw)
+{
+ struct priv *p = hw->priv;
+ GL *gl = hw->gl;
+
+ if (p->mapped) {
+ gl->VDPAUUnmapSurfacesNV(1, &p->vdpgl_surface);
+ if (p->direct_mode) {
+ gl->VDPAUUnregisterSurfaceNV(p->vdpgl_surface);
+ p->vdpgl_surface = 0;
+ }
+ }
+ p->mapped = false;
+}
+
static void mark_vdpau_objects_uninitialized(struct gl_hwdec *hw)
{
struct priv *p = hw->priv;
p->vdp_surface = VDP_INVALID_HANDLE;
- p->mixer->video_mixer = VDP_INVALID_HANDLE;
p->mapped = false;
}
@@ -60,16 +75,15 @@ static void destroy_objects(struct gl_hwdec *hw)
struct vdp_functions *vdp = &p->ctx->vdp;
VdpStatus vdp_st;
- if (p->mapped)
- gl->VDPAUUnmapSurfacesNV(1, &p->vdpgl_surface);
- p->mapped = false;
+ unmap(hw);
if (p->vdpgl_surface)
gl->VDPAUUnregisterSurfaceNV(p->vdpgl_surface);
p->vdpgl_surface = 0;
- glDeleteTextures(1, &p->gl_texture);
- p->gl_texture = 0;
+ glDeleteTextures(4, p->gl_textures);
+ for (int n = 0; n < 4; n++)
+ p->gl_textures[n] = 0;
if (p->vdp_surface != VDP_INVALID_HANDLE) {
vdp_st = vdp->output_surface_destroy(p->vdp_surface);
@@ -77,14 +91,14 @@ static void destroy_objects(struct gl_hwdec *hw)
}
p->vdp_surface = VDP_INVALID_HANDLE;
- glCheckError(gl, hw->log, "Before uninitializing OpenGL interop");
+ gl_check_error(gl, hw->log, "Before uninitializing OpenGL interop");
if (p->vdpgl_initialized)
gl->VDPAUFiniNV();
p->vdpgl_initialized = false;
- glCheckError(gl, hw->log, "After uninitializing OpenGL interop");
+ gl_check_error(gl, hw->log, "After uninitializing OpenGL interop");
}
static void destroy(struct gl_hwdec *hw)
@@ -93,14 +107,14 @@ static void destroy(struct gl_hwdec *hw)
destroy_objects(hw);
mp_vdpau_mixer_destroy(p->mixer);
+ if (p->ctx)
+ hwdec_devices_remove(hw->devs, &p->ctx->hwctx);
mp_vdpau_destroy(p->ctx);
}
static int create(struct gl_hwdec *hw)
{
GL *gl = hw->gl;
- if (hw->hwctx)
- return -1;
Display *x11disp = glXGetCurrentDisplay();
if (!x11disp)
return -1;
@@ -120,8 +134,8 @@ static int create(struct gl_hwdec *hw)
destroy(hw);
return -1;
}
- hw->hwctx = &p->ctx->hwctx;
- hw->converted_imgfmt = IMGFMT_RGB0;
+ p->ctx->hwctx.driver_name = hw->driver->name;
+ hwdec_devices_add(hw->devs, &p->ctx->hwctx);
return 0;
}
@@ -144,39 +158,50 @@ static int reinit(struct gl_hwdec *hw, struct mp_image_params *params)
p->vdpgl_initialized = true;
- vdp_st = vdp->output_surface_create(p->ctx->vdp_device,
- VDP_RGBA_FORMAT_B8G8R8A8,
- params->w, params->h, &p->vdp_surface);
- CHECK_VDP_ERROR(p, "Error when calling vdp_output_surface_create");
-
- gl->GenTextures(1, &p->gl_texture);
- gl->BindTexture(GL_TEXTURE_2D, p->gl_texture);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ p->direct_mode = params->hw_subfmt == IMGFMT_NV12;
+
+ gl->GenTextures(4, p->gl_textures);
+ for (int n = 0; n < 4; n++) {
+ gl->BindTexture(GL_TEXTURE_2D, p->gl_textures[n]);
+ GLenum filter = p->direct_mode ? GL_NEAREST : GL_LINEAR;
+ gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
+ gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
+ gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ }
gl->BindTexture(GL_TEXTURE_2D, 0);
- p->vdpgl_surface = gl->VDPAURegisterOutputSurfaceNV(BRAINDEATH(p->vdp_surface),
- GL_TEXTURE_2D,
- 1, &p->gl_texture);
- if (!p->vdpgl_surface)
- return -1;
+ if (p->direct_mode) {
+ params->imgfmt = IMGFMT_NV12;
+ } else {
+ vdp_st = vdp->output_surface_create(p->ctx->vdp_device,
+ VDP_RGBA_FORMAT_B8G8R8A8,
+ params->w, params->h, &p->vdp_surface);
+ CHECK_VDP_ERROR(p, "Error when calling vdp_output_surface_create");
+
+ p->vdpgl_surface = gl->VDPAURegisterOutputSurfaceNV(BRAINDEATH(p->vdp_surface),
+ GL_TEXTURE_2D,
+ 1, p->gl_textures);
+ if (!p->vdpgl_surface)
+ return -1;
- gl->VDPAUSurfaceAccessNV(p->vdpgl_surface, GL_READ_ONLY);
+ gl->VDPAUSurfaceAccessNV(p->vdpgl_surface, GL_READ_ONLY);
+
+ params->imgfmt = IMGFMT_RGB0;
+ }
- glCheckError(gl, hw->log, "After initializing vdpau OpenGL interop");
+ gl_check_error(gl, hw->log, "After initializing vdpau OpenGL interop");
return 0;
}
-static int map_image(struct gl_hwdec *hw, struct mp_image *hw_image,
- GLuint *out_textures)
+static int map_frame(struct gl_hwdec *hw, struct mp_image *hw_image,
+ struct gl_hwdec_frame *out_frame)
{
struct priv *p = hw->priv;
GL *gl = hw->gl;
-
- assert(hw_image && hw_image->imgfmt == IMGFMT_VDPAU);
+ struct vdp_functions *vdp = &p->ctx->vdp;
+ VdpStatus vdp_st;
int pe = mp_vdpau_handle_preemption(p->ctx, &p->preemption_counter);
if (pe < 1) {
@@ -187,17 +212,58 @@ static int map_image(struct gl_hwdec *hw, struct mp_image *hw_image,
return -1;
}
- if (!p->vdpgl_surface)
- return -1;
+ if (p->direct_mode) {
+ VdpVideoSurface surface = (intptr_t)hw_image->planes[3];
- if (p->mapped)
- gl->VDPAUUnmapSurfacesNV(1, &p->vdpgl_surface);
+ // We need the uncropped size.
+ VdpChromaType s_chroma_type;
+ uint32_t s_w, s_h;
+ vdp_st = vdp->video_surface_get_parameters(surface, &s_chroma_type, &s_w, &s_h);
+ CHECK_VDP_ERROR(hw, "Error when calling vdp_video_surface_get_parameters");
+
+ p->vdpgl_surface = gl->VDPAURegisterVideoSurfaceNV(BRAINDEATH(surface),
+ GL_TEXTURE_2D,
+ 4, p->gl_textures);
+ if (!p->vdpgl_surface)
+ return -1;
- mp_vdpau_mixer_render(p->mixer, NULL, p->vdp_surface, NULL, hw_image, NULL);
+ gl->VDPAUSurfaceAccessNV(p->vdpgl_surface, GL_READ_ONLY);
+ gl->VDPAUMapSurfacesNV(1, &p->vdpgl_surface);
+
+ p->mapped = true;
+ *out_frame = (struct gl_hwdec_frame){
+ .vdpau_fields = true,
+ };
+ for (int n = 0; n < 4; n++) {
+ bool chroma = n >= 2;
+ out_frame->planes[n] = (struct gl_hwdec_plane){
+ .gl_texture = p->gl_textures[n],
+ .gl_target = GL_TEXTURE_2D,
+ .tex_w = s_w / (chroma ? 2 : 1),
+ .tex_h = s_h / (chroma ? 4 : 2),
+ };
+ };
+ } else {
+ if (!p->vdpgl_surface)
+ return -1;
+
+ mp_vdpau_mixer_render(p->mixer, NULL, p->vdp_surface, NULL, hw_image, NULL);
+
+ gl->VDPAUMapSurfacesNV(1, &p->vdpgl_surface);
+
+ p->mapped = true;
+ *out_frame = (struct gl_hwdec_frame){
+ .planes = {
+ {
+ .gl_texture = p->gl_textures[0],
+ .gl_target = GL_TEXTURE_2D,
+ .tex_w = p->image_params.w,
+ .tex_h = p->image_params.h,
+ },
+ },
+ };
+ }
- gl->VDPAUMapSurfacesNV(1, &p->vdpgl_surface);
- p->mapped = true;
- out_textures[0] = p->gl_texture;
return 0;
}
@@ -207,6 +273,7 @@ const struct gl_hwdec_driver gl_hwdec_vdpau = {
.imgfmt = IMGFMT_VDPAU,
.create = create,
.reinit = reinit,
- .map_image = map_image,
+ .map_frame = map_frame,
+ .unmap = unmap,
.destroy = destroy,
};