2 Copyright (C) 2009-2010 Samsung Electronics
3 Copyright (C) 2009-2010 ProFUSION embedded systems
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
21 #define __STDC_FORMAT_MACROS
23 #include "ewk_tiled_matrix.h"
25 #include "ewk_tiled_backing_store.h"
26 #include "ewk_tiled_private.h"
31 #include <stdio.h> // XXX remove me later
35 struct _Ewk_Tile_Matrix_Entry {
39 Eina_Matrixsparse* matrix;
42 typedef struct _Ewk_Tile_Matrix_Entry Ewk_Tile_Matrix_Entry;
44 struct _Ewk_Tile_Matrix {
45 Eina_Matrixsparse* matrix;
46 Eina_Inlist* matrices;
47 Ewk_Tile_Unused_Cache* tilieUnusedCache;
48 Evas_Colorspace cspace;
50 void (*callback)(void* data, Ewk_Tile* tile, const Eina_Rectangle* update);
56 Evas_Coord width, height;
58 #ifdef DEBUG_MEM_LEAKS
61 uint64_t allocated, freed;
67 // Default 40 MB size of newly created cache
68 static const size_t DEFAULT_CACHE_SIZE = 40 * 1024 * 1024;
70 #ifdef DEBUG_MEM_LEAKS
71 static uint64_t tiles_leaked = 0;
72 static uint64_t bytes_leaked = 0;
75 static Ewk_Tile_Matrix_Entry* ewk_tile_matrix_entry_get(Ewk_Tile_Matrix* tileMatrix, float zoom)
77 EINA_SAFETY_ON_NULL_RETURN_VAL(tileMatrix, 0);
78 Ewk_Tile_Matrix_Entry* iterator;
80 EINA_INLIST_FOREACH(tileMatrix->matrices, iterator) {
81 if (iterator->zoom == zoom)
88 /* called when matrixsparse is resized or freed */
89 static void _ewk_tile_matrix_cell_free(void* userData, void* cellData)
91 Ewk_Tile_Matrix* tileMatrix = static_cast<Ewk_Tile_Matrix*>(userData);
92 Ewk_Tile* tile = static_cast<Ewk_Tile*>(cellData);
97 ewk_tile_unused_cache_freeze(tileMatrix->tilieUnusedCache);
99 if (tile->updates || tile->stats.full_update)
100 tileMatrix->updates = eina_list_remove(tileMatrix->updates, tile);
103 ERR("freeing cell that is visible, leaking tile %p", tile);
105 if (!ewk_tile_unused_cache_tile_get(tileMatrix->tilieUnusedCache, tile))
106 ERR("tile %p was not in cache %p? leaking...", tile, tileMatrix->tilieUnusedCache);
108 Ewk_Tile_Matrix_Entry* entry;
109 DBG("tile cell does not exist anymore, free it %p", tile);
110 #ifdef DEBUG_MEM_LEAKS
111 tileMatrix->stats.bytes.freed += tile->bytes;
112 tileMatrix->stats.tiles.freed++;
114 entry = ewk_tile_matrix_entry_get(tileMatrix, tile->zoom);
116 ERR("can't find matrix for zoom %0.3f", tile->zoom);
124 ewk_tile_unused_cache_thaw(tileMatrix->tilieUnusedCache);
127 /* called when cache of unused tile is flushed */
128 static void _ewk_tile_matrix_tile_free(void* data, Ewk_Tile* tile)
130 Ewk_Tile_Matrix* tileMatrix = static_cast<Ewk_Tile_Matrix*>(data);
131 Ewk_Tile_Matrix_Entry* entry;
132 Eina_Matrixsparse_Cell* cell;
134 entry = ewk_tile_matrix_entry_get(tileMatrix, tile->zoom);
136 ERR("removing tile %p that was not in any matrix? Leaking...", tile);
140 if (!eina_matrixsparse_cell_idx_get(entry->matrix, tile->row, tile->col, &cell)) {
142 ERR("removing tile %p that was not in the matrix? Leaking...", tile);
147 ERR("removing tile %p that was not in the matrix? Leaking...", tile);
151 if (tile->updates || tile->stats.full_update)
152 tileMatrix->updates = eina_list_remove(tileMatrix->updates, tile);
154 /* set to null to avoid double free */
155 eina_matrixsparse_cell_data_replace(cell, 0, 0);
156 eina_matrixsparse_cell_clear(cell);
158 if (EINA_UNLIKELY(!!tile->visible)) {
159 ERR("cache of unused tiles requesting deletion of used tile %p? "
164 #ifdef DEBUG_MEM_LEAKS
165 tileMatrix->stats.bytes.freed += tile->bytes;
166 tileMatrix->stats.tiles.freed++;
170 if (!entry->count && entry->matrix != tileMatrix->matrix) {
171 eina_matrixsparse_free(entry->matrix);
172 tileMatrix->matrices = eina_inlist_remove(tileMatrix->matrices, EINA_INLIST_GET(entry));
180 * Creates a new matrix of tiles.
182 * The tile matrix is responsible for keeping tiles around and
183 * providing fast access to them. One can use it to retrieve new or
184 * existing tiles and give them back, allowing them to be
185 * freed/replaced by the cache.
187 * @param tuc cache of unused tiles or @c 0 to create one
189 * @param columns number of columns in the matrix.
190 * @param rows number of rows in the matrix.
191 * @param zoomLevel zoom level for the matrix.
192 * @param cspace the color space used to create tiles in this matrix.
193 * @param render_cb function used to render given tile update.
194 * @param render_data context to give back to @a render_cb.
196 * @return newly allocated instance on success, @c 0 on failure.
198 Ewk_Tile_Matrix* ewk_tile_matrix_new(Ewk_Tile_Unused_Cache* tileUnusedCache, unsigned long columns, unsigned long rows, float zoomLevel, Evas_Colorspace colorSpace, void (*renderCallback)(void* data, Ewk_Tile* tile, const Eina_Rectangle* update), const void* renderData)
200 Ewk_Tile_Matrix* tileMatrix = static_cast<Ewk_Tile_Matrix*>(calloc(1, sizeof(Ewk_Tile_Matrix)));
204 tileMatrix->matrix = eina_matrixsparse_new(rows, columns, _ewk_tile_matrix_cell_free, tileMatrix);
205 if (!tileMatrix->matrix) {
206 ERR("could not create sparse matrix.");
211 ewk_tile_matrix_zoom_level_set(tileMatrix, zoomLevel);
214 tileMatrix->tilieUnusedCache = ewk_tile_unused_cache_ref(tileUnusedCache);
216 tileMatrix->tilieUnusedCache = ewk_tile_unused_cache_new(DEFAULT_CACHE_SIZE);
217 if (!tileMatrix->tilieUnusedCache) {
218 ERR("no cache of unused tile!");
219 eina_matrixsparse_free(tileMatrix->matrix);
225 tileMatrix->cspace = colorSpace;
226 tileMatrix->render.callback = renderCallback;
227 tileMatrix->render.data = (void*)renderData;
228 tileMatrix->tile.width = DEFAULT_TILE_W;
229 tileMatrix->tile.height = DEFAULT_TILE_H;
234 void ewk_tile_matrix_zoom_level_set(Ewk_Tile_Matrix* tileMatrix, float zoom)
236 EINA_SAFETY_ON_NULL_RETURN(tileMatrix);
237 Ewk_Tile_Matrix_Entry* iterator = 0;
238 Ewk_Tile_Matrix_Entry* entry = 0;
239 unsigned long rows = 0, columns = 0;
241 eina_matrixsparse_size_get(tileMatrix->matrix, &rows, &columns);
243 EINA_INLIST_FOREACH(tileMatrix->matrices, iterator) {
244 if (iterator->zoom != zoom)
247 tileMatrix->matrices = eina_inlist_promote(tileMatrix->matrices, EINA_INLIST_GET(entry));
248 eina_matrixsparse_size_set(entry->matrix, rows, columns);
252 entry = static_cast<Ewk_Tile_Matrix_Entry*>(calloc(1, sizeof(Ewk_Tile_Matrix_Entry)));
254 entry->matrix = eina_matrixsparse_new(rows, columns, _ewk_tile_matrix_cell_free, tileMatrix);
255 if (!entry->matrix) {
256 ERR("could not create sparse matrix.");
260 tileMatrix->matrices = eina_inlist_prepend(tileMatrix->matrices, EINA_INLIST_GET(entry));
263 tileMatrix->matrix = entry->matrix;
266 void ewk_tile_matrix_invalidate(Ewk_Tile_Matrix* tileMatrix)
268 EINA_SAFETY_ON_NULL_RETURN(tileMatrix);
269 Ewk_Tile_Matrix_Entry* iterator;
270 Eina_Inlist* matrixList;
272 matrixList = tileMatrix->matrices;
274 iterator = EINA_INLIST_CONTAINER_GET(matrixList, Ewk_Tile_Matrix_Entry);
275 Eina_Inlist *next = (matrixList->next) ? matrixList->next : 0;
277 if (iterator->matrix != tileMatrix->matrix) {
278 eina_matrixsparse_free(iterator->matrix);
279 tileMatrix->matrices = eina_inlist_remove(tileMatrix->matrices, matrixList);
288 * Destroys tiles matrix, releasing its resources.
290 * The cache instance is unreferenced, possibly freeing it.
292 void ewk_tile_matrix_free(Ewk_Tile_Matrix* tileMatrix)
294 Ewk_Tile_Matrix_Entry* entry;
295 #ifdef DEBUG_MEM_LEAKS
296 uint64_t tiles, bytes;
299 EINA_SAFETY_ON_NULL_RETURN(tileMatrix);
300 ewk_tile_unused_cache_freeze(tileMatrix->tilieUnusedCache);
302 ewk_tile_unused_cache_freeze(tileMatrix->tilieUnusedCache);
303 ewk_tile_matrix_invalidate(tileMatrix);
304 entry = EINA_INLIST_CONTAINER_GET(tileMatrix->matrices, Ewk_Tile_Matrix_Entry);
305 tileMatrix->matrices = eina_inlist_remove(tileMatrix->matrices, (Eina_Inlist *)entry);
306 eina_matrixsparse_free(entry->matrix);
308 tileMatrix->matrices = 0;
310 ewk_tile_unused_cache_thaw(tileMatrix->tilieUnusedCache);
311 ewk_tile_unused_cache_unref(tileMatrix->tilieUnusedCache);
313 #ifdef DEBUG_MEM_LEAKS
314 tiles = tileMatrix->stats.tiles.allocated - tileMatrix->stats.tiles.freed;
315 bytes = tileMatrix->stats.bytes.allocated - tileMatrix->stats.bytes.freed;
317 tiles_leaked += tiles;
318 bytes_leaked += bytes;
321 ERR("tiled matrix leaked: tiles[+%" PRIu64 ",-%" PRIu64 ":%" PRIu64 "] "
322 "bytes[+%" PRIu64 ",-%" PRIu64 ":%" PRIu64 "]",
323 tileMatrix->stats.tiles.allocated, tileMatrix->stats.tiles.freed, tiles,
324 tileMatrix->stats.bytes.allocated, tileMatrix->stats.bytes.freed, bytes);
325 else if (tiles_leaked || bytes_leaked)
326 WRN("tiled matrix had no leaks: tiles[+%" PRIu64 ",-%" PRIu64 "] "
327 "bytes[+%" PRIu64 ",-%" PRIu64 "], but some other leaked "
328 "%" PRIu64 " tiles (%" PRIu64 " bytes)",
329 tileMatrix->stats.tiles.allocated, tileMatrix->stats.tiles.freed,
330 tileMatrix->stats.bytes.allocated, tileMatrix->stats.bytes.freed,
331 tiles_leaked, bytes_leaked);
333 INF("tiled matrix had no leaks: tiles[+%" PRIu64 ",-%" PRIu64 "] "
334 "bytes[+%" PRIu64 ",-%" PRIu64 "]",
335 tileMatrix->stats.tiles.allocated, tileMatrix->stats.tiles.freed,
336 tileMatrix->stats.bytes.allocated, tileMatrix->stats.bytes.freed);
343 * Resize matrix to given number of rows and columns.
345 void ewk_tile_matrix_resize(Ewk_Tile_Matrix* tileMatrix, unsigned long cols, unsigned long rows)
347 EINA_SAFETY_ON_NULL_RETURN(tileMatrix);
348 eina_matrixsparse_size_set(tileMatrix->matrix, rows, cols);
352 * Get the cache of unused tiles in use by given matrix.
354 * No reference is taken to the cache.
356 Ewk_Tile_Unused_Cache* ewk_tile_matrix_unused_cache_get(const Ewk_Tile_Matrix* tileMatrix)
358 EINA_SAFETY_ON_NULL_RETURN_VAL(tileMatrix, 0);
359 return tileMatrix->tilieUnusedCache;
363 * Get the exact tile for the given position and zoom.
365 * If the tile.widthas unused then it's removed from the cache.
367 * After usage, please give it back using
368 * ewk_tile_matrix_tile_put(). If you just want to check if it exists,
369 * then use ewk_tile_matrix_tile_exact_exists().
371 * @param tileMatrix the tile matrix to get tile from.
372 * @param column the column number.
373 * @param row the row number.
374 * @param zoom the exact zoom to use.
376 * @return The tile instance or @c 0 if none is found. If the tile
377 * was in the unused cache it will be @b removed (thus
378 * considered used) and one should give it back with
379 * ewk_tile_matrix_tile_put() afterwards.
381 * @see ewk_tile_matrix_tile_exact_get()
383 Ewk_Tile* ewk_tile_matrix_tile_exact_get(Ewk_Tile_Matrix* tileMatrix, unsigned long column, unsigned long row, float zoom)
385 Ewk_Tile* tile = static_cast<Ewk_Tile*>(eina_matrixsparse_data_idx_get(tileMatrix->matrix, row, column));
389 if (tile->zoom == zoom)
393 if (!tile->visible) {
394 if (!ewk_tile_unused_cache_tile_get(tileMatrix->tilieUnusedCache, tile))
395 WRN("Ewk_Tile was unused but not in cache? bug!");
402 * Checks if tile of given zoom exists in matrix.
404 * @param tileMatrix the tile matrix to check tile existence.
405 * @param column the column number.
406 * @param row the row number.
407 * @param zoom the exact zoom to query.
409 * @return @c true if found, @c false otherwise.
411 * @see ewk_tile_matrix_tile_exact_get()
413 Eina_Bool ewk_tile_matrix_tile_exact_exists(Ewk_Tile_Matrix* tileMatrix, unsigned long column, unsigned long row, float zoom)
415 if (!eina_matrixsparse_data_idx_get(tileMatrix->matrix, row, column))
422 * Create a new tile at given position and zoom level in the matrix.
424 * The newly created tile is considered in use and not put into cache
425 * of unused tiles. After it is used one should call
426 * ewk_tile_matrix_tile_put() to give it back to matrix.
428 * @param tileMatrix the tile matrix to create tile on.
429 * @param column the column number.
430 * @param row the row number.
431 * @param zoom the level to create tile, used to determine tile size.
433 Ewk_Tile* ewk_tile_matrix_tile_new(Ewk_Tile_Matrix* tileMatrix, Evas* canvas, unsigned long column, unsigned long row, float zoom)
435 Evas_Coord tileWidth, tileHeight;
437 Ewk_Tile_Matrix_Entry* entry;
439 EINA_SAFETY_ON_NULL_RETURN_VAL(tileMatrix, 0);
440 EINA_SAFETY_ON_FALSE_RETURN_VAL(zoom > 0.0, 0);
441 entry = ewk_tile_matrix_entry_get(tileMatrix, zoom);
443 ERR("could not get matrix at zoom %f for tile", zoom);
448 tileWidth = tileMatrix->tile.width;
449 tileHeight = tileMatrix->tile.height;
451 tile = ewk_tile_new(canvas, tileWidth, tileHeight, zoom, tileMatrix->cspace);
453 ERR("could not create tile %dx%d at %f, cspace=%d", tileWidth, tileHeight, (double)zoom, tileMatrix->cspace);
457 if (!eina_matrixsparse_data_idx_set(tileMatrix->matrix, row, column, tile)) {
458 ERR("could not set matrix cell, row/col outside matrix dimensions!");
465 tile->x = column * tileWidth;
466 tile->y = row * tileHeight;
468 cairo_translate(tile->cairo, -tile->x, -tile->y);
470 tile->stats.full_update = true;
471 tileMatrix->updates = eina_list_append(tileMatrix->updates, tile);
473 #ifdef DEBUG_MEM_LEAKS
474 tileMatrix->stats.bytes.allocated += tile->bytes;
475 tileMatrix->stats.tiles.allocated++;
482 * Gives back the tile to the tile matrix.
484 * This will report the tile is no longer in use by the one that got
485 * it with ewk_tile_matrix_tile_exact_get().
487 * Any previous reference to tile should be released
488 * (ewk_tile.heightide()) before calling this function, so it will
489 * be known if it is not visibile anymore and thus can be put into the
492 * @param tileMatrix the tile matrix to return tile to.
493 * @param t the tile instance to return, must @b not be @c 0.
494 * @param last_used time in which tile.widthas last used.
496 * @return #true on success or #false on failure.
498 Eina_Bool ewk_tile_matrix_tile_put(Ewk_Tile_Matrix* tileMatrix, Ewk_Tile* tile, double lastUsed)
500 EINA_SAFETY_ON_NULL_RETURN_VAL(tileMatrix, false);
501 EINA_SAFETY_ON_NULL_RETURN_VAL(tile, false);
506 tile->stats.last_used = lastUsed;
507 return ewk_tile_unused_cache_tile_put(tileMatrix->tilieUnusedCache, tile, _ewk_tile_matrix_tile_free, tileMatrix);
510 Eina_Bool ewk_tile_matrix_tile_update(Ewk_Tile_Matrix* tileMatrix, unsigned long col, unsigned long row, const Eina_Rectangle* update)
512 Eina_Rectangle newUpdate;
513 EINA_SAFETY_ON_NULL_RETURN_VAL(tileMatrix, false);
514 EINA_SAFETY_ON_NULL_RETURN_VAL(update, false);
516 memcpy(&newUpdate, update, sizeof(newUpdate));
517 // check update is valid, otherwise return false
518 if (update->x < 0 || update->y < 0 || update->w <= 0 || update->h <= 0) {
519 ERR("invalid update region.");
523 if (update->x + update->w - 1 >= tileMatrix->tile.width)
524 newUpdate.w = tileMatrix->tile.width - update->x;
525 if (update->y + update->h - 1 >= tileMatrix->tile.height)
526 newUpdate.h = tileMatrix->tile.height - update->y;
528 Ewk_Tile* tile = static_cast<Ewk_Tile*>(eina_matrixsparse_data_idx_get(tileMatrix->matrix, row, col));
532 if (!tile->updates && !tile->stats.full_update)
533 tileMatrix->updates = eina_list_append(tileMatrix->updates, tile);
534 ewk_tile_update_area(tile, &newUpdate);
539 Eina_Bool ewk_tile_matrix_tile_update_full(Ewk_Tile_Matrix* tileMatrix, unsigned long column, unsigned long row)
541 Eina_Matrixsparse_Cell* cell;
542 EINA_SAFETY_ON_NULL_RETURN_VAL(tileMatrix, false);
544 if (!eina_matrixsparse_cell_idx_get(tileMatrix->matrix, row, column, &cell))
550 Ewk_Tile* tile = static_cast<Ewk_Tile*>(eina_matrixsparse_cell_data_get(cell));
552 CRITICAL("matrix cell with no tile!");
556 if (!tile->updates && !tile->stats.full_update)
557 tileMatrix->updates = eina_list_append(tileMatrix->updates, tile);
558 ewk_tile_update_full(tile);
563 void ewk_tile_matrix_tile_updates_clear(Ewk_Tile_Matrix* tileMatrix, Ewk_Tile* tile)
565 EINA_SAFETY_ON_NULL_RETURN(tileMatrix);
566 if (!tile->updates && !tile->stats.full_update)
568 ewk_tile_updates_clear(tile);
569 tileMatrix->updates = eina_list_remove(tileMatrix->updates, tile);
572 static Eina_Bool _ewk_tile_matrix_slicer_setup(Ewk_Tile_Matrix* tileMatrix, const Eina_Rectangle* area, float zoom, Eina_Tile_Grid_Slicer* slicer)
574 unsigned long rows, cols;
575 Evas_Coord x, y, width, height, tileWidth, tileHeight;
577 if (area->w <= 0 || area->h <= 0) {
578 WRN("invalid area region: %d,%d+%dx%d.",
579 area->x, area->y, area->w, area->h);
588 tileWidth = tileMatrix->tile.width;
589 tileHeight = tileMatrix->tile.height;
591 // cropping area region to fit matrix
592 eina_matrixsparse_size_get(tileMatrix->matrix, &rows, &cols);
602 if (y + height - 1 > (long)(rows * tileHeight))
603 height = rows * tileHeight - y;
604 if (x + width - 1 > (long)(cols * tileWidth))
605 width = cols * tileWidth - x;
607 return eina_tile_grid_slicer_setup(slicer, x, y, width, height, tileWidth, tileHeight);
611 Eina_Bool ewk_tile_matrix_update(Ewk_Tile_Matrix* tileMatrix, const Eina_Rectangle* update, float zoom)
613 const Eina_Tile_Grid_Info* info;
614 Eina_Tile_Grid_Slicer slicer;
615 EINA_SAFETY_ON_NULL_RETURN_VAL(tileMatrix, false);
616 EINA_SAFETY_ON_NULL_RETURN_VAL(update, false);
618 if (update->w < 1 || update->h < 1) {
619 DBG("Why we get updates with empty areas? %d,%d+%dx%d at zoom %f",
620 update->x, update->y, update->w, update->h, zoom);
624 if (!_ewk_tile_matrix_slicer_setup(tileMatrix, update, zoom, &slicer)) {
625 ERR("Could not setup slicer for update %d,%d+%dx%d at zoom %f",
626 update->x, update->y, update->w, update->h, zoom);
630 while (eina_tile_grid_slicer_next(&slicer, &info)) {
631 unsigned long col, row;
635 Ewk_Tile* tile = static_cast<Ewk_Tile*>(eina_matrixsparse_data_idx_get(tileMatrix->matrix, row, col));
639 if (!tile->updates && !tile->stats.full_update)
640 tileMatrix->updates = eina_list_append(tileMatrix->updates, tile);
642 ewk_tile_update_full(tile);
644 ewk_tile_update_area(tile, &info->rect);
651 void ewk_tile_matrix_updates_process(Ewk_Tile_Matrix* tileMatrix)
653 Eina_List* list, *listNext;
655 EINA_SAFETY_ON_NULL_RETURN(tileMatrix);
657 // process updates, unflag tiles
658 EINA_LIST_FOREACH_SAFE(tileMatrix->updates, list, listNext, item) {
659 Ewk_Tile* tile = static_cast<Ewk_Tile*>(item);
660 ewk_tile_updates_process(tile, tileMatrix->render.callback, tileMatrix->render.data);
662 ewk_tile_updates_clear(tile);
663 tileMatrix->updates = eina_list_remove_list(tileMatrix->updates, list);
668 void ewk_tile_matrix_updates_clear(Ewk_Tile_Matrix* tileMatrix)
671 EINA_SAFETY_ON_NULL_RETURN(tileMatrix);
673 EINA_LIST_FREE(tileMatrix->updates, item)
674 ewk_tile_updates_clear(static_cast<Ewk_Tile*>(item));
675 tileMatrix->updates = 0;
679 void ewk_tile_matrix_dbg(const Ewk_Tile_Matrix* tileMatrix)
681 Eina_Iterator* iterator = eina_matrixsparse_iterator_complete_new(tileMatrix->matrix);
682 Eina_Matrixsparse_Cell* cell;
683 Eina_Bool last_empty = false;
685 #ifdef DEBUG_MEM_LEAKS
686 printf("Ewk_Tile Matrix: tiles[+%" PRIu64 ",-%" PRIu64 ":%" PRIu64 "] "
687 "bytes[+%" PRIu64 ",-%" PRIu64 ":%" PRIu64 "]\n",
688 tileMatrix->stats.tiles.allocated, tileMatrix->stats.tiles.freed,
689 tileMatrix->stats.tiles.allocated - tileMatrix->stats.tiles.freed,
690 tileMatrix->stats.bytes.allocated, tileMatrix->stats.bytes.freed,
691 tileMatrix->stats.bytes.allocated - tileMatrix->stats.bytes.freed);
693 printf("Ewk_Tile Matrix:\n");
696 EINA_ITERATOR_FOREACH(iterator, cell) {
697 unsigned long row, column;
698 eina_matrixsparse_cell_position_get(cell, &row, &column);
700 Ewk_Tile* tile = static_cast<Ewk_Tile*>(eina_matrixsparse_cell_data_get(cell));
706 printf(" [%lu,%lu]", column, row);
712 printf("%3lu,%3lu %10p:", column, row, tile);
713 printf(" [%3lu,%3lu + %dx%d @ %0.3f]%c", tile->col, tile->row, tile->width, tile->height, tile->zoom, tile->visible ? '*' : ' ');
719 eina_iterator_free(iterator);
721 ewk_tile_unused_cache_dbg(tileMatrix->tilieUnusedCache);
725 * Freeze matrix to not do maintenance tasks.
727 * Maintenance tasks optimize usage, but maybe we know we should hold
728 * on them until we do the last operation, in this case we freeze
729 * while operating and then thaw when we're done.
731 * @see ewk_tile_matrix_thaw()
733 void ewk_tile_matrix_freeze(Ewk_Tile_Matrix* tileMatrix)
735 EINA_SAFETY_ON_NULL_RETURN(tileMatrix);
736 if (!tileMatrix->frozen)
737 ewk_tile_unused_cache_freeze(tileMatrix->tilieUnusedCache);
738 tileMatrix->frozen++;
742 * Unfreezes maintenance tasks.
744 * If this is the last counterpart of freeze, then maintenance tasks
745 * will run immediately.
747 void ewk_tile_matrix_thaw(Ewk_Tile_Matrix* tileMatrix)
749 EINA_SAFETY_ON_NULL_RETURN(tileMatrix);
750 if (!tileMatrix->frozen) {
751 ERR("thawing more than freezing!");
755 tileMatrix->frozen--;
756 if (!tileMatrix->frozen)
757 ewk_tile_unused_cache_thaw(tileMatrix->tilieUnusedCache);