summaryrefslogtreecommitdiff
path: root/src/lib/evas
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lib/evas/canvas/evas_filter_mixin.c4
-rw-r--r--src/lib/evas/canvas/evas_object_textblock.c2
-rw-r--r--src/lib/evas/filters/evas_filter.c64
-rw-r--r--src/lib/evas/filters/evas_filter_parser.c4
-rw-r--r--src/lib/evas/filters/evas_filter_private.h6
-rw-r--r--src/lib/evas/include/evas_filter.h4
6 files changed, 56 insertions, 28 deletions
diff --git a/src/lib/evas/canvas/evas_filter_mixin.c b/src/lib/evas/canvas/evas_filter_mixin.c
index d9ada4f1d8..31a7628241 100644
--- a/src/lib/evas/canvas/evas_filter_mixin.c
+++ b/src/lib/evas/canvas/evas_filter_mixin.c
@@ -401,7 +401,7 @@ evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
401 401
402 if (filter) 402 if (filter)
403 { 403 {
404 ok = evas_filter_context_program_reuse(filter, pd->data->chain); 404 ok = evas_filter_context_program_reuse(filter, pd->data->chain, X, Y);
405 if (!ok) 405 if (!ok)
406 { 406 {
407 fcow = FCOW_BEGIN(pd); 407 fcow = FCOW_BEGIN(pd);
@@ -417,7 +417,7 @@ evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
417 filter = evas_filter_context_new(obj->layer->evas, do_async, 0); 417 filter = evas_filter_context_new(obj->layer->evas, do_async, 0);
418 418
419 // Run script 419 // Run script
420 ok = evas_filter_context_program_use(filter, pd->data->chain, EINA_FALSE); 420 ok = evas_filter_context_program_use(filter, pd->data->chain, EINA_FALSE, X, Y);
421 if (!filter || !ok) 421 if (!filter || !ok)
422 { 422 {
423 ERR("Parsing failed?"); 423 ERR("Parsing failed?");
diff --git a/src/lib/evas/canvas/evas_object_textblock.c b/src/lib/evas/canvas/evas_object_textblock.c
index f65624fb28..abf076c609 100644
--- a/src/lib/evas/canvas/evas_object_textblock.c
+++ b/src/lib/evas/canvas/evas_object_textblock.c
@@ -13476,7 +13476,7 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
13476 ctx = evas_filter_context_new(obj->layer->evas, do_async, ti->gfx_filter); 13476 ctx = evas_filter_context_new(obj->layer->evas, do_async, ti->gfx_filter);
13477 evas_filter_state_prepare(eo_obj, &state, ti); 13477 evas_filter_state_prepare(eo_obj, &state, ti);
13478 evas_filter_program_state_set(pgm, &state); 13478 evas_filter_program_state_set(pgm, &state);
13479 ok = evas_filter_context_program_use(ctx, pgm, EINA_FALSE); 13479 ok = evas_filter_context_program_use(ctx, pgm, EINA_FALSE, 0, 0);
13480 if (!ok) 13480 if (!ok)
13481 { 13481 {
13482 evas_filter_context_destroy(ctx); 13482 evas_filter_context_destroy(ctx);
diff --git a/src/lib/evas/filters/evas_filter.c b/src/lib/evas/filters/evas_filter.c
index 2500590634..419c662dc2 100644
--- a/src/lib/evas/filters/evas_filter.c
+++ b/src/lib/evas/filters/evas_filter.c
@@ -165,7 +165,7 @@ evas_filter_context_proxy_render_all(Evas_Filter_Context *ctx, Eo *eo_obj,
165} 165}
166 166
167Eina_Bool 167Eina_Bool
168evas_filter_context_program_reuse(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm) 168evas_filter_context_program_reuse(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm, int x, int y)
169{ 169{
170 Evas_Filter_Buffer *fb; 170 Evas_Filter_Buffer *fb;
171 Eina_List *li; 171 Eina_List *li;
@@ -196,7 +196,7 @@ evas_filter_context_program_reuse(Evas_Filter_Context *ctx, Evas_Filter_Program
196 fb->dirty = EINA_FALSE; 196 fb->dirty = EINA_FALSE;
197 } 197 }
198 198
199 return evas_filter_context_program_use(ctx, pgm, EINA_TRUE); 199 return evas_filter_context_program_use(ctx, pgm, EINA_TRUE, x, y);
200} 200}
201 201
202static void 202static void
@@ -691,19 +691,24 @@ evas_filter_command_blur_add_gl(Evas_Filter_Context *ctx,
691 int rx, int ry, int ox, int oy, int count, 691 int rx, int ry, int ox, int oy, int count,
692 int R, int G, int B, int A) 692 int R, int G, int B, int A)
693{ 693{
694 Evas_Filter_Command *cmd; 694 Evas_Filter_Command *cmd = NULL;
695 Evas_Filter_Buffer *dx_in, *dx_out, *dy_in, *dy_out, *tmp = NULL; 695 Evas_Filter_Buffer *dx_in, *dx_out, *dy_in, *dy_out, *tmp = NULL;
696 int down_x = 1, down_y = 1;
697 int pad_x = 0, pad_y = 0;
696 double dx, dy; 698 double dx, dy;
697 699
698 /* GL blur implementation: 700 /* GL blur implementation:
699 * - Create intermediate buffer T (variable size)
700 * - Downscale to buffer T
701 * - Apply X blur kernel
702 * - Apply Y blur kernel while scaling up
703 * 701 *
704 * - TODO: Fix distortion X vs. Y 702 * - Create intermediate buffer T1, T2
705 * - TODO: Calculate best scaline and blur radius 703 * - Downscale input to buffer T1
706 * - TODO: Add post-processing? (2D single-pass) 704 * - Apply X blur kernel from T1 to T2
705 * - Apply Y blur kernel from T2 back to output
706 *
707 * In order to avoid sampling artifacts when moving or resizing a filtered
708 * snapshot, we make sure that we always sample and scale based on the same
709 * original pixels positions:
710 * - Input pixels must be aligned to down_x,down_y boundaries
711 * - T1/T2 buffer size is up to 1px larger than [input / scale_x,y]
707 */ 712 */
708 713
709 dx = rx; 714 dx = rx;
@@ -714,34 +719,43 @@ evas_filter_command_blur_add_gl(Evas_Filter_Context *ctx,
714#if 1 719#if 1
715 if (type == EVAS_FILTER_BLUR_DEFAULT) 720 if (type == EVAS_FILTER_BLUR_DEFAULT)
716 { 721 {
717 int down_x = 1, down_y = 1; 722 // Apply downscaling for large enough radii only.
718
719 /* For now, disable scaling - testing perfect gaussian blur until it's
720 * ready: */
721 down_x = 1 << evas_filter_smallest_pow2_larger_than(dx / 2) / 2; 723 down_x = 1 << evas_filter_smallest_pow2_larger_than(dx / 2) / 2;
722 down_y = 1 << evas_filter_smallest_pow2_larger_than(dy / 2) / 2; 724 down_y = 1 << evas_filter_smallest_pow2_larger_than(dy / 2) / 2;
725
726 // Downscaling to max 4 times for perfect picture quality (with
727 // the standard scaling fragment shader and SHD_SAM22).
723 if (down_x > 4) down_x = 4; 728 if (down_x > 4) down_x = 4;
724 if (down_y > 4) down_y = 4; 729 if (down_y > 4) down_y = 4;
725 730
726 if (down_x > 1 && down_y > 1) 731 if (down_x > 1 && down_y > 1)
727 { 732 {
728 tmp = evas_filter_temporary_buffer_get(ctx, 733 int ww, hh;
729 ceil(ctx->w / down_x), 734
730 ceil(ctx->h / down_y), 735 pad_x = ctx->x % down_x;
731 in->alpha_only, EINA_TRUE); 736 pad_y = ctx->y % down_y;
737
738 ww = ceil((double) ctx->w / down_x) + 1;
739 hh = ceil((double) ctx->h / down_y) + 1;
740
741 tmp = evas_filter_temporary_buffer_get(ctx, ww, hh, in->alpha_only, EINA_TRUE);
732 if (!tmp) goto fail; 742 if (!tmp) goto fail;
733 743
734 dx = rx / down_x; 744 dx /= (double) down_x;
735 dy = ry / down_y; 745 dy /= (double) down_y;
736 746
737 XDBG("Add GL downscale %d (%dx%d) -> %d (%dx%d)", in->id, in->w, in->h, tmp->id, tmp->w, tmp->h); 747 XDBG("Add GL downscale %d (%dx%d) -> %d (%dx%d)", in->id, in->w, in->h, tmp->id, tmp->w, tmp->h);
738 cmd = _command_new(ctx, EVAS_FILTER_MODE_BLEND, in, NULL, tmp); 748 cmd = _command_new(ctx, EVAS_FILTER_MODE_BLEND, in, NULL, tmp);
739 if (!cmd) goto fail; 749 if (!cmd) goto fail;
740 cmd->draw.fillmode = EVAS_FILTER_FILL_MODE_STRETCH_XY; 750 cmd->draw.fillmode = EVAS_FILTER_FILL_MODE_STRETCH_XY;
751 cmd->draw.scale.down = EINA_TRUE;
752 cmd->draw.scale.pad_x = pad_x;
753 cmd->draw.scale.pad_y = pad_y;
754 cmd->draw.scale.factor_x = down_x;
755 cmd->draw.scale.factor_y = down_y;
741 dx_in = tmp; 756 dx_in = tmp;
742 757
743 tmp = evas_filter_temporary_buffer_get(ctx, ctx->w / down_x, ctx->h / down_y, 758 tmp = evas_filter_temporary_buffer_get(ctx, ww, hh, in->alpha_only, EINA_TRUE);
744 in->alpha_only, EINA_TRUE);
745 if (!tmp) goto fail; 759 if (!tmp) goto fail;
746 dy_out = tmp; 760 dy_out = tmp;
747 } 761 }
@@ -780,6 +794,7 @@ evas_filter_command_blur_add_gl(Evas_Filter_Context *ctx,
780 cmd->blur.count = count; 794 cmd->blur.count = count;
781 } 795 }
782 796
797 EINA_SAFETY_ON_NULL_RETURN_VAL(cmd, NULL);
783 if (cmd->output != out) 798 if (cmd->output != out)
784 { 799 {
785 XDBG("Add GL upscale %d (%dx%d) -> %d (%dx%d)", 800 XDBG("Add GL upscale %d (%dx%d) -> %d (%dx%d)",
@@ -787,6 +802,11 @@ evas_filter_command_blur_add_gl(Evas_Filter_Context *ctx,
787 cmd = _command_new(ctx, EVAS_FILTER_MODE_BLEND, cmd->output, NULL, out); 802 cmd = _command_new(ctx, EVAS_FILTER_MODE_BLEND, cmd->output, NULL, out);
788 if (!cmd) goto fail; 803 if (!cmd) goto fail;
789 cmd->draw.fillmode = EVAS_FILTER_FILL_MODE_STRETCH_XY; 804 cmd->draw.fillmode = EVAS_FILTER_FILL_MODE_STRETCH_XY;
805 cmd->draw.scale.down = EINA_FALSE;
806 cmd->draw.scale.pad_x = pad_x;
807 cmd->draw.scale.pad_y = pad_y;
808 cmd->draw.scale.factor_x = down_x;
809 cmd->draw.scale.factor_y = down_y;
790 } 810 }
791 811
792 cmd->draw.ox = ox; 812 cmd->draw.ox = ox;
diff --git a/src/lib/evas/filters/evas_filter_parser.c b/src/lib/evas/filters/evas_filter_parser.c
index 60a7ecb476..ccf2806b6a 100644
--- a/src/lib/evas/filters/evas_filter_parser.c
+++ b/src/lib/evas/filters/evas_filter_parser.c
@@ -3474,7 +3474,7 @@ _instruction_dump(Evas_Filter_Instruction *instr)
3474Eina_Bool 3474Eina_Bool
3475evas_filter_context_program_use(Evas_Filter_Context *ctx, 3475evas_filter_context_program_use(Evas_Filter_Context *ctx,
3476 Evas_Filter_Program *pgm, 3476 Evas_Filter_Program *pgm,
3477 Eina_Bool reuse) 3477 Eina_Bool reuse, int object_x, int object_y)
3478{ 3478{
3479 Evas_Filter_Instruction *instr; 3479 Evas_Filter_Instruction *instr;
3480 Eina_Bool success = EINA_FALSE; 3480 Eina_Bool success = EINA_FALSE;
@@ -3489,6 +3489,8 @@ evas_filter_context_program_use(Evas_Filter_Context *ctx,
3489 // Copy current state (size, edje state val, color class, etc...) 3489 // Copy current state (size, edje state val, color class, etc...)
3490 ctx->w = pgm->state.w; 3490 ctx->w = pgm->state.w;
3491 ctx->h = pgm->state.h; 3491 ctx->h = pgm->state.h;
3492 ctx->x = object_x;
3493 ctx->y = object_y;
3492 3494
3493 // Create empty context with all required buffers 3495 // Create empty context with all required buffers
3494 evas_filter_context_clear(ctx, reuse); 3496 evas_filter_context_clear(ctx, reuse);
diff --git a/src/lib/evas/filters/evas_filter_private.h b/src/lib/evas/filters/evas_filter_private.h
index 01cda4853a..576cef3cca 100644
--- a/src/lib/evas/filters/evas_filter_private.h
+++ b/src/lib/evas/filters/evas_filter_private.h
@@ -125,6 +125,7 @@ struct _Evas_Filter_Context
125 evas_filter_buffer_scaled_get_func buffer_scaled_get; 125 evas_filter_buffer_scaled_get_func buffer_scaled_get;
126 126
127 // Variables changing at each run 127 // Variables changing at each run
128 int x, y; // Position of the object (for GL downscaling of snapshots)
128 int w, h; // Dimensions of the input/output buffers 129 int w, h; // Dimensions of the input/output buffers
129 130
130 struct { 131 struct {
@@ -233,6 +234,11 @@ struct _Evas_Filter_Command
233 int l, r, t, b; 234 int l, r, t, b;
234 }; 235 };
235 } clip; 236 } clip;
237 struct {
238 int factor_x, factor_y;
239 int pad_x, pad_y;
240 Eina_Bool down;
241 } scale;
236 Evas_Filter_Fill_Mode fillmode; 242 Evas_Filter_Fill_Mode fillmode;
237 Eina_Bool clip_use : 1; 243 Eina_Bool clip_use : 1;
238 Eina_Bool clip_mode_lrtb : 1; 244 Eina_Bool clip_mode_lrtb : 1;
diff --git a/src/lib/evas/include/evas_filter.h b/src/lib/evas/include/evas_filter.h
index 697215978a..ca79b36e1e 100644
--- a/src/lib/evas/include/evas_filter.h
+++ b/src/lib/evas/include/evas_filter.h
@@ -147,8 +147,8 @@ void *evas_filter_context_data_get(Evas_Filter_Context *ctx);
147Eina_Bool evas_filter_context_async_get(Evas_Filter_Context *ctx); 147Eina_Bool evas_filter_context_async_get(Evas_Filter_Context *ctx);
148void evas_filter_context_size_get(Evas_Filter_Context *ctx, int *w, int *H); 148void evas_filter_context_size_get(Evas_Filter_Context *ctx, int *w, int *H);
149void evas_filter_context_destroy(Evas_Filter_Context *ctx); 149void evas_filter_context_destroy(Evas_Filter_Context *ctx);
150Eina_Bool evas_filter_context_program_use(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm, Eina_Bool reuse); 150Eina_Bool evas_filter_context_program_use(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm, Eina_Bool reuse, int object_x, int object_y);
151Eina_Bool evas_filter_context_program_reuse(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm); 151Eina_Bool evas_filter_context_program_reuse(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm, int x, int y);
152void evas_filter_context_proxy_render_all(Evas_Filter_Context *ctx, Eo *eo_obj, Eina_Bool do_async); 152void evas_filter_context_proxy_render_all(Evas_Filter_Context *ctx, Eo *eo_obj, Eina_Bool do_async);
153void evas_filter_context_post_run_callback_set(Evas_Filter_Context *ctx, Evas_Filter_Cb cb, void *data); 153void evas_filter_context_post_run_callback_set(Evas_Filter_Context *ctx, Evas_Filter_Cb cb, void *data);
154#define evas_filter_context_autodestroy(ctx) evas_filter_context_post_run_callback_set(ctx, ((Evas_Filter_Cb) evas_filter_context_destroy), ctx) 154#define evas_filter_context_autodestroy(ctx) evas_filter_context_post_run_callback_set(ctx, ((Evas_Filter_Cb) evas_filter_context_destroy), ctx)