[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