[vlc-devel] [PATCH 06/27] opengl: add "direct" sampler

Romain Vimont rom1v at videolabs.io
Mon Jun 29 21:43:36 CEST 2020


On Mon, Jun 29, 2020 at 04:46:36PM +0200, Alexandre Janniaux wrote:
> 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.

A "direct" sampler is only created internally by the filter chain, so
the target is always implicitly GL_TEXTURE_2D ("direct" implies
GL_TEXTURE_2D).

But I'm ok to rename the "constructor" if it's clearer. Maybe
vlc_gl_sampler_NewFromTexture2D? ("NewTexture2D" is confusing because it
suggests that it creates a texture).

Regards

> 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
> _______________________________________________
> 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