#include <stdlib.h>
#include <string.h>
+struct _Ewk_Tile_Matrix_Entry {
+ EINA_INLIST;
+ float zoom;
+ unsigned long count;
+ Eina_Matrixsparse* matrix;
+};
+
+typedef struct _Ewk_Tile_Matrix_Entry Ewk_Tile_Matrix_Entry;
+
struct _Ewk_Tile_Matrix {
Eina_Matrixsparse* matrix;
+ Eina_Inlist* matrices;
Ewk_Tile_Unused_Cache* tilieUnusedCache;
Evas_Colorspace cspace;
struct {
static uint64_t bytes_leaked = 0;
#endif
+static Ewk_Tile_Matrix_Entry* ewk_tile_matrix_entry_get(Ewk_Tile_Matrix* tileMatrix, float zoom)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(tileMatrix, 0);
+ Ewk_Tile_Matrix_Entry* iterator;
+
+ EINA_INLIST_FOREACH(tileMatrix->matrices, iterator) {
+ if (iterator->zoom == zoom)
+ return iterator;
+ }
+
+ return 0;
+}
+
/* called when matrixsparse is resized or freed */
static void _ewk_tile_matrix_cell_free(void* userData, void* cellData)
{
if (!ewk_tile_unused_cache_tile_get(tileMatrix->tilieUnusedCache, tile))
ERR("tile %p was not in cache %p? leaking...", tile, tileMatrix->tilieUnusedCache);
else {
+ Ewk_Tile_Matrix_Entry* entry;
DBG("tile cell does not exist anymore, free it %p", tile);
#ifdef DEBUG_MEM_LEAKS
tileMatrix->stats.bytes.freed += tile->bytes;
tileMatrix->stats.tiles.freed++;
#endif
+ entry = ewk_tile_matrix_entry_get(tileMatrix, tile->zoom);
+ if (!entry)
+ ERR("can't find matrix for zoom %0.3f", tile->zoom);
+ else
+ entry->count--;
+
ewk_tile_free(tile);
}
}
static void _ewk_tile_matrix_tile_free(void* data, Ewk_Tile* tile)
{
Ewk_Tile_Matrix* tileMatrix = static_cast<Ewk_Tile_Matrix*>(data);
+ Ewk_Tile_Matrix_Entry* entry;
Eina_Matrixsparse_Cell* cell;
- if (!eina_matrixsparse_cell_idx_get(tileMatrix->matrix, tile->row, tile->col, &cell)) {
+ entry = ewk_tile_matrix_entry_get(tileMatrix, tile->zoom);
+ if (!entry) {
+ ERR("removing tile %p that was not in any matrix? Leaking...", tile);
+ return;
+ }
+
+ if (!eina_matrixsparse_cell_idx_get(entry->matrix, tile->row, tile->col, &cell)) {
+
ERR("removing tile %p that was not in the matrix? Leaking...", tile);
return;
}
tileMatrix->stats.tiles.freed++;
#endif
+ entry->count--;
+ if (!entry->count && entry->matrix != tileMatrix->matrix) {
+ eina_matrixsparse_free(entry->matrix);
+ tileMatrix->matrices = eina_inlist_remove(tileMatrix->matrices, EINA_INLIST_GET(entry));
+ free(entry);
+ }
+
ewk_tile_free(tile);
}
* automatically.
* @param columns number of columns in the matrix.
* @param rows number of rows in the matrix.
+ * @param zoomLevel zoom level for the matrix.
* @param cspace the color space used to create tiles in this matrix.
* @param render_cb function used to render given tile update.
* @param render_data context to give back to @a render_cb.
*
* @return newly allocated instance on success, @c 0 on failure.
*/
-Ewk_Tile_Matrix* ewk_tile_matrix_new(Ewk_Tile_Unused_Cache* tileUnusedCache, unsigned long columns, unsigned long rows, Evas_Colorspace colorSpace, void (*renderCallback)(void* data, Ewk_Tile* tile, const Eina_Rectangle* update), const void* renderData)
+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)
{
Ewk_Tile_Matrix* tileMatrix = static_cast<Ewk_Tile_Matrix*>(calloc(1, sizeof(Ewk_Tile_Matrix)));
if (!tileMatrix)
return 0;
}
+ ewk_tile_matrix_zoom_level_set(tileMatrix, zoomLevel);
+
if (tileUnusedCache)
tileMatrix->tilieUnusedCache = ewk_tile_unused_cache_ref(tileUnusedCache);
else {
return tileMatrix;
}
+void ewk_tile_matrix_zoom_level_set(Ewk_Tile_Matrix* tileMatrix, float zoom)
+{
+ EINA_SAFETY_ON_NULL_RETURN(tileMatrix);
+ Ewk_Tile_Matrix_Entry* iterator = 0;
+ Ewk_Tile_Matrix_Entry* entry = 0;
+ unsigned long rows = 0, columns = 0;
+
+ eina_matrixsparse_size_get(tileMatrix->matrix, &rows, &columns);
+
+ EINA_INLIST_FOREACH(tileMatrix->matrices, iterator) {
+ if (iterator->zoom != zoom)
+ continue;
+ entry = iterator;
+ tileMatrix->matrices = eina_inlist_promote(tileMatrix->matrices, EINA_INLIST_GET(entry));
+ eina_matrixsparse_size_set(entry->matrix, rows, columns);
+ }
+
+ if (!entry) {
+ entry = static_cast<Ewk_Tile_Matrix_Entry*>(calloc(1, sizeof(Ewk_Tile_Matrix_Entry)));
+ entry->zoom = zoom;
+ entry->matrix = eina_matrixsparse_new(rows, columns, _ewk_tile_matrix_cell_free, tileMatrix);
+ if (!entry->matrix) {
+ ERR("could not create sparse matrix.");
+ free(entry);
+ return;
+ }
+ tileMatrix->matrices = eina_inlist_prepend(tileMatrix->matrices, EINA_INLIST_GET(entry));
+ }
+
+ tileMatrix->matrix = entry->matrix;
+}
+
+void ewk_tile_matrix_invalidate(Ewk_Tile_Matrix* tileMatrix)
+{
+ EINA_SAFETY_ON_NULL_RETURN(tileMatrix);
+ Ewk_Tile_Matrix_Entry* iterator;
+ Eina_Inlist* matrixList;
+
+ matrixList = tileMatrix->matrices;
+ while (matrixList) {
+ iterator = EINA_INLIST_CONTAINER_GET(matrixList, Ewk_Tile_Matrix_Entry);
+ Eina_Inlist *next = (matrixList->next) ? matrixList->next : 0;
+
+ if (iterator->matrix != tileMatrix->matrix) {
+ eina_matrixsparse_free(iterator->matrix);
+ tileMatrix->matrices = eina_inlist_remove(tileMatrix->matrices, matrixList);
+ free(iterator);
+ }
+
+ matrixList = next;
+ }
+}
+
/**
* Destroys tiles matrix, releasing its resources.
*
*/
void ewk_tile_matrix_free(Ewk_Tile_Matrix* tileMatrix)
{
+ Ewk_Tile_Matrix_Entry* entry;
#ifdef DEBUG_MEM_LEAKS
uint64_t tiles, bytes;
#endif
EINA_SAFETY_ON_NULL_RETURN(tileMatrix);
ewk_tile_unused_cache_freeze(tileMatrix->tilieUnusedCache);
- eina_matrixsparse_free(tileMatrix->matrix);
+ ewk_tile_unused_cache_freeze(tileMatrix->tilieUnusedCache);
+ ewk_tile_matrix_invalidate(tileMatrix);
+ entry = EINA_INLIST_CONTAINER_GET(tileMatrix->matrices, Ewk_Tile_Matrix_Entry);
+ eina_matrixsparse_free(entry->matrix);
+ free(entry);
+ tileMatrix->matrices = 0;
ewk_tile_unused_cache_thaw(tileMatrix->tilieUnusedCache);
ewk_tile_unused_cache_unref(tileMatrix->tilieUnusedCache);
{
Evas_Coord tileWidth, tileHeight;
Ewk_Tile* tile;
+ Ewk_Tile_Matrix_Entry* entry;
EINA_SAFETY_ON_NULL_RETURN_VAL(tileMatrix, 0);
EINA_SAFETY_ON_FALSE_RETURN_VAL(zoom > 0.0, 0);
+ entry = ewk_tile_matrix_entry_get(tileMatrix, zoom);
+ if (!entry) {
+ ERR("could not get matrix at zoom %f for tile", zoom);
+ return 0;
+ }
+ entry->count++;
tileWidth = tileMatrix->tile.width;
tileHeight = tileMatrix->tile.height;