2013-06-20 03:53:29 -07:00
|
|
|
#include "evas_common_private.h"
|
2002-11-08 00:02:15 -08:00
|
|
|
#include "evas_private.h"
|
2011-10-10 23:06:11 -07:00
|
|
|
#include <math.h>
|
2013-09-02 21:48:08 -07:00
|
|
|
#include <assert.h>
|
2002-11-08 00:02:15 -08:00
|
|
|
|
2013-01-17 06:31:34 -08:00
|
|
|
#ifdef EVAS_RENDER_DEBUG_TIMING
|
|
|
|
#include <sys/time.h>
|
|
|
|
#endif
|
|
|
|
|
2017-03-14 22:49:50 -07:00
|
|
|
// FIXME: Ugly!
|
|
|
|
#define EFL_CANVAS_FILTER_INTERNAL_PROTECTED
|
|
|
|
#include "efl_canvas_filter_internal.eo.h"
|
|
|
|
|
2015-09-03 23:13:35 -07:00
|
|
|
/* Enable this for extra verbose rendering debug logs */
|
2015-10-07 18:56:35 -07:00
|
|
|
//#define REND_DBG 1
|
2015-09-03 23:13:35 -07:00
|
|
|
#define STDOUT_DBG
|
2009-11-15 05:46:20 -08:00
|
|
|
|
2012-09-12 12:00:23 -07:00
|
|
|
#ifdef REND_DBG
|
2009-11-15 05:46:20 -08:00
|
|
|
static FILE *dbf = NULL;
|
2015-09-01 04:47:40 -07:00
|
|
|
static int __RD_level = 0;
|
2015-10-07 18:56:35 -07:00
|
|
|
static int __RD_enable = REND_DBG;
|
2009-11-15 05:46:20 -08:00
|
|
|
|
2017-01-11 04:18:59 -08:00
|
|
|
static inline Eina_Slstr *
|
|
|
|
_efl_object_name(const Evas_Object_Protected_Data *obj)
|
|
|
|
{
|
|
|
|
const Eo *eo_obj;
|
|
|
|
const char *name;
|
|
|
|
const char *klass;
|
|
|
|
|
|
|
|
if (!obj) return "(nil)";
|
|
|
|
eo_obj = obj->object;
|
|
|
|
name = obj->name ?: efl_name_get(eo_obj);
|
|
|
|
klass = obj->type; //efl_class_name_get(eo_obj);
|
|
|
|
if (name)
|
|
|
|
return eina_slstr_printf("[%p@%p: %s '%s']", eo_obj, obj, klass, name);
|
|
|
|
else
|
|
|
|
return eina_slstr_printf("[%p@%p: %s]", eo_obj, obj, klass);
|
|
|
|
}
|
|
|
|
|
|
|
|
#define RDNAME(_obj) _efl_object_name(_obj)
|
|
|
|
|
2009-11-15 05:46:20 -08:00
|
|
|
static void
|
|
|
|
rend_dbg(const char *txt)
|
|
|
|
{
|
|
|
|
if (!dbf)
|
|
|
|
{
|
2010-09-03 01:23:38 -07:00
|
|
|
#ifdef STDOUT_DBG
|
|
|
|
dbf = stdout;
|
2011-05-20 23:23:33 -07:00
|
|
|
#else
|
2015-12-03 00:32:39 -08:00
|
|
|
dbf = fopen("EVAS-RENDER-DEBUG.log", "wb");
|
2011-05-20 23:23:33 -07:00
|
|
|
#endif
|
2009-11-15 05:46:20 -08:00
|
|
|
if (!dbf) return;
|
|
|
|
}
|
|
|
|
fputs(txt, dbf);
|
|
|
|
fflush(dbf);
|
|
|
|
}
|
2015-01-26 00:35:42 -08:00
|
|
|
#define RD(xxxx, args...) \
|
2015-10-07 18:56:35 -07:00
|
|
|
do { if (__RD_enable) { \
|
2009-11-15 05:46:20 -08:00
|
|
|
char __tmpbuf[4096]; int __tmpi; \
|
2015-09-01 04:47:40 -07:00
|
|
|
__RD_level = xxxx; \
|
2015-01-26 00:35:42 -08:00
|
|
|
if (xxxx) { \
|
|
|
|
for (__tmpi = 0; __tmpi < xxxx * 2; __tmpi++) \
|
|
|
|
__tmpbuf[__tmpi] = ' '; \
|
|
|
|
__tmpbuf[__tmpi] = 0; \
|
|
|
|
rend_dbg(__tmpbuf); \
|
|
|
|
} \
|
|
|
|
snprintf(__tmpbuf, sizeof(__tmpbuf), ##args); \
|
2009-11-15 05:46:20 -08:00
|
|
|
rend_dbg(__tmpbuf); \
|
2015-10-07 18:56:35 -07:00
|
|
|
} } while (0)
|
2015-07-21 01:48:47 -07:00
|
|
|
#define IFRD(ifcase, xxxx, args...) \
|
2015-10-07 18:56:35 -07:00
|
|
|
if (__RD_enable && (ifcase)) { \
|
2015-07-21 01:48:47 -07:00
|
|
|
char __tmpbuf[4096]; int __tmpi; \
|
2015-09-01 04:47:40 -07:00
|
|
|
__RD_level = xxxx; \
|
2015-07-21 01:48:47 -07:00
|
|
|
if (xxxx) { \
|
|
|
|
for (__tmpi = 0; __tmpi < xxxx * 2; __tmpi++) \
|
|
|
|
__tmpbuf[__tmpi] = ' '; \
|
|
|
|
__tmpbuf[__tmpi] = 0; \
|
|
|
|
rend_dbg(__tmpbuf); \
|
|
|
|
} \
|
|
|
|
snprintf(__tmpbuf, sizeof(__tmpbuf), ##args); \
|
|
|
|
rend_dbg(__tmpbuf); \
|
|
|
|
}
|
2009-11-15 05:46:20 -08:00
|
|
|
#else
|
2015-07-21 01:48:47 -07:00
|
|
|
#define RD(xxx, args...)
|
|
|
|
#define IFRD(ifcase, xxx, args...)
|
2017-03-16 19:24:10 -07:00
|
|
|
#define RDNAME(xxx) ""
|
2009-11-15 05:46:20 -08:00
|
|
|
#endif
|
|
|
|
|
2016-11-25 21:25:41 -08:00
|
|
|
#define OBJ_ARRAY_PUSH(array, obj) eina_array_push(array, obj)
|
|
|
|
#define OBJS_ARRAY_CLEAN(array) eina_array_clean(array)
|
|
|
|
#define OBJS_ARRAY_FLUSH(array) eina_array_flush(array)
|
2013-05-02 00:47:16 -07:00
|
|
|
|
2014-11-12 02:25:21 -08:00
|
|
|
/* save typing */
|
2017-04-24 15:09:25 -07:00
|
|
|
#undef ENFN
|
|
|
|
#undef ENC
|
2014-11-12 02:25:21 -08:00
|
|
|
#define ENFN evas->engine.func
|
2017-04-24 15:09:25 -07:00
|
|
|
#define ENC _evas_engine_context(evas)
|
2014-11-12 02:25:21 -08:00
|
|
|
|
2012-12-18 08:28:55 -08:00
|
|
|
typedef struct _Render_Updates Render_Updates;
|
2017-03-22 04:51:53 -07:00
|
|
|
typedef struct _Cutout_Margin Cutout_Margin;
|
|
|
|
|
2012-12-18 08:28:55 -08:00
|
|
|
struct _Render_Updates
|
|
|
|
{
|
|
|
|
void *surface;
|
|
|
|
Eina_Rectangle *area;
|
|
|
|
};
|
|
|
|
|
2017-03-22 04:51:53 -07:00
|
|
|
struct _Cutout_Margin
|
|
|
|
{
|
|
|
|
int l, r, t, b;
|
|
|
|
};
|
|
|
|
|
2017-08-25 10:55:02 -07:00
|
|
|
static void
|
|
|
|
evas_render_pipe_wakeup(void *data);
|
2012-12-18 08:28:55 -08:00
|
|
|
static Eina_Bool
|
2017-08-25 10:55:02 -07:00
|
|
|
evas_render_updates_internal(Evas *eo_e, unsigned char make_updates, unsigned char do_draw, Eina_Bool do_async);
|
2017-08-25 10:52:33 -07:00
|
|
|
static void
|
|
|
|
evas_render_mask_subrender(Evas_Public_Data *evas,
|
|
|
|
void *output,
|
|
|
|
Evas_Object_Protected_Data *mask,
|
|
|
|
Evas_Object_Protected_Data *prev_mask,
|
|
|
|
int level, Eina_Bool do_async);
|
2005-12-03 01:27:53 -08:00
|
|
|
|
2013-09-02 21:48:08 -07:00
|
|
|
static Eina_List *_rendering_evases = NULL;
|
|
|
|
|
2013-01-17 06:31:34 -08:00
|
|
|
#ifdef EVAS_RENDER_DEBUG_TIMING
|
|
|
|
static double
|
|
|
|
_time_get()
|
|
|
|
{
|
|
|
|
struct timeval tv;
|
|
|
|
|
|
|
|
gettimeofday(&tv, NULL);
|
|
|
|
|
|
|
|
return (tv.tv_sec + tv.tv_usec / 1000000.0) * 1000.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct accumulator {
|
2015-04-03 07:34:15 -07:00
|
|
|
double total, min, max, draw_start_time;
|
2013-01-17 06:31:34 -08:00
|
|
|
int samples;
|
|
|
|
const char *what;
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct accumulator async_accumulator = {
|
|
|
|
.total = 0,
|
|
|
|
.min = 1000000,
|
|
|
|
.max = 0,
|
|
|
|
.samples = 0,
|
|
|
|
.what = "async render"
|
|
|
|
};
|
|
|
|
static struct accumulator sync_accumulator = {
|
|
|
|
.total = 0,
|
|
|
|
.min = 1000000,
|
|
|
|
.max = 0,
|
|
|
|
.samples = 0,
|
|
|
|
.what = "sync render"
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
2015-04-03 07:34:15 -07:00
|
|
|
_accumulate_time(double before, Eina_Bool async)
|
2013-01-17 06:31:34 -08:00
|
|
|
{
|
2015-04-03 07:34:15 -07:00
|
|
|
static Eina_Bool async_start = EINA_TRUE;
|
|
|
|
static double cache_before;
|
|
|
|
struct accumulator *acc = &sync_accumulator;
|
|
|
|
if (async)
|
|
|
|
{
|
|
|
|
acc = &async_accumulator;
|
|
|
|
if (async_start)
|
|
|
|
{
|
|
|
|
async_start = EINA_FALSE;
|
|
|
|
cache_before = before;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
async_start = EINA_TRUE;
|
|
|
|
before = cache_before;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-17 06:31:34 -08:00
|
|
|
double diff = _time_get() - before;
|
|
|
|
|
|
|
|
acc->total += diff;
|
|
|
|
if (diff > acc->max) acc->max = diff;
|
|
|
|
if (diff < acc->min) acc->min = diff;
|
|
|
|
|
|
|
|
acc->samples++;
|
|
|
|
if (acc->samples % 100 == 0)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "*** %s: avg %fms min %fms max %fms\n",
|
|
|
|
acc->what, acc->total / 100.0, acc->min, acc->max);
|
|
|
|
acc->total = 0.0;
|
|
|
|
acc->max = 0.0;
|
|
|
|
acc->min = 1000000;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2015-07-07 05:29:31 -07:00
|
|
|
static int _render_busy = 0;
|
|
|
|
|
2016-09-07 18:26:30 -07:00
|
|
|
static inline Eina_Bool
|
2016-11-07 03:36:59 -08:00
|
|
|
_is_obj_in_framespace(Evas_Object_Protected_Data *obj, Evas_Public_Data *evas EINA_UNUSED)
|
2016-09-07 18:26:30 -07:00
|
|
|
{
|
2016-11-07 03:36:59 -08:00
|
|
|
return obj->is_frame;
|
2016-09-07 18:26:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
2016-11-07 03:36:59 -08:00
|
|
|
_evas_render_framespace_context_clip_clip(Evas_Public_Data *evas, void *ctx,
|
|
|
|
int ox, int oy)
|
2016-09-07 18:26:30 -07:00
|
|
|
{
|
|
|
|
int fx, fy, fw, fh;
|
|
|
|
|
|
|
|
fx = evas->framespace.x;
|
|
|
|
fy = evas->framespace.y;
|
|
|
|
fw = evas->viewport.w - evas->framespace.w;
|
|
|
|
fh = evas->viewport.h - evas->framespace.h;
|
|
|
|
|
2017-05-12 15:03:05 -07:00
|
|
|
ENFN->context_clip_clip(ENC, ctx, fx + ox, fy + oy, fw, fh);
|
2016-09-07 18:26:30 -07:00
|
|
|
}
|
|
|
|
|
2015-07-07 05:29:31 -07:00
|
|
|
static void
|
|
|
|
_evas_render_cleanup(void)
|
|
|
|
{
|
|
|
|
if (_render_busy != 0) return;
|
|
|
|
evas_common_rgba_pending_unloads_cleanup();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_evas_render_busy_begin(void)
|
|
|
|
{
|
|
|
|
_render_busy++;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_evas_render_busy_end(void)
|
|
|
|
{
|
|
|
|
_render_busy--;
|
|
|
|
_evas_render_cleanup();
|
|
|
|
}
|
|
|
|
|
2014-03-11 23:53:00 -07:00
|
|
|
EOLIAN void
|
2014-06-26 14:29:46 -07:00
|
|
|
_evas_canvas_damage_rectangle_add(Eo *eo_e EINA_UNUSED, Evas_Public_Data *e, int x, int y, int w, int h)
|
2002-11-08 00:02:15 -08:00
|
|
|
{
|
2012-10-08 18:58:41 -07:00
|
|
|
Eina_Rectangle *r;
|
|
|
|
|
2015-02-10 03:44:38 -08:00
|
|
|
evas_canvas_async_block(e);
|
2009-04-14 02:27:27 -07:00
|
|
|
NEW_RECT(r, x, y, w, h);
|
2002-11-08 00:02:15 -08:00
|
|
|
if (!r) return;
|
2008-10-21 09:31:05 -07:00
|
|
|
e->damages = eina_list_append(e->damages, r);
|
2012-05-16 06:21:37 -07:00
|
|
|
e->changed = EINA_TRUE;
|
2002-11-08 00:02:15 -08:00
|
|
|
}
|
|
|
|
|
2014-03-11 23:53:00 -07:00
|
|
|
EOLIAN void
|
2014-06-26 14:29:46 -07:00
|
|
|
_evas_canvas_obscured_rectangle_add(Eo *eo_e EINA_UNUSED, Evas_Public_Data *e, int x, int y, int w, int h)
|
2012-10-08 18:58:41 -07:00
|
|
|
{
|
|
|
|
Eina_Rectangle *r;
|
|
|
|
|
2015-02-10 03:44:38 -08:00
|
|
|
evas_canvas_async_block(e);
|
2009-04-14 02:27:27 -07:00
|
|
|
NEW_RECT(r, x, y, w, h);
|
2002-11-08 00:02:15 -08:00
|
|
|
if (!r) return;
|
2008-10-21 09:31:05 -07:00
|
|
|
e->obscures = eina_list_append(e->obscures, r);
|
2002-11-08 00:02:15 -08:00
|
|
|
}
|
|
|
|
|
2014-03-11 23:53:00 -07:00
|
|
|
EOLIAN void
|
2014-06-26 14:29:46 -07:00
|
|
|
_evas_canvas_obscured_clear(Eo *eo_e EINA_UNUSED, Evas_Public_Data *e)
|
2012-10-08 18:58:41 -07:00
|
|
|
{
|
|
|
|
Eina_Rectangle *r;
|
|
|
|
|
2015-02-10 03:44:38 -08:00
|
|
|
evas_canvas_async_block(e);
|
2009-04-14 02:27:27 -07:00
|
|
|
EINA_LIST_FREE(e->obscures, r)
|
2009-10-30 03:11:15 -07:00
|
|
|
{
|
|
|
|
eina_rectangle_free(r);
|
|
|
|
}
|
2002-11-08 00:02:15 -08:00
|
|
|
}
|
|
|
|
|
2012-11-20 03:52:16 -08:00
|
|
|
static Eina_Bool
|
|
|
|
_evas_clip_changes_free(const void *container EINA_UNUSED, void *data, void *fdata EINA_UNUSED)
|
|
|
|
{
|
|
|
|
eina_rectangle_free(data);
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
2019-05-06 13:12:48 -07:00
|
|
|
static inline Eina_Rectangle
|
|
|
|
_evas_render_smallest_static_clipped_geometry_get(const Evas_Object_Protected_State *state)
|
|
|
|
{
|
|
|
|
int cx, cy, cw, ch;
|
|
|
|
|
|
|
|
cx = state->geometry.x;
|
|
|
|
cy = state->geometry.y;
|
|
|
|
cw = state->geometry.w;
|
|
|
|
ch = state->geometry.h;
|
|
|
|
while (state->clipper && state->has_fixed_size)
|
|
|
|
{
|
|
|
|
/* walk up the clipper tree as long as the clippers are static */
|
|
|
|
RECTS_CLIP_TO_RECT(cx, cy, cw, ch,
|
|
|
|
state->clipper->cur->geometry.x,
|
|
|
|
state->clipper->cur->geometry.y,
|
|
|
|
state->clipper->cur->geometry.w,
|
|
|
|
state->clipper->cur->geometry.h);
|
|
|
|
if (!state->clipper) break;
|
|
|
|
state = state->clipper->cur;
|
|
|
|
}
|
|
|
|
return (Eina_Rectangle){cx, cy, cw, ch};
|
|
|
|
}
|
|
|
|
|
2009-11-10 00:50:11 -08:00
|
|
|
static Eina_Bool
|
2012-10-10 00:23:00 -07:00
|
|
|
_evas_render_had_map(Evas_Object_Protected_Data *obj)
|
2009-11-10 00:50:11 -08:00
|
|
|
{
|
2013-01-21 19:56:00 -08:00
|
|
|
return ((obj->map->prev.map) && (obj->map->prev.usemap));
|
2009-11-10 00:50:11 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
2019-05-29 12:36:53 -07:00
|
|
|
_evas_render_is_relevant(Evas_Object_Protected_Data *obj)
|
2009-11-10 00:50:11 -08:00
|
|
|
{
|
2019-05-29 12:36:53 -07:00
|
|
|
return ((evas_object_is_visible(obj) && (!obj->cur->have_clipees)) ||
|
2019-05-29 12:36:46 -07:00
|
|
|
(evas_object_was_visible(obj) && (!obj->prev->have_clipees)));
|
2009-11-10 00:50:11 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
2019-05-29 12:36:53 -07:00
|
|
|
_evas_render_can_render(Evas_Object_Protected_Data *obj)
|
2009-11-10 00:50:11 -08:00
|
|
|
{
|
2019-05-29 12:36:53 -07:00
|
|
|
return (evas_object_is_visible(obj) && (!obj->cur->have_clipees) &&
|
2015-05-12 01:37:01 -07:00
|
|
|
!obj->no_render);
|
2009-11-10 00:50:11 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2016-12-14 22:25:43 -08:00
|
|
|
_evas_render_prev_cur_clip_cache_add(Evas_Public_Data *evas, Evas_Object_Protected_Data *obj)
|
2009-11-10 00:50:11 -08:00
|
|
|
{
|
2017-05-12 15:03:05 -07:00
|
|
|
// FIXME: Iterate over each output
|
2017-08-25 10:49:53 -07:00
|
|
|
ENFN->output_redraws_rect_add(ENC,
|
2016-12-14 22:25:43 -08:00
|
|
|
obj->prev->cache.clip.x + evas->framespace.x,
|
|
|
|
obj->prev->cache.clip.y + evas->framespace.y,
|
|
|
|
obj->prev->cache.clip.w,
|
|
|
|
obj->prev->cache.clip.h);
|
2017-08-25 10:49:53 -07:00
|
|
|
ENFN->output_redraws_rect_add(ENC,
|
2016-12-14 22:25:43 -08:00
|
|
|
obj->cur->cache.clip.x + evas->framespace.x,
|
|
|
|
obj->cur->cache.clip.y + evas->framespace.y,
|
|
|
|
obj->cur->cache.clip.w,
|
|
|
|
obj->cur->cache.clip.h);
|
2009-11-10 00:50:11 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-10-10 00:23:00 -07:00
|
|
|
_evas_render_cur_clip_cache_del(Evas_Public_Data *e, Evas_Object_Protected_Data *obj)
|
2009-11-10 00:50:11 -08:00
|
|
|
{
|
2011-11-10 21:56:40 -08:00
|
|
|
Evas_Coord x, y, w, h;
|
2012-05-16 06:21:37 -07:00
|
|
|
|
2013-03-12 05:58:19 -07:00
|
|
|
x = obj->cur->cache.clip.x;
|
|
|
|
y = obj->cur->cache.clip.y;
|
|
|
|
w = obj->cur->cache.clip.w;
|
|
|
|
h = obj->cur->cache.clip.h;
|
|
|
|
if (obj->cur->clipper)
|
2011-11-10 21:56:40 -08:00
|
|
|
{
|
|
|
|
RECTS_CLIP_TO_RECT(x, y, w, h,
|
2013-03-12 05:58:19 -07:00
|
|
|
obj->cur->clipper->cur->cache.clip.x,
|
|
|
|
obj->cur->clipper->cur->cache.clip.y,
|
|
|
|
obj->cur->clipper->cur->cache.clip.w,
|
|
|
|
obj->cur->clipper->cur->cache.clip.h);
|
2011-11-10 21:56:40 -08:00
|
|
|
}
|
2016-11-25 17:47:34 -08:00
|
|
|
evas_render_update_del(e, x + e->framespace.x, y + e->framespace.y, w, h);
|
2009-11-10 00:50:11 -08:00
|
|
|
}
|
|
|
|
|
2014-11-12 17:47:29 -08:00
|
|
|
/* sets the redraw flag for all the proxies depending on this obj as a source */
|
2013-11-24 17:09:34 -08:00
|
|
|
static void
|
|
|
|
_evas_proxy_redraw_set(Evas_Public_Data *e, Evas_Object_Protected_Data *obj,
|
|
|
|
Eina_Bool render)
|
|
|
|
{
|
|
|
|
Evas_Object *eo_proxy;
|
|
|
|
Evas_Object_Protected_Data *proxy;
|
|
|
|
Eina_List *l;
|
|
|
|
|
|
|
|
EINA_LIST_FOREACH(obj->proxy->proxies, l, eo_proxy)
|
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
proxy = efl_data_scope_get(eo_proxy, EFL_CANVAS_OBJECT_CLASS);
|
2013-11-24 17:09:34 -08:00
|
|
|
|
|
|
|
/* Flag need redraw on proxy too */
|
|
|
|
EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, proxy->proxy,
|
|
|
|
Evas_Object_Proxy_Data, proxy_write)
|
|
|
|
proxy_write->redraw = EINA_TRUE;
|
|
|
|
EINA_COW_WRITE_END(evas_object_proxy_cow, proxy->proxy, proxy_write);
|
|
|
|
|
|
|
|
if (render)
|
|
|
|
{
|
2020-03-12 04:39:12 -07:00
|
|
|
/* Not good... but make it sure if the proxies have missed at update
|
|
|
|
if its sources are remained changed as pending objects in the prev frame. */
|
|
|
|
evas_object_change(eo_proxy, proxy);
|
2013-11-24 17:09:34 -08:00
|
|
|
proxy->func->render_pre(eo_proxy, proxy, proxy->private_data);
|
|
|
|
_evas_render_prev_cur_clip_cache_add(e, proxy);
|
|
|
|
}
|
|
|
|
|
|
|
|
//Update the proxies recursively.
|
|
|
|
_evas_proxy_redraw_set(e, proxy, render);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-12 17:47:29 -08:00
|
|
|
/* sets the mask redraw flag for all the objects clipped by this mask */
|
|
|
|
static void
|
|
|
|
_evas_mask_redraw_set(Evas_Public_Data *e EINA_UNUSED,
|
|
|
|
Evas_Object_Protected_Data *obj)
|
|
|
|
{
|
|
|
|
Evas_Object_Protected_Data *clippee;
|
|
|
|
Eina_List *l;
|
|
|
|
|
2015-01-26 22:02:27 -08:00
|
|
|
if (!(obj->mask->redraw))
|
2014-11-12 17:47:29 -08:00
|
|
|
{
|
|
|
|
EINA_COW_WRITE_BEGIN(evas_object_mask_cow, obj->mask,
|
|
|
|
Evas_Object_Mask_Data, mask)
|
|
|
|
mask->redraw = EINA_TRUE;
|
|
|
|
EINA_COW_WRITE_END(evas_object_mask_cow, obj->mask, mask);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!obj->cur->cache.clip.dirty)
|
|
|
|
{
|
|
|
|
EINA_COW_STATE_WRITE_BEGIN(obj, state_write, cur)
|
|
|
|
state_write->cache.clip.dirty = EINA_TRUE;
|
|
|
|
EINA_COW_STATE_WRITE_END(obj, state_write, cur);
|
|
|
|
}
|
|
|
|
|
|
|
|
EINA_LIST_FOREACH(obj->clip.clipees, l, clippee)
|
|
|
|
{
|
|
|
|
evas_object_clip_recalc(clippee);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eina_Bool
|
|
|
|
_evas_render_object_changed_get(Evas_Object_Protected_Data *obj)
|
|
|
|
{
|
|
|
|
if (obj->smart.smart)
|
2018-10-24 16:29:48 -07:00
|
|
|
return evas_object_smart_changed_get(obj);
|
2014-11-12 17:47:29 -08:00
|
|
|
else
|
|
|
|
return obj->changed;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eina_Bool
|
|
|
|
_evas_render_object_is_mask(Evas_Object_Protected_Data *obj)
|
|
|
|
{
|
|
|
|
if (!obj) return EINA_FALSE;
|
2015-01-26 00:35:42 -08:00
|
|
|
if (obj->mask->is_mask && obj->clip.clipees)
|
|
|
|
return EINA_TRUE;
|
|
|
|
return EINA_FALSE;
|
2014-11-12 17:47:29 -08:00
|
|
|
}
|
|
|
|
|
2009-11-06 21:01:43 -08:00
|
|
|
static void
|
2012-10-10 00:23:00 -07:00
|
|
|
_evas_render_phase1_direct(Evas_Public_Data *e,
|
2016-11-25 21:25:41 -08:00
|
|
|
Eina_Inarray *active_objects,
|
2012-10-08 18:58:41 -07:00
|
|
|
Eina_Array *restack_objects EINA_UNUSED,
|
|
|
|
Eina_Array *delete_objects EINA_UNUSED,
|
2009-11-10 00:50:11 -08:00
|
|
|
Eina_Array *render_objects)
|
2009-11-06 21:01:43 -08:00
|
|
|
{
|
|
|
|
unsigned int i;
|
2013-11-24 17:09:34 -08:00
|
|
|
Evas_Object *eo_obj;
|
2009-11-06 21:01:43 -08:00
|
|
|
|
2015-01-26 00:35:42 -08:00
|
|
|
RD(0, " [--- PHASE 1 DIRECT\n");
|
2016-11-25 21:25:41 -08:00
|
|
|
for (i = 0; i < active_objects->len; i++)
|
2011-05-19 06:01:44 -07:00
|
|
|
{
|
2016-11-30 00:36:42 -08:00
|
|
|
Evas_Active_Entry *ent = eina_inarray_nth(active_objects, i);
|
|
|
|
Evas_Object_Protected_Data *obj = ent->obj;
|
2013-04-06 22:00:10 -07:00
|
|
|
|
2016-11-30 00:36:42 -08:00
|
|
|
EINA_PREFETCH(&(obj->cur->clipper));
|
2013-10-31 01:01:41 -07:00
|
|
|
if (obj->changed) evas_object_clip_recalc(obj);
|
|
|
|
|
2020-03-25 03:14:02 -07:00
|
|
|
if (obj->proxy->proxies)
|
2014-11-12 17:47:29 -08:00
|
|
|
{
|
|
|
|
/* is proxy source */
|
|
|
|
if (_evas_render_object_changed_get(obj))
|
|
|
|
_evas_proxy_redraw_set(e, obj, EINA_FALSE);
|
|
|
|
}
|
|
|
|
if (_evas_render_object_is_mask(obj))
|
|
|
|
{
|
|
|
|
/* is image clipper */
|
|
|
|
if (_evas_render_object_changed_get(obj))
|
2015-02-25 22:36:09 -08:00
|
|
|
_evas_mask_redraw_set(e, obj);
|
2014-11-12 17:47:29 -08:00
|
|
|
}
|
2011-05-19 06:01:44 -07:00
|
|
|
}
|
2009-11-09 07:18:37 -08:00
|
|
|
for (i = 0; i < render_objects->count; i++)
|
2009-11-06 21:01:43 -08:00
|
|
|
{
|
2013-11-24 17:09:34 -08:00
|
|
|
Evas_Object_Protected_Data *obj =
|
2016-11-26 19:02:12 -08:00
|
|
|
eina_array_data_get(render_objects, i);
|
2012-10-08 18:58:41 -07:00
|
|
|
eo_obj = obj->object;
|
2013-11-24 17:09:34 -08:00
|
|
|
|
2017-01-11 04:18:59 -08:00
|
|
|
RD(0, " OBJ %s changed %i\n", RDNAME(obj), obj->changed);
|
2013-11-24 17:09:34 -08:00
|
|
|
|
2011-05-20 23:23:33 -07:00
|
|
|
if (obj->changed)
|
2009-11-06 21:01:43 -08:00
|
|
|
{
|
2013-04-06 22:00:10 -07:00
|
|
|
evas_object_clip_recalc(obj);
|
2013-12-07 10:14:14 -08:00
|
|
|
obj->func->render_pre(eo_obj, obj, obj->private_data);
|
2014-11-12 17:47:29 -08:00
|
|
|
|
|
|
|
if (obj->proxy->redraw || obj->mask->redraw)
|
2013-12-07 10:14:14 -08:00
|
|
|
_evas_render_prev_cur_clip_cache_add(e, obj);
|
2014-11-12 17:47:29 -08:00
|
|
|
|
2018-10-24 16:29:48 -07:00
|
|
|
if (!obj->smart.smart || evas_object_smart_changed_get(obj))
|
2011-02-06 15:51:48 -08:00
|
|
|
{
|
2014-11-12 17:47:29 -08:00
|
|
|
/* proxy sources */
|
2020-03-25 03:14:02 -07:00
|
|
|
if (obj->proxy->proxies)
|
2011-05-19 06:01:44 -07:00
|
|
|
{
|
2013-11-17 23:10:55 -08:00
|
|
|
EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, obj->proxy,
|
|
|
|
Evas_Object_Proxy_Data, proxy_write)
|
|
|
|
proxy_write->redraw = EINA_TRUE;
|
|
|
|
EINA_COW_WRITE_END(evas_object_proxy_cow, obj->proxy,
|
|
|
|
proxy_write);
|
2013-11-24 17:09:34 -08:00
|
|
|
_evas_proxy_redraw_set(e, obj, EINA_TRUE);
|
2011-05-19 06:01:44 -07:00
|
|
|
}
|
2014-11-12 17:47:29 -08:00
|
|
|
|
|
|
|
/* clipper objects (image masks) */
|
|
|
|
if (_evas_render_object_is_mask(obj))
|
|
|
|
_evas_mask_redraw_set(e, obj);
|
2011-05-19 06:01:44 -07:00
|
|
|
}
|
2012-05-30 00:32:27 -07:00
|
|
|
|
2019-02-20 12:32:41 -08:00
|
|
|
_evas_object_gfx_mapping_update(obj);
|
2017-04-25 23:11:51 -07:00
|
|
|
|
2018-06-06 22:50:41 -07:00
|
|
|
Eina_Bool has_map = _evas_render_has_map(obj);
|
|
|
|
|
2015-01-26 00:35:42 -08:00
|
|
|
RD(0, " pre-render-done smart:%p|%p [%p, %i] | [%p, %i] has_map:%i had_map:%i\n",
|
2012-05-30 00:32:27 -07:00
|
|
|
obj->smart.smart,
|
2017-02-20 01:07:00 -08:00
|
|
|
obj->is_smart ? evas_object_smart_members_get_direct(eo_obj) : NULL,
|
2013-01-21 19:56:00 -08:00
|
|
|
obj->map->cur.map, obj->map->cur.usemap,
|
2013-08-05 23:45:07 -07:00
|
|
|
obj->map->prev.map, obj->map->prev.usemap,
|
2018-06-06 22:50:41 -07:00
|
|
|
has_map, _evas_render_had_map(obj));
|
|
|
|
|
2012-10-08 18:58:41 -07:00
|
|
|
if ((obj->is_smart) &&
|
2018-06-06 22:50:41 -07:00
|
|
|
((has_map && !_evas_render_can_map(obj)) ||
|
|
|
|
obj->changed_src_visible))
|
2011-05-19 06:01:44 -07:00
|
|
|
{
|
2015-01-26 00:35:42 -08:00
|
|
|
RD(0, " has map + smart\n");
|
2012-10-10 00:23:00 -07:00
|
|
|
_evas_render_prev_cur_clip_cache_add(e, obj);
|
2009-11-15 05:46:20 -08:00
|
|
|
}
|
evas map: check render condition more elaborately.
Summary:
Ok, this was started from a bug that canvas getting not be updated.
If map is just disabled, at least one frame in the map region should be redrawn
So I added a condition 'map changed' in the render even though map is off
status. Now, I got a performance regression issue because it makes dirty
region is always true for the map object.
That is a corner case acutally, that object is not rendered but map still
have changed status.
I replaced the condition only if object is changed + map is changed.
At least, my test case works better with this patch.
@fix T6975
Reviewers: #committers, ManMower, devilhorns
Reviewed By: #committers, ManMower
Subscribers: ApB, ManMower, cedric, #committers, zmike
Tags: #efl
Maniphest Tasks: T6975
Differential Revision: https://phab.enlightenment.org/D6429
2018-06-28 17:58:41 -07:00
|
|
|
/* This is the only case that map was just turned off,
|
|
|
|
Need to redraw the previous obj region as well. */
|
|
|
|
else if (!has_map && obj->changed_map &&
|
|
|
|
_evas_render_object_changed_get(obj))
|
|
|
|
{
|
|
|
|
_evas_render_prev_cur_clip_cache_add(e, obj);
|
|
|
|
obj->changed_map = EINA_FALSE;
|
|
|
|
}
|
2009-11-06 21:01:43 -08:00
|
|
|
}
|
2011-05-20 23:23:33 -07:00
|
|
|
else
|
|
|
|
{
|
2012-10-08 18:58:41 -07:00
|
|
|
if (obj->is_smart)
|
2009-11-06 21:01:43 -08:00
|
|
|
{
|
|
|
|
}
|
2019-05-29 12:36:53 -07:00
|
|
|
else if (evas_object_is_visible(obj) &&
|
2013-09-24 03:32:24 -07:00
|
|
|
((obj->rect_del) ||
|
2019-05-29 12:37:07 -07:00
|
|
|
(evas_object_is_opaque(obj))) &&
|
2014-02-12 22:40:29 -08:00
|
|
|
(!evas_object_is_source_invisible(eo_obj, obj)))
|
2009-11-15 05:46:20 -08:00
|
|
|
{
|
2015-01-26 00:35:42 -08:00
|
|
|
RD(0, " rect del\n");
|
2012-10-10 00:23:00 -07:00
|
|
|
_evas_render_cur_clip_cache_del(e, obj);
|
2009-11-15 05:46:20 -08:00
|
|
|
}
|
2011-05-20 23:23:33 -07:00
|
|
|
}
|
2009-11-06 21:01:43 -08:00
|
|
|
}
|
2015-01-26 00:35:42 -08:00
|
|
|
RD(0, " ---]\n");
|
2009-10-30 03:11:15 -07:00
|
|
|
}
|
|
|
|
|
2016-11-18 01:56:59 -08:00
|
|
|
static void
|
2016-12-14 22:25:43 -08:00
|
|
|
_evas_render_object_map_change_update(Evas_Public_Data *evas,
|
2016-11-18 01:56:59 -08:00
|
|
|
Evas_Object_Protected_Data *obj,
|
|
|
|
Eina_Bool map, Eina_Bool hmap,
|
|
|
|
int *redraw_all)
|
|
|
|
{
|
2017-05-12 15:03:05 -07:00
|
|
|
// FIXME: handle multiple output
|
2016-12-14 22:25:43 -08:00
|
|
|
Evas_Coord x = 0, y = 0, w = 0, h = 0;
|
|
|
|
const int fx = evas->framespace.x;
|
|
|
|
const int fy = evas->framespace.y;
|
|
|
|
|
2016-11-18 01:56:59 -08:00
|
|
|
if (map == hmap) return;
|
|
|
|
|
2016-12-14 22:25:43 -08:00
|
|
|
if (!obj->map)
|
2016-11-18 01:56:59 -08:00
|
|
|
{
|
2016-12-14 22:25:43 -08:00
|
|
|
*redraw_all = 1;
|
|
|
|
return;
|
|
|
|
}
|
2016-11-18 01:56:59 -08:00
|
|
|
|
2016-12-14 22:25:43 -08:00
|
|
|
if (map)
|
|
|
|
{
|
|
|
|
x = obj->prev->cache.clip.x;
|
|
|
|
y = obj->prev->cache.clip.y;
|
|
|
|
w = obj->prev->cache.clip.w;
|
|
|
|
h = obj->prev->cache.clip.h;
|
|
|
|
if (obj->prev->clipper)
|
2016-11-18 01:56:59 -08:00
|
|
|
{
|
2016-12-14 22:25:43 -08:00
|
|
|
RECTS_CLIP_TO_RECT(x, y, w, h,
|
|
|
|
obj->prev->clipper->prev->cache.clip.x,
|
|
|
|
obj->prev->clipper->prev->cache.clip.y,
|
|
|
|
obj->prev->clipper->prev->cache.clip.w,
|
|
|
|
obj->prev->clipper->prev->cache.clip.h);
|
2016-11-18 01:56:59 -08:00
|
|
|
}
|
2017-08-25 10:49:53 -07:00
|
|
|
ENFN->output_redraws_rect_add(ENC, x + fx, y + fy, w, h);
|
2016-12-14 22:25:43 -08:00
|
|
|
x = obj->map->cur.map->normal_geometry.x;
|
|
|
|
y = obj->map->cur.map->normal_geometry.y;
|
|
|
|
w = obj->map->cur.map->normal_geometry.w;
|
|
|
|
h = obj->map->cur.map->normal_geometry.h;
|
|
|
|
if (obj->cur->clipper)
|
|
|
|
{
|
|
|
|
RECTS_CLIP_TO_RECT(x, y, w, h,
|
|
|
|
obj->cur->clipper->cur->cache.clip.x,
|
|
|
|
obj->cur->clipper->cur->cache.clip.y,
|
|
|
|
obj->cur->clipper->cur->cache.clip.w,
|
|
|
|
obj->cur->clipper->cur->cache.clip.h);
|
|
|
|
}
|
2017-08-25 10:49:53 -07:00
|
|
|
ENFN->output_redraws_rect_add(ENC, x + fx, y + fy, w, h);
|
2016-12-14 22:25:43 -08:00
|
|
|
}
|
|
|
|
else if (hmap)
|
|
|
|
{
|
|
|
|
x = obj->map->prev.map->normal_geometry.x;
|
|
|
|
y = obj->map->prev.map->normal_geometry.y;
|
|
|
|
w = obj->map->prev.map->normal_geometry.w;
|
|
|
|
h = obj->map->prev.map->normal_geometry.h;
|
|
|
|
if (obj->prev->clipper)
|
|
|
|
{
|
|
|
|
RECTS_CLIP_TO_RECT(x, y, w, h,
|
|
|
|
obj->prev->clipper->prev->cache.clip.x,
|
|
|
|
obj->prev->clipper->prev->cache.clip.y,
|
|
|
|
obj->prev->clipper->prev->cache.clip.w,
|
|
|
|
obj->prev->clipper->prev->cache.clip.h);
|
|
|
|
}
|
2017-08-25 10:49:53 -07:00
|
|
|
ENFN->output_redraws_rect_add(ENC, x + fx, y + fy, w, h);
|
2016-12-14 22:25:43 -08:00
|
|
|
x = obj->cur->cache.clip.x;
|
|
|
|
y = obj->cur->cache.clip.y;
|
|
|
|
w = obj->cur->cache.clip.w;
|
|
|
|
h = obj->cur->cache.clip.h;
|
|
|
|
if (obj->cur->clipper)
|
|
|
|
{
|
|
|
|
RECTS_CLIP_TO_RECT(x, y, w, h,
|
|
|
|
obj->cur->clipper->cur->cache.clip.x,
|
|
|
|
obj->cur->clipper->cur->cache.clip.y,
|
|
|
|
obj->cur->clipper->cur->cache.clip.w,
|
|
|
|
obj->cur->clipper->cur->cache.clip.h);
|
|
|
|
}
|
2017-08-25 10:49:53 -07:00
|
|
|
ENFN->output_redraws_rect_add(ENC, x + fx, y + fy, w, h);
|
2016-11-18 01:56:59 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-25 17:47:34 -08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// object render update phase 1 code -> figure out updates and built object
|
|
|
|
// render/active/delete etc. lists/arrays.
|
|
|
|
//
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
2016-11-25 21:25:41 -08:00
|
|
|
Eina_Inarray *active_objects;
|
|
|
|
Eina_Array *render_objects;
|
|
|
|
Eina_Array *snapshot_objects;
|
2016-11-25 17:47:34 -08:00
|
|
|
|
|
|
|
Eina_Inarray *update_del;
|
|
|
|
} Render_Cache;
|
|
|
|
|
|
|
|
void
|
2016-12-14 22:25:43 -08:00
|
|
|
evas_render_update_del(Evas_Public_Data *evas, int x, int y, int w, int h)
|
2016-11-25 17:47:34 -08:00
|
|
|
{
|
2017-05-12 15:03:05 -07:00
|
|
|
// FIXME: handle multiple output
|
2016-12-14 22:25:43 -08:00
|
|
|
if (EINA_LIKELY((evas->update_del_redirect_array == NULL)))
|
2016-11-25 17:47:34 -08:00
|
|
|
{
|
2017-08-25 10:49:53 -07:00
|
|
|
ENFN->output_redraws_rect_del(ENC, x, y, w, h);
|
2016-11-25 17:47:34 -08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Eina_Rectangle r;
|
|
|
|
|
|
|
|
r.x = x; r.y = y; r.w = w; r.h = h;
|
2016-12-14 22:25:43 -08:00
|
|
|
eina_inarray_push(evas->update_del_redirect_array, &r);
|
2016-11-25 17:47:34 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
evas_render_object_render_cache_free(Evas_Object *eo_obj EINA_UNUSED,
|
|
|
|
void *data)
|
|
|
|
{
|
|
|
|
Render_Cache *rc;
|
|
|
|
|
|
|
|
if (!data) return;
|
|
|
|
rc = data;
|
2016-11-25 21:25:41 -08:00
|
|
|
eina_inarray_free(rc->active_objects);
|
2016-11-25 17:47:34 -08:00
|
|
|
eina_array_free(rc->render_objects);
|
|
|
|
eina_array_free(rc->snapshot_objects);
|
2016-12-02 19:44:57 -08:00
|
|
|
eina_inarray_free(rc->update_del);
|
2016-11-25 17:47:34 -08:00
|
|
|
free(rc);
|
|
|
|
}
|
|
|
|
|
2018-05-29 00:25:54 -07:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
Evas_Public_Data *e;
|
|
|
|
Eina_Inarray *active_objects;
|
|
|
|
Eina_Array *render_objects;
|
|
|
|
Eina_Array *snapshot_objects;
|
|
|
|
Eina_Array *restack_objects;
|
|
|
|
Eina_Array *delete_objects;
|
|
|
|
int redraw_all;
|
|
|
|
} Phase1_Context;
|
|
|
|
|
|
|
|
#define RENDCACHE 1
|
|
|
|
|
|
|
|
#ifdef RENDCACHE
|
2016-11-25 17:47:34 -08:00
|
|
|
static Render_Cache *
|
|
|
|
_evas_render_phase1_object_render_cache_new(void)
|
|
|
|
{
|
|
|
|
Render_Cache *rc;
|
|
|
|
|
|
|
|
rc = malloc(sizeof(Render_Cache));
|
2016-11-25 21:25:41 -08:00
|
|
|
rc->active_objects = eina_inarray_new(sizeof(Evas_Active_Entry), 32);
|
2016-11-25 17:47:34 -08:00
|
|
|
rc->render_objects = eina_array_new(32);
|
|
|
|
rc->snapshot_objects = eina_array_new(32);
|
|
|
|
rc->update_del = eina_inarray_new(sizeof(Eina_Rectangle), 16);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_evas_render_phase1_object_ctx_render_cache_fill(Phase1_Context *ctx,
|
|
|
|
Render_Cache *rc)
|
|
|
|
{
|
|
|
|
ctx->active_objects = rc->active_objects;
|
|
|
|
ctx->render_objects = rc->render_objects;
|
|
|
|
ctx->snapshot_objects = rc->snapshot_objects;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_evas_render_phase1_object_ctx_render_cache_append(Phase1_Context *ctx,
|
|
|
|
Render_Cache *rc)
|
|
|
|
{
|
|
|
|
void *obj;
|
|
|
|
unsigned int i, c;
|
|
|
|
Eina_Rectangle *r;
|
2016-11-25 21:25:41 -08:00
|
|
|
Evas_Active_Entry *ent;
|
2016-11-25 17:47:34 -08:00
|
|
|
|
|
|
|
#define ARR_APPEND(x) \
|
|
|
|
if (rc->x != ctx->x) { \
|
|
|
|
do { \
|
|
|
|
c = eina_array_count_get(rc->x); \
|
|
|
|
for (i = 0; i < c; i++) { \
|
|
|
|
obj = eina_array_data_get(rc->x, i); \
|
|
|
|
eina_array_push(ctx->x, obj); \
|
|
|
|
} \
|
|
|
|
} while (0); \
|
|
|
|
}
|
|
|
|
ARR_APPEND(render_objects);
|
|
|
|
ARR_APPEND(snapshot_objects);
|
|
|
|
|
2016-11-25 21:25:41 -08:00
|
|
|
c = eina_inarray_count(rc->active_objects);
|
|
|
|
for (i = 0; i < c; i++)
|
|
|
|
{
|
|
|
|
ent = eina_inarray_nth(rc->active_objects, i);
|
|
|
|
eina_inarray_push(ctx->active_objects, ent);
|
|
|
|
}
|
|
|
|
|
2016-11-25 17:47:34 -08:00
|
|
|
c = eina_inarray_count(rc->update_del);
|
|
|
|
for (i = 0; i < c; i++)
|
|
|
|
{
|
|
|
|
r = eina_inarray_nth(rc->update_del, i);
|
|
|
|
evas_render_update_del(ctx->e, r->x, r->y, r->w, r->h);
|
|
|
|
}
|
|
|
|
}
|
2018-05-29 00:25:54 -07:00
|
|
|
#endif
|
2016-11-25 17:47:34 -08:00
|
|
|
|
2009-06-17 03:01:52 -07:00
|
|
|
static Eina_Bool
|
2016-11-21 18:09:18 -08:00
|
|
|
_evas_render_phase1_object_process(Phase1_Context *p1ctx,
|
2016-11-25 18:10:18 -08:00
|
|
|
Evas_Object_Protected_Data *obj,
|
2016-11-22 04:07:29 -08:00
|
|
|
Eina_Bool restack,
|
|
|
|
Eina_Bool mapped_parent,
|
|
|
|
Eina_Bool src_changed,
|
|
|
|
int level);
|
|
|
|
|
|
|
|
static void
|
|
|
|
_evas_render_phase1_object_restack_handle(Phase1_Context *p1ctx,
|
|
|
|
Evas_Object_Protected_Data *obj,
|
|
|
|
Eina_Bool obj_changed)
|
|
|
|
{
|
|
|
|
if (!obj_changed)
|
|
|
|
{
|
|
|
|
OBJ_ARRAY_PUSH(&(p1ctx->e->pending_objects), obj);
|
|
|
|
obj->changed = EINA_TRUE;
|
2018-10-29 13:50:45 -07:00
|
|
|
obj->in_pending_objects = EINA_TRUE;
|
2016-11-22 04:07:29 -08:00
|
|
|
}
|
|
|
|
obj->restack = EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_evas_render_phase1_object_map_clipper_fix(Evas_Object *eo_obj,
|
|
|
|
Evas_Object_Protected_Data *obj)
|
|
|
|
{
|
|
|
|
evas_object_change(obj->cur->clipper->object, obj->cur->clipper);
|
|
|
|
evas_object_clip_dirty(obj->cur->clipper->object, obj->cur->clipper);
|
|
|
|
evas_object_clip_recalc(obj->cur->clipper);
|
|
|
|
evas_object_update_bounding_box(eo_obj, obj, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_evas_render_phase1_object_mapped(Phase1_Context *p1ctx,
|
|
|
|
Evas_Object_Protected_Data *obj,
|
|
|
|
Eina_Bool src_changed,
|
|
|
|
Eina_Bool hmap,
|
|
|
|
Eina_Bool is_active,
|
|
|
|
Eina_Bool obj_changed,
|
|
|
|
int level)
|
|
|
|
{
|
|
|
|
Evas_Object_Protected_Data *obj2;
|
2016-11-25 18:10:18 -08:00
|
|
|
Evas_Object *eo_obj = obj->object;
|
2016-11-22 04:07:29 -08:00
|
|
|
|
|
|
|
RD(level, " obj mapped\n");
|
evas_render: fix objects change occured withoout real rendering.
Summary:
: condition of problem
- rectangle object of RECT part(BASE part of below edje)
- mapped
- has clipper and clipper is ed's base clipper.
1. _evas_render_phase1_object_process is called of rect object
if rect is mapped, not changed, it call _evas_render_phase1_object_mapped.
2. _evas_render_phase1_object_mapped
when _evas_render_phase1_object_mapped is called,
condition is
src_changed=0 , is_active=0 , obj_changed=0
hmap=0 => because map of this object is only enabled once and not changed.
in this case, rect object's clipper always changed and it cause useless randering
so only call _evas_render_phase1_object_map_clipper_fix when obj is changed.
first time of map set, evas object always be changed, so it maybe ok we call clipper_fix only obj is chaned.
below is sample of edj.
group { name: "elm/notify/center/default";
parts {
part { name: "anim_start";
scale: 1;
type: SPACER;
description {
..
perspective {
zplane: -100;
focal: 1000;
}
}
}
part { name: "anim_stop";
scale: 1;
type: SPACER;
description {
..
perspective {
zplane: 0;
focal: 1000;
}
}
}
part { name: "base";
scale: 1;
type: RECT;
description { state: "default" 0.0;
..
map {
on: 1;
perspective_on: 1;
perspective: "anim_stop";
}
}
}
Reviewers: raster, Hermet
Reviewed By: Hermet
Subscribers: cedric, #reviewers, #committers
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D7219
2018-11-04 21:20:42 -08:00
|
|
|
if (!obj_changed) return;
|
|
|
|
|
2016-11-22 04:07:29 -08:00
|
|
|
if (!hmap && obj->cur->clipper)
|
|
|
|
// Fix some bad clipping issues before an evas map animation starts
|
|
|
|
_evas_render_phase1_object_map_clipper_fix(eo_obj, obj);
|
|
|
|
|
2016-12-14 22:25:43 -08:00
|
|
|
_evas_render_object_map_change_update(p1ctx->e, obj, EINA_TRUE, hmap, &(p1ctx->redraw_all));
|
2016-11-22 04:07:29 -08:00
|
|
|
if (!((is_active) &&
|
|
|
|
(!obj->clip.clipees) &&
|
2019-05-29 12:36:53 -07:00
|
|
|
((evas_object_is_visible(obj) &&
|
2016-11-22 04:07:29 -08:00
|
|
|
(!obj->cur->have_clipees)) ||
|
2019-05-29 12:36:46 -07:00
|
|
|
(evas_object_was_visible(obj) &&
|
2016-11-22 04:07:29 -08:00
|
|
|
(!obj->prev->have_clipees)))))
|
|
|
|
return;
|
|
|
|
OBJ_ARRAY_PUSH(p1ctx->render_objects, obj);
|
|
|
|
_evas_render_prev_cur_clip_cache_add(p1ctx->e, obj);
|
|
|
|
obj->render_pre = EINA_TRUE;
|
|
|
|
if (!obj->is_smart) return;
|
2016-11-25 17:47:34 -08:00
|
|
|
if (obj_changed) evas_object_smart_render_cache_clear(eo_obj);
|
2016-11-22 04:07:29 -08:00
|
|
|
EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(eo_obj), obj2)
|
|
|
|
{
|
2016-11-25 18:10:18 -08:00
|
|
|
_evas_render_phase1_object_process(p1ctx, obj2, obj->restack,
|
2016-11-22 04:07:29 -08:00
|
|
|
EINA_TRUE, src_changed, level + 1);
|
|
|
|
}
|
2019-07-08 20:01:22 -07:00
|
|
|
|
|
|
|
/* Restacked mapped object should be used as a redraw rect.
|
|
|
|
The "phase 2. force updates for restack" will use restack_objects. */
|
|
|
|
if (EINA_UNLIKELY(obj->restack))
|
|
|
|
OBJ_ARRAY_PUSH(p1ctx->restack_objects, obj);
|
2016-11-22 04:07:29 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_evas_render_phase1_object_mapped_had_restack(Phase1_Context *p1ctx,
|
|
|
|
Evas_Object_Protected_Data *obj,
|
|
|
|
Eina_Bool map,
|
2016-12-16 00:04:05 -08:00
|
|
|
Eina_Bool obj_changed,
|
|
|
|
int level)
|
2016-11-22 04:07:29 -08:00
|
|
|
{
|
2016-11-25 18:10:18 -08:00
|
|
|
Evas_Object *eo_obj = obj->object;
|
2016-12-16 00:04:05 -08:00
|
|
|
(void) level;
|
2016-11-25 18:10:18 -08:00
|
|
|
|
2016-11-22 04:07:29 -08:00
|
|
|
RD(level, " had map - restack objs\n");
|
|
|
|
_evas_render_prev_cur_clip_cache_add(p1ctx->e, obj);
|
|
|
|
if (obj_changed)
|
|
|
|
{
|
|
|
|
if (!map)
|
|
|
|
{
|
|
|
|
if ((obj->map->cur.map) && (obj->map->cur.usemap))
|
|
|
|
map = EINA_TRUE;
|
|
|
|
}
|
2016-12-14 22:25:43 -08:00
|
|
|
_evas_render_object_map_change_update(p1ctx->e, obj, map, EINA_TRUE, &(p1ctx->redraw_all));
|
2016-11-22 04:07:29 -08:00
|
|
|
}
|
|
|
|
if (!(!map && obj->cur->clipper)) return;
|
|
|
|
// Fix some bad clipping issues after an evas_map animation finishes
|
|
|
|
evas_object_change(obj->cur->clipper->object, obj->cur->clipper);
|
|
|
|
evas_object_clip_dirty(obj->cur->clipper->object, obj->cur->clipper);
|
|
|
|
evas_object_clip_recalc(obj->cur->clipper);
|
|
|
|
evas_object_update_bounding_box(eo_obj, obj, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_evas_render_phase1_object_changed_smart(Phase1_Context *p1ctx,
|
|
|
|
Evas_Object_Protected_Data *obj,
|
|
|
|
Eina_Bool mapped_parent,
|
2016-11-25 17:47:34 -08:00
|
|
|
Eina_Bool obj_changed,
|
2016-11-22 04:07:29 -08:00
|
|
|
Eina_Bool src_changed,
|
|
|
|
Eina_Bool is_active,
|
|
|
|
int level)
|
|
|
|
{
|
|
|
|
Evas_Object_Protected_Data *obj2;
|
2016-11-25 18:10:18 -08:00
|
|
|
Evas_Object *eo_obj = obj->object;
|
2016-11-22 04:07:29 -08:00
|
|
|
|
|
|
|
RD(level, " changed + smart - render ok\n");
|
|
|
|
OBJ_ARRAY_PUSH(p1ctx->render_objects, obj);
|
|
|
|
|
|
|
|
if (!is_active && obj->proxy->proxies) src_changed = EINA_TRUE;
|
|
|
|
|
|
|
|
obj->render_pre = EINA_TRUE;
|
2016-11-25 17:47:34 -08:00
|
|
|
if (obj_changed)
|
2016-11-22 04:07:29 -08:00
|
|
|
{
|
2016-11-25 17:47:34 -08:00
|
|
|
evas_object_smart_render_cache_clear(eo_obj);
|
|
|
|
EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(eo_obj), obj2)
|
|
|
|
{
|
2016-11-25 18:10:18 -08:00
|
|
|
_evas_render_phase1_object_process(p1ctx, obj2, obj->restack,
|
2016-11-25 17:47:34 -08:00
|
|
|
mapped_parent, src_changed,
|
|
|
|
level + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Phase1_Context *ctx = p1ctx;
|
|
|
|
|
|
|
|
#ifdef RENDCACHE
|
2018-05-29 00:25:54 -07:00
|
|
|
Render_Cache *rc = NULL;
|
|
|
|
void *p_del_redir;
|
|
|
|
Phase1_Context tmpctx;
|
|
|
|
|
2016-11-25 17:47:34 -08:00
|
|
|
if (obj->no_change_render > 3)
|
|
|
|
{
|
|
|
|
rc = evas_object_smart_render_cache_get(eo_obj);
|
|
|
|
if (!rc)
|
|
|
|
{
|
|
|
|
rc = _evas_render_phase1_object_render_cache_new();
|
|
|
|
evas_object_smart_render_cache_set(eo_obj, rc);
|
|
|
|
ctx = &tmpctx;
|
|
|
|
*ctx = *p1ctx;
|
|
|
|
p_del_redir = p1ctx->e->update_del_redirect_array;
|
|
|
|
p1ctx->e->update_del_redirect_array = rc->update_del;
|
|
|
|
_evas_render_phase1_object_ctx_render_cache_fill(ctx, rc);
|
|
|
|
EINA_INLIST_FOREACH
|
|
|
|
(evas_object_smart_members_get_direct(eo_obj), obj2)
|
|
|
|
{
|
2016-11-25 18:10:18 -08:00
|
|
|
_evas_render_phase1_object_process(ctx, obj2,
|
2016-11-25 17:47:34 -08:00
|
|
|
obj->restack,
|
|
|
|
mapped_parent,
|
|
|
|
src_changed,
|
|
|
|
level + 1);
|
|
|
|
}
|
|
|
|
p1ctx->redraw_all = ctx->redraw_all;
|
|
|
|
p1ctx->e->update_del_redirect_array = p_del_redir;
|
|
|
|
}
|
|
|
|
_evas_render_phase1_object_ctx_render_cache_append(p1ctx, rc);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
EINA_INLIST_FOREACH
|
|
|
|
(evas_object_smart_members_get_direct(eo_obj), obj2)
|
|
|
|
{
|
2016-11-25 18:10:18 -08:00
|
|
|
_evas_render_phase1_object_process(ctx, obj2, obj->restack,
|
2016-11-25 17:47:34 -08:00
|
|
|
mapped_parent,
|
2016-11-25 18:10:18 -08:00
|
|
|
src_changed, level + 1);
|
2016-11-25 17:47:34 -08:00
|
|
|
}
|
|
|
|
}
|
2016-11-22 04:07:29 -08:00
|
|
|
}
|
|
|
|
return src_changed;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_evas_render_phase1_object_changed_normal(Phase1_Context *p1ctx,
|
|
|
|
Evas_Object_Protected_Data *obj,
|
|
|
|
Eina_Bool is_active,
|
|
|
|
int level
|
|
|
|
#ifndef REND_DBG
|
|
|
|
EINA_UNUSED
|
|
|
|
#endif
|
|
|
|
)
|
|
|
|
{
|
2019-05-29 12:36:53 -07:00
|
|
|
if ((!obj->clip.clipees) && _evas_render_is_relevant(obj))
|
2016-11-22 04:07:29 -08:00
|
|
|
{
|
|
|
|
if (EINA_LIKELY(is_active))
|
|
|
|
{
|
|
|
|
RD(level, " relevant + active\n");
|
|
|
|
if (EINA_UNLIKELY(obj->restack))
|
|
|
|
OBJ_ARRAY_PUSH(p1ctx->restack_objects, obj);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
OBJ_ARRAY_PUSH(p1ctx->render_objects, obj);
|
|
|
|
obj->render_pre = EINA_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* It goes to be hidden. Prev caching should be replaced
|
|
|
|
by the current (hidden) state. */
|
2019-05-29 12:36:53 -07:00
|
|
|
if (evas_object_is_visible(obj) !=
|
2019-05-29 12:36:46 -07:00
|
|
|
evas_object_was_visible(obj))
|
2017-02-03 18:31:55 -08:00
|
|
|
evas_object_cur_prev(obj);
|
2016-11-22 04:07:29 -08:00
|
|
|
RD(level, " skip - not smart, not active or clippees or not relevant\n");
|
|
|
|
}
|
|
|
|
}
|
2016-12-15 19:16:01 -08:00
|
|
|
else if (is_active && _evas_render_object_is_mask(obj) &&
|
|
|
|
(obj->cur->visible || obj->prev->visible))
|
2016-11-22 04:07:29 -08:00
|
|
|
{
|
|
|
|
if (EINA_UNLIKELY(obj->restack))
|
|
|
|
OBJ_ARRAY_PUSH(p1ctx->restack_objects, obj);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
OBJ_ARRAY_PUSH(p1ctx->render_objects, obj);
|
|
|
|
obj->render_pre = EINA_TRUE;
|
|
|
|
}
|
|
|
|
RD(level, " relevant + active: clipper image\n");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
RD(level, " skip - not smart, not active or clippees or not relevant\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_evas_render_phase1_object_no_changed_smart(Phase1_Context *p1ctx,
|
|
|
|
Evas_Object_Protected_Data *obj,
|
|
|
|
Eina_Bool restack,
|
|
|
|
Eina_Bool mapped_parent,
|
|
|
|
Eina_Bool src_changed,
|
|
|
|
int level)
|
|
|
|
{
|
|
|
|
Evas_Object_Protected_Data *obj2;
|
2016-11-25 17:47:34 -08:00
|
|
|
Phase1_Context *ctx = p1ctx;
|
2016-11-25 18:10:18 -08:00
|
|
|
Evas_Object *eo_obj = obj->object;
|
2016-11-22 04:07:29 -08:00
|
|
|
|
|
|
|
RD(level, " smart + visible/was visible + not clip\n");
|
|
|
|
OBJ_ARRAY_PUSH(p1ctx->render_objects, obj);
|
|
|
|
obj->render_pre = EINA_TRUE;
|
2016-11-25 17:47:34 -08:00
|
|
|
#ifdef RENDCACHE
|
2018-05-29 00:25:54 -07:00
|
|
|
void *p_del_redir;
|
|
|
|
Render_Cache *rc = NULL;
|
|
|
|
Phase1_Context tmpctx;
|
|
|
|
|
2016-11-25 17:47:34 -08:00
|
|
|
if (obj->no_change_render > 3)
|
2016-11-22 04:07:29 -08:00
|
|
|
{
|
2016-11-25 17:47:34 -08:00
|
|
|
rc = evas_object_smart_render_cache_get(eo_obj);
|
|
|
|
if (!rc)
|
|
|
|
{
|
|
|
|
rc = _evas_render_phase1_object_render_cache_new();
|
|
|
|
evas_object_smart_render_cache_set(eo_obj, rc);
|
|
|
|
ctx = &tmpctx;
|
|
|
|
*ctx = *p1ctx;
|
|
|
|
p_del_redir = p1ctx->e->update_del_redirect_array;
|
|
|
|
p1ctx->e->update_del_redirect_array = rc->update_del;
|
|
|
|
_evas_render_phase1_object_ctx_render_cache_fill(ctx, rc);
|
|
|
|
EINA_INLIST_FOREACH
|
|
|
|
(evas_object_smart_members_get_direct(eo_obj), obj2)
|
|
|
|
{
|
2016-11-25 18:10:18 -08:00
|
|
|
_evas_render_phase1_object_process(ctx, obj2, restack,
|
2016-11-25 17:47:34 -08:00
|
|
|
mapped_parent,
|
2016-11-25 18:10:18 -08:00
|
|
|
src_changed, level + 1);
|
2016-11-25 17:47:34 -08:00
|
|
|
}
|
|
|
|
p1ctx->redraw_all = ctx->redraw_all;
|
|
|
|
p1ctx->e->update_del_redirect_array = p_del_redir;
|
|
|
|
}
|
|
|
|
_evas_render_phase1_object_ctx_render_cache_append(p1ctx, rc);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
EINA_INLIST_FOREACH
|
|
|
|
(evas_object_smart_members_get_direct(eo_obj), obj2)
|
|
|
|
{
|
2016-11-25 18:10:18 -08:00
|
|
|
_evas_render_phase1_object_process(ctx, obj2, restack,
|
2016-11-25 17:47:34 -08:00
|
|
|
mapped_parent,
|
2016-11-25 18:10:18 -08:00
|
|
|
src_changed, level + 1);
|
2016-11-25 17:47:34 -08:00
|
|
|
}
|
2016-11-22 04:07:29 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_evas_render_phase1_object_no_changed_normal(Phase1_Context *p1ctx,
|
|
|
|
Evas_Object_Protected_Data *obj,
|
|
|
|
int level
|
|
|
|
#ifndef REND_DBG
|
|
|
|
EINA_UNUSED
|
|
|
|
#endif
|
|
|
|
)
|
|
|
|
{
|
2019-05-29 12:37:07 -07:00
|
|
|
if (evas_object_is_opaque(obj) &&
|
2019-05-29 12:36:53 -07:00
|
|
|
evas_object_is_visible(obj))
|
2016-11-22 04:07:29 -08:00
|
|
|
{
|
|
|
|
RD(level, " opaque + visible\n");
|
|
|
|
OBJ_ARRAY_PUSH(p1ctx->render_objects, obj);
|
|
|
|
obj->rect_del = EINA_TRUE;
|
|
|
|
}
|
2019-05-29 12:36:53 -07:00
|
|
|
else if (evas_object_is_visible(obj))
|
2016-11-22 04:07:29 -08:00
|
|
|
{
|
|
|
|
RD(level, " visible\n");
|
|
|
|
OBJ_ARRAY_PUSH(p1ctx->render_objects, obj);
|
|
|
|
obj->render_pre = EINA_TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
RD(level, " skip\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_evas_render_phase1_object_process(Phase1_Context *p1ctx,
|
2016-11-25 18:10:18 -08:00
|
|
|
Evas_Object_Protected_Data *obj,
|
2016-11-22 04:07:29 -08:00
|
|
|
Eina_Bool restack,
|
2014-03-26 23:47:00 -07:00
|
|
|
Eina_Bool mapped_parent,
|
2016-11-21 18:09:18 -08:00
|
|
|
Eina_Bool src_changed,
|
|
|
|
int level)
|
2008-05-26 06:24:24 -07:00
|
|
|
{
|
2009-06-17 03:01:52 -07:00
|
|
|
Eina_Bool clean_them = EINA_FALSE;
|
2016-11-22 04:07:29 -08:00
|
|
|
Eina_Bool map, hmap, can_map, map_not_can_map, obj_changed, is_active;
|
2016-11-25 18:10:18 -08:00
|
|
|
Evas_Object *eo_obj = obj->object;
|
2012-07-16 04:33:12 -07:00
|
|
|
|
2016-11-30 00:36:42 -08:00
|
|
|
EINA_PREFETCH(&(obj->cur->clipper));
|
|
|
|
|
2012-05-15 04:43:23 -07:00
|
|
|
obj->rect_del = EINA_FALSE;
|
|
|
|
obj->render_pre = EINA_FALSE;
|
2008-05-26 06:24:24 -07:00
|
|
|
|
2016-11-22 20:57:27 -08:00
|
|
|
if (obj->delete_me == 2) OBJ_ARRAY_PUSH(p1ctx->delete_objects, obj);
|
2012-04-26 02:53:03 -07:00
|
|
|
else if (obj->delete_me != 0) obj->delete_me++;
|
2016-11-25 17:47:34 -08:00
|
|
|
|
2008-05-26 06:24:24 -07:00
|
|
|
/* If the object will be removed, we should not cache anything during this run. */
|
2009-11-10 00:50:11 -08:00
|
|
|
if (obj->delete_me != 0) clean_them = EINA_TRUE;
|
2008-05-26 06:24:24 -07:00
|
|
|
|
2016-11-25 17:47:34 -08:00
|
|
|
obj_changed = obj->changed;
|
|
|
|
|
|
|
|
if (obj->is_static_clip) goto done;
|
2016-11-22 20:57:27 -08:00
|
|
|
|
|
|
|
//Need pre render for the children of mapped object.
|
|
|
|
//But only when they have changed.
|
2016-11-25 17:47:34 -08:00
|
|
|
if (mapped_parent && (!obj->changed)) goto done;
|
2016-11-22 20:57:27 -08:00
|
|
|
|
2005-10-26 19:44:36 -07:00
|
|
|
/* build active object list */
|
2013-04-06 22:00:10 -07:00
|
|
|
evas_object_clip_recalc(obj);
|
2010-04-27 06:43:10 -07:00
|
|
|
|
2014-03-26 23:47:00 -07:00
|
|
|
if (src_changed) is_active = EINA_TRUE;
|
2014-03-27 00:16:49 -07:00
|
|
|
else
|
|
|
|
{
|
|
|
|
is_active = evas_object_is_active(eo_obj, obj);
|
2014-09-01 03:45:19 -07:00
|
|
|
if (is_active && obj->proxy->proxies) src_changed = is_active;
|
2014-03-27 00:16:49 -07:00
|
|
|
}
|
|
|
|
obj->is_active = is_active;
|
|
|
|
|
2015-01-26 00:35:42 -08:00
|
|
|
#ifdef REND_DBG
|
2017-01-11 04:18:59 -08:00
|
|
|
RD(level, "[--- PROCESS %s active = %i, del = %i | %i,%i %ix%i\n",
|
|
|
|
RDNAME(obj), is_active, obj->delete_me, obj->cur->geometry.x,
|
|
|
|
obj->cur->geometry.y, obj->cur->geometry.w, obj->cur->geometry.h);
|
2015-01-26 00:35:42 -08:00
|
|
|
#endif
|
2012-07-15 20:12:39 -07:00
|
|
|
|
2016-11-22 04:07:29 -08:00
|
|
|
if ((!mapped_parent) &&
|
|
|
|
((is_active) || (obj->delete_me != 0)) &&
|
|
|
|
(!obj->no_render))
|
2016-11-25 21:25:41 -08:00
|
|
|
{
|
|
|
|
Evas_Active_Entry ent;
|
|
|
|
|
|
|
|
#ifdef INLINE_ACTIVE_GEOM
|
|
|
|
if (obj->is_smart)
|
2017-02-20 02:34:58 -08:00
|
|
|
evas_object_smart_bounding_box_get(obj, &(ent.rect), NULL);
|
2016-11-25 21:25:41 -08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
ent.rect.x = obj->cur->cache.clip.x;
|
|
|
|
ent.rect.y = obj->cur->cache.clip.y;
|
|
|
|
ent.rect.w = obj->cur->cache.clip.w;
|
|
|
|
ent.rect.h = obj->cur->cache.clip.h;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
ent.obj = obj;
|
|
|
|
eina_inarray_push(p1ctx->active_objects, &ent);
|
|
|
|
}
|
2015-10-07 18:57:54 -07:00
|
|
|
if (is_active && obj->cur->snapshot && !obj->delete_me &&
|
2019-05-29 12:36:53 -07:00
|
|
|
evas_object_is_visible(obj))
|
2017-03-29 21:52:48 -07:00
|
|
|
{
|
|
|
|
// FIXME: Array should be clean (no need to check if already in there)
|
|
|
|
int found = 0;
|
|
|
|
for (unsigned i = 0; !found && (i < p1ctx->snapshot_objects->count); i++)
|
|
|
|
if (obj == eina_array_data_get(p1ctx->snapshot_objects, i))
|
|
|
|
found = 1;
|
|
|
|
if (!found) OBJ_ARRAY_PUSH(p1ctx->snapshot_objects, obj);
|
|
|
|
}
|
2009-11-19 00:37:22 -08:00
|
|
|
|
2012-09-12 12:00:23 -07:00
|
|
|
#ifdef REND_DBG
|
2009-11-19 00:37:22 -08:00
|
|
|
if (!is_active)
|
|
|
|
{
|
2017-01-11 04:18:59 -08:00
|
|
|
RD(level, "%s vis: %i, cache.clip.vis: %i cache.clip.a: %i [func: %p]\n",
|
|
|
|
RDNAME(obj), obj->cur->visible, obj->cur->cache.clip.visible,
|
|
|
|
obj->cur->cache.clip.a, obj->func->is_visible);
|
2009-11-19 00:37:22 -08:00
|
|
|
}
|
2010-04-27 06:43:10 -07:00
|
|
|
#endif
|
|
|
|
|
2019-02-20 12:32:41 -08:00
|
|
|
_evas_object_gfx_mapping_update(obj);
|
2016-01-06 04:52:46 -08:00
|
|
|
map = _evas_render_has_map(obj);
|
2012-10-10 00:23:00 -07:00
|
|
|
hmap = _evas_render_had_map(obj);
|
2016-01-06 04:52:46 -08:00
|
|
|
can_map = _evas_render_can_map(obj);
|
2016-11-22 04:07:29 -08:00
|
|
|
map_not_can_map = map & !can_map;
|
2010-04-27 06:43:10 -07:00
|
|
|
|
2016-11-22 04:07:29 -08:00
|
|
|
if (EINA_UNLIKELY((restack && !map_not_can_map)))
|
2005-10-26 23:40:28 -07:00
|
|
|
{
|
2016-11-22 04:07:29 -08:00
|
|
|
_evas_render_phase1_object_restack_handle(p1ctx, obj, obj_changed);
|
|
|
|
obj_changed = EINA_TRUE;
|
2011-05-20 23:23:33 -07:00
|
|
|
clean_them = EINA_TRUE;
|
2005-10-26 23:40:28 -07:00
|
|
|
}
|
2009-11-06 21:01:43 -08:00
|
|
|
|
2016-11-22 04:07:29 -08:00
|
|
|
if (EINA_UNLIKELY(map_not_can_map))
|
2009-10-28 01:59:01 -07:00
|
|
|
{
|
2016-11-25 18:10:18 -08:00
|
|
|
_evas_render_phase1_object_mapped(p1ctx, obj, src_changed, hmap,
|
|
|
|
is_active, obj_changed, level);
|
2016-11-25 17:47:34 -08:00
|
|
|
goto done;
|
2009-10-28 01:59:01 -07:00
|
|
|
}
|
2016-11-22 04:07:29 -08:00
|
|
|
else if (EINA_UNLIKELY(hmap && !can_map))
|
2016-11-25 18:10:18 -08:00
|
|
|
_evas_render_phase1_object_mapped_had_restack(p1ctx, obj, map,
|
2016-12-16 00:04:05 -08:00
|
|
|
obj_changed, level);
|
2010-04-27 06:43:10 -07:00
|
|
|
|
2009-10-28 01:59:01 -07:00
|
|
|
/* handle normal rendering. this object knows how to handle maps */
|
2016-11-22 04:07:29 -08:00
|
|
|
if (obj_changed)
|
2005-10-26 19:44:36 -07:00
|
|
|
{
|
2012-10-08 18:58:41 -07:00
|
|
|
if (obj->is_smart)
|
2016-11-22 04:07:29 -08:00
|
|
|
src_changed =
|
2016-11-25 18:10:18 -08:00
|
|
|
_evas_render_phase1_object_changed_smart(p1ctx, obj, mapped_parent,
|
|
|
|
obj_changed, src_changed,
|
|
|
|
is_active, level);
|
2016-11-22 04:07:29 -08:00
|
|
|
else /* non smart object */
|
2016-11-25 18:10:18 -08:00
|
|
|
_evas_render_phase1_object_changed_normal(p1ctx, obj, is_active,
|
|
|
|
level);
|
2005-10-26 19:44:36 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-11-12 17:47:29 -08:00
|
|
|
/* not changed */
|
2015-01-26 00:35:42 -08:00
|
|
|
RD(level, " not changed... [%i] -> (%i %i %p %i) [%i]\n",
|
2019-05-29 12:36:53 -07:00
|
|
|
evas_object_is_visible(obj),
|
2013-03-12 05:58:19 -07:00
|
|
|
obj->cur->visible, obj->cur->cache.clip.visible, obj->smart.smart,
|
2019-05-29 12:36:46 -07:00
|
|
|
obj->cur->cache.clip.a, evas_object_was_visible(obj));
|
2016-11-22 04:07:29 -08:00
|
|
|
if ((!obj->clip.clipees) &&
|
|
|
|
(EINA_LIKELY(obj->delete_me == 0)) &&
|
2019-05-29 12:36:53 -07:00
|
|
|
(_evas_render_can_render(obj) ||
|
2019-05-29 12:36:46 -07:00
|
|
|
(evas_object_was_visible(obj) &&
|
2016-11-22 04:07:29 -08:00
|
|
|
(!obj->prev->have_clipees))))
|
2011-05-20 23:23:33 -07:00
|
|
|
{
|
2012-10-08 18:58:41 -07:00
|
|
|
if (obj->is_smart)
|
2016-11-25 18:10:18 -08:00
|
|
|
_evas_render_phase1_object_no_changed_smart(p1ctx, obj, restack,
|
2016-11-22 04:07:29 -08:00
|
|
|
mapped_parent,
|
2016-11-25 18:10:18 -08:00
|
|
|
src_changed, level);
|
2016-11-22 04:07:29 -08:00
|
|
|
else /* not smart */
|
2016-11-25 18:10:18 -08:00
|
|
|
_evas_render_phase1_object_no_changed_normal(p1ctx, obj, level);
|
2009-11-15 05:46:20 -08:00
|
|
|
}
|
2016-11-22 04:07:29 -08:00
|
|
|
else if (EINA_UNLIKELY(is_active &&
|
|
|
|
_evas_render_object_is_mask(obj) &&
|
2016-12-15 19:16:01 -08:00
|
|
|
obj->cur->visible))
|
2014-11-12 17:47:29 -08:00
|
|
|
{
|
2015-01-26 00:35:42 -08:00
|
|
|
RD(level, " visible clipper image\n");
|
2016-11-21 18:09:18 -08:00
|
|
|
OBJ_ARRAY_PUSH(p1ctx->render_objects, obj);
|
2014-11-12 17:47:29 -08:00
|
|
|
obj->render_pre = EINA_TRUE;
|
|
|
|
}
|
2012-07-15 20:12:39 -07:00
|
|
|
}
|
|
|
|
if (!is_active) obj->restack = EINA_FALSE;
|
2015-01-26 00:35:42 -08:00
|
|
|
RD(level, "---]\n");
|
2016-11-25 17:47:34 -08:00
|
|
|
done:
|
|
|
|
if (obj_changed) obj->no_change_render = 0;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (obj->no_change_render < 255) obj->no_change_render++;
|
|
|
|
}
|
2012-07-15 20:12:39 -07:00
|
|
|
return clean_them;
|
2005-10-26 19:44:36 -07:00
|
|
|
}
|
|
|
|
|
2016-11-25 17:47:34 -08:00
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2009-06-17 03:01:52 -07:00
|
|
|
static Eina_Bool
|
2016-11-21 18:09:18 -08:00
|
|
|
_evas_render_phase1_process(Phase1_Context *p1ctx)
|
2005-10-26 19:44:36 -07:00
|
|
|
{
|
2008-10-17 04:23:18 -07:00
|
|
|
Evas_Layer *lay;
|
2009-06-17 03:01:52 -07:00
|
|
|
Eina_Bool clean_them = EINA_FALSE;
|
2005-10-26 19:44:36 -07:00
|
|
|
|
2015-01-26 00:35:42 -08:00
|
|
|
RD(0, " [--- PHASE 1\n");
|
2016-11-21 18:09:18 -08:00
|
|
|
EINA_INLIST_FOREACH(p1ctx->e->layers, lay)
|
2005-10-26 19:44:36 -07:00
|
|
|
{
|
2012-10-08 18:58:41 -07:00
|
|
|
Evas_Object_Protected_Data *obj;
|
2010-04-27 06:43:10 -07:00
|
|
|
|
2011-05-20 23:23:33 -07:00
|
|
|
EINA_INLIST_FOREACH(lay->objects, obj)
|
|
|
|
{
|
2019-05-29 12:37:13 -07:00
|
|
|
if (evas_object_is_on_plane(obj)) continue;
|
2011-05-20 23:23:33 -07:00
|
|
|
clean_them |= _evas_render_phase1_object_process
|
2016-11-25 18:10:18 -08:00
|
|
|
(p1ctx, obj, EINA_FALSE, EINA_FALSE, EINA_FALSE, 2);
|
2011-05-20 23:23:33 -07:00
|
|
|
}
|
2008-05-26 06:24:24 -07:00
|
|
|
}
|
2015-01-26 00:35:42 -08:00
|
|
|
RD(0, " ---]\n");
|
2008-05-26 06:24:24 -07:00
|
|
|
return clean_them;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-10-08 18:58:41 -07:00
|
|
|
_evas_render_check_pending_objects(Eina_Array *pending_objects, Evas *eo_e EINA_UNUSED, Evas_Public_Data *e)
|
2008-05-26 06:24:24 -07:00
|
|
|
{
|
2010-05-05 04:36:21 -07:00
|
|
|
unsigned int i;
|
2008-05-26 06:24:24 -07:00
|
|
|
|
|
|
|
for (i = 0; i < pending_objects->count; ++i)
|
|
|
|
{
|
2012-10-08 18:58:41 -07:00
|
|
|
Evas_Object *eo_obj;
|
2012-05-16 06:21:37 -07:00
|
|
|
int is_active;
|
|
|
|
Eina_Bool ok = EINA_FALSE;
|
2012-10-08 18:58:41 -07:00
|
|
|
|
2016-11-30 00:36:42 -08:00
|
|
|
Evas_Object_Protected_Data *obj = eina_array_data_get(pending_objects, i);
|
2012-10-08 18:58:41 -07:00
|
|
|
eo_obj = obj->object;
|
|
|
|
|
2011-05-20 23:23:33 -07:00
|
|
|
if (!obj->layer) goto clean_stuff;
|
2010-04-27 06:43:10 -07:00
|
|
|
|
2019-02-20 12:32:41 -08:00
|
|
|
_evas_object_gfx_mapping_update(obj);
|
2016-11-30 00:36:42 -08:00
|
|
|
EINA_PREFETCH(&(obj->cur->clipper));
|
|
|
|
EINA_PREFETCH(&(obj->cur->cache.clip));
|
2016-11-26 19:02:12 -08:00
|
|
|
//If the children are in active objects, They should be cleaned up.
|
|
|
|
if (EINA_UNLIKELY((obj->changed_map) &&
|
|
|
|
(_evas_render_has_map(obj)) &&
|
|
|
|
(!_evas_render_can_map(obj))))
|
|
|
|
goto clean_stuff;
|
2012-05-29 17:51:11 -07:00
|
|
|
|
2013-04-06 22:00:10 -07:00
|
|
|
evas_object_clip_recalc(obj);
|
2012-10-08 18:58:41 -07:00
|
|
|
is_active = evas_object_is_active(eo_obj, obj);
|
2010-04-27 06:43:10 -07:00
|
|
|
|
2011-05-20 23:23:33 -07:00
|
|
|
if ((!is_active) && (!obj->is_active) && (!obj->render_pre) &&
|
2009-10-30 03:11:15 -07:00
|
|
|
(!obj->rect_del))
|
2011-05-20 23:23:33 -07:00
|
|
|
{
|
2012-05-16 06:21:37 -07:00
|
|
|
ok = EINA_TRUE;
|
2011-05-20 23:23:33 -07:00
|
|
|
goto clean_stuff;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (obj->is_active == is_active)
|
|
|
|
{
|
|
|
|
if (obj->changed)
|
|
|
|
{
|
2012-10-08 18:58:41 -07:00
|
|
|
if (obj->is_smart)
|
2011-05-20 23:23:33 -07:00
|
|
|
{
|
2012-05-16 06:21:37 -07:00
|
|
|
if (obj->render_pre || obj->rect_del) ok = EINA_TRUE;
|
2011-05-20 23:23:33 -07:00
|
|
|
}
|
2009-10-28 01:59:01 -07:00
|
|
|
else
|
2011-05-20 23:23:33 -07:00
|
|
|
if ((is_active) && (obj->restack) && (!obj->clip.clipees) &&
|
2019-05-29 12:36:53 -07:00
|
|
|
(_evas_render_can_render(obj) ||
|
2019-05-29 12:36:46 -07:00
|
|
|
(evas_object_was_visible(obj) && (!obj->prev->have_clipees))))
|
2009-10-28 01:59:01 -07:00
|
|
|
{
|
2017-03-05 23:45:24 -08:00
|
|
|
if (!obj->render_pre && !obj->rect_del && !obj->delete_me)
|
2012-05-16 06:21:37 -07:00
|
|
|
ok = EINA_TRUE;
|
2009-10-28 01:59:01 -07:00
|
|
|
}
|
2011-05-20 23:23:33 -07:00
|
|
|
else
|
|
|
|
if (is_active && (!obj->clip.clipees) &&
|
2019-05-29 12:36:53 -07:00
|
|
|
(_evas_render_can_render(obj) ||
|
2019-05-29 12:36:46 -07:00
|
|
|
(evas_object_was_visible(obj) && (!obj->prev->have_clipees))))
|
2011-05-20 23:23:33 -07:00
|
|
|
{
|
2012-05-16 06:21:37 -07:00
|
|
|
if (obj->render_pre || obj->rect_del) ok = EINA_TRUE;
|
2011-05-20 23:23:33 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ((!obj->clip.clipees) && (obj->delete_me == 0) &&
|
2019-05-29 12:36:46 -07:00
|
|
|
(!obj->cur->have_clipees || (evas_object_was_visible(obj) && (!obj->prev->have_clipees)))
|
2019-05-29 12:37:07 -07:00
|
|
|
&& evas_object_is_opaque(obj) && evas_object_is_visible(obj))
|
2009-10-30 03:11:15 -07:00
|
|
|
{
|
2012-10-08 18:58:41 -07:00
|
|
|
if (obj->rect_del || obj->is_smart) ok = EINA_TRUE;
|
2009-10-30 03:11:15 -07:00
|
|
|
}
|
2011-05-20 23:23:33 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
clean_stuff:
|
|
|
|
if (!ok)
|
|
|
|
{
|
2016-11-25 21:25:41 -08:00
|
|
|
eina_inarray_flush(&e->active_objects);
|
2013-05-02 00:47:16 -07:00
|
|
|
OBJS_ARRAY_CLEAN(&e->render_objects);
|
|
|
|
OBJS_ARRAY_CLEAN(&e->restack_objects);
|
|
|
|
OBJS_ARRAY_CLEAN(&e->delete_objects);
|
2015-05-09 11:02:13 -07:00
|
|
|
OBJS_ARRAY_CLEAN(&e->snapshot_objects);
|
2012-05-16 06:21:37 -07:00
|
|
|
e->invalidate = EINA_TRUE;
|
2013-06-20 04:28:18 -07:00
|
|
|
return;
|
2011-05-20 23:23:33 -07:00
|
|
|
}
|
2005-10-26 19:44:36 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-09-03 22:13:19 -07:00
|
|
|
Eina_Bool
|
2012-10-08 18:58:41 -07:00
|
|
|
pending_change(void *data, void *gdata EINA_UNUSED)
|
2008-06-04 09:42:39 -07:00
|
|
|
{
|
2012-10-08 18:58:41 -07:00
|
|
|
Evas_Object *eo_obj;
|
2008-06-04 09:42:39 -07:00
|
|
|
|
2012-10-08 18:58:41 -07:00
|
|
|
Evas_Object_Protected_Data *obj = data;
|
|
|
|
eo_obj = obj->object;
|
2008-10-16 05:27:07 -07:00
|
|
|
if (obj->delete_me) return EINA_FALSE;
|
2009-11-23 02:07:07 -08:00
|
|
|
if (obj->pre_render_done)
|
|
|
|
{
|
2017-01-11 04:18:59 -08:00
|
|
|
RD(0, " OBJ %s pending change %i -> 0, pre %i\n", RDNAME(obj), obj->changed, obj->pre_render_done);
|
evas image: fix non-rendered preload image.
Summary:
This is one more corner-case issue that I found,
When second image doesn't use preload (but still share the resource)
canvas engine triggers cancellation for first image preload function.
Unluckly, preload thread is cancelled on the intermediate rendering,
First image is not going to rendered, even image turn it changed states.
Because end of that frame, canvas reset/flushed all active objects.
Here changes to retain the changes status to redraw it in the next frame.
Test Plan:
img1 = image_add;
image_file_set(img1, "test.jpg");
image_preload(img1, true);
show(img);
img2 = image_add;
image_file_set(img2, "test.jpg"); //same resource
image_preload(img2, false);
show(img2);
img1 is invisible.
Reviewers: #committers
Subscribers: cedric, #reviewers, #committers
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D7157
2018-10-22 22:49:46 -07:00
|
|
|
evas_object_change_reset(obj);
|
2013-07-08 17:46:15 -07:00
|
|
|
obj->func->render_post(eo_obj, obj, obj->private_data);
|
2012-05-16 06:21:37 -07:00
|
|
|
obj->pre_render_done = EINA_FALSE;
|
2009-11-23 02:07:07 -08:00
|
|
|
}
|
2019-05-29 12:36:53 -07:00
|
|
|
else if (!_evas_render_can_render(obj) &&
|
2013-12-19 00:34:05 -08:00
|
|
|
(!obj->is_active) && (!obj->render_pre) &&
|
|
|
|
(!obj->rect_del))
|
|
|
|
{
|
2017-02-03 18:31:55 -08:00
|
|
|
evas_object_change_reset(obj);
|
2013-12-19 00:34:05 -08:00
|
|
|
}
|
evas image: fix non-rendered preload image.
Summary:
This is one more corner-case issue that I found,
When second image doesn't use preload (but still share the resource)
canvas engine triggers cancellation for first image preload function.
Unluckly, preload thread is cancelled on the intermediate rendering,
First image is not going to rendered, even image turn it changed states.
Because end of that frame, canvas reset/flushed all active objects.
Here changes to retain the changes status to redraw it in the next frame.
Test Plan:
img1 = image_add;
image_file_set(img1, "test.jpg");
image_preload(img1, true);
show(img);
img2 = image_add;
image_file_set(img2, "test.jpg"); //same resource
image_preload(img2, false);
show(img2);
img1 is invisible.
Reviewers: #committers
Subscribers: cedric, #reviewers, #committers
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D7157
2018-10-22 22:49:46 -07:00
|
|
|
|
|
|
|
//FIXME: after evas_object_change_reset(), obj->changed is always false...
|
2018-10-29 13:50:45 -07:00
|
|
|
Eina_Bool val = obj->changed ? EINA_TRUE : EINA_FALSE;
|
|
|
|
obj->in_pending_objects = val;
|
|
|
|
return val;
|
2008-06-04 09:42:39 -07:00
|
|
|
}
|
2011-01-19 03:59:53 -08:00
|
|
|
|
2011-10-02 20:28:52 -07:00
|
|
|
static Eina_Bool
|
2017-08-25 10:51:20 -07:00
|
|
|
_evas_render_can_use_overlay(Evas_Public_Data *e, Evas_Object *eo_obj, Efl_Canvas_Output *output)
|
2011-10-02 20:28:52 -07:00
|
|
|
{
|
|
|
|
Eina_Rectangle *r;
|
2012-10-08 18:58:41 -07:00
|
|
|
Evas_Object *eo_tmp;
|
2011-10-02 20:28:52 -07:00
|
|
|
Eina_List *alphas = NULL;
|
|
|
|
Eina_List *opaques = NULL;
|
|
|
|
Evas_Object *video_parent = NULL;
|
|
|
|
Eina_Rectangle zone;
|
|
|
|
Evas_Coord xc1, yc1, xc2, yc2;
|
2015-05-09 11:02:13 -07:00
|
|
|
int i;
|
2011-10-02 20:28:52 -07:00
|
|
|
Eina_Bool nooverlay;
|
2016-08-15 06:44:41 -07:00
|
|
|
Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
|
2012-10-10 00:23:00 -07:00
|
|
|
Evas_Object_Protected_Data *tmp = NULL;
|
evas/image: Add video surface caps.
Wayland subsurfaces can be used as video surfaces too, similarly to
Ecore_X windows. However, they support a different set of features. Some
of them, like subsurface clipping and scaling, might be added in the
future, but so far we must work with what we have.
This commit allows to set an enum bitfield to the Video_Surface, with
the default value being one that will keep the same behavior as before,
for Ecore_X window. Thus, backward compatibility should not be broken.
It's possible to inform Evas that the surface in question is not able to
resize or scale, or that it's above or below the original canvas
surface. This allows Evas to show the surface itself, or use a buffer of
pixels instead, when the capabilities are not available.
2013-09-26 09:49:18 -07:00
|
|
|
Evas_Coord imgw, imgh;
|
|
|
|
unsigned int caps;
|
|
|
|
Eina_Bool surface_below, stacking_check, object_above = EINA_FALSE;
|
|
|
|
Eina_Bool ignore_window;
|
2011-10-02 20:28:52 -07:00
|
|
|
|
2017-08-25 10:51:20 -07:00
|
|
|
if (!_evas_object_image_can_use_plane(obj, output))
|
2017-06-22 10:46:16 -07:00
|
|
|
return EINA_FALSE;
|
|
|
|
|
2017-04-17 15:06:28 -07:00
|
|
|
video_parent = _evas_object_image_video_parent_get(eo_obj);
|
2011-10-02 20:28:52 -07:00
|
|
|
|
|
|
|
/* Check if any one is the stack make this object mapped */
|
2012-10-08 18:58:41 -07:00
|
|
|
eo_tmp = eo_obj;
|
2016-08-15 06:44:41 -07:00
|
|
|
tmp = efl_data_scope_get(eo_tmp, EFL_CANVAS_OBJECT_CLASS);
|
2019-02-20 12:32:41 -08:00
|
|
|
_evas_object_gfx_mapping_update(tmp);
|
2016-01-06 04:52:46 -08:00
|
|
|
while (tmp && !(_evas_render_has_map(tmp) && !_evas_render_can_map(tmp)))
|
2012-10-08 18:58:41 -07:00
|
|
|
{
|
|
|
|
eo_tmp = tmp->smart.parent;
|
2016-08-15 06:44:41 -07:00
|
|
|
tmp = efl_data_scope_get(eo_tmp, EFL_CANVAS_OBJECT_CLASS);
|
2019-02-20 12:32:41 -08:00
|
|
|
if (tmp) _evas_object_gfx_mapping_update(tmp);
|
2012-10-08 18:58:41 -07:00
|
|
|
}
|
2011-10-02 20:28:52 -07:00
|
|
|
|
2016-01-06 04:52:46 -08:00
|
|
|
if (tmp && _evas_render_has_map(tmp) && !_evas_render_can_map(tmp))
|
|
|
|
return EINA_FALSE; /* we are mapped, we can't be an overlay */
|
2011-10-02 20:28:52 -07:00
|
|
|
|
2019-05-29 12:36:53 -07:00
|
|
|
if (!evas_object_is_visible(obj))
|
2016-01-06 04:52:46 -08:00
|
|
|
return EINA_FALSE; /* no need to update the overlay if it's not visible */
|
2011-10-02 20:28:52 -07:00
|
|
|
|
|
|
|
/* If any recoloring of the surface is needed, n overlay to */
|
2013-03-12 05:58:19 -07:00
|
|
|
if ((obj->cur->cache.clip.r != 255) ||
|
|
|
|
(obj->cur->cache.clip.g != 255) ||
|
|
|
|
(obj->cur->cache.clip.b != 255) ||
|
|
|
|
(obj->cur->cache.clip.a != 255))
|
2011-10-02 20:28:52 -07:00
|
|
|
return EINA_FALSE;
|
|
|
|
|
evas/image: Add video surface caps.
Wayland subsurfaces can be used as video surfaces too, similarly to
Ecore_X windows. However, they support a different set of features. Some
of them, like subsurface clipping and scaling, might be added in the
future, but so far we must work with what we have.
This commit allows to set an enum bitfield to the Video_Surface, with
the default value being one that will keep the same behavior as before,
for Ecore_X window. Thus, backward compatibility should not be broken.
It's possible to inform Evas that the surface in question is not able to
resize or scale, or that it's above or below the original canvas
surface. This allows Evas to show the surface itself, or use a buffer of
pixels instead, when the capabilities are not available.
2013-09-26 09:49:18 -07:00
|
|
|
caps = evas_object_image_video_surface_caps_get(eo_obj);
|
|
|
|
|
|
|
|
/* check if surface is above the canvas */
|
|
|
|
surface_below = !!(caps & EVAS_VIDEO_SURFACE_BELOW);
|
|
|
|
if (!surface_below)
|
|
|
|
{
|
|
|
|
/* above canvas, must support resize and clipping */
|
|
|
|
|
|
|
|
/* check if video surface supports resize */
|
|
|
|
evas_object_image_size_get(eo_obj, &imgw, &imgh);
|
|
|
|
if ((obj->cur->geometry.w != imgw) ||
|
|
|
|
(obj->cur->geometry.h != imgh))
|
|
|
|
{
|
|
|
|
if (!(caps & EVAS_VIDEO_SURFACE_RESIZE))
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
/* check if video surface supports clipping */
|
|
|
|
evas_object_image_size_get(eo_obj, &imgw, &imgh);
|
|
|
|
if ((obj->cur->cache.clip.x != obj->cur->geometry.x) ||
|
|
|
|
(obj->cur->cache.clip.y != obj->cur->geometry.y) ||
|
|
|
|
(obj->cur->cache.clip.w != obj->cur->geometry.w) ||
|
|
|
|
(obj->cur->cache.clip.h != obj->cur->geometry.h))
|
|
|
|
{
|
|
|
|
if (!(caps & EVAS_VIDEO_SURFACE_CLIP))
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* check for window/surface/canvas limits */
|
|
|
|
ignore_window = !!(caps & EVAS_VIDEO_SURFACE_IGNORE_WINDOW);
|
|
|
|
if (!ignore_window)
|
|
|
|
{
|
|
|
|
Evas_Coord x1, x2, y1, y2;
|
|
|
|
Evas_Coord fx, fy, fw, fh;
|
|
|
|
|
|
|
|
fx = e->framespace.x;
|
|
|
|
fy = e->framespace.y;
|
|
|
|
fw = e->framespace.w;
|
|
|
|
fh = e->framespace.h;
|
|
|
|
|
|
|
|
x1 = obj->cur->geometry.x + fx;
|
|
|
|
y1 = obj->cur->geometry.y + fy;
|
|
|
|
x2 = obj->cur->geometry.x + obj->cur->geometry.w + fx;
|
|
|
|
y2 = obj->cur->geometry.y + obj->cur->geometry.h + fy;
|
|
|
|
|
|
|
|
if ((x1 < fx) || (y1 < fy) ||
|
|
|
|
(x2 > e->output.w - (fw - fx)) ||
|
|
|
|
(y2 > e->output.h - (fh - fy)))
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* check if there are other objects above the video object? */
|
|
|
|
stacking_check = !!(caps & EVAS_VIDEO_SURFACE_STACKING_CHECK);
|
|
|
|
if (!stacking_check)
|
|
|
|
return EINA_TRUE;
|
|
|
|
|
2011-10-02 20:28:52 -07:00
|
|
|
/* Check presence of transparent object on top of the video object */
|
|
|
|
EINA_RECTANGLE_SET(&zone,
|
2013-03-12 05:58:19 -07:00
|
|
|
obj->cur->cache.clip.x,
|
|
|
|
obj->cur->cache.clip.y,
|
|
|
|
obj->cur->cache.clip.w,
|
|
|
|
obj->cur->cache.clip.h);
|
2011-10-02 20:28:52 -07:00
|
|
|
|
2016-11-25 21:25:41 -08:00
|
|
|
for (i = e->active_objects.len - 1; i > 0; i--)
|
2011-10-02 20:28:52 -07:00
|
|
|
{
|
|
|
|
Eina_Rectangle self;
|
|
|
|
Eina_Rectangle *match;
|
2012-10-08 18:58:41 -07:00
|
|
|
Evas_Object *eo_current;
|
2011-10-02 20:28:52 -07:00
|
|
|
Eina_List *l;
|
|
|
|
int xm1, ym1, xm2, ym2;
|
2016-11-25 21:25:41 -08:00
|
|
|
Evas_Active_Entry *ent = eina_inarray_nth(&e->active_objects, i);
|
|
|
|
Evas_Object_Protected_Data *current = ent->obj;
|
2011-10-02 20:28:52 -07:00
|
|
|
|
2012-10-08 18:58:41 -07:00
|
|
|
eo_current = current->object;
|
2011-10-02 20:28:52 -07:00
|
|
|
/* Did we find the video object in the stack ? */
|
2012-10-08 18:58:41 -07:00
|
|
|
if (eo_current == video_parent || eo_current == eo_obj)
|
2011-10-02 20:28:52 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
EINA_RECTANGLE_SET(&self,
|
2013-03-12 05:58:19 -07:00
|
|
|
current->cur->cache.clip.x,
|
|
|
|
current->cur->cache.clip.y,
|
|
|
|
current->cur->cache.clip.w,
|
|
|
|
current->cur->cache.clip.h);
|
2011-10-02 20:28:52 -07:00
|
|
|
|
|
|
|
/* This doesn't cover the area of the video object, so don't bother with that object */
|
|
|
|
if (!eina_rectangles_intersect(&zone, &self))
|
2012-05-25 05:55:45 -07:00
|
|
|
continue;
|
2011-10-02 20:28:52 -07:00
|
|
|
|
2013-03-12 05:58:19 -07:00
|
|
|
xc1 = current->cur->cache.clip.x;
|
|
|
|
yc1 = current->cur->cache.clip.y;
|
|
|
|
xc2 = current->cur->cache.clip.x + current->cur->cache.clip.w;
|
|
|
|
yc2 = current->cur->cache.clip.y + current->cur->cache.clip.h;
|
2011-10-02 20:28:52 -07:00
|
|
|
|
2019-05-29 12:36:53 -07:00
|
|
|
if (evas_object_is_visible(current) &&
|
2011-10-02 20:28:52 -07:00
|
|
|
(!current->clip.clipees) &&
|
2013-03-12 05:58:19 -07:00
|
|
|
(current->cur->visible) &&
|
2011-10-02 20:28:52 -07:00
|
|
|
(!current->delete_me) &&
|
2013-03-12 05:58:19 -07:00
|
|
|
(current->cur->cache.clip.visible) &&
|
2016-08-15 06:44:41 -07:00
|
|
|
(!efl_isa(eo_current, EFL_CANVAS_GROUP_CLASS)))
|
2011-10-02 20:28:52 -07:00
|
|
|
{
|
|
|
|
Eina_Bool included = EINA_FALSE;
|
|
|
|
|
evas/image: Add video surface caps.
Wayland subsurfaces can be used as video surfaces too, similarly to
Ecore_X windows. However, they support a different set of features. Some
of them, like subsurface clipping and scaling, might be added in the
future, but so far we must work with what we have.
This commit allows to set an enum bitfield to the Video_Surface, with
the default value being one that will keep the same behavior as before,
for Ecore_X window. Thus, backward compatibility should not be broken.
It's possible to inform Evas that the surface in question is not able to
resize or scale, or that it's above or below the original canvas
surface. This allows Evas to show the surface itself, or use a buffer of
pixels instead, when the capabilities are not available.
2013-09-26 09:49:18 -07:00
|
|
|
if (!surface_below)
|
|
|
|
{
|
|
|
|
object_above = EINA_TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2019-05-29 12:37:07 -07:00
|
|
|
if (evas_object_is_opaque(current) ||
|
2011-10-02 20:28:52 -07:00
|
|
|
((current->func->has_opaque_rect) &&
|
2013-07-08 17:46:15 -07:00
|
|
|
(current->func->has_opaque_rect(eo_current, current, current->private_data))))
|
2011-10-02 20:28:52 -07:00
|
|
|
{
|
|
|
|
/* The object is opaque */
|
|
|
|
|
|
|
|
/* Check if the opaque object is inside another opaque object */
|
|
|
|
EINA_LIST_FOREACH(opaques, l, match)
|
|
|
|
{
|
|
|
|
xm1 = match->x;
|
|
|
|
ym1 = match->y;
|
|
|
|
xm2 = match->x + match->w;
|
|
|
|
ym2 = match->y + match->h;
|
|
|
|
|
|
|
|
/* Both object are included */
|
|
|
|
if (xc1 >= xm1 && yc1 >= ym1 && xc2 <= xm2 && yc2 <= ym2)
|
|
|
|
{
|
|
|
|
included = EINA_TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Not included yet */
|
|
|
|
if (!included)
|
|
|
|
{
|
|
|
|
Eina_List *ln;
|
|
|
|
Evas_Coord xn2, yn2;
|
|
|
|
|
2013-03-12 05:58:19 -07:00
|
|
|
r = eina_rectangle_new(current->cur->cache.clip.x, current->cur->cache.clip.y,
|
|
|
|
current->cur->cache.clip.w, current->cur->cache.clip.h);
|
2011-10-02 20:28:52 -07:00
|
|
|
|
|
|
|
opaques = eina_list_append(opaques, r);
|
|
|
|
|
|
|
|
xn2 = r->x + r->w;
|
|
|
|
yn2 = r->y + r->h;
|
|
|
|
|
|
|
|
/* Remove all the transparent object that are covered by the new opaque object */
|
|
|
|
EINA_LIST_FOREACH_SAFE(alphas, l, ln, match)
|
|
|
|
{
|
|
|
|
xm1 = match->x;
|
|
|
|
ym1 = match->y;
|
|
|
|
xm2 = match->x + match->w;
|
|
|
|
ym2 = match->y + match->h;
|
|
|
|
|
|
|
|
if (xm1 >= r->x && ym1 >= r->y && xm2 <= xn2 && ym2 <= yn2)
|
|
|
|
{
|
|
|
|
/* The new rectangle is over some transparent object,
|
|
|
|
so remove the transparent object */
|
|
|
|
alphas = eina_list_remove_list(alphas, l);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* The object has some transparency */
|
|
|
|
|
|
|
|
/* Check if the transparent object is inside any other transparent object */
|
|
|
|
EINA_LIST_FOREACH(alphas, l, match)
|
|
|
|
{
|
|
|
|
xm1 = match->x;
|
|
|
|
ym1 = match->y;
|
|
|
|
xm2 = match->x + match->w;
|
|
|
|
ym2 = match->y + match->h;
|
|
|
|
|
|
|
|
/* Both object are included */
|
|
|
|
if (xc1 >= xm1 && yc1 >= ym1 && xc2 <= xm2 && yc2 <= ym2)
|
|
|
|
{
|
|
|
|
included = EINA_TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If not check if it is inside any opaque one */
|
|
|
|
if (!included)
|
|
|
|
{
|
|
|
|
EINA_LIST_FOREACH(opaques, l, match)
|
|
|
|
{
|
|
|
|
xm1 = match->x;
|
|
|
|
ym1 = match->y;
|
|
|
|
xm2 = match->x + match->w;
|
|
|
|
ym2 = match->y + match->h;
|
|
|
|
|
|
|
|
/* Both object are included */
|
|
|
|
if (xc1 >= xm1 && yc1 >= ym1 && xc2 <= xm2 && yc2 <= ym2)
|
|
|
|
{
|
|
|
|
included = EINA_TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* No inclusion at all, so add it */
|
|
|
|
if (!included)
|
|
|
|
{
|
2013-03-12 05:58:19 -07:00
|
|
|
r = eina_rectangle_new(current->cur->cache.clip.x, current->cur->cache.clip.y,
|
|
|
|
current->cur->cache.clip.w, current->cur->cache.clip.h);
|
2011-10-02 20:28:52 -07:00
|
|
|
|
|
|
|
alphas = eina_list_append(alphas, r);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If there is any pending transparent object, then no overlay */
|
|
|
|
nooverlay = !!eina_list_count(alphas);
|
|
|
|
|
|
|
|
EINA_LIST_FREE(alphas, r)
|
|
|
|
eina_rectangle_free(r);
|
|
|
|
EINA_LIST_FREE(opaques, r)
|
|
|
|
eina_rectangle_free(r);
|
|
|
|
|
evas/image: Add video surface caps.
Wayland subsurfaces can be used as video surfaces too, similarly to
Ecore_X windows. However, they support a different set of features. Some
of them, like subsurface clipping and scaling, might be added in the
future, but so far we must work with what we have.
This commit allows to set an enum bitfield to the Video_Surface, with
the default value being one that will keep the same behavior as before,
for Ecore_X window. Thus, backward compatibility should not be broken.
It's possible to inform Evas that the surface in question is not able to
resize or scale, or that it's above or below the original canvas
surface. This allows Evas to show the surface itself, or use a buffer of
pixels instead, when the capabilities are not available.
2013-09-26 09:49:18 -07:00
|
|
|
if (nooverlay || object_above)
|
2011-10-02 20:28:52 -07:00
|
|
|
return EINA_FALSE;
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
2008-06-04 09:42:39 -07:00
|
|
|
|
2015-09-03 01:38:48 -07:00
|
|
|
static Eina_Bool
|
|
|
|
_proxy_context_clip(Evas_Public_Data *evas, void *ctx, Evas_Proxy_Render_Data *proxy_render_data, Evas_Object_Protected_Data *obj, int off_x, int off_y)
|
|
|
|
{
|
2017-09-13 00:38:33 -07:00
|
|
|
const Eina_Rectangle *clip;
|
2015-09-03 01:38:48 -07:00
|
|
|
Evas_Object_Protected_Data *clipper;
|
2015-10-13 04:33:57 -07:00
|
|
|
int cw, ch;
|
2015-09-03 01:38:48 -07:00
|
|
|
|
|
|
|
/* cache.clip can not be relied on, since the evas is frozen, but we need
|
|
|
|
* to set the clip. so we recurse from clipper to clipper until we reach
|
|
|
|
* the source object's clipper */
|
|
|
|
|
2015-10-13 04:33:57 -07:00
|
|
|
if (!proxy_render_data) return EINA_TRUE;
|
|
|
|
if (proxy_render_data->source_clip)
|
|
|
|
{
|
2019-05-23 06:31:42 -07:00
|
|
|
Evas_Object_Protected_Data *src_obj = proxy_render_data->src_obj;
|
2015-10-13 04:33:57 -07:00
|
|
|
/* trust cache.clip since we clip like the source */
|
2017-05-12 15:03:05 -07:00
|
|
|
ENFN->context_clip_clip(ENC, ctx,
|
2019-05-23 06:31:42 -07:00
|
|
|
src_obj->cur->cache.clip.x + off_x,
|
|
|
|
src_obj->cur->cache.clip.y + off_y,
|
|
|
|
src_obj->cur->cache.clip.w, src_obj->cur->cache.clip.h);
|
2017-05-12 15:03:05 -07:00
|
|
|
ENFN->context_clip_get(ENC, ctx, NULL, NULL, &cw, &ch);
|
2016-06-23 08:26:02 -07:00
|
|
|
return ((cw > 0) && (ch > 0));
|
2015-10-13 04:33:57 -07:00
|
|
|
}
|
|
|
|
|
2017-07-28 20:26:49 -07:00
|
|
|
if (!obj->cur->clipper) return EINA_TRUE;
|
2015-09-03 01:38:48 -07:00
|
|
|
|
|
|
|
clipper = obj->cur->clipper;
|
|
|
|
if (!clipper->cur->visible) return EINA_FALSE;
|
|
|
|
clip = &clipper->cur->geometry;
|
2017-05-12 15:03:05 -07:00
|
|
|
ENFN->context_clip_clip(ENC, ctx, clip->x + off_x, clip->y + off_y, clip->w, clip->h);
|
|
|
|
ENFN->context_clip_get(ENC, ctx, NULL, NULL, &cw, &ch);
|
2016-06-23 08:26:02 -07:00
|
|
|
if ((cw <= 0) || (ch <= 0)) return EINA_FALSE;
|
2015-09-03 01:38:48 -07:00
|
|
|
|
|
|
|
/* stop if we found the source object's clipper */
|
2015-10-13 04:33:57 -07:00
|
|
|
if (clipper == proxy_render_data->src_obj->cur->clipper) return EINA_TRUE;
|
2015-09-03 01:38:48 -07:00
|
|
|
|
2016-06-23 08:48:34 -07:00
|
|
|
/* recurse to the clipper itself.
|
|
|
|
* origin of clipper's clipper won't be transformed to derivative space. */
|
|
|
|
return _proxy_context_clip(evas, ctx, proxy_render_data, clipper,
|
2016-06-23 19:33:04 -07:00
|
|
|
-proxy_render_data->src_obj->cur->geometry.x,
|
|
|
|
-proxy_render_data->src_obj->cur->geometry.y);
|
2015-09-03 01:38:48 -07:00
|
|
|
}
|
|
|
|
|
evas: "fix" masks of masks inside a proxy
Here's the situation:
1. A container (genlist) has a mask, M0.
2. An item I0 inside this container uses a proxy P0 as render object
rather than the item directly (eg. for zooming in/out).
3. An element E0 inside this item has another mask, M1.
Theory:
1. The proxy surface for P0 is rendered, and M1 is applied to
the element E0.
2. The proxy P0 is rendered on the canvas, with M0 applied.
Practice:
1. The element E0 is prepared for rendering, this triggers
a mask subrender for M1.
2. M1 is rendered with M0 as a prev mask, then kept in cache and
not redrawn (no geometry change, etc...)
3. When P0's surface is rendered, M1's surface is the result of M1+M0.
4. When P0 is drawn on screen, we can see the effect of M1+M0 as
P0's geometry might be different from the item's I0.
Solution:
Discard prev masks and force a mask redraw when we're inside a
proxy. Ideally we should detect if the prev mask belongs to the
insides of the proxy or not.
Problems:
_mask_apply_inside_proxy() is definitely not correct, but it's
not easy to test it. Anyway I believe that in order to properly
implement all of this, we need to rethink evas_render and
the draw context. Non-primary render surfaces (maps, proxies,
masks, filters, ...) should be rendered with a clean context
and clipping, masking, etc should be computed appropriately.
2016-12-15 18:19:17 -08:00
|
|
|
static Eina_Bool
|
|
|
|
_mask_apply_inside_proxy(Evas_Proxy_Render_Data *proxy_render_data,
|
|
|
|
Evas_Object_Protected_Data *mask)
|
|
|
|
{
|
|
|
|
// Trying to find out if the mask should be applied inside the proxy or not.
|
|
|
|
if (!proxy_render_data || proxy_render_data->source_clip) return EINA_TRUE;
|
|
|
|
if (!proxy_render_data->src_obj->cur->clipper) return EINA_FALSE;
|
|
|
|
if (!mask) return EINA_FALSE;
|
|
|
|
|
|
|
|
// FIXME: Need to implement a logic similar to _proxy_context_clip
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
2013-07-04 19:09:03 -07:00
|
|
|
static void
|
2015-09-03 00:36:32 -07:00
|
|
|
_evas_render_mapped_context_clip_set(Evas_Public_Data *evas, Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, void *ctx, Evas_Proxy_Render_Data *proxy_render_data, int off_x, int off_y)
|
2013-07-04 19:09:03 -07:00
|
|
|
{
|
|
|
|
int x, y, w, h;
|
|
|
|
Eina_Bool proxy_src_clip = EINA_TRUE;
|
|
|
|
|
|
|
|
if (proxy_render_data) proxy_src_clip = proxy_render_data->source_clip;
|
|
|
|
|
2015-10-13 04:33:57 -07:00
|
|
|
if (proxy_src_clip)
|
2013-07-04 19:09:03 -07:00
|
|
|
{
|
|
|
|
x = obj->cur->cache.clip.x;
|
|
|
|
y = obj->cur->cache.clip.y;
|
|
|
|
w = obj->cur->cache.clip.w;
|
|
|
|
h = obj->cur->cache.clip.h;
|
|
|
|
|
|
|
|
RECTS_CLIP_TO_RECT(x, y, w, h,
|
|
|
|
obj->cur->clipper->cur->cache.clip.x,
|
|
|
|
obj->cur->clipper->cur->cache.clip.y,
|
|
|
|
obj->cur->clipper->cur->cache.clip.w,
|
|
|
|
obj->cur->clipper->cur->cache.clip.h);
|
|
|
|
|
2017-05-12 15:03:05 -07:00
|
|
|
ENFN->context_clip_set(ENC, ctx, x + off_x, y + off_y, w, h);
|
2013-07-04 19:09:03 -07:00
|
|
|
}
|
2015-10-06 01:36:29 -07:00
|
|
|
else if (evas->is_frozen)
|
|
|
|
{
|
|
|
|
/* can't trust cache.clip here - clip should be in ctx already */
|
|
|
|
}
|
2013-07-04 19:09:03 -07:00
|
|
|
else
|
|
|
|
{
|
|
|
|
//FIXME: Consider to clip by the proxy clipper.
|
|
|
|
if (proxy_render_data->eo_src != eo_obj)
|
|
|
|
{
|
|
|
|
x = obj->cur->clipper->cur->geometry.x + off_x;
|
|
|
|
y = obj->cur->clipper->cur->geometry.y + off_y;
|
|
|
|
w = obj->cur->clipper->cur->geometry.w;
|
|
|
|
h = obj->cur->clipper->cur->geometry.h;
|
2017-05-12 15:03:05 -07:00
|
|
|
ENFN->context_clip_clip(ENC, ctx, x, y, w, h);
|
2013-07-04 19:09:03 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-13 08:44:02 -07:00
|
|
|
static void
|
|
|
|
_evas_render_mapped_mask(Evas_Public_Data *evas, Evas_Object_Protected_Data *obj, Evas_Object_Protected_Data *mask,
|
|
|
|
Evas_Proxy_Render_Data *proxy_render_data, void *output, void *ctx, int off_x, int off_y, int level, Eina_Bool do_async)
|
|
|
|
{
|
|
|
|
if (!mask) return;
|
|
|
|
|
|
|
|
// This path can be hit when we're multiplying masks on top of each other...
|
|
|
|
Evas_Object_Protected_Data *prev_mask = obj->clip.prev_mask;
|
|
|
|
Eina_Bool redraw = mask->mask->redraw || !mask->mask->surface;
|
|
|
|
|
|
|
|
RD(level, " has mask: %s redraw:%d sfc:%p prev_mask:%p\n",
|
|
|
|
RDNAME(mask), mask->mask->redraw, mask->mask->surface, prev_mask);
|
|
|
|
if (prev_mask && !_mask_apply_inside_proxy(proxy_render_data, prev_mask))
|
|
|
|
{
|
|
|
|
RD(level, " discard prev mask and redraw (guessed outside proxy)\n");
|
|
|
|
prev_mask = NULL;
|
|
|
|
redraw = EINA_TRUE;
|
|
|
|
}
|
|
|
|
if (redraw)
|
|
|
|
evas_render_mask_subrender(evas, output, mask, prev_mask, level + 1, do_async);
|
|
|
|
|
|
|
|
if (mask->mask->surface)
|
|
|
|
{
|
2019-05-06 13:12:48 -07:00
|
|
|
Eina_Rectangle clip = _evas_render_smallest_static_clipped_geometry_get(mask->cur);
|
2019-05-13 08:44:02 -07:00
|
|
|
ENFN->context_clip_image_set(ENC, ctx, mask->mask->surface,
|
2019-05-06 13:12:48 -07:00
|
|
|
clip.x + off_x,
|
|
|
|
clip.y + off_y,
|
2019-05-13 08:44:02 -07:00
|
|
|
evas, do_async);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-20 07:40:28 -07:00
|
|
|
Eina_Bool
|
2015-09-02 20:11:52 -07:00
|
|
|
evas_render_mapped(Evas_Public_Data *evas, Evas_Object *eo_obj,
|
2012-10-18 04:30:04 -07:00
|
|
|
Evas_Object_Protected_Data *obj, void *context,
|
2017-08-25 10:52:38 -07:00
|
|
|
void *output, void *surface,
|
|
|
|
int off_x, int off_y, int mapped, int ecx,
|
2013-05-31 04:28:12 -07:00
|
|
|
int ecy, int ecw, int ech,
|
2014-11-04 21:54:35 -08:00
|
|
|
Evas_Proxy_Render_Data *proxy_render_data, int level,
|
2016-12-15 17:55:47 -08:00
|
|
|
Eina_Bool do_async)
|
2009-10-30 03:11:15 -07:00
|
|
|
{
|
2012-10-08 18:58:41 -07:00
|
|
|
Evas_Object_Protected_Data *obj2;
|
2010-05-05 04:36:21 -07:00
|
|
|
Eina_Bool clean_them = EINA_FALSE;
|
2013-05-06 06:18:08 -07:00
|
|
|
Eina_Bool proxy_src_clip = EINA_TRUE;
|
2017-07-19 22:35:48 -07:00
|
|
|
Eina_Bool was_pre_render_done = obj->pre_render_done;
|
2015-09-02 22:06:36 -07:00
|
|
|
void *ctx;
|
2009-11-15 05:46:20 -08:00
|
|
|
|
2013-05-31 04:28:12 -07:00
|
|
|
if (!proxy_render_data)
|
2013-04-29 05:05:33 -07:00
|
|
|
{
|
2015-09-03 01:38:48 -07:00
|
|
|
/* don't render if the source is invisible */
|
2013-04-29 05:05:33 -07:00
|
|
|
if ((evas_object_is_source_invisible(eo_obj, obj)))
|
2018-06-28 11:11:59 -07:00
|
|
|
return EINA_FALSE;
|
2013-04-29 05:05:33 -07:00
|
|
|
}
|
|
|
|
else
|
2013-05-31 04:28:12 -07:00
|
|
|
proxy_src_clip = proxy_render_data->source_clip;
|
2013-04-28 23:30:37 -07:00
|
|
|
|
2016-11-30 00:36:42 -08:00
|
|
|
evas_object_clip_recalc(obj);
|
2019-02-20 12:32:41 -08:00
|
|
|
_evas_object_gfx_mapping_update(obj);
|
2016-11-30 00:36:42 -08:00
|
|
|
|
2015-09-03 01:38:48 -07:00
|
|
|
/* leave early if clipper is not visible */
|
2016-11-26 19:02:12 -08:00
|
|
|
if ((obj->cur->clipper) && (!obj->cur->clipper->cur->visible))
|
2018-06-28 11:11:59 -07:00
|
|
|
return EINA_FALSE;
|
2015-09-03 01:38:48 -07:00
|
|
|
|
2016-11-06 18:26:22 -08:00
|
|
|
eina_evlog("+render_object", eo_obj, 0.0, NULL);
|
2015-01-26 00:35:42 -08:00
|
|
|
#ifdef REND_DBG
|
|
|
|
RD(level, "{\n");
|
2017-01-11 04:18:59 -08:00
|
|
|
RD(level, " evas_render_mapped(evas:%p, obj:%s, ctx:%p, sfc:%p, offset:%i,%i, %s, %s)\n",
|
|
|
|
evas->evas, RDNAME(obj), context, surface, off_x, off_y,
|
2016-12-15 17:55:47 -08:00
|
|
|
mapped ? "mapped" : "normal", do_async ? "async" : "sync");
|
2017-01-11 04:18:59 -08:00
|
|
|
IFRD(obj->is_smart, level, " is_smart");
|
|
|
|
IFRD(obj->is_frame, level, " in framespace%s", obj->is_frame_top ? " (top object)" : "");
|
2015-01-26 00:35:42 -08:00
|
|
|
if (obj->cur->clipper)
|
2013-08-19 00:35:34 -07:00
|
|
|
{
|
2017-01-11 04:18:59 -08:00
|
|
|
RD(level, " clipper: %s (mask: %s) %d,%d %dx%d ; color: {%d,%d,%d,%d} ; cached: {%d,%d,%d,%d}\n",
|
|
|
|
RDNAME(obj->cur->clipper), RDNAME(obj->clip.mask),
|
2015-01-26 00:35:42 -08:00
|
|
|
obj->cur->clipper->cur->geometry.x, obj->cur->clipper->cur->geometry.y,
|
2016-10-13 01:42:38 -07:00
|
|
|
obj->cur->clipper->cur->geometry.w, obj->cur->clipper->cur->geometry.h,
|
|
|
|
obj->cur->clipper->cur->color.r, obj->cur->clipper->cur->color.g,
|
|
|
|
obj->cur->clipper->cur->color.b, obj->cur->clipper->cur->color.a,
|
|
|
|
obj->cur->clipper->cur->cache.clip.r, obj->cur->clipper->cur->cache.clip.g,
|
|
|
|
obj->cur->clipper->cur->cache.clip.b, obj->cur->clipper->cur->cache.clip.a);
|
2013-08-19 00:35:34 -07:00
|
|
|
}
|
2015-09-01 04:47:40 -07:00
|
|
|
|
2016-10-13 01:42:38 -07:00
|
|
|
RD(level, " geom: %d,%d %dx%d, cache.clip: (vis: %d) %d,%d %dx%d ; color: {%d,%d,%d,%d} ; cached: {%d,%d,%d,%d}\n",
|
|
|
|
obj->cur->geometry.x, obj->cur->geometry.y, obj->cur->geometry.w, obj->cur->geometry.h, obj->cur->cache.clip.visible,
|
|
|
|
obj->cur->cache.clip.x, obj->cur->cache.clip.y, obj->cur->cache.clip.w, obj->cur->cache.clip.h,
|
|
|
|
obj->cur->color.r, obj->cur->color.g, obj->cur->color.b, obj->cur->color.a,
|
|
|
|
obj->cur->cache.clip.r, obj->cur->cache.clip.g, obj->cur->cache.clip.b, obj->cur->cache.clip.a);
|
2015-09-03 00:36:32 -07:00
|
|
|
{
|
2016-10-13 01:42:38 -07:00
|
|
|
int _cu, _cc, _cm, _cx, _cy, _cw, _ch, _cr, _cg, _cb, _ca, _cmr, _cmg, _cmb, _cma;
|
2017-05-12 15:03:05 -07:00
|
|
|
_cu = ENFN->context_clip_get(ENC, context, &_cx, &_cy, &_cw, &_ch);
|
|
|
|
_cc = ENFN->context_color_get(ENC, context, &_cr, &_cg, &_cb, &_ca);
|
|
|
|
_cm = ENFN->context_multiplier_get(ENC, context, &_cmr, &_cmg, &_cmb, &_cma);
|
2016-10-13 01:42:38 -07:00
|
|
|
RD(level, " context clip: [%d] %d,%d %dx%d ; color: [%d] {%d,%d,%d,%d} ; mult: [%d] {%d,%d,%d,%d}\n",
|
|
|
|
_cu, _cx, _cy, _cw, _ch, _cc, _cr, _cg, _cb, _ca, _cm, _cmr, _cmg, _cmb, _cma);
|
2015-09-03 00:36:32 -07:00
|
|
|
}
|
2015-01-26 00:35:42 -08:00
|
|
|
#endif
|
2013-04-26 04:05:46 -07:00
|
|
|
|
2009-11-09 07:18:37 -08:00
|
|
|
if (mapped)
|
|
|
|
{
|
2015-02-02 22:38:50 -08:00
|
|
|
if (_evas_render_object_is_mask(obj))
|
2014-11-12 17:47:29 -08:00
|
|
|
{
|
2015-01-26 00:35:42 -08:00
|
|
|
RD(level, " is mask: redraw:%d sfc:%p\n", obj->mask->redraw, obj->mask->surface);
|
2016-12-15 17:55:47 -08:00
|
|
|
if (surface != obj->mask->surface)
|
2015-02-02 22:38:50 -08:00
|
|
|
{
|
2015-09-01 04:47:40 -07:00
|
|
|
RD(level, " not rendering mask surface\n");
|
2015-01-26 00:35:42 -08:00
|
|
|
RD(level, "}\n");
|
2016-11-06 18:26:22 -08:00
|
|
|
eina_evlog("-render_object", eo_obj, 0.0, NULL);
|
2018-06-28 11:11:59 -07:00
|
|
|
return EINA_FALSE;
|
2015-02-02 22:38:50 -08:00
|
|
|
}
|
|
|
|
// else don't return: draw mask in its surface
|
2014-11-12 17:47:29 -08:00
|
|
|
}
|
|
|
|
else if (proxy_src_clip)
|
2009-11-15 05:46:20 -08:00
|
|
|
{
|
2015-10-06 01:36:29 -07:00
|
|
|
if (!evas->is_frozen) /* same as "if (proxy_render_data)" */
|
2013-04-25 22:45:41 -07:00
|
|
|
{
|
2019-05-29 12:36:53 -07:00
|
|
|
if ((!evas_object_is_visible(obj)) || (obj->clip.clipees)
|
2015-10-06 01:36:29 -07:00
|
|
|
|| (obj->cur->have_clipees) || (obj->no_render))
|
|
|
|
{
|
|
|
|
IFRD(obj->no_render, level, " no_render\n");
|
|
|
|
IFRD(obj->clip.clipees || obj->cur->have_clipees, level, " has clippees\n");
|
2019-05-29 12:36:53 -07:00
|
|
|
IFRD(!evas_object_is_visible(obj), level, " not visible\n");
|
2015-10-06 01:36:29 -07:00
|
|
|
RD(level, "}\n");
|
2016-11-06 18:26:22 -08:00
|
|
|
eina_evlog("-render_object", eo_obj, 0.0, NULL);
|
2018-06-28 11:11:59 -07:00
|
|
|
return EINA_FALSE;
|
2015-10-06 01:36:29 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* can not trust cache.clip - evas is frozen */
|
2015-11-01 19:23:00 -08:00
|
|
|
if (!obj->cur->visible || obj->clip.clipees || (obj->no_render && !proxy_render_data) ||
|
2015-10-06 01:36:29 -07:00
|
|
|
(!obj->cur->color.a && (obj->cur->render_op == EVAS_RENDER_BLEND)))
|
|
|
|
{
|
|
|
|
IFRD(obj->no_render, level, " proxy_src_clip + no_render\n");
|
|
|
|
IFRD(obj->clip.clipees || obj->cur->have_clipees, level, " proxy_src_clip + has clippees\n");
|
|
|
|
IFRD(!obj->cur->visible, level, " proxy_src_clip + not visible\n");
|
|
|
|
IFRD(!obj->cur->color.a && (obj->cur->render_op == EVAS_RENDER_BLEND), level, " proxy_src_clip + 0 alpha\n");
|
|
|
|
RD(level, "}\n");
|
2016-11-06 18:26:22 -08:00
|
|
|
eina_evlog("-render_object", eo_obj, 0.0, NULL);
|
2018-06-28 11:11:59 -07:00
|
|
|
return EINA_FALSE;
|
2015-10-06 01:36:29 -07:00
|
|
|
}
|
2016-07-04 00:06:04 -07:00
|
|
|
else if (proxy_render_data && (surface != obj->proxy->surface) &&
|
|
|
|
obj->proxy->src_invisible)
|
|
|
|
{
|
|
|
|
RD(level, " src_invisible + not proxy surface (recursive proxies)\n");
|
|
|
|
RD(level, "}\n");
|
2016-11-06 18:26:22 -08:00
|
|
|
eina_evlog("-render_object", eo_obj, 0.0, NULL);
|
2018-06-28 11:11:59 -07:00
|
|
|
return EINA_FALSE;
|
2016-07-04 00:06:04 -07:00
|
|
|
}
|
2013-04-25 22:45:41 -07:00
|
|
|
}
|
2013-04-26 04:05:46 -07:00
|
|
|
}
|
2019-05-29 12:36:59 -07:00
|
|
|
else if (!evas_object_is_proxy_visible(obj) ||
|
2013-07-28 04:24:46 -07:00
|
|
|
(obj->clip.clipees) || (obj->cur->have_clipees))
|
2015-05-12 01:37:01 -07:00
|
|
|
{
|
2019-05-29 12:36:59 -07:00
|
|
|
IFRD(!evas_object_is_proxy_visible(obj), level, " proxy not visible\n");
|
2015-09-01 04:47:40 -07:00
|
|
|
IFRD(obj->clip.clipees || obj->cur->have_clipees, level, " has clippees\n");
|
2015-05-12 01:37:01 -07:00
|
|
|
RD(level, "}\n");
|
2016-11-06 18:26:22 -08:00
|
|
|
eina_evlog("-render_object", eo_obj, 0.0, NULL);
|
2018-06-28 11:11:59 -07:00
|
|
|
return EINA_FALSE;
|
2015-05-12 01:37:01 -07:00
|
|
|
}
|
2016-12-15 17:55:47 -08:00
|
|
|
else if (obj->no_render && (surface != obj->proxy->surface))
|
2015-05-12 01:37:01 -07:00
|
|
|
{
|
2015-09-01 04:47:40 -07:00
|
|
|
RD(level, " no_render\n");
|
|
|
|
RD(level, "}\n");
|
2016-11-06 18:26:22 -08:00
|
|
|
eina_evlog("-render_object", eo_obj, 0.0, NULL);
|
2018-06-28 11:11:59 -07:00
|
|
|
return EINA_FALSE;
|
2009-11-15 05:46:20 -08:00
|
|
|
}
|
2009-11-09 07:18:37 -08:00
|
|
|
}
|
2013-04-26 04:05:46 -07:00
|
|
|
else if (!(((evas_object_is_active(eo_obj, obj) && (!obj->clip.clipees) &&
|
2019-05-29 12:36:53 -07:00
|
|
|
(_evas_render_can_render(obj))))
|
2013-04-26 04:05:46 -07:00
|
|
|
))
|
2009-11-15 05:46:20 -08:00
|
|
|
{
|
2015-09-01 04:47:40 -07:00
|
|
|
IFRD(!evas_object_is_active(eo_obj, obj), level, " not active\n");
|
2019-05-29 12:36:53 -07:00
|
|
|
IFRD(!_evas_render_can_render(obj), level, " can't render\n");
|
2015-09-01 04:47:40 -07:00
|
|
|
IFRD(obj->clip.clipees, level, " has clippees\n");
|
2015-01-26 00:35:42 -08:00
|
|
|
RD(level, "}\n");
|
2016-11-06 18:26:22 -08:00
|
|
|
eina_evlog("-render_object", eo_obj, 0.0, NULL);
|
2018-06-28 11:11:59 -07:00
|
|
|
return EINA_FALSE;
|
2009-11-15 05:46:20 -08:00
|
|
|
}
|
2010-04-27 06:43:10 -07:00
|
|
|
|
2009-11-23 02:07:07 -08:00
|
|
|
// set render_pre - for child objs that may not have gotten it.
|
2013-09-02 20:39:49 -07:00
|
|
|
obj->pre_render_done = EINA_TRUE;
|
2016-01-06 04:52:46 -08:00
|
|
|
RD(level, " hasmap: %s [can_map: %d] cur.map:%p cur.usemap:%d\n",
|
|
|
|
_evas_render_has_map(obj) ? "yes" : "no",
|
2012-10-08 18:58:41 -07:00
|
|
|
obj->func->can_map ? obj->func->can_map(eo_obj): -1,
|
2015-01-26 00:35:42 -08:00
|
|
|
obj->map->cur.map, obj->map->cur.usemap);
|
2016-01-06 04:52:46 -08:00
|
|
|
if (_evas_render_has_map(obj) && !_evas_render_can_map(obj))
|
2009-10-30 03:11:15 -07:00
|
|
|
{
|
2009-10-31 02:08:01 -07:00
|
|
|
int sw, sh;
|
2017-09-27 01:28:59 -07:00
|
|
|
Eina_Bool changed = EINA_FALSE, rendered = EINA_FALSE, pchanged = EINA_FALSE;
|
2010-04-27 06:43:10 -07:00
|
|
|
|
2011-05-20 23:23:33 -07:00
|
|
|
clean_them = EINA_TRUE;
|
2010-05-05 04:36:21 -07:00
|
|
|
|
2013-03-12 05:58:19 -07:00
|
|
|
sw = obj->cur->geometry.w;
|
|
|
|
sh = obj->cur->geometry.h;
|
2015-01-26 00:35:42 -08:00
|
|
|
RD(level, " surf size: %ix%i\n", sw, sh);
|
2017-07-19 22:35:48 -07:00
|
|
|
if ((sw <= 0) || (sh <= 0)) goto end;
|
2014-01-05 20:54:58 -08:00
|
|
|
|
2017-09-27 01:28:59 -07:00
|
|
|
pchanged = evas_object_map_update(eo_obj, off_x, off_y, sw, sh, sw, sh);
|
2010-04-27 06:43:10 -07:00
|
|
|
|
2013-01-21 19:56:00 -08:00
|
|
|
if (obj->map->surface)
|
2009-10-31 02:08:01 -07:00
|
|
|
{
|
2013-01-21 19:56:00 -08:00
|
|
|
if ((obj->map->surface_w != sw) ||
|
|
|
|
(obj->map->surface_h != sh))
|
2009-10-31 02:08:01 -07:00
|
|
|
{
|
2015-01-26 00:35:42 -08:00
|
|
|
RD(level, " new surf: %ix%i\n", sw, sh);
|
2016-12-06 01:56:07 -08:00
|
|
|
EINA_COW_WRITE_BEGIN(evas_object_map_cow, obj->map, Evas_Object_Map_Data, map_write)
|
|
|
|
{
|
2017-04-24 15:09:25 -07:00
|
|
|
ENFN->image_free(ENC, map_write->surface);
|
2016-12-06 01:56:07 -08:00
|
|
|
map_write->surface = NULL;
|
|
|
|
}
|
|
|
|
EINA_COW_WRITE_END(evas_object_map_cow, obj->map, map_write);
|
2009-10-31 02:08:01 -07:00
|
|
|
}
|
|
|
|
}
|
2013-01-21 19:56:00 -08:00
|
|
|
if (!obj->map->surface)
|
2009-10-31 02:08:01 -07:00
|
|
|
{
|
2013-01-21 19:56:00 -08:00
|
|
|
EINA_COW_WRITE_BEGIN(evas_object_map_cow, obj->map, Evas_Object_Map_Data, map_write)
|
|
|
|
{
|
|
|
|
map_write->surface_w = sw;
|
|
|
|
map_write->surface_h = sh;
|
|
|
|
|
2015-09-02 20:11:52 -07:00
|
|
|
map_write->surface = ENFN->image_map_surface_new
|
2017-04-24 15:09:25 -07:00
|
|
|
(ENC, map_write->surface_w,
|
2015-09-02 20:11:52 -07:00
|
|
|
map_write->surface_h,
|
|
|
|
map_write->cur.map->alpha);
|
2013-01-21 19:56:00 -08:00
|
|
|
}
|
|
|
|
EINA_COW_WRITE_END(evas_object_map_cow, obj->map, map_write);
|
|
|
|
|
2015-01-26 00:35:42 -08:00
|
|
|
RD(level, " first surf: %ix%i\n", sw, sh);
|
2012-05-16 06:21:37 -07:00
|
|
|
changed = EINA_TRUE;
|
2009-10-31 02:08:01 -07:00
|
|
|
}
|
2013-05-05 19:03:11 -07:00
|
|
|
|
2018-10-24 16:29:48 -07:00
|
|
|
if (!changed) changed = evas_object_smart_changed_get(obj);
|
2010-04-27 06:43:10 -07:00
|
|
|
|
2012-08-23 12:58:02 -07:00
|
|
|
/* mark the old map as invalid, so later we don't reuse it as a
|
|
|
|
* cache. */
|
2017-09-27 01:28:59 -07:00
|
|
|
if (pchanged && obj->map->prev.map)
|
2013-01-21 19:56:00 -08:00
|
|
|
{
|
|
|
|
EINA_COW_WRITE_BEGIN(evas_object_map_cow, obj->map, Evas_Object_Map_Data, map_write)
|
|
|
|
map_write->prev.valid_map = EINA_FALSE;
|
|
|
|
EINA_COW_WRITE_END(evas_object_map_cow, obj->map, map_write);
|
|
|
|
}
|
2012-08-23 12:58:02 -07:00
|
|
|
|
2009-10-31 02:08:01 -07:00
|
|
|
// clear surface before re-render
|
2013-01-21 19:56:00 -08:00
|
|
|
if ((changed) && (obj->map->surface))
|
2009-10-30 03:11:15 -07:00
|
|
|
{
|
2010-09-01 15:45:30 -07:00
|
|
|
int off_x2, off_y2;
|
2011-05-20 23:23:33 -07:00
|
|
|
|
2015-01-26 00:35:42 -08:00
|
|
|
RD(level, " children redraw\n");
|
2009-11-09 07:18:37 -08:00
|
|
|
// FIXME: calculate "changes" within map surface and only clear
|
|
|
|
// and re-render those
|
2013-01-21 19:56:00 -08:00
|
|
|
if (obj->map->cur.map->alpha)
|
2009-10-31 18:32:23 -07:00
|
|
|
{
|
2017-05-12 15:03:05 -07:00
|
|
|
ctx = ENFN->context_new(ENC);
|
|
|
|
ENFN->context_color_set(ENC, ctx, 0, 0, 0, 0);
|
|
|
|
ENFN->context_render_op_set(ENC, ctx, EVAS_RENDER_COPY);
|
2017-08-25 10:52:38 -07:00
|
|
|
ENFN->rectangle_draw(ENC, output, ctx, obj->map->surface,
|
2015-09-02 20:11:52 -07:00
|
|
|
0, 0, obj->map->surface_w, obj->map->surface_h,
|
|
|
|
EINA_FALSE);
|
2017-05-12 15:03:05 -07:00
|
|
|
ENFN->context_free(ENC, ctx);
|
2009-10-31 18:32:23 -07:00
|
|
|
}
|
2017-05-12 15:03:05 -07:00
|
|
|
ctx = ENFN->context_new(ENC);
|
2013-03-12 05:58:19 -07:00
|
|
|
off_x2 = -obj->cur->geometry.x;
|
|
|
|
off_y2 = -obj->cur->geometry.y;
|
2012-10-08 18:58:41 -07:00
|
|
|
if (obj->is_smart)
|
2009-10-31 02:08:01 -07:00
|
|
|
{
|
|
|
|
EINA_INLIST_FOREACH
|
2012-10-08 18:58:41 -07:00
|
|
|
(evas_object_smart_members_get_direct(eo_obj), obj2)
|
2011-05-20 23:23:33 -07:00
|
|
|
{
|
2015-09-02 20:11:52 -07:00
|
|
|
clean_them |= evas_render_mapped(evas, obj2->object,
|
2012-10-18 04:30:04 -07:00
|
|
|
obj2, ctx,
|
2017-08-25 10:52:38 -07:00
|
|
|
output, obj->map->surface,
|
2011-05-20 23:23:33 -07:00
|
|
|
off_x2, off_y2, 1,
|
2012-10-18 04:30:04 -07:00
|
|
|
ecx, ecy, ecw, ech,
|
2014-11-04 21:54:35 -08:00
|
|
|
proxy_render_data,
|
2016-12-15 17:55:47 -08:00
|
|
|
level + 1, do_async);
|
2014-03-31 22:08:14 -07:00
|
|
|
/* We aren't sure this object will be rendered by
|
|
|
|
normal(not proxy) drawing after, we reset this
|
|
|
|
only in case of normal drawing. For optmizing,
|
2016-11-21 21:33:48 -08:00
|
|
|
push this object in an array then reset them
|
2014-03-31 22:08:14 -07:00
|
|
|
in the end of the rendering.*/
|
|
|
|
if (!proxy_render_data)
|
2017-02-03 18:31:55 -08:00
|
|
|
evas_object_change_reset(obj2);
|
2011-05-20 23:23:33 -07:00
|
|
|
}
|
2009-10-31 02:08:01 -07:00
|
|
|
}
|
|
|
|
else
|
2010-04-28 07:38:46 -07:00
|
|
|
{
|
|
|
|
int x = 0, y = 0, w = 0, h = 0;
|
2010-05-01 06:27:05 -07:00
|
|
|
|
2013-01-21 19:56:00 -08:00
|
|
|
w = obj->map->surface_w;
|
|
|
|
h = obj->map->surface_h;
|
2010-04-28 07:38:46 -07:00
|
|
|
RECTS_CLIP_TO_RECT(x, y, w, h,
|
2013-03-12 05:58:19 -07:00
|
|
|
obj->cur->geometry.x + off_x2,
|
|
|
|
obj->cur->geometry.y + off_y2,
|
|
|
|
obj->cur->geometry.w,
|
|
|
|
obj->cur->geometry.h);
|
2011-03-15 09:20:57 -07:00
|
|
|
|
2017-05-12 15:03:05 -07:00
|
|
|
ENFN->context_clip_set(ENC, ctx, x, y, w, h);
|
2015-09-03 00:36:32 -07:00
|
|
|
#ifdef REND_DBG
|
|
|
|
int _c, _cx, _cy, _cw, _ch;
|
2017-05-12 15:03:05 -07:00
|
|
|
_c = ENFN->context_clip_get(ENC, ctx, &_cx, &_cy, &_cw, &_ch);
|
2015-09-03 00:36:32 -07:00
|
|
|
RD(level, " draw mapped obj: render(clip: [%d] %d,%d %dx%d)\n", _c, _cx, _cy, _cw, _ch);
|
|
|
|
#endif
|
2016-01-06 04:52:46 -08:00
|
|
|
// FIXME: Should this really be sync render?
|
2013-07-08 17:46:15 -07:00
|
|
|
obj->func->render(eo_obj, obj, obj->private_data,
|
2017-08-25 10:52:38 -07:00
|
|
|
ENC, output, ctx,
|
2013-01-21 19:56:00 -08:00
|
|
|
obj->map->surface, off_x2, off_y2,
|
2012-12-18 08:28:55 -08:00
|
|
|
EINA_FALSE);
|
2010-04-28 07:38:46 -07:00
|
|
|
}
|
2017-05-12 15:03:05 -07:00
|
|
|
ENFN->context_free(ENC, ctx);
|
2012-05-16 06:21:37 -07:00
|
|
|
rendered = EINA_TRUE;
|
2009-10-31 02:08:01 -07:00
|
|
|
}
|
|
|
|
|
2010-04-30 01:24:55 -07:00
|
|
|
if (rendered)
|
|
|
|
{
|
2013-01-21 19:56:00 -08:00
|
|
|
EINA_COW_WRITE_BEGIN(evas_object_map_cow, obj->map, Evas_Object_Map_Data, map_write)
|
|
|
|
{
|
2015-09-02 20:11:52 -07:00
|
|
|
map_write->surface = ENFN->image_dirty_region
|
2017-08-25 10:51:10 -07:00
|
|
|
(ENC, map_write->surface,
|
2013-01-21 19:56:00 -08:00
|
|
|
0, 0, map_write->surface_w, map_write->surface_h);
|
|
|
|
|
|
|
|
map_write->cur.valid_map = EINA_TRUE;
|
|
|
|
}
|
|
|
|
EINA_COW_WRITE_END(evas_object_map_cow, obj->map, map_write);
|
2010-04-30 01:24:55 -07:00
|
|
|
}
|
2015-09-02 22:06:36 -07:00
|
|
|
|
|
|
|
/* duplicate context and reset clip */
|
evas: "fix" masks of masks inside a proxy
Here's the situation:
1. A container (genlist) has a mask, M0.
2. An item I0 inside this container uses a proxy P0 as render object
rather than the item directly (eg. for zooming in/out).
3. An element E0 inside this item has another mask, M1.
Theory:
1. The proxy surface for P0 is rendered, and M1 is applied to
the element E0.
2. The proxy P0 is rendered on the canvas, with M0 applied.
Practice:
1. The element E0 is prepared for rendering, this triggers
a mask subrender for M1.
2. M1 is rendered with M0 as a prev mask, then kept in cache and
not redrawn (no geometry change, etc...)
3. When P0's surface is rendered, M1's surface is the result of M1+M0.
4. When P0 is drawn on screen, we can see the effect of M1+M0 as
P0's geometry might be different from the item's I0.
Solution:
Discard prev masks and force a mask redraw when we're inside a
proxy. Ideally we should detect if the prev mask belongs to the
insides of the proxy or not.
Problems:
_mask_apply_inside_proxy() is definitely not correct, but it's
not easy to test it. Anyway I believe that in order to properly
implement all of this, we need to rethink evas_render and
the draw context. Non-primary render surfaces (maps, proxies,
masks, filters, ...) should be rendered with a clean context
and clipping, masking, etc should be computed appropriately.
2016-12-15 18:19:17 -08:00
|
|
|
// FIXME: Shouldn't we use a new, clean context?
|
2017-05-12 15:03:05 -07:00
|
|
|
ctx = ENFN->context_dup(ENC, context);
|
|
|
|
ENFN->context_clip_unset(ENC, ctx);
|
|
|
|
//ENFN->context_multiplier_unset(ENC, ctx); // this probably should be here, too
|
2015-09-02 22:06:36 -07:00
|
|
|
|
2013-01-21 19:56:00 -08:00
|
|
|
if (obj->map->surface)
|
2010-09-01 15:45:30 -07:00
|
|
|
{
|
2016-11-07 23:22:22 -08:00
|
|
|
Evas_Object_Protected_Data *mask = obj->clip.mask;
|
|
|
|
|
2013-03-12 05:58:19 -07:00
|
|
|
if (obj->cur->clipper)
|
2010-09-01 15:45:30 -07:00
|
|
|
{
|
2016-11-30 00:36:42 -08:00
|
|
|
evas_object_clip_recalc(obj);
|
|
|
|
|
2012-10-08 18:58:41 -07:00
|
|
|
if (obj->is_smart)
|
2010-10-11 02:53:52 -07:00
|
|
|
{
|
2013-07-04 19:14:47 -07:00
|
|
|
EINA_COW_STATE_WRITE_BEGIN(obj, state_write, cur)
|
|
|
|
{
|
|
|
|
state_write->cache.clip.dirty = EINA_TRUE;
|
|
|
|
}
|
|
|
|
EINA_COW_STATE_WRITE_END(obj, state_write, cur);
|
2010-10-11 02:53:52 -07:00
|
|
|
}
|
2015-09-02 22:06:36 -07:00
|
|
|
_evas_render_mapped_context_clip_set(evas, eo_obj, obj, ctx,
|
2013-07-04 19:14:47 -07:00
|
|
|
proxy_render_data, off_x,
|
|
|
|
off_y);
|
2015-02-04 23:11:45 -08:00
|
|
|
|
|
|
|
/* Clipper masks */
|
2019-05-13 08:44:02 -07:00
|
|
|
_evas_render_mapped_mask(evas, obj, mask, proxy_render_data, output, ctx, off_x, off_y, level, do_async);
|
2010-09-01 15:45:30 -07:00
|
|
|
}
|
2016-09-07 18:26:30 -07:00
|
|
|
|
2016-12-06 01:56:07 -08:00
|
|
|
if (obj->cur->cache.clip.visible || !proxy_src_clip)
|
|
|
|
{
|
2017-03-01 22:53:03 -08:00
|
|
|
if (!mapped)
|
|
|
|
{
|
2017-05-12 15:03:05 -07:00
|
|
|
ENFN->context_clip_clip(ENC, ctx, ecx, ecy, ecw, ech);
|
2017-03-01 22:53:03 -08:00
|
|
|
if (!_is_obj_in_framespace(obj, evas))
|
|
|
|
{
|
|
|
|
_evas_render_framespace_context_clip_clip
|
|
|
|
(evas, ctx, off_x - evas->framespace.x, off_y - evas->framespace.y);
|
|
|
|
}
|
|
|
|
}
|
2017-05-12 15:03:05 -07:00
|
|
|
ENFN->context_multiplier_unset(ENC, ctx);
|
|
|
|
ENFN->context_render_op_set(ENC, ctx, obj->cur->render_op);
|
2015-09-03 00:36:32 -07:00
|
|
|
#ifdef REND_DBG
|
2016-12-06 01:56:07 -08:00
|
|
|
int _c, _cx, _cy, _cw, _ch;
|
2017-05-12 15:03:05 -07:00
|
|
|
_c = ENFN->context_clip_get(ENC, ctx, &_cx, &_cy, &_cw, &_ch);
|
2016-12-06 01:56:07 -08:00
|
|
|
RD(level, " draw image map(clip: [%d] %d,%d %dx%d)\n", _c, _cx, _cy, _cw, _ch);
|
2015-09-03 00:36:32 -07:00
|
|
|
#endif
|
2016-12-06 01:56:07 -08:00
|
|
|
evas_draw_image_map_async_check
|
2017-08-25 10:52:38 -07:00
|
|
|
(obj, ENC, output, ctx, surface,
|
2017-05-12 15:03:05 -07:00
|
|
|
obj->map->surface, obj->map->spans,
|
|
|
|
obj->map->cur.map->smooth, 0, do_async);
|
2016-12-06 01:56:07 -08:00
|
|
|
}
|
2012-03-20 21:04:03 -07:00
|
|
|
}
|
2015-02-04 23:11:45 -08:00
|
|
|
|
2017-08-25 10:51:05 -07:00
|
|
|
ENFN->context_free(ENC, ctx);
|
2015-02-04 23:11:45 -08:00
|
|
|
|
2009-10-30 03:11:15 -07:00
|
|
|
// FIXME: needs to cache these maps and
|
|
|
|
// keep them only rendering updates
|
|
|
|
}
|
2015-01-26 00:35:42 -08:00
|
|
|
else // not "has map"
|
2009-11-06 21:01:43 -08:00
|
|
|
{
|
2017-08-25 10:51:05 -07:00
|
|
|
ctx = ENFN->context_dup(ENC, context);
|
2009-11-06 21:01:43 -08:00
|
|
|
if (mapped)
|
|
|
|
{
|
2015-09-03 00:36:32 -07:00
|
|
|
RD(level, " child of mapped obj\n");
|
2015-01-26 00:35:42 -08:00
|
|
|
|
2012-10-08 18:58:41 -07:00
|
|
|
if (obj->is_smart)
|
2009-11-06 21:01:43 -08:00
|
|
|
{
|
2015-01-26 00:52:38 -08:00
|
|
|
/* Clipper masks */
|
2015-04-14 00:20:00 -07:00
|
|
|
if (obj->cur->clipper && (mapped > 1) &&
|
2015-01-26 00:52:38 -08:00
|
|
|
_evas_render_object_is_mask(obj->cur->clipper))
|
2019-05-13 08:44:02 -07:00
|
|
|
_evas_render_mapped_mask(evas, obj, obj->cur->clipper, proxy_render_data, output, ctx, off_x, off_y, level, do_async);
|
2019-05-23 06:31:42 -07:00
|
|
|
else if (!proxy_src_clip && proxy_render_data)
|
2015-09-03 01:38:48 -07:00
|
|
|
{
|
2020-02-11 04:44:52 -08:00
|
|
|
if (!_proxy_context_clip(evas, ctx, proxy_render_data, obj, off_x, off_y))
|
evas: "fix" masks of masks inside a proxy
Here's the situation:
1. A container (genlist) has a mask, M0.
2. An item I0 inside this container uses a proxy P0 as render object
rather than the item directly (eg. for zooming in/out).
3. An element E0 inside this item has another mask, M1.
Theory:
1. The proxy surface for P0 is rendered, and M1 is applied to
the element E0.
2. The proxy P0 is rendered on the canvas, with M0 applied.
Practice:
1. The element E0 is prepared for rendering, this triggers
a mask subrender for M1.
2. M1 is rendered with M0 as a prev mask, then kept in cache and
not redrawn (no geometry change, etc...)
3. When P0's surface is rendered, M1's surface is the result of M1+M0.
4. When P0 is drawn on screen, we can see the effect of M1+M0 as
P0's geometry might be different from the item's I0.
Solution:
Discard prev masks and force a mask redraw when we're inside a
proxy. Ideally we should detect if the prev mask belongs to the
insides of the proxy or not.
Problems:
_mask_apply_inside_proxy() is definitely not correct, but it's
not easy to test it. Anyway I believe that in order to properly
implement all of this, we need to rethink evas_render and
the draw context. Non-primary render surfaces (maps, proxies,
masks, filters, ...) should be rendered with a clean context
and clipping, masking, etc should be computed appropriately.
2016-12-15 18:19:17 -08:00
|
|
|
goto on_empty_clip;
|
2015-09-03 01:38:48 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef REND_DBG
|
|
|
|
int _c, _cx, _cy, _cw, _ch;
|
2017-08-25 10:51:05 -07:00
|
|
|
_c = ENFN->context_clip_get(ENC, ctx, &_cx, &_cy, &_cw, &_ch);
|
2015-09-03 01:38:48 -07:00
|
|
|
RD(level, " draw smart children(clip: [%d] %d,%d %dx%d)\n",
|
|
|
|
_c, _cx, _cy, _cw, _ch);
|
|
|
|
#endif
|
2015-01-26 00:52:38 -08:00
|
|
|
|
2009-11-06 21:01:43 -08:00
|
|
|
EINA_INLIST_FOREACH
|
2012-10-08 18:58:41 -07:00
|
|
|
(evas_object_smart_members_get_direct(eo_obj), obj2)
|
2011-05-20 23:23:33 -07:00
|
|
|
{
|
2020-01-21 02:28:59 -08:00
|
|
|
/* skip proxy object if its source is its smart parent.
|
|
|
|
who makes this relation? a proxy object working for
|
|
|
|
a smart object to set a filter program. the proxy
|
|
|
|
object should be a member of smart object to sync
|
|
|
|
stacking changes. */
|
|
|
|
if (obj2->is_filter_object) continue;
|
|
|
|
|
2015-09-02 20:11:52 -07:00
|
|
|
clean_them |= evas_render_mapped(evas, obj2->object,
|
2017-08-25 10:52:38 -07:00
|
|
|
obj2, ctx,
|
|
|
|
output, surface,
|
2015-04-14 00:20:00 -07:00
|
|
|
off_x, off_y, mapped + 1,
|
2012-10-18 04:30:04 -07:00
|
|
|
ecx, ecy, ecw, ech,
|
2014-11-04 21:54:35 -08:00
|
|
|
proxy_render_data,
|
2016-12-15 17:55:47 -08:00
|
|
|
level + 1, do_async);
|
2014-03-31 22:08:14 -07:00
|
|
|
/* We aren't sure this object will be rendered by
|
|
|
|
normal(not proxy) drawing after, we reset this
|
|
|
|
only in case of normal drawing. For optmizing,
|
2015-01-26 00:35:42 -08:00
|
|
|
push this object in an array then reset them
|
2014-03-31 22:08:14 -07:00
|
|
|
in the end of the rendering.*/
|
|
|
|
if (!proxy_render_data)
|
2017-02-03 18:31:55 -08:00
|
|
|
evas_object_change_reset(obj2);
|
2011-05-20 23:23:33 -07:00
|
|
|
}
|
2009-11-06 21:01:43 -08:00
|
|
|
}
|
|
|
|
else
|
2010-08-24 01:14:46 -07:00
|
|
|
{
|
2017-09-13 00:38:33 -07:00
|
|
|
const Eina_Rectangle *clip = &obj->cur->geometry;
|
2017-08-25 10:51:05 -07:00
|
|
|
ENFN->context_clip_clip(ENC, ctx, clip->x + off_x, clip->y + off_y, clip->w, clip->h);
|
2015-09-03 01:38:48 -07:00
|
|
|
|
2015-04-14 00:20:00 -07:00
|
|
|
if (obj->cur->clipper && (mapped > 1))
|
2012-08-16 23:02:49 -07:00
|
|
|
{
|
2016-11-07 23:22:22 -08:00
|
|
|
Evas_Object_Protected_Data *mask = obj->clip.mask;
|
|
|
|
|
|
|
|
if (obj->mask->surface != surface)
|
2015-09-03 01:38:48 -07:00
|
|
|
{
|
2016-11-07 23:22:22 -08:00
|
|
|
if (proxy_src_clip)
|
|
|
|
{
|
2016-11-30 00:36:42 -08:00
|
|
|
if ((_evas_render_has_map(obj) && !_evas_render_can_map(obj)) ||
|
|
|
|
_evas_render_object_is_mask(obj->cur->clipper))
|
|
|
|
evas_object_clip_recalc(obj);
|
2020-02-20 04:20:09 -08:00
|
|
|
_evas_render_mapped_context_clip_set(evas, eo_obj, obj, ctx,
|
|
|
|
proxy_render_data,
|
|
|
|
off_x, off_y);
|
2016-11-07 23:22:22 -08:00
|
|
|
}
|
2019-05-23 06:31:42 -07:00
|
|
|
else if (proxy_render_data)
|
2016-11-07 23:22:22 -08:00
|
|
|
{
|
2020-02-11 04:44:52 -08:00
|
|
|
if (!_proxy_context_clip(evas, ctx, proxy_render_data, obj, off_x, off_y))
|
evas: "fix" masks of masks inside a proxy
Here's the situation:
1. A container (genlist) has a mask, M0.
2. An item I0 inside this container uses a proxy P0 as render object
rather than the item directly (eg. for zooming in/out).
3. An element E0 inside this item has another mask, M1.
Theory:
1. The proxy surface for P0 is rendered, and M1 is applied to
the element E0.
2. The proxy P0 is rendered on the canvas, with M0 applied.
Practice:
1. The element E0 is prepared for rendering, this triggers
a mask subrender for M1.
2. M1 is rendered with M0 as a prev mask, then kept in cache and
not redrawn (no geometry change, etc...)
3. When P0's surface is rendered, M1's surface is the result of M1+M0.
4. When P0 is drawn on screen, we can see the effect of M1+M0 as
P0's geometry might be different from the item's I0.
Solution:
Discard prev masks and force a mask redraw when we're inside a
proxy. Ideally we should detect if the prev mask belongs to the
insides of the proxy or not.
Problems:
_mask_apply_inside_proxy() is definitely not correct, but it's
not easy to test it. Anyway I believe that in order to properly
implement all of this, we need to rethink evas_render and
the draw context. Non-primary render surfaces (maps, proxies,
masks, filters, ...) should be rendered with a clean context
and clipping, masking, etc should be computed appropriately.
2016-12-15 18:19:17 -08:00
|
|
|
goto on_empty_clip;
|
2016-11-07 23:22:22 -08:00
|
|
|
}
|
2015-09-03 01:38:48 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-11-07 23:22:22 -08:00
|
|
|
// rendering a mask in its own surface:
|
|
|
|
// we want to render it fully and clip only at
|
|
|
|
// clippee (maskee) render time
|
|
|
|
RD(level, " draw mask\n");
|
2015-09-03 01:38:48 -07:00
|
|
|
}
|
2014-11-12 17:47:29 -08:00
|
|
|
|
|
|
|
/* Clipper masks */
|
2019-05-13 08:44:02 -07:00
|
|
|
_evas_render_mapped_mask(evas, obj, mask, proxy_render_data, output, ctx, off_x, off_y, level, do_async);
|
2010-09-25 07:30:02 -07:00
|
|
|
}
|
2015-09-03 01:38:48 -07:00
|
|
|
|
2015-09-03 00:36:32 -07:00
|
|
|
#ifdef REND_DBG
|
|
|
|
int _c, _cx, _cy, _cw, _ch;
|
2017-08-25 10:51:05 -07:00
|
|
|
_c = ENFN->context_clip_get(ENC, ctx, &_cx, &_cy, &_cw, &_ch);
|
2015-09-03 00:36:32 -07:00
|
|
|
RD(level, " render(clip: [%d] %d,%d %dx%d)\n", _c, _cx, _cy, _cw, _ch);
|
|
|
|
#endif
|
2015-09-03 01:38:48 -07:00
|
|
|
|
2013-07-08 17:46:15 -07:00
|
|
|
obj->func->render(eo_obj, obj, obj->private_data,
|
evas_render: use do_async for mapped child (SW)
Summary:
On the SW engine, the rendering has inconsistent between smart object and
non-smart object, if they are mapped children. The smart object does ASYNC
render while the non-smart object does SYNC render. Because of this there
is a filckering rendering problem.
[Problem]
The following is a case of problems.
elm_layout (mapped, map_surface_1)
│
├─ elm_image_1 (mapped)
│
└─ elm_image_2 (not mapped)
│
└─ evas_object_image
After elm_image_1 adds draw command to the draw thread queue, and it starts
its drawing on the map_surface_1 on a thread, and stops middle of drawing.
At this point, evas_object_image does SYNC draw on the same surface
map_surface_1. And the thread for elm_image_1 works for remains.
Because the evas_object_image draws before finishing drawing of elm_image_1,
There is the problem.
F.Y.I. From the first evas_render has done SYNC render for mapped child.
cb10c7d evas: Modify software_generic ... with threaded renderer
This patch makes mapped children do ASYNC render.
Test Plan:
{F3856130}
{F3856131}
Reviewers: Hermet, jsuya, herb
Reviewed By: Hermet
Subscribers: cedric, #reviewers, #committers
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D11506
2020-03-16 03:15:17 -07:00
|
|
|
ENC, output, ctx, surface, off_x, off_y, do_async);
|
2015-02-03 00:32:59 -08:00
|
|
|
}
|
2009-11-06 21:01:43 -08:00
|
|
|
}
|
2016-10-31 20:06:22 -07:00
|
|
|
else if (!obj->is_smart)
|
2009-11-09 07:18:37 -08:00
|
|
|
{
|
2013-05-07 09:16:49 -07:00
|
|
|
if (obj->cur->clipper)
|
2011-03-15 09:20:57 -07:00
|
|
|
{
|
2014-11-12 17:47:29 -08:00
|
|
|
Evas_Object_Protected_Data *clipper = obj->cur->clipper;
|
2011-03-15 09:20:57 -07:00
|
|
|
int x, y, w, h;
|
|
|
|
|
2015-09-03 01:38:48 -07:00
|
|
|
if (proxy_src_clip)
|
|
|
|
{
|
2016-11-30 00:36:42 -08:00
|
|
|
if ((_evas_render_has_map(obj) && !_evas_render_can_map(obj)) ||
|
|
|
|
_evas_render_object_is_mask(obj->cur->clipper))
|
|
|
|
evas_object_clip_recalc(obj);
|
2015-09-03 01:38:48 -07:00
|
|
|
x = obj->cur->cache.clip.x;
|
|
|
|
y = obj->cur->cache.clip.y;
|
|
|
|
w = obj->cur->cache.clip.w;
|
|
|
|
h = obj->cur->cache.clip.h;
|
|
|
|
RECTS_CLIP_TO_RECT(x, y, w, h,
|
|
|
|
clipper->cur->cache.clip.x,
|
|
|
|
clipper->cur->cache.clip.y,
|
|
|
|
clipper->cur->cache.clip.w,
|
|
|
|
clipper->cur->cache.clip.h);
|
2017-08-25 10:51:05 -07:00
|
|
|
ENFN->context_clip_set(ENC, ctx, x + off_x, y + off_y, w, h);
|
2016-10-21 12:17:43 -07:00
|
|
|
if (!_is_obj_in_framespace(obj, evas))
|
2016-11-07 03:36:59 -08:00
|
|
|
{
|
|
|
|
_evas_render_framespace_context_clip_clip
|
|
|
|
(evas, ctx, off_x - evas->framespace.x, off_y - evas->framespace.y);
|
|
|
|
}
|
2016-09-07 18:26:30 -07:00
|
|
|
|
2017-08-25 10:51:05 -07:00
|
|
|
ENFN->context_clip_clip(ENC, ctx, ecx, ecy, ecw, ech);
|
2015-09-03 01:38:48 -07:00
|
|
|
}
|
2019-05-23 06:31:42 -07:00
|
|
|
else if (proxy_render_data)
|
2015-09-03 01:38:48 -07:00
|
|
|
{
|
2020-02-11 04:44:52 -08:00
|
|
|
if (!_proxy_context_clip(evas, ctx, proxy_render_data, obj, off_x, off_y))
|
evas: "fix" masks of masks inside a proxy
Here's the situation:
1. A container (genlist) has a mask, M0.
2. An item I0 inside this container uses a proxy P0 as render object
rather than the item directly (eg. for zooming in/out).
3. An element E0 inside this item has another mask, M1.
Theory:
1. The proxy surface for P0 is rendered, and M1 is applied to
the element E0.
2. The proxy P0 is rendered on the canvas, with M0 applied.
Practice:
1. The element E0 is prepared for rendering, this triggers
a mask subrender for M1.
2. M1 is rendered with M0 as a prev mask, then kept in cache and
not redrawn (no geometry change, etc...)
3. When P0's surface is rendered, M1's surface is the result of M1+M0.
4. When P0 is drawn on screen, we can see the effect of M1+M0 as
P0's geometry might be different from the item's I0.
Solution:
Discard prev masks and force a mask redraw when we're inside a
proxy. Ideally we should detect if the prev mask belongs to the
insides of the proxy or not.
Problems:
_mask_apply_inside_proxy() is definitely not correct, but it's
not easy to test it. Anyway I believe that in order to properly
implement all of this, we need to rethink evas_render and
the draw context. Non-primary render surfaces (maps, proxies,
masks, filters, ...) should be rendered with a clean context
and clipping, masking, etc should be computed appropriately.
2016-12-15 18:19:17 -08:00
|
|
|
goto on_empty_clip;
|
2015-09-03 01:38:48 -07:00
|
|
|
}
|
2011-03-15 09:20:57 -07:00
|
|
|
}
|
2016-11-07 03:36:59 -08:00
|
|
|
else if (!_is_obj_in_framespace(obj, evas))
|
|
|
|
{
|
|
|
|
_evas_render_framespace_context_clip_clip
|
|
|
|
(evas, ctx, off_x - evas->framespace.x, off_y - evas->framespace.y);
|
|
|
|
}
|
2011-03-15 09:20:57 -07:00
|
|
|
|
2015-09-03 00:36:32 -07:00
|
|
|
#ifdef REND_DBG
|
|
|
|
int _c, _cx, _cy, _cw, _ch;
|
2017-08-25 10:51:05 -07:00
|
|
|
_c = ENFN->context_clip_get(ENC, context, &_cx, &_cy, &_cw, &_ch);
|
2015-09-03 00:36:32 -07:00
|
|
|
RD(level, " draw normal obj: render(clip: [%d] %d,%d %dx%d)\n", _c, _cx, _cy, _cw, _ch);
|
|
|
|
#endif
|
2015-09-03 01:38:48 -07:00
|
|
|
|
2013-07-08 17:46:15 -07:00
|
|
|
obj->func->render(eo_obj, obj, obj->private_data,
|
2017-08-25 10:52:38 -07:00
|
|
|
ENC, output, ctx, surface,
|
2012-12-18 08:28:55 -08:00
|
|
|
off_x, off_y, do_async);
|
2009-11-09 07:18:37 -08:00
|
|
|
}
|
2012-05-28 22:13:03 -07:00
|
|
|
if (obj->changed_map) clean_them = EINA_TRUE;
|
evas: "fix" masks of masks inside a proxy
Here's the situation:
1. A container (genlist) has a mask, M0.
2. An item I0 inside this container uses a proxy P0 as render object
rather than the item directly (eg. for zooming in/out).
3. An element E0 inside this item has another mask, M1.
Theory:
1. The proxy surface for P0 is rendered, and M1 is applied to
the element E0.
2. The proxy P0 is rendered on the canvas, with M0 applied.
Practice:
1. The element E0 is prepared for rendering, this triggers
a mask subrender for M1.
2. M1 is rendered with M0 as a prev mask, then kept in cache and
not redrawn (no geometry change, etc...)
3. When P0's surface is rendered, M1's surface is the result of M1+M0.
4. When P0 is drawn on screen, we can see the effect of M1+M0 as
P0's geometry might be different from the item's I0.
Solution:
Discard prev masks and force a mask redraw when we're inside a
proxy. Ideally we should detect if the prev mask belongs to the
insides of the proxy or not.
Problems:
_mask_apply_inside_proxy() is definitely not correct, but it's
not easy to test it. Anyway I believe that in order to properly
implement all of this, we need to rethink evas_render and
the draw context. Non-primary render surfaces (maps, proxies,
masks, filters, ...) should be rendered with a clean context
and clipping, masking, etc should be computed appropriately.
2016-12-15 18:19:17 -08:00
|
|
|
|
|
|
|
on_empty_clip:
|
2017-08-25 10:51:05 -07:00
|
|
|
ENFN->context_free(ENC, ctx);
|
2009-11-06 21:01:43 -08:00
|
|
|
}
|
2010-05-05 04:36:21 -07:00
|
|
|
|
2017-07-19 22:35:48 -07:00
|
|
|
end:
|
|
|
|
RD(level, "}\n");
|
|
|
|
obj->pre_render_done = was_pre_render_done;
|
2016-11-06 18:26:22 -08:00
|
|
|
eina_evlog("-render_object", eo_obj, 0.0, NULL);
|
2010-05-05 04:36:21 -07:00
|
|
|
return clean_them;
|
2009-10-30 03:11:15 -07:00
|
|
|
}
|
|
|
|
|
2014-10-22 23:27:40 -07:00
|
|
|
/*
|
|
|
|
* Render the source object when a proxy is set.
|
|
|
|
* Used to force a draw if necessary, else just makes sure it's available.
|
|
|
|
* Called from: image objects and text with filters.
|
|
|
|
*/
|
|
|
|
void
|
2017-08-25 10:52:29 -07:00
|
|
|
evas_render_proxy_subrender(Evas *eo_e, void *output, Evas_Object *eo_source, Evas_Object *eo_proxy,
|
2016-12-19 22:47:54 -08:00
|
|
|
Evas_Object_Protected_Data *proxy_obj,
|
2016-12-13 23:28:42 -08:00
|
|
|
Eina_Bool source_clip, Eina_Bool do_async)
|
2014-10-22 23:27:40 -07:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Evas_Public_Data *evas = efl_data_scope_get(eo_e, EVAS_CANVAS_CLASS);
|
2019-05-10 11:14:49 -07:00
|
|
|
Evas_Object_Protected_Data *source, *proxy;
|
2015-09-01 04:47:40 -07:00
|
|
|
int level = 1;
|
2014-10-22 23:27:40 -07:00
|
|
|
void *ctx;
|
2019-05-10 11:14:49 -07:00
|
|
|
int w, h, off_x = 0, off_y = 0;
|
2020-02-11 06:03:43 -08:00
|
|
|
Eina_Rectangle lr = {0, 0, 0, 0};
|
2014-10-22 23:27:40 -07:00
|
|
|
|
2015-09-01 04:47:40 -07:00
|
|
|
#ifdef REND_DBG
|
|
|
|
level = __RD_level;
|
|
|
|
#endif
|
|
|
|
|
2014-10-22 23:27:40 -07:00
|
|
|
if (!eo_source) return;
|
2016-11-06 18:26:22 -08:00
|
|
|
eina_evlog("+proxy_subrender", eo_proxy, 0.0, NULL);
|
2016-08-15 06:44:41 -07:00
|
|
|
source = efl_data_scope_get(eo_source, EFL_CANVAS_OBJECT_CLASS);
|
2019-05-10 11:14:49 -07:00
|
|
|
proxy = efl_data_scope_get(eo_proxy, EFL_CANVAS_OBJECT_CLASS);
|
2014-10-22 23:27:40 -07:00
|
|
|
|
2020-02-03 19:14:23 -08:00
|
|
|
evas_object_image_load_region_get(eo_proxy, &lr.x, &lr.y, &lr.w, &lr.h);
|
|
|
|
|
|
|
|
if (lr.w > 0 && lr.h > 0)
|
|
|
|
{
|
|
|
|
w = lr.w;
|
|
|
|
h = lr.h;
|
|
|
|
off_x = -lr.x;
|
|
|
|
off_y = -lr.y;
|
|
|
|
}
|
|
|
|
else if (proxy->proxy->proxies || (!proxy->cur->clipper) || (!proxy->cur->has_fixed_size))
|
2019-05-10 11:14:49 -07:00
|
|
|
{
|
|
|
|
/* make full surface available if this proxy is being sampled from */
|
|
|
|
w = source->cur->geometry.w;
|
|
|
|
h = source->cur->geometry.h;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Eina_Rectangle clip = _evas_render_smallest_static_clipped_geometry_get(proxy->cur);
|
|
|
|
/* nothing is using this proxy, so the proxy render surface can be sized
|
|
|
|
* to fit exactly the proxy object's render size, and the proxy render will
|
|
|
|
* naturally be clipped to this geometry
|
|
|
|
*/
|
|
|
|
w = clip.w;
|
|
|
|
h = clip.h;
|
|
|
|
/* set the render offset for the proxy offset based on the geometry which will
|
|
|
|
* be visible on the proxy surface after clipping
|
|
|
|
*/
|
|
|
|
off_x = proxy->cur->geometry.x - clip.x;
|
|
|
|
off_y = proxy->cur->geometry.y - clip.y;
|
|
|
|
}
|
2016-12-19 22:47:54 -08:00
|
|
|
|
2017-01-11 04:18:59 -08:00
|
|
|
RD(level, " proxy_subrender(source: %s, proxy: %s, %dx%d)\n",
|
|
|
|
RDNAME(source), RDNAME(proxy_obj), w, h);
|
2015-09-01 04:47:40 -07:00
|
|
|
|
2014-10-22 23:27:40 -07:00
|
|
|
EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, source->proxy,
|
|
|
|
Evas_Object_Proxy_Data, proxy_write)
|
|
|
|
{
|
|
|
|
proxy_write->redraw = EINA_FALSE;
|
|
|
|
|
|
|
|
/* We need to redraw surface then */
|
|
|
|
if ((proxy_write->surface) &&
|
|
|
|
((proxy_write->w != w) || (proxy_write->h != h)))
|
|
|
|
{
|
2015-09-01 04:47:40 -07:00
|
|
|
RD(level, " free surface: %p\n", proxy_write->surface);
|
2017-04-24 15:09:25 -07:00
|
|
|
ENFN->image_free(ENC, proxy_write->surface);
|
2014-10-22 23:27:40 -07:00
|
|
|
proxy_write->surface = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* FIXME: Hardcoded alpha 'on' */
|
|
|
|
/* FIXME (cont): Should see if the object has alpha */
|
|
|
|
if (!proxy_write->surface)
|
|
|
|
{
|
2016-07-18 22:36:41 -07:00
|
|
|
if ((w < 1) || (h < 1)) goto end;
|
2017-04-24 15:09:25 -07:00
|
|
|
proxy_write->surface = ENFN->image_map_surface_new(ENC, w, h, 1);
|
2015-09-01 04:47:40 -07:00
|
|
|
RD(level, " created surface: %p %dx%d\n", proxy_write->surface, w, h);
|
2014-10-22 23:27:40 -07:00
|
|
|
if (!proxy_write->surface) goto end;
|
|
|
|
proxy_write->w = w;
|
|
|
|
proxy_write->h = h;
|
|
|
|
}
|
|
|
|
|
2016-11-06 18:26:22 -08:00
|
|
|
eina_evlog("+proxy_fill", eo_proxy, 0.0, NULL);
|
2017-05-12 15:03:05 -07:00
|
|
|
ctx = ENFN->context_new(ENC);
|
|
|
|
ENFN->context_color_set(ENC, ctx, 0, 0,0, 0);
|
|
|
|
ENFN->context_render_op_set(ENC, ctx, EVAS_RENDER_COPY);
|
2017-08-25 10:52:29 -07:00
|
|
|
ENFN->rectangle_draw(ENC, output, ctx, proxy_write->surface, 0, 0, w, h, do_async);
|
2017-05-12 15:03:05 -07:00
|
|
|
ENFN->context_free(ENC, ctx);
|
2016-11-06 18:26:22 -08:00
|
|
|
eina_evlog("-proxy_fill", eo_proxy, 0.0, NULL);
|
2014-10-22 23:27:40 -07:00
|
|
|
|
|
|
|
Evas_Proxy_Render_Data proxy_render_data = {
|
|
|
|
.eo_proxy = eo_proxy,
|
|
|
|
.proxy_obj = proxy_obj,
|
|
|
|
.eo_src = eo_source,
|
2015-09-03 01:38:48 -07:00
|
|
|
.src_obj = source,
|
2014-10-22 23:27:40 -07:00
|
|
|
.source_clip = source_clip
|
|
|
|
};
|
2015-09-03 00:36:32 -07:00
|
|
|
|
2015-09-03 01:38:48 -07:00
|
|
|
/* protect changes to the objects' cache.clip */
|
|
|
|
evas_event_freeze(evas->evas);
|
|
|
|
|
2017-05-12 15:03:05 -07:00
|
|
|
ctx = ENFN->context_new(ENC);
|
2017-08-25 10:52:38 -07:00
|
|
|
evas_render_mapped(evas, eo_source, source, ctx,
|
|
|
|
output, proxy_write->surface,
|
2019-05-10 11:14:49 -07:00
|
|
|
-source->cur->geometry.x + off_x,
|
|
|
|
-source->cur->geometry.y + off_y,
|
2015-09-01 04:47:40 -07:00
|
|
|
level + 1, 0, 0, evas->output.w, evas->output.h,
|
2016-12-15 17:55:47 -08:00
|
|
|
&proxy_render_data, level + 1, do_async);
|
2017-05-12 15:03:05 -07:00
|
|
|
ENFN->context_free(ENC, ctx);
|
2015-09-03 00:36:32 -07:00
|
|
|
|
2017-05-12 15:03:05 -07:00
|
|
|
proxy_write->surface = ENFN->image_dirty_region(ENC, proxy_write->surface, 0, 0, w, h);
|
2015-09-03 01:38:48 -07:00
|
|
|
|
|
|
|
/* restore previous state */
|
|
|
|
evas_event_thaw(evas->evas);
|
2014-10-22 23:27:40 -07:00
|
|
|
}
|
|
|
|
end:
|
|
|
|
EINA_COW_WRITE_END(evas_object_proxy_cow, source->proxy, proxy_write);
|
2016-11-06 18:26:22 -08:00
|
|
|
eina_evlog("-proxy_subrender", eo_proxy, 0.0, NULL);
|
2014-10-22 23:27:40 -07:00
|
|
|
}
|
|
|
|
|
2014-11-12 17:47:29 -08:00
|
|
|
/* @internal
|
|
|
|
* Synchronously render a mask image (or smart object) into a surface.
|
|
|
|
* In SW the target surface will be ALPHA only (GRY8), after conversion.
|
|
|
|
* In GL the target surface will be RGBA for now. TODO: Find out how to
|
|
|
|
* render GL to alpha, if that's possible.
|
|
|
|
*/
|
2017-08-25 10:52:33 -07:00
|
|
|
static void
|
2014-11-12 17:47:29 -08:00
|
|
|
evas_render_mask_subrender(Evas_Public_Data *evas,
|
2017-08-25 10:52:33 -07:00
|
|
|
void *output,
|
2014-11-12 17:47:29 -08:00
|
|
|
Evas_Object_Protected_Data *mask,
|
2015-01-26 00:35:42 -08:00
|
|
|
Evas_Object_Protected_Data *prev_mask,
|
2016-12-15 17:55:47 -08:00
|
|
|
int level, Eina_Bool do_async)
|
2014-11-12 17:47:29 -08:00
|
|
|
{
|
2016-12-16 00:04:05 -08:00
|
|
|
int x, y, w, h, r, g, b, a, cr, cg, cb, ca;
|
|
|
|
Eina_Bool is_image, done = EINA_FALSE, restore_state = EINA_FALSE;
|
2014-11-12 17:47:29 -08:00
|
|
|
void *ctx;
|
|
|
|
|
|
|
|
if (!mask) return;
|
|
|
|
|
2016-11-06 18:26:22 -08:00
|
|
|
eina_evlog("+mask_subrender", mask->object, 0.0, NULL);
|
2017-01-11 04:18:59 -08:00
|
|
|
RD(level, "evas_render_mask_subrender(mask: %s, prev: %s, %s)\n",
|
|
|
|
RDNAME(mask), RDNAME(prev_mask), do_async ? "async" : "sync");
|
2015-01-26 00:35:42 -08:00
|
|
|
|
2016-08-15 06:44:41 -07:00
|
|
|
is_image = efl_isa(mask->object, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
|
2015-02-25 02:05:12 -08:00
|
|
|
|
2014-11-12 17:47:29 -08:00
|
|
|
x = mask->cur->geometry.x;
|
|
|
|
y = mask->cur->geometry.y;
|
|
|
|
w = mask->cur->geometry.w;
|
|
|
|
h = mask->cur->geometry.h;
|
2019-05-06 13:12:48 -07:00
|
|
|
if (mask->cur->clipper && mask->cur->has_fixed_size)
|
|
|
|
{
|
|
|
|
Eina_Rectangle clip = _evas_render_smallest_static_clipped_geometry_get(mask->cur);
|
|
|
|
x = clip.x;
|
|
|
|
y = clip.y;
|
|
|
|
w = clip.w;
|
|
|
|
h = clip.h;
|
|
|
|
}
|
2014-11-12 17:47:29 -08:00
|
|
|
|
|
|
|
r = mask->cur->color.r;
|
|
|
|
g = mask->cur->color.g;
|
|
|
|
b = mask->cur->color.b;
|
|
|
|
a = mask->cur->color.a;
|
2016-12-16 00:04:05 -08:00
|
|
|
cr = mask->cur->cache.clip.r;
|
|
|
|
cg = mask->cur->cache.clip.g;
|
|
|
|
cb = mask->cur->cache.clip.b;
|
|
|
|
ca = mask->cur->cache.clip.a;
|
|
|
|
if ((r != 255) || (g != 255) || (b != 255) || (a != 255) ||
|
|
|
|
(cr != 255) || (cg != 255) || (cb != 255) || (ca != 255))
|
2014-11-12 17:47:29 -08:00
|
|
|
{
|
2016-12-16 00:04:05 -08:00
|
|
|
restore_state = EINA_TRUE;
|
2014-11-12 17:47:29 -08:00
|
|
|
EINA_COW_STATE_WRITE_BEGIN(mask, state_write, cur)
|
|
|
|
{
|
|
|
|
state_write->color.r = 255;
|
|
|
|
state_write->color.g = 255;
|
|
|
|
state_write->color.b = 255;
|
|
|
|
state_write->color.a = 255;
|
2016-12-16 00:04:05 -08:00
|
|
|
state_write->cache.clip.r = 255;
|
|
|
|
state_write->cache.clip.g = 255;
|
|
|
|
state_write->cache.clip.b = 255;
|
|
|
|
state_write->cache.clip.a = 255;
|
2014-11-12 17:47:29 -08:00
|
|
|
}
|
|
|
|
EINA_COW_STATE_WRITE_END(mask, state_write, cur);
|
|
|
|
}
|
|
|
|
|
2016-12-15 17:55:47 -08:00
|
|
|
// For SW engine, we want sync render of masks to be able to convert the
|
|
|
|
// surface from RGBA to Alpha. See below. (this logic could be improved)
|
|
|
|
if (!ENFN->gl_surface_read_pixels)
|
|
|
|
do_async = EINA_FALSE;
|
|
|
|
|
2014-11-12 17:47:29 -08:00
|
|
|
if (prev_mask == mask)
|
|
|
|
prev_mask = NULL;
|
|
|
|
|
|
|
|
if (prev_mask)
|
|
|
|
{
|
|
|
|
if (!prev_mask->mask->is_mask)
|
|
|
|
{
|
|
|
|
ERR("Passed invalid mask that is not a mask");
|
|
|
|
prev_mask = NULL;
|
|
|
|
}
|
|
|
|
else if (!prev_mask->mask->surface)
|
|
|
|
{
|
2015-02-02 22:51:01 -08:00
|
|
|
// Note: This is preventive code. Never seen it happen.
|
2014-11-12 17:47:29 -08:00
|
|
|
WRN("Mask render order may be invalid");
|
2017-08-25 10:52:33 -07:00
|
|
|
evas_render_mask_subrender(evas, output, prev_mask, prev_mask->clip.prev_mask, level + 1, do_async);
|
2014-11-12 17:47:29 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
EINA_COW_WRITE_BEGIN(evas_object_mask_cow, mask->mask, Evas_Object_Mask_Data, mdata)
|
|
|
|
mdata->redraw = EINA_FALSE;
|
|
|
|
|
2015-04-16 17:24:46 -07:00
|
|
|
if (is_image && ENFN->image_scaled_update)
|
2014-11-12 17:47:29 -08:00
|
|
|
{
|
2015-04-16 17:24:46 -07:00
|
|
|
Eina_Bool filled = EINA_FALSE, border = EINA_FALSE;
|
|
|
|
int bl = 0, br = 0, bt = 0, bb = 0;
|
2015-02-26 22:57:36 -08:00
|
|
|
|
|
|
|
if (evas_object_image_filled_get(mask->object))
|
|
|
|
filled = EINA_TRUE;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int fx, fy, fw, fh;
|
|
|
|
evas_object_image_fill_get(mask->object, &fx, &fy, &fw, &fh);
|
2019-05-06 13:12:48 -07:00
|
|
|
if ((fx == 0) && (fy == 0) && (fw == mask->cur->geometry.w) && (fh == mask->cur->geometry.h))
|
2015-02-26 22:57:36 -08:00
|
|
|
filled = EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
2015-04-16 17:24:46 -07:00
|
|
|
evas_object_image_border_get(mask->object, &bl, &br, &bt, &bb);
|
|
|
|
if (bl || br || bt || bb)
|
|
|
|
border = EINA_TRUE;
|
|
|
|
|
2016-01-12 18:10:25 -08:00
|
|
|
if (!border && filled && !prev_mask && mask->func->engine_data_get)
|
2015-02-25 02:05:12 -08:00
|
|
|
{
|
2016-11-06 18:26:22 -08:00
|
|
|
eina_evlog("+mask_scaled_update", mask->object, 0.0, NULL);
|
2015-02-26 22:57:36 -08:00
|
|
|
/* Fast path (for GL) that avoids creating a map surface, render the
|
|
|
|
* scaled image in it, when the shaders can just scale on the fly. */
|
|
|
|
Eina_Bool smooth = evas_object_image_smooth_scale_get(mask->object);
|
|
|
|
void *original = mask->func->engine_data_get(mask->object);
|
|
|
|
void *scaled = ENFN->image_scaled_update
|
2017-08-25 10:51:10 -07:00
|
|
|
(ENC, mdata->surface, original, w, h, smooth, EVAS_COLORSPACE_GRY8);
|
2015-02-26 22:57:36 -08:00
|
|
|
if (scaled)
|
|
|
|
{
|
|
|
|
done = EINA_TRUE;
|
|
|
|
mdata->surface = scaled;
|
|
|
|
mdata->w = w;
|
|
|
|
mdata->h = h;
|
2017-08-25 10:51:10 -07:00
|
|
|
mdata->is_alpha = (ENFN->image_colorspace_get(ENC, scaled) == EVAS_COLORSPACE_GRY8);
|
2015-03-11 19:28:02 -07:00
|
|
|
mdata->is_scaled = EINA_TRUE;
|
2015-02-26 22:57:36 -08:00
|
|
|
}
|
2016-11-06 18:26:22 -08:00
|
|
|
eina_evlog("-mask_scaled_update", mask->object, 0.0, NULL);
|
2015-02-25 02:05:12 -08:00
|
|
|
}
|
2014-11-12 17:47:29 -08:00
|
|
|
}
|
|
|
|
|
2015-02-25 02:05:12 -08:00
|
|
|
if (!done)
|
2014-11-12 17:47:29 -08:00
|
|
|
{
|
2015-02-25 02:05:12 -08:00
|
|
|
/* delete render surface if changed or if already alpha
|
|
|
|
* (we don't know how to render objects to alpha) */
|
2015-03-11 19:28:02 -07:00
|
|
|
if (mdata->surface && ((w != mdata->w) || (h != mdata->h) || mdata->is_alpha || mdata->is_scaled))
|
2015-02-25 02:05:12 -08:00
|
|
|
{
|
2017-04-24 15:09:25 -07:00
|
|
|
ENFN->image_free(ENC, mdata->surface);
|
2015-02-25 02:05:12 -08:00
|
|
|
mdata->surface = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* create new RGBA render surface if needed */
|
|
|
|
if (!mdata->surface)
|
|
|
|
{
|
2016-11-06 18:26:22 -08:00
|
|
|
eina_evlog("+mask_surface_new", mask->object, 0.0, NULL);
|
2017-04-24 15:09:25 -07:00
|
|
|
mdata->surface = ENFN->image_map_surface_new(ENC, w, h, EINA_TRUE);
|
2016-11-06 18:26:22 -08:00
|
|
|
eina_evlog("-mask_surface_new", mask->object, 0.0, NULL);
|
2015-02-25 02:05:12 -08:00
|
|
|
if (!mdata->surface) goto end;
|
|
|
|
mdata->is_alpha = EINA_FALSE;
|
2015-03-11 19:28:02 -07:00
|
|
|
mdata->is_scaled = EINA_FALSE;
|
2015-02-25 02:05:12 -08:00
|
|
|
mdata->w = w;
|
|
|
|
mdata->h = h;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Clear surface with transparency */
|
2016-11-06 18:26:22 -08:00
|
|
|
eina_evlog("+mask_rect_clear", mask->object, 0.0, NULL);
|
2017-05-12 15:03:05 -07:00
|
|
|
ctx = ENFN->context_new(ENC);
|
|
|
|
ENFN->context_color_set(ENC, ctx, 0, 0, 0, 0);
|
|
|
|
ENFN->context_render_op_set(ENC, ctx, EVAS_RENDER_COPY);
|
2017-08-25 10:52:33 -07:00
|
|
|
ENFN->rectangle_draw(ENC, output, ctx, mdata->surface, 0, 0, w, h, do_async);
|
2017-05-12 15:03:05 -07:00
|
|
|
ENFN->context_free(ENC, ctx);
|
2016-11-06 18:26:22 -08:00
|
|
|
eina_evlog("-mask_rect_clear", mask->object, 0.0, NULL);
|
2015-02-25 02:05:12 -08:00
|
|
|
|
|
|
|
/* Render mask to RGBA surface */
|
2017-05-12 15:03:05 -07:00
|
|
|
ctx = ENFN->context_new(ENC);
|
2015-02-25 02:05:12 -08:00
|
|
|
if (prev_mask)
|
|
|
|
{
|
2019-05-06 13:12:48 -07:00
|
|
|
Eina_Rectangle pclip = _evas_render_smallest_static_clipped_geometry_get(prev_mask->cur);
|
2017-05-12 15:03:05 -07:00
|
|
|
ENFN->context_clip_image_set(ENC, ctx,
|
2015-02-25 02:05:12 -08:00
|
|
|
prev_mask->mask->surface,
|
2019-05-06 13:12:48 -07:00
|
|
|
pclip.x - x,
|
|
|
|
pclip.y - y,
|
2016-12-15 17:55:47 -08:00
|
|
|
evas, do_async);
|
2017-05-12 15:03:05 -07:00
|
|
|
ENFN->context_clip_set(ENC, ctx,
|
2019-05-06 13:12:48 -07:00
|
|
|
pclip.x - x,
|
|
|
|
pclip.y - y,
|
|
|
|
pclip.w,
|
|
|
|
pclip.h);
|
2015-02-25 02:05:12 -08:00
|
|
|
}
|
2016-12-15 17:53:03 -08:00
|
|
|
|
|
|
|
if (EINA_LIKELY(!mask->is_smart))
|
|
|
|
{
|
|
|
|
mask->func->render(mask->object, mask, mask->private_data,
|
2017-08-25 10:52:33 -07:00
|
|
|
ENC, output, ctx, mdata->surface, -x, -y, do_async);
|
2016-12-15 17:53:03 -08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Unreachable code until we implement support for smart masks
|
2017-08-25 10:52:38 -07:00
|
|
|
evas_render_mapped(evas, mask->object, mask, ctx,
|
|
|
|
output, mdata->surface,
|
2020-02-18 03:07:08 -08:00
|
|
|
-x, -y, 2, 0, 0, evas->output.w, evas->output.h,
|
2016-12-15 17:55:47 -08:00
|
|
|
NULL, level, do_async);
|
2016-12-15 17:53:03 -08:00
|
|
|
}
|
2017-05-12 15:03:05 -07:00
|
|
|
ENFN->context_free(ENC, ctx);
|
2015-02-25 02:05:12 -08:00
|
|
|
|
|
|
|
/* BEGIN HACK */
|
|
|
|
|
|
|
|
/* Now we want to convert this RGBA surface to Alpha.
|
|
|
|
* NOTE: So, this is not going to work with the GL engine but only with
|
|
|
|
* the SW engine. Here's the detection hack:
|
|
|
|
* FIXME: If you know of a way to support rendering to GL_ALPHA in GL,
|
|
|
|
* then we should render directly to an ALPHA surface. A priori,
|
|
|
|
* GLES FBO does not support this.
|
|
|
|
*/
|
|
|
|
if (!ENFN->gl_surface_read_pixels)
|
|
|
|
{
|
|
|
|
RGBA_Image *alpha_surface;
|
|
|
|
DATA32 *rgba;
|
|
|
|
DATA8* alpha;
|
|
|
|
|
2016-11-06 18:26:22 -08:00
|
|
|
eina_evlog("+mask_new_cpy_data", mask->object, 0.0, NULL);
|
2015-02-25 02:05:12 -08:00
|
|
|
alpha_surface = ENFN->image_new_from_copied_data
|
2017-04-24 15:09:25 -07:00
|
|
|
(ENC, w, h, NULL, EINA_TRUE, EVAS_COLORSPACE_GRY8);
|
2016-11-06 18:26:22 -08:00
|
|
|
eina_evlog("-mask_new_cpy_data", mask->object, 0.0, NULL);
|
2015-02-25 02:05:12 -08:00
|
|
|
if (!alpha_surface) goto end;
|
|
|
|
|
2016-11-06 18:26:22 -08:00
|
|
|
eina_evlog("+mask_cpy_data", mask->object, 0.0, NULL);
|
2015-02-25 02:05:12 -08:00
|
|
|
/* Copy alpha channel */
|
|
|
|
rgba = ((RGBA_Image *) mdata->surface)->image.data;
|
|
|
|
alpha = alpha_surface->image.data8;
|
|
|
|
for (y = h; y; --y)
|
|
|
|
for (x = w; x; --x, alpha++, rgba++)
|
|
|
|
*alpha = (DATA8) A_VAL(rgba);
|
2016-11-06 18:26:22 -08:00
|
|
|
eina_evlog("-mask_cpy_data", mask->object, 0.0, NULL);
|
2015-02-25 02:05:12 -08:00
|
|
|
|
|
|
|
/* Now we can drop the original surface */
|
2017-04-24 15:09:25 -07:00
|
|
|
ENFN->image_free(ENC, mdata->surface);
|
2015-02-25 02:05:12 -08:00
|
|
|
mdata->surface = alpha_surface;
|
|
|
|
mdata->is_alpha = EINA_TRUE;
|
|
|
|
}
|
|
|
|
/* END OF HACK */
|
2014-11-12 17:47:29 -08:00
|
|
|
}
|
|
|
|
|
2017-08-25 10:51:10 -07:00
|
|
|
mdata->surface = ENFN->image_dirty_region(ENC, mdata->surface, 0, 0, w, h);
|
2015-01-21 00:30:18 -08:00
|
|
|
|
2014-11-12 17:47:29 -08:00
|
|
|
end:
|
|
|
|
EINA_COW_WRITE_END(evas_object_mask_cow, mask->mask, mdata);
|
|
|
|
|
2016-12-16 00:04:05 -08:00
|
|
|
if (restore_state)
|
2014-11-12 17:47:29 -08:00
|
|
|
{
|
|
|
|
EINA_COW_STATE_WRITE_BEGIN(mask, state_write, cur)
|
|
|
|
{
|
|
|
|
state_write->color.r = r;
|
|
|
|
state_write->color.g = g;
|
|
|
|
state_write->color.b = b;
|
|
|
|
state_write->color.a = a;
|
2016-12-16 00:04:05 -08:00
|
|
|
state_write->cache.clip.r = cr;
|
|
|
|
state_write->cache.clip.g = cg;
|
|
|
|
state_write->cache.clip.b = cb;
|
|
|
|
state_write->cache.clip.a = ca;
|
2014-11-12 17:47:29 -08:00
|
|
|
}
|
|
|
|
EINA_COW_STATE_WRITE_END(mask, state_write, cur);
|
|
|
|
}
|
2016-11-06 18:26:22 -08:00
|
|
|
eina_evlog("-mask_subrender", mask->object, 0.0, NULL);
|
2014-11-12 17:47:29 -08:00
|
|
|
}
|
|
|
|
|
2011-10-27 02:39:18 -07:00
|
|
|
static void
|
2017-03-16 19:24:10 -07:00
|
|
|
_evas_render_cutout_add(Evas_Public_Data *evas, void *context,
|
|
|
|
Evas_Object_Protected_Data *obj, int off_x, int off_y,
|
2017-03-22 04:51:53 -07:00
|
|
|
Cutout_Margin *cutout_margin)
|
2011-10-27 02:39:18 -07:00
|
|
|
{
|
2017-03-16 19:24:10 -07:00
|
|
|
Evas_Coord cox = 0, coy = 0, cow = 0, coh = 0;
|
|
|
|
|
2013-04-11 00:25:36 -07:00
|
|
|
if (evas_object_is_source_invisible(obj->object, obj)) return;
|
2019-05-29 12:37:07 -07:00
|
|
|
if (evas_object_is_opaque(obj))
|
2011-10-27 02:39:18 -07:00
|
|
|
{
|
2013-03-12 05:58:19 -07:00
|
|
|
cox = obj->cur->cache.clip.x;
|
|
|
|
coy = obj->cur->cache.clip.y;
|
|
|
|
cow = obj->cur->cache.clip.w;
|
|
|
|
coh = obj->cur->cache.clip.h;
|
2013-01-21 19:56:00 -08:00
|
|
|
if ((obj->map->cur.map) && (obj->map->cur.usemap))
|
2011-10-27 02:39:18 -07:00
|
|
|
{
|
2012-10-16 05:41:48 -07:00
|
|
|
Evas_Object_Protected_Data *oo;
|
2012-05-16 06:21:37 -07:00
|
|
|
|
2017-03-22 04:51:53 -07:00
|
|
|
for (oo = obj; oo->cur->clipper; oo = oo->cur->clipper)
|
2011-10-27 02:39:18 -07:00
|
|
|
{
|
2013-03-12 05:58:19 -07:00
|
|
|
if ((oo->cur->clipper->map->cur.map_parent
|
2013-01-21 19:56:00 -08:00
|
|
|
!= oo->map->cur.map_parent) &&
|
|
|
|
(!((oo->map->cur.map) && (oo->map->cur.usemap))))
|
2011-10-27 02:39:18 -07:00
|
|
|
break;
|
|
|
|
RECTS_CLIP_TO_RECT(cox, coy, cow, coh,
|
2013-03-12 05:58:19 -07:00
|
|
|
oo->cur->geometry.x,
|
|
|
|
oo->cur->geometry.y,
|
|
|
|
oo->cur->geometry.w,
|
|
|
|
oo->cur->geometry.h);
|
2017-03-22 04:51:53 -07:00
|
|
|
if ((cow <= 0) || (coh <= 0)) return;
|
2011-10-27 02:39:18 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-03-16 19:24:10 -07:00
|
|
|
else if (obj->func->get_opaque_rect)
|
|
|
|
{
|
|
|
|
obj->func->get_opaque_rect(obj->object, obj, obj->private_data, &cox, &coy, &cow, &coh);
|
|
|
|
if ((cow <= 0) || (coh <= 0)) return;
|
|
|
|
RECTS_CLIP_TO_RECT(cox, coy, cow, coh,
|
|
|
|
obj->cur->cache.clip.x, obj->cur->cache.clip.y,
|
|
|
|
obj->cur->cache.clip.w, obj->cur->cache.clip.h);
|
|
|
|
}
|
|
|
|
else return;
|
2017-03-22 04:51:53 -07:00
|
|
|
if (cutout_margin)
|
|
|
|
{
|
|
|
|
cox += cutout_margin->l;
|
|
|
|
coy += cutout_margin->t;
|
|
|
|
cow -= cutout_margin->l + cutout_margin->r;
|
|
|
|
coh -= cutout_margin->t + cutout_margin->b;
|
|
|
|
}
|
2017-03-16 19:24:10 -07:00
|
|
|
if ((cow <= 0) || (coh <= 0)) return;
|
2017-05-12 15:03:05 -07:00
|
|
|
ENFN->context_cutout_add(ENC, context, cox + off_x, coy + off_y, cow, coh);
|
2011-10-27 02:39:18 -07:00
|
|
|
}
|
|
|
|
|
2012-12-18 08:26:44 -08:00
|
|
|
void
|
|
|
|
evas_render_rendering_wait(Evas_Public_Data *evas)
|
|
|
|
{
|
|
|
|
while (evas->rendering) evas_async_events_process_blocking();
|
|
|
|
}
|
|
|
|
|
2013-09-02 21:48:08 -07:00
|
|
|
/*
|
|
|
|
* Syncs ALL async rendering canvases. Must be called in the main thread.
|
|
|
|
*/
|
2013-09-02 15:38:52 -07:00
|
|
|
void
|
2013-10-17 12:13:24 -07:00
|
|
|
evas_all_sync(void)
|
2013-09-02 15:38:52 -07:00
|
|
|
{
|
2013-09-02 21:48:08 -07:00
|
|
|
Evas_Public_Data *evas;
|
2013-09-02 15:38:52 -07:00
|
|
|
|
2013-09-02 21:48:08 -07:00
|
|
|
if (!_rendering_evases) return;
|
|
|
|
|
|
|
|
evas = eina_list_data_get(eina_list_last(_rendering_evases));
|
|
|
|
evas_render_rendering_wait(evas);
|
|
|
|
|
|
|
|
assert(_rendering_evases == NULL);
|
2013-09-02 15:38:52 -07:00
|
|
|
}
|
|
|
|
|
2013-01-11 11:54:12 -08:00
|
|
|
static Eina_Bool
|
2013-01-17 14:14:05 -08:00
|
|
|
_drop_scie_ref(const void *container EINA_UNUSED, void *data, void *fdata EINA_UNUSED)
|
2013-01-11 11:54:12 -08:00
|
|
|
{
|
2013-01-17 14:14:05 -08:00
|
|
|
evas_common_rgba_image_scalecache_item_unref(data);
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
2013-01-16 14:32:39 -08:00
|
|
|
|
2013-01-17 14:14:05 -08:00
|
|
|
static Eina_Bool
|
|
|
|
_drop_image_cache_ref(const void *container EINA_UNUSED, void *data, void *fdata EINA_UNUSED)
|
|
|
|
{
|
2018-08-29 21:48:38 -07:00
|
|
|
evas_cache_image_drop((Image_Entry *)data);
|
2013-01-11 11:54:12 -08:00
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
2013-11-30 20:26:04 -08:00
|
|
|
static void
|
2019-10-14 06:30:17 -07:00
|
|
|
_cb_always_call(Evas *eo_e, Evas_Public_Data *e, Evas_Callback_Type type, void *event_info)
|
2013-11-30 20:26:04 -08:00
|
|
|
{
|
|
|
|
int freeze_num = 0, i;
|
|
|
|
|
2019-10-14 06:30:17 -07:00
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case EVAS_CALLBACK_RENDER_PRE:
|
|
|
|
if (!e->cb_render_pre) return;
|
|
|
|
break;
|
|
|
|
case EVAS_CALLBACK_RENDER_POST:
|
|
|
|
if (!e->cb_render_post) return;
|
|
|
|
break;
|
|
|
|
case EVAS_CALLBACK_RENDER_FLUSH_PRE:
|
|
|
|
if (!e->cb_render_flush_pre) return;
|
|
|
|
break;
|
|
|
|
case EVAS_CALLBACK_RENDER_FLUSH_POST:
|
|
|
|
if (!e->cb_render_flush_post) return;
|
|
|
|
break;
|
|
|
|
default: break;
|
|
|
|
}
|
2016-08-10 07:23:04 -07:00
|
|
|
freeze_num = efl_event_freeze_count_get(eo_e);
|
|
|
|
for (i = 0; i < freeze_num; i++) efl_event_thaw(eo_e);
|
2013-11-30 20:26:04 -08:00
|
|
|
evas_event_callback_call(eo_e, type, event_info);
|
2016-08-10 07:23:04 -07:00
|
|
|
for (i = 0; i < freeze_num; i++) efl_event_freeze(eo_e);
|
2013-11-30 20:26:04 -08:00
|
|
|
}
|
|
|
|
|
2016-11-25 21:25:41 -08:00
|
|
|
#ifndef INLINE_ACTIVE_GEOM
|
2016-05-24 19:45:16 -07:00
|
|
|
static inline Eina_Bool
|
|
|
|
_is_obj_in_rect(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj,
|
|
|
|
int x, int y, int w, int h)
|
|
|
|
{
|
2017-04-24 22:34:03 -07:00
|
|
|
if (obj->is_smart && !_evas_render_has_map(obj))
|
2016-05-24 19:45:16 -07:00
|
|
|
{
|
2017-09-13 00:38:33 -07:00
|
|
|
Eina_Rectangle rect;
|
2016-05-24 19:45:16 -07:00
|
|
|
|
2017-02-20 02:34:58 -08:00
|
|
|
evas_object_smart_bounding_box_get(obj, &rect, NULL);
|
2016-05-24 19:45:16 -07:00
|
|
|
if (RECTS_INTERSECT(x, y, w, h, rect.x, rect.y, rect.w, rect.h))
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-05-12 15:03:05 -07:00
|
|
|
// FIXME: handle multiple output
|
2016-05-24 19:45:16 -07:00
|
|
|
if (evas_object_is_in_output_rect(eo_obj, obj, x, y, w, h))
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
2016-11-25 21:25:41 -08:00
|
|
|
#endif
|
2016-05-24 19:45:16 -07:00
|
|
|
|
2017-03-22 04:51:53 -07:00
|
|
|
static void
|
|
|
|
_snapshot_redraw_update(Evas_Public_Data *evas, Evas_Object_Protected_Data *snap)
|
2017-02-09 23:08:58 -08:00
|
|
|
{
|
2017-03-22 04:51:53 -07:00
|
|
|
Eina_Bool above = EINA_FALSE, add_rect = EINA_FALSE, need_redraw = EINA_FALSE;
|
2017-02-09 23:08:58 -08:00
|
|
|
const int x = snap->cur->geometry.x;
|
|
|
|
const int y = snap->cur->geometry.y;
|
|
|
|
const int w = snap->cur->geometry.w;
|
|
|
|
const int h = snap->cur->geometry.h;
|
|
|
|
Evas_Object_Protected_Data *obj;
|
|
|
|
Evas_Active_Entry *ent;
|
2017-03-29 21:52:48 -07:00
|
|
|
Eina_Rectangle snap_clip;
|
|
|
|
Eina_Tiler *tiler = NULL;
|
2017-02-09 23:08:58 -08:00
|
|
|
void *surface;
|
|
|
|
|
2017-03-29 21:52:48 -07:00
|
|
|
// FIXME: Tiler should be inside snapshot data
|
2017-03-22 04:51:53 -07:00
|
|
|
// TODO: Also list redraw regions (partial updates)
|
|
|
|
|
2019-05-29 12:36:53 -07:00
|
|
|
if (!evas_object_is_visible(snap)) return;
|
2017-03-22 04:51:53 -07:00
|
|
|
|
2017-03-22 23:55:41 -07:00
|
|
|
evas_object_clip_recalc(snap);
|
2017-03-29 21:52:48 -07:00
|
|
|
snap_clip.x = snap->cur->cache.clip.x - x;
|
|
|
|
snap_clip.y = snap->cur->cache.clip.y - y;
|
2017-03-22 23:55:41 -07:00
|
|
|
snap_clip.w = snap->cur->cache.clip.w;
|
|
|
|
snap_clip.h = snap->cur->cache.clip.h;
|
|
|
|
|
2017-02-09 23:08:58 -08:00
|
|
|
surface = _evas_object_image_surface_get(snap, EINA_FALSE);
|
2017-03-22 04:51:53 -07:00
|
|
|
if (!surface) need_redraw = EINA_TRUE;
|
|
|
|
if (snap->changed) add_rect = EINA_TRUE;
|
2017-02-09 23:08:58 -08:00
|
|
|
|
2017-03-29 21:52:48 -07:00
|
|
|
if (!add_rect && !need_redraw)
|
2017-02-09 23:08:58 -08:00
|
|
|
{
|
2017-03-29 21:52:48 -07:00
|
|
|
// Objects below snapshot
|
|
|
|
EINA_INARRAY_FOREACH(&evas->active_objects, ent)
|
2017-03-14 22:49:50 -07:00
|
|
|
{
|
2017-03-29 21:52:48 -07:00
|
|
|
obj = ent->obj;
|
|
|
|
if (obj == snap) break;
|
2017-03-14 22:49:50 -07:00
|
|
|
|
|
|
|
if (!obj->is_smart && obj->changed &&
|
|
|
|
evas_object_is_in_output_rect(obj->object, obj, x, y, w, h))
|
2017-03-22 04:51:53 -07:00
|
|
|
need_redraw = EINA_TRUE;
|
2017-03-14 22:49:50 -07:00
|
|
|
}
|
2017-03-29 21:52:48 -07:00
|
|
|
}
|
|
|
|
|
2017-04-03 22:28:29 -07:00
|
|
|
if (snap->snapshot_no_obscure || _evas_render_has_map(snap))
|
2017-03-29 21:52:48 -07:00
|
|
|
goto skip_obscures;
|
|
|
|
|
|
|
|
tiler = eina_tiler_new(w, h);
|
|
|
|
eina_tiler_tile_size_set(tiler, 1, 1);
|
|
|
|
eina_tiler_strict_set(tiler, EINA_TRUE);
|
|
|
|
|
|
|
|
// Opaque objects above snapshot
|
|
|
|
for (unsigned i = 0; i < evas->obscuring_objects.count; i++)
|
|
|
|
{
|
|
|
|
obj = eina_array_data_get(&evas->obscuring_objects, i);
|
|
|
|
if (!above)
|
2017-03-14 22:49:50 -07:00
|
|
|
{
|
2017-03-29 21:52:48 -07:00
|
|
|
if (obj == snap) above = EINA_TRUE;
|
|
|
|
continue;
|
|
|
|
}
|
2019-05-29 12:37:07 -07:00
|
|
|
if (!obj->cur->snapshot || evas_object_is_opaque(obj))
|
2017-03-29 21:52:48 -07:00
|
|
|
{
|
|
|
|
const Eina_Rectangle cur = {
|
|
|
|
obj->cur->cache.clip.x - x, obj->cur->cache.clip.y - y,
|
|
|
|
obj->cur->cache.clip.w, obj->cur->cache.clip.h
|
|
|
|
};
|
|
|
|
|
|
|
|
if (_evas_eina_rectangle_inside(&cur, &snap_clip))
|
|
|
|
goto end; // Totally hidden
|
|
|
|
|
|
|
|
eina_tiler_rect_add(tiler, &cur);
|
2017-03-14 22:49:50 -07:00
|
|
|
}
|
2017-02-09 23:08:58 -08:00
|
|
|
}
|
2017-03-22 04:51:53 -07:00
|
|
|
|
2017-03-29 21:52:48 -07:00
|
|
|
skip_obscures:
|
|
|
|
need_redraw |= _evas_filter_obscured_regions_set(snap, tiler);
|
|
|
|
if (memcmp(&snap->cur->geometry, &snap->prev->geometry, sizeof(snap->cur->geometry)))
|
|
|
|
need_redraw = EINA_TRUE;
|
2017-03-22 04:51:53 -07:00
|
|
|
snap->snapshot_needs_redraw |= need_redraw;
|
|
|
|
|
|
|
|
if (add_rect || need_redraw)
|
|
|
|
{
|
2017-03-22 23:55:41 -07:00
|
|
|
// FIXME: Only add necessary rects (if object itself hasn't changed)
|
2017-05-12 15:03:05 -07:00
|
|
|
// FIXME: handle multiple output
|
2017-08-25 10:49:53 -07:00
|
|
|
ENFN->output_redraws_rect_add(ENC, x, y, w, h);
|
2017-03-22 04:51:53 -07:00
|
|
|
}
|
2017-03-29 21:52:48 -07:00
|
|
|
|
|
|
|
end:
|
|
|
|
eina_tiler_free(tiler);
|
2017-02-09 23:08:58 -08:00
|
|
|
}
|
|
|
|
|
2017-07-06 00:29:20 -07:00
|
|
|
static void
|
|
|
|
evas_render_pre(Evas *eo_e, Evas_Public_Data *evas)
|
|
|
|
{
|
|
|
|
Eo *eo_obj;
|
|
|
|
|
2017-08-16 04:04:07 -07:00
|
|
|
if (!evas->finalize_objects) return; // avoid evlog
|
|
|
|
|
2017-07-06 00:29:20 -07:00
|
|
|
// Finalize EO objects now
|
|
|
|
eina_evlog("+render_pre_objects_finalize", eo_e, 0.0, NULL);
|
|
|
|
|
|
|
|
EINA_LIST_FREE(evas->finalize_objects, eo_obj)
|
|
|
|
{
|
|
|
|
Evas_Object_Protected_Data *obj;
|
|
|
|
|
|
|
|
obj = efl_data_scope_safe_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
|
|
|
|
if (!EVAS_OBJECT_DATA_ALIVE(obj)) continue;
|
|
|
|
obj->legacy.finalized = EINA_TRUE;
|
|
|
|
|
|
|
|
if (!obj->legacy.visible_set)
|
2018-04-05 01:47:26 -07:00
|
|
|
efl_gfx_entity_visible_set(eo_obj, EINA_TRUE);
|
2017-07-27 04:46:17 -07:00
|
|
|
|
|
|
|
// weight should be set during finalize()
|
|
|
|
if (EINA_UNLIKELY(!obj->legacy.weight_set))
|
2019-02-21 09:19:45 -08:00
|
|
|
efl_gfx_hint_weight_set(eo_obj, 1.0, 1.0);
|
2017-07-06 00:29:20 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
eina_evlog("-render_pre_objects_finalize", eo_e, 0.0, NULL);
|
|
|
|
}
|
|
|
|
|
2017-12-19 03:37:25 -08:00
|
|
|
EAPI void
|
|
|
|
evas_render_pending_objects_flush(Evas *eo_e)
|
|
|
|
{
|
2019-07-19 12:44:58 -07:00
|
|
|
Evas_Public_Data *evas = efl_data_scope_safe_get(eo_e, EVAS_CANVAS_CLASS);
|
2017-12-19 03:37:25 -08:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN(evas);
|
|
|
|
evas_render_pre(eo_e, evas);
|
|
|
|
}
|
|
|
|
|
2015-04-15 03:05:59 -07:00
|
|
|
static Eina_Bool
|
2016-12-14 22:25:43 -08:00
|
|
|
evas_render_updates_internal_loop(Evas *eo_e, Evas_Public_Data *evas,
|
2017-08-25 10:52:42 -07:00
|
|
|
void *output, void *surface, void *context,
|
2015-05-09 11:02:13 -07:00
|
|
|
Evas_Object_Protected_Data *top,
|
2015-04-15 03:05:59 -07:00
|
|
|
int ux, int uy, int uw, int uh,
|
|
|
|
int cx, int cy, int cw, int ch,
|
2017-03-22 04:51:53 -07:00
|
|
|
int fx, int fy,
|
2017-03-29 21:52:48 -07:00
|
|
|
Eina_Bool skip_cutouts, Cutout_Margin *cutout_margin,
|
2017-03-22 04:51:53 -07:00
|
|
|
Eina_Bool alpha, Eina_Bool do_async,
|
2015-10-07 18:56:35 -07:00
|
|
|
unsigned int *offset, int level)
|
2015-04-15 03:05:59 -07:00
|
|
|
{
|
|
|
|
Evas_Object *eo_obj;
|
|
|
|
Evas_Object_Protected_Data *obj;
|
|
|
|
int off_x, off_y;
|
|
|
|
unsigned int i, j;
|
|
|
|
Eina_Bool clean_them = EINA_FALSE;
|
2017-03-29 21:52:48 -07:00
|
|
|
Eina_Bool above_top = EINA_FALSE;
|
2015-04-15 03:05:59 -07:00
|
|
|
|
|
|
|
eina_evlog("+render_setup", eo_e, 0.0, NULL);
|
2015-10-07 18:56:35 -07:00
|
|
|
RD(level, " [--- UPDATE %i %i %ix%i\n", ux, uy, uw, uh);
|
2015-04-15 03:05:59 -07:00
|
|
|
|
|
|
|
off_x = cx - ux;
|
|
|
|
off_y = cy - uy;
|
|
|
|
/* build obscuring objects list (in order from bottom to top) */
|
|
|
|
if (alpha)
|
|
|
|
{
|
2017-05-12 15:03:05 -07:00
|
|
|
ENFN->context_clip_set(ENC, context, ux + off_x, uy + off_y, uw, uh);
|
2015-04-15 03:05:59 -07:00
|
|
|
}
|
2016-12-14 22:25:43 -08:00
|
|
|
for (i = 0; i < evas->obscuring_objects.count; ++i)
|
2015-04-15 03:05:59 -07:00
|
|
|
{
|
2017-03-29 21:52:48 -07:00
|
|
|
obj = eina_array_data_get(&evas->obscuring_objects, i);
|
|
|
|
if (obj == top) above_top = EINA_TRUE;
|
|
|
|
|
2015-04-15 03:05:59 -07:00
|
|
|
if (evas_object_is_in_output_rect(obj->object, obj, ux - fx, uy - fy, uw, uh))
|
|
|
|
{
|
2016-12-14 22:25:43 -08:00
|
|
|
OBJ_ARRAY_PUSH(&evas->temporary_objects, obj);
|
2015-04-15 03:05:59 -07:00
|
|
|
|
2017-03-29 21:52:48 -07:00
|
|
|
if (above_top) continue;
|
2019-05-29 12:37:07 -07:00
|
|
|
if (obj->cur->snapshot && !evas_object_is_opaque(obj))
|
2017-04-03 22:28:29 -07:00
|
|
|
continue;
|
2015-07-31 16:32:24 -07:00
|
|
|
|
2015-04-15 03:05:59 -07:00
|
|
|
/* reset the background of the area if needed (using cutout and engine alpha flag to help) */
|
2017-03-29 21:52:48 -07:00
|
|
|
if (alpha && !skip_cutouts)
|
2017-03-16 19:24:10 -07:00
|
|
|
_evas_render_cutout_add(evas, context, obj, off_x + fx, off_y + fy, cutout_margin);
|
2015-04-15 03:05:59 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (alpha)
|
|
|
|
{
|
2017-05-12 15:03:05 -07:00
|
|
|
ENFN->context_color_set(ENC, context, 0, 0, 0, 0);
|
|
|
|
ENFN->context_multiplier_unset(ENC, context);
|
|
|
|
ENFN->context_render_op_set(ENC, context, EVAS_RENDER_COPY);
|
2017-08-25 10:52:42 -07:00
|
|
|
ENFN->rectangle_draw(ENC, output, context, surface, cx, cy, cw, ch, do_async);
|
2017-05-12 15:03:05 -07:00
|
|
|
ENFN->context_cutout_clear(ENC, context);
|
|
|
|
ENFN->context_clip_unset(ENC, context);
|
2015-04-15 03:05:59 -07:00
|
|
|
}
|
|
|
|
eina_evlog("-render_setup", eo_e, 0.0, NULL);
|
|
|
|
|
|
|
|
eina_evlog("+render_objects", eo_e, 0.0, NULL);
|
|
|
|
/* render all object that intersect with rect */
|
2016-12-14 22:25:43 -08:00
|
|
|
for (i = 0; i < evas->active_objects.len; i++)
|
2015-04-15 03:05:59 -07:00
|
|
|
{
|
2016-12-14 22:25:43 -08:00
|
|
|
Evas_Active_Entry *ent = eina_inarray_nth(&evas->active_objects, i);
|
2016-11-25 21:25:41 -08:00
|
|
|
|
|
|
|
obj = ent->obj;
|
2015-04-15 03:05:59 -07:00
|
|
|
eo_obj = obj->object;
|
|
|
|
|
2015-05-09 11:02:13 -07:00
|
|
|
if (obj == top) break;
|
|
|
|
|
2015-04-15 03:05:59 -07:00
|
|
|
/* if it's in our outpout rect and it doesn't clip anything */
|
2017-01-11 04:18:59 -08:00
|
|
|
RD(level, " OBJ: %s %i %i %ix%i\n", RDNAME(obj), obj->cur->geometry.x, obj->cur->geometry.y, obj->cur->geometry.w, obj->cur->geometry.h);
|
2016-11-25 21:25:41 -08:00
|
|
|
if (
|
2015-04-15 03:05:59 -07:00
|
|
|
(!obj->clip.clipees) &&
|
|
|
|
(obj->cur->visible) &&
|
|
|
|
(obj->cur->cache.clip.visible) &&
|
2016-11-25 21:25:41 -08:00
|
|
|
#ifdef INLINE_ACTIVE_GEOM
|
|
|
|
RECTS_INTERSECT(ux - fx, uy - fy, uw, uh,
|
|
|
|
ent->rect.x, ent->rect.y,
|
|
|
|
ent->rect.w, ent->rect.h) &&
|
|
|
|
#else
|
|
|
|
(_is_obj_in_rect(eo_obj, obj, ux - fx, uy - fy, uw, uh)) &&
|
|
|
|
#endif
|
|
|
|
(!obj->delete_me) &&
|
2015-04-15 03:05:59 -07:00
|
|
|
((obj->cur->color.a > 0 || obj->cur->render_op != EVAS_RENDER_BLEND)))
|
|
|
|
{
|
|
|
|
int x, y, w, h;
|
|
|
|
|
2015-10-07 18:56:35 -07:00
|
|
|
RD(level, " DRAW (vis: %i, a: %i, clipees: %p)\n", obj->cur->visible, obj->cur->color.a, obj->clip.clipees);
|
2016-12-14 22:25:43 -08:00
|
|
|
if ((evas->temporary_objects.count > *offset) &&
|
|
|
|
(eina_array_data_get(&evas->temporary_objects, *offset) == obj))
|
2015-04-15 03:05:59 -07:00
|
|
|
(*offset)++;
|
|
|
|
x = cx; y = cy; w = cw; h = ch;
|
|
|
|
if (((w > 0) && (h > 0)) || (obj->is_smart))
|
|
|
|
{
|
2016-12-15 19:16:01 -08:00
|
|
|
Evas_Object_Protected_Data *mask;
|
2015-04-15 03:05:59 -07:00
|
|
|
|
|
|
|
if (!obj->is_smart)
|
|
|
|
{
|
2016-11-16 01:09:37 -08:00
|
|
|
int cfx, cfy;
|
|
|
|
if (!obj->is_frame)
|
|
|
|
{
|
|
|
|
cfx = obj->cur->cache.clip.x + off_x + fx;
|
|
|
|
cfy = obj->cur->cache.clip.y + off_y + fy;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
cfx = obj->cur->cache.clip.x + off_x;
|
|
|
|
cfy = obj->cur->cache.clip.y + off_y;
|
|
|
|
}
|
|
|
|
RECTS_CLIP_TO_RECT(x, y, w, h, cfx, cfy,
|
2015-04-15 03:05:59 -07:00
|
|
|
obj->cur->cache.clip.w,
|
|
|
|
obj->cur->cache.clip.h);
|
|
|
|
}
|
|
|
|
|
2017-05-12 15:03:05 -07:00
|
|
|
ENFN->context_clip_set(ENC, context, x, y, w, h);
|
2016-11-21 21:33:48 -08:00
|
|
|
|
2016-12-15 19:16:01 -08:00
|
|
|
mask = obj->clip.mask;
|
2015-04-15 03:05:59 -07:00
|
|
|
if (mask)
|
|
|
|
{
|
2016-12-15 19:16:01 -08:00
|
|
|
Evas_Object_Protected_Data *prev_mask = obj->clip.prev_mask;
|
|
|
|
|
2015-04-15 03:05:59 -07:00
|
|
|
if (mask->mask->redraw || !mask->mask->surface)
|
2017-08-25 10:52:42 -07:00
|
|
|
evas_render_mask_subrender(obj->layer->evas, output, mask, prev_mask, 4, do_async);
|
2015-04-15 03:05:59 -07:00
|
|
|
|
|
|
|
if (mask->mask->surface)
|
|
|
|
{
|
2019-05-06 13:12:48 -07:00
|
|
|
Eina_Rectangle clip = _evas_render_smallest_static_clipped_geometry_get(mask->cur);
|
2017-05-12 15:03:05 -07:00
|
|
|
ENFN->context_clip_image_set(ENC, context,
|
2016-12-14 22:25:43 -08:00
|
|
|
mask->mask->surface,
|
2019-05-06 13:12:48 -07:00
|
|
|
clip.x + off_x,
|
|
|
|
clip.y + off_y,
|
2016-12-14 22:25:43 -08:00
|
|
|
evas, do_async);
|
2015-04-15 03:05:59 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-06 18:26:22 -08:00
|
|
|
eina_evlog("+cutouts_add", obj->object, 0.0, NULL);
|
2017-03-29 21:52:48 -07:00
|
|
|
above_top = EINA_FALSE;
|
2015-04-15 03:05:59 -07:00
|
|
|
#if 1 /* FIXME: this can slow things down... figure out optimum... coverage */
|
2017-03-29 21:52:48 -07:00
|
|
|
if (!skip_cutouts)
|
2015-04-15 03:05:59 -07:00
|
|
|
{
|
2017-03-29 21:52:48 -07:00
|
|
|
for (j = *offset; j < evas->temporary_objects.count; ++j)
|
|
|
|
{
|
|
|
|
Evas_Object_Protected_Data *obj2;
|
2015-04-15 03:05:59 -07:00
|
|
|
|
2017-03-29 21:52:48 -07:00
|
|
|
obj2 = eina_array_data_get(&evas->temporary_objects, j);
|
|
|
|
if (obj2 == top) above_top = EINA_TRUE;
|
2017-04-03 22:28:29 -07:00
|
|
|
if (obj2->cur->snapshot)
|
|
|
|
{
|
|
|
|
if (above_top) continue;
|
2019-05-29 12:37:07 -07:00
|
|
|
if (!evas_object_is_opaque(obj2)) continue;
|
2017-04-03 22:28:29 -07:00
|
|
|
}
|
2015-10-04 23:51:02 -07:00
|
|
|
#if 1
|
2017-03-29 21:52:48 -07:00
|
|
|
if (
|
|
|
|
RECTS_INTERSECT
|
|
|
|
(obj->cur->cache.clip.x, obj->cur->cache.clip.y,
|
|
|
|
obj->cur->cache.clip.w, obj->cur->cache.clip.h,
|
|
|
|
obj2->cur->cache.clip.x, obj2->cur->cache.clip.y,
|
|
|
|
obj2->cur->cache.clip.w, obj2->cur->cache.clip.h) &&
|
|
|
|
RECTS_INTERSECT
|
|
|
|
(obj2->cur->cache.clip.x, obj2->cur->cache.clip.y,
|
|
|
|
obj2->cur->cache.clip.w, obj2->cur->cache.clip.h,
|
|
|
|
ux, uy, uw, uh)
|
|
|
|
)
|
2015-10-04 23:51:02 -07:00
|
|
|
#endif
|
2017-03-29 21:52:48 -07:00
|
|
|
_evas_render_cutout_add(evas, context, obj2, off_x + fx, off_y + fy, cutout_margin);
|
|
|
|
}
|
2015-04-15 03:05:59 -07:00
|
|
|
}
|
|
|
|
#endif
|
2017-05-12 15:03:05 -07:00
|
|
|
ENFN->context_cutout_target(ENC, context,
|
2016-12-30 01:55:55 -08:00
|
|
|
off_x + obj->cur->cache.clip.x,
|
|
|
|
off_y + obj->cur->cache.clip.y,
|
|
|
|
obj->cur->cache.clip.w,
|
|
|
|
obj->cur->cache.clip.h);
|
2016-11-06 18:26:22 -08:00
|
|
|
eina_evlog("-cutouts_add", obj->object, 0.0, NULL);
|
2016-12-14 22:25:43 -08:00
|
|
|
clean_them |= evas_render_mapped(evas, eo_obj, obj, context,
|
2017-08-25 10:52:42 -07:00
|
|
|
output, surface,
|
2017-08-25 10:52:38 -07:00
|
|
|
off_x + fx, off_y + fy, 0,
|
2015-04-15 03:05:59 -07:00
|
|
|
cx, cy, cw, ch,
|
2016-12-15 17:55:47 -08:00
|
|
|
NULL, level + 3, do_async);
|
2017-05-12 15:03:05 -07:00
|
|
|
ENFN->context_cutout_clear(ENC, context);
|
2015-04-15 03:05:59 -07:00
|
|
|
|
2017-05-12 15:03:05 -07:00
|
|
|
if (mask) ENFN->context_clip_image_unset(ENC, context);
|
2015-04-15 03:05:59 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
eina_evlog("-render_objects", eo_e, 0.0, NULL);
|
|
|
|
/* free obscuring objects list */
|
2016-12-14 22:25:43 -08:00
|
|
|
OBJS_ARRAY_CLEAN(&evas->temporary_objects);
|
2015-10-11 20:03:52 -07:00
|
|
|
|
|
|
|
#ifdef REND_DBG
|
2017-01-11 04:18:59 -08:00
|
|
|
if (top) RD(level, " ---] SNAPSHOT [obj:%s sfc:%p]\n", RDNAME(top), surface);
|
2015-10-07 18:56:35 -07:00
|
|
|
else RD(level, " ---]\n");
|
2015-10-11 20:03:52 -07:00
|
|
|
#endif
|
2015-04-15 03:05:59 -07:00
|
|
|
|
|
|
|
return clean_them;
|
|
|
|
}
|
|
|
|
|
2017-08-25 10:55:15 -07:00
|
|
|
typedef enum _Evas_3State
|
|
|
|
{
|
|
|
|
EVAS_3STATE_OUTSIDE,
|
|
|
|
EVAS_3STATE_INSIDE,
|
|
|
|
EVAS_3STATE_OVER
|
|
|
|
} Evas_3State;
|
|
|
|
|
|
|
|
static Evas_3State
|
|
|
|
_evas_overlay_output_find(Efl_Canvas_Output *output,
|
|
|
|
Evas_Object_Protected_Data *obj)
|
2017-08-25 10:51:20 -07:00
|
|
|
{
|
|
|
|
const Eina_Rectangle geometry = {
|
|
|
|
obj->cur->geometry.x,
|
|
|
|
obj->cur->geometry.y,
|
|
|
|
obj->cur->geometry.w,
|
|
|
|
obj->cur->geometry.h
|
|
|
|
};
|
|
|
|
Eina_Rectangle copy = geometry;
|
|
|
|
|
|
|
|
/* A video object can only be in one output at a time, check that first */
|
2017-08-25 10:55:15 -07:00
|
|
|
if (!eina_rectangle_intersection(©, &output->geometry))
|
|
|
|
return EVAS_3STATE_OUTSIDE;
|
2017-08-25 10:51:20 -07:00
|
|
|
|
2017-08-25 10:55:15 -07:00
|
|
|
if (memcmp(©, &geometry, sizeof (Eina_Rectangle)) != 0)
|
|
|
|
/* This means that it does intersect this output and another */
|
|
|
|
return EVAS_3STATE_OVER;
|
2017-08-25 10:51:20 -07:00
|
|
|
|
2017-08-25 10:55:15 -07:00
|
|
|
return EVAS_3STATE_INSIDE;
|
2017-08-25 10:51:20 -07:00
|
|
|
}
|
|
|
|
|
2018-10-22 08:30:23 -07:00
|
|
|
static void
|
|
|
|
_evas_planes(Evas_Public_Data *evas)
|
|
|
|
{
|
|
|
|
Evas_Active_Entry *ao;
|
|
|
|
|
|
|
|
/* check if individual image objects can be dropped into hardware planes */
|
|
|
|
if (ENFN->image_plane_assign)
|
|
|
|
EINA_INARRAY_FOREACH(&evas->active_objects, ao)
|
|
|
|
{
|
|
|
|
Evas_Object_Protected_Data *obj2;
|
|
|
|
Evas_Object *eo_obj2;
|
|
|
|
Efl_Canvas_Output *output;
|
|
|
|
Evas_3State state;
|
|
|
|
Eina_List *lo;
|
|
|
|
|
|
|
|
obj2 = ao->obj;
|
|
|
|
eo_obj2 = obj2->object;
|
|
|
|
|
|
|
|
if (!efl_isa(eo_obj2, EFL_CANVAS_IMAGE_INTERNAL_CLASS)) continue;
|
|
|
|
|
|
|
|
/* Find the output the object was in */
|
|
|
|
EINA_LIST_FOREACH(evas->outputs, lo, output)
|
|
|
|
{
|
|
|
|
if (!output->output) continue ;
|
|
|
|
if (!eina_list_data_find(output->planes, obj2)) continue;
|
|
|
|
_evas_object_image_plane_release(eo_obj2, obj2, output);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2019-05-29 12:36:53 -07:00
|
|
|
if (evas_object_is_visible(obj2))
|
2018-10-22 08:30:23 -07:00
|
|
|
EINA_LIST_FOREACH(evas->outputs, lo, output)
|
|
|
|
{
|
|
|
|
/* A video object can only be in one output at a time, check that first */
|
|
|
|
state = _evas_overlay_output_find(output, obj2);
|
|
|
|
if (state == EVAS_3STATE_OUTSIDE) continue;
|
|
|
|
|
|
|
|
if (!_evas_render_can_use_overlay(evas, eo_obj2, output))
|
|
|
|
{
|
|
|
|
/* This may free up things temporarily allocated by
|
|
|
|
* _can_use_overlay() testing in the engine */
|
|
|
|
_evas_object_image_plane_release(eo_obj2, obj2, output);
|
|
|
|
} else break;
|
|
|
|
}
|
2019-05-29 12:37:18 -07:00
|
|
|
if (evas_object_plane_changed(obj2))
|
2018-10-22 08:33:35 -07:00
|
|
|
{
|
|
|
|
/* Since we're lifting this object out of the scene graph
|
|
|
|
* (or putting it back), we need to force redraw of the space
|
|
|
|
* under it.
|
|
|
|
*/
|
|
|
|
_evas_canvas_damage_rectangle_add(NULL, evas,
|
|
|
|
obj2->cur->geometry.x,
|
|
|
|
obj2->cur->geometry.y,
|
|
|
|
obj2->cur->geometry.w,
|
|
|
|
obj2->cur->geometry.h);
|
|
|
|
|
|
|
|
/* We also need to clean its previously drawn position
|
|
|
|
* but only if we're removing it */
|
2019-05-29 12:37:13 -07:00
|
|
|
if (evas_object_is_on_plane(obj2))
|
2018-10-22 08:33:35 -07:00
|
|
|
_evas_canvas_damage_rectangle_add(NULL, evas,
|
|
|
|
obj2->prev->geometry.x,
|
|
|
|
obj2->prev->geometry.y,
|
|
|
|
obj2->prev->geometry.w,
|
|
|
|
obj2->prev->geometry.h);
|
|
|
|
|
|
|
|
}
|
2018-10-22 08:30:23 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-18 08:26:44 -08:00
|
|
|
static Eina_Bool
|
2012-10-08 18:58:41 -07:00
|
|
|
evas_render_updates_internal(Evas *eo_e,
|
2009-10-28 01:59:01 -07:00
|
|
|
unsigned char make_updates,
|
2012-12-18 08:26:44 -08:00
|
|
|
unsigned char do_draw,
|
|
|
|
Eina_Bool do_async)
|
2002-11-08 00:02:15 -08:00
|
|
|
{
|
2017-05-12 15:03:05 -07:00
|
|
|
// FIXME: handle multiple output
|
2012-10-08 18:58:41 -07:00
|
|
|
Evas_Object *eo_obj;
|
|
|
|
Evas_Object_Protected_Data *obj;
|
2016-12-14 22:25:43 -08:00
|
|
|
Evas_Public_Data *evas, *e;
|
2017-08-25 10:54:59 -07:00
|
|
|
Efl_Canvas_Output *out;
|
2017-08-25 10:55:15 -07:00
|
|
|
Eina_List *ll, *l;
|
2009-06-17 03:01:52 -07:00
|
|
|
Eina_Bool clean_them = EINA_FALSE;
|
2016-11-15 15:54:29 -08:00
|
|
|
Eina_Bool rendering = EINA_FALSE;
|
2009-06-26 06:26:52 -07:00
|
|
|
Eina_Bool alpha;
|
2009-06-23 06:57:27 -07:00
|
|
|
Eina_Rectangle *r;
|
2015-04-15 03:05:59 -07:00
|
|
|
unsigned int i;
|
2016-11-21 18:09:18 -08:00
|
|
|
Phase1_Context p1ctx;
|
2010-08-23 23:58:07 -07:00
|
|
|
int redraw_all = 0;
|
2015-04-15 03:05:59 -07:00
|
|
|
Evas_Render_Mode render_mode = !do_async ?
|
|
|
|
EVAS_RENDER_MODE_SYNC :
|
|
|
|
EVAS_RENDER_MODE_ASYNC_INIT;
|
2017-08-25 10:55:15 -07:00
|
|
|
Eina_Bool haveup = EINA_FALSE;
|
2005-05-21 19:49:50 -07:00
|
|
|
|
2012-10-08 18:58:41 -07:00
|
|
|
MAGIC_CHECK(eo_e, Evas, MAGIC_EVAS);
|
2012-12-18 08:26:44 -08:00
|
|
|
return EINA_FALSE;
|
2002-11-08 00:02:15 -08:00
|
|
|
MAGIC_CHECK_END();
|
2012-10-10 00:23:00 -07:00
|
|
|
|
2016-12-14 22:25:43 -08:00
|
|
|
e = evas = efl_data_scope_get(eo_e, EVAS_CANVAS_CLASS);
|
2017-05-03 16:07:34 -07:00
|
|
|
if (e->inside_post_render) return EINA_FALSE;
|
canvas render: stop render_pre/post cb if it didn't render.
Summary:
Basically, render_pre/post should be called only if rendering happens.
Unfortunately, this behavior had been broken by some mistakes.
As far as I understand after reading history carefully,
this issue introduced for fixing unpair of pre/post cbs.
In case of async render, the post callback would be triggered in
evas_render_pipe_wakeup(), it means POST callbake shouldn't be tiggered in
evas_render_updates_internal(). If that post callback were removed in
evas_render_updates_internal(), then in case of sync_render,
POST callback won't be triggered. So previously, the PRE/POST couldn't get
paired.
I guess cedric put a mistake that nothing2rendering which brought
the pre/post pair issue, even he said that patch fix the unpair of them.
(But actually that patch brought the issue!)
See this: dc841ed9b2ccf880df2d7590ea46d95e03e8752f
Whatever it was intented or not, that patch totally insane, even
non-descripting.
If we just trigger post cb only if sync render or no_rendered case,
We could make satisfication for both cases.
@fix
Reviewers: #committers, devilhorns, zmike
Reviewed By: #committers, zmike
Subscribers: cedric, #committers, zmike
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D6573
2018-07-12 06:14:32 -07:00
|
|
|
if (!e->changed) return EINA_FALSE;
|
2012-12-18 08:26:44 -08:00
|
|
|
|
2013-01-11 10:20:11 -08:00
|
|
|
if (e->rendering)
|
|
|
|
{
|
2013-01-14 12:02:43 -08:00
|
|
|
if (do_async)
|
|
|
|
return EINA_FALSE;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
WRN("Mixing render sync as already doing async "
|
|
|
|
"render! Syncing! e=%p [%s]", e,
|
|
|
|
e->engine.module->definition->name);
|
2015-05-14 01:35:22 -07:00
|
|
|
eina_evlog("+render_wait", eo_e, 0.0, NULL);
|
|
|
|
evas_render_rendering_wait(e);
|
|
|
|
eina_evlog("-render_wait", eo_e, 0.0, NULL);
|
2013-01-14 12:02:43 -08:00
|
|
|
}
|
2013-01-11 10:20:11 -08:00
|
|
|
}
|
2015-04-03 07:34:15 -07:00
|
|
|
#ifdef EVAS_RENDER_DEBUG_TIMING
|
|
|
|
double start_time = _time_get();
|
|
|
|
#endif
|
|
|
|
|
2017-08-16 04:04:07 -07:00
|
|
|
evas_render_pre(eo_e, evas);
|
|
|
|
|
2018-10-22 08:32:24 -07:00
|
|
|
_evas_planes(e);
|
|
|
|
|
2015-05-14 01:35:22 -07:00
|
|
|
eina_evlog("+render_calc", eo_e, 0.0, NULL);
|
2012-10-08 18:58:41 -07:00
|
|
|
evas_call_smarts_calculate(eo_e);
|
2015-05-14 01:35:22 -07:00
|
|
|
eina_evlog("-render_calc", eo_e, 0.0, NULL);
|
2010-04-27 06:43:10 -07:00
|
|
|
|
2015-04-16 01:36:32 -07:00
|
|
|
RD(0, "[--- RENDER EVAS (size: %ix%i): %p (eo %p)\n", e->viewport.w, e->viewport.h, e, eo_e);
|
2010-04-27 06:43:10 -07:00
|
|
|
|
2019-10-14 06:30:17 -07:00
|
|
|
_cb_always_call(eo_e, e, EVAS_CALLBACK_RENDER_PRE, NULL);
|
2012-05-16 06:21:37 -07:00
|
|
|
|
2008-05-26 06:24:24 -07:00
|
|
|
/* Check if the modified object mean recalculating every thing */
|
2008-06-04 09:42:39 -07:00
|
|
|
if (!e->invalidate)
|
2015-05-14 01:35:22 -07:00
|
|
|
{
|
|
|
|
eina_evlog("+render_pending", eo_e, 0.0, NULL);
|
|
|
|
_evas_render_check_pending_objects(&e->pending_objects, eo_e, e);
|
|
|
|
eina_evlog("-render_pending", eo_e, 0.0, NULL);
|
|
|
|
}
|
2008-05-26 06:24:24 -07:00
|
|
|
|
2002-11-08 00:02:15 -08:00
|
|
|
/* phase 1. add extra updates for changed objects */
|
2011-10-21 03:25:35 -07:00
|
|
|
if (e->invalidate || e->render_objects.count <= 0)
|
2015-05-14 01:35:22 -07:00
|
|
|
{
|
|
|
|
eina_evlog("+render_phase1", eo_e, 0.0, NULL);
|
2016-11-21 18:09:18 -08:00
|
|
|
|
|
|
|
p1ctx.e = e;
|
|
|
|
p1ctx.active_objects = &e->active_objects;
|
|
|
|
p1ctx.restack_objects = &e->restack_objects;
|
|
|
|
p1ctx.delete_objects = &e->delete_objects;
|
|
|
|
p1ctx.render_objects = &e->render_objects;
|
|
|
|
p1ctx.snapshot_objects = &e->snapshot_objects;
|
|
|
|
p1ctx.redraw_all = redraw_all;
|
|
|
|
clean_them = _evas_render_phase1_process(&p1ctx);
|
|
|
|
redraw_all = p1ctx.redraw_all;
|
2015-05-14 01:35:22 -07:00
|
|
|
eina_evlog("-render_phase1", eo_e, 0.0, NULL);
|
|
|
|
}
|
2010-04-27 06:43:10 -07:00
|
|
|
|
2015-05-14 01:35:22 -07:00
|
|
|
eina_evlog("+render_phase1_direct", eo_e, 0.0, NULL);
|
2011-10-13 02:23:42 -07:00
|
|
|
/* phase 1.8. pre render for proxy */
|
2012-10-10 00:23:00 -07:00
|
|
|
_evas_render_phase1_direct(e, &e->active_objects, &e->restack_objects,
|
2011-10-13 02:23:42 -07:00
|
|
|
&e->delete_objects, &e->render_objects);
|
2015-05-14 01:35:22 -07:00
|
|
|
eina_evlog("-render_phase1_direct", eo_e, 0.0, NULL);
|
2011-10-13 02:23:42 -07:00
|
|
|
|
2002-11-08 00:02:15 -08:00
|
|
|
/* phase 2. force updates for restacks */
|
2015-05-14 01:35:22 -07:00
|
|
|
eina_evlog("+render_phase2", eo_e, 0.0, NULL);
|
2008-05-26 06:24:24 -07:00
|
|
|
for (i = 0; i < e->restack_objects.count; ++i)
|
2002-11-08 00:02:15 -08:00
|
|
|
{
|
2011-05-20 23:23:33 -07:00
|
|
|
obj = eina_array_data_get(&e->restack_objects, i);
|
2015-02-03 21:43:14 -08:00
|
|
|
if (_evas_render_object_is_mask(obj))
|
|
|
|
_evas_mask_redraw_set(e, obj);
|
2014-01-27 08:54:25 -08:00
|
|
|
obj->func->render_pre(obj->object, obj, obj->private_data);
|
2012-10-10 00:23:00 -07:00
|
|
|
_evas_render_prev_cur_clip_cache_add(e, obj);
|
2002-11-08 00:02:15 -08:00
|
|
|
}
|
2013-05-02 00:47:16 -07:00
|
|
|
OBJS_ARRAY_CLEAN(&e->restack_objects);
|
2015-05-14 01:35:22 -07:00
|
|
|
eina_evlog("-render_phase2", eo_e, 0.0, NULL);
|
2011-12-26 15:10:27 -08:00
|
|
|
|
2002-11-08 00:02:15 -08:00
|
|
|
/* phase 3. add exposes */
|
2015-05-14 01:35:22 -07:00
|
|
|
eina_evlog("+render_phase3", eo_e, 0.0, NULL);
|
2009-04-14 02:27:27 -07:00
|
|
|
EINA_LIST_FREE(e->damages, r)
|
2002-11-08 00:02:15 -08:00
|
|
|
{
|
2017-08-25 10:49:53 -07:00
|
|
|
ENFN->output_redraws_rect_add(ENC, r->x, r->y, r->w, r->h);
|
2010-09-24 23:19:30 -07:00
|
|
|
eina_rectangle_free(r);
|
2002-11-08 00:02:15 -08:00
|
|
|
}
|
2015-05-14 01:35:22 -07:00
|
|
|
eina_evlog("-render_phase3", eo_e, 0.0, NULL);
|
2011-12-26 15:10:27 -08:00
|
|
|
|
2011-12-17 10:45:09 -08:00
|
|
|
/* phase 4. framespace, output & viewport changes */
|
2015-05-14 01:35:22 -07:00
|
|
|
eina_evlog("+render_phase4", eo_e, 0.0, NULL);
|
2003-04-17 05:05:00 -07:00
|
|
|
if (e->viewport.changed)
|
|
|
|
{
|
2017-08-25 10:49:53 -07:00
|
|
|
ENFN->output_redraws_rect_add(ENC, 0, 0, e->output.w, e->output.h);
|
2003-04-17 05:05:00 -07:00
|
|
|
}
|
2006-11-15 19:20:24 -08:00
|
|
|
if ((e->output.w != e->viewport.w) || (e->output.h != e->viewport.h))
|
|
|
|
{
|
2011-05-20 23:23:33 -07:00
|
|
|
ERR("viewport size != output size!");
|
2006-11-15 19:20:24 -08:00
|
|
|
}
|
2012-05-25 05:55:45 -07:00
|
|
|
|
|
|
|
if (e->framespace.changed)
|
2010-08-23 23:58:07 -07:00
|
|
|
{
|
2013-08-23 00:34:22 -07:00
|
|
|
/* NB: If the framespace changes, we need to add a redraw rectangle
|
2016-11-21 21:33:48 -08:00
|
|
|
* which covers the Whole viewport. This is because 'framespace' is
|
|
|
|
* defined as "the space IN the viewport which is Occupied by the
|
2013-08-23 00:34:22 -07:00
|
|
|
* window frame" */
|
2017-08-25 10:49:53 -07:00
|
|
|
ENFN->output_redraws_rect_add(ENC,
|
2016-12-14 22:25:43 -08:00
|
|
|
e->viewport.x, e->viewport.y,
|
|
|
|
e->viewport.w, e->viewport.h);
|
2012-05-25 05:55:45 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (redraw_all)
|
|
|
|
{
|
2017-08-25 10:49:53 -07:00
|
|
|
ENFN->output_redraws_rect_add(ENC, 0, 0, e->output.w, e->output.h);
|
2010-08-23 23:58:07 -07:00
|
|
|
}
|
2015-05-14 01:35:22 -07:00
|
|
|
eina_evlog("-render_phase4", eo_e, 0.0, NULL);
|
2011-12-26 15:10:27 -08:00
|
|
|
|
2003-04-17 05:05:00 -07:00
|
|
|
/* phase 5. add obscures */
|
2015-05-14 01:35:22 -07:00
|
|
|
eina_evlog("+render_phase5", eo_e, 0.0, NULL);
|
2008-10-21 09:31:05 -07:00
|
|
|
EINA_LIST_FOREACH(e->obscures, ll, r)
|
2016-11-25 17:47:34 -08:00
|
|
|
evas_render_update_del(e, r->x, r->y, r->w, r->h);
|
2016-11-14 18:22:14 -08:00
|
|
|
|
|
|
|
static int prepare = -1;
|
|
|
|
if (prepare == -1)
|
|
|
|
{
|
|
|
|
if (getenv("EVAS_PREPARE")) prepare = !!atoi(getenv("EVAS_PREPARE"));
|
|
|
|
else prepare = 1;
|
|
|
|
}
|
|
|
|
/* build obscure objects list of active objects that obscure as well
|
|
|
|
* as objects that may need data (image data loads, texture updates,
|
|
|
|
* pre-render buffers/fbo's etc.) that are not up to date yet */
|
2016-11-25 21:25:41 -08:00
|
|
|
for (i = 0; i < e->active_objects.len; i++)
|
2002-11-08 00:02:15 -08:00
|
|
|
{
|
2016-11-30 00:36:42 -08:00
|
|
|
Evas_Active_Entry *ent = eina_inarray_nth(&e->active_objects, i);
|
2016-11-25 21:25:41 -08:00
|
|
|
|
|
|
|
obj = ent->obj;
|
2012-10-08 18:58:41 -07:00
|
|
|
eo_obj = obj->object;
|
2016-11-26 23:58:56 -08:00
|
|
|
if (UNLIKELY(
|
|
|
|
(!obj->is_smart) &&
|
|
|
|
(!obj->clip.clipees) &&
|
2019-05-29 12:37:07 -07:00
|
|
|
(evas_object_is_opaque(obj) || obj->cur->snapshot ||
|
2009-02-16 20:53:03 -08:00
|
|
|
((obj->func->has_opaque_rect) &&
|
2013-07-08 17:46:15 -07:00
|
|
|
(obj->func->has_opaque_rect(eo_obj, obj, obj->private_data)))) &&
|
2019-05-29 12:36:53 -07:00
|
|
|
evas_object_is_visible(obj) &&
|
2016-11-26 23:58:56 -08:00
|
|
|
(!obj->mask->is_mask) && (!obj->clip.mask) &&
|
|
|
|
(!obj->delete_me)))
|
2013-05-02 00:47:16 -07:00
|
|
|
OBJ_ARRAY_PUSH(&e->obscuring_objects, obj);
|
2016-11-14 18:22:14 -08:00
|
|
|
if (prepare)
|
|
|
|
{
|
|
|
|
if (obj->func->render_prepare)
|
2016-11-16 19:28:52 -08:00
|
|
|
obj->func->render_prepare(eo_obj, obj, do_async);
|
2016-11-14 18:22:14 -08:00
|
|
|
}
|
2002-11-08 00:02:15 -08:00
|
|
|
}
|
2017-03-29 21:52:48 -07:00
|
|
|
if (!redraw_all)
|
|
|
|
{
|
|
|
|
for (i = 0; i < e->snapshot_objects.count; i++)
|
|
|
|
{
|
|
|
|
obj = eina_array_data_get(&e->snapshot_objects, i);
|
|
|
|
_snapshot_redraw_update(evas, obj);
|
|
|
|
}
|
|
|
|
}
|
2015-05-14 01:35:22 -07:00
|
|
|
eina_evlog("-render_phase5", eo_e, 0.0, NULL);
|
2011-10-02 20:28:52 -07:00
|
|
|
|
2017-08-25 10:55:15 -07:00
|
|
|
EINA_LIST_FOREACH(e->outputs, l, out)
|
2017-08-25 10:54:59 -07:00
|
|
|
{
|
2017-09-11 11:31:50 -07:00
|
|
|
// Avoid processing not ready output until they are
|
2018-02-21 06:07:58 -08:00
|
|
|
if (!out->output) continue;
|
2017-10-26 13:35:27 -07:00
|
|
|
// Locked output are output that should not yet be rendered
|
|
|
|
// because the tick/vsync for it doesn't allow it yet.
|
2018-02-21 06:07:58 -08:00
|
|
|
if (out->lock > 0) continue;
|
2017-09-11 11:31:50 -07:00
|
|
|
|
2017-08-25 10:55:15 -07:00
|
|
|
/* phase 6. Initialize output */
|
|
|
|
if (out->changed)
|
|
|
|
{
|
|
|
|
ENFN->output_resize(ENC, out->output,
|
|
|
|
out->geometry.w, out->geometry.h);
|
|
|
|
ENFN->output_redraws_rect_add(ENC,
|
|
|
|
out->geometry.x, out->geometry.y,
|
|
|
|
out->geometry.w, out->geometry.h);
|
|
|
|
out->changed = EINA_FALSE;
|
|
|
|
}
|
2017-08-25 10:54:19 -07:00
|
|
|
|
2017-08-25 10:55:15 -07:00
|
|
|
/* Define the output for Evas_GL operation */
|
|
|
|
if (ENFN->gl_output_set)
|
|
|
|
ENFN->gl_output_set(ENC, out->output);
|
2017-08-25 10:52:52 -07:00
|
|
|
|
2017-08-25 10:55:15 -07:00
|
|
|
/* phase 7. check if video surface should be inlined or stay in their hardware plane */
|
|
|
|
eina_evlog("+render_phase7", eo_e, 0.0, NULL);
|
|
|
|
alpha = ENFN->canvas_alpha_get(out->output);
|
2017-08-25 10:52:52 -07:00
|
|
|
|
2017-08-25 10:55:15 -07:00
|
|
|
EINA_LIST_FOREACH(e->video_objects, ll, eo_obj)
|
|
|
|
{
|
2017-08-28 18:43:33 -07:00
|
|
|
Evas_Object_Protected_Data *obj2;
|
2017-08-25 10:55:15 -07:00
|
|
|
Evas_3State state;
|
|
|
|
|
2017-08-28 18:43:33 -07:00
|
|
|
obj2 = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
|
|
|
|
state = _evas_overlay_output_find(out, obj2);
|
2017-08-25 10:55:15 -07:00
|
|
|
if (state == EVAS_3STATE_OUTSIDE) continue;
|
|
|
|
|
|
|
|
/* we need the surface to be transparent to display the underlying overlay */
|
|
|
|
if (state == EVAS_3STATE_INSIDE &&
|
|
|
|
alpha &&
|
|
|
|
_evas_render_can_use_overlay(e, eo_obj, out))
|
|
|
|
_evas_object_image_video_overlay_show(eo_obj);
|
|
|
|
else
|
|
|
|
_evas_object_image_video_overlay_hide(eo_obj);
|
|
|
|
}
|
|
|
|
eina_evlog("-render_phase7", eo_e, 0.0, NULL);
|
2017-08-25 10:52:52 -07:00
|
|
|
|
2017-08-25 10:55:15 -07:00
|
|
|
/* phase 8. go thru each update rect and render objects in it*/
|
|
|
|
eina_evlog("+render_phase8", eo_e, 0.0, NULL);
|
|
|
|
if (do_draw)
|
2011-05-20 23:23:33 -07:00
|
|
|
{
|
2017-08-25 10:55:15 -07:00
|
|
|
Render_Updates *ru;
|
|
|
|
void *surface;
|
|
|
|
int ux, uy, uw, uh;
|
|
|
|
int cx, cy, cw, ch;
|
|
|
|
unsigned int offset = 0;
|
|
|
|
int fx = e->framespace.x;
|
|
|
|
int fy = e->framespace.y;
|
|
|
|
int j;
|
|
|
|
|
2018-02-21 09:39:04 -08:00
|
|
|
DBG("Rendering output %p [%i, %i, %i, %i]\n", out,
|
|
|
|
out->geometry.x, out->geometry.y,
|
|
|
|
out->geometry.w, out->geometry.h);
|
|
|
|
|
2017-08-25 10:55:15 -07:00
|
|
|
if (do_async) _evas_render_busy_begin();
|
|
|
|
eina_evlog("+render_surface", eo_e, 0.0, NULL);
|
|
|
|
while ((surface =
|
|
|
|
ENFN->output_redraws_next_update_get
|
|
|
|
(ENC, out->output,
|
|
|
|
&ux, &uy, &uw, &uh,
|
|
|
|
&cx, &cy, &cw, &ch)))
|
|
|
|
{
|
|
|
|
void *ctx;
|
2016-12-15 17:44:47 -08:00
|
|
|
|
2017-08-25 10:55:15 -07:00
|
|
|
haveup = EINA_TRUE;
|
2014-11-12 17:47:29 -08:00
|
|
|
|
2017-12-14 10:54:10 -08:00
|
|
|
/* adjust the rendering rectangle to the output offset */
|
|
|
|
ux += out->geometry.x;
|
|
|
|
uy += out->geometry.y;
|
|
|
|
|
2018-02-21 09:39:04 -08:00
|
|
|
DBG("Surface %p offset: [%i, %i, %i, %i]\n", surface,
|
|
|
|
ux, uy, uw, uh);
|
|
|
|
|
2017-08-25 10:55:15 -07:00
|
|
|
/* phase 7.1 render every snapshot that needs to be updated
|
|
|
|
for this part of the screen */
|
|
|
|
eina_evlog("+render_snapshots", eo_e, 0.0, NULL);
|
|
|
|
for (j = e->snapshot_objects.count - 1; j >= 0; j--)
|
2015-05-09 11:02:13 -07:00
|
|
|
{
|
2017-08-25 10:55:15 -07:00
|
|
|
Evas_Object_Protected_Data *snap;
|
|
|
|
Eina_Rectangle output, cr, ur;
|
|
|
|
|
|
|
|
snap = eina_array_data_get(&e->snapshot_objects, j);
|
|
|
|
|
|
|
|
EINA_RECTANGLE_SET(&output,
|
|
|
|
snap->cur->geometry.x,
|
|
|
|
snap->cur->geometry.y,
|
|
|
|
snap->cur->geometry.w,
|
|
|
|
snap->cur->geometry.h);
|
|
|
|
EINA_RECTANGLE_SET(&ur, ux, uy, uw, uh);
|
|
|
|
|
|
|
|
// FIXME: We should render snapshots only once per frame,
|
|
|
|
// not once per update region per output !
|
|
|
|
if (snap->snapshot_needs_redraw &&
|
|
|
|
eina_rectangle_intersection(&ur, &output))
|
|
|
|
{
|
|
|
|
Cutout_Margin cm = {};
|
|
|
|
unsigned int restore_offset = offset;
|
|
|
|
Eina_Bool skip_cutouts = EINA_FALSE;
|
|
|
|
void *pseudo_canvas;
|
|
|
|
|
|
|
|
EINA_RECTANGLE_SET(&cr,
|
|
|
|
ur.x - output.x, ur.y - output.y,
|
|
|
|
ur.w, ur.h);
|
|
|
|
|
|
|
|
pseudo_canvas = _evas_object_image_surface_get(snap, EINA_TRUE);
|
|
|
|
|
|
|
|
// Get required margin for filters (eg. blur radius)
|
|
|
|
_evas_filter_radius_get(snap, &cm.l, &cm.r, &cm.t, &cm.b);
|
|
|
|
|
|
|
|
if (snap->map->cur.usemap || snap->proxy->proxies ||
|
|
|
|
snap->snapshot_no_obscure ||
|
|
|
|
((cm.l + cm.r) >= output.w) ||
|
|
|
|
((cm.t + cm.b) >= output.h))
|
|
|
|
skip_cutouts = EINA_TRUE;
|
|
|
|
|
|
|
|
RD(0, " SNAPSHOT %s [sfc:%p ur:%d,%d %dx%d]\n", RDNAME(snap), pseudo_canvas, ur.x, ur.y, ur.w, ur.h);
|
|
|
|
ctx = ENFN->context_new(ENC);
|
|
|
|
clean_them |= evas_render_updates_internal_loop(eo_e, e, out->output, pseudo_canvas, ctx,
|
|
|
|
snap,
|
|
|
|
ur.x, ur.y, ur.w, ur.h,
|
|
|
|
cr.x, cr.y, cr.w, cr.h,
|
|
|
|
fx, fy, skip_cutouts, &cm,
|
|
|
|
alpha, do_async,
|
|
|
|
&offset, 1);
|
|
|
|
ENFN->context_free(ENC, ctx);
|
|
|
|
|
|
|
|
offset = restore_offset;
|
|
|
|
}
|
2015-05-09 11:02:13 -07:00
|
|
|
}
|
2017-08-25 10:55:15 -07:00
|
|
|
eina_evlog("-render_snapshots", eo_e, 0.0, NULL);
|
2015-05-09 11:02:13 -07:00
|
|
|
|
2017-08-25 10:55:15 -07:00
|
|
|
eina_evlog("+render_update", eo_e, 0.0, NULL);
|
|
|
|
/* phase 7.2 render all the object on the target surface */
|
|
|
|
if ((do_async) || (make_updates))
|
|
|
|
{
|
|
|
|
ru = malloc(sizeof(*ru));
|
|
|
|
ru->surface = surface;
|
|
|
|
//XXX: need a way of reffing output surfaces
|
|
|
|
NEW_RECT(ru->area, ux, uy, uw, uh);
|
|
|
|
eina_spinlock_take(&(e->render.lock));
|
|
|
|
out->updates = eina_list_append(out->updates, ru);
|
|
|
|
eina_spinlock_release(&(e->render.lock));
|
|
|
|
}
|
2015-07-31 16:47:46 -07:00
|
|
|
|
2017-08-25 10:55:15 -07:00
|
|
|
ctx = ENFN->context_new(ENC);
|
|
|
|
clean_them |= evas_render_updates_internal_loop(eo_e, e, out->output, surface,
|
|
|
|
ctx, NULL,
|
|
|
|
ux, uy, uw, uh,
|
|
|
|
cx, cy, cw, ch,
|
|
|
|
fx, fy,
|
|
|
|
EINA_FALSE, NULL,
|
|
|
|
alpha, do_async,
|
|
|
|
&offset, 0);
|
|
|
|
ENFN->context_free(ENC, ctx);
|
2016-12-15 17:44:47 -08:00
|
|
|
|
2017-08-25 10:55:15 -07:00
|
|
|
eina_evlog("-render_update", eo_e, 0.0, NULL);
|
|
|
|
if (!do_async)
|
|
|
|
{
|
|
|
|
eina_evlog("+render_push", eo_e, 0.0, NULL);
|
2018-02-21 11:15:11 -08:00
|
|
|
ENFN->output_redraws_next_update_push(ENC, out->output, surface,
|
|
|
|
ux - out->geometry.x, uy - out->geometry.y, uw, uh,
|
|
|
|
render_mode);
|
2017-08-25 10:55:15 -07:00
|
|
|
eina_evlog("-render_push", eo_e, 0.0, NULL);
|
|
|
|
}
|
2015-09-15 02:26:35 -07:00
|
|
|
}
|
2017-08-25 10:55:15 -07:00
|
|
|
|
|
|
|
eina_evlog("-render_surface", eo_e, 0.0, NULL);
|
2011-05-20 23:23:33 -07:00
|
|
|
}
|
2020-03-24 10:22:09 -07:00
|
|
|
else if (make_updates)
|
|
|
|
{
|
|
|
|
Render_Updates *ru;
|
|
|
|
void *surface;
|
|
|
|
int ux, uy, uw, uh;
|
|
|
|
int cx, cy, cw, ch;
|
|
|
|
while ((surface =
|
|
|
|
ENFN->output_redraws_next_update_get
|
|
|
|
(ENC, out->output,
|
|
|
|
&ux, &uy, &uw, &uh,
|
|
|
|
&cx, &cy, &cw, &ch)))
|
|
|
|
{
|
|
|
|
haveup = EINA_TRUE;
|
|
|
|
|
|
|
|
/* adjust the rendering rectangle to the output offset */
|
|
|
|
ux += out->geometry.x;
|
|
|
|
uy += out->geometry.y;
|
|
|
|
ru = malloc(sizeof(*ru));
|
|
|
|
ru->surface = surface;
|
|
|
|
//XXX: need a way of reffing output surfaces
|
|
|
|
NEW_RECT(ru->area, ux, uy, uw, uh);
|
|
|
|
eina_spinlock_take(&(e->render.lock));
|
|
|
|
out->updates = eina_list_append(out->updates, ru);
|
|
|
|
eina_spinlock_release(&(e->render.lock));
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2017-08-25 10:55:15 -07:00
|
|
|
}
|
2012-12-18 08:26:44 -08:00
|
|
|
|
2017-08-25 10:55:15 -07:00
|
|
|
/* First process all output, then flush */
|
|
|
|
if (do_draw)
|
|
|
|
{
|
2016-11-16 11:30:16 -08:00
|
|
|
if (haveup)
|
2010-03-16 05:30:55 -07:00
|
|
|
{
|
2016-11-16 11:30:16 -08:00
|
|
|
if (do_async)
|
|
|
|
{
|
|
|
|
eina_evlog("+render_output_async_flush", eo_e, 0.0, NULL);
|
|
|
|
efl_ref(eo_e);
|
2019-01-10 13:59:26 -08:00
|
|
|
_rendering_evases = eina_list_prepend(_rendering_evases, e);
|
|
|
|
e->rendering = _rendering_evases;
|
2019-10-14 06:30:17 -07:00
|
|
|
_cb_always_call(eo_e, e, EVAS_CALLBACK_RENDER_FLUSH_PRE, NULL);
|
2017-08-25 10:55:02 -07:00
|
|
|
evas_thread_queue_flush((Evas_Thread_Command_Cb)evas_render_pipe_wakeup, e);
|
2016-11-16 11:30:16 -08:00
|
|
|
eina_evlog("-render_output_async_flush", eo_e, 0.0, NULL);
|
|
|
|
}
|
|
|
|
else
|
2013-10-01 11:35:09 -07:00
|
|
|
{
|
2016-11-16 11:30:16 -08:00
|
|
|
eina_evlog("+render_output_flush", eo_e, 0.0, NULL);
|
|
|
|
EINA_LIST_FOREACH(e->video_objects, ll, eo_obj)
|
|
|
|
{
|
|
|
|
_evas_object_image_video_overlay_do(eo_obj);
|
|
|
|
}
|
2019-10-14 06:30:17 -07:00
|
|
|
_cb_always_call(eo_e, e, EVAS_CALLBACK_RENDER_FLUSH_PRE, NULL);
|
2017-08-25 10:55:15 -07:00
|
|
|
EINA_LIST_FOREACH(e->outputs, l, out)
|
2017-09-11 11:31:50 -07:00
|
|
|
if (out->output)
|
|
|
|
ENFN->output_flush(ENC, out->output, EVAS_RENDER_MODE_SYNC);
|
2019-10-14 06:30:17 -07:00
|
|
|
_cb_always_call(eo_e, e, EVAS_CALLBACK_RENDER_FLUSH_POST, NULL);
|
2019-03-26 21:11:15 -07:00
|
|
|
_deferred_callbacks_process(eo_e, evas);
|
2016-11-16 11:30:16 -08:00
|
|
|
eina_evlog("-render_output_flush", eo_e, 0.0, NULL);
|
2013-10-01 11:35:09 -07:00
|
|
|
}
|
2010-03-16 05:30:55 -07:00
|
|
|
}
|
2016-11-16 11:30:16 -08:00
|
|
|
rendering = haveup;
|
2002-11-08 00:02:15 -08:00
|
|
|
}
|
2017-08-25 10:54:59 -07:00
|
|
|
eina_evlog("-render_phase8", eo_e, 0.0, NULL);
|
2012-12-18 08:26:44 -08:00
|
|
|
|
2015-05-14 01:35:22 -07:00
|
|
|
eina_evlog("+render_clear", eo_e, 0.0, NULL);
|
2016-11-16 11:30:16 -08:00
|
|
|
if (!do_async && rendering)
|
2012-12-18 08:26:44 -08:00
|
|
|
{
|
|
|
|
/* clear redraws */
|
2017-08-25 10:55:15 -07:00
|
|
|
EINA_LIST_FOREACH(e->outputs, l, out)
|
2017-09-11 11:31:50 -07:00
|
|
|
if (out->output)
|
|
|
|
ENFN->output_redraws_clear(ENC, out->output);
|
2012-12-18 08:26:44 -08:00
|
|
|
}
|
2015-05-14 01:35:22 -07:00
|
|
|
eina_evlog("-render_clear", eo_e, 0.0, NULL);
|
2012-12-18 08:26:44 -08:00
|
|
|
|
2002-11-08 00:02:15 -08:00
|
|
|
/* and do a post render pass */
|
2015-05-14 01:35:22 -07:00
|
|
|
eina_evlog("+render_post", eo_e, 0.0, NULL);
|
2016-11-25 21:25:41 -08:00
|
|
|
IFRD(e->active_objects.len, 0, " [--- POST RENDER\n");
|
|
|
|
for (i = 0; i < e->active_objects.len; i++)
|
2002-11-08 00:02:15 -08:00
|
|
|
{
|
2016-11-25 21:25:41 -08:00
|
|
|
Evas_Active_Entry *ent = eina_inarray_nth(&e->active_objects, i);
|
|
|
|
|
|
|
|
obj = ent->obj;
|
2012-10-08 18:58:41 -07:00
|
|
|
eo_obj = obj->object;
|
2012-05-16 06:21:37 -07:00
|
|
|
obj->pre_render_done = EINA_FALSE;
|
2017-01-11 04:18:59 -08:00
|
|
|
RD(0, " OBJ %s changed:%i do_draw:%i\n", RDNAME(obj), obj->changed, do_draw);
|
2012-10-19 05:00:57 -07:00
|
|
|
if ((clean_them) || (obj->changed && do_draw))
|
2009-11-06 00:44:49 -08:00
|
|
|
{
|
2017-01-11 04:18:59 -08:00
|
|
|
RD(0, " OBJ %s render_post()\n", RDNAME(obj));
|
2012-05-16 06:21:37 -07:00
|
|
|
obj->restack = EINA_FALSE;
|
2017-02-03 18:31:55 -08:00
|
|
|
evas_object_change_reset(obj);
|
evas image: fix non-rendered preload image.
Summary:
This is one more corner-case issue that I found,
When second image doesn't use preload (but still share the resource)
canvas engine triggers cancellation for first image preload function.
Unluckly, preload thread is cancelled on the intermediate rendering,
First image is not going to rendered, even image turn it changed states.
Because end of that frame, canvas reset/flushed all active objects.
Here changes to retain the changes status to redraw it in the next frame.
Test Plan:
img1 = image_add;
image_file_set(img1, "test.jpg");
image_preload(img1, true);
show(img);
img2 = image_add;
image_file_set(img2, "test.jpg"); //same resource
image_preload(img2, false);
show(img2);
img1 is invisible.
Reviewers: #committers
Subscribers: cedric, #reviewers, #committers
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D7157
2018-10-22 22:49:46 -07:00
|
|
|
obj->func->render_post(eo_obj, obj, obj->private_data);
|
2009-11-06 00:44:49 -08:00
|
|
|
}
|
2002-11-08 00:02:15 -08:00
|
|
|
}
|
2017-08-25 10:54:19 -07:00
|
|
|
|
2017-03-22 04:51:53 -07:00
|
|
|
for (i = 0; i < e->snapshot_objects.count; i++)
|
|
|
|
{
|
|
|
|
Evas_Object_Protected_Data *snap;
|
|
|
|
|
|
|
|
snap = eina_array_data_get(&e->snapshot_objects, i);
|
|
|
|
snap->snapshot_needs_redraw = EINA_FALSE;
|
2017-03-29 21:52:48 -07:00
|
|
|
snap->snapshot_no_obscure = EINA_FALSE;
|
2017-03-22 04:51:53 -07:00
|
|
|
}
|
2015-05-14 01:35:22 -07:00
|
|
|
eina_evlog("-render_post", eo_e, 0.0, NULL);
|
2016-11-25 21:25:41 -08:00
|
|
|
IFRD(e->active_objects.len, 0, " ---]\n");
|
2015-01-26 00:35:42 -08:00
|
|
|
|
2017-08-25 10:54:19 -07:00
|
|
|
/* Set back Evas_GL output to NULL */
|
|
|
|
/* if (ENFN->gl_output_set) */
|
|
|
|
/* ENFN->gl_output_set(ENC, NULL); */
|
|
|
|
|
2005-10-26 21:25:30 -07:00
|
|
|
/* free our obscuring object list */
|
2013-05-02 00:47:16 -07:00
|
|
|
OBJS_ARRAY_CLEAN(&e->obscuring_objects);
|
2008-06-04 09:42:39 -07:00
|
|
|
|
|
|
|
/* If some object are still marked as changed, do not remove
|
|
|
|
them from the pending list. */
|
2008-10-16 05:27:07 -07:00
|
|
|
eina_array_remove(&e->pending_objects, pending_change, NULL);
|
2008-06-04 09:42:39 -07:00
|
|
|
|
2013-12-02 23:23:05 -08:00
|
|
|
/* Reinsert parent of changed object in the pending changed state */
|
2016-11-06 18:26:22 -08:00
|
|
|
eina_evlog("+render_post_change", eo_e, 0.0, NULL);
|
2013-12-02 23:23:05 -08:00
|
|
|
for (i = 0; i < e->pending_objects.count; ++i)
|
|
|
|
{
|
|
|
|
obj = eina_array_data_get(&e->pending_objects, i);
|
|
|
|
if (obj->smart.parent)
|
|
|
|
{
|
2019-07-11 11:17:54 -07:00
|
|
|
/* these are all objects which could not be rendered because they were
|
|
|
|
* added to their smart parent in this cycle and the parent was not changed
|
|
|
|
*/
|
2013-12-02 23:23:05 -08:00
|
|
|
Evas_Object_Protected_Data *smart_parent;
|
|
|
|
|
2016-08-15 06:44:41 -07:00
|
|
|
smart_parent = efl_data_scope_get(obj->smart.parent,
|
2016-06-20 21:26:15 -07:00
|
|
|
EFL_CANVAS_OBJECT_CLASS);
|
2013-12-02 23:23:05 -08:00
|
|
|
evas_object_change(obj->smart.parent, smart_parent);
|
2019-07-11 11:17:54 -07:00
|
|
|
/* render cache must be invalidated to correctly render subobj on next pass */
|
|
|
|
evas_object_smart_render_cache_clear(obj->smart.parent);
|
2013-12-02 23:23:05 -08:00
|
|
|
}
|
2018-10-29 13:50:45 -07:00
|
|
|
obj->changed = EINA_TRUE;
|
2013-12-02 23:23:05 -08:00
|
|
|
}
|
2016-11-06 18:26:22 -08:00
|
|
|
eina_evlog("-render_post_change", eo_e, 0.0, NULL);
|
2013-12-02 23:23:05 -08:00
|
|
|
|
2016-11-06 18:26:22 -08:00
|
|
|
eina_evlog("+render_post_reset", eo_e, 0.0, NULL);
|
2011-06-13 00:34:44 -07:00
|
|
|
for (i = 0; i < e->render_objects.count; ++i)
|
|
|
|
{
|
|
|
|
obj = eina_array_data_get(&e->render_objects, i);
|
2012-10-08 18:58:41 -07:00
|
|
|
eo_obj = obj->object;
|
2012-05-16 06:21:37 -07:00
|
|
|
obj->pre_render_done = EINA_FALSE;
|
2012-09-12 11:36:08 -07:00
|
|
|
if ((obj->changed) && (do_draw))
|
|
|
|
{
|
|
|
|
obj->restack = EINA_FALSE;
|
2017-02-03 18:31:55 -08:00
|
|
|
evas_object_change_reset(obj);
|
evas image: fix non-rendered preload image.
Summary:
This is one more corner-case issue that I found,
When second image doesn't use preload (but still share the resource)
canvas engine triggers cancellation for first image preload function.
Unluckly, preload thread is cancelled on the intermediate rendering,
First image is not going to rendered, even image turn it changed states.
Because end of that frame, canvas reset/flushed all active objects.
Here changes to retain the changes status to redraw it in the next frame.
Test Plan:
img1 = image_add;
image_file_set(img1, "test.jpg");
image_preload(img1, true);
show(img);
img2 = image_add;
image_file_set(img2, "test.jpg"); //same resource
image_preload(img2, false);
show(img2);
img1 is invisible.
Reviewers: #committers
Subscribers: cedric, #reviewers, #committers
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D7157
2018-10-22 22:49:46 -07:00
|
|
|
obj->func->render_post(eo_obj, obj, obj->private_data);
|
2012-09-12 11:36:08 -07:00
|
|
|
}
|
2011-06-13 00:34:44 -07:00
|
|
|
}
|
2016-11-06 18:26:22 -08:00
|
|
|
eina_evlog("-render_post_reset", eo_e, 0.0, NULL);
|
2011-06-13 00:34:44 -07:00
|
|
|
|
2016-11-06 18:26:22 -08:00
|
|
|
eina_evlog("+render_end", eo_e, 0.0, NULL);
|
2012-05-16 06:21:37 -07:00
|
|
|
e->changed = EINA_FALSE;
|
|
|
|
e->viewport.changed = EINA_FALSE;
|
|
|
|
e->framespace.changed = EINA_FALSE;
|
|
|
|
e->invalidate = EINA_FALSE;
|
2008-06-04 09:42:39 -07:00
|
|
|
|
2012-03-20 01:08:42 -07:00
|
|
|
// always clean... lots of mem waste!
|
2010-04-27 06:43:10 -07:00
|
|
|
/* If their are some object to restack or some object to delete,
|
2009-11-09 07:18:37 -08:00
|
|
|
* it's useless to keep the render object list around. */
|
2010-05-05 04:36:21 -07:00
|
|
|
if (clean_them)
|
2008-06-04 09:42:39 -07:00
|
|
|
{
|
2016-11-25 21:25:41 -08:00
|
|
|
eina_inarray_flush(&e->active_objects);
|
2013-05-02 00:47:16 -07:00
|
|
|
OBJS_ARRAY_CLEAN(&e->render_objects);
|
|
|
|
OBJS_ARRAY_CLEAN(&e->restack_objects);
|
|
|
|
OBJS_ARRAY_CLEAN(&e->temporary_objects);
|
2015-05-09 11:02:13 -07:00
|
|
|
OBJS_ARRAY_CLEAN(&e->snapshot_objects);
|
2012-11-20 03:52:16 -08:00
|
|
|
eina_array_foreach(&e->clip_changes, _evas_clip_changes_free, NULL);
|
2012-03-20 01:08:42 -07:00
|
|
|
eina_array_clean(&e->clip_changes);
|
2012-05-16 06:21:37 -07:00
|
|
|
e->invalidate = EINA_TRUE;
|
2008-06-04 09:42:39 -07:00
|
|
|
}
|
2008-04-14 02:31:31 -07:00
|
|
|
|
2013-05-02 00:48:43 -07:00
|
|
|
/* delete all objects flagged for deletion now */
|
|
|
|
for (i = 0; i < e->delete_objects.count; ++i)
|
|
|
|
{
|
|
|
|
obj = eina_array_data_get(&e->delete_objects, i);
|
2018-05-14 16:15:48 -07:00
|
|
|
evas_object_free(obj, EINA_TRUE);
|
2013-05-02 00:48:43 -07:00
|
|
|
}
|
|
|
|
eina_array_clean(&e->delete_objects);
|
|
|
|
/* if we deleted no objects this frame or we deleted a lot (> 1024) then
|
|
|
|
* try and reset the deleted objects array to empty (no mem used) for
|
|
|
|
* efficiency */
|
|
|
|
if ((e->delete_objects.count == 0) || (e->delete_objects.count > 1024))
|
|
|
|
eina_array_flush(&e->delete_objects);
|
2016-11-21 21:33:48 -08:00
|
|
|
|
2006-09-18 02:40:29 -07:00
|
|
|
evas_module_clean();
|
2012-05-16 06:21:37 -07:00
|
|
|
|
canvas render: stop render_pre/post cb if it didn't render.
Summary:
Basically, render_pre/post should be called only if rendering happens.
Unfortunately, this behavior had been broken by some mistakes.
As far as I understand after reading history carefully,
this issue introduced for fixing unpair of pre/post cbs.
In case of async render, the post callback would be triggered in
evas_render_pipe_wakeup(), it means POST callbake shouldn't be tiggered in
evas_render_updates_internal(). If that post callback were removed in
evas_render_updates_internal(), then in case of sync_render,
POST callback won't be triggered. So previously, the PRE/POST couldn't get
paired.
I guess cedric put a mistake that nothing2rendering which brought
the pre/post pair issue, even he said that patch fix the unpair of them.
(But actually that patch brought the issue!)
See this: dc841ed9b2ccf880df2d7590ea46d95e03e8752f
Whatever it was intented or not, that patch totally insane, even
non-descripting.
If we just trigger post cb only if sync render or no_rendered case,
We could make satisfication for both cases.
@fix
Reviewers: #committers, devilhorns, zmike
Reviewed By: #committers, zmike
Subscribers: cedric, #committers, zmike
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D6573
2018-07-12 06:14:32 -07:00
|
|
|
/* Send a RENDER_POST when we are rendering synchronously or,
|
|
|
|
when do_async but no drawing. This gurantees pre-post pair. */
|
2017-05-09 15:39:58 -07:00
|
|
|
if (!do_async || !rendering)
|
2013-03-20 02:53:26 -07:00
|
|
|
{
|
|
|
|
Evas_Event_Render_Post post;
|
2017-08-28 18:43:33 -07:00
|
|
|
Eina_List *l1, *l2;
|
2016-03-31 16:52:38 -07:00
|
|
|
Render_Updates *ru;
|
2013-03-20 02:53:26 -07:00
|
|
|
|
2016-03-31 16:52:38 -07:00
|
|
|
post.updated_area = NULL;
|
2020-03-24 10:22:09 -07:00
|
|
|
if (haveup)
|
2016-03-31 16:52:38 -07:00
|
|
|
{
|
2020-03-24 10:22:09 -07:00
|
|
|
EINA_LIST_FOREACH(e->outputs, l1, out)
|
2017-08-25 10:55:02 -07:00
|
|
|
{
|
2020-03-24 10:22:09 -07:00
|
|
|
if (!out->output) continue ;
|
|
|
|
EINA_LIST_FOREACH(out->updates, l2, ru)
|
|
|
|
{
|
|
|
|
post.updated_area = eina_list_append(post.updated_area, ru->area);
|
|
|
|
//XXX: need a way of unreffing output surfaces
|
|
|
|
ru->surface = NULL;
|
|
|
|
}
|
2017-08-25 10:55:02 -07:00
|
|
|
}
|
2016-03-31 16:52:38 -07:00
|
|
|
}
|
2015-09-27 10:56:28 -07:00
|
|
|
eina_spinlock_take(&(e->render.lock));
|
2017-03-28 00:09:34 -07:00
|
|
|
e->inside_post_render = EINA_TRUE;
|
2019-10-14 06:30:17 -07:00
|
|
|
_cb_always_call(eo_e, e, EVAS_CALLBACK_RENDER_POST, &post);
|
2017-03-28 00:09:34 -07:00
|
|
|
e->inside_post_render = EINA_FALSE;
|
2015-09-27 10:56:28 -07:00
|
|
|
eina_spinlock_release(&(e->render.lock));
|
2016-03-31 16:52:38 -07:00
|
|
|
if (post.updated_area) eina_list_free(post.updated_area);
|
2013-03-20 02:53:26 -07:00
|
|
|
}
|
2008-04-14 02:31:31 -07:00
|
|
|
|
2015-01-26 00:35:42 -08:00
|
|
|
RD(0, "---]\n");
|
2010-04-27 06:43:10 -07:00
|
|
|
|
2013-01-17 06:31:34 -08:00
|
|
|
#ifdef EVAS_RENDER_DEBUG_TIMING
|
2015-04-03 07:34:15 -07:00
|
|
|
_accumulate_time(start_time, do_async);
|
2013-01-17 06:31:34 -08:00
|
|
|
#endif
|
|
|
|
|
2015-07-07 05:29:31 -07:00
|
|
|
if (!do_async) _evas_render_cleanup();
|
2016-11-06 18:26:22 -08:00
|
|
|
eina_evlog("-render_end", eo_e, 0.0, NULL);
|
2016-11-15 15:54:29 -08:00
|
|
|
return rendering;
|
2012-12-18 08:26:44 -08:00
|
|
|
}
|
|
|
|
|
2013-01-11 11:55:40 -08:00
|
|
|
static Eina_Bool
|
|
|
|
_drop_glyph_ref(const void *container EINA_UNUSED, void *data, void *fdata EINA_UNUSED)
|
|
|
|
{
|
|
|
|
evas_common_font_glyphs_unref(data);
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
2013-01-15 09:35:11 -08:00
|
|
|
static Eina_Bool
|
|
|
|
_drop_texts_ref(const void *container EINA_UNUSED, void *data, void *fdata EINA_UNUSED)
|
|
|
|
{
|
|
|
|
evas_common_font_fonts_unref(data);
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
2012-12-18 08:26:44 -08:00
|
|
|
static void
|
|
|
|
evas_render_wakeup(Evas *eo_e)
|
|
|
|
{
|
2013-03-20 02:53:26 -07:00
|
|
|
Evas_Event_Render_Post post;
|
2012-12-18 08:26:44 -08:00
|
|
|
Render_Updates *ru;
|
|
|
|
Eina_Bool haveup = EINA_FALSE;
|
2017-08-25 10:55:02 -07:00
|
|
|
Eina_List *ret_updates = NULL, *l;
|
2016-12-22 03:46:49 -08:00
|
|
|
Evas_Post_Render_Job *job;
|
2016-12-14 22:25:43 -08:00
|
|
|
Evas_Public_Data *evas;
|
2017-08-25 10:55:02 -07:00
|
|
|
Efl_Canvas_Output *out;
|
2016-12-22 03:46:49 -08:00
|
|
|
Eina_Inlist *jobs_il;
|
2016-12-14 22:25:43 -08:00
|
|
|
|
|
|
|
evas = efl_data_scope_get(eo_e, EVAS_CANVAS_CLASS);
|
2012-12-18 08:26:44 -08:00
|
|
|
|
2016-11-06 18:26:22 -08:00
|
|
|
eina_evlog("+render_wakeup", eo_e, 0.0, NULL);
|
2016-12-14 22:25:43 -08:00
|
|
|
eina_spinlock_take(&(evas->render.lock));
|
2017-08-25 10:55:02 -07:00
|
|
|
EINA_LIST_FOREACH(evas->outputs, l, out)
|
2012-12-18 08:26:44 -08:00
|
|
|
{
|
2017-09-11 11:31:50 -07:00
|
|
|
if (!out->output) continue ;
|
2017-08-25 10:55:02 -07:00
|
|
|
EINA_LIST_FREE(out->updates, ru)
|
|
|
|
{
|
|
|
|
ret_updates = eina_list_append(ret_updates, ru->area);
|
|
|
|
free(ru);
|
|
|
|
haveup = EINA_TRUE;
|
|
|
|
}
|
2012-12-18 08:26:44 -08:00
|
|
|
}
|
2016-12-14 22:25:43 -08:00
|
|
|
eina_spinlock_release(&(evas->render.lock));
|
2012-12-18 08:26:44 -08:00
|
|
|
|
|
|
|
/* flush redraws */
|
|
|
|
if (haveup)
|
|
|
|
{
|
2013-10-01 11:35:09 -07:00
|
|
|
Eina_List *ll;
|
|
|
|
Evas_Object *eo_obj;
|
2016-12-14 22:25:43 -08:00
|
|
|
EINA_LIST_FOREACH(evas->video_objects, ll, eo_obj)
|
2013-10-01 11:35:09 -07:00
|
|
|
{
|
|
|
|
_evas_object_image_video_overlay_do(eo_obj);
|
|
|
|
}
|
2019-10-14 06:30:17 -07:00
|
|
|
_cb_always_call(eo_e, evas, EVAS_CALLBACK_RENDER_FLUSH_POST, NULL);
|
2012-12-18 08:26:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* clear redraws */
|
2017-08-25 10:55:02 -07:00
|
|
|
EINA_LIST_FOREACH(evas->outputs, l, out)
|
|
|
|
{
|
2017-09-11 11:31:50 -07:00
|
|
|
if (!out->output) continue ;
|
2017-08-25 10:55:02 -07:00
|
|
|
ENFN->output_redraws_clear(ENC, out->output);
|
|
|
|
}
|
2012-12-18 08:26:44 -08:00
|
|
|
|
2013-01-11 11:55:40 -08:00
|
|
|
/* unref queues */
|
2016-12-14 22:25:43 -08:00
|
|
|
eina_array_foreach(&evas->scie_unref_queue, _drop_scie_ref, NULL);
|
|
|
|
eina_array_clean(&evas->scie_unref_queue);
|
2013-01-17 14:14:05 -08:00
|
|
|
evas_common_rgba_image_scalecache_prune();
|
|
|
|
|
2016-12-14 22:25:43 -08:00
|
|
|
eina_array_foreach(&evas->image_unref_queue, _drop_image_cache_ref, NULL);
|
|
|
|
eina_array_clean(&evas->image_unref_queue);
|
2013-01-16 14:32:39 -08:00
|
|
|
|
2016-12-14 22:25:43 -08:00
|
|
|
eina_array_foreach(&evas->glyph_unref_queue, _drop_glyph_ref, NULL);
|
|
|
|
eina_array_clean(&evas->glyph_unref_queue);
|
2013-01-16 14:32:39 -08:00
|
|
|
|
2016-12-14 22:25:43 -08:00
|
|
|
eina_array_foreach(&evas->texts_unref_queue, _drop_texts_ref, NULL);
|
|
|
|
eina_array_clean(&evas->texts_unref_queue);
|
2013-01-11 11:54:12 -08:00
|
|
|
|
2016-12-22 03:46:49 -08:00
|
|
|
SLKL(evas->post_render.lock);
|
|
|
|
jobs_il = EINA_INLIST_GET(evas->post_render.jobs);
|
|
|
|
evas->post_render.jobs = NULL;
|
|
|
|
SLKU(evas->post_render.lock);
|
2017-03-28 00:09:34 -07:00
|
|
|
|
|
|
|
evas->inside_post_render = EINA_TRUE;
|
2016-12-22 03:46:49 -08:00
|
|
|
EINA_INLIST_FREE(jobs_il, job)
|
|
|
|
{
|
|
|
|
jobs_il = eina_inlist_remove(jobs_il, EINA_INLIST_GET(job));
|
|
|
|
if (job->func)
|
|
|
|
job->func(job->data);
|
|
|
|
free(job);
|
|
|
|
}
|
|
|
|
|
2013-01-17 14:14:05 -08:00
|
|
|
/* post rendering */
|
2019-01-10 13:59:26 -08:00
|
|
|
_rendering_evases = eina_list_remove_list(_rendering_evases, evas->rendering);
|
|
|
|
evas->rendering = NULL;
|
2013-01-14 12:02:43 -08:00
|
|
|
|
2013-03-20 02:53:26 -07:00
|
|
|
post.updated_area = ret_updates;
|
2019-10-14 06:30:17 -07:00
|
|
|
_cb_always_call(eo_e, evas, EVAS_CALLBACK_RENDER_POST, &post);
|
2017-03-28 00:09:34 -07:00
|
|
|
evas->inside_post_render = EINA_FALSE;
|
evas: Defer render post callbacks added during async render
Summary:
To take screenshots, Enlightenment makes a new snapshot object, performs
a manual render, and uses the snapshot results.
Turns out if this happens while an async render is in progress, the
async render's completion triggers a render post callback on the snapshot
object even though it's never been involved in a render.
We need to defer new render post callbacks until any currently running
render completes, then add them during that render's post.
Fix T7156
Reviewers: devilhorns, zmike
Reviewed By: devilhorns, zmike
Subscribers: devilhorns, cedric, #committers, zmike
Tags: #efl
Maniphest Tasks: T7156
Differential Revision: https://phab.enlightenment.org/D6711
2018-07-31 14:02:12 -07:00
|
|
|
_deferred_callbacks_process(eo_e, evas);
|
2013-01-14 12:02:43 -08:00
|
|
|
|
2013-03-25 19:48:23 -07:00
|
|
|
evas_render_updates_free(ret_updates);
|
2012-12-18 08:26:44 -08:00
|
|
|
|
2016-11-06 18:26:22 -08:00
|
|
|
eina_evlog("-render_wakeup", eo_e, 0.0, NULL);
|
2016-08-15 06:44:41 -07:00
|
|
|
efl_unref(eo_e);
|
2015-04-03 07:34:15 -07:00
|
|
|
|
|
|
|
#ifdef EVAS_RENDER_DEBUG_TIMING
|
|
|
|
_accumulate_time(0, EINA_TRUE);
|
|
|
|
#endif
|
2012-12-18 08:26:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
evas_render_async_wakeup(void *target, Evas_Callback_Type type EINA_UNUSED, void *event_info EINA_UNUSED)
|
|
|
|
{
|
|
|
|
Evas_Public_Data *e = target;
|
|
|
|
evas_render_wakeup(e->evas);
|
2015-07-07 05:29:31 -07:00
|
|
|
_evas_render_busy_end();
|
2012-12-18 08:26:44 -08:00
|
|
|
}
|
|
|
|
|
2017-05-12 15:03:05 -07:00
|
|
|
// FIXME: This event should be per output... maybe ? maybe not ?
|
2012-12-18 08:26:44 -08:00
|
|
|
static void
|
|
|
|
evas_render_pipe_wakeup(void *data)
|
|
|
|
{
|
2017-08-25 10:55:02 -07:00
|
|
|
Eina_List *l, *ll;
|
2015-09-15 02:26:35 -07:00
|
|
|
Render_Updates *ru;
|
2016-12-14 22:25:43 -08:00
|
|
|
Evas_Public_Data *evas = data;
|
2017-08-25 10:55:02 -07:00
|
|
|
Efl_Canvas_Output *out;
|
2020-03-18 09:29:21 -07:00
|
|
|
Evas *e;
|
2015-09-15 02:26:35 -07:00
|
|
|
|
2016-12-14 22:25:43 -08:00
|
|
|
eina_evlog("+render_pipe_wakeup", evas->evas, 0.0, NULL);
|
|
|
|
eina_spinlock_take(&(evas->render.lock));
|
2020-03-18 09:29:21 -07:00
|
|
|
e = evas->evas;
|
2017-08-25 10:55:02 -07:00
|
|
|
EINA_LIST_FOREACH(evas->outputs, ll, out)
|
2016-12-14 22:25:43 -08:00
|
|
|
{
|
2017-09-11 11:31:50 -07:00
|
|
|
if (!out->output) continue ;
|
2017-08-25 10:55:02 -07:00
|
|
|
EINA_LIST_FOREACH(out->updates, l, ru)
|
|
|
|
{
|
|
|
|
eina_evlog("+render_push", evas->evas, 0.0, NULL);
|
|
|
|
ENFN->output_redraws_next_update_push
|
2018-02-21 11:15:11 -08:00
|
|
|
(ENC, out->output, ru->surface,
|
|
|
|
ru->area->x - out->geometry.x, ru->area->y - out->geometry.y,
|
|
|
|
ru->area->w, ru->area->h,
|
2017-08-25 10:55:02 -07:00
|
|
|
EVAS_RENDER_MODE_ASYNC_END);
|
|
|
|
eina_evlog("-render_push", evas->evas, 0.0, NULL);
|
|
|
|
//XXX: need a way to unref render output surfaces
|
|
|
|
ru->surface = NULL;
|
|
|
|
}
|
|
|
|
eina_evlog("+render_output_flush", evas->evas, 0.0, NULL);
|
|
|
|
ENFN->output_flush(ENC, out->output, EVAS_RENDER_MODE_ASYNC_END);
|
|
|
|
eina_evlog("-render_output_flush", evas->evas, 0.0, NULL);
|
2015-09-15 02:26:35 -07:00
|
|
|
}
|
2016-12-14 22:25:43 -08:00
|
|
|
eina_spinlock_release(&(evas->render.lock));
|
2012-12-18 08:26:44 -08:00
|
|
|
evas_async_events_put(data, 0, NULL, evas_render_async_wakeup);
|
2020-03-18 09:29:21 -07:00
|
|
|
/* use local pointer to avoid data race with 'evas' deref after releasing lock */
|
|
|
|
eina_evlog("-render_pipe_wakeup", e, 0.0, NULL);
|
2002-11-08 00:02:15 -08:00
|
|
|
}
|
|
|
|
|
2006-01-06 15:05:17 -08:00
|
|
|
EAPI void
|
2008-10-21 09:31:05 -07:00
|
|
|
evas_render_updates_free(Eina_List *updates)
|
2002-11-08 00:02:15 -08:00
|
|
|
{
|
2009-06-23 06:57:27 -07:00
|
|
|
Eina_Rectangle *r;
|
2009-04-14 05:15:07 -07:00
|
|
|
|
|
|
|
EINA_LIST_FREE(updates, r)
|
2011-05-20 23:23:33 -07:00
|
|
|
eina_rectangle_free(r);
|
2002-11-08 00:02:15 -08:00
|
|
|
}
|
|
|
|
|
2015-03-19 22:18:17 -07:00
|
|
|
EOLIAN Eina_Bool
|
|
|
|
_evas_canvas_render_async(Eo *eo_e, Evas_Public_Data *e)
|
|
|
|
{
|
2015-05-14 01:35:22 -07:00
|
|
|
Eina_Bool ret;
|
|
|
|
eina_evlog("+render_block", eo_e, 0.0, NULL);
|
2015-02-10 03:44:38 -08:00
|
|
|
evas_canvas_async_block(e);
|
2015-05-14 01:35:22 -07:00
|
|
|
eina_evlog("-render_block", eo_e, 0.0, NULL);
|
|
|
|
eina_evlog("+render", eo_e, 0.0, NULL);
|
2017-08-25 10:55:02 -07:00
|
|
|
ret = evas_render_updates_internal(eo_e, 1, 1, EINA_TRUE);
|
2015-05-14 01:35:22 -07:00
|
|
|
eina_evlog("-render", eo_e, 0.0, NULL);
|
|
|
|
return ret;
|
2012-12-18 08:26:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_List *
|
|
|
|
evas_render_updates_internal_wait(Evas *eo_e,
|
|
|
|
unsigned char make_updates,
|
|
|
|
unsigned char do_draw)
|
|
|
|
{
|
2017-08-25 10:55:02 -07:00
|
|
|
Eina_List *ret = NULL, *l;
|
|
|
|
Efl_Canvas_Output *out;
|
|
|
|
Evas_Public_Data *e;
|
|
|
|
|
|
|
|
e = efl_data_scope_get(eo_e, EVAS_CANVAS_CLASS);
|
2018-08-21 07:36:55 -07:00
|
|
|
if (!evas_render_updates_internal(eo_e, make_updates, do_draw, EINA_FALSE))
|
|
|
|
return NULL;
|
2012-12-18 08:26:44 -08:00
|
|
|
|
2015-09-27 10:56:28 -07:00
|
|
|
eina_spinlock_take(&(e->render.lock));
|
2017-08-25 10:55:02 -07:00
|
|
|
EINA_LIST_FOREACH(e->outputs, l, out)
|
|
|
|
{
|
2017-09-11 11:31:50 -07:00
|
|
|
if (!out->output) continue ;
|
2017-08-25 10:55:02 -07:00
|
|
|
ret = eina_list_merge(ret, out->updates);
|
|
|
|
out->updates = NULL;
|
|
|
|
}
|
2015-09-27 10:56:28 -07:00
|
|
|
eina_spinlock_release(&(e->render.lock));
|
2012-12-18 08:26:44 -08:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2015-02-10 03:44:38 -08:00
|
|
|
|
2014-03-11 23:53:00 -07:00
|
|
|
EOLIAN Eina_List*
|
2014-06-26 14:29:46 -07:00
|
|
|
_evas_canvas_render_updates(Eo *eo_e, Evas_Public_Data *e)
|
2012-10-08 18:58:41 -07:00
|
|
|
{
|
2016-03-31 16:52:38 -07:00
|
|
|
Eina_List *ret, *updates = NULL;
|
|
|
|
Render_Updates *ru;
|
2015-05-14 01:35:22 -07:00
|
|
|
eina_evlog("+render_block", eo_e, 0.0, NULL);
|
2015-02-10 03:44:38 -08:00
|
|
|
evas_canvas_async_block(e);
|
2015-05-14 01:35:22 -07:00
|
|
|
eina_evlog("-render_block", eo_e, 0.0, NULL);
|
|
|
|
eina_evlog("+render", eo_e, 0.0, NULL);
|
|
|
|
ret = evas_render_updates_internal_wait(eo_e, 1, 1);
|
|
|
|
eina_evlog("-render", eo_e, 0.0, NULL);
|
2016-03-31 16:52:38 -07:00
|
|
|
EINA_LIST_FREE(ret, ru)
|
|
|
|
{
|
|
|
|
updates = eina_list_append(updates, ru->area);
|
|
|
|
free(ru);
|
|
|
|
}
|
|
|
|
return updates;
|
2005-12-03 01:27:53 -08:00
|
|
|
}
|
|
|
|
|
2014-03-11 23:53:00 -07:00
|
|
|
EOLIAN void
|
2014-06-26 14:29:46 -07:00
|
|
|
_evas_canvas_render(Eo *eo_e, Evas_Public_Data *e)
|
2012-10-08 18:58:41 -07:00
|
|
|
{
|
2016-03-31 16:52:38 -07:00
|
|
|
Eina_List *ret;
|
|
|
|
Render_Updates *ru;
|
2006-09-18 02:40:29 -07:00
|
|
|
if (!e->changed) return;
|
2015-05-14 01:35:22 -07:00
|
|
|
eina_evlog("+render_block", eo_e, 0.0, NULL);
|
2015-02-10 03:44:38 -08:00
|
|
|
evas_canvas_async_block(e);
|
2015-05-14 01:35:22 -07:00
|
|
|
eina_evlog("-render_block", eo_e, 0.0, NULL);
|
|
|
|
eina_evlog("+render", eo_e, 0.0, NULL);
|
2016-03-31 16:52:38 -07:00
|
|
|
ret = evas_render_updates_internal_wait(eo_e, 0, 1);
|
2015-05-14 01:35:22 -07:00
|
|
|
eina_evlog("-render", eo_e, 0.0, NULL);
|
2016-03-31 16:52:38 -07:00
|
|
|
EINA_LIST_FREE(ret, ru)
|
|
|
|
{
|
|
|
|
eina_rectangle_free(ru->area);
|
|
|
|
free(ru);
|
|
|
|
}
|
2007-01-16 02:17:10 -08:00
|
|
|
}
|
|
|
|
|
2014-03-11 23:53:00 -07:00
|
|
|
EOLIAN void
|
2015-02-10 03:44:38 -08:00
|
|
|
_evas_canvas_norender(Eo *eo_e, Evas_Public_Data *e)
|
2012-10-08 18:58:41 -07:00
|
|
|
{
|
2018-08-21 07:36:55 -07:00
|
|
|
evas_canvas_async_block(e);
|
2020-03-25 06:27:16 -07:00
|
|
|
evas_render_updates_internal_wait(eo_e, 0, 0);
|
2002-11-08 00:02:15 -08:00
|
|
|
}
|
2007-01-16 02:17:10 -08:00
|
|
|
|
2020-03-24 10:22:12 -07:00
|
|
|
EAPI void
|
|
|
|
evas_norender_with_updates(Eo *eo_e)
|
|
|
|
{
|
|
|
|
Evas_Public_Data *e = efl_data_scope_get(eo_e, EVAS_CANVAS_CLASS);
|
|
|
|
Eina_List *ret;
|
|
|
|
Render_Updates *ru;
|
|
|
|
|
|
|
|
evas_canvas_async_block(e);
|
|
|
|
ret = evas_render_updates_internal_wait(eo_e, 1, 0);
|
|
|
|
EINA_LIST_FREE(ret, ru)
|
|
|
|
{
|
|
|
|
eina_rectangle_free(ru->area);
|
|
|
|
free(ru);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-11 23:53:00 -07:00
|
|
|
EOLIAN void
|
2016-12-14 22:25:43 -08:00
|
|
|
_evas_canvas_render_idle_flush(Eo *eo_e, Evas_Public_Data *evas)
|
2012-10-08 18:58:41 -07:00
|
|
|
{
|
2016-11-06 18:26:22 -08:00
|
|
|
eina_evlog("+idle_flush", eo_e, 0.0, NULL);
|
2018-08-21 07:36:55 -07:00
|
|
|
evas_canvas_async_block(evas);
|
2013-12-19 05:49:16 -08:00
|
|
|
|
2018-08-21 07:36:55 -07:00
|
|
|
evas_render_rendering_wait(evas);
|
2015-03-19 22:18:17 -07:00
|
|
|
|
2018-08-21 07:36:55 -07:00
|
|
|
evas_fonts_zero_pressure();
|
2015-03-19 22:18:17 -07:00
|
|
|
|
2018-08-21 07:36:55 -07:00
|
|
|
if (ENFN && ENFN->output_idle_flush)
|
|
|
|
{
|
|
|
|
Efl_Canvas_Output *output;
|
|
|
|
Eina_List *l;
|
2017-04-24 15:09:25 -07:00
|
|
|
|
2018-08-21 07:36:55 -07:00
|
|
|
EINA_LIST_FOREACH(evas->outputs, l, output)
|
|
|
|
if (output->output)
|
|
|
|
ENFN->output_idle_flush(ENC, output->output);
|
|
|
|
}
|
2015-03-19 22:18:17 -07:00
|
|
|
|
2018-08-21 07:36:55 -07:00
|
|
|
eina_inarray_flush(&evas->active_objects);
|
|
|
|
OBJS_ARRAY_FLUSH(&evas->render_objects);
|
|
|
|
OBJS_ARRAY_FLUSH(&evas->restack_objects);
|
|
|
|
OBJS_ARRAY_FLUSH(&evas->delete_objects);
|
|
|
|
OBJS_ARRAY_FLUSH(&evas->obscuring_objects);
|
|
|
|
OBJS_ARRAY_FLUSH(&evas->temporary_objects);
|
|
|
|
eina_array_foreach(&evas->clip_changes, _evas_clip_changes_free, NULL);
|
|
|
|
eina_array_clean(&evas->clip_changes);
|
2015-03-19 22:18:17 -07:00
|
|
|
|
2018-08-21 07:36:55 -07:00
|
|
|
evas->invalidate = EINA_TRUE;
|
2016-11-06 18:26:22 -08:00
|
|
|
eina_evlog("-idle_flush", eo_e, 0.0, NULL);
|
2007-06-16 19:56:59 -07:00
|
|
|
}
|
2008-05-26 06:24:24 -07:00
|
|
|
|
2014-03-11 23:53:00 -07:00
|
|
|
EOLIAN void
|
2014-06-26 14:29:46 -07:00
|
|
|
_evas_canvas_sync(Eo *eo_e, Evas_Public_Data *e)
|
2012-10-08 18:58:41 -07:00
|
|
|
{
|
2015-05-14 01:35:22 -07:00
|
|
|
eina_evlog("+render_sync", eo_e, 0.0, NULL);
|
2018-08-21 07:36:55 -07:00
|
|
|
evas_canvas_async_block(e);
|
|
|
|
evas_render_rendering_wait(e);
|
2015-05-14 01:35:22 -07:00
|
|
|
eina_evlog("-render_sync", eo_e, 0.0, NULL);
|
2012-10-08 18:58:41 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
_evas_render_dump_map_surfaces(Evas_Object *eo_obj)
|
2010-04-12 01:23:53 -07:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
|
2013-01-21 19:56:00 -08:00
|
|
|
if ((obj->map->cur.map) && obj->map->surface)
|
2010-04-12 01:23:53 -07:00
|
|
|
{
|
2016-12-14 22:25:43 -08:00
|
|
|
Evas_Public_Data *evas = obj->layer->evas;
|
2017-04-24 15:09:25 -07:00
|
|
|
ENFN->image_free(ENC, obj->map->surface);
|
2013-01-21 19:56:00 -08:00
|
|
|
EINA_COW_WRITE_BEGIN(evas_object_map_cow, obj->map, Evas_Object_Map_Data, map_write)
|
|
|
|
map_write->surface = NULL;
|
|
|
|
EINA_COW_WRITE_END(evas_object_map_cow, obj->map, map_write);
|
2010-04-12 01:23:53 -07:00
|
|
|
}
|
2010-04-27 06:43:10 -07:00
|
|
|
|
2012-10-08 18:58:41 -07:00
|
|
|
if (obj->is_smart)
|
2010-04-12 01:23:53 -07:00
|
|
|
{
|
2012-10-08 18:58:41 -07:00
|
|
|
Evas_Object_Protected_Data *obj2;
|
2010-04-27 06:43:10 -07:00
|
|
|
|
2012-10-08 18:58:41 -07:00
|
|
|
EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(eo_obj), obj2)
|
|
|
|
_evas_render_dump_map_surfaces(obj2->object);
|
2010-04-12 01:23:53 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-11 23:53:00 -07:00
|
|
|
EOLIAN void
|
2018-08-29 10:15:20 -07:00
|
|
|
_evas_canvas_render_dump(Eo *eo_e EINA_UNUSED, Evas_Public_Data *evas)
|
2012-10-08 18:58:41 -07:00
|
|
|
{
|
2018-08-21 07:36:55 -07:00
|
|
|
Evas_Layer *lay;
|
2015-03-19 22:18:17 -07:00
|
|
|
|
2018-08-21 07:36:55 -07:00
|
|
|
evas_canvas_async_block(evas);
|
2015-03-19 22:18:17 -07:00
|
|
|
|
2018-08-21 07:36:55 -07:00
|
|
|
evas_all_sync();
|
|
|
|
evas_cache_async_freeze();
|
2015-03-19 22:18:17 -07:00
|
|
|
|
2018-08-21 07:36:55 -07:00
|
|
|
EINA_INLIST_FOREACH(evas->layers, lay)
|
|
|
|
{
|
|
|
|
Evas_Object_Protected_Data *obj;
|
2015-03-19 22:18:17 -07:00
|
|
|
|
2018-08-21 07:36:55 -07:00
|
|
|
lay->walking_objects++;
|
|
|
|
EINA_INLIST_FOREACH(lay->objects, obj)
|
|
|
|
{
|
|
|
|
if (obj->proxy->surface)
|
2013-09-02 05:07:37 -07:00
|
|
|
{
|
2018-08-21 07:36:55 -07:00
|
|
|
EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, obj->proxy, Evas_Object_Proxy_Data, proxy_write)
|
2013-09-02 05:07:37 -07:00
|
|
|
{
|
2018-08-21 07:36:55 -07:00
|
|
|
ENFN->image_free(ENC, proxy_write->surface);
|
|
|
|
proxy_write->surface = NULL;
|
2013-09-02 05:07:37 -07:00
|
|
|
}
|
2018-08-21 07:36:55 -07:00
|
|
|
EINA_COW_WRITE_END(evas_object_proxy_cow, obj->proxy, proxy_write);
|
|
|
|
}
|
|
|
|
if (obj->mask->surface)
|
|
|
|
{
|
|
|
|
EINA_COW_WRITE_BEGIN(evas_object_mask_cow, obj->mask, Evas_Object_Mask_Data, mdata)
|
2015-04-26 23:56:54 -07:00
|
|
|
{
|
2018-08-21 07:36:55 -07:00
|
|
|
ENFN->image_free(ENC, mdata->surface);
|
|
|
|
mdata->surface = NULL;
|
2015-04-26 23:56:54 -07:00
|
|
|
}
|
2018-08-21 07:36:55 -07:00
|
|
|
EINA_COW_WRITE_END(evas_object_mask_cow, obj->mask, mdata);
|
2013-09-02 05:07:37 -07:00
|
|
|
}
|
2018-08-21 07:36:55 -07:00
|
|
|
if ((obj->type) && (!strcmp(obj->type, "image")))
|
|
|
|
evas_object_inform_call_image_unloaded(obj->object);
|
|
|
|
_evas_render_dump_map_surfaces(obj->object);
|
2010-12-24 08:04:27 -08:00
|
|
|
}
|
2018-08-21 07:36:55 -07:00
|
|
|
lay->walking_objects--;
|
|
|
|
_evas_layer_flush_removes(lay);
|
|
|
|
}
|
|
|
|
if (ENFN && ENFN->output_dump)
|
|
|
|
{
|
|
|
|
Efl_Canvas_Output *output;
|
|
|
|
Eina_List *l;
|
2017-04-24 15:09:25 -07:00
|
|
|
|
2018-08-21 07:36:55 -07:00
|
|
|
EINA_LIST_FOREACH(evas->outputs, l, output)
|
|
|
|
if (output->output)
|
|
|
|
ENFN->output_dump(ENC, output->output);
|
|
|
|
}
|
2013-04-01 02:39:50 -07:00
|
|
|
|
2013-12-19 05:49:16 -08:00
|
|
|
#define GC_ALL(Cow) \
|
2018-08-21 07:36:55 -07:00
|
|
|
if (Cow) while (eina_cow_gc(Cow))
|
|
|
|
GC_ALL(evas_object_proxy_cow);
|
|
|
|
GC_ALL(evas_object_map_cow);
|
|
|
|
GC_ALL(evas_object_image_pixels_cow);
|
|
|
|
GC_ALL(evas_object_image_load_opts_cow);
|
|
|
|
GC_ALL(evas_object_image_state_cow);
|
2015-03-19 22:18:17 -07:00
|
|
|
|
2018-08-21 07:36:55 -07:00
|
|
|
evas_fonts_zero_pressure();
|
2015-03-19 22:18:17 -07:00
|
|
|
|
2018-08-21 07:36:55 -07:00
|
|
|
if (ENFN && ENFN->output_idle_flush)
|
|
|
|
{
|
|
|
|
Efl_Canvas_Output *output;
|
|
|
|
Eina_List *l;
|
2017-04-24 15:09:25 -07:00
|
|
|
|
2018-08-21 07:36:55 -07:00
|
|
|
EINA_LIST_FOREACH(evas->outputs, l, output)
|
|
|
|
if (output->output)
|
|
|
|
ENFN->output_idle_flush(ENC, output->output);
|
|
|
|
}
|
2015-03-19 22:18:17 -07:00
|
|
|
|
2018-08-21 07:36:55 -07:00
|
|
|
eina_inarray_flush(&evas->active_objects);
|
|
|
|
OBJS_ARRAY_FLUSH(&evas->render_objects);
|
|
|
|
OBJS_ARRAY_FLUSH(&evas->restack_objects);
|
|
|
|
OBJS_ARRAY_FLUSH(&evas->delete_objects);
|
|
|
|
OBJS_ARRAY_FLUSH(&evas->obscuring_objects);
|
|
|
|
OBJS_ARRAY_FLUSH(&evas->temporary_objects);
|
|
|
|
eina_array_foreach(&evas->clip_changes, _evas_clip_changes_free, NULL);
|
|
|
|
eina_array_clean(&evas->clip_changes);
|
2015-03-19 22:18:17 -07:00
|
|
|
|
2018-08-21 07:36:55 -07:00
|
|
|
evas->invalidate = EINA_TRUE;
|
2015-03-19 22:18:17 -07:00
|
|
|
|
2018-08-21 07:36:55 -07:00
|
|
|
evas_cache_async_thaw();
|
2010-04-12 01:23:53 -07:00
|
|
|
}
|
|
|
|
|
2008-05-26 06:24:24 -07:00
|
|
|
void
|
2012-10-08 18:58:41 -07:00
|
|
|
evas_render_invalidate(Evas *eo_e)
|
2008-05-26 06:24:24 -07:00
|
|
|
{
|
2012-10-10 00:23:00 -07:00
|
|
|
Evas_Public_Data *e;
|
|
|
|
|
2012-10-08 18:58:41 -07:00
|
|
|
MAGIC_CHECK(eo_e, Evas, MAGIC_EVAS);
|
2008-05-26 06:24:24 -07:00
|
|
|
return;
|
|
|
|
MAGIC_CHECK_END();
|
2016-08-15 06:44:41 -07:00
|
|
|
e = efl_data_scope_get(eo_e, EVAS_CANVAS_CLASS);
|
2008-05-26 06:24:24 -07:00
|
|
|
|
2016-11-25 21:25:41 -08:00
|
|
|
eina_inarray_flush(&e->active_objects);
|
2013-05-02 00:47:16 -07:00
|
|
|
OBJS_ARRAY_CLEAN(&e->render_objects);
|
2008-06-04 09:42:39 -07:00
|
|
|
|
2013-05-02 00:47:16 -07:00
|
|
|
OBJS_ARRAY_FLUSH(&e->restack_objects);
|
|
|
|
OBJS_ARRAY_FLUSH(&e->delete_objects);
|
2015-05-09 11:02:13 -07:00
|
|
|
|
|
|
|
OBJS_ARRAY_FLUSH(&e->snapshot_objects);
|
2008-06-04 09:42:39 -07:00
|
|
|
|
2012-05-16 06:21:37 -07:00
|
|
|
e->invalidate = EINA_TRUE;
|
2008-05-26 06:24:24 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-02-20 19:24:56 -08:00
|
|
|
evas_render_object_recalc(Evas_Object_Protected_Data *obj)
|
2008-05-26 06:24:24 -07:00
|
|
|
{
|
2008-06-12 06:22:26 -07:00
|
|
|
if ((!obj->changed) && (obj->delete_me < 2))
|
2012-04-26 02:53:03 -07:00
|
|
|
{
|
2012-10-08 18:58:41 -07:00
|
|
|
Evas_Public_Data *e;
|
2012-05-16 06:21:37 -07:00
|
|
|
|
2012-04-26 02:53:03 -07:00
|
|
|
e = obj->layer->evas;
|
|
|
|
if ((!e) || (e->cleanup)) return;
|
2018-10-29 13:50:45 -07:00
|
|
|
if (!obj->in_pending_objects)
|
|
|
|
OBJ_ARRAY_PUSH(&e->pending_objects, obj);
|
|
|
|
obj->in_pending_objects = obj->changed = EINA_TRUE;
|
2012-04-26 02:53:03 -07:00
|
|
|
}
|
2008-05-26 06:24:24 -07:00
|
|
|
}
|
2011-02-06 15:50:19 -08:00
|
|
|
|
2013-01-11 11:54:12 -08:00
|
|
|
void
|
|
|
|
evas_unref_queue_image_put(Evas_Public_Data *pd, void *image)
|
|
|
|
{
|
|
|
|
eina_array_push(&pd->image_unref_queue, image);
|
2013-01-17 14:14:05 -08:00
|
|
|
evas_common_rgba_image_scalecache_items_ref(image, &pd->scie_unref_queue);
|
2013-01-11 11:54:12 -08:00
|
|
|
}
|
|
|
|
|
2013-01-11 11:55:40 -08:00
|
|
|
void
|
|
|
|
evas_unref_queue_glyph_put(Evas_Public_Data *pd, void *glyph)
|
|
|
|
{
|
|
|
|
eina_array_push(&pd->glyph_unref_queue, glyph);
|
|
|
|
}
|
|
|
|
|
2013-01-15 09:35:11 -08:00
|
|
|
void
|
|
|
|
evas_unref_queue_texts_put(Evas_Public_Data *pd, void *texts)
|
|
|
|
{
|
|
|
|
eina_array_push(&pd->texts_unref_queue, texts);
|
|
|
|
}
|
|
|
|
|
2016-12-22 03:46:49 -08:00
|
|
|
void
|
|
|
|
evas_post_render_job_add(Evas_Public_Data *pd, void (*func)(void *), void *data)
|
|
|
|
{
|
|
|
|
Evas_Post_Render_Job *job;
|
|
|
|
|
|
|
|
if (!pd || pd->delete_me) return;
|
|
|
|
if (!func) return;
|
|
|
|
|
|
|
|
job = malloc(sizeof(*job));
|
|
|
|
job->func = func;
|
|
|
|
job->data = data;
|
|
|
|
|
|
|
|
SLKL(pd->post_render.lock);
|
|
|
|
pd->post_render.jobs = (Evas_Post_Render_Job *)
|
|
|
|
eina_inlist_append(EINA_INLIST_GET(pd->post_render.jobs), EINA_INLIST_GET(job));
|
|
|
|
SLKU(pd->post_render.lock);
|
|
|
|
}
|
|
|
|
|
2011-02-06 15:50:19 -08:00
|
|
|
/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/
|
2014-03-11 23:53:00 -07:00
|
|
|
|