From: Shinwoo Kim Date: Wed, 19 Jun 2019 01:28:34 +0000 (+0900) Subject: evas filter: make curve work for every X-Git-Tag: accepted/tizen/unified/20190620.071902^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=635ee0377cc79986ab1d4c16a2e3f4a41400a7cc;p=platform%2Fupstream%2Fefl.git evas filter: make curve work for every Summary: If an input buffer and an output buffer for the curve filter are same, it reads and writes to the same texture which behavior is not defined. I could not find good reference for this, but following could be a reference. https://stackoverflow.com/questions/11410292/opengl-read-and-write-to-the-same-texture The texture gets 0 color value as a result. So the curve filter does not work. This patch makes the curve filter use different input and output buffer. Test Plan: This attached file could explain what 'read and write to the same texture' is. {F3724537} Reviewers: Hermet, jpeg, jsuya Reviewed By: Hermet Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D9085 --- diff --git a/src/lib/evas/filters/evas_filter.c b/src/lib/evas/filters/evas_filter.c index b3dca7c..65632ab 100644 --- a/src/lib/evas/filters/evas_filter.c +++ b/src/lib/evas/filters/evas_filter.c @@ -1263,13 +1263,13 @@ evas_filter_command_grow_add(Evas_Filter_Context *ctx, void *draw_context, int inbuf, int outbuf, int radius, Eina_Bool smooth, Eina_Bool alphaonly) { - Evas_Filter_Command *blurcmd, *threshcmd, *blendcmd; - Evas_Filter_Buffer *tmp = NULL, *in, *out; + Evas_Filter_Command *blurcmd = NULL, *threshcmd = NULL, *blendcmd; + Evas_Filter_Buffer *tmp, *in, *out; int diam = abs(radius) * 2 + 1; DATA8 curve[256] = {0}; int tmin = 0, growbuf; - EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, NULL); + EINA_SAFETY_ON_NULL_GOTO(ctx, fail); if (!radius) { @@ -1279,15 +1279,15 @@ evas_filter_command_grow_add(Evas_Filter_Context *ctx, void *draw_context, } in = _filter_buffer_get(ctx, inbuf); - EINA_SAFETY_ON_NULL_RETURN_VAL(in, NULL); + EINA_SAFETY_ON_NULL_GOTO(in, fail); out = _filter_buffer_get(ctx, outbuf); - EINA_SAFETY_ON_NULL_RETURN_VAL(out, NULL); + EINA_SAFETY_ON_NULL_GOTO(out, fail); if ((inbuf != outbuf) && out->dirty) { tmp = evas_filter_temporary_buffer_get(ctx, in->w, in->h, in->alpha_only, 1); - EINA_SAFETY_ON_NULL_RETURN_VAL(tmp, NULL); + EINA_SAFETY_ON_NULL_GOTO(tmp, fail); growbuf = tmp->id; } else @@ -1297,7 +1297,7 @@ evas_filter_command_grow_add(Evas_Filter_Context *ctx, void *draw_context, EVAS_FILTER_BLUR_DEFAULT, abs(radius), abs(radius), 0, 0, 0, alphaonly); - if (!blurcmd) return NULL; + EINA_SAFETY_ON_NULL_GOTO(blurcmd, fail); if (diam > 255) diam = 255; if (radius > 0) @@ -1322,29 +1322,29 @@ evas_filter_command_grow_add(Evas_Filter_Context *ctx, void *draw_context, memset(curve + end, 255, 256 - end); } - threshcmd = evas_filter_command_curve_add(ctx, draw_context, growbuf, growbuf, + /* Use a temp buffer here. Becuase curve_add is using a temp buffer as well + if inbuf and outbuf are same and doing blend_add. Then grow_add will do + blend_add twice. Using a temp buffer will save a calling blend_add */ + tmp = evas_filter_temporary_buffer_get(ctx, in->w, in->h, in->alpha_only, 1); + EINA_SAFETY_ON_NULL_GOTO(tmp, fail); + + threshcmd = evas_filter_command_curve_add(ctx, draw_context, growbuf, tmp->id, curve, EVAS_FILTER_CHANNEL_ALPHA); - if (!threshcmd) - { - _command_del(ctx, blurcmd); - return NULL; - } + EINA_SAFETY_ON_NULL_GOTO(threshcmd, fail); - if (tmp) - { - blendcmd = evas_filter_command_blend_add(ctx, draw_context, tmp->id, - outbuf, 0, 0, - EVAS_FILTER_FILL_MODE_NONE, - alphaonly); - if (!blendcmd) - { - _command_del(ctx, threshcmd); - _command_del(ctx, blurcmd); - return NULL; - } - } + blendcmd = evas_filter_command_blend_add(ctx, draw_context, tmp->id, + outbuf, 0, 0, + EVAS_FILTER_FILL_MODE_NONE, + alphaonly); + EINA_SAFETY_ON_NULL_GOTO(blendcmd, fail); return blurcmd; + +fail: + ERR("Failed to add grow"); + if (threshcmd) _command_del(ctx, threshcmd); + if (blurcmd) _command_del(ctx, blurcmd); + return NULL; } Evas_Filter_Command * @@ -1353,8 +1353,8 @@ evas_filter_command_curve_add(Evas_Filter_Context *ctx, int inbuf, int outbuf, DATA8 *curve, Evas_Filter_Channel channel) { - Evas_Filter_Command *cmd; - Evas_Filter_Buffer *in, *out; + Evas_Filter_Command *cmd, *blendcmd; + Evas_Filter_Buffer *in, *out, *tmp = NULL, *curve_out; DATA8 *copy; EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, NULL); @@ -1369,12 +1369,20 @@ evas_filter_command_curve_add(Evas_Filter_Context *ctx, WRN("Incompatible formats for color curves, implicit conversion will be " "slow and may not produce the desired output."); - XDBG("Add curve %d -> %d", in->id, out->id); + if (in == out) + { + tmp = evas_filter_temporary_buffer_get(ctx, in->w, in->h, in->alpha_only, 1); + if (!tmp) return NULL; + curve_out = tmp; + } + else curve_out = out; + + XDBG("Add curve %d -> %d", in->id, curve_out->id); copy = malloc(256 * sizeof(DATA8)); if (!copy) return NULL; - cmd = _command_new(ctx, EVAS_FILTER_MODE_CURVE, in, NULL, out); + cmd = _command_new(ctx, EVAS_FILTER_MODE_CURVE, in, NULL, curve_out); if (!cmd) { _free(copy); @@ -1388,6 +1396,19 @@ evas_filter_command_curve_add(Evas_Filter_Context *ctx, else cmd->curve.channel = channel; + if (tmp) + { + blendcmd = evas_filter_command_blend_add(ctx, draw_context, curve_out->id, + out->id, 0, 0, + EVAS_FILTER_FILL_MODE_NONE, + out->alpha_only); + if (!blendcmd) + { + _command_del(ctx, cmd); + return NULL; + } + } + return cmd; }