Commit 8291e736 authored by Thomas Guillem's avatar 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).
parent a6dec5c8
......@@ -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;
......
......@@ -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
......
......@@ -242,19 +242,28 @@ struct opengl_tex_converter_t
unsigned width, unsigned height,
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
......
......@@ -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);
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment