From 3e3efae7e9420817a6fe35545d97568a69e2ce7c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 17 Apr 2014 15:14:07 +1000 Subject: Viewport Text Drawing: replace single allocs with a memarena - pass label strlen since in many cases its already known. - use single linked list for cached text drawing. - add BLI_link_utils.h for single linked list macros. own tests give approx 22% overall speedup. --- source/blender/blenlib/BLI_link_utils.h | 46 +++++++ source/blender/editors/include/UI_view2d.h | 4 +- source/blender/editors/interface/view2d.c | 81 ++++++++---- source/blender/editors/space_nla/nla_draw.c | 18 +-- .../editors/space_sequencer/sequencer_draw.c | 81 +++++++----- source/blender/editors/space_view3d/drawanimviz.c | 17 ++- source/blender/editors/space_view3d/drawarmature.c | 4 +- source/blender/editors/space_view3d/drawobject.c | 146 +++++++++++++-------- .../blender/editors/space_view3d/view3d_intern.h | 4 +- 9 files changed, 267 insertions(+), 134 deletions(-) create mode 100644 source/blender/blenlib/BLI_link_utils.h diff --git a/source/blender/blenlib/BLI_link_utils.h b/source/blender/blenlib/BLI_link_utils.h new file mode 100644 index 00000000000..d469b105f93 --- /dev/null +++ b/source/blender/blenlib/BLI_link_utils.h @@ -0,0 +1,46 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __BLI_LINK_UTILS_H__ +#define __BLI_LINK_UTILS_H__ + +/** \file BLI_link_utils.h + * \ingroup bli + * \brief Single link-list utility macros. (header only api). + * + * Use this api when the structure defines its own ``next`` pointer + * and a double linked list such as #ListBase isnt needed. + */ + +#define BLI_LINKS_PREPEND(list, link) { \ + CHECK_TYPE_PAIR(list, link); \ + (link)->next = list; \ + list = link; \ +} (void)0 + +#define BLI_LINKS_FREE(list) { \ + while (list) { \ + void *next = list->next; \ + MEM_freeN(list); \ + list = next; \ + } \ +} (void)0 + +#endif /* __BLI_LINK_UTILS_H__ */ diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h index 1208446e14d..b087469887b 100644 --- a/source/blender/editors/include/UI_view2d.h +++ b/source/blender/editors/include/UI_view2d.h @@ -210,8 +210,8 @@ void UI_view2d_offset(struct View2D *v2d, float xfac, float yfac); short UI_view2d_mouse_in_scrollers(const struct bContext *C, struct View2D *v2d, int x, int y); /* cached text drawing in v2d, to allow pixel-aligned draw as post process */ -void UI_view2d_text_cache_add(struct View2D *v2d, float x, float y, const char *str, const char col[4]); -void UI_view2d_text_cache_rectf(struct View2D *v2d, const struct rctf *rect, const char *str, const char col[4]); +void UI_view2d_text_cache_add(struct View2D *v2d, float x, float y, const char *str, size_t str_len, const char col[4]); +void UI_view2d_text_cache_rectf(struct View2D *v2d, const struct rctf *rect, const char *str, size_t str_len, const char col[4]); void UI_view2d_text_cache_draw(struct ARegion *ar); /* operators */ diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c index f20a196627e..8f501e226e7 100644 --- a/source/blender/editors/interface/view2d.c +++ b/source/blender/editors/interface/view2d.c @@ -38,9 +38,13 @@ #include "DNA_scene_types.h" #include "DNA_userdef_types.h" -#include "BLI_blenlib.h" -#include "BLI_math.h" #include "BLI_utildefines.h" +#include "BLI_listbase.h" +#include "BLI_link_utils.h" +#include "BLI_rect.h" +#include "BLI_linklist.h" +#include "BLI_math.h" +#include "BLI_memarena.h" #include "BLI_timecode.h" #include "BKE_context.h" @@ -2175,56 +2179,76 @@ short UI_view2d_mouse_in_scrollers(const bContext *C, View2D *v2d, int x, int y) /* ******************* view2d text drawing cache ******************** */ -/* assumes caches are used correctly, so for time being no local storage in v2d */ -static ListBase strings = {NULL, NULL}; - typedef struct View2DString { - struct View2DString *next, *prev; + struct View2DString *next; union { unsigned char ub[4]; int pack; } col; - int mval[2]; rcti rect; + int mval[2]; } View2DString; +/* assumes caches are used correctly, so for time being no local storage in v2d */ +static MemArena *g_v2d_strings_arena = NULL; +static View2DString *g_v2d_strings = NULL; -void UI_view2d_text_cache_add(View2D *v2d, float x, float y, const char *str, const char col[4]) +void UI_view2d_text_cache_add(View2D *v2d, float x, float y, const char *str, size_t str_len, const char col[4]) { int mval[2]; + BLI_assert(str_len == strlen(str)); + UI_view2d_view_to_region(v2d, x, y, mval, mval + 1); if (mval[0] != V2D_IS_CLIPPED && mval[1] != V2D_IS_CLIPPED) { - int len = strlen(str) + 1; - /* use calloc, rect has to be zeroe'd */ - View2DString *v2s = MEM_callocN(sizeof(View2DString) + len, "View2DString"); - char *v2s_str = (char *)(v2s + 1); - memcpy(v2s_str, str, len); + int alloc_len = str_len + 1; + View2DString *v2s; + + if (g_v2d_strings_arena == NULL) { + g_v2d_strings_arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 14), __func__); + } + + v2s = BLI_memarena_alloc(g_v2d_strings_arena, sizeof(View2DString) + alloc_len); + + BLI_LINKS_PREPEND(g_v2d_strings, v2s); - BLI_addtail(&strings, v2s); v2s->col.pack = *((int *)col); + + memset(&v2s->rect, 0, sizeof(v2s->rect)); + v2s->mval[0] = mval[0]; v2s->mval[1] = mval[1]; + + memcpy(v2s + 1, str, alloc_len); } } /* no clip (yet) */ -void UI_view2d_text_cache_rectf(View2D *v2d, const rctf *rect, const char *str, const char col[4]) +void UI_view2d_text_cache_rectf(View2D *v2d, const rctf *rect, const char *str, size_t str_len, const char col[4]) { - int len = strlen(str) + 1; - View2DString *v2s = MEM_callocN(sizeof(View2DString) + len, "View2DString"); - char *v2s_str = (char *)(v2s + 1); - memcpy(v2s_str, str, len); + int alloc_len = str_len; + View2DString *v2s; + + BLI_assert(str_len == strlen(str)); + + if (g_v2d_strings_arena == NULL) { + g_v2d_strings_arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 14), __func__); + } + + v2s = BLI_memarena_alloc(g_v2d_strings_arena, sizeof(View2DString) + alloc_len); + + BLI_LINKS_PREPEND(g_v2d_strings, v2s); + + v2s->col.pack = *((int *)col); UI_view2d_to_region_no_clip(v2d, rect->xmin, rect->ymin, &v2s->rect.xmin, &v2s->rect.ymin); UI_view2d_to_region_no_clip(v2d, rect->xmax, rect->ymax, &v2s->rect.xmax, &v2s->rect.ymax); - v2s->col.pack = *((int *)col); v2s->mval[0] = v2s->rect.xmin; v2s->mval[1] = v2s->rect.ymin; - BLI_addtail(&strings, v2s); + memcpy(v2s + 1, str, alloc_len); } @@ -2234,7 +2258,7 @@ void UI_view2d_text_cache_draw(ARegion *ar) int col_pack_prev = 0; /* investigate using BLF_ascender() */ - const float default_height = strings.first ? BLF_height_default("28", 3) : 0.0f; + const float default_height = g_v2d_strings ? BLF_height_default("28", 3) : 0.0f; // glMatrixMode(GL_PROJECTION); // glPushMatrix(); @@ -2242,7 +2266,7 @@ void UI_view2d_text_cache_draw(ARegion *ar) // glPushMatrix(); ED_region_pixelspace(ar); - for (v2s = strings.first; v2s; v2s = v2s->next) { + for (v2s = g_v2d_strings; v2s; v2s = v2s->next) { const char *str = (const char *)(v2s + 1); int xofs = 0, yofs; @@ -2263,14 +2287,17 @@ void UI_view2d_text_cache_draw(ARegion *ar) BLF_disable_default(BLF_CLIPPING); } } - + g_v2d_strings = NULL; + + if (g_v2d_strings_arena) { + BLI_memarena_free(g_v2d_strings_arena); + g_v2d_strings_arena = NULL; + } + // glMatrixMode(GL_PROJECTION); // glPopMatrix(); // glMatrixMode(GL_MODELVIEW); // glPopMatrix(); - - if (strings.first) - BLI_freelistN(&strings); } diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index cf01ebd6976..46fd32541cb 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -428,16 +428,17 @@ static void nla_draw_strip_text(AnimData *adt, NlaTrack *nlt, NlaStrip *strip, i { short notSolo = ((adt && (adt->flag & ADT_NLA_SOLO_TRACK)) && (nlt->flag & NLATRACK_SOLO) == 0); char str[256]; + size_t str_len; char col[4]; float xofs; rctf rect; /* just print the name and the range */ if (strip->flag & NLASTRIP_FLAG_TEMP_META) { - BLI_snprintf(str, sizeof(str), "%d) Temp-Meta", index); + str_len = BLI_snprintf(str, sizeof(str), "%d) Temp-Meta", index); } else { - BLI_strncpy(str, strip->name, sizeof(str)); + str_len = BLI_strncpy_rlen(str, strip->name, sizeof(str)); } /* set text color - if colors (see above) are light, draw black text, otherwise draw white */ @@ -470,7 +471,7 @@ static void nla_draw_strip_text(AnimData *adt, NlaTrack *nlt, NlaStrip *strip, i rect.ymax = ymaxc; /* add this string to the cache of texts to draw */ - UI_view2d_text_cache_rectf(v2d, &rect, str, col); + UI_view2d_text_cache_rectf(v2d, &rect, str, str_len, col); } /* add frame extents to cache of text-strings to draw in pixelspace @@ -480,7 +481,8 @@ static void nla_draw_strip_frames_text(NlaTrack *UNUSED(nlt), NlaStrip *strip, V { const float ytol = 1.0f; /* small offset to vertical positioning of text, for legibility */ const char col[4] = {220, 220, 220, 255}; /* light gray */ - char numstr[32] = ""; + char numstr[32]; + size_t numstr_len; /* Always draw times above the strip, whereas sequencer drew below + above. @@ -490,12 +492,12 @@ static void nla_draw_strip_frames_text(NlaTrack *UNUSED(nlt), NlaStrip *strip, V * while also preserving some accuracy, since we do use floats */ /* start frame */ - BLI_snprintf(numstr, sizeof(numstr), "%.1f", strip->start); - UI_view2d_text_cache_add(v2d, strip->start - 1.0f, ymaxc + ytol, numstr, col); + numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%.1f", strip->start); + UI_view2d_text_cache_add(v2d, strip->start - 1.0f, ymaxc + ytol, numstr, numstr_len, col); /* end frame */ - BLI_snprintf(numstr, sizeof(numstr), "%.1f", strip->end); - UI_view2d_text_cache_add(v2d, strip->end, ymaxc + ytol, numstr, col); + numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%.1f", strip->end); + UI_view2d_text_cache_add(v2d, strip->end, ymaxc + ytol, numstr, numstr_len, col); } /* ---------------------- */ diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index fe900b6bcae..a4390d56bcf 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -342,7 +342,6 @@ static void draw_seq_handle(View2D *v2d, Sequence *seq, const float handsize_cla { float v1[2], v2[2], v3[2], rx1 = 0, rx2 = 0; //for triangles and rect float x1, x2, y1, y2; - char numstr[32]; unsigned int whichsel = 0; x1 = seq->startdisp; @@ -401,17 +400,20 @@ static void draw_seq_handle(View2D *v2d, Sequence *seq, const float handsize_cla if ((G.moving & G_TRANSFORM_SEQ) || (seq->flag & whichsel)) { const char col[4] = {255, 255, 255, 255}; + char numstr[32]; + size_t numstr_len; + if (direction == SEQ_LEFTHANDLE) { - BLI_snprintf(numstr, sizeof(numstr), "%d", seq->startdisp); + numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", seq->startdisp); x1 = rx1; y1 -= 0.45f; } else { - BLI_snprintf(numstr, sizeof(numstr), "%d", seq->enddisp - 1); + numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", seq->enddisp - 1); x1 = x2 - handsize_clamped * 0.75f; y1 = y2 + 0.05f; } - UI_view2d_text_cache_add(v2d, x1, y1, numstr, col); + UI_view2d_text_cache_add(v2d, x1, y1, numstr, numstr_len, col); } } @@ -526,6 +528,7 @@ static void draw_seq_text(View2D *v2d, Sequence *seq, float x1, float x2, float { rctf rect; char str[32 + FILE_MAX]; + size_t str_len; const char *name = seq->name + 2; char col[4]; @@ -534,67 +537,76 @@ static void draw_seq_text(View2D *v2d, Sequence *seq, float x1, float x2, float name = BKE_sequence_give_name(seq); if (seq->type == SEQ_TYPE_META || seq->type == SEQ_TYPE_ADJUSTMENT) { - BLI_snprintf(str, sizeof(str), "%s | %d", name, seq->len); + str_len = BLI_snprintf(str, sizeof(str), "%s | %d", name, seq->len); } else if (seq->type == SEQ_TYPE_SCENE) { if (seq->scene) { if (seq->scene_camera) { - BLI_snprintf(str, sizeof(str), "%s: %s (%s) | %d", - name, seq->scene->id.name + 2, ((ID *)seq->scene_camera)->name + 2, seq->len); + str_len = BLI_snprintf(str, sizeof(str), "%s: %s (%s) | %d", + name, seq->scene->id.name + 2, ((ID *)seq->scene_camera)->name + 2, seq->len); } else { - BLI_snprintf(str, sizeof(str), "%s: %s | %d", - name, seq->scene->id.name + 2, seq->len); + str_len = BLI_snprintf(str, sizeof(str), "%s: %s | %d", + name, seq->scene->id.name + 2, seq->len); } } else { - BLI_snprintf(str, sizeof(str), "%s | %d", - name, seq->len); + str_len = BLI_snprintf(str, sizeof(str), "%s | %d", + name, seq->len); } } else if (seq->type == SEQ_TYPE_MOVIECLIP) { if (seq->clip && strcmp(name, seq->clip->id.name + 2) != 0) { - BLI_snprintf(str, sizeof(str), "%s: %s | %d", - name, seq->clip->id.name + 2, seq->len); + str_len = BLI_snprintf(str, sizeof(str), "%s: %s | %d", + name, seq->clip->id.name + 2, seq->len); } else { - BLI_snprintf(str, sizeof(str), "%s | %d", - name, seq->len); + str_len = BLI_snprintf(str, sizeof(str), "%s | %d", + name, seq->len); } } else if (seq->type == SEQ_TYPE_MASK) { if (seq->mask && strcmp(name, seq->mask->id.name + 2) != 0) { - BLI_snprintf(str, sizeof(str), "%s: %s | %d", - name, seq->mask->id.name + 2, seq->len); + str_len = BLI_snprintf(str, sizeof(str), "%s: %s | %d", + name, seq->mask->id.name + 2, seq->len); } else { - BLI_snprintf(str, sizeof(str), "%s | %d", - name, seq->len); + str_len = BLI_snprintf(str, sizeof(str), "%s | %d", + name, seq->len); } } else if (seq->type == SEQ_TYPE_MULTICAM) { - BLI_snprintf(str, sizeof(str), "Cam %s: %d", - name, seq->multicam_source); + str_len = BLI_snprintf(str, sizeof(str), "Cam %s: %d", + name, seq->multicam_source); } else if (seq->type == SEQ_TYPE_IMAGE) { - BLI_snprintf(str, sizeof(str), "%s: %s%s | %d", - name, seq->strip->dir, seq->strip->stripdata->name, seq->len); + str_len = BLI_snprintf(str, sizeof(str), "%s: %s%s | %d", + name, seq->strip->dir, seq->strip->stripdata->name, seq->len); } else if (seq->type & SEQ_TYPE_EFFECT) { - BLI_snprintf(str, sizeof(str), "%s | %d", - name, seq->len); + str_len = BLI_snprintf(str, sizeof(str), "%s | %d", + name, seq->len); } else if (seq->type == SEQ_TYPE_SOUND_RAM) { - if (seq->sound) - BLI_snprintf(str, sizeof(str), "%s: %s | %d", - name, seq->sound->name, seq->len); - else - BLI_snprintf(str, sizeof(str), "%s | %d", - name, seq->len); + if (seq->sound) { + str_len = BLI_snprintf(str, sizeof(str), "%s: %s | %d", + name, seq->sound->name, seq->len); + } + else { + str_len = BLI_snprintf(str, sizeof(str), "%s | %d", + name, seq->len); + } } else if (seq->type == SEQ_TYPE_MOVIE) { - BLI_snprintf(str, sizeof(str), "%s: %s%s | %d", - name, seq->strip->dir, seq->strip->stripdata->name, seq->len); + str_len = BLI_snprintf(str, sizeof(str), "%s: %s%s | %d", + name, seq->strip->dir, seq->strip->stripdata->name, seq->len); + } + else { + /* should never get here!, but might with files from future */ + BLI_assert(0); + + str_len = BLI_snprintf(str, sizeof(str), "%s | %d", + name, seq->len); } if (seq->flag & SELECT) { @@ -612,7 +624,8 @@ static void draw_seq_text(View2D *v2d, Sequence *seq, float x1, float x2, float rect.ymin = y1; rect.xmax = x2; rect.ymax = y2; - UI_view2d_text_cache_rectf(v2d, &rect, str, col); + + UI_view2d_text_cache_rectf(v2d, &rect, str, str_len, col); } /* draws a shaded strip, made from gradient + flat color + gradient */ diff --git a/source/blender/editors/space_view3d/drawanimviz.c b/source/blender/editors/space_view3d/drawanimviz.c index 82e85e3a449..17f90fc54e3 100644 --- a/source/blender/editors/space_view3d/drawanimviz.c +++ b/source/blender/editors/space_view3d/drawanimviz.c @@ -238,22 +238,25 @@ void draw_motion_path_instance(Scene *scene, for (i = 0, mpv = mpv_start; i < len; i += stepsize, mpv += stepsize) { int frame = sfra + i; char numstr[32]; + size_t numstr_len; float co[3]; /* only draw framenum if several consecutive highlighted points don't occur on same point */ if (i == 0) { - sprintf(numstr, " %d", frame); + numstr_len = sprintf(numstr, " %d", frame); mul_v3_m4v3(co, ob->imat, mpv->co); - view3d_cached_text_draw_add(co, numstr, 0, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, col); + view3d_cached_text_draw_add(co, numstr, numstr_len, + 0, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, col); } else if ((i >= stepsize) && (i < len - stepsize)) { bMotionPathVert *mpvP = (mpv - stepsize); bMotionPathVert *mpvN = (mpv + stepsize); if ((equals_v3v3(mpv->co, mpvP->co) == 0) || (equals_v3v3(mpv->co, mpvN->co) == 0)) { - sprintf(numstr, " %d", frame); + numstr_len = sprintf(numstr, " %d", frame); mul_v3_m4v3(co, ob->imat, mpv->co); - view3d_cached_text_draw_add(co, numstr, 0, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, col); + view3d_cached_text_draw_add(co, numstr, numstr_len, + 0, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, col); } } } @@ -314,10 +317,12 @@ void draw_motion_path_instance(Scene *scene, if (BLI_dlrbTree_search_exact(&keys, compare_ak_cfraPtr, &mframe)) { char numstr[32]; + size_t numstr_len; - sprintf(numstr, " %d", (sfra + i)); + numstr_len = sprintf(numstr, " %d", (sfra + i)); mul_v3_m4v3(co, ob->imat, mpv->co); - view3d_cached_text_draw_add(co, numstr, 0, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, col); + view3d_cached_text_draw_add(co, numstr, numstr_len, + 0, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, col); } } } diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c index 4a2fd5f7004..5863416f451 100644 --- a/source/blender/editors/space_view3d/drawarmature.c +++ b/source/blender/editors/space_view3d/drawarmature.c @@ -2065,7 +2065,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, /* Draw names of bone */ if (arm->flag & ARM_DRAWNAMES) { mid_v3_v3v3(vec, pchan->pose_head, pchan->pose_tail); - view3d_cached_text_draw_add(vec, pchan->name, 10, 0, col); + view3d_cached_text_draw_add(vec, pchan->name, strlen(pchan->name), 10, 0, col); } /* Draw additional axes on the bone tail */ @@ -2270,7 +2270,7 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt) if (arm->flag & ARM_DRAWNAMES) { mid_v3_v3v3(vec, eBone->head, eBone->tail); glRasterPos3fv(vec); - view3d_cached_text_draw_add(vec, eBone->name, 10, 0, col); + view3d_cached_text_draw_add(vec, eBone->name, strlen(eBone->name), 10, 0, col); } /* Draw additional axes */ if (arm->flag & ARM_DRAWAXES) { diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index df34f1f6f65..178a7aa5798 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -43,8 +43,12 @@ #include "DNA_world_types.h" #include "DNA_object_types.h" -#include "BLI_blenlib.h" +#include "BLI_listbase.h" +#include "BLI_link_utils.h" +#include "BLI_string.h" +#include "BLI_rect.h" #include "BLI_math.h" +#include "BLI_memarena.h" #include "BKE_anim.h" /* for the where_on_path function */ #include "BKE_armature.h" @@ -742,11 +746,9 @@ static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, const float co[3], } /* *********** text drawing for object/particles/armature ************* */ -static ListBase CachedText[3]; -static int CachedTextLevel = 0; typedef struct ViewCachedString { - struct ViewCachedString *next, *prev; + struct ViewCachedString *next; float vec[3]; union { unsigned char ub[4]; @@ -759,43 +761,61 @@ typedef struct ViewCachedString { /* str is allocated past the end */ } ViewCachedString; +/* one arena for all 3 string lists */ +static MemArena *g_v3d_strings_arena = NULL; +static ViewCachedString *g_v3d_strings[3] = {NULL, NULL, NULL}; +static int g_v3d_string_level = -1; + void view3d_cached_text_draw_begin(void) { - ListBase *strings = &CachedText[CachedTextLevel]; - BLI_listbase_clear(strings); - CachedTextLevel++; + g_v3d_string_level++; + + BLI_assert(g_v3d_string_level >= 0); + + if (g_v3d_string_level == 0) { + BLI_assert(g_v3d_strings_arena == NULL); + } } void view3d_cached_text_draw_add(const float co[3], - const char *str, + const char *str, const size_t str_len, short xoffs, short flag, const unsigned char col[4]) { - int alloc_len = strlen(str) + 1; - ListBase *strings = &CachedText[CachedTextLevel - 1]; + int alloc_len = str_len + 1; /* TODO, replace with more efficient malloc, perhaps memarena per draw? */ - ViewCachedString *vos = MEM_callocN(sizeof(ViewCachedString) + alloc_len, "ViewCachedString"); + ViewCachedString *vos; + + BLI_assert(str_len == strlen(str)); + + if (g_v3d_strings_arena == NULL) { + g_v3d_strings_arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 14), __func__); + } + + vos = BLI_memarena_alloc(g_v3d_strings_arena, sizeof(ViewCachedString) + alloc_len); + + BLI_LINKS_PREPEND(g_v3d_strings[g_v3d_string_level], vos); - BLI_addtail(strings, vos); copy_v3_v3(vos->vec, co); copy_v4_v4_char((char *)vos->col.ub, (const char *)col); vos->xoffs = xoffs; vos->flag = flag; - vos->str_len = alloc_len - 1; + vos->str_len = str_len; /* allocate past the end */ - memcpy(++vos, str, alloc_len); + memcpy(vos + 1, str, alloc_len); } void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write, float mat[4][4]) { RegionView3D *rv3d = ar->regiondata; - ListBase *strings = &CachedText[CachedTextLevel - 1]; ViewCachedString *vos; int tot = 0; + BLI_assert(g_v3d_string_level >= 0 && g_v3d_string_level <= 2); + /* project first and test */ - for (vos = strings->first; vos; vos = vos->next) { + for (vos = g_v3d_strings[g_v3d_string_level]; vos; vos = vos->next) { if (mat && !(vos->flag & V3D_CACHE_TEXT_WORLDSPACE)) mul_m4_v3(mat, vos->vec); @@ -840,7 +860,7 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write, flo glDepthMask(0); } - for (vos = strings->first; vos; vos = vos->next) { + for (vos = g_v3d_strings[g_v3d_string_level]; vos; vos = vos->next) { if (vos->sco[0] != IS_CLIPPED) { const char *str = (char *)(vos + 1); @@ -859,7 +879,7 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write, flo vos->str_len); } } - + if (depth_write) { if (v3d->zbuf) glEnable(GL_DEPTH_TEST); } @@ -876,11 +896,17 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write, flo ED_view3d_clipping_enable(); } } - - if (strings->first) - BLI_freelistN(strings); - - CachedTextLevel--; + + g_v3d_strings[g_v3d_string_level] = NULL; + + if (g_v3d_string_level == 0) { + if (g_v3d_strings_arena) { + BLI_memarena_free(g_v3d_strings_arena); + g_v3d_strings_arena = NULL; + } + } + + g_v3d_string_level--; } /* ******************** primitive drawing ******************* */ @@ -1605,7 +1631,10 @@ static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D float pos[3]; mul_v3_m4v3(pos, mat, track->bundle_pos); - view3d_cached_text_draw_add(pos, track->name, 10, V3D_CACHE_TEXT_GLOBALSPACE, selected ? col_sel : col_unsel); + view3d_cached_text_draw_add(pos, + track->name, strlen(track->name), + 10, V3D_CACHE_TEXT_GLOBALSPACE, + selected ? col_sel : col_unsel); } tracknr++; @@ -2780,6 +2809,7 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe Mesh *me = ob->data; float v1[3], v2[3], v3[3], vmid[3], fvec[3]; char numstr[32]; /* Stores the measurement display text here */ + size_t numstr_len; const char *conv_float; /* Use a float conversion matching the grid size */ unsigned char col[4] = {0, 0, 0, 255}; /* color of the text to draw */ float area; /* area of the face */ @@ -2857,14 +2887,14 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe } if (unit->system) { - bUnit_AsString(numstr, sizeof(numstr), len_v3v3(v1, v2) * unit->scale_length, 3, - unit->system, B_UNIT_LENGTH, do_split, false); + numstr_len = bUnit_AsString(numstr, sizeof(numstr), len_v3v3(v1, v2) * unit->scale_length, 3, + unit->system, B_UNIT_LENGTH, do_split, false); } else { - BLI_snprintf(numstr, sizeof(numstr), conv_float, len_v3v3(v1, v2)); + numstr_len = BLI_snprintf(numstr, sizeof(numstr), conv_float, len_v3v3(v1, v2)); } - view3d_cached_text_draw_add(vmid, numstr, 0, txt_flag, col); + view3d_cached_text_draw_add(vmid, numstr, numstr_len, 0, txt_flag, col); } } } @@ -2940,9 +2970,9 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe angle = angle_normalized_v3v3(no_a, no_b); - BLI_snprintf(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle)); + numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle)); - view3d_cached_text_draw_add(vmid, numstr, 0, txt_flag, col); + view3d_cached_text_draw_add(vmid, numstr, numstr_len, 0, txt_flag, col); } } } @@ -2959,14 +2989,15 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { \ mul_v3_fl(vmid, 1.0f / (float)n); \ if (unit->system) { \ - bUnit_AsString(numstr, sizeof(numstr), \ - (double)(area * unit->scale_length * unit->scale_length), \ - 3, unit->system, B_UNIT_AREA, do_split, false); \ + numstr_len = bUnit_AsString( \ + numstr, sizeof(numstr), \ + (double)(area * unit->scale_length * unit->scale_length), \ + 3, unit->system, B_UNIT_AREA, do_split, false); \ } \ else { \ - BLI_snprintf(numstr, sizeof(numstr), conv_float, area); \ + numstr_len = BLI_snprintf(numstr, sizeof(numstr), conv_float, area); \ } \ - view3d_cached_text_draw_add(vmid, numstr, 0, txt_flag, col); \ + view3d_cached_text_draw_add(vmid, numstr, numstr_len, 0, txt_flag, col); \ } (void)0 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col); @@ -3082,9 +3113,9 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe angle = angle_v3v3v3(v1, v2, v3); - BLI_snprintf(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle)); + numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle)); interp_v3_v3v3(fvec, vmid, v2_local, 0.8f); - view3d_cached_text_draw_add(fvec, numstr, 0, txt_flag, col); + view3d_cached_text_draw_add(fvec, numstr, numstr_len, 0, txt_flag, col); } } } @@ -3100,6 +3131,7 @@ static void draw_em_indices(BMEditMesh *em) BMVert *v; int i; char numstr[32]; + size_t numstr_len; float pos[3]; unsigned char col[4]; @@ -3112,8 +3144,8 @@ static void draw_em_indices(BMEditMesh *em) UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col); BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(v, BM_ELEM_SELECT)) { - BLI_snprintf(numstr, sizeof(numstr), "%d", i); - view3d_cached_text_draw_add(v->co, numstr, 0, txt_flag, col); + numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", i); + view3d_cached_text_draw_add(v->co, numstr, numstr_len, 0, txt_flag, col); } i++; } @@ -3124,9 +3156,9 @@ static void draw_em_indices(BMEditMesh *em) UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col); BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { - BLI_snprintf(numstr, sizeof(numstr), "%d", i); + numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", i); mid_v3_v3v3(pos, e->v1->co, e->v2->co); - view3d_cached_text_draw_add(pos, numstr, 0, txt_flag, col); + view3d_cached_text_draw_add(pos, numstr, numstr_len, 0, txt_flag, col); } i++; } @@ -3138,8 +3170,8 @@ static void draw_em_indices(BMEditMesh *em) BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { BM_face_calc_center_mean(f, pos); - BLI_snprintf(numstr, sizeof(numstr), "%d", i); - view3d_cached_text_draw_add(pos, numstr, 0, txt_flag, col); + numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", i); + view3d_cached_text_draw_add(pos, numstr, numstr_len, 0, txt_flag, col); } i++; } @@ -4484,6 +4516,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv bool select = (ob->flag & SELECT) != 0, create_cdata = false, need_v = false; GLint polygonmode[2]; char numstr[32]; + size_t numstr_len; unsigned char tcol[4] = {0, 0, 0, 255}; /* 1. */ @@ -4831,28 +4864,32 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv if ((part->draw & PART_DRAW_NUM || part->draw & PART_DRAW_HEALTH) && (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) { + size_t numstr_len; float vec_txt[3]; char *val_pos = numstr; numstr[0] = '\0'; if (part->draw & PART_DRAW_NUM) { if (a < totpart && (part->draw & PART_DRAW_HEALTH) && (part->phystype == PART_PHYS_BOIDS)) { - BLI_snprintf(val_pos, sizeof(numstr), "%d:%.2f", a, pa_health); + numstr_len = BLI_snprintf(val_pos, sizeof(numstr), "%d:%.2f", a, pa_health); } else { - BLI_snprintf(val_pos, sizeof(numstr), "%d", a); + numstr_len = BLI_snprintf(val_pos, sizeof(numstr), "%d", a); } } else { if (a < totpart && (part->draw & PART_DRAW_HEALTH) && (part->phystype == PART_PHYS_BOIDS)) { - BLI_snprintf(val_pos, sizeof(numstr), "%.2f", pa_health); + numstr_len = BLI_snprintf(val_pos, sizeof(numstr), "%.2f", pa_health); } } - /* in path drawing state.co is the end point */ - /* use worldspace beause object matrix is already applied */ - mul_v3_m4v3(vec_txt, ob->imat, state.co); - view3d_cached_text_draw_add(vec_txt, numstr, 10, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, tcol); + if (numstr[0]) { + /* in path drawing state.co is the end point */ + /* use worldspace beause object matrix is already applied */ + mul_v3_m4v3(vec_txt, ob->imat, state.co); + view3d_cached_text_draw_add(vec_txt, numstr, numstr_len, + 10, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, tcol); + } } } } @@ -4944,10 +4981,11 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv for (a = 0, pa = psys->particles; a < totpart; a++, pa++) { float vec_txt[3]; - BLI_snprintf(numstr, sizeof(numstr), "%i", a); + numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%i", a); /* use worldspace beause object matrix is already applied */ mul_v3_m4v3(vec_txt, ob->imat, cache[a]->co); - view3d_cached_text_draw_add(vec_txt, numstr, 10, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, tcol); + view3d_cached_text_draw_add(vec_txt, numstr, numstr_len, + 10, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, tcol); } } } @@ -6630,7 +6668,7 @@ static void draw_rigid_body_pivot(bRigidBodyJointConstraint *data, /* when const color is set wirecolor is NULL - we could get the current color but * with selection and group instancing its not needed to draw the text */ if ((dflag & DRAW_CONSTCOLOR) == 0) { - view3d_cached_text_draw_add(v, axis_str[axis], 0, V3D_CACHE_TEXT_ASCII, ob_wire_col); + view3d_cached_text_draw_add(v, axis_str[axis], 2, 0, V3D_CACHE_TEXT_ASCII, ob_wire_col); } } glLineWidth(1.0f); @@ -7404,7 +7442,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short /* but, we also don't draw names for sets or duplicators */ if (dflag == 0) { const float zero[3] = {0, 0, 0}; - view3d_cached_text_draw_add(zero, ob->id.name + 2, 10, 0, ob_wire_col); + view3d_cached_text_draw_add(zero, ob->id.name + 2, strlen(ob->id.name + 2), 10, 0, ob_wire_col); } } /*if (dtx & OB_DRAWIMAGE) drawDispListwire(&ob->disp);*/ diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 9bc498808ec..3e7c97abaa9 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -140,7 +140,9 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, struc void drawaxes(float size, char drawtype); void view3d_cached_text_draw_begin(void); -void view3d_cached_text_draw_add(const float co[3], const char *str, short xoffs, short flag, const unsigned char col[4]); +void view3d_cached_text_draw_add(const float co[3], + const char *str, const size_t str_len, + short xoffs, short flag, const unsigned char col[4]); void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write, float mat[4][4]); bool check_object_draw_texture(struct Scene *scene, struct View3D *v3d, const char drawtype); -- cgit v1.2.3