Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenlib')
-rw-r--r--source/blender/blenlib/BLI_stackdefines.h12
-rw-r--r--source/blender/blenlib/intern/BLI_ghash.c2
-rw-r--r--source/blender/blenlib/intern/BLI_mempool.c42
-rw-r--r--source/blender/blenlib/intern/array_store.c187
-rw-r--r--source/blender/blenlib/intern/noise.c4
5 files changed, 176 insertions, 71 deletions
diff --git a/source/blender/blenlib/BLI_stackdefines.h b/source/blender/blenlib/BLI_stackdefines.h
index b26dc3e26aa..42b11eb9a2b 100644
--- a/source/blender/blenlib/BLI_stackdefines.h
+++ b/source/blender/blenlib/BLI_stackdefines.h
@@ -31,28 +31,28 @@
/* only validate array-bounds in debug mode */
#ifdef DEBUG
# define STACK_DECLARE(stack) unsigned int _##stack##_index, _##stack##_totalloc
-# define STACK_INIT(stack, tot) ((void)stack, (void)((_##stack##_index) = 0), (void)((_##stack##_totalloc) = tot))
-# define _STACK_SIZETEST(stack, off) (BLI_assert((_##stack##_index) + off <= _##stack##_totalloc))
+# define STACK_INIT(stack, tot) ((void)stack, (void)((_##stack##_index) = 0), (void)((_##stack##_totalloc) = (tot)))
+# define _STACK_SIZETEST(stack, off) (BLI_assert((_##stack##_index) + (off) <= _##stack##_totalloc))
# define _STACK_SWAP_TOTALLOC(stack_a, stack_b) SWAP(unsigned int, _##stack_a##_totalloc, _##stack_b##_totalloc)
#else
# define STACK_DECLARE(stack) unsigned int _##stack##_index
-# define STACK_INIT(stack, tot) ((void)stack, (void)((_##stack##_index) = 0), (void)(0 ? tot : 0))
+# define STACK_INIT(stack, tot) ((void)stack, (void)((_##stack##_index) = 0), (void)(0 ? (tot) : 0))
# define _STACK_SIZETEST(stack, off) (void)(stack), (void)(off)
# define _STACK_SWAP_TOTALLOC(stack_a, stack_b) (void)(stack_a), (void)(stack_b)
#endif
-#define _STACK_BOUNDSTEST(stack, index) ((void)stack, BLI_assert((unsigned int)index < _##stack##_index))
+#define _STACK_BOUNDSTEST(stack, index) ((void)stack, BLI_assert((unsigned int)(index) < _##stack##_index))
#define STACK_SIZE(stack) ((void)stack, (_##stack##_index))
#define STACK_CLEAR(stack) {(void)stack; _##stack##_index = 0; } ((void)0)
/** add item to stack */
-#define STACK_PUSH(stack, val) ((void)stack, _STACK_SIZETEST(stack, 1), ((stack)[(_##stack##_index)++] = val))
+#define STACK_PUSH(stack, val) ((void)stack, _STACK_SIZETEST(stack, 1), ((stack)[(_##stack##_index)++] = (val)))
#define STACK_PUSH_RET(stack) ((void)stack, _STACK_SIZETEST(stack, 1), ((stack)[(_##stack##_index)++]))
#define STACK_PUSH_RET_PTR(stack) ((void)stack, _STACK_SIZETEST(stack, 1), &((stack)[(_##stack##_index)++]))
/** take last item from stack */
#define STACK_POP(stack) ((_##stack##_index) ? ((stack)[--(_##stack##_index)]) : NULL)
#define STACK_POP_PTR(stack) ((_##stack##_index) ? &((stack)[--(_##stack##_index)]) : NULL)
-#define STACK_POP_DEFAULT(stack, r) ((_##stack##_index) ? ((stack)[--(_##stack##_index)]) : r)
+#define STACK_POP_DEFAULT(stack, r) ((_##stack##_index) ? ((stack)[--(_##stack##_index)]) : (r))
/** look at last item (assumes non-empty stack) */
#define STACK_PEEK(stack) (BLI_assert(_##stack##_index), ((stack)[_##stack##_index - 1]))
#define STACK_PEEK_PTR(stack) (BLI_assert(_##stack##_index), &((stack)[_##stack##_index - 1]))
diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c
index 05f2d9221ef..06946e520a8 100644
--- a/source/blender/blenlib/intern/BLI_ghash.c
+++ b/source/blender/blenlib/intern/BLI_ghash.c
@@ -1287,7 +1287,7 @@ bool BLI_ghashutil_paircmp(const void *a, const void *b)
const GHashPair *A = a;
const GHashPair *B = b;
- return (BLI_ghashutil_ptrcmp(A->first, B->first) &&
+ return (BLI_ghashutil_ptrcmp(A->first, B->first) ||
BLI_ghashutil_ptrcmp(A->second, B->second));
}
diff --git a/source/blender/blenlib/intern/BLI_mempool.c b/source/blender/blenlib/intern/BLI_mempool.c
index 7338804c685..b7a51f2c48e 100644
--- a/source/blender/blenlib/intern/BLI_mempool.c
+++ b/source/blender/blenlib/intern/BLI_mempool.c
@@ -57,12 +57,29 @@
#ifdef __BIG_ENDIAN__
/* Big Endian */
# define MAKE_ID(a, b, c, d) ( (int)(a) << 24 | (int)(b) << 16 | (c) << 8 | (d) )
+# define MAKE_ID_8(a, b, c, d, e, f, g, h) \
+ ((int64_t)(a) << 56 | (int64_t)(b) << 48 | (int64_t)(c) << 40 | (int64_t)(d) << 32 | \
+ (int64_t)(e) << 24 | (int64_t)(f) << 16 | (int64_t)(g) << 8 | (h) )
#else
/* Little Endian */
# define MAKE_ID(a, b, c, d) ( (int)(d) << 24 | (int)(c) << 16 | (b) << 8 | (a) )
+# define MAKE_ID_8(a, b, c, d, e, f, g, h) \
+ ((int64_t)(h) << 56 | (int64_t)(g) << 48 | (int64_t)(f) << 40 | (int64_t)(e) << 32 | \
+ (int64_t)(d) << 24 | (int64_t)(c) << 16 | (int64_t)(b) << 8 | (a) )
#endif
-#define FREEWORD MAKE_ID('f', 'r', 'e', 'e')
+/**
+ * Important that this value is an is _not_ aligned with ``sizeof(void *)``.
+ * So having a pointer to 2/4/8... aligned memory is enough to ensure the freeword will never be used.
+ * To be safe, use a word thats the same in both directions.
+ */
+#define FREEWORD ((sizeof(void *) > sizeof(int32_t)) ? \
+ MAKE_ID_8('e', 'e', 'r', 'f', 'f', 'r', 'e', 'e') : \
+ MAKE_ID('e', 'f', 'f', 'e'))
+
+/**
+ * The 'used' word just needs to be set to something besides FREEWORD.
+ */
#define USEDWORD MAKE_ID('u', 's', 'e', 'd')
/* currently totalloc isnt used */
@@ -87,7 +104,7 @@ static bool mempool_debug_memset = false;
*/
typedef struct BLI_freenode {
struct BLI_freenode *next;
- int freeword; /* used to identify this as a freed node */
+ intptr_t freeword; /* used to identify this as a freed node */
} BLI_freenode;
/**
@@ -588,19 +605,26 @@ void *BLI_mempool_iterstep(BLI_mempool_iter *iter)
*/
void *BLI_mempool_iterstep(BLI_mempool_iter *iter)
{
- BLI_freenode *ret;
+ if (UNLIKELY(iter->curchunk == NULL)) {
+ return NULL;
+ }
+ const unsigned int esize = iter->pool->esize;
+ BLI_freenode *curnode = POINTER_OFFSET(CHUNK_DATA(iter->curchunk), (esize * iter->curindex));
+ BLI_freenode *ret;
do {
- if (LIKELY(iter->curchunk)) {
- ret = (BLI_freenode *)(((char *)CHUNK_DATA(iter->curchunk)) + (iter->pool->esize * iter->curindex));
+ ret = curnode;
+
+ if (++iter->curindex != iter->pool->pchunk) {
+ curnode = POINTER_OFFSET(curnode, esize);
}
else {
- return NULL;
- }
-
- if (UNLIKELY(++iter->curindex == iter->pool->pchunk)) {
iter->curindex = 0;
iter->curchunk = iter->curchunk->next;
+ if (iter->curchunk == NULL) {
+ return NULL;
+ }
+ curnode = CHUNK_DATA(iter->curchunk);
}
} while (ret->freeword == FREEWORD);
diff --git a/source/blender/blenlib/intern/array_store.c b/source/blender/blenlib/intern/array_store.c
index 7f657f4a048..9baccf38fa3 100644
--- a/source/blender/blenlib/intern/array_store.c
+++ b/source/blender/blenlib/intern/array_store.c
@@ -229,7 +229,9 @@ typedef struct BArrayInfo {
/* pre-calculated */
size_t chunk_byte_size;
+ /* min/max limits (inclusive) */
size_t chunk_byte_size_min;
+ size_t chunk_byte_size_max;
size_t accum_read_ahead_bytes;
#ifdef USE_HASH_TABLE_ACCUMULATE
@@ -455,7 +457,7 @@ static void bchunk_list_ensure_min_size_last(
if (MIN2(chunk_prev->data_len, chunk_curr->data_len) < info->chunk_byte_size_min) {
const size_t data_merge_len = chunk_prev->data_len + chunk_curr->data_len;
/* we could pass, but no need */
- if (data_merge_len <= (info->chunk_byte_size * BCHUNK_SIZE_MAX_MUL)) {
+ if (data_merge_len <= info->chunk_byte_size_max) {
/* we have enough space to merge */
/* remove last from linklist */
@@ -527,6 +529,53 @@ static void bchunk_list_ensure_min_size_last(
}
#endif /* USE_MERGE_CHUNKS */
+
+/**
+ * Split length into 2 values
+ * \param r_data_trim_len: Length which is aligned to the #BArrayInfo.chunk_byte_size
+ * \param r_data_last_chunk_len: The remaining bytes.
+ *
+ * \note This function ensures the size of \a r_data_last_chunk_len
+ * is larger than #BArrayInfo.chunk_byte_size_min.
+ */
+static void bchunk_list_calc_trim_len(
+ const BArrayInfo *info, const size_t data_len,
+ size_t *r_data_trim_len, size_t *r_data_last_chunk_len)
+{
+ size_t data_last_chunk_len = 0;
+ size_t data_trim_len = data_len;
+
+#ifdef USE_MERGE_CHUNKS
+ /* avoid creating too-small chunks
+ * more efficient then merging after */
+ if (data_len > info->chunk_byte_size) {
+ data_last_chunk_len = (data_trim_len % info->chunk_byte_size);
+ data_trim_len = data_trim_len - data_last_chunk_len;
+ if (data_last_chunk_len) {
+ if (data_last_chunk_len < info->chunk_byte_size_min) {
+ /* may be zero and thats OK */
+ data_trim_len -= info->chunk_byte_size;
+ data_last_chunk_len += info->chunk_byte_size;
+ }
+ }
+ }
+ else {
+ data_trim_len = 0;
+ data_last_chunk_len = data_len;
+ }
+
+ BLI_assert((data_trim_len == 0) || (data_trim_len >= info->chunk_byte_size));
+#else
+ data_last_chunk_len = (data_trim_len % info->chunk_byte_size);
+ data_trim_len = data_trim_len - data_last_chunk_len;
+#endif
+
+ BLI_assert(data_trim_len + data_last_chunk_len == data_len);
+
+ *r_data_trim_len = data_trim_len;
+ *r_data_last_chunk_len = data_last_chunk_len;
+}
+
/**
* Append and don't manage merging small chunks.
*/
@@ -542,14 +591,21 @@ static bool bchunk_list_append_only(
return chunk;
}
+/**
+ * \note This is for writing single chunks,
+ * use #bchunk_list_append_data_n when writing large blocks of memory into many chunks.
+ */
static void bchunk_list_append_data(
const BArrayInfo *info, BArrayMemory *bs_mem,
BChunkList *chunk_list,
const ubyte *data, const size_t data_len)
{
BLI_assert(data_len != 0);
+
// printf("data_len: %d\n", data_len);
#ifdef USE_MERGE_CHUNKS
+ BLI_assert(data_len <= info->chunk_byte_size_max);
+
if (!BLI_listbase_is_empty(&chunk_list->chunk_refs)) {
BChunkRef *cref = chunk_list->chunk_refs.last;
BChunk *chunk_prev = cref->link;
@@ -589,6 +645,59 @@ static void bchunk_list_append_data(
#endif
}
+/**
+ * Similar to #bchunk_list_append_data, but handle multiple chunks.
+ * Use for adding arrays of arbitrary sized memory at once.
+ *
+ * \note This function takes care not to perform redundant chunk-merging checks,
+ * so we can write succesive fixed size chunks quickly.
+ */
+static void bchunk_list_append_data_n(
+ const BArrayInfo *info, BArrayMemory *bs_mem,
+ BChunkList *chunk_list,
+ const ubyte *data, size_t data_len)
+{
+ size_t data_trim_len, data_last_chunk_len;
+ bchunk_list_calc_trim_len(info, data_len, &data_trim_len, &data_last_chunk_len);
+
+ if (data_trim_len != 0) {
+ size_t i_prev;
+
+ {
+ const size_t i = info->chunk_byte_size;
+ bchunk_list_append_data(info, bs_mem, chunk_list, data, i);
+ i_prev = i;
+ }
+
+ while (i_prev != data_trim_len) {
+ const size_t i = i_prev + info->chunk_byte_size;
+ BChunk *chunk = bchunk_new_copydata(bs_mem, &data[i_prev], i - i_prev);
+ bchunk_list_append_only(bs_mem, chunk_list, chunk);
+ i_prev = i;
+ }
+
+ if (data_last_chunk_len) {
+ BChunk *chunk = bchunk_new_copydata(bs_mem, &data[i_prev], data_last_chunk_len);
+ bchunk_list_append_only(bs_mem, chunk_list, chunk);
+ // i_prev = data_len; /* UNUSED */
+ }
+ }
+ else {
+ /* if we didn't write any chunks previously,
+ * we may need to merge with the last. */
+ if (data_last_chunk_len) {
+ bchunk_list_append_data(info, bs_mem, chunk_list, data, data_last_chunk_len);
+ // i_prev = data_len; /* UNUSED */
+ }
+ }
+
+#ifdef USE_MERGE_CHUNKS
+ if (data_len > info->chunk_byte_size) {
+ BLI_assert(((BChunkRef *)chunk_list->chunk_refs.last)->link->data_len >= info->chunk_byte_size_min);
+ }
+#endif
+}
+
static void bchunk_list_append(
const BArrayInfo *info, BArrayMemory *bs_mem,
BChunkList *chunk_list,
@@ -611,37 +720,11 @@ static void bchunk_list_fill_from_array(
{
BLI_assert(BLI_listbase_is_empty(&chunk_list->chunk_refs));
- size_t data_last_chunk_len = 0;
- size_t data_trim_len = data_len;
-
-#ifdef USE_MERGE_CHUNKS
- /* avoid creating too-small chunks
- * more efficient then merging after */
- if (data_len > info->chunk_byte_size) {
- data_last_chunk_len = (data_trim_len % info->chunk_byte_size);
- data_trim_len = data_trim_len - data_last_chunk_len;
- if (data_last_chunk_len) {
- if (data_last_chunk_len < info->chunk_byte_size_min) {
- /* may be zero and thats OK */
- data_trim_len -= info->chunk_byte_size;
- data_last_chunk_len += info->chunk_byte_size;
- }
- }
- }
- else {
- data_trim_len = 0;
- data_last_chunk_len = data_len;
- }
-#else
- data_last_chunk_len = (data_trim_len % info->chunk_byte_size);
- data_trim_len = data_trim_len - data_last_chunk_len;
-#endif
-
-
- BLI_assert(data_trim_len + data_last_chunk_len == data_len);
+ size_t data_trim_len, data_last_chunk_len;
+ bchunk_list_calc_trim_len(info, data_len, &data_trim_len, &data_last_chunk_len);
size_t i_prev = 0;
- while (i_prev < data_trim_len) {
+ while (i_prev != data_trim_len) {
const size_t i = i_prev + info->chunk_byte_size;
BChunk *chunk = bchunk_new_copydata(bs_mem, &data[i_prev], i - i_prev);
bchunk_list_append_only(bs_mem, chunk_list, chunk);
@@ -1220,21 +1303,8 @@ static BChunkList *bchunk_list_from_data_merge(
if (cref_found != NULL) {
BLI_assert(i < data_len);
if (i != i_prev) {
- size_t i_step = MIN2(i_prev + info->chunk_byte_size, data_len);
- BLI_assert(i_step <= data_len);
-
- while (i_prev != i) {
- i_step = MIN2(i_step, i);
- const ubyte *data_slice = &data[i_prev];
- const size_t data_slice_len = i_step - i_prev;
- /* First add all previous chunks! */
- i_prev += data_slice_len;
- bchunk_list_append_data(info, bs_mem, chunk_list, data_slice, data_slice_len);
- BLI_assert(i_prev <= data_len);
- ASSERT_CHUNKLIST_SIZE(chunk_list, i_prev);
- ASSERT_CHUNKLIST_DATA(chunk_list, data);
- i_step += info->chunk_byte_size;
- }
+ bchunk_list_append_data_n(info, bs_mem, chunk_list, &data[i_prev], i - i_prev);
+ i_prev = i;
}
/* now add the reference chunk */
@@ -1294,14 +1364,9 @@ static BChunkList *bchunk_list_from_data_merge(
*
* Trailing chunks, no matches found in table lookup above.
* Write all new data. */
- BLI_assert(i_prev <= data_len);
- while (i_prev != data_len) {
- size_t i = i_prev + info->chunk_byte_size;
- i = MIN2(i, data_len);
- BLI_assert(i != i_prev);
- bchunk_list_append_data(info, bs_mem, chunk_list, &data[i_prev], i - i_prev);
- ASSERT_CHUNKLIST_DATA(chunk_list, data);
- i_prev = i;
+ if (i_prev != data_len) {
+ bchunk_list_append_data_n(info, bs_mem, chunk_list, &data[i_prev], data_len - i_prev);
+ i_prev = data_len;
}
BLI_assert(i_prev == data_len);
@@ -1374,6 +1439,7 @@ BArrayStore *BLI_array_store_create(
bs->info.chunk_byte_size = chunk_count * stride;
#ifdef USE_MERGE_CHUNKS
bs->info.chunk_byte_size_min = MAX2(1u, chunk_count / BCHUNK_SIZE_MIN_DIV) * stride;
+ bs->info.chunk_byte_size_max = (chunk_count * BCHUNK_SIZE_MAX_MUL) * stride;
#endif
#ifdef USE_HASH_TABLE_ACCUMULATE
@@ -1640,6 +1706,21 @@ bool BLI_array_store_is_valid(
if (!(bchunk_list_size(chunk_list) == chunk_list->total_size)) {
return false;
}
+
+ if (BLI_listbase_count(&chunk_list->chunk_refs) != (int)chunk_list->chunk_refs_len) {
+ return false;
+ }
+
+#ifdef USE_MERGE_CHUNKS
+ /* ensure we merge all chunks that could be merged */
+ if (chunk_list->total_size > bs->info.chunk_byte_size_min) {
+ for (BChunkRef *cref = chunk_list->chunk_refs.first; cref; cref = cref->next) {
+ if (cref->link->data_len < bs->info.chunk_byte_size_min) {
+ return false;
+ }
+ }
+ }
+#endif
}
{
diff --git a/source/blender/blenlib/intern/noise.c b/source/blender/blenlib/intern/noise.c
index c3a0c44d7c5..f834c5b4c74 100644
--- a/source/blender/blenlib/intern/noise.c
+++ b/source/blender/blenlib/intern/noise.c
@@ -1048,8 +1048,8 @@ static float noise3_perlin(float vec[3])
b01 = p[i + by1];
b11 = p[j + by1];
-#define VALUE_AT(rx, ry, rz) (rx * q[0] + ry * q[1] + rz * q[2])
-#define SURVE(t) (t * t * (3.0f - 2.0f * t))
+#define VALUE_AT(rx, ry, rz) ((rx) * q[0] + (ry) * q[1] + (rz) * q[2])
+#define SURVE(t) ((t) * (t) * (3.0f - 2.0f * (t)))
/* lerp moved to improved perlin above */