Evas GL: Add support for uniforms in the shaders
This will simplify greatly the code for map masking.
This commit is contained in:
parent
888fc6e93f
commit
21d08f86e6
|
@ -468,6 +468,7 @@ struct _Evas_Engine_GL_Context
|
|||
GLfloat *texa;
|
||||
GLfloat *texsam;
|
||||
GLfloat *texm;
|
||||
Eina_List *uniforms; /* Evas_GL_Uniform */
|
||||
Eina_Bool line: 1;
|
||||
Eina_Bool use_vertex : 1;
|
||||
Eina_Bool use_color : 1;
|
||||
|
|
|
@ -1318,6 +1318,100 @@ array_alloc(Evas_Engine_GL_Context *gc, int n)
|
|||
RALOC(texm, GLfloat, 2);
|
||||
}
|
||||
|
||||
|
||||
/* Very basic uniform upload support.
|
||||
* TODO: Optimize out call to glGetUniformLocation(). */
|
||||
|
||||
typedef enum _Evas_GL_Uniform_Type Evas_GL_Uniform_Type;
|
||||
typedef struct _Evas_GL_Uniform Evas_GL_Uniform;
|
||||
|
||||
enum _Evas_GL_Uniform_Type {
|
||||
EVAS_GL_UNIFORM_FLOAT,
|
||||
EVAS_GL_UNIFORM_VEC2,
|
||||
EVAS_GL_UNIFORM_VEC4,
|
||||
// Add more types if needed.
|
||||
};
|
||||
|
||||
struct _Evas_GL_Uniform {
|
||||
Eina_Stringshare *name;
|
||||
Evas_GL_Uniform_Type type;
|
||||
union {
|
||||
GLfloat f;
|
||||
GLfloat vec2[2];
|
||||
GLfloat vec4[4];
|
||||
} value;
|
||||
};
|
||||
|
||||
static inline void
|
||||
push_uniform(Evas_Engine_GL_Context *gc, int n, Evas_GL_Uniform_Type type, const char *name, ...)
|
||||
{
|
||||
Evas_GL_Uniform *u = calloc(1, sizeof(Evas_GL_Uniform));
|
||||
va_list args;
|
||||
va_start(args, name);
|
||||
|
||||
if (!gc || !u) return;
|
||||
u->name = eina_stringshare_add(name);
|
||||
u->type = type;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case EVAS_GL_UNIFORM_FLOAT:
|
||||
u->value.f = (GLfloat) va_arg(args, double);
|
||||
break;
|
||||
case EVAS_GL_UNIFORM_VEC2:
|
||||
u->value.vec2[0] = (GLfloat) va_arg(args, double);
|
||||
u->value.vec2[1] = (GLfloat) va_arg(args, double);
|
||||
break;
|
||||
case EVAS_GL_UNIFORM_VEC4:
|
||||
u->value.vec4[0] = (GLfloat) va_arg(args, double);
|
||||
u->value.vec4[1] = (GLfloat) va_arg(args, double);
|
||||
u->value.vec4[2] = (GLfloat) va_arg(args, double);
|
||||
u->value.vec4[3] = (GLfloat) va_arg(args, double);
|
||||
break;
|
||||
default:
|
||||
free(u);
|
||||
va_end(args);
|
||||
return;
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
gc->pipe[n].array.uniforms = eina_list_append(gc->pipe[n].array.uniforms, u);
|
||||
}
|
||||
|
||||
static inline void
|
||||
shader_array_uniforms_set(Evas_Engine_GL_Context *gc, int n)
|
||||
{
|
||||
Evas_GL_Uniform *u;
|
||||
|
||||
if (!gc || !gc->pipe[n].array.uniforms) return;
|
||||
EINA_LIST_FREE(gc->pipe[n].array.uniforms, u)
|
||||
{
|
||||
GLint loc = glGetUniformLocation(gc->pipe[n].shader.cur_prog, u->name);
|
||||
GLERR(__FUNCTION__, __FILE__, __LINE__, "glUniform");
|
||||
if (loc >= 0)
|
||||
{
|
||||
switch (u->type)
|
||||
{
|
||||
case EVAS_GL_UNIFORM_FLOAT:
|
||||
glUniform1f(loc, u->value.f);
|
||||
break;
|
||||
case EVAS_GL_UNIFORM_VEC2:
|
||||
glUniform2fv(loc, 1, u->value.vec2);
|
||||
break;
|
||||
case EVAS_GL_UNIFORM_VEC4:
|
||||
glUniform4fv(loc, 1, u->value.vec4);
|
||||
break;
|
||||
default: ERR("Unhandled uniform type"); break;
|
||||
}
|
||||
GLERR(__FUNCTION__, __FILE__, __LINE__, "glUniform");
|
||||
}
|
||||
eina_stringshare_del(u->name);
|
||||
free(u);
|
||||
}
|
||||
}
|
||||
|
||||
#define PUSH_UNIFORM(pn, type, name, ...) push_uniform(gc, pn, type, name, __VA_ARGS__)
|
||||
|
||||
#ifdef GLPIPES
|
||||
static int
|
||||
pipe_region_intersects(Evas_Engine_GL_Context *gc, int n,
|
||||
|
@ -2706,8 +2800,8 @@ evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *gc,
|
|||
gc->pipe[pn].array.use_texuv2 = (utexture || uvtexture) ? 1 : 0;
|
||||
gc->pipe[pn].array.use_texuv3 = (utexture) ? 1 : 0;
|
||||
gc->pipe[pn].array.use_texm = !!mtex;
|
||||
gc->pipe[pn].array.use_texa = !!mtex;
|
||||
gc->pipe[pn].array.use_texsam = gc->pipe[pn].array.use_texm;
|
||||
gc->pipe[pn].array.use_texa = 0;
|
||||
gc->pipe[pn].array.use_texsam = 0;
|
||||
|
||||
pipe_region_expand(gc, pn, x, y, w, h);
|
||||
PIPE_GROW(gc, pn, 6);
|
||||
|
@ -2769,8 +2863,8 @@ evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *gc,
|
|||
|
||||
if (mtex)
|
||||
{
|
||||
GLfloat glmdx = 0.f, glmdy = 0.f, glmdw = 1.f, glmdh = 1.f, yinv = -1.f;
|
||||
GLfloat gw = gc->w, gh = gc->h;
|
||||
double glmdx = 0.f, glmdy = 0.f, glmdw = 1.f, glmdh = 1.f, yinv = -1.f;
|
||||
double gw = gc->w, gh = gc->h;
|
||||
|
||||
// Note: I couldn't write any test case where it was necessary
|
||||
// to know the mask position in its texture. Thus these unused vars.
|
||||
|
@ -2784,36 +2878,13 @@ evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *gc,
|
|||
yinv = 1.f;
|
||||
}
|
||||
|
||||
if (gw) glmdx = (GLfloat) mdx / (GLfloat) gw;
|
||||
if (gh) glmdy = (GLfloat) mdy / (GLfloat) gh;
|
||||
if (mdw) glmdw = (GLfloat) gw / (GLfloat) mdw;
|
||||
if (mdh) glmdh = (GLfloat) gh / (GLfloat) mdh;
|
||||
if (gw) glmdx = (double) mdx / (double) gw;
|
||||
if (gh) glmdy = (double) mdy / (double) gh;
|
||||
if (mdw) glmdw = (double) gw / (double) mdw;
|
||||
if (mdh) glmdh = (double) gh / (double) mdh;
|
||||
|
||||
// FIXME!!!
|
||||
// We seriously need uniforms here. Abusing tex_coordm for storage.
|
||||
// Passing mask x,y (on canvas) to the fragment shader
|
||||
PUSH_TEXM(pn, glmdx, glmdy);
|
||||
PUSH_TEXM(pn, glmdx, glmdy);
|
||||
PUSH_TEXM(pn, glmdx, glmdy);
|
||||
PUSH_TEXM(pn, glmdx, glmdy);
|
||||
PUSH_TEXM(pn, glmdx, glmdy);
|
||||
PUSH_TEXM(pn, glmdx, glmdy);
|
||||
|
||||
// Abusing tex_sample to pass mask 1/w, 1/h as well
|
||||
PUSH_TEXSAM(pn, glmdw, glmdh);
|
||||
PUSH_TEXSAM(pn, glmdw, glmdh);
|
||||
PUSH_TEXSAM(pn, glmdw, glmdh);
|
||||
PUSH_TEXSAM(pn, glmdw, glmdh);
|
||||
PUSH_TEXSAM(pn, glmdw, glmdh);
|
||||
PUSH_TEXSAM(pn, glmdw, glmdh);
|
||||
|
||||
// Abusing tex_coorda to pass Y-invert flag
|
||||
PUSH_TEXA(pn, 1.f, yinv);
|
||||
PUSH_TEXA(pn, 1.f, yinv);
|
||||
PUSH_TEXA(pn, 1.f, yinv);
|
||||
PUSH_TEXA(pn, 1.f, yinv);
|
||||
PUSH_TEXA(pn, 1.f, yinv);
|
||||
PUSH_TEXA(pn, 1.f, yinv);
|
||||
PUSH_UNIFORM(pn, EVAS_GL_UNIFORM_VEC4, "mask_Absolute", glmdx, glmdy, glmdw, glmdh);
|
||||
PUSH_UNIFORM(pn, EVAS_GL_UNIFORM_FLOAT, "yinvert", yinv);
|
||||
|
||||
//DBG("Orig %d,%d - %dx%d --> %f,%f - %f x %f", mdx, mdy, mdw, mdh,
|
||||
// glmdx, glmdy, glmdw, glmdh);
|
||||
|
@ -3347,18 +3418,6 @@ shader_array_flush(Evas_Engine_GL_Context *gc)
|
|||
|
||||
MASK_TEXTURE += 1;
|
||||
}
|
||||
else if (gc->pipe[i].array.use_texa && (gc->pipe[i].region.type == RTYPE_MAP))
|
||||
{
|
||||
/* FIXME:
|
||||
* This is a workaround as we hijack some tex ids
|
||||
* (namely tex_coordm, tex_coorda and tex_sample) for map masking.
|
||||
* These masking shaders should definitely use uniforms.
|
||||
*/
|
||||
glEnableVertexAttribArray(SHAD_TEXA);
|
||||
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
|
||||
glVertexAttribPointer(SHAD_TEXA, 2, GL_FLOAT, GL_FALSE, 0, (void *)texa_ptr);
|
||||
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
|
||||
}
|
||||
else
|
||||
{
|
||||
glDisableVertexAttribArray(SHAD_TEXA);
|
||||
|
@ -3520,6 +3579,10 @@ shader_array_flush(Evas_Engine_GL_Context *gc)
|
|||
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
|
||||
}
|
||||
|
||||
// Push all uniforms
|
||||
if (gc->pipe[i].array.uniforms)
|
||||
shader_array_uniforms_set(gc, i);
|
||||
|
||||
if (dbgflushnum == 1)
|
||||
{
|
||||
const char *types[6] =
|
||||
|
|
|
@ -2711,13 +2711,13 @@ static const char const map_mask_frag_glsl[] =
|
|||
"#endif\n"
|
||||
"#endif\n"
|
||||
"uniform sampler2D tex, texm;\n"
|
||||
"uniform vec4 mask_Absolute;\n"
|
||||
"varying vec2 tex_c;\n"
|
||||
"varying vec4 mask_Position, col, mask_Absolute;\n"
|
||||
"varying vec4 mask_Position, col;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" // FIXME: Use mask coordinates within its texture\n"
|
||||
" // FIXME: Fix Mach band effect using proper 4-point color interpolation\n"
|
||||
" // FIXME: We're abusing varying where we should have uniforms\n"
|
||||
" vec2 mpos = vec2(mask_Position.xy - mask_Absolute.xy) * mask_Absolute.zw;\n"
|
||||
" gl_FragColor = texture2D(tex, tex_c.xy).bgra * texture2D(texm, mpos).a * col;\n"
|
||||
"}\n";
|
||||
|
@ -2733,20 +2733,17 @@ static const char const map_mask_vert_glsl[] =
|
|||
"precision highp float;\n"
|
||||
"#endif\n"
|
||||
"attribute vec4 vertex, color;\n"
|
||||
"attribute vec2 tex_coord, tex_coordm, tex_sample, tex_coorda;\n"
|
||||
"attribute vec2 tex_coord;\n"
|
||||
"uniform float yinvert;\n"
|
||||
"uniform mat4 mvp;\n"
|
||||
"varying vec2 tex_c;\n"
|
||||
"varying vec4 mask_Position, col, mask_Absolute;\n"
|
||||
"varying vec4 mask_Position, col;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_Position = mvp * vertex;\n"
|
||||
" tex_c = tex_coord;\n"
|
||||
" col = color;\n"
|
||||
" // tex_coorda contains the Y-invert flag\n"
|
||||
" // tex_coordm contains the X,Y position of the mask\n"
|
||||
" // tex_sample contains the W,H size of the mask (inverted)\n"
|
||||
" mask_Position = mvp * vertex * vec4(tex_coorda.x * 0.5, tex_coorda.y * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);\n"
|
||||
" mask_Absolute = vec4(tex_coordm, tex_sample); // x, y, 1/w, 1/h on canvas in GL coords\n"
|
||||
" mask_Position = mvp * vertex * vec4(0.5, yinvert * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);\n"
|
||||
"}\n";
|
||||
Evas_GL_Program_Source shader_map_mask_vert_src =
|
||||
{
|
||||
|
@ -2813,13 +2810,13 @@ static const char const map_mask_bgra_frag_glsl[] =
|
|||
"#endif\n"
|
||||
"#endif\n"
|
||||
"uniform sampler2D tex, texm;\n"
|
||||
"uniform vec4 mask_Absolute;\n"
|
||||
"varying vec2 tex_c;\n"
|
||||
"varying vec4 mask_Position, col, mask_Absolute;\n"
|
||||
"varying vec4 mask_Position, col;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" // FIXME: Use mask coordinates within its texture\n"
|
||||
" // FIXME: Fix Mach band effect using proper 4-point color interpolation\n"
|
||||
" // FIXME: We're abusing varying where we should have uniforms\n"
|
||||
" vec2 mpos = vec2(mask_Position.xy - mask_Absolute.xy) * mask_Absolute.zw;\n"
|
||||
" gl_FragColor = texture2D(tex, tex_c.xy) * texture2D(texm, mpos).a * col;\n"
|
||||
"}\n";
|
||||
|
@ -2835,20 +2832,17 @@ static const char const map_mask_bgra_vert_glsl[] =
|
|||
"precision highp float;\n"
|
||||
"#endif\n"
|
||||
"attribute vec4 vertex, color;\n"
|
||||
"attribute vec2 tex_coord, tex_coordm, tex_sample, tex_coorda;\n"
|
||||
"attribute vec2 tex_coord;\n"
|
||||
"uniform float yinvert;\n"
|
||||
"uniform mat4 mvp;\n"
|
||||
"varying vec2 tex_c;\n"
|
||||
"varying vec4 mask_Position, col, mask_Absolute;\n"
|
||||
"varying vec4 mask_Position, col;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_Position = mvp * vertex;\n"
|
||||
" tex_c = tex_coord;\n"
|
||||
" col = color;\n"
|
||||
" // tex_coorda contains the Y-invert flag\n"
|
||||
" // tex_coordm contains the X,Y position of the mask\n"
|
||||
" // tex_sample contains the W,H size of the mask (inverted)\n"
|
||||
" mask_Position = mvp * vertex * vec4(tex_coorda.x * 0.5, tex_coorda.y * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);\n"
|
||||
" mask_Absolute = vec4(tex_coordm, tex_sample); // x, y, 1/w, 1/h on canvas in GL coords\n"
|
||||
" mask_Position = mvp * vertex * vec4(0.5, yinvert * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);\n"
|
||||
"}\n";
|
||||
Evas_GL_Program_Source shader_map_mask_bgra_vert_src =
|
||||
{
|
||||
|
|
|
@ -6,13 +6,13 @@ precision mediump float;
|
|||
#endif
|
||||
#endif
|
||||
uniform sampler2D tex, texm;
|
||||
uniform vec4 mask_Absolute;
|
||||
varying vec2 tex_c;
|
||||
varying vec4 mask_Position, col, mask_Absolute;
|
||||
varying vec4 mask_Position, col;
|
||||
void main()
|
||||
{
|
||||
// FIXME: Use mask coordinates within its texture
|
||||
// FIXME: Fix Mach band effect using proper 4-point color interpolation
|
||||
// FIXME: We're abusing varying where we should have uniforms
|
||||
vec2 mpos = vec2(mask_Position.xy - mask_Absolute.xy) * mask_Absolute.zw;
|
||||
gl_FragColor = texture2D(tex, tex_c.xy) * texture2D(texm, mpos).a * col;
|
||||
}
|
||||
|
|
|
@ -2,20 +2,16 @@
|
|||
precision highp float;
|
||||
#endif
|
||||
attribute vec4 vertex, color;
|
||||
attribute vec2 tex_coord, tex_coordm, tex_sample, tex_coorda;
|
||||
attribute vec2 tex_coord;
|
||||
uniform float yinvert;
|
||||
uniform mat4 mvp;
|
||||
varying vec2 tex_c;
|
||||
varying vec4 mask_Position, col, mask_Absolute;
|
||||
varying vec4 mask_Position, col;
|
||||
void main()
|
||||
{
|
||||
gl_Position = mvp * vertex;
|
||||
tex_c = tex_coord;
|
||||
col = color;
|
||||
|
||||
// tex_coorda contains the Y-invert flag
|
||||
// tex_coordm contains the X,Y position of the mask
|
||||
// tex_sample contains the W,H size of the mask (inverted)
|
||||
|
||||
mask_Position = mvp * vertex * vec4(tex_coorda.x * 0.5, tex_coorda.y * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);
|
||||
mask_Absolute = vec4(tex_coordm, tex_sample); // x, y, 1/w, 1/h on canvas in GL coords
|
||||
mask_Position = mvp * vertex * vec4(0.5, yinvert * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);
|
||||
}
|
||||
|
|
|
@ -6,13 +6,13 @@ precision mediump float;
|
|||
#endif
|
||||
#endif
|
||||
uniform sampler2D tex, texm;
|
||||
uniform vec4 mask_Absolute;
|
||||
varying vec2 tex_c;
|
||||
varying vec4 mask_Position, col, mask_Absolute;
|
||||
varying vec4 mask_Position, col;
|
||||
void main()
|
||||
{
|
||||
// FIXME: Use mask coordinates within its texture
|
||||
// FIXME: Fix Mach band effect using proper 4-point color interpolation
|
||||
// FIXME: We're abusing varying where we should have uniforms
|
||||
vec2 mpos = vec2(mask_Position.xy - mask_Absolute.xy) * mask_Absolute.zw;
|
||||
gl_FragColor = texture2D(tex, tex_c.xy).bgra * texture2D(texm, mpos).a * col;
|
||||
}
|
||||
|
|
|
@ -2,20 +2,16 @@
|
|||
precision highp float;
|
||||
#endif
|
||||
attribute vec4 vertex, color;
|
||||
attribute vec2 tex_coord, tex_coordm, tex_sample, tex_coorda;
|
||||
attribute vec2 tex_coord;
|
||||
uniform float yinvert;
|
||||
uniform mat4 mvp;
|
||||
varying vec2 tex_c;
|
||||
varying vec4 mask_Position, col, mask_Absolute;
|
||||
varying vec4 mask_Position, col;
|
||||
void main()
|
||||
{
|
||||
gl_Position = mvp * vertex;
|
||||
tex_c = tex_coord;
|
||||
col = color;
|
||||
|
||||
// tex_coorda contains the Y-invert flag
|
||||
// tex_coordm contains the X,Y position of the mask
|
||||
// tex_sample contains the W,H size of the mask (inverted)
|
||||
|
||||
mask_Position = mvp * vertex * vec4(tex_coorda.x * 0.5, tex_coorda.y * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);
|
||||
mask_Absolute = vec4(tex_coordm, tex_sample); // x, y, 1/w, 1/h on canvas in GL coords
|
||||
mask_Position = mvp * vertex * vec4(0.5, yinvert * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue