diff options
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 1 | ||||
-rw-r--r-- | source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c | 6 | ||||
-rw-r--r-- | source/blender/draw/engines/gpencil/gpencil_draw_utils.c | 6 | ||||
-rw-r--r-- | source/blender/draw/engines/gpencil/gpencil_engine.c | 2 | ||||
-rw-r--r-- | source/blender/editors/gpencil/annotate_draw.c | 2 | ||||
-rw-r--r-- | source/blender/editors/gpencil/annotate_paint.c | 77 | ||||
-rw-r--r-- | source/blender/editors/gpencil/gpencil_edit.c | 5 | ||||
-rw-r--r-- | source/blender/editors/gpencil/gpencil_fill.c | 18 | ||||
-rw-r--r-- | source/blender/editors/gpencil/gpencil_intern.h | 4 | ||||
-rw-r--r-- | source/blender/editors/gpencil/gpencil_paint.c | 92 | ||||
-rw-r--r-- | source/blender/editors/gpencil/gpencil_primitive.c | 25 | ||||
-rw-r--r-- | source/blender/editors/gpencil/gpencil_utils.c | 36 | ||||
-rw-r--r-- | source/blender/editors/include/ED_gpencil.h | 6 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_gpencil_types.h | 10 |
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; |