[EFL] Added DEFAULT_CACHE_SIZE define.
[WebKit-https.git] / Source / WebKit / efl / ewk / ewk_tiled_matrix.cpp
index c8c34853206d1dbdea65188648074a44e694933e..c3a596d418c836a89d718e97b69b1266d64278f8 100644 (file)
@@ -18,6 +18,7 @@
     Boston, MA 02110-1301, USA.
 */
 
+#define __STDC_FORMAT_MACROS
 #include "config.h"
 #include "ewk_tiled_matrix.h"
 
 #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 {
@@ -53,11 +64,27 @@ struct _Ewk_Tile_Matrix {
 #endif
 };
 
+// Default 40 MB size of newly created cache
+static const size_t DEFAULT_CACHE_SIZE = 40 * 1024 * 1024;
+
 #ifdef DEBUG_MEM_LEAKS
 static uint64_t tiles_leaked = 0;
 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)
 {
@@ -78,11 +105,18 @@ 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);
         }
     }
@@ -94,9 +128,17 @@ static void _ewk_tile_matrix_cell_free(void* userData, void* cellData)
 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;
     }
@@ -124,6 +166,13 @@ static void _ewk_tile_matrix_tile_free(void* data, Ewk_Tile* tile)
     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);
 }
 
@@ -139,13 +188,14 @@ static void _ewk_tile_matrix_tile_free(void* data, Ewk_Tile* 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)
@@ -158,10 +208,12 @@ Ewk_Tile_Matrix* ewk_tile_matrix_new(Ewk_Tile_Unused_Cache* tileUnusedCache, uns
         return 0;
     }
 
