scanfill curves, ngons, masks had their own memarena code and would allocate a new...
authorCampbell Barton <ideasman42@gmail.com>
Wed, 28 Aug 2013 02:07:54 +0000 (02:07 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Wed, 28 Aug 2013 02:07:54 +0000 (02:07 +0000)
now use BLI_memarena and support passing the arena into the fill function, so the arena is re-used, when scanfill is called in a loop.

source/blender/blenkernel/intern/displist.c
source/blender/blenkernel/intern/editmesh.c
source/blender/blenkernel/intern/mask_rasterize.c
source/blender/blenkernel/intern/mesh.c
source/blender/blenlib/BLI_scanfill.h
source/blender/blenlib/intern/scanfill.c

index 77ec333c1738ea7baa07a47056d64c3028de04a4..6a89ca2cb847598a0bcb3ee8de44cad607fbe4c8 100644 (file)
@@ -43,6 +43,7 @@
 #include "DNA_material_types.h"
 
 #include "BLI_blenlib.h"
+#include "BLI_memarena.h"
 #include "BLI_math.h"
 #include "BLI_scanfill.h"
 #include "BLI_utildefines.h"
@@ -450,6 +451,7 @@ void BKE_displist_fill(ListBase *dispbase, ListBase *to, const float normal_proj
        ScanFillContext sf_ctx;
        ScanFillVert *sf_vert, *sf_vert_new, *sf_vert_last;
        ScanFillFace *sf_tri;
+       MemArena *sf_arena;
        DispList *dlnew = NULL, *dl;
        float *f1;
        int colnr = 0, charidx = 0, cont = 1, tot, a, *index, nextcol = 0;
@@ -460,12 +462,14 @@ void BKE_displist_fill(ListBase *dispbase, ListBase *to, const float normal_proj
        if (dispbase->first == NULL)
                return;
 
+       sf_arena = BLI_memarena_new(BLI_SCANFILL_ARENA_SIZE, __func__);
+
        while (cont) {
                cont = 0;
                totvert = 0;
                nextcol = 0;
 
-               BLI_scanfill_begin(&sf_ctx);
+               BLI_scanfill_begin_arena(&sf_ctx, sf_arena);
 
                dl = dispbase->first;
                while (dl) {
@@ -553,7 +557,7 @@ void BKE_displist_fill(ListBase *dispbase, ListBase *to, const float normal_proj
 
                        BLI_addhead(to, dlnew);
                }
-               BLI_scanfill_end(&sf_ctx);
+               BLI_scanfill_end_arena(&sf_ctx, sf_arena);
 
                if (nextcol) {
                        /* stay at current char but fill polys with next material */
@@ -566,6 +570,8 @@ void BKE_displist_fill(ListBase *dispbase, ListBase *to, const float normal_proj
                }
        }
 
+       BLI_memarena_free(sf_arena);
+
        /* do not free polys, needed for wireframe display */
 }
 
index 74cd8834d5d7b47e07c0a93b7f6bddf49df89be7..6a89d16d7bfc1f8eeae3586041290bc840ee2d72 100644 (file)
@@ -36,6 +36,7 @@
 #include "DNA_mesh_types.h"
 
 #include "BLI_math.h"
+#include "BLI_memarena.h"
 #include "BLI_scanfill.h"
 
 #include "BKE_editmesh.h"
@@ -123,6 +124,7 @@ static void editmesh_tessface_calc_intern(BMEditMesh *em)
        int i = 0;
 
        ScanFillContext sf_ctx;
+       MemArena *sf_arena = NULL;
 
 #if 0
        /* note, we could be clever and re-use this array but would need to ensure
@@ -217,7 +219,11 @@ static void editmesh_tessface_calc_intern(BMEditMesh *em)
                        ScanFillFace *sf_tri;
                        int totfilltri;
 
-                       BLI_scanfill_begin(&sf_ctx);
+                       if (UNLIKELY(sf_arena == NULL)) {
+                               sf_arena = BLI_memarena_new(BLI_SCANFILL_ARENA_SIZE, __func__);
+                       }
+
+                       BLI_scanfill_begin_arena(&sf_ctx, sf_arena);
 
                        /* scanfill time */
                        j = 0;
@@ -262,10 +268,15 @@ static void editmesh_tessface_calc_intern(BMEditMesh *em)
                                l_ptr[2] = l3;
                        }
 
-                       BLI_scanfill_end(&sf_ctx);
+                       BLI_scanfill_end_arena(&sf_ctx, sf_arena);
                }
        }
 
+       if (sf_arena) {
+               BLI_memarena_free(sf_arena);
+               sf_arena = NULL;
+       }
+
        em->tottri = i;
        em->looptris = looptris;
 
index ac48eaa3185b76b7704de9926c00f55a008141cc..e5e49763784ca59a970a104b740e6bc1bf450e18 100644 (file)
@@ -575,11 +575,14 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas
        const float zvec[3] = {0.0f, 0.0f, 1.0f};
        MaskLayer *masklay;
        unsigned int masklay_index;
+       MemArena *sf_arena;
 
        mr_handle->layers_tot = (unsigned int)BLI_countlist(&mask->masklayers);
        mr_handle->layers = MEM_mallocN(sizeof(MaskRasterLayer) * mr_handle->layers_tot, "MaskRasterLayer");
        BLI_rctf_init_minmax(&mr_handle->bounds);
 
+       sf_arena = BLI_memarena_new(BLI_SCANFILL_ARENA_SIZE, __func__);
+
        for (masklay = mask->masklayers.first, masklay_index = 0; masklay; masklay = masklay->next, masklay_index++) {
 
                /* we need to store vertex ranges for open splines for filling */
@@ -613,7 +616,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas
                tot_splines = (unsigned int)BLI_countlist(&masklay->splines);
                open_spline_ranges = MEM_callocN(sizeof(*open_spline_ranges) * tot_splines, __func__);
 
-               BLI_scanfill_begin(&sf_ctx);
+               BLI_scanfill_begin_arena(&sf_ctx, sf_arena);
 
                for (spline = masklay->splines.first; spline; spline = spline->next) {
                        const unsigned int is_cyclic = (spline->flag & MASK_SPLINE_CYCLIC) != 0;
@@ -1148,8 +1151,10 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas
                }
 
                /* add trianges */
-               BLI_scanfill_end(&sf_ctx);
+               BLI_scanfill_end_arena(&sf_ctx, sf_arena);
        }
+
+       BLI_memarena_free(sf_arena);
 }
 
 
