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:
authorAntonioya <blendergit@gmail.com>2019-07-21 00:01:19 +0300
committerAntonio Vazquez <blendergit@gmail.com>2019-07-30 18:11:56 +0300
commit7f29fc7415a49d5688efbe10fa0a81b174d49435 (patch)
tree5feca8d0936990eb434cd860e716fc7316773bfb
parentf69e57a53fab92d549a90a0198b86ff766ba0da2 (diff)
Fix T65691: GPencil Drawing long strokes turn invisible
There was a fixed limit to the number of points available in a buffer stroke. Now, the array is expanded as needed using a predefined number of points for each expansion, instead to add one by one. This is done to reduce the number of times the memory allocation is required. As part of the fix, some variables have been renamed to reflect better their use.
-rw-r--r--source/blender/blenloader/intern/readfile.c1
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c6
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_draw_utils.c6
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.c2
-rw-r--r--source/blender/editors/gpencil/annotate_draw.c2
-rw-r--r--source/blender/editors/gpencil/annotate_paint.c77
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c5
-rw-r--r--source/blender/editors/gpencil/gpencil_fill.c18
-rw-r--r--source/blender/editors/gpencil/gpencil_intern.h4
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c92
-rw-r--r--source/blender/editors/gpencil/gpencil_primitive.c25
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c36
-rw-r--r--source/blender/editors/include/ED_gpencil.h6
-rw-r--r--source/blender/makesdna/DNA_gpencil_types.h10
14 files changed, 147 insertions, 143 deletions
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 88d878ac019..a4979cc470c 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -7039,6 +7039,7 @@ static void direct_link_gpencil(FileData *fd, bGPdata *gpd)
/* init stroke buffer */
gpd->runtime.sbuffer = NULL;
+ gpd->runtime.sbuffer_used = 0;
gpd->runtime.sbuffer_size = 0;
gpd->runtime.tot_cp_points = 0;
diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c
index 18950f00823..d5f8d062593 100644
--- a/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c
+++ b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c
@@ -375,7 +375,7 @@ GPUBatch *gpencil_get_buffer_stroke_geom(bGPdata *gpd, short thickness)
Object *ob = draw_ctx->obact;
tGPspoint *points = gpd->runtime.sbuffer;
- int totpoints = gpd->runtime.sbuffer_size;
+ int totpoints = gpd->runtime.sbuffer_used;
/* if cyclic needs more vertex */
int cyclic_add = (gpd->runtime.sbuffer_sflag & GP_STROKE_CYCLIC) ? 1 : 0;
int totvertex = totpoints + cyclic_add + 2;
@@ -477,7 +477,7 @@ GPUBatch *gpencil_get_buffer_point_geom(bGPdata *gpd, short thickness)
Object *ob = draw_ctx->obact;
tGPspoint *points = gpd->runtime.sbuffer;
- int totpoints = gpd->runtime.sbuffer_size;
+ int totpoints = gpd->runtime.sbuffer_used;
static GPUVertFormat format = {0};
static uint pos_id, color_id, thickness_id, uvdata_id, prev_pos_id;
@@ -621,7 +621,7 @@ GPUBatch *gpencil_get_buffer_fill_geom(bGPdata *gpd)
}
const tGPspoint *points = gpd->runtime.sbuffer;
- int totpoints = gpd->runtime.sbuffer_size;
+ int totpoints = gpd->runtime.sbuffer_used;
if (totpoints < 3) {
return NULL;
}
diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c
index 181d2efbabb..9b755217946 100644
--- a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c
+++ b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c
@@ -1493,7 +1493,7 @@ void gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data,
/* Check if may need to draw the active stroke cache, only if this layer is the active layer
* that is being edited. (Stroke buffer is currently stored in gp-data)
*/
- if (gpd->runtime.sbuffer_size > 0) {
+ if (gpd->runtime.sbuffer_used > 0) {
if ((gpd->runtime.sbuffer_sflag & GP_STROKE_ERASER) == 0) {
/* It should also be noted that sbuffer contains temporary point types
* i.e. tGPspoints NOT bGPDspoints
@@ -1506,7 +1506,7 @@ void gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data,
stl->storage->alignment_mode = (gp_style) ? gp_style->alignment_mode : GP_STYLE_FOLLOW_PATH;
/* if only one point, don't need to draw buffer because the user has no time to see it */
- if (gpd->runtime.sbuffer_size > 1) {
+ if (gpd->runtime.sbuffer_used > 1) {
if ((gp_style) && (gp_style->mode == GP_STYLE_MODE_LINE)) {
stl->g_data->shgrps_drawing_stroke = gpencil_shgroup_stroke_create(
vedata,
@@ -1562,7 +1562,7 @@ void gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data,
DRW_shgroup_call(
stl->g_data->shgrps_drawing_stroke, stl->g_data->batch_buffer_stroke, NULL);
- if ((gpd->runtime.sbuffer_size >= 3) &&
+ if ((gpd->runtime.sbuffer_used >= 3) &&
(gpd->runtime.sfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) &&
((gpd->runtime.sbuffer_sflag & GP_STROKE_NOFILL) == 0) &&
((brush->gpencil_settings->flag & GP_BRUSH_DISSABLE_LASSO) == 0) &&
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
index 5d7ec490fb6..16162645f3d 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -430,7 +430,7 @@ void GPENCIL_cache_init(void *vedata)
/* need the original to avoid cow overhead while drawing */
bGPdata *gpd_orig = (bGPdata *)DEG_get_original_id(&obact_gpd->id);
if (((gpd_orig->runtime.sbuffer_sflag & GP_STROKE_ERASER) == 0) &&
- (gpd_orig->runtime.sbuffer_size > 0) &&
+ (gpd_orig->runtime.sbuffer_used > 0) &&
((gpd_orig->flag & GP_DATA_STROKE_POLYGON) == 0) && !DRW_state_is_depth() &&
(stl->storage->background_ready == true)) {
stl->g_data->session_flag |= GP_DRW_PAINT_PAINTING;
diff --git a/source/blender/editors/gpencil/annotate_draw.c b/source/blender/editors/gpencil/annotate_draw.c
index e8f97290173..dce6ed29c05 100644
--- a/source/blender/editors/gpencil/annotate_draw.c
+++ b/source/blender/editors/gpencil/annotate_draw.c
@@ -924,7 +924,7 @@ static void annotation_draw_data_layers(
* i.e. tGPspoints NOT bGPDspoints
*/
annotation_draw_stroke_buffer(gpd->runtime.sbuffer,
- gpd->runtime.sbuffer_size,
+ gpd->runtime.sbuffer_used,
lthick,
dflag,
gpd->runtime.sbuffer_sflag,
diff --git a/source/blender/editors/gpencil/annotate_paint.c b/source/blender/editors/gpencil/annotate_paint.c
index 5962d95c5af..5793b407bdc 100644
--- a/source/blender/editors/gpencil/annotate_paint.c
+++ b/source/blender/editors/gpencil/annotate_paint.c
@@ -281,7 +281,7 @@ static bool gp_stroke_filtermval(tGPsdata *p, const float mval[2], float pmval[2
int dy = (int)fabsf(mval[1] - pmval[1]);
/* if buffer is empty, just let this go through (i.e. so that dots will work) */
- if (p->gpd->runtime.sbuffer_size == 0) {
+ if (p->gpd->runtime.sbuffer_used == 0) {
return true;
/* check if mouse moved at least certain distance on both axes (best case)
@@ -382,7 +382,7 @@ static void gp_stroke_convertcoords(tGPsdata *p, const float mval[2], float out[
static void gp_smooth_buffer(tGPsdata *p, float inf, int idx)
{
bGPdata *gpd = p->gpd;
- short num_points = gpd->runtime.sbuffer_size;
+ short num_points = gpd->runtime.sbuffer_used;
/* Do nothing if not enough points to smooth out */
if ((num_points < 3) || (idx < 3) || (inf == 0.0f)) {
@@ -437,7 +437,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure
/* check painting mode */
if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) {
/* straight lines only - i.e. only store start and end point in buffer */
- if (gpd->runtime.sbuffer_size == 0) {
+ if (gpd->runtime.sbuffer_used == 0) {
/* first point in buffer (start point) */
pt = (tGPspoint *)(gpd->runtime.sbuffer);
@@ -449,7 +449,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure
pt->time = (float)(curtime - p->inittime);
/* increment buffer size */
- gpd->runtime.sbuffer_size++;
+ gpd->runtime.sbuffer_used++;
}
else {
/* just reset the endpoint to the latest value
@@ -465,20 +465,19 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure
pt->time = (float)(curtime - p->inittime);
/* now the buffer has 2 points (and shouldn't be allowed to get any larger) */
- gpd->runtime.sbuffer_size = 2;
+ gpd->runtime.sbuffer_used = 2;
}
/* can keep carrying on this way :) */
return GP_STROKEADD_NORMAL;
}
else if (p->paintmode == GP_PAINTMODE_DRAW) { /* normal drawing */
- /* check if still room in buffer */
- if (gpd->runtime.sbuffer_size >= GP_STROKE_BUFFER_MAX) {
- return GP_STROKEADD_OVERFLOW;
- }
+ /* check if still room in buffer or add more */
+ gpd->runtime.sbuffer = ED_gpencil_sbuffer_ensure(
+ gpd->runtime.sbuffer, &gpd->runtime.sbuffer_size, &gpd->runtime.sbuffer_used, false);
/* get pointer to destination point */
- pt = ((tGPspoint *)(gpd->runtime.sbuffer) + gpd->runtime.sbuffer_size);
+ pt = ((tGPspoint *)(gpd->runtime.sbuffer) + gpd->runtime.sbuffer_used);
/* store settings */
copy_v2_v2(&pt->x, mval);
@@ -490,19 +489,13 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure
pt->time = (float)(curtime - p->inittime);
/* increment counters */
- gpd->runtime.sbuffer_size++;
+ gpd->runtime.sbuffer_used++;
/* smooth while drawing previous points with a reduction factor for previous */
for (int s = 0; s < 3; s++) {
- gp_smooth_buffer(p, 0.5f * ((3.0f - s) / 3.0f), gpd->runtime.sbuffer_size - s);
+ gp_smooth_buffer(p, 0.5f * ((3.0f - s) / 3.0f), gpd->runtime.sbuffer_used - s);
}
- /* check if another operation can still occur */
- if (gpd->runtime.sbuffer_size == GP_STROKE_BUFFER_MAX) {
- return GP_STROKEADD_FULL;
- }
- else {
- return GP_STROKEADD_NORMAL;
- }
+ return GP_STROKEADD_NORMAL;
}
else if (p->paintmode == GP_PAINTMODE_DRAW_POLY) {
/* get pointer to destination point */
@@ -524,7 +517,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure
bGPDspoint *pts;
/* first time point is adding to temporary buffer -- need to allocate new point in stroke */
- if (gpd->runtime.sbuffer_size == 0) {
+ if (gpd->runtime.sbuffer_used == 0) {
gps->points = MEM_reallocN(gps->points, sizeof(bGPDspoint) * (gps->totpoints + 1));
gps->totpoints++;
}
@@ -557,8 +550,8 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure
}
/* increment counters */
- if (gpd->runtime.sbuffer_size == 0) {
- gpd->runtime.sbuffer_size++;
+ if (gpd->runtime.sbuffer_used == 0) {
+ gpd->runtime.sbuffer_used++;
}
return GP_STROKEADD_NORMAL;
@@ -576,7 +569,7 @@ static void gp_stroke_simplify(tGPsdata *p)
{
bGPdata *gpd = p->gpd;
tGPspoint *old_points = (tGPspoint *)gpd->runtime.sbuffer;
- short num_points = gpd->runtime.sbuffer_size;
+ short num_points = gpd->runtime.sbuffer_used;
short flag = gpd->runtime.sbuffer_sflag;
short i, j;
@@ -668,17 +661,17 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
* - drawing straight-lines only requires the endpoints
*/
if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) {
- totelem = (gpd->runtime.sbuffer_size >= 2) ? 2 : gpd->runtime.sbuffer_size;
+ totelem = (gpd->runtime.sbuffer_used >= 2) ? 2 : gpd->runtime.sbuffer_used;
}
else {
- totelem = gpd->runtime.sbuffer_size;
+ totelem = gpd->runtime.sbuffer_used;
}
/* exit with error if no valid points from this stroke */
if (totelem == 0) {
if (G.debug & G_DEBUG) {
printf("Error: No valid points in stroke buffer to convert (tot=%d)\n",
- gpd->runtime.sbuffer_size);
+ gpd->runtime.sbuffer_used);
}
return;
}
@@ -736,7 +729,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
if (totelem == 2) {
/* last point if applicable */
- ptc = ((tGPspoint *)gpd->runtime.sbuffer) + (gpd->runtime.sbuffer_size - 1);
+ ptc = ((tGPspoint *)gpd->runtime.sbuffer) + (gpd->runtime.sbuffer_used - 1);
/* convert screen-coordinates to appropriate coordinates (and store them) */
gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL);
@@ -769,9 +762,9 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
int interp_depth = 0;
int found_depth = 0;
- depth_arr = MEM_mallocN(sizeof(float) * gpd->runtime.sbuffer_size, "depth_points");
+ depth_arr = MEM_mallocN(sizeof(float) * gpd->runtime.sbuffer_used, "depth_points");
- for (i = 0, ptc = gpd->runtime.sbuffer; i < gpd->runtime.sbuffer_size; i++, ptc++, pt++) {
+ for (i = 0, ptc = gpd->runtime.sbuffer; i < gpd->runtime.sbuffer_used; i++, ptc++, pt++) {
round_v2i_v2fl(mval_i, &ptc->x);
if ((ED_view3d_autodist_depth(p->ar, mval_i, depth_margin, depth_arr + i) == 0) &&
@@ -788,7 +781,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
if (found_depth == false) {
/* eeh... not much we can do.. :/, ignore depth in this case, use the 3D cursor */
- for (i = gpd->runtime.sbuffer_size - 1; i >= 0; i--) {
+ for (i = gpd->runtime.sbuffer_used - 1; i >= 0; i--) {
depth_arr[i] = 0.9999f;
}
}
@@ -798,14 +791,14 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
int first_valid = 0;
int last_valid = 0;
- for (i = 0; i < gpd->runtime.sbuffer_size; i++) {
+ for (i = 0; i < gpd->runtime.sbuffer_used; i++) {
if (depth_arr[i] != FLT_MAX) {
break;
}
}
first_valid = i;
- for (i = gpd->runtime.sbuffer_size - 1; i >= 0; i--) {
+ for (i = gpd->runtime.sbuffer_used - 1; i >= 0; i--) {
if (depth_arr[i] != FLT_MAX) {
break;
}
@@ -821,7 +814,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
}
if (interp_depth) {
- interp_sparse_array(depth_arr, gpd->runtime.sbuffer_size, FLT_MAX);
+ interp_sparse_array(depth_arr, gpd->runtime.sbuffer_used, FLT_MAX);
}
}
}
@@ -829,7 +822,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
pt = gps->points;
/* convert all points (normal behavior) */
- for (i = 0, ptc = gpd->runtime.sbuffer; i < gpd->runtime.sbuffer_size && ptc;
+ for (i = 0, ptc = gpd->runtime.sbuffer; i < gpd->runtime.sbuffer_used && ptc;
i++, ptc++, pt++) {
/* convert screen-coordinates to appropriate coordinates (and store them) */
gp_stroke_convertcoords(p, &ptc->x, &pt->x, depth_arr ? depth_arr + i : NULL);
@@ -1049,19 +1042,8 @@ static void gp_session_validatebuffer(tGPsdata *p)
{
bGPdata *gpd = p->gpd;
- /* clear memory of buffer (or allocate it if starting a new session) */
- if (gpd->runtime.sbuffer) {
- /* printf("\t\tGP - reset sbuffer\n"); */
- memset(gpd->runtime.sbuffer, 0, sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX);
- }
- else {
- /* printf("\t\tGP - allocate sbuffer\n"); */
- gpd->runtime.sbuffer = MEM_callocN(sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX,
- "gp_session_strokebuffer");
- }
-
- /* reset indices */
- gpd->runtime.sbuffer_size = 0;
+ gpd->runtime.sbuffer = ED_gpencil_sbuffer_ensure(
+ gpd->runtime.sbuffer, &gpd->runtime.sbuffer_size, &gpd->runtime.sbuffer_used, true);
/* reset flags */
gpd->runtime.sbuffer_sflag = 0;
@@ -1295,6 +1277,7 @@ static void gp_session_cleanup(tGPsdata *p)
}
/* clear flags */
+ gpd->runtime.sbuffer_used = 0;
gpd->runtime.sbuffer_size = 0;
gpd->runtime.sbuffer_sflag = 0;
p->inittime = 0.0;
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index 8ac3f801999..0fc051e4756 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -3144,10 +3144,7 @@ static void gpencil_stroke_join_strokes(bGPDstroke *gps_a,
/* 3rd: add all points */
for (i = 0, pt = gps_b->points; i < gps_b->totpoints && pt; i++, pt++) {
- /* check if still room in buffer */
- if (gps_a->totpoints <= GP_STROKE_BUFFER_MAX - 2) {
- gpencil_stroke_copy_point(gps_a, pt, i, delta, pt->pressure, pt->strength, deltatime);
- }
+ gpencil_stroke_copy_point(gps_a, pt, i, delta, pt->pressure, pt->strength, deltatime);
}
}
diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c
index d914cdea442..1ac4471547e 100644
--- a/source/blender/editors/gpencil/gpencil_fill.c
+++ b/source/blender/editors/gpencil/gpencil_fill.c
@@ -135,7 +135,7 @@ typedef struct tGPDfill {
short fill_factor;
/** number of elements currently in cache */
- short sbuffer_size;
+ short sbuffer_used;
/** temporary points */
void *sbuffer;
/** depth array for reproject */
@@ -918,7 +918,7 @@ static void gpencil_get_depth_array(tGPDfill *tgpf)
{
tGPspoint *ptc;
ToolSettings *ts = tgpf->scene->toolsettings;
- int totpoints = tgpf->sbuffer_size;
+ int totpoints = tgpf->sbuffer_used;
int i = 0;
if (totpoints == 0) {
@@ -984,7 +984,7 @@ static void gpencil_points_from_stack(tGPDfill *tgpf)
return;
}
- tgpf->sbuffer_size = (short)totpoints;
+ tgpf->sbuffer_used = (short)totpoints;
tgpf->sbuffer = MEM_callocN(sizeof(tGPspoint) * totpoints, __func__);
point2D = tgpf->sbuffer;
@@ -1020,7 +1020,7 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf)
MDeformVert *dvert = NULL;
tGPspoint *point2D;
- if (tgpf->sbuffer_size == 0) {
+ if (tgpf->sbuffer_used == 0) {
return;
}
@@ -1041,8 +1041,8 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf)
gps->mat_nr = BKE_gpencil_object_material_ensure(tgpf->bmain, tgpf->ob, tgpf->mat);
/* allocate memory for storage points */
- gps->totpoints = tgpf->sbuffer_size;
- gps->points = MEM_callocN(sizeof(bGPDspoint) * tgpf->sbuffer_size, "gp_stroke_points");
+ gps->totpoints = tgpf->sbuffer_used;
+ gps->points = MEM_callocN(sizeof(bGPDspoint) * tgpf->sbuffer_used, "gp_stroke_points");
/* initialize triangle memory to dummy data */
gps->tot_triangles = 0;
@@ -1069,7 +1069,7 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf)
dvert = gps->dvert;
}
- for (int i = 0; i < tgpf->sbuffer_size && point2D; i++, point2D++, pt++) {
+ for (int i = 0; i < tgpf->sbuffer_used && point2D; i++, point2D++, pt++) {
/* convert screen-coordinates to 3D coordinates */
gp_stroke_convertcoords_tpoint(tgpf->scene,
tgpf->ar,
@@ -1120,7 +1120,7 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf)
}
/* if parented change position relative to parent object */
- for (int a = 0; a < tgpf->sbuffer_size; a++) {
+ for (int a = 0; a < tgpf->sbuffer_used; a++) {
pt = &gps->points[a];
gp_apply_parent_point(tgpf->depsgraph, tgpf->ob, tgpf->gpd, tgpf->gpl, pt);
}
@@ -1225,7 +1225,7 @@ static tGPDfill *gp_session_init_fill(bContext *C, wmOperator *UNUSED(op))
tgpf->lock_axis = ts->gp_sculpt.lock_axis;
tgpf->oldkey = -1;
- tgpf->sbuffer_size = 0;
+ tgpf->sbuffer_used = 0;
tgpf->sbuffer = NULL;
tgpf->depth_arr = NULL;
diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h
index 6a3439a4898..e28e83b23b0 100644
--- a/source/blender/editors/gpencil/gpencil_intern.h
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -378,8 +378,8 @@ typedef enum eGPencil_PaintModes {
GP_PAINTMODE_SET_CP,
} eGPencil_PaintModes;
-/* maximum sizes of gp-session buffer */
-#define GP_STROKE_BUFFER_MAX 5000
+/* chunk size for gp-session buffer (the total size is a multiple of this number) */
+#define GP_STROKE_BUFFER_CHUNK 2048
/* stroke editing ----- */
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index eed95d1883a..5af355b908d 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -349,7 +349,7 @@ static bool gp_stroke_filtermval(tGPsdata *p, const float mval[2], float mvalo[2
brush->gpencil_settings->flag &= ~GP_BRUSH_STABILIZE_MOUSE_TEMP;
/* if buffer is empty, just let this go through (i.e. so that dots will work) */
- if (p->gpd->runtime.sbuffer_size == 0) {
+ if (p->gpd->runtime.sbuffer_used == 0) {
return true;
}
/* if lazy mouse, check minimum distance */
@@ -486,7 +486,7 @@ static void gp_brush_jitter(bGPdata *gpd,
/* Jitter is applied perpendicular to the mouse movement vector (2D space) */
float mvec[2], svec[2];
/* mouse movement in ints -> floats */
- if (gpd->runtime.sbuffer_size > 1) {
+ if (gpd->runtime.sbuffer_used > 1) {
mvec[0] = (mval[0] - (pt - 1)->x);
mvec[1] = (mval[1] - (pt - 1)->y);
normalize_v2(mvec);
@@ -524,7 +524,7 @@ static void gp_brush_angle(bGPdata *gpd, Brush *brush, tGPspoint *pt, const floa
float v0[2] = {cos(angle), sin(angle)};
/* Apply to first point (only if there are 2 points because before no data to do it ) */
- if (gpd->runtime.sbuffer_size == 1) {
+ if (gpd->runtime.sbuffer_used == 1) {
mvec[0] = (mval[0] - (pt - 1)->x);
mvec[1] = (mval[1] - (pt - 1)->y);
normalize_v2(mvec);
@@ -537,7 +537,7 @@ static void gp_brush_angle(bGPdata *gpd, Brush *brush, tGPspoint *pt, const floa
}
/* apply from second point */
- if (gpd->runtime.sbuffer_size >= 1) {
+ if (gpd->runtime.sbuffer_used >= 1) {
mvec[0] = (mval[0] - (pt - 1)->x);
mvec[1] = (mval[1] - (pt - 1)->y);
normalize_v2(mvec);
@@ -563,7 +563,7 @@ static void gp_brush_angle(bGPdata *gpd, Brush *brush, tGPspoint *pt, const floa
static void gp_smooth_buffer(tGPsdata *p, float inf, int idx)
{
bGPdata *gpd = p->gpd;
- short num_points = gpd->runtime.sbuffer_size;
+ short num_points = gpd->runtime.sbuffer_used;
/* Do nothing if not enough points to smooth out */
if ((num_points < 3) || (idx < 3) || (inf == 0.0f)) {
@@ -626,7 +626,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure
/* check painting mode */
if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) {
/* straight lines only - i.e. only store start and end point in buffer */
- if (gpd->runtime.sbuffer_size == 0) {
+ if (gpd->runtime.sbuffer_used == 0) {
/* first point in buffer (start point) */
pt = (tGPspoint *)(gpd->runtime.sbuffer);
@@ -638,7 +638,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure
pt->time = (float)(curtime - p->inittime);
/* increment buffer size */
- gpd->runtime.sbuffer_size++;
+ gpd->runtime.sbuffer_used++;
}
else {
/* just reset the endpoint to the latest value
@@ -654,20 +654,19 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure
pt->time = (float)(curtime - p->inittime);
/* now the buffer has 2 points (and shouldn't be allowed to get any larger) */
- gpd->runtime.sbuffer_size = 2;
+ gpd->runtime.sbuffer_used = 2;
}
/* can keep carrying on this way :) */
return GP_STROKEADD_NORMAL;
}
else if (p->paintmode == GP_PAINTMODE_DRAW) { /* normal drawing */
- /* check if still room in buffer */
- if (gpd->runtime.sbuffer_size >= GP_STROKE_BUFFER_MAX) {
- return GP_STROKEADD_OVERFLOW;
- }
+ /* check if still room in buffer or add more */
+ gpd->runtime.sbuffer = ED_gpencil_sbuffer_ensure(
+ gpd->runtime.sbuffer, &gpd->runtime.sbuffer_size, &gpd->runtime.sbuffer_used, false);
/* get pointer to destination point */
- pt = ((tGPspoint *)(gpd->runtime.sbuffer) + gpd->runtime.sbuffer_size);
+ pt = ((tGPspoint *)(gpd->runtime.sbuffer) + gpd->runtime.sbuffer_used);
/* store settings */
/* pressure */
@@ -760,9 +759,9 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure
pt->time = (float)(curtime - p->inittime);
/* point uv (only 3d view) */
- if ((p->sa->spacetype == SPACE_VIEW3D) && (gpd->runtime.sbuffer_size > 0)) {
+ if ((p->sa->spacetype == SPACE_VIEW3D) && (gpd->runtime.sbuffer_used > 0)) {
float pixsize = gp_style->texture_pixsize / 1000000.0f;
- tGPspoint *ptb = (tGPspoint *)gpd->runtime.sbuffer + gpd->runtime.sbuffer_size - 1;
+ tGPspoint *ptb = (tGPspoint *)gpd->runtime.sbuffer + gpd->runtime.sbuffer_used - 1;
bGPDspoint spt, spt2;
/* get origin to reproject point */
@@ -787,24 +786,18 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure
}
/* increment counters */
- gpd->runtime.sbuffer_size++;
+ gpd->runtime.sbuffer_used++;
/* smooth while drawing previous points with a reduction factor for previous */
if (brush->gpencil_settings->active_smooth > 0.0f) {
for (int s = 0; s < 3; s++) {
gp_smooth_buffer(p,
brush->gpencil_settings->active_smooth * ((3.0f - s) / 3.0f),
- gpd->runtime.sbuffer_size - s);
+ gpd->runtime.sbuffer_used - s);
}
}
- /* check if another operation can still occur */
- if (gpd->runtime.sbuffer_size == GP_STROKE_BUFFER_MAX) {
- return GP_STROKEADD_FULL;
- }
- else {
- return GP_STROKEADD_NORMAL;
- }
+ return GP_STROKEADD_NORMAL;
}
else if (p->paintmode == GP_PAINTMODE_DRAW_POLY) {
@@ -832,7 +825,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure
MDeformVert *dvert = NULL;
/* first time point is adding to temporary buffer -- need to allocate new point in stroke */
- if (gpd->runtime.sbuffer_size == 0) {
+ if (gpd->runtime.sbuffer_used == 0) {
gps->points = MEM_reallocN(gps->points, sizeof(bGPDspoint) * (gps->totpoints + 1));
if (gps->dvert != NULL) {
gps->dvert = MEM_reallocN(gps->dvert, sizeof(MDeformVert) * (gps->totpoints + 1));
@@ -889,8 +882,8 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure
}
/* increment counters */
- if (gpd->runtime.sbuffer_size == 0) {
- gpd->runtime.sbuffer_size++;
+ if (gpd->runtime.sbuffer_used == 0) {
+ gpd->runtime.sbuffer_used++;
}
return GP_STROKEADD_NORMAL;
@@ -930,17 +923,17 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
* - drawing straight-lines only requires the endpoints
*/
if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) {
- totelem = (gpd->runtime.sbuffer_size >= 2) ? 2 : gpd->runtime.sbuffer_size;
+ totelem = (gpd->runtime.sbuffer_used >= 2) ? 2 : gpd->runtime.sbuffer_used;
}
else {
- totelem = gpd->runtime.sbuffer_size;
+ totelem = gpd->runtime.sbuffer_used;
}
/* exit with error if no valid points from this stroke */
if (totelem == 0) {
if (G.debug & G_DEBUG) {
printf("Error: No valid points in stroke buffer to convert (tot=%d)\n",
- gpd->runtime.sbuffer_size);
+ gpd->runtime.sbuffer_used);
}
return;
}
@@ -1024,7 +1017,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
if (totelem == 2) {
/* last point if applicable */
- ptc = ((tGPspoint *)gpd->runtime.sbuffer) + (gpd->runtime.sbuffer_size - 1);
+ ptc = ((tGPspoint *)gpd->runtime.sbuffer) + (gpd->runtime.sbuffer_used - 1);
/* convert screen-coordinates to appropriate coordinates (and store them) */
gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL);
@@ -1105,9 +1098,9 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
int interp_depth = 0;
int found_depth = 0;
- depth_arr = MEM_mallocN(sizeof(float) * gpd->runtime.sbuffer_size, "depth_points");
+ depth_arr = MEM_mallocN(sizeof(float) * gpd->runtime.sbuffer_used, "depth_points");
- for (i = 0, ptc = gpd->runtime.sbuffer; i < gpd->runtime.sbuffer_size; i++, ptc++, pt++) {
+ for (i = 0, ptc = gpd->runtime.sbuffer; i < gpd->runtime.sbuffer_used; i++, ptc++, pt++) {
round_v2i_v2fl(mval_i, &ptc->x);
@@ -1125,7 +1118,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
if (found_depth == false) {
/* eeh... not much we can do.. :/, ignore depth in this case, use the 3D cursor */
- for (i = gpd->runtime.sbuffer_size - 1; i >= 0; i--) {
+ for (i = gpd->runtime.sbuffer_used - 1; i >= 0; i--) {
depth_arr[i] = 0.9999f;
}
}
@@ -1137,7 +1130,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
int last_valid = 0;
/* find first valid contact point */
- for (i = 0; i < gpd->runtime.sbuffer_size; i++) {
+ for (i = 0; i < gpd->runtime.sbuffer_used; i++) {
if (depth_arr[i] != FLT_MAX) {
break;
}
@@ -1149,7 +1142,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
last_valid = first_valid;
}
else {
- for (i = gpd->runtime.sbuffer_size - 1; i >= 0; i--) {
+ for (i = gpd->runtime.sbuffer_used - 1; i >= 0; i--) {
if (depth_arr[i] != FLT_MAX) {
break;
}
@@ -1158,7 +1151,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
}
/* invalidate any other point, to interpolate between
* first and last contact in an imaginary line between them */
- for (i = 0; i < gpd->runtime.sbuffer_size; i++) {
+ for (i = 0; i < gpd->runtime.sbuffer_used; i++) {
if ((i != first_valid) && (i != last_valid)) {
depth_arr[i] = FLT_MAX;
}
@@ -1167,7 +1160,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
}
if (interp_depth) {
- interp_sparse_array(depth_arr, gpd->runtime.sbuffer_size, FLT_MAX);
+ interp_sparse_array(depth_arr, gpd->runtime.sbuffer_used, FLT_MAX);
}
}
}
@@ -1176,7 +1169,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
dvert = gps->dvert;
/* convert all points (normal behavior) */
- for (i = 0, ptc = gpd->runtime.sbuffer; i < gpd->runtime.sbuffer_size && ptc;
+ for (i = 0, ptc = gpd->runtime.sbuffer; i < gpd->runtime.sbuffer_used && ptc;
i++, ptc++, pt++) {
/* convert screen-coordinates to appropriate coordinates (and store them) */
gp_stroke_convertcoords(p, &ptc->x, &pt->x, depth_arr ? depth_arr + i : NULL);
@@ -1725,18 +1718,8 @@ static void gp_session_validatebuffer(tGPsdata *p)
Brush *brush = p->brush;
/* clear memory of buffer (or allocate it if starting a new session) */
- if (gpd->runtime.sbuffer) {
- /* printf("\t\tGP - reset sbuffer\n"); */
- memset(gpd->runtime.sbuffer, 0, sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX);
- }
- else {
- /* printf("\t\tGP - allocate sbuffer\n"); */
- gpd->runtime.sbuffer = MEM_callocN(sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX,
- "gp_session_strokebuffer");
- }
-
- /* reset indices */
- gpd->runtime.sbuffer_size = 0;
+ gpd->runtime.sbuffer = ED_gpencil_sbuffer_ensure(
+ gpd->runtime.sbuffer, &gpd->runtime.sbuffer_size, &gpd->runtime.sbuffer_used, true);
/* reset flags */
gpd->runtime.sbuffer_sflag = 0;
@@ -2070,6 +2053,7 @@ static void gp_session_cleanup(tGPsdata *p)
}
/* clear flags */
+ gpd->runtime.sbuffer_used = 0;
gpd->runtime.sbuffer_size = 0;
gpd->runtime.sbuffer_sflag = 0;
p->inittime = 0.0;
@@ -2623,14 +2607,14 @@ static void gpencil_draw_apply(bContext *C, wmOperator *op, tGPsdata *p, Depsgra
p->opressure = p->pressure;
p->ocurtime = p->curtime;
- pt = (tGPspoint *)gpd->runtime.sbuffer + gpd->runtime.sbuffer_size - 1;
+ pt = (tGPspoint *)gpd->runtime.sbuffer + gpd->runtime.sbuffer_used - 1;
if (p->paintmode != GP_PAINTMODE_ERASER) {
ED_gpencil_toggle_brush_cursor(C, true, &pt->x);
}
}
else if ((p->brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) &&
- (gpd->runtime.sbuffer_size > 0)) {
- pt = (tGPspoint *)gpd->runtime.sbuffer + gpd->runtime.sbuffer_size - 1;
+ (gpd->runtime.sbuffer_used > 0)) {
+ pt = (tGPspoint *)gpd->runtime.sbuffer + gpd->runtime.sbuffer_used - 1;
if (p->paintmode != GP_PAINTMODE_ERASER) {
ED_gpencil_toggle_brush_cursor(C, true, &pt->x);
}
diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c
index ca77b209811..c79366e6a2b 100644
--- a/source/blender/editors/gpencil/gpencil_primitive.c
+++ b/source/blender/editors/gpencil/gpencil_primitive.c
@@ -114,16 +114,8 @@ static void gp_session_validatebuffer(tGPDprimitive *p)
bGPdata *gpd = p->gpd;
/* clear memory of buffer (or allocate it if starting a new session) */
- if (gpd->runtime.sbuffer) {
- memset(gpd->runtime.sbuffer, 0, sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX);
- }
- else {
- gpd->runtime.sbuffer = MEM_callocN(sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX,
- "gp_session_strokebuffer");
- }
-
- /* reset indices */
- gpd->runtime.sbuffer_size = 0;
+ gpd->runtime.sbuffer = ED_gpencil_sbuffer_ensure(
+ gpd->runtime.sbuffer, &gpd->runtime.sbuffer_size, &gpd->runtime.sbuffer_used, true);
/* reset flags */
gpd->runtime.sbuffer_sflag = 0;
@@ -828,7 +820,7 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi)
}
/* Copy points to buffer */
- tGPspoint *tpt = ((tGPspoint *)(gpd->runtime.sbuffer) + gpd->runtime.sbuffer_size);
+ tGPspoint *tpt = ((tGPspoint *)(gpd->runtime.sbuffer) + gpd->runtime.sbuffer_used);
/* Store original points */
float tmp_xyp[2];
@@ -927,10 +919,10 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi)
tpt->time = p2d->time;
/* point uv */
- if (gpd->runtime.sbuffer_size > 0) {
+ if (gpd->runtime.sbuffer_used > 0) {
MaterialGPencilStyle *gp_style = tgpi->mat->gp_style;
const float pixsize = gp_style->texture_pixsize / 1000000.0f;
- tGPspoint *tptb = (tGPspoint *)gpd->runtime.sbuffer + gpd->runtime.sbuffer_size - 1;
+ tGPspoint *tptb = (tGPspoint *)gpd->runtime.sbuffer + gpd->runtime.sbuffer_used - 1;
bGPDspoint spt, spt2;
/* get origin to reproject point */
@@ -958,7 +950,11 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi)
tpt->uv_rot = p2d->uv_rot;
- gpd->runtime.sbuffer_size++;
+ gpd->runtime.sbuffer_used++;
+
+ /* check if still room in buffer or add more */
+ gpd->runtime.sbuffer = ED_gpencil_sbuffer_ensure(
+ gpd->runtime.sbuffer, &gpd->runtime.sbuffer_size, &gpd->runtime.sbuffer_used, false);
/* add small offset to keep stroke over the surface */
if ((depth_arr) && (gpd->zdepth_offset > 0.0f)) {
@@ -1078,6 +1074,7 @@ static void gpencil_primitive_exit(bContext *C, wmOperator *op)
gpd->runtime.sbuffer = NULL;
/* clear flags */
+ gpd->runtime.sbuffer_used = 0;
gpd->runtime.sbuffer_size = 0;
gpd->runtime.sbuffer_sflag = 0;
}
diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c
index 065c133bf97..ac8196f5ed0 100644
--- a/source/blender/editors/gpencil/gpencil_utils.c
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -1740,7 +1740,7 @@ static void gp_brush_cursor_draw(bContext *C, int x, int y, void *customdata)
}
/* while drawing hide */
- if ((gpd->runtime.sbuffer_size > 0) &&
+ if ((gpd->runtime.sbuffer_used > 0) &&
((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE) == 0) &&
((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) == 0)) {
return;
@@ -2525,3 +2525,37 @@ void ED_gpencil_select_toggle_all(bContext *C, int action)
CTX_DATA_END;
}
}
+
+/* Ensure the SBuffer (while drawing stroke) size is enough to save all points of the stroke */
+tGPspoint *ED_gpencil_sbuffer_ensure(tGPspoint *buffer_array,
+ short *buffer_size,
+ short *buffer_used,
+ const bool clear)
+{
+ tGPspoint *p = NULL;
+
+ /* By default a buffer is created with one block with a predefined number of free points,
+ * if the size is not enough, the cache is reallocated adding a new block of free points.
+ * This is done in order to keep cache small and improve speed. */
+ if (*buffer_used + 1 > *buffer_size) {
+ if ((*buffer_size == 0) || (buffer_array == NULL)) {
+ p = MEM_callocN(sizeof(struct tGPspoint) * GP_STROKE_BUFFER_CHUNK, "GPencil Sbuffer");
+ *buffer_size = GP_STROKE_BUFFER_CHUNK;
+ }
+ else {
+ *buffer_size += GP_STROKE_BUFFER_CHUNK;
+ p = MEM_recallocN(buffer_array, sizeof(struct tGPspoint) * *buffer_size);
+ }
+ buffer_array = p;
+ }
+
+ /* clear old data */
+ if (clear) {
+ *buffer_used = 0;
+ if (buffer_array != NULL) {
+ memset(buffer_array, 0, sizeof(tGPspoint) * *buffer_size);
+ }
+ }
+
+ return buffer_array;
+}
diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h
index 0e3204b30c7..6410e6630a7 100644
--- a/source/blender/editors/include/ED_gpencil.h
+++ b/source/blender/editors/include/ED_gpencil.h
@@ -35,6 +35,7 @@ struct bGPDlayer;
struct bGPDspoint;
struct bGPDstroke;
struct bGPdata;
+struct tGPspoint;
struct ARegion;
struct Depsgraph;
@@ -287,4 +288,9 @@ int ED_gpencil_select_stroke_segment(struct bGPDlayer *gpl,
void ED_gpencil_select_toggle_all(struct bContext *C, int action);
+/* Ensure stroke sbuffer size is enough */
+struct tGPspoint *ED_gpencil_sbuffer_ensure(struct tGPspoint *buffer_array,
+ short *buffer_size,
+ short *buffer_used,
+ const bool clear);
#endif /* __ED_GPENCIL_H__ */
diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h
index 307a6f2fe16..9134e603a87 100644
--- a/source/blender/makesdna/DNA_gpencil_types.h
+++ b/source/blender/makesdna/DNA_gpencil_types.h
@@ -412,7 +412,7 @@ typedef enum eGPLayerBlendModes {
typedef struct bGPdata_Runtime {
/** Last region where drawing was originated. */
struct ARegion *ar;
- /** Stroke buffer (can hold GP_STROKE_BUFFER_MAX). */
+ /** Stroke buffer. */
void *sbuffer;
/* GP Object drawing */
@@ -431,11 +431,13 @@ typedef struct bGPdata_Runtime {
* - buffer must be initialized before use, but freed after
* whole paint operation is over
*/
- /** Number of elements currently in cache. */
- short sbuffer_size;
+ /** Number of elements currently used in cache. */
+ short sbuffer_used;
/** Flags for stroke that cache represents. */
short sbuffer_sflag;
- char _pad[6];
+ /** Number of total elements available in cache. */
+ short sbuffer_size;
+ char _pad[4];
/** Number of control-points for stroke. */
int tot_cp_points;