[vlc-commits] opengl: fetch attrib/uniform locations only one time
Thomas Guillem
git at videolan.org
Thu Jan 26 12:47:46 CET 2017
vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Wed Jan 25 18:22:18 2017 +0100| [8291e7363924d26c7e6c773704b2cf23da0d017e] | committer: Thomas Guillem
opengl: fetch attrib/uniform locations only one time
And assert/fails if a variable can't be found in the program. This will permit
to debug fragment and vertex shaders as missing variables won't be ignored
anymore (beware, variables can be optimized out).
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=8291e7363924d26c7e6c773704b2cf23da0d017e
---
modules/video_output/opengl/converter_android.c | 22 ++--
modules/video_output/opengl/converters.c | 78 ++++++++++----
modules/video_output/opengl/internal.h | 19 +++-
modules/video_output/opengl/vout_helper.c | 134 ++++++++++++++++--------
4 files changed, 179 insertions(+), 74 deletions(-)
diff --git a/modules/video_output/opengl/converter_android.c b/modules/video_output/opengl/converter_android.c
index 9e1f274..405a7b5 100644
--- a/modules/video_output/opengl/converter_android.c
+++ b/modules/video_output/opengl/converter_android.c
@@ -35,6 +35,10 @@ struct priv
{
SurfaceTexture *stex;
const float *transform_mtx;
+
+ struct {
+ GLint uSTMatrix;
+ } uloc;
};
static int
@@ -177,17 +181,22 @@ tc_anop_update(const opengl_tex_converter_t *tc, GLuint *textures,
return VLC_SUCCESS;
}
+static int
+tc_anop_fetch_locations(const opengl_tex_converter_t *tc, GLuint program)
+{
+ struct priv *priv = tc->priv;
+ priv->uloc.uSTMatrix = tc->api->GetUniformLocation(program, "uSTMatrix");
+ return priv->uloc.uSTMatrix != -1 ? VLC_SUCCESS : VLC_EGENERIC;
+}
+
static void
-tc_anop_prepare_shader(const opengl_tex_converter_t *tc,
- GLuint program, float alpha)
+tc_anop_prepare_shader(const opengl_tex_converter_t *tc, float alpha)
{
(void) alpha;
struct priv *priv = tc->priv;
if (priv->transform_mtx != NULL)
- {
- GLint handle = tc->api->GetUniformLocation(program, "uSTMatrix");
- tc->api->UniformMatrix4fv(handle, 1, GL_FALSE, priv->transform_mtx);
- }
+ tc->api->UniformMatrix4fv(priv->uloc.uSTMatrix, 1, GL_FALSE,
+ priv->transform_mtx);
}
static void
@@ -221,6 +230,7 @@ opengl_tex_converter_anop_init(const video_format_t *fmt,
tc->pf_del_textures = tc_anop_del_textures;
tc->pf_get_pool = tc_anop_get_pool;
tc->pf_update = tc_anop_update;
+ tc->pf_fetch_locations = tc_anop_fetch_locations;
tc->pf_prepare_shader = tc_anop_prepare_shader;
tc->pf_release = tc_anop_release;
diff --git a/modules/video_output/opengl/converters.c b/modules/video_output/opengl/converters.c
index 71863f1..0c96be9 100644
--- a/modules/video_output/opengl/converters.c
+++ b/modules/video_output/opengl/converters.c
@@ -58,6 +58,14 @@ struct priv
GLenum tex_format;
GLenum tex_type;
+ struct {
+ GLint Texture0;
+ GLint Texture1;
+ GLint Texture2;
+ GLint Coefficient;
+ GLint FillColor;
+ } uloc;
+
bool has_unpack_subimage;
void * texture_temp_buf;
size_t texture_temp_buf_size;
@@ -499,13 +507,22 @@ common_init(opengl_tex_converter_t *tc, size_t priv_size, vlc_fourcc_t chroma,
return VLC_SUCCESS;
}
+static int
+tc_rgba_fetch_locations(const opengl_tex_converter_t *tc, GLuint program)
+{
+ struct priv *priv = tc->priv;
+ priv->uloc.Texture0 = tc->api->GetUniformLocation(program, "Texture0");
+ priv->uloc.FillColor = tc->api->GetUniformLocation(program, "FillColor");
+ return priv->uloc.Texture0 != -1 && priv->uloc.FillColor != -1 ?
+ VLC_SUCCESS : VLC_EGENERIC;
+}
+
static void
-tc_rgba_prepare_shader(const opengl_tex_converter_t *tc,
- GLuint program, float alpha)
+tc_rgba_prepare_shader(const opengl_tex_converter_t *tc, float alpha)
{
- tc->api->Uniform1i(tc->api->GetUniformLocation(program, "Texture0"), 0);
- tc->api->Uniform4f(tc->api->GetUniformLocation(program, "FillColor"),
- 1.0f, 1.0f, 1.0f, alpha);
+ struct priv *priv = tc->priv;
+ tc->api->Uniform1i(priv->uloc.Texture0, 0);
+ tc->api->Uniform4f(priv->uloc.FillColor, 1.0f, 1.0f, 1.0f, alpha);
}
int
@@ -519,6 +536,7 @@ opengl_tex_converter_rgba_init(const video_format_t *fmt,
GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE) != VLC_SUCCESS)
return VLC_ENOMEM;
+ tc->pf_fetch_locations = tc_rgba_fetch_locations;
tc->pf_prepare_shader = tc_rgba_prepare_shader;
#if 0
@@ -538,12 +556,12 @@ opengl_tex_converter_rgba_init(const video_format_t *fmt,
static const char *code =
"#version " GLSL_VERSION "\n"
PRECISION
- "uniform sampler2D Texture;"
+ "uniform sampler2D Texture0;"
"uniform vec4 FillColor;"
"varying vec4 TexCoord0;"
"void main()"
"{ "
- " gl_FragColor = texture2D(Texture, TexCoord0.st) * FillColor;"
+ " gl_FragColor = texture2D(Texture0, TexCoord0.st) * FillColor;"
"}";
tc->fragment_shader = tc->api->CreateShader(GL_FRAGMENT_SHADER);
@@ -586,17 +604,29 @@ static int GetTexFormatSize(int target, int tex_format, int tex_internal,
}
#endif
+static int
+tc_yuv_fetch_locations(const opengl_tex_converter_t *tc, GLuint program)
+{
+ struct priv *priv = tc->priv;
+ priv->uloc.Coefficient = tc->api->GetUniformLocation(program, "Coefficient");
+ priv->uloc.Texture0 = tc->api->GetUniformLocation(program, "Texture0");
+ priv->uloc.Texture1 = tc->api->GetUniformLocation(program, "Texture1");
+ priv->uloc.Texture2 = tc->api->GetUniformLocation(program, "Texture2");
+ return priv->uloc.Coefficient != -1 && priv->uloc.Texture0 != -1
+ && priv->uloc.Texture1 != -1 && priv->uloc.Texture2 != -1 ?
+ VLC_SUCCESS : VLC_EGENERIC;
+}
+
static void
-tc_yuv_prepare_shader(const opengl_tex_converter_t *tc,
- GLuint program, float alpha)
+tc_yuv_prepare_shader(const opengl_tex_converter_t *tc, float alpha)
{
(void) alpha;
- struct yuv_priv *priv = tc->priv;
- tc->api->Uniform4fv(tc->api->GetUniformLocation(program, "Coefficient"), 4,
- priv->local_value);
- tc->api->Uniform1i(tc->api->GetUniformLocation(program, "Texture0"), 0);
- tc->api->Uniform1i(tc->api->GetUniformLocation(program, "Texture1"), 1);
- tc->api->Uniform1i(tc->api->GetUniformLocation(program, "Texture2"), 2);
+ struct priv *priv = tc->priv;
+ tc->api->Uniform4fv(priv->uloc.Coefficient, 4,
+ ((struct yuv_priv *)priv)->local_value);
+ tc->api->Uniform1i(priv->uloc.Texture0, 0);
+ tc->api->Uniform1i(priv->uloc.Texture1, 1);
+ tc->api->Uniform1i(priv->uloc.Texture2, 2);
}
int
@@ -658,6 +688,7 @@ opengl_tex_converter_yuv_init(const video_format_t *fmt,
if (!*list)
return VLC_EGENERIC;
+ tc->pf_fetch_locations = tc_yuv_fetch_locations;
tc->pf_prepare_shader = tc_yuv_prepare_shader;
GLfloat *local_value = ((struct yuv_priv*) tc->priv)->local_value;
@@ -750,12 +781,20 @@ opengl_tex_converter_yuv_init(const video_format_t *fmt,
return VLC_SUCCESS;
}
+static int
+tc_xyz12_fetch_locations(const opengl_tex_converter_t *tc, GLuint program)
+{
+ struct priv *priv = tc->priv;
+ priv->uloc.Texture0 = tc->api->GetUniformLocation(program, "Texture0");
+ return priv->uloc.Texture0 != -1 ? VLC_SUCCESS : VLC_EGENERIC;
+}
+
static void
-tc_xyz12_prepare_shader(const opengl_tex_converter_t *tc,
- GLuint program, float alpha)
+tc_xyz12_prepare_shader(const opengl_tex_converter_t *tc, float alpha)
{
- (void) tc; (void) alpha;
- tc->api->Uniform1i(tc->api->GetUniformLocation(program, "Texture0"), 0);
+ (void) alpha;
+ struct priv *priv = tc->priv;
+ tc->api->Uniform1i(priv->uloc.Texture0, 0);
}
int
@@ -769,6 +808,7 @@ opengl_tex_converter_xyz12_init(const video_format_t *fmt,
GL_RGB, GL_RGB, GL_UNSIGNED_SHORT) != VLC_SUCCESS)
return VLC_ENOMEM;
+ tc->pf_fetch_locations = tc_xyz12_fetch_locations;
tc->pf_prepare_shader = tc_xyz12_prepare_shader;
/* Shader for XYZ to RGB correction
diff --git a/modules/video_output/opengl/internal.h b/modules/video_output/opengl/internal.h
index e1be75d..22ee015 100644
--- a/modules/video_output/opengl/internal.h
+++ b/modules/video_output/opengl/internal.h
@@ -243,18 +243,27 @@ struct opengl_tex_converter_t
picture_t *pic, const size_t *plane_offset);
/*
+ * Callback to fetch locations of uniform or attributes variables
+ *
+ * This function pointer cannot be NULL. This callback is called one time
+ * after init.
+ *
+ * \param fc OpenGL tex converter
+ * \param program linked program that will be used by this tex converter
+ * \return VLC_SUCCESS or a VLC error
+ */
+ int (*pf_fetch_locations)(const opengl_tex_converter_t *fc, GLuint program);
+
+ /*
* Callback to prepare the fragment shader
*
* This function pointer cannot be NULL. This callback can be used to
- * specify values of uniform variables for the program object that is
- * attached to the configured shader.
+ * specify values of uniform variables.
*
* \param fc OpenGL tex converter
* \param alpha alpha value, used only for RGBA fragment shader
- * \param program current program object
*/
- void (*pf_prepare_shader)(const opengl_tex_converter_t *fc,
- GLuint program, float alpha);
+ void (*pf_prepare_shader)(const opengl_tex_converter_t *fc, float alpha);
/*
* Callback to release the shader and the private context
diff --git a/modules/video_output/opengl/vout_helper.c b/modules/video_output/opengl/vout_helper.c
index 3ed2822..7c4a455 100644
--- a/modules/video_output/opengl/vout_helper.c
+++ b/modules/video_output/opengl/vout_helper.c
@@ -78,6 +78,19 @@ struct prgm
{
GLuint id;
opengl_tex_converter_t tc;
+
+ struct { /* UniformLocation */
+ GLint OrientationMatrix;
+ GLint ProjectionMatrix;
+ GLint ZRotMatrix;
+ GLint YRotMatrix;
+ GLint XRotMatrix;
+ GLint ZoomMatrix;
+ } uloc;
+ struct { /* AttribLocation */
+ GLint MultiTexCoord[3];
+ GLint VertexPosition;
+ } aloc;
};
struct vout_display_opengl_t {
@@ -310,6 +323,7 @@ vout_display_opengl_t *vout_display_opengl_New(video_format_t *fmt,
tex_conv.fragment_shader != 0 &&
tex_conv.pf_gen_textures != NULL &&
tex_conv.pf_update != NULL &&
+ tex_conv.pf_fetch_locations != NULL &&
tex_conv.pf_prepare_shader != NULL &&
tex_conv.pf_release != NULL);
vgl->fmt = *fmt;
@@ -399,6 +413,53 @@ vout_display_opengl_t *vout_display_opengl_New(video_format_t *fmt,
vgl->chroma = vgl->prgm->tc.desc;
assert(vgl->chroma != NULL);
+ /* Fetch UniformLocations and AttribLocations */
+ for (GLuint i = 0; i < 2; i++)
+ {
+#define GET_LOC(type, x, str) do { \
+ x = vgl->api.Get##type##Location(prgm->id, str); \
+ assert(x != -1); \
+ if (x == -1) { \
+ msg_Err(gl, "Unable to Get"#type"Location(%s)\n", str); \
+ vout_display_opengl_Delete(vgl); \
+ return NULL; \
+ } \
+} 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)
+ struct prgm *prgm = &vgl->prgms[i];
+ GET_ULOC(OrientationMatrix, "OrientationMatrix");
+ GET_ULOC(ProjectionMatrix, "ProjectionMatrix");
+ GET_ULOC(ZRotMatrix, "ZRotMatrix");
+ GET_ULOC(YRotMatrix, "YRotMatrix");
+ GET_ULOC(XRotMatrix, "XRotMatrix");
+ GET_ULOC(ZoomMatrix, "ZoomMatrix");
+
+ GET_ALOC(VertexPosition, "VertexPosition");
+ GET_ALOC(MultiTexCoord[0], "MultiTexCoord0");
+ /* MultiTexCoord 1 and 2 can be optimized out if not used */
+ if (prgm->tc.desc->plane_count > 1)
+ GET_ALOC(MultiTexCoord[1], "MultiTexCoord1");
+ else
+ prgm->aloc.MultiTexCoord[1] = -1;
+ if (prgm->tc.desc->plane_count > 2)
+ GET_ALOC(MultiTexCoord[2], "MultiTexCoord2");
+ else
+ prgm->aloc.MultiTexCoord[2] = -1;
+#undef GET_LOC
+#undef GET_ULOC
+#undef GET_ALOC
+ int ret = prgm->tc.pf_fetch_locations(&prgm->tc, prgm->id);
+ assert(ret == VLC_SUCCESS);
+ if (ret != VLC_SUCCESS)
+ {
+ msg_Err(gl, "Unable to get locations from %4.4s tex_conv\n",
+ (const char *) &prgm->tc.chroma);
+ vout_display_opengl_Delete(vgl);
+ return NULL;
+ }
+ }
+
/* Texture size */
for (unsigned j = 0; j < vgl->chroma->plane_count; j++) {
int w = vgl->fmt.i_visible_width * vgl->chroma->p[j].w.num
@@ -1135,7 +1196,7 @@ static void DrawWithShaders(vout_display_opengl_t *vgl,
GLuint program = prgm->id;
opengl_tex_converter_t *tc = &prgm->tc;
vgl->api.UseProgram(program);
- tc->pf_prepare_shader(tc, program, 1.0f);
+ tc->pf_prepare_shader(tc, 1.0f);
GLfloat *vertexCoord, *textureCoord;
GLushort *indices;
@@ -1207,11 +1268,10 @@ static void DrawWithShaders(vout_display_opengl_t *vgl,
vgl->api.BufferData(GL_ARRAY_BUFFER, nbVertices * 2 * sizeof(GLfloat),
textureCoord + j * nbVertices * 2, GL_STATIC_DRAW);
- char attribute[20];
- snprintf(attribute, sizeof(attribute), "MultiTexCoord%1d", j);
- vgl->api.EnableVertexAttribArray(vgl->api.GetAttribLocation(program, attribute));
- vgl->api.VertexAttribPointer(vgl->api.GetAttribLocation(program, attribute), 2,
- GL_FLOAT, 0, 0, 0);
+ assert(prgm->aloc.MultiTexCoord[j] != -1);
+ vgl->api.EnableVertexAttribArray(prgm->aloc.MultiTexCoord[j]);
+ vgl->api.VertexAttribPointer(prgm->aloc.MultiTexCoord[j], 2, GL_FLOAT,
+ 0, 0, 0);
}
free(textureCoord);
vgl->api.BindBuffer(GL_ARRAY_BUFFER, vgl->vertex_buffer_object);
@@ -1220,23 +1280,17 @@ static void DrawWithShaders(vout_display_opengl_t *vgl,
vgl->api.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, vgl->index_buffer_object);
vgl->api.BufferData(GL_ELEMENT_ARRAY_BUFFER, nbIndices * sizeof(GLushort), indices, GL_STATIC_DRAW);
free(indices);
- vgl->api.EnableVertexAttribArray(vgl->api.GetAttribLocation(program,
- "VertexPosition"));
- vgl->api.VertexAttribPointer(vgl->api.GetAttribLocation(program, "VertexPosition"),
- 3, GL_FLOAT, 0, 0, 0);
-
- vgl->api.UniformMatrix4fv(vgl->api.GetUniformLocation(program, "OrientationMatrix"),
- 1, GL_FALSE, orientationMatrix);
- vgl->api.UniformMatrix4fv(vgl->api.GetUniformLocation(program, "ProjectionMatrix"),
- 1, GL_FALSE, projectionMatrix);
- vgl->api.UniformMatrix4fv(vgl->api.GetUniformLocation(program, "ZRotMatrix"),
- 1, GL_FALSE, zRotMatrix);
- vgl->api.UniformMatrix4fv(vgl->api.GetUniformLocation(program, "YRotMatrix"),
- 1, GL_FALSE, yRotMatrix);
- vgl->api.UniformMatrix4fv(vgl->api.GetUniformLocation(program, "XRotMatrix"),
- 1, GL_FALSE, xRotMatrix);
- vgl->api.UniformMatrix4fv(vgl->api.GetUniformLocation(program, "ZoomMatrix"),
- 1, GL_FALSE, zoomMatrix);
+ vgl->api.EnableVertexAttribArray(prgm->aloc.VertexPosition);
+ vgl->api.VertexAttribPointer(prgm->aloc.VertexPosition, 3, GL_FLOAT, 0, 0, 0);
+
+ vgl->api.UniformMatrix4fv(prgm->uloc.OrientationMatrix, 1, GL_FALSE,
+ orientationMatrix);
+ vgl->api.UniformMatrix4fv(prgm->uloc.ProjectionMatrix, 1, GL_FALSE,
+ projectionMatrix);
+ vgl->api.UniformMatrix4fv(prgm->uloc.ZRotMatrix, 1, GL_FALSE, zRotMatrix);
+ vgl->api.UniformMatrix4fv(prgm->uloc.YRotMatrix, 1, GL_FALSE, yRotMatrix);
+ vgl->api.UniformMatrix4fv(prgm->uloc.XRotMatrix, 1, GL_FALSE, xRotMatrix);
+ vgl->api.UniformMatrix4fv(prgm->uloc.ZoomMatrix, 1, GL_FALSE, zoomMatrix);
glDrawElements(GL_TRIANGLES, nbIndices, GL_UNSIGNED_SHORT, 0);
}
@@ -1326,35 +1380,27 @@ int vout_display_opengl_Display(vout_display_opengl_t *vgl,
assert(glr->texture != 0);
glBindTexture(tc->tex_target, glr->texture);
- tc->pf_prepare_shader(tc, program, glr->alpha);
+ tc->pf_prepare_shader(tc, glr->alpha);
vgl->api.BindBuffer(GL_ARRAY_BUFFER, vgl->subpicture_buffer_object[2 * i]);
vgl->api.BufferData(GL_ARRAY_BUFFER, sizeof(textureCoord), textureCoord, GL_STATIC_DRAW);
- vgl->api.EnableVertexAttribArray(vgl->api.GetAttribLocation(program,
- "MultiTexCoord0"));
- vgl->api.VertexAttribPointer(vgl->api.GetAttribLocation(program,
- "MultiTexCoord0"), 2, GL_FLOAT, 0, 0, 0);
+ vgl->api.EnableVertexAttribArray(prgm->aloc.MultiTexCoord[0]);
+ vgl->api.VertexAttribPointer(prgm->aloc.MultiTexCoord[0], 2, GL_FLOAT,
+ 0, 0, 0);
vgl->api.BindBuffer(GL_ARRAY_BUFFER, vgl->subpicture_buffer_object[2 * i + 1]);
vgl->api.BufferData(GL_ARRAY_BUFFER, sizeof(vertexCoord), vertexCoord, GL_STATIC_DRAW);
- vgl->api.EnableVertexAttribArray(vgl->api.GetAttribLocation(program,
- "VertexPosition"));
- vgl->api.VertexAttribPointer(vgl->api.GetAttribLocation(program,
- "VertexPosition"), 2, GL_FLOAT, 0, 0, 0);
+ vgl->api.EnableVertexAttribArray(prgm->aloc.VertexPosition);
+ vgl->api.VertexAttribPointer(prgm->aloc.VertexPosition, 2, GL_FLOAT,
+ 0, 0, 0);
// Subpictures have the correct orientation:
- vgl->api.UniformMatrix4fv(vgl->api.GetUniformLocation(program,
- "OrientationMatrix"), 1, GL_FALSE, identity);
- vgl->api.UniformMatrix4fv(vgl->api.GetUniformLocation(program,
- "ProjectionMatrix"), 1, GL_FALSE, identity);
- vgl->api.UniformMatrix4fv(vgl->api.GetUniformLocation(program,
- "ZRotMatrix"), 1, GL_FALSE, identity);
- vgl->api.UniformMatrix4fv(vgl->api.GetUniformLocation(program,
- "YRotMatrix"), 1, GL_FALSE, identity);
- vgl->api.UniformMatrix4fv(vgl->api.GetUniformLocation(program,
- "XRotMatrix"), 1, GL_FALSE, identity);
- vgl->api.UniformMatrix4fv(vgl->api.GetUniformLocation(program,
- "ZoomMatrix"), 1, GL_FALSE, identity);
+ vgl->api.UniformMatrix4fv(prgm->uloc.OrientationMatrix, 1, GL_FALSE, identity);
+ vgl->api.UniformMatrix4fv(prgm->uloc.ProjectionMatrix, 1, GL_FALSE, identity);
+ vgl->api.UniformMatrix4fv(prgm->uloc.ZRotMatrix, 1, GL_FALSE, identity);
+ vgl->api.UniformMatrix4fv(prgm->uloc.YRotMatrix, 1, GL_FALSE, identity);
+ vgl->api.UniformMatrix4fv(prgm->uloc.XRotMatrix, 1, GL_FALSE, identity);
+ vgl->api.UniformMatrix4fv(prgm->uloc.ZoomMatrix, 1, GL_FALSE, identity);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
More information about the vlc-commits
mailing list