This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/draw/intern/draw_manager_text.c
Campbell Barton a4540116ba DRW: use memiter for on screen text allocation
Avoid allocation for each string,
improves redraw speed for text heavy views.

A contrived test showed FPS ~18.5% speedup but this doesn't represent
typical usage.
2019-03-06 02:42:53 +11:00

181 lines
4.2 KiB
C

/*
* 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.
*
* Copyright 2016, Blender Foundation.
*/
/** \file
* \ingroup draw
*/
#include "MEM_guardedalloc.h"
#include "BLI_memiter.h"
#include "BLI_math.h"
#include "GPU_matrix.h"
#include "ED_screen.h"
#include "ED_view3d.h"
#include "UI_interface.h"
#include "WM_api.h"
#include "BLF_api.h"
#include "draw_manager_text.h"
typedef struct ViewCachedString {
float vec[3];
union {
uchar ub[4];
int pack;
} col;
short sco[2];
short xoffs, yoffs;
short flag;
int str_len;
/* str is allocated past the end */
char str[0];
} ViewCachedString;
typedef struct DRWTextStore {
BLI_memiter *cache_strings;
} DRWTextStore;
DRWTextStore *DRW_text_cache_create(void)
{
DRWTextStore *dt = MEM_callocN(sizeof(*dt), __func__);
dt->cache_strings = BLI_memiter_create(1 << 14); /* 16kb */
return dt;
}
void DRW_text_cache_destroy(struct DRWTextStore *dt)
{
BLI_memiter_destroy(dt->cache_strings);
MEM_freeN(dt);
}
void DRW_text_cache_add(
DRWTextStore *dt,
const float co[3],
const char *str, const int str_len,
short xoffs, short yoffs, short flag,
const uchar col[4])
{
int alloc_len;
ViewCachedString *vos;
if (flag & DRW_TEXT_CACHE_STRING_PTR) {
BLI_assert(str_len == strlen(str));
alloc_len = sizeof(void *);
}
else {
alloc_len = str_len + 1;
}
vos = BLI_memiter_alloc(dt->cache_strings, sizeof(ViewCachedString) + alloc_len);
copy_v3_v3(vos->vec, co);
copy_v4_v4_uchar(vos->col.ub, col);
vos->xoffs = xoffs;
vos->yoffs = yoffs;
vos->flag = flag;
vos->str_len = str_len;
/* allocate past the end */
if (flag & DRW_TEXT_CACHE_STRING_PTR) {
memcpy(vos->str, &str, alloc_len);
}
else {
memcpy(vos->str, str, alloc_len);
}
}
void DRW_text_cache_draw(DRWTextStore *dt, ARegion *ar)
{
RegionView3D *rv3d = ar->regiondata;
ViewCachedString *vos;
int tot = 0;
/* project first and test */
BLI_memiter_handle it;
BLI_memiter_iter_init(dt->cache_strings, &it);
while ((vos = BLI_memiter_iter_step(&it))) {
if (ED_view3d_project_short_ex(
ar,
(vos->flag & DRW_TEXT_CACHE_GLOBALSPACE) ? rv3d->persmat : rv3d->persmatob,
(vos->flag & DRW_TEXT_CACHE_LOCALCLIP) != 0,
vos->vec, vos->sco,
V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
{
tot++;
}
else {
vos->sco[0] = IS_CLIPPED;
}
}
if (tot) {
int col_pack_prev = 0;
if (rv3d->rflag & RV3D_CLIPPING) {
ED_view3d_clipping_disable();
}
float original_proj[4][4];
GPU_matrix_projection_get(original_proj);
wmOrtho2_region_pixelspace(ar);
GPU_matrix_push();
GPU_matrix_identity_set();
const int font_id = BLF_default();
const uiStyle *style = UI_style_get();
BLF_size(font_id, style->widget.points * U.pixelsize, U.dpi);
BLI_memiter_iter_init(dt->cache_strings, &it);
while ((vos = BLI_memiter_iter_step(&it))) {
if (vos->sco[0] != IS_CLIPPED) {
if (col_pack_prev != vos->col.pack) {
BLF_color4ubv(font_id, vos->col.ub);
col_pack_prev = vos->col.pack;
}
BLF_position(
font_id,
(float)(vos->sco[0] + vos->xoffs), (float)(vos->sco[1] + vos->yoffs), 2.0f);
((vos->flag & DRW_TEXT_CACHE_ASCII) ?
BLF_draw_ascii :
BLF_draw
)(font_id,
(vos->flag & DRW_TEXT_CACHE_STRING_PTR) ? *((const char **)vos->str) : vos->str,
vos->str_len);
}
}
GPU_matrix_pop();
GPU_matrix_projection_set(original_proj);
if (rv3d->rflag & RV3D_CLIPPING) {
ED_view3d_clipping_enable();
}
}
}