index 9465044ba0b47d1ac5370c79a47c1e4c6041736d..0d3bc1b71e3f5d42006837dde9d0c3f4bf74de1d 100644 (file)
@@ -46,6 +46,7 @@
 
 #include "BLI_utildefines.h"
 #include "BLI_blenlib.h"
+#include "BLI_memarena.h"
 #include "BLI_math.h"
 #include "BLI_edgehash.h"
 #include "BLI_bitmap.h"
@@ -2733,6 +2734,7 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata,
        ScanFillContext sf_ctx;
        ScanFillVert *sf_vert, *sf_vert_last, *sf_vert_first;
        ScanFillFace *sf_tri;
+       MemArena *sf_arena = NULL;
        int *mface_to_poly_map;
        int lindex[4]; /* only ever use 3 in this case */
        int poly_index, j, mface_index;
@@ -2815,7 +2817,11 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata,
 #endif
                        ml = mloop + mp->loopstart;
                        
-                       BLI_scanfill_begin(&sf_ctx);
+                       if (UNLIKELY(sf_arena == NULL)) {
+                               sf_arena = BLI_memarena_new(BLI_SCANFILL_ARENA_SIZE, __func__);
+                       }
+
+                       BLI_scanfill_begin_arena(&sf_ctx, sf_arena);
                        sf_vert_first = NULL;
                        sf_vert_last = NULL;
                        for (j = 0; j < mp->totloop; j++, ml++) {
@@ -2867,12 +2873,17 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata,
                                mface_index++;
                        }
        
