[vlc-commits] opengl: determine shader version dynamically
Romain Vimont
git at videolan.org
Tue Apr 20 10:49:19 UTC 2021
vlc | branch: master | Romain Vimont <rom1v at videolabs.io> | Mon Apr 12 17:58:55 2021 +0200| [199f3812b0c2c19f317df57bf60d3f4cd7b7373a] | committer: Alexandre Janniaux
opengl: determine shader version dynamically
In the future, we would like OpenGL and OpenGL ES2 versions of a filter
to be available without compiling it twice.
Co-authored-by: Alexandre Janniaux <ajanni at videolabs.io>
Signed-off-by: Alexandre Janniaux <ajanni at videolabs.io>
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=199f3812b0c2c19f317df57bf60d3f4cd7b7373a
---
modules/video_output/opengl/filter_draw.c | 58 +++++++-------
modules/video_output/opengl/filter_mock.c | 128 +++++++++++++++++++-----------
modules/video_output/opengl/renderer.c | 112 ++++++++++----------------
3 files changed, 157 insertions(+), 141 deletions(-)
diff --git a/modules/video_output/opengl/filter_draw.c b/modules/video_output/opengl/filter_draw.c
index 60aeddc539..b921b3f0ee 100644
--- a/modules/video_output/opengl/filter_draw.c
+++ b/modules/video_output/opengl/filter_draw.c
@@ -97,16 +97,7 @@ vlc_gl_filter_draw_Open(struct vlc_gl_filter *filter,
struct vlc_gl_sampler *sampler = vlc_gl_filter_GetSampler(filter);
-#ifdef USE_OPENGL_ES2
-# define SHADER_VERSION "#version 100\n"
-# define FRAGMENT_SHADER_PRECISION "precision highp float;\n"
-#else
-# define SHADER_VERSION "#version 120\n"
-# define FRAGMENT_SHADER_PRECISION
-#endif
-
- static const char *const VERTEX_SHADER =
- SHADER_VERSION
+ static const char *const VERTEX_SHADER_BODY =
"attribute vec2 vertex_pos;\n"
"varying vec2 tex_coords;\n"
"void main() {\n"
@@ -115,8 +106,7 @@ vlc_gl_filter_draw_Open(struct vlc_gl_filter *filter,
" (vertex_pos.y + 1.0) / 2.0);\n"
"}\n";
- static const char *const VERTEX_SHADER_VFLIP =
- SHADER_VERSION
+ static const char *const VERTEX_SHADER_BODY_VFLIP =
"attribute vec2 vertex_pos;\n"
"varying vec2 tex_coords;\n"
"void main() {\n"
@@ -125,11 +115,7 @@ vlc_gl_filter_draw_Open(struct vlc_gl_filter *filter,
" (-vertex_pos.y + 1.0) / 2.0);\n"
"}\n";
- static const char *const FRAGMENT_SHADER_TEMPLATE =
- SHADER_VERSION
- "%s\n" /* extensions */
- FRAGMENT_SHADER_PRECISION
- "%s\n" /* vlc_texture definition */
+ static const char *const FRAGMENT_SHADER_BODY =
"varying vec2 tex_coords;\n"
"void main() {\n"
" gl_FragColor = vlc_texture(tex_coords);\n"
@@ -138,24 +124,40 @@ vlc_gl_filter_draw_Open(struct vlc_gl_filter *filter,
const char *extensions = sampler->shader.extensions
? sampler->shader.extensions : "";
- char *fragment_shader;
- int ret = asprintf(&fragment_shader, FRAGMENT_SHADER_TEMPLATE, extensions,
- sampler->shader.body);
- if (ret < 0)
- goto error;
-
const opengl_vtable_t *vt = &filter->api->vt;
+ const char *shader_version;
+ const char *shader_precision;
+ if (filter->api->is_gles)
+ {
+ shader_version = "#version 100\n";
+ shader_precision = "precision highp float;\n";
+ }
+ else
+ {
+ shader_version = "#version 120\n";
+ shader_precision = "";
+ }
+
config_ChainParse(filter, DRAW_CFG_PREFIX, filter_options, config);
bool vflip = var_InheritBool(filter, DRAW_CFG_PREFIX "vflip");
- const char *vertex_shader = vflip ? VERTEX_SHADER_VFLIP : VERTEX_SHADER;
+ const char *vertex_shader[] = {
+ shader_version,
+ vflip ? VERTEX_SHADER_BODY_VFLIP : VERTEX_SHADER_BODY,
+ };
+ const char *fragment_shader[] = {
+ shader_version,
+ extensions,
+ shader_precision,
+ sampler->shader.body,
+ FRAGMENT_SHADER_BODY,
+ };
+
GLuint program_id =
vlc_gl_BuildProgram(VLC_OBJECT(filter), vt,
- 1, &vertex_shader,
- 1, (const char **) &fragment_shader);
-
- free(fragment_shader);
+ ARRAY_SIZE(vertex_shader), vertex_shader,
+ ARRAY_SIZE(fragment_shader), fragment_shader);
if (!program_id)
goto error;
diff --git a/modules/video_output/opengl/filter_mock.c b/modules/video_output/opengl/filter_mock.c
index 41851fe35d..e6252f36b6 100644
--- a/modules/video_output/opengl/filter_mock.c
+++ b/modules/video_output/opengl/filter_mock.c
@@ -73,14 +73,6 @@
#include "gl_common.h"
#include "gl_util.h"
-#ifdef USE_OPENGL_ES2
-# define SHADER_VERSION "#version 100\n"
-# define FRAGMENT_SHADER_PRECISION "precision mediump float;\n"
-#else
-# define SHADER_VERSION "#version 120\n"
-# define FRAGMENT_SHADER_PRECISION
-#endif
-
#define MOCK_CFG_PREFIX "mock-"
static const char *const filter_options[] = {
@@ -241,8 +233,7 @@ InitBlend(struct vlc_gl_filter *filter)
struct sys *sys = filter->sys;
const opengl_vtable_t *vt = &filter->api->vt;
- static const char *const VERTEX_SHADER =
- SHADER_VERSION
+ static const char *const VERTEX_SHADER_BODY =
"attribute vec2 vertex_pos;\n"
"attribute vec3 vertex_color;\n"
"uniform mat4 rotation_matrix;\n"
@@ -252,18 +243,39 @@ InitBlend(struct vlc_gl_filter *filter)
" color = vertex_color;\n"
"}\n";
- static const char *const FRAGMENT_SHADER =
- SHADER_VERSION
- FRAGMENT_SHADER_PRECISION
+ static const char *const FRAGMENT_SHADER_BODY =
"varying vec3 color;\n"
"void main() {\n"
" gl_FragColor = vec4(color, 0.5);\n"
"}\n";
+ const char *shader_version;
+ const char *shader_precision;
+ if (filter->api->is_gles)
+ {
+ shader_version = "#version 100\n";
+ shader_precision = "precision highp float;\n";
+ }
+ else
+ {
+ shader_version = "#version 120\n";
+ shader_precision = "";
+ }
+
+ const char *vertex_shader[] = {
+ shader_version,
+ VERTEX_SHADER_BODY,
+ };
+ const char *fragment_shader[] = {
+ shader_version,
+ shader_precision,
+ FRAGMENT_SHADER_BODY,
+ };
+
GLuint program_id =
vlc_gl_BuildProgram(VLC_OBJECT(filter), vt,
- 1, (const char **) &VERTEX_SHADER,
- 1, (const char **) &FRAGMENT_SHADER);
+ ARRAY_SIZE(vertex_shader), vertex_shader,
+ ARRAY_SIZE(fragment_shader), fragment_shader);
if (!program_id)
return VLC_EGENERIC;
@@ -316,8 +328,7 @@ InitMask(struct vlc_gl_filter *filter)
struct vlc_gl_sampler *sampler = vlc_gl_filter_GetSampler(filter);
- static const char *const VERTEX_SHADER =
- SHADER_VERSION
+ static const char *const VERTEX_SHADER_BODY =
"attribute vec2 vertex_pos;\n"
"uniform mat4 rotation_matrix;\n"
"varying vec2 tex_coords;\n"
@@ -328,11 +339,7 @@ InitMask(struct vlc_gl_filter *filter)
" gl_Position = pos\n;"
"}\n";
- static const char *const FRAGMENT_SHADER_TEMPLATE =
- SHADER_VERSION
- "%s\n" /* extensions */
- FRAGMENT_SHADER_PRECISION
- "%s\n" /* vlc_texture definition */
+ static const char *const FRAGMENT_SHADER_BODY =
"varying vec2 tex_coords;\n"
"void main() {\n"
" gl_FragColor = vlc_texture(tex_coords);\n"
@@ -341,17 +348,35 @@ InitMask(struct vlc_gl_filter *filter)
const char *extensions = sampler->shader.extensions
? sampler->shader.extensions : "";
- char *fragment_shader;
- int ret = asprintf(&fragment_shader, FRAGMENT_SHADER_TEMPLATE, extensions,
- sampler->shader.body);
- if (ret < 0)
- return VLC_EGENERIC;
+ const char *shader_version;
+ const char *shader_precision;
+ if (filter->api->is_gles)
+ {
+ shader_version = "#version 100\n";
+ shader_precision = "precision highp float;\n";
+ }
+ else
+ {
+ shader_version = "#version 120\n";
+ shader_precision = "";
+ }
+
+ const char *vertex_shader[] = {
+ shader_version,
+ VERTEX_SHADER_BODY,
+ };
+ const char *fragment_shader[] = {
+ shader_version,
+ extensions,
+ shader_precision,
+ sampler->shader.body,
+ FRAGMENT_SHADER_BODY,
+ };
GLuint program_id =
vlc_gl_BuildProgram(VLC_OBJECT(filter), vt,
- 1, (const char **) &VERTEX_SHADER,
- 1, (const char **) &fragment_shader);
- free(fragment_shader);
+ ARRAY_SIZE(vertex_shader), vertex_shader,
+ ARRAY_SIZE(fragment_shader), fragment_shader);
if (!program_id)
return VLC_EGENERIC;
@@ -401,8 +426,7 @@ InitPlane(struct vlc_gl_filter *filter)
struct vlc_gl_sampler *sampler = vlc_gl_filter_GetSampler(filter);
- static const char *const VERTEX_SHADER =
- SHADER_VERSION
+ static const char *const VERTEX_SHADER_BODY =
"attribute vec2 vertex_pos;\n"
"varying vec2 tex_coords;\n"
"void main() {\n"
@@ -411,11 +435,7 @@ InitPlane(struct vlc_gl_filter *filter)
" (vertex_pos.y + 1.0) / 2.0);\n"
"}\n";
- static const char *const FRAGMENT_SHADER_TEMPLATE =
- SHADER_VERSION
- "%s\n" /* extensions */
- FRAGMENT_SHADER_PRECISION
- "%s\n" /* vlc_texture definition */
+ static const char *const FRAGMENT_SHADER_BODY =
"varying vec2 tex_coords;\n"
"uniform int plane;\n"
"void main() {\n"
@@ -426,17 +446,35 @@ InitPlane(struct vlc_gl_filter *filter)
const char *extensions = sampler->shader.extensions
? sampler->shader.extensions : "";
- char *fragment_shader;
- int ret = asprintf(&fragment_shader, FRAGMENT_SHADER_TEMPLATE, extensions,
- sampler->shader.body);
- if (ret < 0)
- return VLC_EGENERIC;
+ const char *shader_version;
+ const char *shader_precision;
+ if (filter->api->is_gles)
+ {
+ shader_version = "#version 100\n";
+ shader_precision = "precision highp float;\n";
+ }
+ else
+ {
+ shader_version = "#version 120\n";
+ shader_precision = "";
+ }
+
+ const char *vertex_shader[] = {
+ shader_version,
+ VERTEX_SHADER_BODY,
+ };
+ const char *fragment_shader[] = {
+ shader_version,
+ extensions,
+ shader_precision,
+ sampler->shader.body,
+ FRAGMENT_SHADER_BODY,
+ };
GLuint program_id =
vlc_gl_BuildProgram(VLC_OBJECT(filter), vt,
- 1, (const char **) &VERTEX_SHADER,
- 1, (const char **) &fragment_shader);
- free(fragment_shader);
+ ARRAY_SIZE(vertex_shader), vertex_shader,
+ ARRAY_SIZE(fragment_shader), fragment_shader);
if (!program_id)
return VLC_EGENERIC;
diff --git a/modules/video_output/opengl/renderer.c b/modules/video_output/opengl/renderer.c
index a6d1b65508..773571e2fe 100644
--- a/modules/video_output/opengl/renderer.c
+++ b/modules/video_output/opengl/renderer.c
@@ -170,25 +170,14 @@ InitStereoMatrix(GLfloat matrix_out[static 3*3],
#undef ROW
}
-/* https://en.wikipedia.org/wiki/OpenGL_Shading_Language#Versions */
-#ifdef USE_OPENGL_ES2
-# define SHADER_VERSION "#version 100\n"
- /* In OpenGL ES, the fragment language has no default precision qualifier for
- * floating point types. */
-# define FRAGMENT_SHADER_PRECISION "precision highp float;\n"
-#else
-# define SHADER_VERSION "#version 120\n"
-# define FRAGMENT_SHADER_PRECISION
-#endif
-
-static char *
-BuildVertexShader(struct vlc_gl_filter *filter)
+static int
+opengl_link_program(struct vlc_gl_filter *filter)
{
struct vlc_gl_renderer *renderer = filter->sys;
+ struct vlc_gl_sampler *sampler = renderer->sampler;
+ const opengl_vtable_t *vt = renderer->vt;
- /* Basic vertex shader */
- static const char *template =
- SHADER_VERSION
+ static const char *const VERTEX_SHADER_BODY =
"attribute vec2 PicCoordsIn;\n"
"varying vec2 PicCoords;\n"
"attribute vec3 VertexPosition;\n"
@@ -200,29 +189,9 @@ BuildVertexShader(struct vlc_gl_filter *filter)
" PicCoords = (StereoMatrix * vec3(PicCoordsIn, 1.0)).st;\n"
" gl_Position = ProjectionMatrix * ZoomMatrix * ViewMatrix\n"
" * vec4(VertexPosition, 1.0);\n"
- "}";
-
- char *code = strdup(template);
- if (!code)
- return NULL;
-
- if (renderer->dump_shaders)
- msg_Dbg(filter, "\n=== Vertex shader for fourcc: %4.4s ===\n%s\n",
- (const char *) &renderer->sampler->fmt.i_chroma, code);
- return code;
-}
-
-static char *
-BuildFragmentShader(struct vlc_gl_filter *filter)
-{
- struct vlc_gl_renderer *renderer = filter->sys;
- struct vlc_gl_sampler *sampler = renderer->sampler;
+ "}\n";
- static const char *template =
- SHADER_VERSION
- "%s" /* extensions */
- FRAGMENT_SHADER_PRECISION
- "%s" /* vlc_texture definition */
+ static const char *const FRAGMENT_SHADER_BODY =
"varying vec2 PicCoords;\n"
"void main() {\n"
" gl_FragColor = vlc_texture(PicCoords);\n"
@@ -231,35 +200,44 @@ BuildFragmentShader(struct vlc_gl_filter *filter)
const char *extensions = sampler->shader.extensions
? sampler->shader.extensions : "";
- char *code;
- int ret = asprintf(&code, template, extensions, sampler->shader.body);
- if (ret < 0)
- return NULL;
-
- if (renderer->dump_shaders)
- msg_Dbg(filter, "\n=== Fragment shader for fourcc: %4.4s, colorspace: %d ===\n%s\n",
- (const char *) &sampler->fmt.i_chroma,
- sampler->fmt.space, code);
-
- return code;
-}
-
-static int
-opengl_link_program(struct vlc_gl_filter *filter)
-{
- struct vlc_gl_renderer *renderer = filter->sys;
- struct vlc_gl_sampler *sampler = renderer->sampler;
- const opengl_vtable_t *vt = renderer->vt;
+ const char *shader_version;
+ const char *shader_precision;
+ if (filter->api->is_gles)
+ {
+ shader_version = "#version 100\n";
+ shader_precision = "precision highp float;\n";
+ }
+ else
+ {
+ shader_version = "#version 120\n";
+ shader_precision = "";
+ }
- char *vertex_shader = BuildVertexShader(filter);
- if (!vertex_shader)
- return VLC_EGENERIC;
+ const char *vertex_shader[] = {
+ shader_version,
+ VERTEX_SHADER_BODY,
+ };
+ const char *fragment_shader[] = {
+ shader_version,
+ extensions,
+ shader_precision,
+ sampler->shader.body,
+ FRAGMENT_SHADER_BODY,
+ };
- char *fragment_shader = BuildFragmentShader(filter);
- if (!fragment_shader)
+ if (renderer->dump_shaders)
{
- free(vertex_shader);
- return VLC_EGENERIC;
+ msg_Dbg(filter, "\n=== Vertex shader for fourcc: %4.4s ===\n",
+ (const char *) &renderer->sampler->fmt.i_chroma);
+ for (unsigned i = 0; i < ARRAY_SIZE(vertex_shader); ++i)
+ msg_Dbg(filter, "[%u] %s", i, vertex_shader[i]);
+
+ msg_Dbg(filter,
+ "\n=== Fragment shader for fourcc: %4.4s, colorspace: %d ===\n",
+ (const char *) &renderer->sampler->fmt.i_chroma,
+ sampler->fmt.space);
+ for (unsigned i = 0; i < ARRAY_SIZE(fragment_shader); ++i)
+ msg_Dbg(filter, "[%u] %s", i, fragment_shader[i]);
}
assert(sampler->ops &&
@@ -268,10 +246,8 @@ opengl_link_program(struct vlc_gl_filter *filter)
GLuint program_id =
vlc_gl_BuildProgram(VLC_OBJECT(filter), vt,
- 1, (const char **) &vertex_shader,
- 1, (const char **) &fragment_shader);
- free(vertex_shader);
- free(fragment_shader);
+ ARRAY_SIZE(vertex_shader), vertex_shader,
+ ARRAY_SIZE(fragment_shader), fragment_shader);
if (!program_id)
return VLC_EGENERIC;
More information about the vlc-commits
mailing list