vlc | branch: master | Romain Vimont <[email protected]> | Tue Jul 7 12:33:49 2020 +0200| [c49b345e963c40cda3eb4e2cd9a687c8e1275f48] | committer: Alexandre Janniaux
opengl: add "direct" sampler A sampler exposes the VLC input picture via a GLSL function vlc_texture(). Until now, the input picture always came from the interop (initialized from a picture_t). With filters, the input picture may now be the output picture of the previous filter, already stored in a OpenGL texture. In that case, we need a sampler able to expose this input via vlc_texture(). Co-authored-by: Alexandre Janniaux <[email protected]> Signed-off-by: Alexandre Janniaux <[email protected]> > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=c49b345e963c40cda3eb4e2cd9a687c8e1275f48 --- modules/video_output/opengl/sampler.c | 105 +++++++++++++++++++++++++++-- modules/video_output/opengl/sampler_priv.h | 42 +++++++++++- modules/video_output/opengl/vout_helper.c | 4 +- 3 files changed, 141 insertions(+), 10 deletions(-) diff --git a/modules/video_output/opengl/sampler.c b/modules/video_output/opengl/sampler.c index 219cac3aec..8588cd883c 100644 --- a/modules/video_output/opengl/sampler.c +++ b/modules/video_output/opengl/sampler.c @@ -81,7 +81,16 @@ struct vlc_gl_sampler_priv { unsigned int i_visible_height; } last_source; + /* A sampler supports 2 kinds of input. + * - created with _NewFromInterop(), it receives input pictures from VLC + * (picture_t) via _UpdatePicture(); + * - created with _NewFromTexture2D() (interop is NULL), it receives + * directly OpenGL textures via _UpdateTexture(). + */ struct vlc_gl_interop *interop; + + /* Only used for "direct" sampler (when interop == NULL) */ + video_format_t direct_fmt; }; #define PRIV(sampler) container_of(sampler, struct vlc_gl_sampler_priv, sampler) @@ -936,7 +945,7 @@ opengl_fragment_shader_init(struct vlc_gl_sampler *sampler, GLenum tex_target, } struct vlc_gl_sampler * -vlc_gl_sampler_New(struct vlc_gl_interop *interop) +vlc_gl_sampler_NewFromInterop(struct vlc_gl_interop *interop) { struct vlc_gl_sampler_priv *priv = calloc(1, sizeof(*priv)); if (!priv) @@ -1026,16 +1035,86 @@ vlc_gl_sampler_New(struct vlc_gl_interop *interop) return sampler; } + +static void +sampler_direct_fetch_locations(struct vlc_gl_sampler *sampler, GLuint program) +{ + struct vlc_gl_sampler_priv *priv = PRIV(sampler); + const opengl_vtable_t *vt = priv->vt; + + priv->uloc.Textures[0] = + vt->GetUniformLocation(program, "vlc_input_texture"); + assert(priv->uloc.Textures[0] != -1); +} + +static void +sampler_direct_load(const struct vlc_gl_sampler *sampler) +{ + struct vlc_gl_sampler_priv *priv = PRIV(sampler); + const opengl_vtable_t *vt = priv->vt; + + GLuint texture = priv->textures[0]; + + vt->ActiveTexture(GL_TEXTURE0); + vt->BindTexture(GL_TEXTURE_2D, texture); + vt->Uniform1i(priv->uloc.Textures[0], 0); +} + +struct vlc_gl_sampler * +vlc_gl_sampler_NewFromTexture2D(struct vlc_gl_t *gl, + const struct vlc_gl_api *api, + const video_format_t *fmt) +{ + struct vlc_gl_sampler_priv *priv = calloc(1, sizeof(*priv)); + if (!priv) + return NULL; + + struct vlc_gl_sampler *sampler = &priv->sampler; + + priv->interop = NULL; + priv->gl = gl; + priv->vt = &api->vt; + + sampler->fmt = *fmt; + /* this is the only allocated field, and we don't need it */ + sampler->fmt.p_palette = NULL; + + static const char *const SHADER_BODY = + "uniform sampler2D vlc_input_texture;\n" + "vec4 vlc_texture(vec2 pic_coords) {\n" + " return texture2D(vlc_input_texture, pic_coords);\n" + "}\n"; + + sampler->shader.body = strdup(SHADER_BODY); + if (!sampler->shader.body) + { + free(priv); + return NULL; + } + + /* No extension required */ + sampler->shader.extensions = NULL; + + static const struct vlc_gl_sampler_ops ops = { + .fetch_locations = sampler_direct_fetch_locations, + .load = sampler_direct_load, + }; + sampler->ops = &ops; + + return sampler; +} + void vlc_gl_sampler_Delete(struct vlc_gl_sampler *sampler) { struct vlc_gl_sampler_priv *priv = PRIV(sampler); struct vlc_gl_interop *interop = priv->interop; - const opengl_vtable_t *vt = interop->vt; - - if (!interop->handle_texs_gen) + if (interop && !interop->handle_texs_gen) + { + const opengl_vtable_t *vt = interop->vt; vt->DeleteTextures(interop->tex_count, priv->textures); + } #ifdef HAVE_LIBPLACEBO FREENULL(priv->uloc.pl_vars); @@ -1050,11 +1129,13 @@ vlc_gl_sampler_Delete(struct vlc_gl_sampler *sampler) } int -vlc_gl_sampler_Update(struct vlc_gl_sampler *sampler, picture_t *picture) +vlc_gl_sampler_UpdatePicture(struct vlc_gl_sampler *sampler, picture_t *picture) { struct vlc_gl_sampler_priv *priv = PRIV(sampler); const struct vlc_gl_interop *interop = priv->interop; + assert(interop); + const video_format_t *source = &picture->format; if (source->i_x_offset != priv->last_source.i_x_offset @@ -1142,3 +1223,17 @@ vlc_gl_sampler_Update(struct vlc_gl_sampler *sampler, picture_t *picture) priv->tex_widths, priv->tex_heights, picture, NULL); } + +int +vlc_gl_sampler_UpdateTexture(struct vlc_gl_sampler *sampler, GLuint texture, + GLsizei tex_width, GLsizei tex_height) +{ + struct vlc_gl_sampler_priv *priv = PRIV(sampler); + assert(!priv->interop); + + priv->textures[0] = texture; + priv->tex_widths[0] = tex_width; + priv->tex_heights[0] = tex_height; + + return VLC_SUCCESS; +} diff --git a/modules/video_output/opengl/sampler_priv.h b/modules/video_output/opengl/sampler_priv.h index ccd96b60c4..e6c977d467 100644 --- a/modules/video_output/opengl/sampler_priv.h +++ b/modules/video_output/opengl/sampler_priv.h @@ -23,17 +23,36 @@ #include <vlc_common.h> +#include "gl_api.h" #include "sampler.h" struct vlc_gl_interop; /** - * Create a new sampler + * Create a new sampler from an interop + * + * It receives input pictures from `picture_t`, and uses the interop to + * uploaded them to OpenGL textures. * * \param interop the interop */ struct vlc_gl_sampler * -vlc_gl_sampler_New(struct vlc_gl_interop *interop); +vlc_gl_sampler_NewFromInterop(struct vlc_gl_interop *interop); + +/** + * Create a new direct sampler + * + * It receives input textures directly (typically the output of a previous + * filter), with target GL_TEXTURE_2D. + * + * \param gl the OpenGL context + * \param api the OpenGL API + * \param fmt the input format + */ +struct vlc_gl_sampler * +vlc_gl_sampler_NewFromTexture2D(struct vlc_gl_t *gl, + const struct vlc_gl_api *api, + const video_format_t *fmt); /** * Delete a sampler @@ -48,10 +67,27 @@ vlc_gl_sampler_Delete(struct vlc_gl_sampler *sampler); * * This changes the current input picture, available from the fragment shader. * + * Warning: only call on sampler created by vlc_gl_sampler_NewFromInterop(). + * * \param sampler the sampler * \param picture the new picture */ int -vlc_gl_sampler_Update(struct vlc_gl_sampler *sampler, picture_t *picture); +vlc_gl_sampler_UpdatePicture(struct vlc_gl_sampler *sampler, + picture_t *picture); + +/** + * Update the input texture + * + * Warning: only call on sampler created by vlc_gl_sampler_NewFromTexture2D(). + * + * \param sampler the sampler + * \param texture the new texture, with target GL_TEXTURE_2D + * \param tex_width the texture width + * \param tex_height the texture height + */ +int +vlc_gl_sampler_UpdateTexture(struct vlc_gl_sampler *sampler, GLuint texture, + GLsizei tex_width, GLsizei tex_height); #endif diff --git a/modules/video_output/opengl/vout_helper.c b/modules/video_output/opengl/vout_helper.c index 04f7f41749..6707adcd66 100644 --- a/modules/video_output/opengl/vout_helper.c +++ b/modules/video_output/opengl/vout_helper.c @@ -144,7 +144,7 @@ vout_display_opengl_t *vout_display_opengl_New(video_format_t *fmt, goto free_vgl; } - vgl->sampler = vlc_gl_sampler_New(vgl->interop); + vgl->sampler = vlc_gl_sampler_NewFromInterop(vgl->interop); if (!vgl->sampler) { msg_Err(gl, "Could not create sampler"); @@ -266,7 +266,7 @@ int vout_display_opengl_Prepare(vout_display_opengl_t *vgl, { GL_ASSERT_NOERROR(&vgl->api.vt); - int ret = vlc_gl_sampler_Update(vgl->sampler, picture); + int ret = vlc_gl_sampler_UpdatePicture(vgl->sampler, picture); if (ret != VLC_SUCCESS) return ret; _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
