evas filters: Use GL downscaling for blur
This will improve the performance a lot. Now remains to figure out the best values for downscaling and improve the actual blur shader as well.
This commit is contained in:
parent
d56f9afa40
commit
a9ddeeb4fb
|
@ -543,24 +543,53 @@ static Evas_Filter_Command *
|
|||
evas_filter_command_blur_add_gl(Evas_Filter_Context *ctx,
|
||||
Evas_Filter_Buffer *in, Evas_Filter_Buffer *out,
|
||||
Evas_Filter_Blur_Type type,
|
||||
int dx, int dy, int ox, int oy, int count,
|
||||
int rx, int ry, int ox, int oy, int count,
|
||||
int R, int G, int B, int A)
|
||||
{
|
||||
Evas_Filter_Command *cmd;
|
||||
Evas_Filter_Buffer *dx_out, *dy_in;
|
||||
Evas_Filter_Buffer *dx_in, *dx_out, *dy_in, *tmp = NULL;
|
||||
int down_x, down_y, dx, dy;
|
||||
|
||||
/* GL blur implementation:
|
||||
* - Always split X and Y passes (only one pass if 1D blur)
|
||||
* - TODO: Repeat blur for large radius
|
||||
* - TODO: Scale down & up for cheap blur
|
||||
* - The rest is all up to the engine!
|
||||
* - Create intermediate buffer T (variable size)
|
||||
* - Downscale to buffer T
|
||||
* - Apply X blur kernel
|
||||
* - Apply Y blur kernel while scaling up
|
||||
*
|
||||
* - TODO: Fix distortion X vs. Y
|
||||
* - TODO: Calculate best scaline and blur radius
|
||||
* - TODO: Add post-processing? (2D single-pass)
|
||||
*/
|
||||
|
||||
dx = rx;
|
||||
dy = ry;
|
||||
dx_in = in;
|
||||
|
||||
if (type == EVAS_FILTER_BLUR_DEFAULT)
|
||||
{
|
||||
down_x = MAX((1 << evas_filter_smallest_pow2_larger_than(dx / 2) / 2), 1);
|
||||
down_y = MAX((1 << evas_filter_smallest_pow2_larger_than(dy / 2) / 2), 1);
|
||||
|
||||
tmp = evas_filter_temporary_buffer_get(ctx, ctx->w / down_x, ctx->h / down_y,
|
||||
in->alpha_only, EINA_TRUE);
|
||||
if (!tmp) goto fail;
|
||||
|
||||
// FIXME: Fix logic here. This is where the smarts are! Now it's dumb.
|
||||
dx = rx / down_x;
|
||||
dy = ry / down_y;
|
||||
|
||||
XDBG("Add GL downscale %d (%dx%d) -> %d (%dx%d)", in->id, in->w, in->h, tmp->id, tmp->w, tmp->h);
|
||||
cmd = _command_new(ctx, EVAS_FILTER_MODE_BLEND, in, NULL, tmp);
|
||||
if (!cmd) goto fail;
|
||||
cmd->draw.fillmode = EVAS_FILTER_FILL_MODE_STRETCH_XY;
|
||||
dx_in = tmp;
|
||||
}
|
||||
|
||||
if (dx && dy)
|
||||
{
|
||||
dx_out = evas_filter_temporary_buffer_get(ctx, 0, 0, in->alpha_only, 1);
|
||||
if (!dx_out) goto fail;
|
||||
dy_in = dx_out;
|
||||
tmp = evas_filter_temporary_buffer_get(ctx, 0, 0, in->alpha_only, 1);
|
||||
if (!tmp) goto fail;
|
||||
dy_in = dx_out = tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -570,8 +599,8 @@ evas_filter_command_blur_add_gl(Evas_Filter_Context *ctx,
|
|||
|
||||
if (dx)
|
||||
{
|
||||
XDBG("Add GL blur %d -> %d (%dx%d px)", in->id, dx_out->id, dx, 0);
|
||||
cmd = _command_new(ctx, EVAS_FILTER_MODE_BLUR, in, NULL, dx_out);
|
||||
XDBG("Add GL blur %d -> %d (%dx%d px)", dx_in->id, dx_out->id, dx, 0);
|
||||
cmd = _command_new(ctx, EVAS_FILTER_MODE_BLUR, dx_in, NULL, dx_out);
|
||||
if (!cmd) goto fail;
|
||||
cmd->blur.type = type;
|
||||
cmd->blur.dx = dx;
|
||||
|
|
|
@ -651,7 +651,7 @@ void evas_gl_common_filter_displace_push(Evas_Engine_GL_Context *gc
|
|||
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);
|
||||
void evas_gl_common_filter_blur_push(Evas_Engine_GL_Context *gc, Evas_GL_Texture *tex, int x, int y, int w, int h, double radius, Eina_Bool horiz);
|
||||
void evas_gl_common_filter_blur_push(Evas_Engine_GL_Context *gc, Evas_GL_Texture *tex, double sx, double sy, double sw, double sh, double dx, double dy, double dw, double dh, double radius, Eina_Bool horiz);
|
||||
|
||||
int evas_gl_common_shader_program_init(Evas_GL_Shared *shared);
|
||||
void evas_gl_common_shader_program_shutdown(Evas_GL_Shared *shared);
|
||||
|
|
|
@ -3430,11 +3430,11 @@ evas_gl_common_filter_curve_push(Evas_Engine_GL_Context *gc,
|
|||
void
|
||||
evas_gl_common_filter_blur_push(Evas_Engine_GL_Context *gc,
|
||||
Evas_GL_Texture *tex,
|
||||
int x, int y, int w, int h,
|
||||
double sx, double sy, double sw, double sh,
|
||||
double dx, double dy, double dw, double dh,
|
||||
double radius, Eina_Bool horiz)
|
||||
{
|
||||
double sx, sy, sw, sh, pw, ph;
|
||||
double ox1, oy1, ox2, oy2, ox3, oy3, ox4, oy4;
|
||||
double ox1, oy1, ox2, oy2, ox3, oy3, ox4, oy4, pw, ph;
|
||||
GLfloat tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4;
|
||||
GLfloat offsetx, offsety;
|
||||
int r, g, b, a, nomul = 0, pn;
|
||||
|
@ -3452,14 +3452,14 @@ evas_gl_common_filter_blur_push(Evas_Engine_GL_Context *gc,
|
|||
blend = EINA_FALSE;
|
||||
|
||||
prog = evas_gl_common_shader_program_get(gc, type, NULL, 0, r, g, b, a,
|
||||
w, h, w, h, smooth, tex, EINA_FALSE,
|
||||
sw, sh, dw, dh, smooth, tex, EINA_FALSE,
|
||||
NULL, EINA_FALSE, EINA_FALSE, 0, 0,
|
||||
NULL, &nomul, NULL);
|
||||
_filter_data_flush(gc, prog);
|
||||
EINA_SAFETY_ON_NULL_RETURN(prog);
|
||||
|
||||
pn = _evas_gl_common_context_push(type, gc, tex, NULL, prog,
|
||||
x, y, w, h, blend, smooth,
|
||||
sx, sy, dw, dh, blend, smooth,
|
||||
0, 0, 0, 0, 0, EINA_FALSE);
|
||||
|
||||
gc->pipe[pn].region.type = type;
|
||||
|
@ -3486,19 +3486,14 @@ evas_gl_common_filter_blur_push(Evas_Engine_GL_Context *gc,
|
|||
gc->pipe[pn].array.use_mask = 0;
|
||||
gc->pipe[pn].array.use_masksam = 0;
|
||||
|
||||
pipe_region_expand(gc, pn, x, y, w, h);
|
||||
pipe_region_expand(gc, pn, dx, dy, dw, dh);
|
||||
PIPE_GROW(gc, pn, 6);
|
||||
|
||||
// Set blur properties... TODO
|
||||
_filter_data_prepare(gc, pn, prog, 1);
|
||||
filter_data = gc->pipe[pn].array.filter_data;
|
||||
filter_data[0] = radius;
|
||||
filter_data[1] = horiz ? w : h;
|
||||
|
||||
sx = 0;
|
||||
sy = 0;
|
||||
sw = w;
|
||||
sh = h;
|
||||
filter_data[1] = horiz ? sw : sh;
|
||||
|
||||
pw = tex->pt->w;
|
||||
ph = tex->pt->h;
|
||||
|
@ -3524,7 +3519,7 @@ evas_gl_common_filter_blur_push(Evas_Engine_GL_Context *gc,
|
|||
tx4 = ((double)(offsetx) + ox4) / pw;
|
||||
ty4 = ((double)(offsety) + oy4) / ph;
|
||||
|
||||
PUSH_6_VERTICES(pn, x, y, w, h);
|
||||
PUSH_6_VERTICES(pn, dx, dy, dw, dh);
|
||||
PUSH_6_QUAD(pn, tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4);
|
||||
|
||||
if (!nomul)
|
||||
|
|
|
@ -7,16 +7,11 @@ _gl_filter_blur(Render_Engine_GL_Generic *re, Evas_Filter_Command *cmd)
|
|||
Evas_GL_Image *image, *surface;
|
||||
RGBA_Draw_Context *dc_save;
|
||||
Eina_Bool horiz;
|
||||
double radius;
|
||||
int x, y, w, h;
|
||||
double sx, sy, sw, sh, ssx, ssy, ssw, ssh, dx, dy, dw, dh, radius;
|
||||
int nx, ny, nw, nh;
|
||||
|
||||
DEBUG_TIME_BEGIN();
|
||||
|
||||
x = cmd->draw.ox;
|
||||
y = cmd->draw.oy;
|
||||
w = cmd->input->w;
|
||||
h = cmd->input->h;
|
||||
|
||||
re->window_use(re->software.ob);
|
||||
gc = re->window_gl_context_get(re->software.ob);
|
||||
|
||||
|
@ -52,7 +47,23 @@ _gl_filter_blur(Render_Engine_GL_Generic *re, Evas_Filter_Command *cmd)
|
|||
cmd->input->id, cmd->input->buffer, cmd->output->id, cmd->output->buffer,
|
||||
radius, horiz ? "X" : "Y");
|
||||
|
||||
evas_gl_common_filter_blur_push(gc, image->tex, x, y, w, h, radius, horiz);
|
||||
sx = 0;
|
||||
sy = 0;
|
||||
sw = cmd->input->w;
|
||||
sh = cmd->input->h;
|
||||
dx = cmd->draw.ox;
|
||||
dy = cmd->draw.oy;
|
||||
dw = cmd->output->w;
|
||||
dh = cmd->output->h;
|
||||
|
||||
nx = dx; ny = dy; nw = dw; nh = dh;
|
||||
RECTS_CLIP_TO_RECT(nx, ny, nw, nh, 0, 0, cmd->output->w, cmd->output->h);
|
||||
ssx = (double)sx + ((double)(sw * (nx - dx)) / (double)(dw));
|
||||
ssy = (double)sy + ((double)(sh * (ny - dy)) / (double)(dh));
|
||||
ssw = ((double)sw * (double)(nw)) / (double)(dw);
|
||||
ssh = ((double)sh * (double)(nh)) / (double)(dh);
|
||||
|
||||
evas_gl_common_filter_blur_push(gc, image->tex, ssx, ssy, ssw, ssh, dx, dy, dw, dh, radius, horiz);
|
||||
|
||||
evas_common_draw_context_free(gc->dc);
|
||||
gc->dc = dc_save;
|
||||
|
|
Loading…
Reference in New Issue