forked from enlightenment/efl
evas filters: Implement displace filter in pure GL
This one was a bit more... "fun". I had to add a new vertex attribute and obviously using a VertexAttribPointer led to incomprehensible crashes. But a simple glVertexAttrib2fv makes it work like a charm! A rare option is not handled yet.
This commit is contained in:
parent
ac8812665b
commit
125c7d956e
|
@ -844,6 +844,8 @@ modules/evas/engines/gl_generic/evas_ector_gl_buffer.c \
|
|||
modules/evas/engines/gl_generic/evas_ector_gl_image_buffer.c \
|
||||
modules/evas/engines/gl_generic/filters/gl_engine_filter.h \
|
||||
modules/evas/engines/gl_generic/filters/gl_filter_blend.c \
|
||||
modules/evas/engines/gl_generic/filters/gl_filter_curve.c \
|
||||
modules/evas/engines/gl_generic/filters/gl_filter_displace.c \
|
||||
modules/evas/engines/gl_generic/filters/gl_filter_fill.c \
|
||||
modules/evas/engines/gl_generic/filters/gl_filter_mask.c \
|
||||
$(NULL)
|
||||
|
|
|
@ -433,6 +433,11 @@ _command_new(Evas_Filter_Context *ctx, Evas_Filter_Mode mode,
|
|||
cmd->input = input;
|
||||
cmd->mask = mask;
|
||||
cmd->output = output;
|
||||
cmd->draw.R = 255;
|
||||
cmd->draw.G = 255;
|
||||
cmd->draw.B = 255;
|
||||
cmd->draw.A = 255;
|
||||
cmd->draw.rop = EFL_GFX_RENDER_OP_BLEND;
|
||||
if (output) output->dirty = EINA_TRUE;
|
||||
|
||||
ctx->commands = eina_inlist_append(ctx->commands, EINA_INLIST_GET(cmd));
|
||||
|
@ -1001,7 +1006,10 @@ evas_filter_command_curve_add(Evas_Filter_Context *ctx,
|
|||
|
||||
memcpy(copy, curve, 256 * sizeof(DATA8));
|
||||
cmd->curve.data = copy;
|
||||
cmd->curve.channel = channel;
|
||||
if (cmd->input->alpha_only)
|
||||
cmd->curve.channel = EVAS_FILTER_CHANNEL_ALPHA;
|
||||
else
|
||||
cmd->curve.channel = channel;
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
|
|
@ -107,6 +107,10 @@ struct _Evas_GL_Program
|
|||
struct {
|
||||
GLuint mvp, rotation_id;
|
||||
} uniform;
|
||||
struct {
|
||||
GLuint loc_filter_data[3];
|
||||
Eina_Bool known_locations;
|
||||
} attribute;
|
||||
GLuint prog;
|
||||
|
||||
Eina_Bool reset : 1;
|
||||
|
@ -239,6 +243,8 @@ enum _Shader_Type {
|
|||
SHD_NV12_709,
|
||||
SHD_RGB_A_PAIR,
|
||||
SHD_MAP,
|
||||
SHD_FILTER_DISPLACE,
|
||||
SHD_FILTER_CURVE,
|
||||
SHD_TYPE_LAST
|
||||
};
|
||||
|
||||
|
@ -268,6 +274,7 @@ struct _Evas_Engine_GL_Context
|
|||
Eina_Bool blend : 2;
|
||||
Eina_Bool clip : 2;
|
||||
Eina_Bool anti_alias : 2;
|
||||
Eina_Bool has_filter_data : 1;
|
||||
} current;
|
||||
} state;
|
||||
|
||||
|
@ -300,6 +307,11 @@ struct _Evas_Engine_GL_Context
|
|||
Eina_Bool blend : 2;
|
||||
Eina_Bool mask_smooth : 2;
|
||||
Eina_Bool clip : 2;
|
||||
struct {
|
||||
GLuint map_tex;
|
||||
Eina_Bool map_nearest : 1;
|
||||
Eina_Bool map_delete : 1;
|
||||
} filter;
|
||||
} shader;
|
||||
struct {
|
||||
int num, alloc;
|
||||
|
@ -312,6 +324,8 @@ struct _Evas_Engine_GL_Context
|
|||
GLfloat *texsam;
|
||||
GLfloat *mask;
|
||||
GLfloat *masksam;
|
||||
int filter_data_count; // number of vec2
|
||||
GLfloat *filter_data;
|
||||
Evas_GL_Image *im;
|
||||
GLuint buffer;
|
||||
int buffer_alloc;
|
||||
|
@ -631,6 +645,12 @@ void evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *g
|
|||
Eina_Bool tex_only,
|
||||
Evas_Colorspace cspace);
|
||||
|
||||
// Gfx Filters
|
||||
void evas_gl_common_filter_displace_push(Evas_Engine_GL_Context *gc, Evas_GL_Texture *tex, Evas_GL_Texture *map_tex,
|
||||
int x, int y, int w, int h, double dx, double dy, Eina_Bool nearest);
|
||||
void evas_gl_common_filter_curve_push(Evas_Engine_GL_Context *gc, Evas_GL_Texture *tex,
|
||||
int x, int y, int w, int h, const uint8_t *points, int channel);
|
||||
|
||||
int evas_gl_common_shader_program_init(Evas_GL_Shared *shared);
|
||||
void evas_gl_common_shader_program_shutdown(Evas_GL_Shared *shared);
|
||||
EAPI void evas_gl_common_shaders_flush(Evas_GL_Shared *shared);
|
||||
|
|
|
@ -1380,6 +1380,7 @@ evas_gl_common_context_free(Evas_Engine_GL_Context *gc)
|
|||
PIPE_FREE(gc->pipe[i].array.texsam);
|
||||
PIPE_FREE(gc->pipe[i].array.mask);
|
||||
PIPE_FREE(gc->pipe[i].array.masksam);
|
||||
PIPE_FREE(gc->pipe[i].array.filter_data);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3117,6 +3118,309 @@ evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *gc,
|
|||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Gfx Filters
|
||||
|
||||
static inline void
|
||||
_filter_data_flush(Evas_Engine_GL_Context *gc, Evas_GL_Program *prog)
|
||||
{
|
||||
// filter_data is not using a vertex array, which means early flushes
|
||||
// are necessary. Vertex arrays crashed for whatever reason :(
|
||||
for (size_t k = 0; k < MAX_PIPES; k++)
|
||||
if ((gc->pipe[k].array.filter_data || gc->pipe[k].shader.filter.map_tex)
|
||||
&& (gc->pipe[k].shader.prog == prog))
|
||||
{
|
||||
shader_array_flush(gc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
evas_gl_common_filter_displace_push(Evas_Engine_GL_Context *gc,
|
||||
Evas_GL_Texture *tex, Evas_GL_Texture *map_tex,
|
||||
int x, int y, int w, int h, double dx, double dy,
|
||||
Eina_Bool nearest)
|
||||
{
|
||||
double sx, sy, sw, sh, pw, ph;
|
||||
double ox1, oy1, ox2, oy2, ox3, oy3, ox4, oy4;
|
||||
GLfloat tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4;
|
||||
Shader_Sampling sam = SHD_SAM11;
|
||||
GLfloat offsetx, offsety;
|
||||
GLfloat *filter_data;
|
||||
int r, g, b, a, nomul = 0, pn;
|
||||
Evas_GL_Program *prog;
|
||||
Eina_Bool blend = EINA_TRUE;
|
||||
Eina_Bool smooth = EINA_TRUE;
|
||||
|
||||
r = R_VAL(&gc->dc->mul.col);
|
||||
g = G_VAL(&gc->dc->mul.col);
|
||||
b = B_VAL(&gc->dc->mul.col);
|
||||
a = A_VAL(&gc->dc->mul.col);
|
||||
if (gc->dc->render_op == EVAS_RENDER_COPY)
|
||||
blend = EINA_FALSE;
|
||||
|
||||
prog = evas_gl_common_shader_program_get(gc, SHD_FILTER_DISPLACE, NULL, 0, r, g, b, a,
|
||||
w, h, w, h, smooth, tex, EINA_FALSE,
|
||||
NULL, EINA_FALSE, EINA_FALSE, 0, 0,
|
||||
&sam, &nomul, NULL);
|
||||
_filter_data_flush(gc, prog);
|
||||
|
||||
pn = _evas_gl_common_context_push(SHD_FILTER_DISPLACE, gc, tex, NULL, prog,
|
||||
x, y, w, h, blend, smooth,
|
||||
0, 0, 0, 0, 0, EINA_FALSE);
|
||||
|
||||
gc->pipe[pn].region.type = SHD_FILTER_DISPLACE;
|
||||
gc->pipe[pn].shader.prog = prog;
|
||||
gc->pipe[pn].shader.cur_tex = tex->pt->texture;
|
||||
gc->pipe[pn].shader.cur_texm = 0;
|
||||
gc->pipe[pn].shader.tex_target = GL_TEXTURE_2D;
|
||||
gc->pipe[pn].shader.smooth = smooth;
|
||||
gc->pipe[pn].shader.mask_smooth = 0;
|
||||
gc->pipe[pn].shader.blend = blend;
|
||||
gc->pipe[pn].shader.render_op = gc->dc->render_op;
|
||||
gc->pipe[pn].shader.clip = 0;
|
||||
gc->pipe[pn].shader.cx = 0;
|
||||
gc->pipe[pn].shader.cy = 0;
|
||||
gc->pipe[pn].shader.cw = 0;
|
||||
gc->pipe[pn].shader.ch = 0;
|
||||
gc->pipe[pn].array.line = 0;
|
||||
gc->pipe[pn].array.use_vertex = 1;
|
||||
gc->pipe[pn].array.use_color = !nomul;
|
||||
gc->pipe[pn].array.use_texuv = 1;
|
||||
gc->pipe[pn].array.use_texuv2 = 0;
|
||||
gc->pipe[pn].array.use_texuv3 = 0;
|
||||
gc->pipe[pn].array.use_texsam = (sam != SHD_SAM11);
|
||||
gc->pipe[pn].array.use_mask = 0;
|
||||
gc->pipe[pn].array.use_masksam = 0;
|
||||
|
||||
pipe_region_expand(gc, pn, x, y, w, h);
|
||||
PIPE_GROW(gc, pn, 6);
|
||||
|
||||
// displace properties
|
||||
gc->pipe[pn].shader.filter.map_tex = map_tex->pt->texture;
|
||||
gc->pipe[pn].shader.filter.map_nearest = nearest;
|
||||
gc->pipe[pn].array.filter_data_count = 3;
|
||||
gc->pipe[pn].array.filter_data = malloc(6 * sizeof(GLfloat));
|
||||
|
||||
if (!prog->attribute.known_locations)
|
||||
{
|
||||
for (int k = 0; k < gc->pipe[pn].array.filter_data_count; k++)
|
||||
{
|
||||
char name[32];
|
||||
|
||||
sprintf(name, "filter_data_%d", k);
|
||||
prog->attribute.loc_filter_data[k] = glGetAttribLocation(prog->prog, name);
|
||||
}
|
||||
}
|
||||
|
||||
sx = x;
|
||||
sy = y;
|
||||
sw = w;
|
||||
sh = h;
|
||||
|
||||
pw = tex->pt->w;
|
||||
ph = tex->pt->h;
|
||||
|
||||
ox1 = sx;
|
||||
oy1 = sy;
|
||||
ox2 = sx + sw;
|
||||
oy2 = sy;
|
||||
ox3 = sx + sw;
|
||||
oy3 = sy + sh;
|
||||
ox4 = sx;
|
||||
oy4 = sy + sh;
|
||||
|
||||
offsetx = tex->x;
|
||||
offsety = tex->y;
|
||||
|
||||
tx1 = ((double)(offsetx) + ox1) / pw;
|
||||
ty1 = ((double)(offsety) + oy1) / ph;
|
||||
tx2 = ((double)(offsetx) + ox2) / pw;
|
||||
ty2 = ((double)(offsety) + oy2) / ph;
|
||||
tx3 = ((double)(offsetx) + ox3) / pw;
|
||||
ty3 = ((double)(offsety) + oy3) / ph;
|
||||
tx4 = ((double)(offsetx) + ox4) / pw;
|
||||
ty4 = ((double)(offsety) + oy4) / ph;
|
||||
|
||||
PUSH_6_VERTICES(pn, x, y, w, h);
|
||||
PUSH_6_QUAD(pn, tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4);
|
||||
|
||||
if (sam)
|
||||
{
|
||||
double samx = (double)(sw) / (double)(tex->pt->w * w * 4);
|
||||
double samy = (double)(sh) / (double)(tex->pt->h * h * 4);
|
||||
PUSH_SAMPLES(pn, samx, samy);
|
||||
}
|
||||
|
||||
filter_data = gc->pipe[pn].array.filter_data;
|
||||
filter_data[0] = (dx * tex->w / pw) / w;
|
||||
filter_data[1] = (dy * tex->h / ph) / h;
|
||||
filter_data[2] = tex->x / pw;
|
||||
filter_data[3] = tex->y / ph;
|
||||
filter_data[4] = (tex->x + tex->w) / pw;
|
||||
filter_data[5] = (tex->y + tex->h) / ph;
|
||||
|
||||
if (!nomul)
|
||||
PUSH_6_COLORS(pn, r, g, b, a);
|
||||
}
|
||||
|
||||
void
|
||||
evas_gl_common_filter_curve_push(Evas_Engine_GL_Context *gc,
|
||||
Evas_GL_Texture *tex,
|
||||
int x, int y, int w, int h,
|
||||
const uint8_t *points, int channel)
|
||||
{
|
||||
double sx, sy, sw, sh, pw, ph;
|
||||
double ox1, oy1, ox2, oy2, ox3, oy3, ox4, oy4;
|
||||
GLfloat tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4;
|
||||
Shader_Sampling sam = SHD_SAM11;
|
||||
GLfloat offsetx, offsety;
|
||||
int r, g, b, a, nomul = 0, pn, k;
|
||||
uint32_t values[256];
|
||||
Evas_GL_Program *prog;
|
||||
Eina_Bool blend = EINA_TRUE;
|
||||
Eina_Bool smooth = EINA_TRUE;
|
||||
GLuint map_tex;
|
||||
|
||||
r = R_VAL(&gc->dc->mul.col);
|
||||
g = G_VAL(&gc->dc->mul.col);
|
||||
b = B_VAL(&gc->dc->mul.col);
|
||||
a = A_VAL(&gc->dc->mul.col);
|
||||
if (gc->dc->render_op == EVAS_RENDER_COPY)
|
||||
blend = EINA_FALSE;
|
||||
|
||||
prog = evas_gl_common_shader_program_get(gc, SHD_FILTER_CURVE, NULL, 0, r, g, b, a,
|
||||
w, h, w, h, smooth, tex, EINA_FALSE,
|
||||
NULL, EINA_FALSE, EINA_FALSE, 0, 0,
|
||||
&sam, &nomul, NULL);
|
||||
_filter_data_flush(gc, prog);
|
||||
|
||||
pn = _evas_gl_common_context_push(SHD_FILTER_CURVE, gc, tex, NULL, prog,
|
||||
x, y, w, h, blend, smooth,
|
||||
0, 0, 0, 0, 0, EINA_FALSE);
|
||||
|
||||
gc->pipe[pn].region.type = SHD_FILTER_CURVE;
|
||||
gc->pipe[pn].shader.prog = prog;
|
||||
gc->pipe[pn].shader.cur_tex = tex->pt->texture;
|
||||
gc->pipe[pn].shader.cur_texm = 0;
|
||||
gc->pipe[pn].shader.tex_target = GL_TEXTURE_2D;
|
||||
gc->pipe[pn].shader.smooth = smooth;
|
||||
gc->pipe[pn].shader.mask_smooth = 0;
|
||||
gc->pipe[pn].shader.blend = blend;
|
||||
gc->pipe[pn].shader.render_op = gc->dc->render_op;
|
||||
gc->pipe[pn].shader.clip = 0;
|
||||
gc->pipe[pn].shader.cx = 0;
|
||||
gc->pipe[pn].shader.cy = 0;
|
||||
gc->pipe[pn].shader.cw = 0;
|
||||
gc->pipe[pn].shader.ch = 0;
|
||||
gc->pipe[pn].array.line = 0;
|
||||
gc->pipe[pn].array.use_vertex = 1;
|
||||
gc->pipe[pn].array.use_color = !nomul;
|
||||
gc->pipe[pn].array.use_texuv = 1;
|
||||
gc->pipe[pn].array.use_texuv2 = 0;
|
||||
gc->pipe[pn].array.use_texuv3 = 0;
|
||||
gc->pipe[pn].array.use_texsam = (sam != SHD_SAM11);
|
||||
gc->pipe[pn].array.use_mask = 0;
|
||||
gc->pipe[pn].array.use_masksam = 0;
|
||||
|
||||
pipe_region_expand(gc, pn, x, y, w, h);
|
||||
PIPE_GROW(gc, pn, 6);
|
||||
|
||||
// Build 256 colors map in RGBA
|
||||
switch (channel)
|
||||
{
|
||||
case 0: // EVAS_FILTER_CHANNEL_ALPHA
|
||||
for (k = 0; k < 256; k++)
|
||||
values[k] = ARGB_JOIN(points[k], k, k, k);
|
||||
break;
|
||||
case 1: // EVAS_FILTER_CHANNEL_RED
|
||||
for (k = 0; k < 256; k++)
|
||||
values[k] = ARGB_JOIN(k, points[k], k, k);
|
||||
break;
|
||||
case 2: // EVAS_FILTER_CHANNEL_GREEN
|
||||
for (k = 0; k < 256; k++)
|
||||
values[k] = ARGB_JOIN(k, k, points[k], k);
|
||||
break;
|
||||
case 3: // EVAS_FILTER_CHANNEL_BLUE
|
||||
for (k = 0; k < 256; k++)
|
||||
values[k] = ARGB_JOIN(k, k, k, points[k]);
|
||||
break;
|
||||
case 4: // EVAS_FILTER_CHANNEL_RGB
|
||||
for (k = 0; k < 256; k++)
|
||||
values[k] = ARGB_JOIN(k, points[k], points[k], points[k]);
|
||||
break;
|
||||
case 5: // ALPHA only
|
||||
for (k = 0; k < 256; k++)
|
||||
values[k] = ARGB_JOIN(points[k], points[k], points[k], points[k]);
|
||||
break;
|
||||
default: // INVALID: no curve applied
|
||||
for (k = 0; k < 256; k++)
|
||||
values[k] = ARGB_JOIN(k, k, k, k);
|
||||
break;
|
||||
}
|
||||
|
||||
// Synchronous upload of 256x1 RGBA texture (FIXME: no reuse)
|
||||
glGenTextures(1, &map_tex);
|
||||
glBindTexture(GL_TEXTURE_2D, map_tex);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, values);
|
||||
|
||||
// Set curve properties (no need for filter_data)
|
||||
gc->pipe[pn].shader.filter.map_tex = map_tex;
|
||||
gc->pipe[pn].shader.filter.map_nearest = EINA_TRUE;
|
||||
gc->pipe[pn].shader.filter.map_delete = EINA_TRUE;
|
||||
gc->pipe[pn].array.filter_data_count = 0;
|
||||
|
||||
sx = x;
|
||||
sy = y;
|
||||
sw = w;
|
||||
sh = h;
|
||||
|
||||
pw = tex->pt->w;
|
||||
ph = tex->pt->h;
|
||||
|
||||
ox1 = sx;
|
||||
oy1 = sy;
|
||||
ox2 = sx + sw;
|
||||
oy2 = sy;
|
||||
ox3 = sx + sw;
|
||||
oy3 = sy + sh;
|
||||
ox4 = sx;
|
||||
oy4 = sy + sh;
|
||||
|
||||
offsetx = tex->x;
|
||||
offsety = tex->y;
|
||||
|
||||
tx1 = ((double)(offsetx) + ox1) / pw;
|
||||
ty1 = ((double)(offsety) + oy1) / ph;
|
||||
tx2 = ((double)(offsetx) + ox2) / pw;
|
||||
ty2 = ((double)(offsety) + oy2) / ph;
|
||||
tx3 = ((double)(offsetx) + ox3) / pw;
|
||||
ty3 = ((double)(offsety) + oy3) / ph;
|
||||
tx4 = ((double)(offsetx) + ox4) / pw;
|
||||
ty4 = ((double)(offsety) + oy4) / ph;
|
||||
|
||||
PUSH_6_VERTICES(pn, x, y, w, h);
|
||||
PUSH_6_QUAD(pn, tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4);
|
||||
|
||||
if (sam)
|
||||
{
|
||||
double samx = (double)(sw) / (double)(tex->pt->w * w * 4);
|
||||
double samy = (double)(sh) / (double)(tex->pt->h * h * 4);
|
||||
PUSH_SAMPLES(pn, samx, samy);
|
||||
}
|
||||
|
||||
if (!nomul)
|
||||
PUSH_6_COLORS(pn, r, g, b, a);
|
||||
|
||||
shader_array_flush(gc);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
EAPI void
|
||||
evas_gl_common_context_flush(Evas_Engine_GL_Context *gc)
|
||||
{
|
||||
|
@ -3454,7 +3758,7 @@ shader_array_flush(Evas_Engine_GL_Context *gc)
|
|||
unsigned char *texsam_ptr = NULL;
|
||||
unsigned char *mask_ptr = NULL;
|
||||
unsigned char *masksam_ptr = NULL;
|
||||
GLint MASK_TEXTURE = GL_TEXTURE0;
|
||||
GLint ACTIVE_TEXTURE = GL_TEXTURE0;
|
||||
|
||||
if (glsym_glMapBuffer && glsym_glUnmapBuffer)
|
||||
{
|
||||
|
@ -3576,7 +3880,7 @@ shader_array_flush(Evas_Engine_GL_Context *gc)
|
|||
{
|
||||
glEnableVertexAttribArray(SHAD_MASK);
|
||||
glVertexAttribPointer(SHAD_MASK, MASK_CNT, GL_FLOAT, GL_FALSE, 0, mask_ptr);
|
||||
glActiveTexture(MASK_TEXTURE);
|
||||
glActiveTexture(ACTIVE_TEXTURE);
|
||||
glBindTexture(GL_TEXTURE_2D, gc->pipe[i].shader.cur_texm);
|
||||
#ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
|
||||
if (shared->info.anisotropic > 0.0)
|
||||
|
@ -3618,7 +3922,7 @@ shader_array_flush(Evas_Engine_GL_Context *gc)
|
|||
glEnableVertexAttribArray(SHAD_TEXUV);
|
||||
glVertexAttribPointer(SHAD_TEXUV, TEX_CNT, GL_FLOAT, GL_FALSE, 0, texuv_ptr);
|
||||
|
||||
MASK_TEXTURE += 1;
|
||||
ACTIVE_TEXTURE += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3650,7 +3954,7 @@ shader_array_flush(Evas_Engine_GL_Context *gc)
|
|||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
MASK_TEXTURE += 1;
|
||||
ACTIVE_TEXTURE += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3697,7 +4001,7 @@ shader_array_flush(Evas_Engine_GL_Context *gc)
|
|||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
MASK_TEXTURE += 2;
|
||||
ACTIVE_TEXTURE += 2;
|
||||
}
|
||||
else if (gc->pipe[i].array.use_texuv2)
|
||||
{
|
||||
|
@ -3728,7 +4032,7 @@ shader_array_flush(Evas_Engine_GL_Context *gc)
|
|||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
glDisableVertexAttribArray(SHAD_TEXUV3);
|
||||
MASK_TEXTURE += 1;
|
||||
ACTIVE_TEXTURE += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3741,7 +4045,7 @@ shader_array_flush(Evas_Engine_GL_Context *gc)
|
|||
{
|
||||
glEnableVertexAttribArray(SHAD_MASK);
|
||||
glVertexAttribPointer(SHAD_MASK, MASK_CNT, GL_FLOAT, GL_FALSE, 0, mask_ptr);
|
||||
glActiveTexture(MASK_TEXTURE);
|
||||
glActiveTexture(ACTIVE_TEXTURE);
|
||||
glBindTexture(GL_TEXTURE_2D, gc->pipe[i].shader.cur_texm);
|
||||
#ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
|
||||
if (shared->info.anisotropic > 0.0)
|
||||
|
@ -3767,6 +4071,7 @@ shader_array_flush(Evas_Engine_GL_Context *gc)
|
|||
glVertexAttribPointer(SHAD_MASKSAM, SAM_CNT, GL_FLOAT, GL_FALSE, 0, masksam_ptr);
|
||||
}
|
||||
else glDisableVertexAttribArray(SHAD_MASKSAM);
|
||||
ACTIVE_TEXTURE += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3774,10 +4079,38 @@ shader_array_flush(Evas_Engine_GL_Context *gc)
|
|||
glDisableVertexAttribArray(SHAD_MASKSAM);
|
||||
}
|
||||
|
||||
/* Gfx filters: data */
|
||||
if (gc->pipe[i].array.filter_data)
|
||||
{
|
||||
for (int k = 0; k < gc->pipe[i].array.filter_data_count; k++)
|
||||
glVertexAttrib2fv(prog->attribute.loc_filter_data[k], &gc->pipe[i].array.filter_data[k * 2]);
|
||||
}
|
||||
|
||||
/* Gfx filters: texture (or data array as texture) */
|
||||
if (gc->pipe[i].shader.filter.map_tex)
|
||||
{
|
||||
glActiveTexture(ACTIVE_TEXTURE);
|
||||
glBindTexture(GL_TEXTURE_2D, gc->pipe[i].shader.filter.map_tex);
|
||||
if (gc->pipe[i].shader.filter.map_nearest)
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
}
|
||||
else
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
}
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
ACTIVE_TEXTURE += 1;
|
||||
}
|
||||
|
||||
if (dbgflushnum == 1)
|
||||
{
|
||||
const char *types[] =
|
||||
{ "----", "RECT", "IMAG", "FONT", "YUV-", "YUY2", "NV12", "LINE", "PAIR", "EXTR", "MAP-" };
|
||||
{ "----", "RECT", "IMAG", "FONT", "YUV-", "YUY2", "NV12", "LINE", "PAIR", "EXTR", "MAP-", "FILTER_DISPLACE" };
|
||||
printf(" DRAW#%3i %4i -> %p[%4ix%4i] @ %4ix%4i -{ tex %4i type %s }-\n",
|
||||
i,
|
||||
gc->pipe[i].array.num / 6,
|
||||
|
@ -3818,6 +4151,13 @@ shader_array_flush(Evas_Engine_GL_Context *gc)
|
|||
gc->state.current.clip = gc->pipe[i].shader.clip;
|
||||
gc->state.current.anti_alias = gc->pipe[i].array.anti_alias;
|
||||
|
||||
if (gc->pipe[i].shader.filter.map_delete)
|
||||
{
|
||||
glDeleteTextures(1, &gc->pipe[i].shader.filter.map_tex);
|
||||
gc->pipe[i].shader.filter.map_delete = EINA_FALSE;
|
||||
gc->pipe[i].shader.filter.map_tex = 0;
|
||||
}
|
||||
|
||||
gc->pipe[i].array.line = 0;
|
||||
//gc->pipe[i].array.use_vertex = 0;
|
||||
gc->pipe[i].array.use_color = 0;
|
||||
|
@ -3829,6 +4169,7 @@ shader_array_flush(Evas_Engine_GL_Context *gc)
|
|||
gc->pipe[i].array.use_mask = 0;
|
||||
gc->pipe[i].array.use_masksam = 0;
|
||||
gc->pipe[i].array.anti_alias = 0;
|
||||
gc->pipe[i].array.filter_data_count = 0;
|
||||
|
||||
PIPE_FREE(gc->pipe[i].array.vertex);
|
||||
PIPE_FREE(gc->pipe[i].array.color);
|
||||
|
@ -3839,6 +4180,7 @@ shader_array_flush(Evas_Engine_GL_Context *gc)
|
|||
PIPE_FREE(gc->pipe[i].array.texsam);
|
||||
PIPE_FREE(gc->pipe[i].array.mask);
|
||||
PIPE_FREE(gc->pipe[i].array.masksam);
|
||||
PIPE_FREE(gc->pipe[i].array.filter_data);
|
||||
|
||||
gc->pipe[i].array.num = 0;
|
||||
gc->pipe[i].array.alloc = 0;
|
||||
|
|
|
@ -40,8 +40,10 @@ typedef enum {
|
|||
SHADER_FLAG_NOMUL = (1 << 18),
|
||||
SHADER_FLAG_ALPHA = (1 << 19),
|
||||
SHADER_FLAG_RGB_A_PAIR = (1 << 20),
|
||||
SHADER_FLAG_FILTER_DISPLACE = (1 << 21),
|
||||
SHADER_FLAG_FILTER_CURVE = (1 << 22),
|
||||
} Shader_Flag;
|
||||
#define SHADER_FLAG_COUNT 21
|
||||
#define SHADER_FLAG_COUNT 23
|
||||
|
||||
static const char *_shader_flags[SHADER_FLAG_COUNT] = {
|
||||
"TEX",
|
||||
|
@ -64,7 +66,9 @@ static const char *_shader_flags[SHADER_FLAG_COUNT] = {
|
|||
"AFILL",
|
||||
"NOMUL",
|
||||
"ALPHA",
|
||||
"RGB_A_PAIR"
|
||||
"RGB_A_PAIR",
|
||||
"FILTER_DISPLACE",
|
||||
"FILTER_CURVE"
|
||||
};
|
||||
|
||||
static Eina_Bool compiler_released = EINA_FALSE;
|
||||
|
@ -95,6 +99,20 @@ gl_compile_link_error(GLuint target, const char *action, Eina_Bool is_shader)
|
|||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_attributes_bind(GLint prg)
|
||||
{
|
||||
glBindAttribLocation(prg, SHAD_VERTEX, "vertex");
|
||||
glBindAttribLocation(prg, SHAD_COLOR, "color");
|
||||
glBindAttribLocation(prg, SHAD_TEXUV, "tex_coord");
|
||||
glBindAttribLocation(prg, SHAD_TEXUV2, "tex_coord2");
|
||||
glBindAttribLocation(prg, SHAD_TEXUV3, "tex_coord3");
|
||||
glBindAttribLocation(prg, SHAD_TEXA, "tex_coorda");
|
||||
glBindAttribLocation(prg, SHAD_TEXSAM, "tex_sample");
|
||||
glBindAttribLocation(prg, SHAD_MASK, "mask_coord");
|
||||
glBindAttribLocation(prg, SHAD_MASKSAM, "tex_masksample");
|
||||
}
|
||||
|
||||
static Evas_GL_Program *
|
||||
_evas_gl_common_shader_program_binary_load(Eet_File *ef, unsigned int flags)
|
||||
{
|
||||
|
@ -138,15 +156,7 @@ _evas_gl_common_shader_program_binary_load(Eet_File *ef, unsigned int flags)
|
|||
#endif
|
||||
glsym_glProgramBinary(prg, formats[0], data, length);
|
||||
|
||||
glBindAttribLocation(prg, SHAD_VERTEX, "vertex");
|
||||
glBindAttribLocation(prg, SHAD_COLOR, "color");
|
||||
glBindAttribLocation(prg, SHAD_TEXUV, "tex_coord");
|
||||
glBindAttribLocation(prg, SHAD_TEXUV2, "tex_coord2");
|
||||
glBindAttribLocation(prg, SHAD_TEXUV3, "tex_coord3");
|
||||
glBindAttribLocation(prg, SHAD_TEXA, "tex_coorda");
|
||||
glBindAttribLocation(prg, SHAD_TEXSAM, "tex_sample");
|
||||
glBindAttribLocation(prg, SHAD_MASK, "mask_coord");
|
||||
glBindAttribLocation(prg, SHAD_MASKSAM, "tex_masksample");
|
||||
_attributes_bind(prg);
|
||||
|
||||
glGetProgramiv(prg, GL_LINK_STATUS, &ok);
|
||||
if (!ok)
|
||||
|
@ -403,6 +413,7 @@ evas_gl_common_shader_glsl_get(unsigned int flags, const char *base)
|
|||
unsigned int k;
|
||||
char *str;
|
||||
|
||||
//eina_strbuf_append_printf(s, "#version 300 es\n");
|
||||
for (k = 0; k < SHADER_FLAG_COUNT; k++)
|
||||
{
|
||||
if (flags & (1 << k))
|
||||
|
@ -460,15 +471,7 @@ evas_gl_common_shader_compile(unsigned int flags, const char *vertex,
|
|||
glAttachShader(prg, vtx);
|
||||
glAttachShader(prg, frg);
|
||||
|
||||
glBindAttribLocation(prg, SHAD_VERTEX, "vertex");
|
||||
glBindAttribLocation(prg, SHAD_COLOR, "color");
|
||||
glBindAttribLocation(prg, SHAD_TEXUV, "tex_coord");
|
||||
glBindAttribLocation(prg, SHAD_TEXUV2, "tex_coord2");
|
||||
glBindAttribLocation(prg, SHAD_TEXUV3, "tex_coord3");
|
||||
glBindAttribLocation(prg, SHAD_TEXA, "tex_coorda");
|
||||
glBindAttribLocation(prg, SHAD_TEXSAM, "tex_sample");
|
||||
glBindAttribLocation(prg, SHAD_MASK, "mask_coord");
|
||||
glBindAttribLocation(prg, SHAD_MASKSAM, "tex_masksample");
|
||||
_attributes_bind(prg);
|
||||
|
||||
glLinkProgram(prg);
|
||||
glGetProgramiv(prg, GL_LINK_STATUS, &ok);
|
||||
|
@ -776,6 +779,12 @@ evas_gl_common_shader_flags_get(Evas_GL_Shared *shared, Shader_Type type,
|
|||
case SHD_RGB_A_PAIR:
|
||||
case SHD_MAP:
|
||||
break;
|
||||
case SHD_FILTER_DISPLACE:
|
||||
flags |= SHADER_FLAG_FILTER_DISPLACE;
|
||||
break;
|
||||
case SHD_FILTER_CURVE:
|
||||
flags |= SHADER_FLAG_FILTER_CURVE;
|
||||
break;
|
||||
default:
|
||||
CRI("Impossible shader type.");
|
||||
return 0;
|
||||
|
@ -847,6 +856,7 @@ evas_gl_common_shader_textures_bind(Evas_GL_Program *p)
|
|||
{ "texu", 0 },
|
||||
{ "texv", 0 },
|
||||
{ "texuv", 0 },
|
||||
{ "tex_filter", 0 },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
Eina_Bool hastex = 0;
|
||||
|
@ -881,6 +891,12 @@ evas_gl_common_shader_textures_bind(Evas_GL_Program *p)
|
|||
textures[5].enabled = 1;
|
||||
hastex = 1;
|
||||
}
|
||||
if ((p->flags & SHADER_FLAG_FILTER_DISPLACE) ||
|
||||
(p->flags & SHADER_FLAG_FILTER_CURVE))
|
||||
{
|
||||
textures[6].enabled = 1;
|
||||
hastex = 1;
|
||||
}
|
||||
|
||||
if (hastex)
|
||||
{
|
||||
|
|
|
@ -80,9 +80,26 @@ static const char fragment_glsl[] =
|
|||
"# endif\n"
|
||||
"# endif\n"
|
||||
"#endif\n"
|
||||
"#ifdef SHD_FILTER_DISPLACE\n"
|
||||
"uniform sampler2D tex_filter;\n"
|
||||
"varying vec2 displace_vector;\n"
|
||||
"varying vec2 displace_min;\n"
|
||||
"varying vec2 displace_max;\n"
|
||||
"#endif\n"
|
||||
"#ifdef SHD_FILTER_CURVE\n"
|
||||
"uniform sampler2D tex_filter;\n"
|
||||
"#endif\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
"#if defined(SHD_EXTERNAL) || defined(SHD_TEX)\n"
|
||||
" vec2 coord = tex_c;\n"
|
||||
"#endif\n"
|
||||
" vec4 c;\n"
|
||||
"#ifdef SHD_FILTER_DISPLACE\n"
|
||||
" vec2 dxy = texture2D(tex_filter, tex_c).rg * displace_vector;\n"
|
||||
" float fa = texture2D(tex_filter, tex_c).a;\n"
|
||||
" coord = clamp(tex_c + dxy, displace_min, displace_max);\n"
|
||||
"#endif\n"
|
||||
"#if defined(SHD_YUV) || defined(SHD_NV12) || defined(SHD_YUY2)\n"
|
||||
" float r, g, b, y, u, v, vmu;\n"
|
||||
"# if defined(SHD_YUV)\n"
|
||||
|
@ -116,17 +133,17 @@ static const char fragment_glsl[] =
|
|||
" b = y + u;\n"
|
||||
" c = vec4(r, g, b, 1.0);\n"
|
||||
"#elif defined(SHD_SAM12) || defined(SHD_SAM21)\n"
|
||||
" vec4 col00 = texture2D(tex, tex_c + tex_s[0]).SWZ;\n"
|
||||
" vec4 col01 = texture2D(tex, tex_c + tex_s[1]).SWZ;\n"
|
||||
" vec4 col00 = texture2D(tex, coord + tex_s[0]).SWZ;\n"
|
||||
" vec4 col01 = texture2D(tex, coord + tex_s[1]).SWZ;\n"
|
||||
" c = (col00 + col01) / div_s;\n"
|
||||
"#elif defined(SHD_SAM22)\n"
|
||||
" vec4 col00 = texture2D(tex, tex_c + tex_s[0]).SWZ;\n"
|
||||
" vec4 col01 = texture2D(tex, tex_c + tex_s[1]).SWZ;\n"
|
||||
" vec4 col10 = texture2D(tex, tex_c + tex_s[2]).SWZ;\n"
|
||||
" vec4 col11 = texture2D(tex, tex_c + tex_s[3]).SWZ;\n"
|
||||
" vec4 col00 = texture2D(tex, coord + tex_s[0]).SWZ;\n"
|
||||
" vec4 col01 = texture2D(tex, coord + tex_s[1]).SWZ;\n"
|
||||
" vec4 col10 = texture2D(tex, coord + tex_s[2]).SWZ;\n"
|
||||
" vec4 col11 = texture2D(tex, coord + tex_s[3]).SWZ;\n"
|
||||
" c = (col00 + col01 + col10 + col11) / div_s;\n"
|
||||
"#elif defined(SHD_TEX) || defined(SHD_EXTERNAL)\n"
|
||||
" c = texture2D(tex, tex_c).SWZ;\n"
|
||||
" c = texture2D(tex, coord).SWZ;\n"
|
||||
"#else\n"
|
||||
" c = vec4(1, 1, 1, 1);\n"
|
||||
"#endif\n"
|
||||
|
@ -168,6 +185,18 @@ static const char fragment_glsl[] =
|
|||
"#ifdef SHD_AFILL\n"
|
||||
" c.a = 1.0;\n"
|
||||
"#endif\n"
|
||||
"#ifdef SHD_TEXA\n"
|
||||
" c *= texture2D(texa, tex_a).r;\n"
|
||||
"#endif\n"
|
||||
"#if defined(SHD_FILTER_CURVE)\n"
|
||||
" float old_alpha = max(c.a, 0.00001);\n"
|
||||
" float new_alpha = texture2D(tex_filter, vec2(old_alpha, 0.0)).a;\n"
|
||||
" c = vec4(texture2D(tex_filter, vec2(c.r / old_alpha, 0.0)).r * new_alpha,\n"
|
||||
" texture2D(tex_filter, vec2(c.g / old_alpha, 0.0)).g * new_alpha,\n"
|
||||
" texture2D(tex_filter, vec2(c.b / old_alpha, 0.0)).b * new_alpha,\n"
|
||||
" new_alpha);\n"
|
||||
" //c = vec4(new_alpha, new_alpha, new_alpha, new_alpha);\n"
|
||||
"#endif\n"
|
||||
" gl_FragColor =\n"
|
||||
" c\n"
|
||||
"#ifndef SHD_NOMUL\n"
|
||||
|
@ -176,8 +205,8 @@ static const char fragment_glsl[] =
|
|||
"#ifdef SHD_MASK\n"
|
||||
" * ma\n"
|
||||
"#endif\n"
|
||||
"#ifdef SHD_TEXA\n"
|
||||
" * texture2D(texa, tex_a).r\n"
|
||||
"#ifdef SHD_FILTER_DISPLACE\n"
|
||||
" * fa\n"
|
||||
"#endif\n"
|
||||
" ;\n"
|
||||
"}\n";
|
||||
|
@ -244,6 +273,15 @@ static const char vertex_glsl[] =
|
|||
"varying vec2 masktex_s[4];\n"
|
||||
"# endif\n"
|
||||
"#endif\n"
|
||||
"/* Gfx Filters: displace */\n"
|
||||
"#ifdef SHD_FILTER_DISPLACE\n"
|
||||
"attribute vec2 filter_data_0;\n"
|
||||
"attribute vec2 filter_data_1;\n"
|
||||
"attribute vec2 filter_data_2;\n"
|
||||
"varying vec2 displace_vector;\n"
|
||||
"varying vec2 displace_min;\n"
|
||||
"varying vec2 displace_max;\n"
|
||||
"#endif\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_Position = mvp * vertex;\n"
|
||||
|
@ -307,5 +345,10 @@ static const char vertex_glsl[] =
|
|||
" pos[3] = vec2(window_Position.y, 1.0 - window_Position.x);\n"
|
||||
" tex_m = pos[rotation_id] * abs(mask_coord.zw) + mask_coord.xy;\n"
|
||||
"#endif\n"
|
||||
"#ifdef SHD_FILTER_DISPLACE\n"
|
||||
" displace_vector = filter_data_0;\n"
|
||||
" displace_min = filter_data_1;\n"
|
||||
" displace_max = filter_data_2;\n"
|
||||
"#endif\n"
|
||||
"}\n";
|
||||
|
||||
|
|
|
@ -74,10 +74,31 @@ varying vec2 masktex_s[4];
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef SHD_FILTER_DISPLACE
|
||||
uniform sampler2D tex_filter;
|
||||
varying vec2 displace_vector;
|
||||
varying vec2 displace_min;
|
||||
varying vec2 displace_max;
|
||||
#endif
|
||||
|
||||
#ifdef SHD_FILTER_CURVE
|
||||
uniform sampler2D tex_filter;
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
#if defined(SHD_EXTERNAL) || defined(SHD_TEX)
|
||||
vec2 coord = tex_c;
|
||||
#endif
|
||||
|
||||
vec4 c;
|
||||
|
||||
#ifdef SHD_FILTER_DISPLACE
|
||||
vec2 dxy = (texture2D(tex_filter, tex_c).rg - vec2(0.5, 0.5)) * displace_vector;
|
||||
float fa = texture2D(tex_filter, tex_c).a;
|
||||
coord = clamp(tex_c + dxy, displace_min, displace_max);
|
||||
#endif
|
||||
|
||||
#if defined(SHD_YUV) || defined(SHD_NV12) || defined(SHD_YUY2)
|
||||
float r, g, b, y, u, v, vmu;
|
||||
# if defined(SHD_YUV)
|
||||
|
@ -113,19 +134,19 @@ void main()
|
|||
c = vec4(r, g, b, 1.0);
|
||||
|
||||
#elif defined(SHD_SAM12) || defined(SHD_SAM21)
|
||||
vec4 col00 = texture2D(tex, tex_c + tex_s[0]).SWZ;
|
||||
vec4 col01 = texture2D(tex, tex_c + tex_s[1]).SWZ;
|
||||
vec4 col00 = texture2D(tex, coord + tex_s[0]).SWZ;
|
||||
vec4 col01 = texture2D(tex, coord + tex_s[1]).SWZ;
|
||||
c = (col00 + col01) / div_s;
|
||||
|
||||
#elif defined(SHD_SAM22)
|
||||
vec4 col00 = texture2D(tex, tex_c + tex_s[0]).SWZ;
|
||||
vec4 col01 = texture2D(tex, tex_c + tex_s[1]).SWZ;
|
||||
vec4 col10 = texture2D(tex, tex_c + tex_s[2]).SWZ;
|
||||
vec4 col11 = texture2D(tex, tex_c + tex_s[3]).SWZ;
|
||||
vec4 col00 = texture2D(tex, coord + tex_s[0]).SWZ;
|
||||
vec4 col01 = texture2D(tex, coord + tex_s[1]).SWZ;
|
||||
vec4 col10 = texture2D(tex, coord + tex_s[2]).SWZ;
|
||||
vec4 col11 = texture2D(tex, coord + tex_s[3]).SWZ;
|
||||
c = (col00 + col01 + col10 + col11) / div_s;
|
||||
|
||||
#elif defined(SHD_TEX) || defined(SHD_EXTERNAL)
|
||||
c = texture2D(tex, tex_c).SWZ;
|
||||
c = texture2D(tex, coord).SWZ;
|
||||
|
||||
#else
|
||||
c = vec4(1, 1, 1, 1);
|
||||
|
@ -171,6 +192,19 @@ void main()
|
|||
c.a = 1.0;
|
||||
#endif
|
||||
|
||||
#ifdef SHD_TEXA
|
||||
c *= texture2D(texa, tex_a).r;
|
||||
#endif
|
||||
|
||||
#if defined(SHD_FILTER_CURVE)
|
||||
float old_alpha = max(c.a, 0.00001);
|
||||
float new_alpha = texture2D(tex_filter, vec2(old_alpha, 0.0)).a;
|
||||
c = vec4(texture2D(tex_filter, vec2(c.r / old_alpha, 0.0)).r * new_alpha,
|
||||
texture2D(tex_filter, vec2(c.g / old_alpha, 0.0)).g * new_alpha,
|
||||
texture2D(tex_filter, vec2(c.b / old_alpha, 0.0)).b * new_alpha,
|
||||
new_alpha);
|
||||
#endif
|
||||
|
||||
gl_FragColor =
|
||||
c
|
||||
#ifndef SHD_NOMUL
|
||||
|
@ -179,8 +213,8 @@ void main()
|
|||
#ifdef SHD_MASK
|
||||
* ma
|
||||
#endif
|
||||
#ifdef SHD_TEXA
|
||||
* texture2D(texa, tex_a).r
|
||||
#ifdef SHD_FILTER_DISPLACE
|
||||
* fa
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
|
|
@ -68,6 +68,16 @@ varying vec2 masktex_s[4];
|
|||
# endif
|
||||
#endif
|
||||
|
||||
/* Gfx Filters: displace */
|
||||
#ifdef SHD_FILTER_DISPLACE
|
||||
attribute vec2 filter_data_0;
|
||||
attribute vec2 filter_data_1;
|
||||
attribute vec2 filter_data_2;
|
||||
varying vec2 displace_vector;
|
||||
varying vec2 displace_min;
|
||||
varying vec2 displace_max;
|
||||
#endif
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
|
@ -141,5 +151,11 @@ void main()
|
|||
pos[3] = vec2(window_Position.y, 1.0 - window_Position.x);
|
||||
tex_m = pos[rotation_id] * abs(mask_coord.zw) + mask_coord.xy;
|
||||
#endif
|
||||
|
||||
#ifdef SHD_FILTER_DISPLACE
|
||||
displace_vector = filter_data_0;
|
||||
displace_min = filter_data_1;
|
||||
displace_max = filter_data_2;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -3031,8 +3031,8 @@ _gfx_filter_func_get(Evas_Filter_Command *cmd)
|
|||
case EVAS_FILTER_MODE_BLEND: funcptr = gl_filter_blend_func_get(cmd); break;
|
||||
//case EVAS_FILTER_MODE_BLUR: funcptr = gl_filter_blur_func_get(cmd); break;
|
||||
//case EVAS_FILTER_MODE_BUMP: funcptr = gl_filter_bump_func_get(cmd); break;
|
||||
//case EVAS_FILTER_MODE_CURVE: funcptr = gl_filter_curve_func_get(cmd); break;
|
||||
//case EVAS_FILTER_MODE_DISPLACE: funcptr = gl_filter_displace_func_get(cmd); break;
|
||||
case EVAS_FILTER_MODE_CURVE: funcptr = gl_filter_curve_func_get(cmd); break;
|
||||
case EVAS_FILTER_MODE_DISPLACE: funcptr = gl_filter_displace_func_get(cmd); break;
|
||||
case EVAS_FILTER_MODE_FILL: funcptr = gl_filter_fill_func_get(cmd); break;
|
||||
case EVAS_FILTER_MODE_MASK: funcptr = gl_filter_mask_func_get(cmd); break;
|
||||
//case EVAS_FILTER_MODE_TRANSFORM: funcptr = gl_filter_transform_func_get(cmd); break;
|
||||
|
|
|
@ -12,8 +12,8 @@ typedef Eina_Bool (* GL_Filter_Apply_Func) (Render_Engine_GL_Generic *re, Evas_F
|
|||
GL_Filter_Apply_Func gl_filter_blend_func_get(Evas_Filter_Command *cmd);
|
||||
//GL_Filter_Apply_Func gl_filter_blur_func_get(Evas_Filter_Command *cmd);
|
||||
//GL_Filter_Apply_Func gl_filter_bump_func_get(Evas_Filter_Command *cmd);
|
||||
//GL_Filter_Apply_Func gl_filter_curve_func_get(Evas_Filter_Command *cmd);
|
||||
//GL_Filter_Apply_Func gl_filter_displace_func_get(Evas_Filter_Command *cmd);
|
||||
GL_Filter_Apply_Func gl_filter_curve_func_get(Evas_Filter_Command *cmd);
|
||||
GL_Filter_Apply_Func gl_filter_displace_func_get(Evas_Filter_Command *cmd);
|
||||
GL_Filter_Apply_Func gl_filter_fill_func_get(Evas_Filter_Command *cmd);
|
||||
GL_Filter_Apply_Func gl_filter_mask_func_get(Evas_Filter_Command *cmd);
|
||||
//GL_Filter_Apply_Func gl_filter_transform_func_get(Evas_Filter_Command *cmd);
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
#include "gl_engine_filter.h"
|
||||
|
||||
static Eina_Bool
|
||||
_gl_filter_curve(Render_Engine_GL_Generic *re, Evas_Filter_Command *cmd)
|
||||
{
|
||||
Evas_Engine_GL_Context *gc;
|
||||
Evas_GL_Image *image, *surface;
|
||||
RGBA_Draw_Context *dc_save;
|
||||
const uint8_t *points;
|
||||
int channel;
|
||||
int w, h;
|
||||
|
||||
DEBUG_TIME_BEGIN();
|
||||
|
||||
w = cmd->input->w;
|
||||
h = cmd->input->h;
|
||||
EINA_SAFETY_ON_FALSE_RETURN_VAL(w == cmd->output->w, EINA_FALSE);
|
||||
EINA_SAFETY_ON_FALSE_RETURN_VAL(h == cmd->output->h, EINA_FALSE);
|
||||
|
||||
image = evas_ector_buffer_drawable_image_get(cmd->input->buffer);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(image, EINA_FALSE);
|
||||
|
||||
surface = evas_ector_buffer_render_image_get(cmd->output->buffer);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(surface, EINA_FALSE);
|
||||
|
||||
DBG("curve %d @%p -> %d @%p", cmd->input->id, cmd->input->buffer,
|
||||
cmd->output->id, cmd->output->buffer);
|
||||
|
||||
re->window_use(re->software.ob);
|
||||
gc = re->window_gl_context_get(re->software.ob);
|
||||
evas_gl_common_context_target_surface_set(gc, surface);
|
||||
|
||||
dc_save = gc->dc;
|
||||
gc->dc = evas_common_draw_context_new();
|
||||
evas_common_draw_context_set_multiplier(gc->dc, cmd->draw.R, cmd->draw.G, cmd->draw.B, cmd->draw.A);
|
||||
evas_common_draw_context_clip_clip(gc->dc, 0, 0, w, h);
|
||||
if (cmd->input == cmd->output)
|
||||
gc->dc->render_op = EVAS_RENDER_COPY;
|
||||
|
||||
points = cmd->curve.data;
|
||||
channel = (int) cmd->curve.channel;
|
||||
if (cmd->input->alpha_only)
|
||||
channel = 5;
|
||||
|
||||
evas_gl_common_filter_curve_push(gc, image->tex, 0, 0, w, h, points, channel);
|
||||
|
||||
evas_common_draw_context_free(gc->dc);
|
||||
gc->dc = dc_save;
|
||||
|
||||
evas_ector_buffer_engine_image_release(cmd->input->buffer, image);
|
||||
evas_ector_buffer_engine_image_release(cmd->output->buffer, surface);
|
||||
|
||||
DEBUG_TIME_END();
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
GL_Filter_Apply_Func
|
||||
gl_filter_curve_func_get(Evas_Filter_Command *cmd)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd, NULL);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input, NULL);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output, NULL);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->curve.data, NULL);
|
||||
|
||||
return _gl_filter_curve;
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
#include "gl_engine_filter.h"
|
||||
|
||||
static Eina_Bool
|
||||
_gl_filter_displace(Render_Engine_GL_Generic *re, Evas_Filter_Command *cmd)
|
||||
{
|
||||
Evas_Engine_GL_Context *gc;
|
||||
Evas_GL_Image *image, *surface, *orig_map, *use_map;
|
||||
RGBA_Draw_Context *dc_save;
|
||||
int x, y, w, h, map_w, map_h;
|
||||
Eina_Bool nearest = EINA_FALSE;
|
||||
double dx, dy;
|
||||
|
||||
DEBUG_TIME_BEGIN();
|
||||
|
||||
w = cmd->input->w;
|
||||
h = cmd->input->h;
|
||||
dx = dy = cmd->displacement.intensity;
|
||||
EINA_SAFETY_ON_FALSE_RETURN_VAL(w == cmd->output->w, EINA_FALSE);
|
||||
EINA_SAFETY_ON_FALSE_RETURN_VAL(h == cmd->output->h, EINA_FALSE);
|
||||
|
||||
image = evas_ector_buffer_drawable_image_get(cmd->input->buffer);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(image, EINA_FALSE);
|
||||
|
||||
orig_map = evas_ector_buffer_drawable_image_get(cmd->mask->buffer);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(orig_map, EINA_FALSE);
|
||||
|
||||
surface = evas_ector_buffer_render_image_get(cmd->output->buffer);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(surface, EINA_FALSE);
|
||||
|
||||
DBG("displace %d @%p map %d %p -> %d @%p", cmd->input->id, cmd->input->buffer,
|
||||
cmd->mask->id, cmd->mask->buffer, cmd->output->id, cmd->output->buffer);
|
||||
|
||||
re->window_use(re->software.ob);
|
||||
gc = re->window_gl_context_get(re->software.ob);
|
||||
evas_gl_common_context_target_surface_set(gc, surface);
|
||||
|
||||
dc_save = gc->dc;
|
||||
gc->dc = evas_common_draw_context_new();
|
||||
evas_common_draw_context_set_multiplier(gc->dc, cmd->draw.R, cmd->draw.G, cmd->draw.B, cmd->draw.A);
|
||||
evas_common_draw_context_clip_clip(gc->dc, 0, 0, w, h);
|
||||
|
||||
map_w = (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_X) ? w : cmd->mask->w;
|
||||
map_h = (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_Y) ? h : cmd->mask->h;
|
||||
use_map = evas_gl_common_image_virtual_scaled_get(NULL, orig_map, map_w, map_h, EINA_TRUE);
|
||||
|
||||
// FIXME: Flags not handled:
|
||||
// EVAS_FILTER_DISPLACE_BLACK vs. EVAS_FILTER_DISPLACE_STRETCH
|
||||
|
||||
if ((cmd->displacement.flags & EVAS_FILTER_DISPLACE_LINEAR) == 0)
|
||||
nearest = EINA_TRUE;
|
||||
|
||||
for (y = 0; y < h; y += map_h)
|
||||
for (x = 0; x < w; x += map_w)
|
||||
{
|
||||
int sw, sh;
|
||||
|
||||
sw = MIN(map_w, w - x);
|
||||
sh = MIN(map_h, h - y);
|
||||
|
||||
evas_gl_common_filter_displace_push(gc, image->tex, use_map->tex,
|
||||
x, y, sw, sh, dx, dy, nearest);
|
||||
}
|
||||
|
||||
evas_common_draw_context_free(gc->dc);
|
||||
gc->dc = dc_save;
|
||||
|
||||
evas_ector_buffer_engine_image_release(cmd->input->buffer, image);
|
||||
evas_ector_buffer_engine_image_release(cmd->mask->buffer, orig_map);
|
||||
evas_ector_buffer_engine_image_release(cmd->output->buffer, surface);
|
||||
|
||||
DEBUG_TIME_END();
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
GL_Filter_Apply_Func
|
||||
gl_filter_displace_func_get(Evas_Filter_Command *cmd)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd, NULL);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input, NULL);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output, NULL);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->mask, NULL);
|
||||
|
||||
return _gl_filter_displace;
|
||||
}
|
Loading…
Reference in New Issue