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:
authorClément Foucault <foucault.clem@gmail.com>2018-03-30 20:16:14 +0300
committerClément Foucault <foucault.clem@gmail.com>2018-03-30 21:09:26 +0300
commitab9adf9cdc3b2fd91dcade32ea4b4359f4897392 (patch)
tree1f9e12d6a24fa1f74cfc4ab595ac1680d0202433 /source/blender/blenfont
parent8568d38f1b0858a3138b72698babd6ba7b65d6b3 (diff)
BLF: Use Batch API instead of IMM.
This is not a perfect win just yet. It's now calling glBufferSubData for every call (instead of using glMapBufferRange which is almost faster), but with this system we will be able to batch drawcalls together. See next commit.
Diffstat (limited to 'source/blender/blenfont')
-rw-r--r--source/blender/blenfont/BLF_api.h1
-rw-r--r--source/blender/blenfont/intern/blf.c47
-rw-r--r--source/blender/blenfont/intern/blf_font.c126
-rw-r--r--source/blender/blenfont/intern/blf_glyph.c15
-rw-r--r--source/blender/blenfont/intern/blf_internal.h7
-rw-r--r--source/blender/blenfont/intern/blf_internal_types.h18
6 files changed, 150 insertions, 64 deletions
diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h
index cd3a15f1c88..fd0c0362300 100644
--- a/source/blender/blenfont/BLF_api.h
+++ b/source/blender/blenfont/BLF_api.h
@@ -47,6 +47,7 @@ void BLF_exit(void);
void BLF_default_dpi(int dpi);
void BLF_default_set(int fontid);
int BLF_default(void); /* get default font ID so we can pass it to other functions */
+void BLF_batch_reset(void); /* call when changing opengl context. */
void BLF_antialias_set(bool enabled);
bool BLF_antialias_get(void);
diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c
index 30919f1acda..5b51ecbc047 100644
--- a/source/blender/blenfont/intern/blf.c
+++ b/source/blender/blenfont/intern/blf.c
@@ -132,6 +132,11 @@ void BLF_exit(void)
blf_font_exit();
}
+void BLF_batch_reset(void)
+{
+ blf_batching_vao_clear();
+}
+
void BLF_cache_clear(void)
{
FontBLF *font;
@@ -561,8 +566,11 @@ static void blf_draw_gl__start(FontBLF *font)
* in BLF_position (old ui_rasterpos_safe).
*/
- glEnable(GL_BLEND);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ /* always bind the texture for the first glyph */
+ font->tex_bind_state = 0;
+
+ if ((font->flags & (BLF_ROTATION | BLF_MATRIX | BLF_ASPECT)) == 0)
+ return; /* glyphs will be translated individually and batched. */
gpuPushMatrix();
@@ -576,35 +584,12 @@ static void blf_draw_gl__start(FontBLF *font)
if (font->flags & BLF_ROTATION)
gpuRotate2D(RAD2DEG(font->angle));
-
-#ifndef BLF_STANDALONE
- Gwn_VertFormat *format = immVertexFormat();
- unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
- unsigned int texCoord = GWN_vertformat_attr_add(format, "tex", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
- unsigned int color = GWN_vertformat_attr_add(format, "col", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
-
- BLI_assert(pos == BLF_POS_ID);
- BLI_assert(texCoord == BLF_COORD_ID);
- BLI_assert(color == BLF_COLOR_ID);
-
- UNUSED_VARS_NDEBUG(pos, texCoord, color);
-
- immBindBuiltinProgram(GPU_SHADER_TEXT);
-#endif
-
- /* always bind the texture for the first glyph */
- font->tex_bind_state = -1;
}
-static void blf_draw_gl__end(void)
+static void blf_draw_gl__end(FontBLF *font)
{
- gpuPopMatrix();
-
-#ifndef BLF_STANDALONE
- immUnbindProgram();
-#endif
-
- glDisable(GL_BLEND);
+ if ((font->flags & (BLF_ROTATION | BLF_MATRIX | BLF_ASPECT)) != 0)
+ gpuPopMatrix();
}
void BLF_draw_ex(
@@ -623,7 +608,7 @@ void BLF_draw_ex(
else {
blf_font_draw(font, str, len, r_info);
}
- blf_draw_gl__end();
+ blf_draw_gl__end(font);
}
}
void BLF_draw(int fontid, const char *str, size_t len)
@@ -652,7 +637,7 @@ void BLF_draw_ascii_ex(
else {
blf_font_draw_ascii(font, str, len, r_info);
}
- blf_draw_gl__end();
+ blf_draw_gl__end(font);
}
}
void BLF_draw_ascii(int fontid, const char *str, size_t len)
@@ -676,7 +661,7 @@ int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth)
if (font && font->glyph_cache) {
blf_draw_gl__start(font);
columns = blf_font_draw_mono(font, str, len, cwidth);
- blf_draw_gl__end();
+ blf_draw_gl__end(font);
}
return columns;
diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c
index 1f304d208e6..868d8eb775e 100644
--- a/source/blender/blenfont/intern/blf_font.c
+++ b/source/blender/blenfont/intern/blf_font.c
@@ -59,6 +59,8 @@
#include "BLF_api.h"
#include "GPU_immediate.h"
+#include "GPU_matrix.h"
+#include "GPU_batch.h"
#include "blf_internal_types.h"
#include "blf_internal.h"
@@ -69,12 +71,104 @@
# define FT_New_Face FT_New_Face__win32_compat
#endif
+/* Batching buffer for drawing. */
+BatchBLF g_batch;
+
/* freetype2 handle ONLY for this file!. */
static FT_Library ft_lib;
static SpinLock ft_lib_mutex;
+/* -------------------------------------------------------------------- */
+/** \name Glyph Batching
+ * \{ */
+/**
+ * Drawcalls are precious! make them count!
+ * Since most of the Text elems are not covered by other UI elements, we can
+ * group some strings together and render them in one drawcall. This behaviour
+ * is on demand only, between BLF_batch_start() and BLF_batch_end().
+ **/
+static void blf_batching_init(void)
+{
+ Gwn_VertFormat format = {0};
+ g_batch.pos_loc = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ g_batch.tex_loc = GWN_vertformat_attr_add(&format, "tex", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ g_batch.col_loc = GWN_vertformat_attr_add(&format, "col", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+
+ g_batch.verts = GWN_vertbuf_create_with_format_ex(&format, GWN_USAGE_STREAM);
+ GWN_vertbuf_data_alloc(g_batch.verts, BLF_BATCHING_SIZE);
+
+ g_batch.batch = GWN_batch_create_ex(GWN_PRIM_POINTS, g_batch.verts, NULL, GWN_BATCH_OWNS_VBO);
+}
+
+static void blf_batching_exit(void)
+{
+ GWN_BATCH_DISCARD_SAFE(g_batch.batch);
+}
+
+void blf_batching_vao_clear(void)
+{
+ if (g_batch.batch) {
+ gwn_batch_vao_cache_clear(g_batch.batch);
+ }
+}
+
+void blf_batching_start(FontBLF *font)
+{
+ if (g_batch.batch == NULL) {
+ blf_batching_init();
+ }
+
+ zero_v2(g_batch.ofs);
+ if ((font->flags & (BLF_ROTATION | BLF_MATRIX | BLF_ASPECT)) == 0) {
+ copy_v2_v2(g_batch.ofs, font->pos);
+ }
+
+ /* restart to 1st vertex data pointers */
+ GWN_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.pos_loc, &g_batch.pos_step);
+ GWN_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.tex_loc, &g_batch.tex_step);
+ GWN_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.col_loc, &g_batch.col_step);
+ g_batch.glyph_ct = 0;
+ g_batch.font = font;
+}
+
+void blf_batching_draw(void)
+{
+ if (g_batch.glyph_ct == 0)
+ return;
+
+ glEnable(GL_BLEND);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
+ BLI_assert(g_batch.font->tex_bind_state != 0); /* must still be valid */
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, g_batch.font->tex_bind_state);
+
+ GWN_vertbuf_vertex_count_set(g_batch.verts, g_batch.glyph_ct);
+ GWN_vertbuf_use(g_batch.verts); /* send data */
+
+ GWN_batch_program_set_builtin(g_batch.batch, GPU_SHADER_TEXT);
+ GWN_batch_uniform_1i(g_batch.batch, "glyph", 0);
+ GWN_batch_draw(g_batch.batch);
+
+ glDisable(GL_BLEND);
+
+ g_batch.glyph_ct = 0;
+}
+
+static void blf_batching_end(void)
+{
+ if (!g_batch.enabled) {
+ blf_batching_draw();
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
int blf_font_init(void)
{
+ memset(&g_batch, 0, sizeof(g_batch));
BLI_spin_init(&ft_lib_mutex);
return FT_Init_FreeType(&ft_lib);
}
@@ -83,6 +177,7 @@ void blf_font_exit(void)
{
FT_Done_FreeType(ft_lib);
BLI_spin_end(&ft_lib_mutex);
+ blf_batching_exit();
}
void blf_font_size(FontBLF *font, unsigned int size, unsigned int dpi)
@@ -174,24 +269,6 @@ static void blf_font_ensure_ascii_table(FontBLF *font)
} \
} (void)0
-static unsigned int verts_needed(const FontBLF *font, const char *str, size_t len)
-{
- size_t str_len = (len > 50) ? strlen(str) : INT_MAX; /* Arbitrary. */
- unsigned int length = (unsigned int)MIN2(str_len, len);
- unsigned int quad_ct = 1;
-
- if (font->flags & BLF_SHADOW) {
- if (font->shadow == 0)
- quad_ct += 1;
- if (font->shadow <= 4)
- quad_ct += 9; /* 3x3 kernel */
- else
- quad_ct += 25; /* 5x5 kernel */
- }
-
- return length * quad_ct; /* Only one vert per quad */
-}
-
static void blf_font_draw_ex(
FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info,
int pen_y)
@@ -212,8 +289,7 @@ static void blf_font_draw_ex(
blf_font_ensure_ascii_table(font);
- immBeginAtMost(GWN_PRIM_POINTS, verts_needed(font, str, len));
- /* at most because some glyphs might be clipped & not drawn */
+ blf_batching_start(font);
while ((i < len) && str[i]) {
BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
@@ -232,7 +308,7 @@ static void blf_font_draw_ex(
g_prev = g;
}
- immEnd();
+ blf_batching_end();
if (r_info) {
r_info->lines = 1;
@@ -259,7 +335,7 @@ static void blf_font_draw_ascii_ex(
blf_font_ensure_ascii_table(font);
- immBeginAtMost(GWN_PRIM_POINTS, verts_needed(font, str, len));
+ blf_batching_start(font);
while ((c = *(str++)) && len--) {
BLI_assert(c < 128);
@@ -275,7 +351,7 @@ static void blf_font_draw_ascii_ex(
g_prev = g;
}
- immEnd();
+ blf_batching_end();
if (r_info) {
r_info->lines = 1;
@@ -299,7 +375,7 @@ int blf_font_draw_mono(FontBLF *font, const char *str, size_t len, int cwidth)
blf_font_ensure_ascii_table(font);
- immBeginAtMost(GWN_PRIM_POINTS, verts_needed(font, str, len));
+ blf_batching_start(font);
while ((i < len) && str[i]) {
BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
@@ -320,7 +396,7 @@ int blf_font_draw_mono(FontBLF *font, const char *str, size_t len, int cwidth)
pen_x += cwidth * col;
}
- immEnd();
+ blf_batching_end();
return columns;
}
diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c
index 5e1debf1501..b91eceac817 100644
--- a/source/blender/blenfont/intern/blf_glyph.c
+++ b/source/blender/blenfont/intern/blf_glyph.c
@@ -63,6 +63,7 @@
#include "blf_internal.h"
#include "BLI_strict_flags.h"
+#include "BLI_math_vector.h"
GlyphCacheBLF *blf_glyph_cache_find(FontBLF *font, unsigned int size, unsigned int dpi)
{
@@ -316,13 +317,19 @@ void blf_glyph_free(GlyphBLF *g)
MEM_freeN(g);
}
-static void blf_texture_draw(const unsigned char color[4], float uv[2][2], float dx, float y1, float dx1, float y2)
+static void blf_texture_draw(const unsigned char color[4], float uv[2][2], float x1, float y1, float x2, float y2)
{
+ if (g_batch.glyph_ct == BLF_BATCHING_SIZE) {
+ blf_batching_draw();
+ blf_batching_start(g_batch.font);
+ }
+ g_batch.glyph_ct++;
/* Only one vertex per glyph, geometry shader expand it into a quad. */
/* TODO Get rid of Geom Shader because it's not optimal AT ALL for the GPU */
- immAttrib4ubv(BLF_COLOR_ID, color);
- immAttrib4fv(BLF_COORD_ID, (float *)uv);
- immVertex4f(BLF_POS_ID, dx, y1, dx1, y2);
+ copy_v4_fl4(GWN_vertbuf_raw_step(&g_batch.pos_step), x1 + g_batch.ofs[0], y1 + g_batch.ofs[1],
+ x2 + g_batch.ofs[0], y2 + g_batch.ofs[1]);
+ copy_v4_v4(GWN_vertbuf_raw_step(&g_batch.tex_step), (float *)uv);
+ copy_v4_v4_uchar(GWN_vertbuf_raw_step(&g_batch.col_step), color);
}
static void blf_texture5_draw(const unsigned char color_in[4], float uv[2][2], float x1, float y1, float x2, float y2)
diff --git a/source/blender/blenfont/intern/blf_internal.h b/source/blender/blenfont/intern/blf_internal.h
index ba17e050399..c9ea8c3323b 100644
--- a/source/blender/blenfont/intern/blf_internal.h
+++ b/source/blender/blenfont/intern/blf_internal.h
@@ -37,10 +37,9 @@ struct GlyphBLF;
struct GlyphCacheBLF;
struct rctf;
-/* vertex attribute IDs (fixed IDs so we don't have to pass them around) */
-#define BLF_POS_ID 0
-#define BLF_COORD_ID 1
-#define BLF_COLOR_ID 2
+void blf_batching_vao_clear(void);
+void blf_batching_start(struct FontBLF *font);
+void blf_batching_draw(void);
unsigned int blf_next_p2(unsigned int x);
unsigned int blf_hash(unsigned int val);
diff --git a/source/blender/blenfont/intern/blf_internal_types.h b/source/blender/blenfont/intern/blf_internal_types.h
index 9164a02b2cc..360aae47dd0 100644
--- a/source/blender/blenfont/intern/blf_internal_types.h
+++ b/source/blender/blenfont/intern/blf_internal_types.h
@@ -31,6 +31,24 @@
#ifndef __BLF_INTERNAL_TYPES_H__
#define __BLF_INTERNAL_TYPES_H__
+#include "../../../intern/gawain/gawain/gwn_vertex_buffer.h"
+
+#define BLF_BATCHING_SIZE 2048 /* in glyph */
+
+typedef struct BatchBLF{
+ struct FontBLF *font; /* can only batch glyph from the same font */
+ struct Gwn_Batch *batch;
+ struct Gwn_VertBuf *verts;
+ struct Gwn_VertBufRaw pos_step, tex_step, col_step;
+ unsigned int pos_loc, tex_loc, col_loc;
+ unsigned int glyph_ct;
+ float ofs[2]; /* copy of font->pos */
+ float mat[4][4]; /* to catch bad usage */
+ bool enabled;
+} BatchBLF;
+
+extern BatchBLF g_batch;
+
typedef struct GlyphCacheBLF {
struct GlyphCacheBLF *next;
struct GlyphCacheBLF *prev;