-                       BLI_scanfill_end(&sf_ctx);
+                       BLI_scanfill_end_arena(&sf_ctx, sf_arena);
 
 #undef USE_TESSFACE_CALCNORMAL
                }
        }
 
+       if (sf_arena) {
+               BLI_memarena_free(sf_arena);
+               sf_arena = NULL;
+       }
+
        CustomData_free(fdata, totface);
        totface = mface_index;
 
index 21197670640064f1d06fd60f9e18f4f23bb512d8..40658095fd9c3d6d734fa1dc68447d3b827239d3 100644 (file)
@@ -46,20 +46,13 @@ typedef struct ScanFillContext {
        ListBase filledgebase;
        ListBase fillfacebase;
 
-       /* simple optimization for allocating thousands of small memory blocks
-        * only to be used within loops, and not by one function at a time
-        * free in the end, with argument '-1'
-        */
-#define MEM_ELEM_BLOCKSIZE 16384
-       struct mem_elements *melem__cur;
-       int melem__offs;                   /* the current free address */
-       ListBase melem__lb;
-
        /* private */
        struct ScanFillVertLink *_scdata;
+       struct MemArena *arena;
 } ScanFillContext;
 
-/* note; changing this also might affect the undo copy in editmesh.c */
+#define BLI_SCANFILL_ARENA_SIZE 16384
+
 typedef struct ScanFillVert {
        struct ScanFillVert *next, *prev;
        union {
@@ -68,9 +61,9 @@ typedef struct ScanFillVert {
                intptr_t             l;
                unsigned int         u;
        } tmp;
-       float co[3]; /* vertex location */
-       float xy[2]; /* 2D copy of vertex location (using dominant axis) */
-       unsigned int keyindex; /* original index #, for restoring  key information */
+       float co[3];  /* vertex location */
+       float xy[2];  /* 2D projection of vertex location */
+       unsigned int keyindex; /* index, caller can use how it likes to match the scanfill result with own data */
        short poly_nr;
        unsigned char edge_tot;  /* number of edges using this vertex */
        unsigned char f;
@@ -91,7 +84,7 @@ typedef struct ScanFillFace {
        struct ScanFillVert *v1, *v2, *v3;
 } ScanFillFace;
 
-/* scanfill.c: used in displist only... */
+/* scanfill.c */
 struct ScanFillVert *BLI_scanfill_vert_add(ScanFillContext *sf_ctx, const float vec[3]);
 struct ScanFillEdge *BLI_scanfill_edge_add(ScanFillContext *sf_ctx, struct ScanFillVert *v1, struct ScanFillVert *v2);
 
@@ -113,6 +106,9 @@ int  BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag,
                           const float nor_proj[3]);
 void BLI_scanfill_end(ScanFillContext *sf_ctx);
 
+void BLI_scanfill_begin_arena(ScanFillContext *sf_ctx, struct MemArena *arena);
+void BLI_scanfill_end_arena(ScanFillContext *sf_ctx, struct MemArena *arena);
+
 /* These callbacks are needed to make the lib finction properly */
 void BLI_setErrorCallBack(void (*f)(const char *));
 
index c7163874dcad6545fa407a66c4cb7a774e8d19b2..ae9f36b957cf8af4743ebcfb1e58035e8444d2c8 100644 (file)
@@ -40,6 +40,7 @@
 #include "BLI_callbacks.h"
 #include "BLI_listbase.h"
 #include "BLI_math.h"
+#include "BLI_memarena.h"
 #include "BLI_scanfill.h"
 #include "BLI_utildefines.h"
 
@@ -132,99 +133,45 @@ static int vergpoly(const void *a1, const void *a2)
        return 0;
 }
 
