123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760 |
- /*
- Copyright (C) 2009-2010 Samsung Electronics
- Copyright (C) 2009-2010 ProFUSION embedded systems
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
- You should have received a copy of the GNU Library General Public License
- along with this library; see the file COPYING.LIB. If not, write to
- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
- */
- #define __STDC_FORMAT_MACROS
- #include "config.h"
- #include "ewk_private.h"
- #include "ewk_tiled_backing_store_private.h"
- #include "ewk_tiled_model_private.h"
- #include <Ecore_Evas.h>
- #include <Eina.h>
- #include <eina_safety_checks.h>
- #include <errno.h>
- #include <inttypes.h>
- #include <stdlib.h>
- #include <string.h>
- #ifdef TILE_STATS_ACCOUNT_RENDER_TIME
- #include <sys/time.h>
- #endif
- #define IDX(col, row, rowspan) (col + (rowidth * rowspan))
- #ifdef DEBUG_MEM_LEAKS
- static uint64_t tiles_allocated = 0;
- static uint64_t tiles_freed = 0;
- static uint64_t bytes_allocated = 0;
- static uint64_t bytes_freed = 0;
- struct tile_account {
- Evas_Coord size;
- struct {
- uint64_t allocated;
- uint64_t freed;
- } tiles, bytes;
- };
- static size_t accounting_len = 0;
- static struct tile_account* accounting = 0;
- static inline struct tile_account* _ewk_tile_account_get(const Ewk_Tile* tile)
- {
- struct tile_account* acc;
- for (size_t i = 0; i < accounting_len; i++) {
- if (accounting[i].size == tile->width)
- return accounting + i;
- }
- accounting = static_cast<struct tile_account*>(realloc(accounting, sizeof(struct tile_account) * (accounting_len + 1)));
- acc = accounting + accounting_len;
- acc->size = tile->width;
- acc->tiles.allocated = 0;
- acc->tiles.freed = 0;
- acc->bytes.allocated = 0;
- acc->bytes.freed = 0;
- accounting_len++;
- return acc;
- }
- static inline void _ewk_tile_account_allocated(const Ewk_Tile* tile)
- {
- struct tile_account* acc = _ewk_tile_account_get(tile);
- if (!acc)
- return;
- acc->bytes.allocated += tile->bytes;
- acc->tiles.allocated++;
- bytes_allocated += tile->bytes;
- tiles_allocated++;
- }
- static inline void _ewk_tile_account_freed(const Ewk_Tile* tile)
- {
- struct tile_account* acc = _ewk_tile_account_get(tile);
- if (!acc)
- return;
- acc->bytes.freed += tile->bytes;
- acc->tiles.freed++;
- bytes_freed += tile->bytes;
- tiles_freed++;
- }
- void ewk_tile_accounting_dbg()
- {
- struct tile_account* acc;
- struct tile_account* acc_end;
- printf("TILE BALANCE: tiles[+%" PRIu64 ",-%" PRIu64 ":%" PRIu64 "] "
- "bytes[+%" PRIu64 ",-%" PRIu64 ":%" PRIu64 "]\n",
- tiles_allocated, tiles_freed, tiles_allocated - tiles_freed,
- bytes_allocated, bytes_freed, bytes_allocated - bytes_freed);
- if (!accounting_len)
- return;
- acc = accounting;
- acc_end = acc + accounting_len;
- printf("BEGIN: TILE BALANCE DETAILS (TO THIS MOMENT!):\n");
- for (; acc < acc_end; acc++) {
- uint64_t tiles, bytes;
- tiles = acc->tiles.allocated - acc->tiles.freed;
- bytes = acc->bytes.allocated - acc->bytes.freed;
- printf(" %4d: tiles[+%4" PRIu64 ",-%4" PRIu64 ":%4" PRIu64 "] "
- "bytes[+%8" PRIu64 ",-%8" PRIu64 ":%8" PRIu64 "]%s\n",
- acc->size,
- acc->tiles.allocated, acc->tiles.freed, tiles,
- acc->bytes.allocated, acc->bytes.freed, bytes,
- (bytes || tiles) ? " POSSIBLE LEAK" : "");
- }
- printf("END: TILE BALANCE DETAILS (TO THIS MOMENT!):\n");
- }
- #else
- static inline void _ewk_tile_account_allocated(const Ewk_Tile*) { }
- static inline void _ewk_tile_account_freed(const Ewk_Tile*) { }
- void ewk_tile_accounting_dbg()
- {
- printf("compile webkit with DEBUG_MEM_LEAKS defined!\n");
- }
- #endif
- /**
- * Create a new tile of given size, zoom level and colorspace.
- *
- * After created these properties are immutable as they're the basic
- * characteristic of the tile and any change will lead to invalid
- * memory access.
- *
- * Other members are of free-access and no getters/setters are
- * provided in orderr to avoid expensive operations on those, however
- * some are better manipulated with provided functions, such as
- * ewk_tile_show() and ewk_tile_hide() to change
- * @c visible or ewk_tile_update_full(), ewk_tile_update_area(),
- * ewk_tile_updates_clear() to change @c stats.misses,
- * @c stats.full_update and @c updates.
- */
- Ewk_Tile* ewk_tile_new(Evas* evas, Evas_Coord width, Evas_Coord height, float zoom, Evas_Colorspace colorSpace)
- {
- Evas_Coord* evasCoord;
- Evas_Colorspace* evasColorSpace;
- float* tileZoom;
- size_t* tileSize;
- Ewk_Tile* tile;
- unsigned int area;
- size_t bytes;
- Ecore_Evas* ecoreEvas;
- const char* engine;
- area = width * height;
- if (colorSpace == EVAS_COLORSPACE_ARGB8888)
- bytes = area * 4;
- else if (colorSpace == EVAS_COLORSPACE_RGB565_A5P)
- bytes = area * 2;
- else {
- ERR("unknown color space: %d", colorSpace);
- return 0;
- }
- DBG("size: %dx%d (%d), zoom: %f, cspace=%d", width, height, area, (double)zoom, colorSpace);
- tile = static_cast<Ewk_Tile*>(malloc(sizeof(Ewk_Tile)));
- if (!tile)
- return 0;
- tile->image = evas_object_image_add(evas);
- ecoreEvas = ecore_evas_ecore_evas_get(evas);
- engine = ecore_evas_engine_name_get(ecoreEvas);
- if (engine && !strcmp(engine, "opengl_x11"))
- evas_object_image_content_hint_set(tile->image, EVAS_IMAGE_CONTENT_HINT_DYNAMIC);
- tile->visible = 0;
- tile->updates = 0;
- memset(&tile->stats, 0, sizeof(Ewk_Tile_Stats));
- tile->stats.area = area;
- /* ugly, but let's avoid at all costs having users to modify those */
- evasCoord = (Evas_Coord*)&tile->width;
- *evasCoord = width;
- evasCoord = (Evas_Coord*)&tile->height;
- *evasCoord = height;
- evasColorSpace = (Evas_Colorspace*)&tile->cspace;
- *evasColorSpace = colorSpace;
- tileZoom = (float*)&tile->zoom;
- *tileZoom = zoom;
- tileSize = (size_t*)&tile->bytes;
- *tileSize = bytes;
- evas_object_image_size_set(tile->image, tile->width, tile->height);
- evas_object_image_colorspace_set(tile->image, tile->cspace);
- _ewk_tile_account_allocated(tile);
- return tile;
- }
- /**
- * Free tile memory.
- */
- void ewk_tile_free(Ewk_Tile* tile)
- {
- _ewk_tile_account_freed(tile);
- if (tile->updates)
- eina_tiler_free(tile->updates);
- evas_object_del(tile->image);
- free(tile);
- }
- /**
- * @internal
- * Returns memory size used by given tile
- *
- * @param t tile to size check
- * @return Returns used memory or zero if object is NULL.
- */
- size_t ewk_tile_memory_size_get(const Ewk_Tile* tile)
- {
- EINA_SAFETY_ON_NULL_RETURN_VAL(tile, 0);
- return sizeof(Ewk_Tile) + tile->bytes;
- }
- /**
- * Make the tile visible, incrementing its counter.
- */
- void ewk_tile_show(Ewk_Tile* tile)
- {
- tile->visible++;
- evas_object_show(tile->image);
- }
- /**
- * Decrement the visibility counter, making it invisible if necessary.
- */
- void ewk_tile_hide(Ewk_Tile* tile)
- {
- tile->visible--;
- if (!tile->visible)
- evas_object_hide(tile->image);
- }
- /**
- * Returns true if the tile is visible, false otherwise.
- */
- Eina_Bool ewk_tile_visible_get(Ewk_Tile* tile)
- {
- return !!tile->visible;
- }
- /**
- * Mark whole tile as dirty and requiring update.
- */
- void ewk_tile_update_full(Ewk_Tile* tile)
- {
- /* TODO: list of tiles pending updates? */
- tile->stats.misses++;
- if (!tile->stats.full_update) {
- tile->stats.full_update = true;
- if (tile->updates) {
- eina_tiler_free(tile->updates);
- tile->updates = 0;
- }
- }
- }
- /**
- * Mark the specific subarea as dirty and requiring update.
- */
- void ewk_tile_update_area(Ewk_Tile* tile, const Eina_Rectangle* rect)
- {
- /* TODO: list of tiles pending updates? */
- tile->stats.misses++;
- if (tile->stats.full_update)
- return;
- if (!rect->x && !rect->y && rect->w == tile->width && rect->h == tile->height) {
- tile->stats.full_update = true;
- if (tile->updates) {
- eina_tiler_free(tile->updates);
- tile->updates = 0;
- }
- return;
- }
- if (!tile->updates) {
- tile->updates = eina_tiler_new(tile->width, tile->height);
- if (!tile->updates) {
- CRITICAL("could not create eina_tiler %dx%d.", tile->width, tile->height);
- return;
- }
- }
- eina_tiler_rect_add(tile->updates, rect);
- }
- /**
- * For each updated region, call the given function.
- *
- * This will not change the tile statistics or clear the processed
- * updates, use ewk_tile_updates_clear() for that.
- */
- void ewk_tile_updates_process(Ewk_Tile* tile, void (*callback)(void* data, Ewk_Tile* tile, const Eina_Rectangle* update), const void* data)
- {
- if (tile->stats.full_update) {
- Eina_Rectangle rect;
- rect.x = 0;
- rect.y = 0;
- rect.w = tile->width;
- rect.h = tile->height;
- #ifdef TILE_STATS_ACCOUNT_RENDER_TIME
- struct timeval timev;
- double renderStartTime;
- gettimeofday(&timev, 0);
- renderStartTime = (double)timev.tv_sec +
- (((double)timev.tv_usec) / 1000000);
- #endif
- callback((void*)data, tile, &rect);
- #ifdef TILE_STATS_ACCOUNT_RENDER_TIME
- gettimeofday(&timev, 0);
- tile->stats.render_time = (double)timev.tv_sec +
- (((double)timev.tv_usec) / 1000000) - renderStartTime;
- #endif
- } else if (tile->updates) {
- Eina_Iterator* itr = eina_tiler_iterator_new(tile->updates);
- Eina_Rectangle* rect;
- if (!itr) {
- CRITICAL("could not create tiler iterator!");
- return;
- }
- EINA_ITERATOR_FOREACH(itr, rect)
- callback((void*)data, tile, rect);
- eina_iterator_free(itr);
- }
- }
- /**
- * Clear all updates in region, if any.
- *
- * This will change the tile statistics, specially zero stat.misses
- * and unset stats.full_update. If tile->updates existed, then it will be
- * destroyed.
- *
- * This function is usually called after ewk_tile_updates_process() is
- * called.
- */
- void ewk_tile_updates_clear(Ewk_Tile* tile)
- {
- /* TODO: remove from list of pending updates? */
- tile->stats.misses = 0;
- if (tile->stats.full_update)
- tile->stats.full_update = 0;
- else if (tile->updates) {
- eina_tiler_free(tile->updates);
- tile->updates = 0;
- }
- }
- typedef struct _Ewk_Tile_Unused_Cache_Entry Ewk_Tile_Unused_Cache_Entry;
- struct _Ewk_Tile_Unused_Cache_Entry {
- Ewk_Tile* tile;
- int weight;
- struct {
- void (*callback)(void* data, Ewk_Tile* tile);
- void* data;
- } tile_free;
- };
- struct _Ewk_Tile_Unused_Cache {
- struct {
- Eina_List* list;
- size_t count;
- size_t allocated;
- } entries;
- struct {
- size_t max; /**< watermark (in bytes) to start freeing tiles */
- size_t used; /**< in bytes, maybe more than max. */
- } memory;
- struct {
- Evas_Coord x, y, width, height;
- float zoom;
- Eina_Bool locked;
- } locked;
- int references;
- unsigned int frozen;
- };
- static const size_t TILE_UNUSED_CACHE_ALLOCATE_INITIAL = 128;
- static const size_t TILE_UNUSED_CACHE_ALLOCATE_STEP = 16;
- static const size_t TILE_UNUSED_CACHE_MAX_FREE = 32;
- /**
- * Cache of unused tiles (those that are not visible).
- *
- * The cache of unused tiles.
- *
- * @param max cache size in bytes.
- *
- * @return newly allocated cache of unused tiles, use
- * ewk_tile_unused_cache_free() to release resources. If not
- * possible to allocate memory, @c 0 is returned.
- */
- Ewk_Tile_Unused_Cache* ewk_tile_unused_cache_new(size_t max)
- {
- Ewk_Tile_Unused_Cache* tileUnusedCache;
- tileUnusedCache = new Ewk_Tile_Unused_Cache;
- memset(tileUnusedCache, 0, sizeof(Ewk_Tile_Unused_Cache));
- DBG("tileUnusedCache=%p", tileUnusedCache);
- tileUnusedCache->memory.max = max;
- tileUnusedCache->references = 1;
- return tileUnusedCache;
- }
- void ewk_tile_unused_cache_lock_area(Ewk_Tile_Unused_Cache* tileUnusedCache, Evas_Coord x, Evas_Coord y, Evas_Coord width, Evas_Coord height, float zoom)
- {
- EINA_SAFETY_ON_NULL_RETURN(tileUnusedCache);
- tileUnusedCache->locked.locked = true;
- tileUnusedCache->locked.x = x;
- tileUnusedCache->locked.y = y;
- tileUnusedCache->locked.width = width;
- tileUnusedCache->locked.height = height;
- tileUnusedCache->locked.zoom = zoom;
- }
- void ewk_tile_unused_cache_unlock_area(Ewk_Tile_Unused_Cache* tileUnusedCache)
- {
- EINA_SAFETY_ON_NULL_RETURN(tileUnusedCache);
- tileUnusedCache->locked.locked = false;
- }
- /**
- * Free cache of unused tiles.
- *
- * This function should be only called by ewk_tile_unused_cache_unref
- * function. Calling this function without considering reference counting
- * may lead to unknown results.
- *
- * Those tiles that are still visible will remain live. The unused
- * tiles will be freed.
- *
- * @see ewk_tile_unused_cache_unref()
- */
- static void _ewk_tile_unused_cache_free(Ewk_Tile_Unused_Cache* tileUnusedCache)
- {
- EINA_SAFETY_ON_NULL_RETURN(tileUnusedCache);
- DBG("tileUnusedCache=%p, "
- "entries=(count:%zd, allocated:%zd), "
- "memory=(max:%zd, used:%zd)",
- tileUnusedCache, tileUnusedCache->entries.count, tileUnusedCache->entries.allocated,
- tileUnusedCache->memory.max, tileUnusedCache->memory.used);
- ewk_tile_unused_cache_clear(tileUnusedCache);
- delete tileUnusedCache;
- }
- /**
- * Clear cache of unused tiles.
- *
- * Any tiles that are in the cache are freed. The only tiles that are
- * kept are those that aren't in the cache (i.e. that are visible).
- */
- void ewk_tile_unused_cache_clear(Ewk_Tile_Unused_Cache* tileUnusedCache)
- {
- EINA_SAFETY_ON_NULL_RETURN(tileUnusedCache);
- if (!tileUnusedCache->entries.count)
- return;
- void* item;
- EINA_LIST_FREE(tileUnusedCache->entries.list, item) {
- Ewk_Tile_Unused_Cache_Entry* itr = static_cast<Ewk_Tile_Unused_Cache_Entry*>(item);
- itr->tile_free.callback(itr->tile_free.data, itr->tile);
- delete itr;
- }
- tileUnusedCache->memory.used = 0;
- tileUnusedCache->entries.count = 0;
- }
- /**
- * Hold reference to cache.
- *
- * @return same pointer as taken.
- *
- * @see ewk_tile_unused_cache_unref()
- */
- Ewk_Tile_Unused_Cache* ewk_tile_unused_cache_ref(Ewk_Tile_Unused_Cache* tileUnusedCache)
- {
- EINA_SAFETY_ON_NULL_RETURN_VAL(tileUnusedCache, 0);
- tileUnusedCache->references++;
- return tileUnusedCache;
- }
- /**
- * Release cache reference, freeing it if it drops to zero.
- *
- * @see ewk_tile_unused_cache_ref()
- * @see ewk_tile_unused_cache_free()
- */
- void ewk_tile_unused_cache_unref(Ewk_Tile_Unused_Cache* tileUnusedCache)
- {
- EINA_SAFETY_ON_NULL_RETURN(tileUnusedCache);
- tileUnusedCache->references--;
- if (!tileUnusedCache->references)
- _ewk_tile_unused_cache_free(tileUnusedCache);
- }
- void ewk_tile_unused_cache_max_set(Ewk_Tile_Unused_Cache* tileUnusedCache, size_t max)
- {
- EINA_SAFETY_ON_NULL_RETURN(tileUnusedCache);
- size_t oldMax = tileUnusedCache->memory.max;
- tileUnusedCache->memory.max = max;
- /* Cache flush when new max is lower then old one */
- if (oldMax > max)
- ewk_tile_unused_cache_auto_flush(tileUnusedCache);
- }
- size_t ewk_tile_unused_cache_max_get(const Ewk_Tile_Unused_Cache* tileUnusedCache)
- {
- EINA_SAFETY_ON_NULL_RETURN_VAL(tileUnusedCache, 0);
- return tileUnusedCache->memory.max;
- }
- size_t ewk_tile_unused_cache_used_get(const Ewk_Tile_Unused_Cache* tileUnusedCache)
- {
- EINA_SAFETY_ON_NULL_RETURN_VAL(tileUnusedCache, 0);
- return tileUnusedCache->memory.used;
- }
- size_t ewk_tile_unused_cache_flush(Ewk_Tile_Unused_Cache* tileUnusedCache, size_t bytes)
- {
- Eina_List* list, * listNext;
- EINA_SAFETY_ON_NULL_RETURN_VAL(tileUnusedCache, 0);
- size_t done;
- unsigned int count;
- if (!tileUnusedCache->entries.count)
- return 0;
- if (bytes < 1)
- return 0;
- /*
- * NOTE: the cache is a FIFO queue currently.
- * Don't need to sort any more.
- */
- void* item;
- done = 0;
- count = 0;
- EINA_LIST_FOREACH_SAFE(tileUnusedCache->entries.list, list, listNext, item) {
- Ewk_Tile_Unused_Cache_Entry* itr = static_cast<Ewk_Tile_Unused_Cache_Entry*>(item);
- Ewk_Tile* tile = itr->tile;
- if (done > bytes)
- break;
- if (tileUnusedCache->locked.locked
- && tile->x + tile->width > tileUnusedCache->locked.x
- && tile->y + tile->height > tileUnusedCache->locked.y
- && tile->x < tileUnusedCache->locked.x + tileUnusedCache->locked.width
- && tile->y < tileUnusedCache->locked.y + tileUnusedCache->locked.height
- && tile->zoom == tileUnusedCache->locked.zoom) {
- continue;
- }
- done += ewk_tile_memory_size_get(itr->tile);
- itr->tile_free.callback(itr->tile_free.data, itr->tile);
- tileUnusedCache->entries.list = eina_list_remove_list(tileUnusedCache->entries.list, list);
- delete itr;
- count++;
- }
- tileUnusedCache->memory.used -= done;
- tileUnusedCache->entries.count -= count;
- return done;
- }
- void ewk_tile_unused_cache_auto_flush(Ewk_Tile_Unused_Cache* tileUnusedCache)
- {
- EINA_SAFETY_ON_NULL_RETURN(tileUnusedCache);
- if (tileUnusedCache->memory.used <= tileUnusedCache->memory.max)
- return;
- ewk_tile_unused_cache_flush(tileUnusedCache, tileUnusedCache->memory.used - tileUnusedCache->memory.max);
- if (tileUnusedCache->memory.used > tileUnusedCache->memory.max)
- CRITICAL("Cache still using too much memory: %zd KB; max: %zd KB",
- tileUnusedCache->memory.used, tileUnusedCache->memory.max);
- }
- /**
- * Freeze cache to not do maintenance tasks.
- *
- * Maintenance tasks optimize cache usage, but maybe we know we should
- * hold on them until we do the last operation, in this case we freeze
- * while operating and then thaw when we're done.
- *
- * @see ewk_tile_unused_cache_thaw()
- */
- void ewk_tile_unused_cache_freeze(Ewk_Tile_Unused_Cache* tileUnusedCache)
- {
- tileUnusedCache->frozen++;
- }
- /**
- * Unfreezes maintenance tasks.
- *
- * If this is the last counterpart of freeze, then maintenance tasks
- * will run immediately.
- */
- void ewk_tile_unused_cache_thaw(Ewk_Tile_Unused_Cache* tileUnusedCache)
- {
- if (!tileUnusedCache->frozen) {
- ERR("thawing more than freezing!");
- return;
- }
- tileUnusedCache->frozen--;
- }
- /**
- * Get tile from cache of unused tiles, removing it from the cache.
- *
- * If the tile is used, then it's not in cache of unused tiles, so it
- * is removed from the cache and may be given back with
- * ewk_tile_unused_cache_tile_put().
- *
- * @param tileUnusedCache cache of unused tiles
- * @param tile the tile to be removed from Ewk_Tile_Unused_Cache.
- *
- * @return #true on success, #false otherwise.
- */
- Eina_Bool ewk_tile_unused_cache_tile_get(Ewk_Tile_Unused_Cache* tileUnusedCache, Ewk_Tile* tile)
- {
- Eina_List* iterateEntry;
- void* item;
- EINA_LIST_FOREACH(tileUnusedCache->entries.list, iterateEntry, item) {
- Ewk_Tile_Unused_Cache_Entry* entry = static_cast<Ewk_Tile_Unused_Cache_Entry*>(item);
- if (entry->tile == tile) {
- tileUnusedCache->entries.count--;
- tileUnusedCache->memory.used -= ewk_tile_memory_size_get(tile);
- tileUnusedCache->entries.list = eina_list_remove_list(tileUnusedCache->entries.list, iterateEntry);
- delete entry;
- return true;
- }
- }
- ERR("tile %p not found in cache %p", tile, tileUnusedCache);
- return false;
- }
- /**
- * Put tile into cache of unused tiles, adding it to the cache.
- *
- * This should be called when @c tile->visible is @c 0 and no objects are
- * using the tile anymore, making it available to be expired and have
- * its memory replaced.
- *
- * Note that tiles are not automatically deleted if cache is full,
- * instead the cache will have more bytes used than maximum and one
- * can call ewk_tile_unused_cache_auto_flush() to free them. This is done
- * because usually we want a lazy operation for better performance.
- *
- * @param tileUnusedCache cache of unused tiles
- * @param tile tile to be added to cache.
- * @param tileFreeCallback function used to free tiles.
- * @param data context to give back to @a tile_free_cb as first argument.
- *
- * @return #true on success, #false otherwise. If @c tile->visible
- * is not #false, then it will return #false.
- *
- * @see ewk_tile_unused_cache_auto_flush()
- */
- Eina_Bool ewk_tile_unused_cache_tile_put(Ewk_Tile_Unused_Cache* tileUnusedCache, Ewk_Tile* tile, void (* tileFreeCallback)(void* data, Ewk_Tile* tile), const void* data)
- {
- Ewk_Tile_Unused_Cache_Entry* unusedCacheEntry;
- if (tile->visible) {
- ERR("tile=%p is not unused (visible=%d)", tile, tile->visible);
- return false;
- }
- unusedCacheEntry = new Ewk_Tile_Unused_Cache_Entry;
- tileUnusedCache->entries.list = eina_list_append(tileUnusedCache->entries.list, unusedCacheEntry);
- if (eina_error_get()) {
- ERR("List allocation failed");
- return false;
- }
- unusedCacheEntry->tile = tile;
- unusedCacheEntry->weight = 0; /* calculated just before sort */
- unusedCacheEntry->tile_free.callback = tileFreeCallback;
- unusedCacheEntry->tile_free.data = (void*)data;
- tileUnusedCache->entries.count++;
- tileUnusedCache->memory.used += ewk_tile_memory_size_get(tile);
- return true;
- }
- void ewk_tile_unused_cache_dbg(const Ewk_Tile_Unused_Cache* tileUnusedCache)
- {
- void* item;
- Eina_List* list;
- int count = 0;
- printf("Cache of unused tiles: entries: %zu/%zu, memory: %zu/%zu\n",
- tileUnusedCache->entries.count, tileUnusedCache->entries.allocated,
- tileUnusedCache->memory.used, tileUnusedCache->memory.max);
- EINA_LIST_FOREACH(tileUnusedCache->entries.list, list, item) {
- const Ewk_Tile* tile = static_cast<Ewk_Tile_Unused_Cache_Entry*>(item)->tile;
- printf(" [%3lu,%3lu + %dx%d @ %0.3f]%c",
- tile->column, tile->row, tile->width, tile->height, tile->zoom,
- tile->visible ? '*' : ' ');
- if (!(count % 4))
- printf("\n");
- }
- printf("\n");
- }
|