[vlc-devel] [PATCH 06/27] opengl: add "direct" sampler
Alexandre Janniaux
ajanni at videolabs.io
Mon Jun 29 16:46:36 CEST 2020
Hi,
NewDirect should probably be able to take the characteristics of
the input picture as parameter, or be called NewTexture2D instead.
"OpenGL textures" as-is doesn't designate a precise OpenGL object,
but a category of object. Without defining which target it's using
it doesn't feel right.
Regards,
--
Alexandre Janniaux
Videolabs
On Thu, Jun 25, 2020 at 02:22:53PM +0200, Romain Vimont wrote:
> 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().
> ---
> modules/video_output/opengl/sampler.c | 104 ++++++++++++++++++++-
> modules/video_output/opengl/sampler_priv.h | 41 +++++++-
> modules/video_output/opengl/vout_helper.c | 4 +-
> 3 files changed, 139 insertions(+), 10 deletions(-)
>
> diff --git a/modules/video_output/opengl/sampler.c b/modules/video_output/opengl/sampler.c
> index 0b58ffb0f6..3b7802be2f 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 _NewDirect() (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)
> @@ -1024,16 +1033,85 @@ 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_NewDirect(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);
> @@ -1048,11 +1126,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
> @@ -1140,3 +1220,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..20513b9f6d 100644
> --- a/modules/video_output/opengl/sampler_priv.h
> +++ b/modules/video_output/opengl/sampler_priv.h
> @@ -23,17 +23,35 @@
>
> #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).
> + *
> + * \param gl the OpenGL context
> + * \param api the OpenGL API
> + * \param fmt the input format
> + */
> +struct vlc_gl_sampler *
> +vlc_gl_sampler_NewDirect(struct vlc_gl_t *gl, const struct vlc_gl_api *api,
> + const video_format_t *fmt);
>
> /**
> * Delete a sampler
> @@ -48,10 +66,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_NewDirect().
> + *
> + * \param sampler the sampler
> + * \param texture the new current texture
> + * \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 8eed276d54..726bff56bd 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;
>
> --
> 2.27.0
>
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel
More information about the vlc-devel
mailing list