-/* ************* MEMORY MANAGEMENT ************* */
-
-/* memory management */
-struct mem_elements {
-       struct mem_elements *next, *prev;
-       char *data;
-};
+/* ****  FILL ROUTINES *************************** */
 
-static void *mem_element_new(ScanFillContext *sf_ctx, int size)
+ScanFillVert *BLI_scanfill_vert_add(ScanFillContext *sf_ctx, const float vec[3])
 {
-       BLI_assert(!(size > 10000 || size == 0)); /* this is invalid use! */
-
-       size = (size + 3) & ~3;     /* allocate in units of 4 */
+       ScanFillVert *sf_v;
        
-       if (sf_ctx->melem__cur && (size + sf_ctx->melem__offs < MEM_ELEM_BLOCKSIZE)) {
-               void *adr = (void *) (sf_ctx->melem__cur->data + sf_ctx->melem__offs);
-               sf_ctx->melem__offs += size;
-               return adr;
-       }
-       else {
-               sf_ctx->melem__cur = MEM_callocN(sizeof(struct mem_elements), "newmem");
-               sf_ctx->melem__cur->data = MEM_callocN(MEM_ELEM_BLOCKSIZE, "newmem");
-               BLI_addtail(&sf_ctx->melem__lb, sf_ctx->melem__cur);
+       sf_v = BLI_memarena_alloc(sf_ctx->arena, sizeof(ScanFillVert));
 
-               sf_ctx->melem__offs = size;
-               return sf_ctx->melem__cur->data;
-       }
-}
-static void mem_element_reset(ScanFillContext *sf_ctx, int keep_first)
-{
-       struct mem_elements *first;
-
-       if ((first = sf_ctx->melem__lb.first)) { /* can be false if first fill fails */
-               if (keep_first) {
-                       BLI_remlink(&sf_ctx->melem__lb, first);
-               }
-
-               sf_ctx->melem__cur = sf_ctx->melem__lb.first;
-               while (sf_ctx->melem__cur) {
-                       MEM_freeN(sf_ctx->melem__cur->data);
-                       sf_ctx->melem__cur = sf_ctx->melem__cur->next;
-               }
-               BLI_freelistN(&sf_ctx->melem__lb);
-
-               /*reset the block we're keeping*/
-               if (keep_first) {
-                       BLI_addtail(&sf_ctx->melem__lb, first);
-                       memset(first->data, 0, MEM_ELEM_BLOCKSIZE);
-               }
-               else {
-                       first = NULL;
+       BLI_addtail(&sf_ctx->fillvertbase, sf_v);
 
-               }
-       }
+       sf_v->tmp.p = NULL;
+       copy_v3_v3(sf_v->co, vec);
 
-       sf_ctx->melem__cur = first;
-       sf_ctx->melem__offs = 0;
-}
+       /* just zero out the rest */
+       zero_v2(sf_v->xy);
+       sf_v->keyindex = 0;
+       sf_v->poly_nr = 0;
+       sf_v->edge_tot = 0;
+       sf_v->f = 0;
 