+    ewk_tile_matrix_zoom_level_set(tileMatrix, zoomLevel);
+
     if (tileUnusedCache)
         tileMatrix->tilieUnusedCache = ewk_tile_unused_cache_ref(tileUnusedCache);
     else {
-        tileMatrix->tilieUnusedCache = ewk_tile_unused_cache_new(40960000);
+        tileMatrix->tilieUnusedCache = ewk_tile_unused_cache_new(DEFAULT_CACHE_SIZE);
         if (!tileMatrix->tilieUnusedCache) {
             ERR("no cache of unused tile!");
             eina_matrixsparse_free(tileMatrix->matrix);
@@ -179,6 +231,59 @@ Ewk_Tile_Matrix* ewk_tile_matrix_new(Ewk_Tile_Unused_Cache* tileUnusedCache, uns
     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.
  *
@@ -186,6 +291,7 @@ Ewk_Tile_Matrix* ewk_tile_matrix_new(Ewk_Tile_Unused_Cache* tileUnusedCache, uns
  */
 void ewk_tile_matrix_free(Ewk_Tile_Matrix* tileMatrix)
 {
+    Ewk_Tile_Matrix_Entry* entry;
 #ifdef DEBUG_MEM_LEAKS
     uint64_t tiles, bytes;
 #endif
@@ -193,7 +299,12 @@ void ewk_tile_matrix_free(Ewk_Tile_Matrix* tileMatrix)
     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);
@@ -215,7 +326,7 @@ void ewk_tile_matrix_free(Ewk_Tile_Matrix* tileMatrix)
             "bytes[+%" PRIu64 ",-%" PRIu64 "], but some other leaked "
             "%" PRIu64 " tiles (%" PRIu64 " bytes)",
             tileMatrix->stats.tiles.allocated, tileMatrix->stats.tiles.freed,
-            tileMatrix->stats.bytes.allocated, tileMatrixm->stats.bytes.freed,
+            tileMatrix->stats.bytes.allocated, tileMatrix->stats.bytes.freed,
             tiles_leaked, bytes_leaked);
     else
         INF("tiled matrix had no leaks: tiles[+%" PRIu64 ",-%" PRIu64 "] "
@@ -294,16 +405,16 @@ end:
  * @param row the row number.
  * @param zoom the exact zoom to query.
  *
- * @return @c EINA_TRUE if found, @c EINA_FALSE otherwise.
+ * @return @c true if found, @c false otherwise.
  *
  * @see ewk_tile_matrix_tile_exact_get()
  */
 Eina_Bool ewk_tile_matrix_tile_exact_exists(Ewk_Tile_Matrix* tileMatrix, unsigned long column, unsigned long row, float zoom)
 {
     if (!eina_matrixsparse_data_idx_get(tileMatrix->matrix, row, column))
-        return EINA_FALSE;
+        return false;
 
-    return EINA_TRUE;
+    return true;
 }
 
 /**
@@ -322,9 +433,16 @@ Ewk_Tile* ewk_tile_matrix_tile_new(Ewk_Tile_Matrix* tileMatrix, Evas* canvas, un
 {
     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;
@@ -348,7 +466,7 @@ Ewk_Tile* ewk_tile_matrix_tile_new(Ewk_Tile_Matrix* tileMatrix, Evas* canvas, un
 
     cairo_translate(tile->cairo, -tile->x, -tile->y);
 
-    tile->stats.full_update = EINA_TRUE;
+    tile->stats.full_update = true;
     tileMatrix->updates = eina_list_append(tileMatrix->updates, tile);
 
 #ifdef DEBUG_MEM_LEAKS
@@ -374,15 +492,15 @@ Ewk_Tile* ewk_tile_matrix_tile_new(Ewk_Tile_Matrix* tileMatrix, Evas* canvas, un
  * @param t the tile instance to return, must @b not be @c 0.
  * @param last_used time in which tile.widthas last used.
  *
- * @return #EINA_TRUE on success or #EINA_FALSE on failure.
+ * @return #true on success or #false on failure.
  */
 Eina_Bool ewk_tile_matrix_tile_put(Ewk_Tile_Matrix* tileMatrix, Ewk_Tile* tile, double lastUsed)
 {
-    EINA_SAFETY_ON_NULL_RETURN_VAL(tileMatrix, EINA_FALSE);
-    EINA_SAFETY_ON_NULL_RETURN_VAL(tile, EINA_FALSE);
+    EINA_SAFETY_ON_NULL_RETURN_VAL(tileMatrix, false);
+    EINA_SAFETY_ON_NULL_RETURN_VAL(tile, false);
 
     if (tile->visible)
-        return EINA_TRUE;
+        return true;
 
     tile->stats.last_used = lastUsed;
     return ewk_tile_unused_cache_tile_put(tileMatrix->tilieUnusedCache, tile, _ewk_tile_matrix_tile_free, tileMatrix);
@@ -391,14 +509,14 @@ Eina_Bool ewk_tile_matrix_tile_put(Ewk_Tile_Matrix* tileMatrix, Ewk_Tile* tile,
 Eina_Bool ewk_tile_matrix_tile_update(Ewk_Tile_Matrix* tileMatrix, unsigned long col, unsigned long row, const Eina_Rectangle* update)
 {
     Eina_Rectangle newUpdate;
-    EINA_SAFETY_ON_NULL_RETURN_VAL(tileMatrix, EINA_FALSE);
-    EINA_SAFETY_ON_NULL_RETURN_VAL(update, EINA_FALSE);
+    EINA_SAFETY_ON_NULL_RETURN_VAL(tileMatrix, false);
+    EINA_SAFETY_ON_NULL_RETURN_VAL(update, false);
 
     memcpy(&newUpdate, update, sizeof(newUpdate));
-    // check update is valid, otherwise return EINA_FALSE
+    // check update is valid, otherwise return false
     if (update->x < 0 || update->y < 0 || update->w <= 0 || update->h <= 0) {
         ERR("invalid update region.");
-        return EINA_FALSE;
+        return false;
     }
 
     if (update->x + update->w - 1 >= tileMatrix->tile.width)
@@ -408,37 +526,37 @@ Eina_Bool ewk_tile_matrix_tile_update(Ewk_Tile_Matrix* tileMatrix, unsigned long
 
     Ewk_Tile* tile = static_cast<Ewk_Tile*>(eina_matrixsparse_data_idx_get(tileMatrix->matrix, row, col));
     if (!tile)
-        return EINA_TRUE;
+        return true;
 
     if (!tile->updates && !tile->stats.full_update)
         tileMatrix->updates = eina_list_append(tileMatrix->updates, tile);
     ewk_tile_update_area(tile, &newUpdate);
 
-    return EINA_TRUE;
+    return true;
 }
 
 Eina_Bool ewk_tile_matrix_tile_update_full(Ewk_Tile_Matrix* tileMatrix, unsigned long column, unsigned long row)
 {
     Eina_Matrixsparse_Cell* cell;
-    EINA_SAFETY_ON_NULL_RETURN_VAL(tileMatrix, EINA_FALSE);
+    EINA_SAFETY_ON_NULL_RETURN_VAL(tileMatrix, false);
 
     if (!eina_matrixsparse_cell_idx_get(tileMatrix->matrix, row, column, &cell))
-        return EINA_FALSE;
+        return false;
 
     if (!cell)
-        return EINA_TRUE;
+        return true;
 
     Ewk_Tile* tile = static_cast<Ewk_Tile*>(eina_matrixsparse_cell_data_get(cell));
     if (!tile) {
         CRITICAL("matrix cell with no tile!");
-        return EINA_TRUE;
+        return true;
     }
 
     if (!tile->updates && !tile->stats.full_update)
         tileMatrix->updates = eina_list_append(tileMatrix->updates, tile);
     ewk_tile_update_full(tile);
 
-    return EINA_TRUE;
+    return true;
 }
 
 void ewk_tile_matrix_tile_updates_clear(Ewk_Tile_Matrix* tileMatrix, Ewk_Tile* tile)
@@ -458,7 +576,7 @@ static Eina_Bool _ewk_tile_matrix_slicer_setup(Ewk_Tile_Matrix* tileMatrix, cons
     if (area->w <= 0 || area->h <= 0) {
         WRN("invalid area region: %d,%d+%dx%d.",
             area->x, area->y, area->w, area->h);
-        return EINA_FALSE;
+        return false;
     }
 
     x = area->x;
@@ -493,19 +611,19 @@ Eina_Bool ewk_tile_matrix_update(Ewk_Tile_Matrix* tileMatrix, const Eina_Rectang
 {
     const Eina_Tile_Grid_Info* info;
     Eina_Tile_Grid_Slicer slicer;
-    EINA_SAFETY_ON_NULL_RETURN_VAL(tileMatrix, EINA_FALSE);
-    EINA_SAFETY_ON_NULL_RETURN_VAL(update, EINA_FALSE);
+    EINA_SAFETY_ON_NULL_RETURN_VAL(tileMatrix, false);
+    EINA_SAFETY_ON_NULL_RETURN_VAL(update, false);
 
     if (update->w < 1 || update->h < 1) {
         DBG("Why we get updates with empty areas? %d,%d+%dx%d at zoom %f",
             update->x, update->y, update->w, update->h, zoom);
-        return EINA_TRUE;
+        return true;
     }
 
     if (!_ewk_tile_matrix_slicer_setup(tileMatrix, update, zoom, &slicer)) {
         ERR("Could not setup slicer for update %d,%d+%dx%d at zoom %f",
             update->x, update->y, update->w, update->h, zoom);
-        return EINA_FALSE;
+        return false;
     }
 
     while (eina_tile_grid_slicer_next(&slicer, &info)) {
@@ -526,7 +644,7 @@ Eina_Bool ewk_tile_matrix_update(Ewk_Tile_Matrix* tileMatrix, const Eina_Rectang
     }
 
 
-    return EINA_TRUE;
+    return true;
 }
 
 void ewk_tile_matrix_updates_process(Ewk_Tile_Matrix* tileMatrix)
@@ -561,15 +679,15 @@ void ewk_tile_matrix_dbg(const Ewk_Tile_Matrix* tileMatrix)
 {
     Eina_Iterator* iterator = eina_matrixsparse_iterator_complete_new(tileMatrix->matrix);
     Eina_Matrixsparse_Cell* cell;
-    Eina_Bool last_empty = EINA_FALSE;
+    Eina_Bool last_empty = false;
 
 #ifdef DEBUG_MEM_LEAKS
     printf("Ewk_Tile Matrix: tiles[+%" PRIu64 ",-%" PRIu64 ":%" PRIu64 "] "
            "bytes[+%" PRIu64 ",-%" PRIu64 ":%" PRIu64 "]\n",
-           tm->stats.tiles.allocated, tm->stats.tiles.freed,
-           tm->stats.tiles.allocated - tm->stats.tiles.freed,
-           tm->stats.bytes.allocated, tm->stats.bytes.freed,
-           tm->stats.bytes.allocated - tm->stats.bytes.freed);
+           tileMatrix->stats.tiles.allocated, tileMatrix->stats.tiles.freed,
+           tileMatrix->stats.tiles.allocated - tileMatrix->stats.tiles.freed,
+           tileMatrix->stats.bytes.allocated, tileMatrix->stats.bytes.freed,
+           tileMatrix->stats.bytes.allocated - tileMatrix->stats.bytes.freed);
 #else
     printf("Ewk_Tile Matrix:\n");
 #endif
@@ -581,13 +699,13 @@ void ewk_tile_matrix_dbg(const Ewk_Tile_Matrix* tileMatrix)
         Ewk_Tile* tile = static_cast<Ewk_Tile*>(eina_matrixsparse_cell_data_get(cell));
         if (!tile) {
             if (!last_empty) {
-                last_empty = EINA_TRUE;
+                last_empty = true;
                 printf("Empty:");
             }
             printf(" [%lu,%lu]", column, row);
         } else {
             if (last_empty) {
-                last_empty = EINA_FALSE;
+                last_empty = false;
                 printf("\n");
             }
             printf("%3lu,%3lu %10p:", column, row, tile);