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;
}
Пример #2
0
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);
}