[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