[vlc-devel] [PATCH] opengl: use common fragment shader for Android

Thomas Guillem thomas at gllm.fr
Thu Dec 19 11:44:02 CET 2019


LGTM,
Thanks for this patch (and clearing my mess)

On Thu, Dec 19, 2019, at 11:32, Romain Vimont wrote:
> The OpenGL converter for Android used its own minimal fragment shader,
> instead of the common one used by all the other converters.
> 
> This stemmed from the fact that on each texture update, Android provides
> a transform matrix to apply in order to retrieve the correct texture
> coordinates.
> 
> Adapt the common fragment shader to accept a transform matrix provided
> by the converter, and make the Android converter use it.
> ---
>  modules/video_output/opengl/converter.h       | 20 +++++++
>  .../video_output/opengl/converter_android.c   | 54 +++----------------
>  .../video_output/opengl/fragment_shaders.c    | 12 ++++-
>  modules/video_output/opengl/gl_common.h       |  3 ++
>  modules/video_output/opengl/vout_helper.c     | 22 +++++++-
>  5 files changed, 63 insertions(+), 48 deletions(-)
> 
> diff --git a/modules/video_output/opengl/converter.h 
> b/modules/video_output/opengl/converter.h
> index a3aba06621..211d7e07c4 100644
> --- a/modules/video_output/opengl/converter.h
> +++ b/modules/video_output/opengl/converter.h
> @@ -196,6 +196,26 @@ struct opengl_tex_converter_t
>      void (*pf_prepare_shader)(const opengl_tex_converter_t *tc,
>                                const GLsizei *tex_width, const GLsizei 
> *tex_height,
>                                float alpha);
> +
> +    /**
> +     * Callback to retrieve the transform matrix to apply to texture 
> coordinates
> +     *
> +     * This function pointer can be NULL. If it is set, it may return 
> NULL.
> +     *
> +     * Otherwise, it must return a 4x4 matrix, as an array of 16 
> floats in
> +     * column-major order.
> +     *
> +     * This transform matrix maps 2D homogeneous texture coordinates 
> of the
> +     * form (s, t, 0, 1) with s and t in the inclusive range [0, 1] to 
> the
> +     * texture coordinate that should be used to sample that location 
> from the
> +     * texture.
> +     *
> +     * The returned pointer is owned by the converter module, and must 
> not be
> +     * freed before the module is closed.
> +     *
> +     * \param tc OpenGL tex converter
> +     */
> +    const float *(*pf_get_transform_matrix)(const 
> opengl_tex_converter_t *tc);
>  };
>  
>  /**
> diff --git a/modules/video_output/opengl/converter_android.c 
> b/modules/video_output/opengl/converter_android.c
> index 6fb0a4e631..6468068640 100644
> --- a/modules/video_output/opengl/converter_android.c
> +++ b/modules/video_output/opengl/converter_android.c
> @@ -35,10 +35,6 @@ struct priv
>      AWindowHandler *awh;
>      const float *transform_mtx;
>      bool stex_attached;
> -
> -    struct {
> -        GLint uSTMatrix;
> -    } uloc;
>  };
>  
>  static int
> @@ -87,24 +83,11 @@ tc_anop_update(const opengl_tex_converter_t *tc, 
> GLuint *textures,
>      return VLC_SUCCESS;
>  }
>  
> -static int
> -tc_anop_fetch_locations(opengl_tex_converter_t *tc, GLuint program)
> +static const float *
> +tc_get_transform_matrix(const opengl_tex_converter_t *tc)
>  {
>      struct priv *priv = tc->priv;
> -    priv->uloc.uSTMatrix = tc->vt->GetUniformLocation(program, "uSTMatrix");
> -    return priv->uloc.uSTMatrix != -1 ? VLC_SUCCESS : VLC_EGENERIC;
> -}
> -
> -static void
> -tc_anop_prepare_shader(const opengl_tex_converter_t *tc,
> -                       const GLsizei *tex_width, const GLsizei *tex_height,
> -                       float alpha)
> -{
> -    (void) tex_width; (void) tex_height; (void) alpha;
> -    struct priv *priv = tc->priv;
> -    if (priv->transform_mtx != NULL)
> -        tc->vt->UniformMatrix4fv(priv->uloc.uSTMatrix, 1, GL_FALSE,
> -                                  priv->transform_mtx);
> +    return priv->transform_mtx;
>  }
>  
>  static void
> @@ -147,13 +130,7 @@ Open(vlc_object_t *obj)
>  
>      tc->pf_allocate_textures = tc_anop_allocate_textures;
>      tc->pf_update         = tc_anop_update;
> -    tc->pf_fetch_locations = tc_anop_fetch_locations;
> -    tc->pf_prepare_shader = tc_anop_prepare_shader;
> -
> -    tc->tex_count = 1;
> -    tc->texs[0] = (struct opengl_tex_cfg) { { 1, 1 }, { 1, 1 }, 0, 0, 0 };
> -
> -    tc->tex_target   = GL_TEXTURE_EXTERNAL_OES;
> +    tc->pf_get_transform_matrix = tc_get_transform_matrix;
>  
>      /* The transform Matrix (uSTMatrix) given by the SurfaceTexture is not
>       * using the same origin than us. Ask the caller to rotate textures
> @@ -186,29 +163,14 @@ Open(vlc_object_t *obj)
>              break;
>      }
>  
> -    static const char *template =
> -        "#version %u\n"
> -        "#extension GL_OES_EGL_image_external : require\n"
> -        "%s" /* precision */
> -        "varying vec2 TexCoord0;"
> -        "uniform samplerExternalOES sTexture;"
> -        "uniform mat4 uSTMatrix;"
> -        "void main()"
> -        "{ "
> -        "  gl_FragColor = texture2D(sTexture, (uSTMatrix * 
> vec4(TexCoord0, 1, 1)).xy).rgba;"
> -        "}";
> -
> -    char *code;
> -    if (asprintf(&code, template, tc->glsl_version, 
> tc->glsl_precision_header) < 0)
> +    tc->fshader = opengl_fragment_shader_init(tc, 
> GL_TEXTURE_EXTERNAL_OES,
> +                                              VLC_CODEC_RGB32,
> +                                              COLOR_SPACE_UNDEF);
> +    if (!tc->fshader)
>      {
>          free(tc->priv);
>          return VLC_EGENERIC;
>      }
> -    GLuint fragment_shader = tc->vt->CreateShader(GL_FRAGMENT_SHADER);
> -    tc->vt->ShaderSource(fragment_shader, 1, (const char **) &code, 
> NULL);
> -    tc->vt->CompileShader(fragment_shader);
> -    tc->fshader = fragment_shader;
> -    free(code);
>  
>      return VLC_SUCCESS;
>  }
> diff --git a/modules/video_output/opengl/fragment_shaders.c 
> b/modules/video_output/opengl/fragment_shaders.c
> index 9694b52d63..bd9978fda4 100644
> --- a/modules/video_output/opengl/fragment_shaders.c
> +++ b/modules/video_output/opengl/fragment_shaders.c
> @@ -524,6 +524,11 @@ 
> opengl_fragment_shader_init_impl(opengl_tex_converter_t *tc, GLenum 
> tex_target,
>      const char *sampler, *lookup, *coord_name;
>      switch (tex_target)
>      {
> +        case GL_TEXTURE_EXTERNAL_OES:
> +            sampler = "samplerExternalOES";
> +            lookup = "texture2D";
> +            coord_name = "TexCoord";
> +            break;
>          case GL_TEXTURE_2D:
>              sampler = "sampler2D";
>              lookup  = "texture2D";
> @@ -545,7 +550,12 @@ 
> opengl_fragment_shader_init_impl(opengl_tex_converter_t *tc, GLenum 
> tex_target,
>  #define ADD(x) vlc_memstream_puts(&ms, x)
>  #define ADDF(x, ...) vlc_memstream_printf(&ms, x, ##__VA_ARGS__)
>  
> -    ADDF("#version %u\n%s", tc->glsl_version, tc->glsl_precision_header);
> +    ADDF("#version %u\n", tc->glsl_version);
> +
> +    if (tex_target == GL_TEXTURE_EXTERNAL_OES)
> +        ADDF("#extension GL_OES_EGL_image_external : require\n");
> +
> +    ADDF("%s", tc->glsl_precision_header);
>  
>      for (unsigned i = 0; i < tc->tex_count; ++i)
>          ADDF("uniform %s Texture%u;\n"
> diff --git a/modules/video_output/opengl/gl_common.h 
> b/modules/video_output/opengl/gl_common.h
> index 11c109a7a7..fb14ae3b66 100644
> --- a/modules/video_output/opengl/gl_common.h
> +++ b/modules/video_output/opengl/gl_common.h
> @@ -52,6 +52,9 @@
>  #ifndef GL_TEXTURE_RECTANGLE
>  # define GL_TEXTURE_RECTANGLE 0x84F5
>  #endif
> +#ifndef GL_TEXTURE_EXTERNAL_OES
> +# define GL_TEXTURE_EXTERNAL_OES 0x8D65
> +#endif
>  
>  #ifndef APIENTRY
>  # define APIENTRY
> diff --git a/modules/video_output/opengl/vout_helper.c 
> b/modules/video_output/opengl/vout_helper.c
> index 8e692eae5a..fae2ebd15e 100644
> --- a/modules/video_output/opengl/vout_helper.c
> +++ b/modules/video_output/opengl/vout_helper.c
> @@ -49,6 +49,12 @@
>  
>  #define SPHERE_RADIUS 1.f
>  
> +static const GLfloat MATRIX_IDENTITY[16] =
> +    { 1, 0, 0, 0,
> +      0, 1, 0, 0,
> +      0, 0, 1, 0,
> +      0, 0, 0, 1 };
> +
>  /* FIXME: GL_ASSERT_NOERROR disabled for now because:
>   * Proper GL error handling need to be implemented
>   * glClear(GL_COLOR_BUFFER_BIT) throws a 
> GL_INVALID_FRAMEBUFFER_OPERATION on macOS
> @@ -105,6 +111,7 @@ struct prgm
>      } var;
>  
>      struct { /* UniformLocation */
> +        GLint TransformMatrix;
>          GLint OrientationMatrix;
>          GLint ProjectionMatrix;
>          GLint ViewMatrix;
> @@ -315,12 +322,13 @@ static GLuint BuildVertexShader(const 
> opengl_tex_converter_t *tc,
>          "attribute vec4 MultiTexCoord0;\n"
>          "%s%s"
>          "attribute vec3 VertexPosition;\n"
> +        "uniform mat4 TransformMatrix;\n"
>          "uniform mat4 OrientationMatrix;\n"
>          "uniform mat4 ProjectionMatrix;\n"
>          "uniform mat4 ZoomMatrix;\n"
>          "uniform mat4 ViewMatrix;\n"
>          "void main() {\n"
> -        " TexCoord0 = vec4(OrientationMatrix * MultiTexCoord0).st;\n"
> +        " TexCoord0 = vec4(TransformMatrix * OrientationMatrix * 
> MultiTexCoord0).st;\n"
>          "%s%s"
>          " gl_Position = ProjectionMatrix * ZoomMatrix * ViewMatrix\n"
>          "               * vec4(VertexPosition, 1.0);\n"
> @@ -463,6 +471,7 @@ opengl_link_program(struct prgm *prgm)
>  } while (0)
>  #define GET_ULOC(x, str) GET_LOC(Uniform, prgm->uloc.x, str)
>  #define GET_ALOC(x, str) GET_LOC(Attrib, prgm->aloc.x, str)
> +    GET_ULOC(TransformMatrix, "TransformMatrix");
>      GET_ULOC(OrientationMatrix, "OrientationMatrix");
>      GET_ULOC(ProjectionMatrix, "ProjectionMatrix");
>      GET_ULOC(ViewMatrix, "ViewMatrix");
> @@ -533,6 +542,7 @@ opengl_init_program(vout_display_opengl_t *vgl, 
> vlc_video_context *context,
>      tc->vt = &vgl->vt;
>      tc->b_dump_shaders = b_dump_shaders;
>      tc->pf_fragment_shader_init = opengl_fragment_shader_init_impl;
> +    tc->pf_get_transform_matrix = NULL;
>      tc->glexts = glexts;
>  #if defined(USE_OPENGL_ES2)
>      tc->is_gles = true;
> @@ -1498,6 +1508,13 @@ static void 
> DrawWithShaders(vout_display_opengl_t *vgl, struct prgm *prgm)
>      vgl->vt.EnableVertexAttribArray(prgm->aloc.VertexPosition);
>      vgl->vt.VertexAttribPointer(prgm->aloc.VertexPosition, 3, 
> GL_FLOAT, 0, 0, 0);
>  
> +    const GLfloat *tm = tc->pf_get_transform_matrix
> +                      ? tc->pf_get_transform_matrix(tc) : NULL;
> +    if (!tm)
> +        tm = MATRIX_IDENTITY;
> +
> +    vgl->vt.UniformMatrix4fv(prgm->uloc.TransformMatrix, 1, GL_FALSE, 
> tm);
> +
>      vgl->vt.UniformMatrix4fv(prgm->uloc.OrientationMatrix, 1, GL_FALSE,
>                               prgm->var.OrientationMatrix);
>      vgl->vt.UniformMatrix4fv(prgm->uloc.ProjectionMatrix, 1, GL_FALSE,
> @@ -1677,6 +1694,9 @@ int 
> vout_display_opengl_Display(vout_display_opengl_t *vgl,
>          vgl->vt.VertexAttribPointer(prgm->aloc.VertexPosition, 2, 
> GL_FLOAT,
>                                      0, 0, 0);
>  
> +        vgl->vt.UniformMatrix4fv(prgm->uloc.TransformMatrix, 1, GL_FALSE,
> +                                 MATRIX_IDENTITY);
> +
>          vgl->vt.UniformMatrix4fv(prgm->uloc.OrientationMatrix, 1, GL_FALSE,
>                                   prgm->var.OrientationMatrix);
>          vgl->vt.UniformMatrix4fv(prgm->uloc.ProjectionMatrix, 1, GL_FALSE,
> -- 
> 2.24.1
> 
> _______________________________________________
> 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