scanfill curves, ngons, masks had their own memarena code and would allocate a new one for every fill.
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.
This commit is contained in:
@@ -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 */
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 *));
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
static void *mem_element_new(ScanFillContext *sf_ctx, int size)
|
||||
{
|
||||
BLI_assert(!(size > 10000 || size == 0)); /* this is invalid use! */
|
||||
|
||||
size = (size + 3) & ~3; /* allocate in units of 4 */
|
||||
|
||||
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_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;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
sf_ctx->melem__cur = first;
|
||||
sf_ctx->melem__offs = 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;
|
||||
ScanFillVert *sf_v;
|
||||
|
||||
eve = mem_element_new(sf_ctx, sizeof(ScanFillVert));
|
||||
BLI_addtail(&sf_ctx->fillvertbase, eve);
|
||||
|
||||
copy_v3_v3(eve->co, vec);
|
||||
sf_v = BLI_memarena_alloc(sf_ctx->arena, sizeof(ScanFillVert));
|
||||
|
||||
return eve;
|
||||
BLI_addtail(&sf_ctx->fillvertbase, sf_v);
|
||||
|
||||
sf_v->tmp.p = NULL;
|
||||
copy_v3_v3(sf_v->co, vec);
|
||||
|
||||
/* 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;
|
||||
|
||||
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;
|
||||
|
||||
return newed;
|
||||
/* just zero out the rest */
|
||||
sf_ed->poly_nr = 0;
|
||||
sf_ed->f = 0;
|
||||
sf_ed->tmp.c = 0;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user