BArrayStore *BLI_array_store_at_size_ensure( struct BArrayStore_AtSize *bs_stride, const int stride, const int chunk_size) { if (bs_stride->stride_table_len < stride) { bs_stride->stride_table_len = stride; bs_stride->stride_table = MEM_recallocN(bs_stride->stride_table, sizeof(*bs_stride->stride_table) * stride); } BArrayStore **bs_p = &bs_stride->stride_table[stride - 1]; if ((*bs_p) == NULL) { #if 0 unsigned int chunk_count = chunk_size; #else /* calculate best chunk-count to fit a power of two */ unsigned int chunk_count = chunk_size; { unsigned int size = chunk_count * stride; size = power_of_2_max_u(size); size = MEM_SIZE_OPTIMAL(size); chunk_count = size / stride; } #endif (*bs_p) = BLI_array_store_create(stride, chunk_count); } return *bs_p; }
static void layer_bucket_init(MaskRasterLayer *layer, const float pixel_size) { MemArena *arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), __func__); const float bucket_dim_x = BLI_rctf_size_x(&layer->bounds); const float bucket_dim_y = BLI_rctf_size_y(&layer->bounds); layer->buckets_x = (unsigned int)((bucket_dim_x / pixel_size) / (float)BUCKET_PIXELS_PER_CELL); layer->buckets_y = (unsigned int)((bucket_dim_y / pixel_size) / (float)BUCKET_PIXELS_PER_CELL); // printf("bucket size %ux%u\n", layer->buckets_x, layer->buckets_y); CLAMP(layer->buckets_x, 8, 512); CLAMP(layer->buckets_y, 8, 512); layer->buckets_xy_scalar[0] = (1.0f / (bucket_dim_x + FLT_EPSILON)) * (float)layer->buckets_x; layer->buckets_xy_scalar[1] = (1.0f / (bucket_dim_y + FLT_EPSILON)) * (float)layer->buckets_y; { /* width and height of each bucket */ const float bucket_size_x = (bucket_dim_x + FLT_EPSILON) / (float)layer->buckets_x; const float bucket_size_y = (bucket_dim_y + FLT_EPSILON) / (float)layer->buckets_y; const float bucket_max_rad = (max_ff(bucket_size_x, bucket_size_y) * (float)M_SQRT2) + FLT_EPSILON; const float bucket_max_rad_squared = bucket_max_rad * bucket_max_rad; unsigned int *face = &layer->face_array[0][0]; float (*cos)[3] = layer->face_coords; const unsigned int bucket_tot = layer->buckets_x * layer->buckets_y; LinkNode **bucketstore = MEM_callocN(bucket_tot * sizeof(LinkNode *), __func__); unsigned int *bucketstore_tot = MEM_callocN(bucket_tot * sizeof(unsigned int), __func__); unsigned int face_index; for (face_index = 0; face_index < layer->face_tot; face_index++, face += 4) { float xmin; float xmax; float ymin; float ymax; if (face[3] == TRI_VERT) { const float *v1 = cos[face[0]]; const float *v2 = cos[face[1]]; const float *v3 = cos[face[2]]; xmin = min_ff(v1[0], min_ff(v2[0], v3[0])); xmax = max_ff(v1[0], max_ff(v2[0], v3[0])); ymin = min_ff(v1[1], min_ff(v2[1], v3[1])); ymax = max_ff(v1[1], max_ff(v2[1], v3[1])); } else { const float *v1 = cos[face[0]]; const float *v2 = cos[face[1]]; const float *v3 = cos[face[2]]; const float *v4 = cos[face[3]]; xmin = min_ff(v1[0], min_ff(v2[0], min_ff(v3[0], v4[0]))); xmax = max_ff(v1[0], max_ff(v2[0], max_ff(v3[0], v4[0]))); ymin = min_ff(v1[1], min_ff(v2[1], min_ff(v3[1], v4[1]))); ymax = max_ff(v1[1], max_ff(v2[1], max_ff(v3[1], v4[1]))); } /* not essential but may as will skip any faces outside the view */ if (!((xmax < 0.0f) || (ymax < 0.0f) || (xmin > 1.0f) || (ymin > 1.0f))) { CLAMP(xmin, 0.0f, 1.0f); CLAMP(ymin, 0.0f, 1.0f); CLAMP(xmax, 0.0f, 1.0f); CLAMP(ymax, 0.0f, 1.0f); { unsigned int xi_min = (unsigned int) ((xmin - layer->bounds.xmin) * layer->buckets_xy_scalar[0]); unsigned int xi_max = (unsigned int) ((xmax - layer->bounds.xmin) * layer->buckets_xy_scalar[0]); unsigned int yi_min = (unsigned int) ((ymin - layer->bounds.ymin) * layer->buckets_xy_scalar[1]); unsigned int yi_max = (unsigned int) ((ymax - layer->bounds.ymin) * layer->buckets_xy_scalar[1]); void *face_index_void = SET_UINT_IN_POINTER(face_index); unsigned int xi, yi; /* this should _almost_ never happen but since it can in extreme cases, * we have to clamp the values or we overrun the buffer and crash */ if (xi_min >= layer->buckets_x) xi_min = layer->buckets_x - 1; if (xi_max >= layer->buckets_x) xi_max = layer->buckets_x - 1; if (yi_min >= layer->buckets_y) yi_min = layer->buckets_y - 1; if (yi_max >= layer->buckets_y) yi_max = layer->buckets_y - 1; for (yi = yi_min; yi <= yi_max; yi++) { unsigned int bucket_index = (layer->buckets_x * yi) + xi_min; for (xi = xi_min; xi <= xi_max; xi++, bucket_index++) { // unsigned int bucket_index = (layer->buckets_x * yi) + xi; /* correct but do in outer loop */ BLI_assert(xi < layer->buckets_x); BLI_assert(yi < layer->buckets_y); BLI_assert(bucket_index < bucket_tot); /* check if the bucket intersects with the face */ /* note: there is a trade off here since checking box/tri intersections isn't * as optimal as it could be, but checking pixels against faces they will never intersect * with is likely the greater slowdown here - so check if the cell intersects the face */ if (layer_bucket_isect_test(layer, face_index, xi, yi, bucket_size_x, bucket_size_y, bucket_max_rad_squared)) { BLI_linklist_prepend_arena(&bucketstore[bucket_index], face_index_void, arena); bucketstore_tot[bucket_index]++; } } } } } } if (1) { /* now convert linknodes into arrays for faster per pixel access */ unsigned int **buckets_face = MEM_mallocN(bucket_tot * sizeof(*buckets_face), __func__); unsigned int bucket_index; for (bucket_index = 0; bucket_index < bucket_tot; bucket_index++) { if (bucketstore_tot[bucket_index]) { unsigned int *bucket = MEM_mallocN((bucketstore_tot[bucket_index] + 1) * sizeof(unsigned int), __func__); LinkNode *bucket_node; buckets_face[bucket_index] = bucket; for (bucket_node = bucketstore[bucket_index]; bucket_node; bucket_node = bucket_node->next) { *bucket = GET_UINT_FROM_POINTER(bucket_node->link); bucket++; } *bucket = TRI_TERMINATOR_ID; } else { buckets_face[bucket_index] = NULL; } } layer->buckets_face = buckets_face; } MEM_freeN(bucketstore); MEM_freeN(bucketstore_tot); } BLI_memarena_free(arena); }