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 /source/blender/editors/gpencil
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.
Diffstat (limited to 'source/blender/editors/gpencil')
-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
8 files changed, 127 insertions, 132 deletions
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;
+}