-void BLI_scanfill_end(ScanFillContext *sf_ctx)
-{
-       mem_element_reset(sf_ctx, FALSE);
-       
-       sf_ctx->fillvertbase.first = sf_ctx->fillvertbase.last = NULL;
-       sf_ctx->filledgebase.first = sf_ctx->filledgebase.last = NULL;
-       sf_ctx->fillfacebase.first = sf_ctx->fillfacebase.last = NULL;
-}
-
-/* ****  FILL ROUTINES *************************** */
-
-ScanFillVert *BLI_scanfill_vert_add(ScanFillContext *sf_ctx, const float vec[3])
-{
-       ScanFillVert *eve;
-       
-       eve = mem_element_new(sf_ctx, sizeof(ScanFillVert));
-       BLI_addtail(&sf_ctx->fillvertbase, eve);
-       
-       copy_v3_v3(eve->co, vec);
-
-       return eve;
+       return sf_v;
 }
 
 ScanFillEdge *BLI_scanfill_edge_add(ScanFillContext *sf_ctx, ScanFillVert *v1, ScanFillVert *v2)
 {
-       ScanFillEdge *newed;
+       ScanFillEdge *sf_ed;
 
-       newed = mem_element_new(sf_ctx, sizeof(ScanFillEdge));
-       BLI_addtail(&sf_ctx->filledgebase, newed);
+       sf_ed = BLI_memarena_alloc(sf_ctx->arena, sizeof(ScanFillEdge));
+       BLI_addtail(&sf_ctx->filledgebase, sf_ed);
        
-       newed->v1 = v1;
-       newed->v2 = v2;
+       sf_ed->v1 = v1;
+       sf_ed->v2 = v2;
+
+       /* just zero out the rest */
+       sf_ed->poly_nr = 0;
+       sf_ed->f = 0;
+       sf_ed->tmp.c = 0;
 
-       return newed;
+       return sf_ed;
 }
 
 static void addfillface(ScanFillContext *sf_ctx, ScanFillVert *v1, ScanFillVert *v2, ScanFillVert *v3)
@@ -232,7 +179,7 @@ static void addfillface(ScanFillContext *sf_ctx, ScanFillVert *v1, ScanFillVert
        /* does not make edges */
        ScanFillFace *sf_tri;
 
-       sf_tri = mem_element_new(sf_ctx, sizeof(ScanFillFace));
+       sf_tri = BLI_memarena_alloc(sf_ctx->arena, sizeof(ScanFillFace));
        BLI_addtail(&sf_ctx->fillfacebase, sf_tri);
        
        sf_tri->v1 = v1;
@@ -826,11 +773,33 @@ static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int flag)
 void BLI_scanfill_begin(ScanFillContext *sf_ctx)
 {
        memset(sf_ctx, 0, sizeof(*sf_ctx));
+       sf_ctx->arena = BLI_memarena_new(BLI_SCANFILL_ARENA_SIZE, __func__);
 }
 
-int BLI_scanfill_calc(ScanFillContext *sf_ctx, const int flag)
+void BLI_scanfill_begin_arena(ScanFillContext *sf_ctx, MemArena *arena)
 {
-       return BLI_scanfill_calc_ex(sf_ctx, flag, NULL);
+       memset(sf_ctx, 0, sizeof(*sf_ctx));
+       sf_ctx->arena = arena;
+}
+
+void BLI_scanfill_end(ScanFillContext *sf_ctx)
+{
+       BLI_memarena_free(sf_ctx->arena);
+       sf_ctx->arena = NULL;
+
+       sf_ctx->fillvertbase.first = sf_ctx->fillvertbase.last = NULL;
+       sf_ctx->filledgebase.first = sf_ctx->filledgebase.last = NULL;
+       sf_ctx->fillfacebase.first = sf_ctx->fillfacebase.last = NULL;
+}
+
+void BLI_scanfill_end_arena(ScanFillContext *sf_ctx, MemArena *arena)
+{
+       BLI_memarena_clear(arena);
+       BLI_assert(sf_ctx->arena == arena);
+
+       sf_ctx->fillvertbase.first = sf_ctx->fillvertbase.last = NULL;
+       sf_ctx->filledgebase.first = sf_ctx->filledgebase.last = NULL;
+       sf_ctx->fillfacebase.first = sf_ctx->fillfacebase.last = NULL;
 }
 
 int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float nor_proj[3])
@@ -1177,3 +1146,8 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float no
 
        return totfaces;
 }
+
+int BLI_scanfill_calc(ScanFillContext *sf_ctx, const int flag)
+{
+       return BLI_scanfill_calc_ex(sf_ctx, flag, NULL);
+}