EAPI void evas_render (Evas *e) EINA_ARG_NONNULL(1);
EAPI void evas_norender (Evas *e) EINA_ARG_NONNULL(1);
EAPI void evas_render_idle_flush (Evas *e) EINA_ARG_NONNULL(1);
-
+ EAPI void evas_render_dump (Evas *e) EINA_ARG_NONNULL(1);
/**
* @defgroup Evas_Output_Method Render Engine Functions
EAPI Image_Entry* evas_cache_image_alone(Image_Entry *im);
EAPI Image_Entry* evas_cache_image_dirty(Image_Entry *im, int x, int y, int w, int h);
EAPI void evas_cache_image_load_data(Image_Entry *im);
+EAPI void evas_cache_image_unload_data(Image_Entry *im);
EAPI Eina_Bool evas_cache_image_is_loaded(Image_Entry *im);
+EAPI void evas_cache_image_unload_all(Evas_Cache_Image *cache);
EAPI void evas_cache_image_surface_alloc(Image_Entry *im, int w, int h);
EAPI DATA32* evas_cache_image_pixels(Image_Entry *im);
EAPI Image_Entry* evas_cache_image_copied_data(Evas_Cache_Image *cache, int w, int h, DATA32 *image_data, int alpha, int cspace);
#endif
}
+EAPI void
+evas_cache_image_unload_data(Image_Entry *im)
+{
+ Evas_Cache_Image *cache;
+
+ assert(im);
+ assert(im->cache);
+ cache = im->cache;
+
+#ifdef BUILD_ASYNC_PRELOAD
+ LKL(im->lock);
+#endif
+ if ((!im->flags.loaded) || (!im->file) ||
+ (!im->info.module) || (im->flags.dirty))
+ {
+#ifdef BUILD_ASYNC_PRELOAD
+ LKU(im->lock);
+#endif
+ return;
+ }
+ cache->func.destructor(im);
+
+#ifdef BUILD_ASYNC_PRELOAD
+ LKU(im->lock);
+#endif
+}
+
+static Eina_Bool
+_evas_cache_image_unload_cb(__UNUSED__ const Eina_Hash *hash, __UNUSED__ const void *key, void *data, __UNUSED__ void *fdata)
+{
+ evas_cache_image_unload_data(data);
+ return EINA_TRUE;
+}
+
+EAPI void
+evas_cache_image_unload_all(Evas_Cache_Image *cache)
+{
+ Image_Entry *im;
+
+ EINA_INLIST_FOREACH(cache->lru, im) evas_cache_image_unload_data(im);
+ EINA_INLIST_FOREACH(cache->lru_nodata, im) evas_cache_image_unload_data(im);
+ eina_hash_foreach(cache->activ, _evas_cache_image_unload_cb, NULL);
+ eina_hash_foreach(cache->inactiv, _evas_cache_image_unload_cb, NULL);
+}
+
EAPI Eina_Bool
evas_cache_image_is_loaded(Image_Entry *im)
{
assert(im);
-
- if (im->flags.loaded)
- return EINA_TRUE;
+ if (im->flags.loaded) return EINA_TRUE;
return EINA_FALSE;
}
}
static inline void
-_evas_map_free(Evas_Map *m)
+_evas_map_free(Evas_Object *obj, Evas_Map *m)
{
+ if (obj)
+ {
+ if (m->surface)
+ obj->layer->evas->engine.func->image_map_surface_free
+ (obj->layer->evas->engine.data.output, m->surface);
+ }
free(m);
}
obj->prev.geometry = obj->cur.map->normal_geometry;
if (!obj->prev.map)
{
- _evas_map_free(obj->cur.map);
+ _evas_map_free(obj, obj->cur.map);
obj->cur.map = NULL;
return;
}
- _evas_map_free(obj->cur.map);
+ _evas_map_free(obj, obj->cur.map);
obj->cur.map = NULL;
if (!obj->cur.usemap) _evas_map_calc_geom_change(obj);
else _evas_map_calc_map_geometry(obj);
evas_map_free(Evas_Map *m)
{
if (!m) return;
- _evas_map_free(m);
+ _evas_map_free(NULL, m);
}
/**
int tabstops;
int linesize;
double linerelsize;
+ int linegap;
+ double linerelgap;
unsigned char style;
unsigned char wrap_word : 1;
unsigned char wrap_char : 1;
static const char *tabstopsstr = NULL;
static const char *linesizestr = NULL;
static const char *linerelsizestr = NULL;
+static const char *linegap = NULL;
+static const char *linerelgap = NULL;
static void
_format_command_init(void)
tabstopsstr = eina_stringshare_add("tabstops");
linesizestr = eina_stringshare_add("linesize");
linerelsizestr = eina_stringshare_add("linerelsize");
+ linegap = eina_stringshare_add("linegap");
+ linerelgap = eina_stringshare_add("linerelgap");
}
static void
eina_stringshare_del(tabstopsstr);
eina_stringshare_del(linesizestr);
eina_stringshare_del(linerelsizestr);
+ eina_stringshare_del(linegap);
+ eina_stringshare_del(linerelgap);
}
static void
}
}
}
+ else if (cmd == linegap)
+ {
+ fmt->linegap = atoi(tmp_param);
+ fmt->linerelgap = 0.0;
+ }
+ else if (cmd == linerelgap)
+ {
+ char *endptr = NULL;
+ double val = strtod(tmp_param, &endptr);
+ if (endptr)
+ {
+ while (*endptr && _is_white(*endptr))
+ endptr++;
+ if (*endptr == '%')
+ {
+ fmt->linerelgap = val / 100.0;
+ fmt->linegap = 0;
+ if (fmt->linerelgap < 0.0) fmt->linerelgap = 0.0;
+ }
+ }
+ }
if (new_font)
{
descent = ((ascent + descent) * fmt->linerelsize) - (ascent * fmt->linerelsize);
ascent = ascent * fmt->linerelsize;
}
+ c->maxdescent += fmt->linegap;
+ c->maxdescent += ((ascent + descent) * fmt->linerelgap);
if (c->maxascent < ascent) c->maxascent = ascent;
if (c->maxdescent < descent) c->maxdescent = descent;
}
fmt->tabstops = 32;
fmt->linesize = 0;
fmt->linerelsize = 0.0;
+ fmt->linegap = 0;
+ fmt->linerelgap = 0.0;
}
return fmt;
}
}
/**
- * Make the canvas discard internally cached data used for renderization
+ * Make the canvas discard internally cached data used for rendering.
*
* @param e The given canvas pointer.
*
* This function flushes the arrays of delete, active and render objects.
+ * Other things it may also discard are: shared memory segments,
+ * temporary scratch buffers, cached data to avoid re-compute of that data etc.
*
* @ingroup Evas_Canvas
*/
e->invalidate = 1;
}
+/**
+ * Make the canvas discard as much data as possible used by the engine at
+ * runtime.
+ *
+ * @param e The given canvas pointer.
+ *
+ * This function will unload images, delete textures and much more, where
+ * possible. You may also want to call evas_render_idle_flush() immediately
+ * prior to this to perhaps discard a little more, though evas_render_dump()
+ * should implicitly delete most of what evas_render_idle_flush() might
+ * discard too.
+ *
+ * @ingroup Evas_Canvas
+ */
+static void
+_evas_render_dump_map_surfaces(Evas_Object *obj)
+{
+ if ((obj->cur.map) && obj->cur.map->surface)
+ {
+ obj->layer->evas->engine.func->image_map_surface_free
+ (obj->layer->evas->engine.data.output, obj->cur.map->surface);
+ obj->cur.map->surface = NULL;
+ }
+
+ if (obj->smart.smart)
+ {
+ Evas_Object *obj2;
+
+ EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), obj2)
+ _evas_render_dump_map_surfaces(obj2);
+ }
+}
+
+EAPI void
+evas_render_dump(Evas *e)
+{
+ Evas_Layer *lay;
+
+ MAGIC_CHECK(e, Evas, MAGIC_EVAS);
+ return;
+ MAGIC_CHECK_END();
+
+ EINA_INLIST_FOREACH(e->layers, lay)
+ {
+ Evas_Object *obj;
+
+ EINA_INLIST_FOREACH(lay->objects, obj)
+ _evas_render_dump_map_surfaces(obj);
+ }
+ if ((e->engine.func) && (e->engine.func->output_dump) &&
+ (e->engine.data.output))
+ e->engine.func->output_dump(e->engine.data.output);
+}
+
void
evas_render_invalidate(Evas *e)
{
EAPI void evas_common_font_init (void);
EAPI void evas_common_font_shutdown (void);
-
+EAPI void evas_common_font_font_all_unload (void);
+
EAPI int evas_common_font_ascent_get (RGBA_Font *fn);
EAPI int evas_common_font_descent_get (RGBA_Font *fn);
EAPI int evas_common_font_max_ascent_get (RGBA_Font *fn);
static Eina_Hash * fonts = NULL;
static Eina_List * fonts_lru = NULL;
-static Eina_Bool font_modify_cache_cb(const Eina_Hash *hash, const void *key, void *data, void *fdata);
-static Eina_Bool font_flush_free_glyph_cb(const Eina_Hash *hash, const void *key, void *data, void *fdata);
+//static Eina_Bool font_modify_cache_cb(const Eina_Hash *hash, const void *key, void *data, void *fdata);
+//static Eina_Bool font_flush_free_glyph_cb(const Eina_Hash *hash, const void *key, void *data, void *fdata);
+static void _evas_common_font_int_clear(RGBA_Font_Int *fi);
static int
_evas_font_cache_int_cmp(const RGBA_Font_Int *k1, int k1_length __UNUSED__,
if (fs->name) eina_stringshare_del(fs->name);
free(fs);
}
-
-
+/*
static Eina_Bool
font_flush_free_glyph_cb(const Eina_Hash *hash, const void *key, void *data, void *fdata)
{
fg = data;
FT_Done_Glyph(fg->glyph);
- /* extension calls */
+ // extension calls
if (fg->ext_dat_free) fg->ext_dat_free(fg->ext_dat);
free(fg);
return 1;
key = 0;
fdata = 0;
}
-
+*/
static void
_evas_common_font_int_free(RGBA_Font_Int *fi)
{
evas_common_font_int_modify_cache_by(fi, -1);
+ _evas_common_font_int_clear(fi);
// eina_hash_foreach(fi->glyphs, font_flush_free_glyph_cb, NULL);
// eina_hash_free(fi->glyphs);
- eina_hash_free(fi->kerning);
+ eina_hash_free(fi->kerning);
// eina_hash_free(fi->indexes);
#ifdef HAVE_PTHREAD
if (fi->references == 0)
fonts_lru = eina_list_remove(fonts_lru, fi);
-
+
if (fi->fash) fi->fash->freeme(fi->fash);
free(fi);
}
return fn;
}
+static void
+_evas_common_font_int_clear(RGBA_Font_Int *fi)
+{
+ int i, j;
+
+ LKL(fi->ft_mutex);
+ if (!fi->fash)
+ {
+ LKU(fi->ft_mutex);
+ return;
+ }
+
+ evas_common_font_int_modify_cache_by(fi, -1);
+
+ for (j = 0; j <= 0xff; j++) // fixme: to do > 65k
+ {
+ Fash_Glyph_Map *fmap = fi->fash->bucket[j];
+ if (fmap)
+ {
+ for (i = 0; i <= 0xff; i++)
+ {
+ RGBA_Font_Glyph *fg = fmap->item[i];
+ if ((fg) && (fg != (void *)(-1)))
+ {
+ FT_Done_Glyph(fg->glyph);
+ /* extension calls */
+ if (fg->ext_dat_free) fg->ext_dat_free(fg->ext_dat);
+ free(fg);
+ fmap->item[i] = NULL;
+ }
+ }
+ }
+ }
+ fi->fash->freeme(fi->fash);
+ fi->fash = NULL;
+ LKU(fi->ft_mutex);
+}
+
+static Eina_Bool
+_evas_common_font_all_clear_cb(const Eina_Hash *hash, const void *key, void *data, void *fdata)
+{
+ RGBA_Font_Int *fi = data;
+ _evas_common_font_int_clear(fi);
+ return 1;
+}
+
+EAPI void
+evas_common_font_all_clear(void)
+{
+ eina_hash_foreach(fonts, _evas_common_font_all_clear_cb, NULL);
+}
+
+/*
static Eina_Bool
font_modify_cache_cb(const Eina_Hash *hash, const void *key, void *data, void *fdata)
{
dir = fdata;
font_cache_usage += (*dir) *
((fg->glyph_out->bitmap.width * fg->glyph_out->bitmap.rows) +
- sizeof(RGBA_Font_Glyph) + sizeof(Eina_List) + 400); /* fudge values */
+ sizeof(RGBA_Font_Glyph) + sizeof(Eina_List) + 400); // fudge values
return 1;
hash = 0;
key = 0;
}
-
+*/
/* when the fi->references == 0 we increase this instead of really deleting
* we then check if the cache_useage size is larger than allowed
* !If the cache is NOT too large we dont delete font_int
evas_common_font_int_modify_cache_by(RGBA_Font_Int *fi, int dir)
{
int sz_hash = 0;
-
+ int i, j;
+
+ if (fi->fash)
+ {
+ for (j = 0; j <= 0xff; j++) // fixme: to do > 65k
+ {
+ Fash_Glyph_Map *fmap = fi->fash->bucket[j];
+ if (fmap)
+ {
+ for (i = 0; i <= 0xff; i++)
+ {
+ RGBA_Font_Glyph *fg = fmap->item[i];
+ if ((fg) && (fg != (void *)(-1)))
+ sz_hash +=
+ sizeof(RGBA_Font_Glyph) + sizeof(Eina_List) +
+ (fg->glyph_out->bitmap.width *
+ fg->glyph_out->bitmap.rows) +
+ 400;
+ }
+ }
+ }
+ }
// if (fi->glyphs) sz_hash = eina_hash_population(fi->glyphs);
// eina_hash_foreach(fi->glyphs, font_modify_cache_cb, &dir);
font_cache_usage += dir * (sizeof(RGBA_Font) + sz_hash +
evas_ft_lib = 0;
}
+EAPI void
+evas_common_font_font_all_unload(void)
+{
+ evas_common_font_all_clear();
+}
+
EAPI int
evas_common_font_ascent_get(RGBA_Font *fn)
{
EAPI void evas_common_image_init (void);
EAPI void evas_common_image_shutdown (void);
+EAPI void evas_common_image_image_all_unload (void);
+
EAPI void evas_common_rgba_image_free (Image_Entry *ie);
EAPI void evas_common_rgba_image_unload (Image_Entry *ie);
EAPI void evas_common_image_colorspace_normalize (RGBA_Image *im);
evas_common_scalecache_shutdown();
}
+EAPI void
+evas_common_image_image_all_unload(void)
+{
+ evas_common_rgba_image_scalecache_flush();
+ evas_cache_image_unload_all(eci);
+}
+
static Image_Entry *
_evas_common_rgba_image_new(void)
{
RGBA_Image *im = (RGBA_Image *) ie;
evas_cache_image_preload_cancel(ie, NULL);
-
+
if (!ie->flags.loaded) return;
if ((!ie->info.module) && (!ie->data1)) return;
if (!ie->file) return;
+
+ evas_common_rgba_image_scalecache_dirty(ie);
ie->flags.loaded = 0;
}
static void
-_evas_common_rgba_image_unload(Image_Entry* im __UNUSED__)
+_evas_common_rgba_image_unload(Image_Entry *im)
{
+ evas_common_rgba_image_unload(im);
}
static void
void (*output_redraws_next_update_push) (void *data, void *surface, int x, int y, int w, int h);
void (*output_flush) (void *data);
void (*output_idle_flush) (void *data);
+ void (*output_dump) (void *data);
void *(*context_new) (void *data);
Eina_Bool (*canvas_alpha_get) (void *data, void *context);
Evas_GL_Texture *evas_gl_common_texture_yuv_new(Evas_GL_Context *gc, DATA8 **rows, int w, int h);
void evas_gl_common_texture_yuv_update(Evas_GL_Texture *tex, DATA8 **rows, int w, int h);
+void evas_gl_common_image_all_unload(Evas_GL_Context *gc);
+
Evas_GL_Image *evas_gl_common_image_load(Evas_GL_Context *gc, const char *file, const char *key, Evas_Image_Load_Opts *lo, int *error);
Evas_GL_Image *evas_gl_common_image_new_from_data(Evas_GL_Context *gc, int w, int h, DATA32 *data, int alpha, int cspace);
Evas_GL_Image *evas_gl_common_image_new_from_copied_data(Evas_GL_Context *gc, int w, int h, DATA32 *data, int alpha, int cspace);
#include "evas_gl_private.h"
+void
+evas_gl_common_image_all_unload(Evas_GL_Context *gc)
+{
+ Eina_List *l;
+ Evas_GL_Image *im;
+
+ EINA_LIST_FOREACH(gc->shared->images, l, im)
+ {
+ if (im->im) evas_cache_image_unload_data(&im->im->cache_entry);
+ if (im->tex) evas_gl_common_texture_free(im->tex);
+ im->tex = NULL;
+ }
+}
+
Evas_GL_Image *
evas_gl_common_image_load(Evas_GL_Context *gc, const char *file, const char *key, Evas_Image_Load_Opts *lo, int *error)
{
switch (im->cs.space)
{
case EVAS_COLORSPACE_ARGB8888:
- evas_cache_image_load_data(&im->im->cache_entry);
if ((im->tex) && (im->dirty))
- evas_gl_common_texture_update(im->tex, im->im);
+ {
+ evas_cache_image_load_data(&im->im->cache_entry);
+ evas_gl_common_texture_update(im->tex, im->im);
+ evas_cache_image_unload_data(&im->im->cache_entry);
+ }
if (!im->tex)
- im->tex = evas_gl_common_texture_new(gc, im->im);
+ {
+ evas_cache_image_load_data(&im->im->cache_entry);
+ im->tex = evas_gl_common_texture_new(gc, im->im);
+ evas_cache_image_unload_data(&im->im->cache_entry);
+ }
im->dirty = 0;
if (!im->tex) return;
break;
}
static void
+eng_output_dump(void *data __UNUSED__)
+{
+ Render_Engine *re;
+
+ re = (Render_Engine *)data;
+ evas_common_image_image_all_unload();
+ evas_common_font_font_all_unload();
+ evas_gl_common_image_all_unload(re->window->gl_context);
+}
+
+static void
eng_context_cutout_add(void *data __UNUSED__, void *context, int x, int y, int w, int h)
{
evas_common_draw_context_add_cutout(context, x, y, w, h);
ORD(context_cutout_clear);
ORD(output_flush);
ORD(output_idle_flush);
+ ORD(output_dump);
ORD(rectangle_draw);
ORD(line_draw);
ORD(polygon_point_add);
static void
eng_output_idle_flush(void *data)
{
-// Render_Engine *re;
-//
-// re = (Render_Engine *)data;
+ Render_Engine *re;
+
+ re = (Render_Engine *)data;
+}
+
+static void
+eng_output_dump(void *data)
+{
+ Render_Engine *re;
+
+ re = (Render_Engine *)data;
+ evas_common_image_image_all_unload();
+ evas_common_font_font_all_unload();
+ evas_gl_common_image_all_unload(re->gl_context);
}
static void
ORD(context_cutout_clear);
ORD(output_flush);
ORD(output_idle_flush);
+ ORD(output_dump);
ORD(rectangle_draw);
ORD(line_draw);
ORD(polygon_point_add);
static void
eng_output_idle_flush(void *data)
{
-// Render_Engine *re;
-//
-// re = (Render_Engine *)data;
+ Render_Engine *re;
+
+ re = (Render_Engine *)data;
+}
+
+static void
+eng_output_dump(void *data)
+{
+ Render_Engine *re;
+
+ re = (Render_Engine *)data;
+ evas_common_image_image_all_unload();
+ evas_common_font_font_all_unload();
+ evas_gl_common_image_all_unload(re->win->gl_context);
}
static void
ORD(context_cutout_clear);
ORD(output_flush);
ORD(output_idle_flush);
+ ORD(output_dump);
ORD(rectangle_draw);
ORD(line_draw);
ORD(polygon_point_add);
WRN("NOT_IMPLEMENTED: %s() at %s:%d", \
__FUNCTION__, __FILE__, __LINE__)
+static void
+eng_output_dump(void *data __UNUSED__)
+{
+ evas_common_image_image_all_unload();
+ evas_common_font_font_all_unload();
+}
+
static void *
eng_context_new(void *data __UNUSED__)
{
NULL,
NULL,
NULL,
+ eng_output_dump,
/* draw context virtual methods */
eng_context_new,
eng_canvas_alpha_get,
*/
static int cpunum = 0;
static int _evas_soft_gen_log_dom = -1;
+
+static void
+eng_output_dump(void *data __UNUSED__)
+{
+ evas_common_image_image_all_unload();
+ evas_common_font_font_all_unload();
+}
+
static void *
eng_context_new(void *data __UNUSED__)
{
NULL,
NULL,
NULL,
+ eng_output_dump,
/* draw context virtual methods */
eng_context_new,
eng_canvas_alpha_get,
}
static void
+eng_output_dump(void *data)
+{
+ Render_Engine *re;
+
+ re = (Render_Engine *)data;
+ evas_common_image_image_all_unload();
+ evas_common_font_font_all_unload();
+ // FIXME: kill pixmaps too - but... xrender engine is dead... no? :):)
+}
+
+static void
eng_rectangle_draw(void *data, void *context, void *surface, int x, int y, int w, int h)
{
Render_Engine *re;
ORD(output_redraws_next_update_push);
ORD(output_flush);
ORD(output_idle_flush);
+ ORD(output_dump);
ORD(rectangle_draw);
ORD(line_draw);
ORD(polygon_draw);