add ability to dump engine coontents (if engine supports it). this means

unload images it has loaded from disk, unload fonts, and more. dump dump dump!



SVN revision: 47947
This commit is contained in:
Carsten Haitzler 2010-04-12 08:23:53 +00:00
parent 02c4cbac7d
commit afe65d7c0a
20 changed files with 355 additions and 32 deletions

View File

@ -640,7 +640,7 @@ extern "C" {
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

View File

@ -128,7 +128,9 @@ EAPI void evas_cache_image_set(Evas_Cache_Image *cache, int
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);

View File

@ -1179,13 +1179,56 @@ evas_cache_image_load_data(Image_Entry *im)
#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;
}

View File

@ -111,8 +111,14 @@ _evas_map_dup(const Evas_Map *orig)
}
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);
}
@ -417,11 +423,11 @@ evas_object_map_set(Evas_Object *obj, const Evas_Map *map)
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);
@ -593,7 +599,7 @@ EAPI void
evas_map_free(Evas_Map *m)
{
if (!m) return;
_evas_map_free(m);
_evas_map_free(NULL, m);
}
/**

View File

@ -96,6 +96,8 @@ struct _Evas_Object_Textblock_Format
int tabstops;
int linesize;
double linerelsize;
int linegap;
double linerelgap;
unsigned char style;
unsigned char wrap_word : 1;
unsigned char wrap_char : 1;
@ -778,6 +780,8 @@ static const char *stylestr = NULL;
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)
@ -808,6 +812,8 @@ _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
@ -839,6 +845,8 @@ _format_command_shutdown(void)
eina_stringshare_del(tabstopsstr);
eina_stringshare_del(linesizestr);
eina_stringshare_del(linerelsizestr);
eina_stringshare_del(linegap);
eina_stringshare_del(linerelgap);
}
static void
@ -1114,6 +1122,27 @@ _format_command(Evas_Object *obj, Evas_Object_Textblock_Format *fmt, const char
}
}
}
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)
{
@ -1313,6 +1342,8 @@ _layout_format_ascent_descent_adjust(Ctxt *c, Evas_Object_Textblock_Format *fmt)
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;
}
@ -1351,6 +1382,8 @@ _layout_format_push(Ctxt *c, Evas_Object_Textblock_Format *fmt)
fmt->tabstops = 32;
fmt->linesize = 0;
fmt->linerelsize = 0.0;
fmt->linegap = 0;
fmt->linerelgap = 0.0;
}
return fmt;
}

View File

@ -1249,11 +1249,13 @@ evas_norender(Evas *e)
}
/**
* 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
*/
@ -1279,6 +1281,60 @@ evas_render_idle_flush(Evas *e)
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)
{

View File

@ -10,7 +10,8 @@
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);

View File

@ -17,8 +17,9 @@ static Eina_Hash * fonts_src = NULL;
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__,
@ -51,8 +52,7 @@ _evas_common_font_source_free(RGBA_Font_Source *fs)
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)
{
@ -60,7 +60,7 @@ font_flush_free_glyph_cb(const Eina_Hash *hash, const void *key, void *data, voi
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;
@ -68,7 +68,7 @@ font_flush_free_glyph_cb(const Eina_Hash *hash, const void *key, void *data, voi
key = 0;
fdata = 0;
}
*/
static void
_evas_common_font_int_free(RGBA_Font_Int *fi)
{
@ -76,10 +76,11 @@ _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
@ -90,7 +91,7 @@ _evas_common_font_int_free(RGBA_Font_Int *fi)
if (fi->references == 0)
fonts_lru = eina_list_remove(fonts_lru, fi);
if (fi->fash) fi->fash->freeme(fi->fash);
free(fi);
}
@ -651,6 +652,59 @@ evas_common_font_memory_hinting_add(RGBA_Font *fn, const char *name, int size, c
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)
{
@ -661,12 +715,12 @@ font_modify_cache_cb(const Eina_Hash *hash, const void *key, void *data, void *f
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
@ -675,7 +729,28 @@ EAPI void
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 +

View File

@ -39,6 +39,12 @@ evas_common_font_shutdown(void)
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)
{

View File

@ -5,6 +5,8 @@
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);

View File

@ -125,6 +125,13 @@ evas_common_image_shutdown(void)
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)
{
@ -174,10 +181,12 @@ evas_common_rgba_image_unload(Image_Entry *ie)
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;
@ -274,8 +283,9 @@ _evas_common_rgba_image_surface_delete(Image_Entry *ie)
}
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

View File

@ -581,6 +581,7 @@ struct _Evas_Func
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);

View File

@ -338,6 +338,8 @@ void evas_gl_common_texture_alpha_update(Evas_GL_Texture *tex, DATA
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);

View File

@ -1,5 +1,19 @@
#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)
{
@ -330,11 +344,18 @@ _evas_gl_common_image_update(Evas_GL_Context *gc, Evas_GL_Image *im)
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;

View File

@ -258,6 +258,17 @@ eng_output_idle_flush(void *data __UNUSED__)
{
}
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)
{
@ -1042,6 +1053,7 @@ module_open(Evas_Module *em)
ORD(context_cutout_clear);
ORD(output_flush);
ORD(output_idle_flush);
ORD(output_dump);
ORD(rectangle_draw);
ORD(line_draw);
ORD(polygon_point_add);

View File

@ -254,9 +254,20 @@ eng_output_flush(void *data)
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
@ -1230,6 +1241,7 @@ module_open(Evas_Module *em)
ORD(context_cutout_clear);
ORD(output_flush);
ORD(output_idle_flush);
ORD(output_dump);
ORD(rectangle_draw);
ORD(line_draw);
ORD(polygon_point_add);

View File

@ -551,9 +551,20 @@ eng_output_flush(void *data)
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
@ -1903,6 +1914,7 @@ module_open(Evas_Module *em)
ORD(context_cutout_clear);
ORD(output_flush);
ORD(output_idle_flush);
ORD(output_dump);
ORD(rectangle_draw);
ORD(line_draw);
ORD(polygon_point_add);

View File

@ -38,6 +38,13 @@ int _evas_soft16_log_dom = -1;
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__)
{
@ -883,6 +890,7 @@ static Evas_Func func =
NULL,
NULL,
NULL,
eng_output_dump,
/* draw context virtual methods */
eng_context_new,
eng_canvas_alpha_get,

View File

@ -10,6 +10,14 @@
*/
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__)
{
@ -1057,6 +1065,7 @@ static Evas_Func func =
NULL,
NULL,
NULL,
eng_output_dump,
/* draw context virtual methods */
eng_context_new,
eng_canvas_alpha_get,

View File

@ -686,6 +686,17 @@ eng_output_idle_flush(void *data)
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();
// 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)
{
@ -1485,6 +1496,7 @@ module_open(Evas_Module *em)
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);