diff options
Diffstat (limited to '')
-rw-r--r-- | src/lib/evas/canvas/evas_filter_mixin.c | 4 | ||||
-rw-r--r-- | src/lib/evas/canvas/evas_object_textblock.c | 2 | ||||
-rw-r--r-- | src/lib/evas/filters/evas_filter.c | 64 | ||||
-rw-r--r-- | src/lib/evas/filters/evas_filter_parser.c | 4 | ||||
-rw-r--r-- | src/lib/evas/filters/evas_filter_private.h | 6 | ||||
-rw-r--r-- | src/lib/evas/include/evas_filter.h | 4 |
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 | ||
167 | Eina_Bool | 167 | Eina_Bool |
168 | evas_filter_context_program_reuse(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm) | 168 | evas_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 | ||
202 | static void | 202 | static 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) | |||
3474 | Eina_Bool | 3474 | Eina_Bool |
3475 | evas_filter_context_program_use(Evas_Filter_Context *ctx, | 3475 | evas_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); | |||
147 | Eina_Bool evas_filter_context_async_get(Evas_Filter_Context *ctx); | 147 | Eina_Bool evas_filter_context_async_get(Evas_Filter_Context *ctx); |
148 | void evas_filter_context_size_get(Evas_Filter_Context *ctx, int *w, int *H); | 148 | void evas_filter_context_size_get(Evas_Filter_Context *ctx, int *w, int *H); |
149 | void evas_filter_context_destroy(Evas_Filter_Context *ctx); | 149 | void evas_filter_context_destroy(Evas_Filter_Context *ctx); |
150 | Eina_Bool evas_filter_context_program_use(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm, Eina_Bool reuse); | 150 | Eina_Bool evas_filter_context_program_use(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm, Eina_Bool reuse, int object_x, int object_y); |
151 | Eina_Bool evas_filter_context_program_reuse(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm); | 151 | Eina_Bool evas_filter_context_program_reuse(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm, int x, int y); |
152 | void evas_filter_context_proxy_render_all(Evas_Filter_Context *ctx, Eo *eo_obj, Eina_Bool do_async); | 152 | void evas_filter_context_proxy_render_all(Evas_Filter_Context *ctx, Eo *eo_obj, Eina_Bool do_async); |
153 | void evas_filter_context_post_run_callback_set(Evas_Filter_Context *ctx, Evas_Filter_Cb cb, void *data); | 153 | void 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) |