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:
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenfont/intern/blf.c3
-rw-r--r--source/blender/blenfont/intern/blf_font.c53
-rw-r--r--source/blender/blenfont/intern/blf_glyph.c230
-rw-r--r--source/blender/blenfont/intern/blf_internal_types.h47
-rw-r--r--source/blender/gpu/shaders/gpu_shader_text_frag.glsl119
-rw-r--r--source/blender/gpu/shaders/gpu_shader_text_vert.glsl21
6 files changed, 242 insertions, 231 deletions
diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c
index 2b592c9e550..725c4c0712d 100644
--- a/source/blender/blenfont/intern/blf.c
+++ b/source/blender/blenfont/intern/blf.c
@@ -584,9 +584,6 @@ static void blf_draw_gl__start(FontBLF *font)
* in BLF_position (old ui_rasterpos_safe).
*/
- /* 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. */
}
diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c
index 25ea0770f8b..f0afe184233 100644
--- a/source/blender/blenfont/intern/blf_font.c
+++ b/source/blender/blenfont/intern/blf_font.c
@@ -84,16 +84,19 @@ static void blf_batch_draw_init(void)
{
GPUVertFormat format = {0};
g_batch.pos_loc = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- g_batch.tex_loc = GPU_vertformat_attr_add(&format, "tex", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
g_batch.col_loc = GPU_vertformat_attr_add(
&format, "col", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ g_batch.offset_loc = GPU_vertformat_attr_add(&format, "offset", GPU_COMP_I32, 1, GPU_FETCH_INT);
+ g_batch.glyph_size_loc = GPU_vertformat_attr_add(
+ &format, "glyph_size", GPU_COMP_I32, 2, GPU_FETCH_INT);
g_batch.verts = GPU_vertbuf_create_with_format_ex(&format, GPU_USAGE_STREAM);
GPU_vertbuf_data_alloc(g_batch.verts, BLF_BATCH_DRAW_LEN_MAX);
GPU_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.pos_loc, &g_batch.pos_step);
- GPU_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.tex_loc, &g_batch.tex_step);
GPU_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.col_loc, &g_batch.col_step);
+ GPU_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.offset_loc, &g_batch.offset_step);
+ GPU_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.glyph_size_loc, &g_batch.glyph_size_step);
g_batch.glyph_len = 0;
/* A dummy vbo containing 4 points, attribs are not used. */
@@ -177,6 +180,46 @@ void blf_batch_draw_begin(FontBLF *font)
}
}
+static GPUTexture *blf_batch_cache_texture_load(void)
+{
+ GlyphCacheBLF *gc = g_batch.glyph_cache;
+ BLI_assert(gc);
+ BLI_assert(gc->bitmap_len > 0);
+
+ if (gc->bitmap_len > gc->bitmap_len_landed) {
+ const int tex_width = GPU_texture_width(gc->texture);
+
+ int bitmap_len_landed = gc->bitmap_len_landed;
+ int remain = gc->bitmap_len - bitmap_len_landed;
+ int offset_x = bitmap_len_landed % tex_width;
+ int offset_y = bitmap_len_landed / tex_width;
+
+ /* TODO(germano): Update more than one row in a single call. */
+ while (remain) {
+ int remain_row = tex_width - offset_x;
+ int width = remain > remain_row ? remain_row : remain;
+ GPU_texture_update_sub(gc->texture,
+ GPU_DATA_UNSIGNED_BYTE,
+ &gc->bitmap_result[bitmap_len_landed],
+ offset_x,
+ offset_y,
+ 0,
+ width,
+ 1,
+ 0);
+
+ bitmap_len_landed += width;
+ remain -= width;
+ offset_x = 0;
+ offset_y += 1;
+ }
+
+ gc->bitmap_len_landed = bitmap_len_landed;
+ }
+
+ return gc->texture;
+}
+
void blf_batch_draw(void)
{
if (g_batch.glyph_len == 0) {
@@ -190,7 +233,8 @@ void blf_batch_draw(void)
/* We need to flush widget base first to ensure correct ordering. */
UI_widgetbase_draw_cache_flush();
- GPU_texture_bind(g_batch.tex_bind_state, 0);
+ GPUTexture *texture = blf_batch_cache_texture_load();
+ GPU_texture_bind(texture, 0);
GPU_vertbuf_data_len_set(g_batch.verts, g_batch.glyph_len);
GPU_vertbuf_use(g_batch.verts); /* send data */
@@ -202,8 +246,9 @@ void blf_batch_draw(void)
/* restart to 1st vertex data pointers */
GPU_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.pos_loc, &g_batch.pos_step);
- GPU_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.tex_loc, &g_batch.tex_step);
GPU_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.col_loc, &g_batch.col_step);
+ GPU_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.offset_loc, &g_batch.offset_step);
+ GPU_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.glyph_size_loc, &g_batch.glyph_size_step);
g_batch.glyph_len = 0;
}
diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c
index 80d43a49e77..8e88bda37a5 100644
--- a/source/blender/blenfont/intern/blf_glyph.c
+++ b/source/blender/blenfont/intern/blf_glyph.c
@@ -143,13 +143,6 @@ GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font)
memset(gc->glyph_ascii_table, 0, sizeof(gc->glyph_ascii_table));
memset(gc->bucket, 0, sizeof(gc->bucket));
- gc->textures = (GPUTexture **)MEM_callocN(sizeof(GPUTexture *) * 256, __func__);
- gc->textures_len = 256;
- gc->texture_current = BLF_TEXTURE_UNSET;
- gc->offset_x = 3; /* enough padding for blur */
- gc->offset_y = 3; /* enough padding for blur */
- gc->pad = 6;
-
gc->glyphs_len_max = (int)font->face->num_glyphs;
gc->glyphs_len_free = (int)font->face->num_glyphs;
gc->ascender = ((float)font->face->size->metrics.ascender) / 64.0f;
@@ -173,9 +166,6 @@ GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font)
CLAMP_MIN(gc->glyph_width_max, 1);
CLAMP_MIN(gc->glyph_height_max, 1);
- gc->p2_width = 0;
- gc->p2_height = 0;
-
BLI_addhead(&font->cache, gc);
return gc;
}
@@ -229,52 +219,13 @@ void blf_glyph_cache_free(GlyphCacheBLF *gc)
blf_glyph_free(g);
}
}
- for (i = 0; i < gc->textures_len; i++) {
- if (gc->textures[i]) {
- GPU_texture_free(gc->textures[i]);
- }
+ if (gc->texture) {
+ GPU_texture_free(gc->texture);
}
- MEM_freeN(gc->textures);
- MEM_freeN(gc);
-}
-
-static void blf_glyph_cache_texture(FontBLF *font, GlyphCacheBLF *gc)
-{
- int i;
- char error[256];
-
- /* move the index. */
- gc->texture_current++;
-
- if (UNLIKELY(gc->texture_current >= gc->textures_len)) {
- gc->textures_len *= 2;
- gc->textures = MEM_recallocN((void *)gc->textures, sizeof(GPUTexture *) * gc->textures_len);
- }
-
- gc->p2_width = (int)blf_next_p2(
- (unsigned int)((gc->glyphs_len_free * gc->glyph_width_max) + (gc->pad * 2)));
- if (gc->p2_width > font->tex_size_max) {
- gc->p2_width = font->tex_size_max;
+ if (gc->bitmap_result) {
+ MEM_freeN(gc->bitmap_result);
}
-
- i = (int)((gc->p2_width - (gc->pad * 2)) / gc->glyph_width_max);
- gc->p2_height = (int)blf_next_p2(
- (unsigned int)(((gc->glyphs_len_max / i) + 1) * gc->glyph_height_max + (gc->pad * 2)));
-
- if (gc->p2_height > font->tex_size_max) {
- gc->p2_height = font->tex_size_max;
- }
-
- GPUTexture *tex = GPU_texture_create_nD(
- gc->p2_width, gc->p2_height, 0, 2, NULL, GPU_R8, GPU_DATA_UNSIGNED_BYTE, 0, false, error);
-
- GPU_texture_bind(tex, 0);
- GPU_texture_wrap_mode(tex, false);
- GPU_texture_filters(tex, GPU_NEAREST, GPU_LINEAR);
- GPU_texture_clear(tex, GPU_DATA_UNSIGNED_BYTE, NULL);
- GPU_texture_unbind(tex);
-
- gc->textures[gc->texture_current] = tex;
+ MEM_freeN(gc);
}
GlyphBLF *blf_glyph_search(GlyphCacheBLF *gc, unsigned int c)
@@ -377,8 +328,6 @@ GlyphBLF *blf_glyph_add(FontBLF *font, GlyphCacheBLF *gc, unsigned int index, un
g = (GlyphBLF *)MEM_callocN(sizeof(GlyphBLF), "blf_glyph_add");
g->c = c;
g->idx = (FT_UInt)index;
- g->offset_x = -1;
- g->offset_y = -1;
bitmap = slot->bitmap;
g->width = (int)bitmap.width;
g->height = (int)bitmap.rows;
@@ -418,17 +367,19 @@ GlyphBLF *blf_glyph_add(FontBLF *font, GlyphCacheBLF *gc, unsigned int index, un
void blf_glyph_free(GlyphBLF *g)
{
- /* don't need free the texture, the GlyphCache already
- * have a list of all the texture and free it.
- */
if (g->bitmap) {
MEM_freeN(g->bitmap);
}
MEM_freeN(g);
}
-static void blf_texture_draw(
- const unsigned char color[4], const float uv[2][2], float x1, float y1, float x2, float y2)
+static void blf_texture_draw(const unsigned char color[4],
+ const int glyph_size[2],
+ const int offset,
+ float x1,
+ float y1,
+ float x2,
+ float y2)
{
/* 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 */
@@ -437,8 +388,10 @@ static void blf_texture_draw(
y1 + g_batch.ofs[1],
x2 + g_batch.ofs[0],
y2 + g_batch.ofs[1]);
- copy_v4_v4(GPU_vertbuf_raw_step(&g_batch.tex_step), (float *)uv);
copy_v4_v4_uchar(GPU_vertbuf_raw_step(&g_batch.col_step), color);
+ copy_v2_v2_int(GPU_vertbuf_raw_step(&g_batch.glyph_size_step), glyph_size);
+ *((int *)GPU_vertbuf_raw_step(&g_batch.offset_step)) = offset;
+
g_batch.glyph_len++;
/* Flush cache if it's full. */
if (g_batch.glyph_len == BLF_BATCH_DRAW_LEN_MAX) {
@@ -447,45 +400,35 @@ static void blf_texture_draw(
}
static void blf_texture5_draw(const unsigned char color_in[4],
- int tex_w,
- int tex_h,
- const float uv[2][2],
+ const int glyph_size[2],
+ const int offset,
float x1,
float y1,
float x2,
float y2)
{
- float ofs[2] = {2 / (float)tex_w, 2 / (float)tex_h};
- float uv_flag[2][2];
- copy_v4_v4((float *)uv_flag, (float *)uv);
+ int glyph_size_flag[2];
/* flag the x and y component signs for 5x5 blurring */
- uv_flag[0][0] = -(uv_flag[0][0] - ofs[0]);
- uv_flag[0][1] = -(uv_flag[0][1] - ofs[1]);
- uv_flag[1][0] = -(uv_flag[1][0] + ofs[0]);
- uv_flag[1][1] = -(uv_flag[1][1] + ofs[1]);
+ glyph_size_flag[0] = -glyph_size[0];
+ glyph_size_flag[1] = -glyph_size[1];
- blf_texture_draw(color_in, uv_flag, x1 - 2, y1 + 2, x2 + 2, y2 - 2);
+ blf_texture_draw(color_in, glyph_size_flag, offset, x1, y1, x2, y2);
}
static void blf_texture3_draw(const unsigned char color_in[4],
- int tex_w,
- int tex_h,
- const float uv[2][2],
+ const int glyph_size[2],
+ const int offset,
float x1,
float y1,
float x2,
float y2)
{
- float ofs[2] = {1 / (float)tex_w, 1 / (float)tex_h};
- float uv_flag[2][2];
- copy_v4_v4((float *)uv_flag, (float *)uv);
+ int glyph_size_flag[2];
/* flag the x component sign for 3x3 blurring */
- uv_flag[0][0] = -(uv_flag[0][0] - ofs[0]);
- uv_flag[0][1] = (uv_flag[0][1] - ofs[1]);
- uv_flag[1][0] = -(uv_flag[1][0] + ofs[0]);
- uv_flag[1][1] = (uv_flag[1][1] + ofs[1]);
+ glyph_size_flag[0] = -glyph_size[0];
+ glyph_size_flag[1] = glyph_size[1];
- blf_texture_draw(color_in, uv_flag, x1 - 1, y1 + 1, x2 + 1, y2 - 1);
+ blf_texture_draw(color_in, glyph_size_flag, offset, x1, y1, x2, y2);
}
static void blf_glyph_calc_rect(rctf *rect, GlyphBLF *g, float x, float y)
@@ -518,63 +461,38 @@ void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, fl
return;
}
- if (g->build_tex == 0) {
+ if (!g->cached) {
if (font->tex_size_max == -1) {
font->tex_size_max = GPU_max_texture_size();
}
- if (gc->texture_current == BLF_TEXTURE_UNSET) {
- blf_glyph_cache_texture(font, gc);
- gc->offset_x = gc->pad;
- gc->offset_y = 3; /* enough padding for blur */
- }
+ g->offset = gc->bitmap_len;
- if (gc->offset_x > (gc->p2_width - gc->glyph_width_max)) {
- gc->offset_x = gc->pad;
- gc->offset_y += gc->glyph_height_max;
+ int buff_size = g->width * g->height;
+ int bitmap_len = gc->bitmap_len + buff_size;
- if (gc->offset_y > (gc->p2_height - gc->glyph_height_max)) {
- gc->offset_y = 3; /* enough padding for blur */
- blf_glyph_cache_texture(font, gc);
- }
- }
+ if (bitmap_len > gc->bitmap_len_alloc) {
+ int w = font->tex_size_max;
+ int h = bitmap_len / w + 1;
- g->tex = gc->textures[gc->texture_current];
- g->offset_x = gc->offset_x;
- g->offset_y = gc->offset_y;
+ gc->bitmap_len_alloc = w * h;
+ gc->bitmap_result = MEM_reallocN(gc->bitmap_result, (size_t)gc->bitmap_len_alloc);
- /* prevent glTexSubImage2D from failing if the character
- * asks for pixels out of bounds, this tends only to happen
- * with very small sizes (5px high or less) */
- if (UNLIKELY((g->offset_x + g->width) > gc->p2_width)) {
- g->width -= (g->offset_x + g->width) - gc->p2_width;
- BLI_assert(g->width > 0);
- }
- if (UNLIKELY((g->offset_y + g->height) > gc->p2_height)) {
- g->height -= (g->offset_y + g->height) - gc->p2_height;
- BLI_assert(g->height > 0);
- }
-
- GPU_texture_update_sub(g->tex,
- GPU_DATA_UNSIGNED_BYTE,
- g->bitmap,
- g->offset_x,
- g->offset_y,
- 0,
- g->width,
- g->height,
- 0);
+ /* Keep in sync with the texture. */
+ if (gc->texture) {
+ GPU_texture_free(gc->texture);
+ }
+ gc->texture = GPU_texture_create_nD(
+ w, h, 0, 1, NULL, GPU_R8, GPU_DATA_UNSIGNED_BYTE, 0, false, NULL);
- g->uv[0][0] = ((float)g->offset_x) / ((float)gc->p2_width);
- g->uv[0][1] = ((float)g->offset_y) / ((float)gc->p2_height);
- g->uv[1][0] = ((float)(g->offset_x + g->width)) / ((float)gc->p2_width);
- g->uv[1][1] = ((float)(g->offset_y + g->height)) / ((float)gc->p2_height);
+ gc->bitmap_len_landed = 0;
+ }
- /* update the x offset for the next glyph. */
- gc->offset_x += (int)BLI_rctf_size_x(&g->box) + gc->pad;
+ memcpy(&gc->bitmap_result[gc->bitmap_len], g->bitmap, (size_t)buff_size);
+ gc->bitmap_len = bitmap_len;
gc->glyphs_len_free--;
- g->build_tex = 1;
+ g->cached = true;
}
if (font->flags & BLF_CLIPPING) {
@@ -587,27 +505,26 @@ void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, fl
}
}
- if (font->tex_bind_state != g->tex) {
- blf_batch_draw();
- font->tex_bind_state = g->tex;
- GPU_texture_bind(font->tex_bind_state, 0);
- }
-
- g_batch.tex_bind_state = g->tex;
+ g_batch.glyph_cache = gc;
+ BLI_assert(g->offset < gc->bitmap_len);
if (font->flags & BLF_SHADOW) {
rctf rect_ofs;
blf_glyph_calc_rect_shadow(&rect_ofs, g, x, y, font);
if (font->shadow == 0) {
- blf_texture_draw(
- font->shadow_color, g->uv, rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax);
+ blf_texture_draw(font->shadow_color,
+ (int[2]){g->width, g->height},
+ g->offset,
+ rect_ofs.xmin,
+ rect_ofs.ymin,
+ rect_ofs.xmax,
+ rect_ofs.ymax);
}
else if (font->shadow <= 4) {
blf_texture3_draw(font->shadow_color,
- gc->p2_width,
- gc->p2_height,
- g->uv,
+ (int[2]){g->width, g->height},
+ g->offset,
rect_ofs.xmin,
rect_ofs.ymin,
rect_ofs.xmax,
@@ -615,9 +532,8 @@ void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, fl
}
else {
blf_texture5_draw(font->shadow_color,
- gc->p2_width,
- gc->p2_height,
- g->uv,
+ (int[2]){g->width, g->height},
+ g->offset,
rect_ofs.xmin,
rect_ofs.ymin,
rect_ofs.xmax,
@@ -632,9 +548,8 @@ void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, fl
switch (font->blur) {
case 3:
blf_texture3_draw(font->color,
- gc->p2_width,
- gc->p2_height,
- g->uv,
+ (int[2]){g->width, g->height},
+ g->offset,
rect.xmin,
rect.ymin,
rect.xmax,
@@ -642,18 +557,29 @@ void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, fl
break;
case 5:
blf_texture5_draw(font->color,
- gc->p2_width,
- gc->p2_height,
- g->uv,
+ (int[2]){g->width, g->height},
+ g->offset,
rect.xmin,
rect.ymin,
rect.xmax,
rect.ymax);
break;
default:
- blf_texture_draw(font->color, g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ blf_texture_draw(font->color,
+ (int[2]){g->width, g->height},
+ g->offset,
+ rect.xmin,
+ rect.ymin,
+ rect.xmax,
+ rect.ymax);
}
#else
- blf_texture_draw(font->color, g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ blf_texture_draw(font->color,
+ (int[2]){g->width, g->height},
+ g->offset,
+ rect.xmin,
+ rect.ymin,
+ rect.xmax,
+ rect.ymax);
#endif
}
diff --git a/source/blender/blenfont/intern/blf_internal_types.h b/source/blender/blenfont/intern/blf_internal_types.h
index 45086de0f61..bb1697d7860 100644
--- a/source/blender/blenfont/intern/blf_internal_types.h
+++ b/source/blender/blenfont/intern/blf_internal_types.h
@@ -33,13 +33,13 @@ typedef struct BatchBLF {
struct FontBLF *font; /* can only batch glyph from the same font */
struct GPUBatch *batch;
struct GPUVertBuf *verts;
- struct GPUVertBufRaw pos_step, tex_step, col_step;
- unsigned int pos_loc, tex_loc, col_loc;
+ struct GPUVertBufRaw pos_step, col_step, offset_step, glyph_size_step;
+ unsigned int pos_loc, col_loc, offset_loc, glyph_size_loc;
unsigned int glyph_len;
float ofs[2]; /* copy of font->pos */
float mat[4][4]; /* previous call modelmatrix. */
bool enabled, active, simple_shader;
- GPUTexture *tex_bind_state;
+ struct GlyphCacheBLF *glyph_cache;
} BatchBLF;
extern BatchBLF g_batch;
@@ -72,30 +72,16 @@ typedef struct GlyphCacheBLF {
struct GlyphBLF *glyph_ascii_table[256];
/* texture array, to draw the glyphs. */
- GPUTexture **textures;
-
- /* size of the array. */
- unsigned int textures_len;
-
- /* and the last texture, aka. the current texture. */
- unsigned int texture_current;
-
- /* We draw every glyph in a big texture, so this is the
- * current position inside the texture. */
- int offset_x;
- int offset_y;
-
- /* and the space from one to other. */
- int pad;
+ GPUTexture *texture;
+ char *bitmap_result;
+ int bitmap_len;
+ int bitmap_len_landed;
+ int bitmap_len_alloc;
/* and the bigger glyph in the font. */
int glyph_width_max;
int glyph_height_max;
- /* next two integer power of two, to build the texture. */
- int p2_width;
- int p2_height;
-
/* number of glyphs in the font. */
int glyphs_len_max;
@@ -125,12 +111,8 @@ typedef struct GlyphBLF {
/* avoid conversion to int while drawing */
int advance_i;
- /* texture id where this glyph is store. */
- GPUTexture *tex;
-
/* position inside the texture where this glyph is store. */
- int offset_x;
- int offset_y;
+ int offset;
/* Bitmap data, from freetype. Take care that this
* can be NULL.
@@ -142,9 +124,6 @@ typedef struct GlyphBLF {
int height;
int pitch;
- /* uv coords. */
- float uv[2][2];
-
/* X and Y bearing of the glyph.
* The X bearing is from the origin to the glyph left bbox edge.
* The Y bearing is from the baseline to the top of the glyph edge.
@@ -152,8 +131,7 @@ typedef struct GlyphBLF {
float pos_x;
float pos_y;
- /* with value of zero mean that we need build the texture. */
- char build_tex;
+ bool cached;
} GlyphBLF;
typedef struct FontBufInfoBLF {
@@ -239,9 +217,6 @@ typedef struct FontBLF {
/* max texture size. */
int tex_size_max;
- /* cache current OpenGL texture to save calls into the API */
- GPUTexture *tex_bind_state;
-
/* font options. */
int flags;
@@ -286,6 +261,4 @@ typedef struct DirBLF {
char *path;
} DirBLF;
-#define BLF_TEXTURE_UNSET ((unsigned int)-1)
-
#endif /* __BLF_INTERNAL_TYPES_H__ */
diff --git a/source/blender/gpu/shaders/gpu_shader_text_frag.glsl b/source/blender/gpu/shaders/gpu_shader_text_frag.glsl
index f9f195c31d6..554596fa9ae 100644
--- a/source/blender/gpu/shaders/gpu_shader_text_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_text_frag.glsl
@@ -1,9 +1,13 @@
flat in vec4 color_flat;
noperspective in vec2 texCoord_interp;
+flat in int glyph_offset;
+flat in ivec2 glyph_dim;
+flat in int interp_size;
+
out vec4 fragColor;
-uniform sampler2D glyph;
+uniform sampler1DArray glyph;
const vec2 offsets4[4] = vec2[4](
vec2(-0.5, 0.5), vec2(0.5, 0.5), vec2(-0.5, -0.5), vec2(-0.5, -0.5));
@@ -25,54 +29,107 @@ const vec2 offsets16[16] = vec2[16](vec2(-1.5, 1.5),
vec2(0.5, -1.5),
vec2(1.5, -1.5));
-#define sample_glyph_offset(texco, texel, ofs) texture(glyph, texco + ofs * texel).r
+//#define GPU_NEAREST
+#define sample_glyph_offset(texel, ofs) texture_1D_custom_bilinear_filter(texCoord_interp + ofs * texel)
+
+float texel_fetch(int index)
+{
+ int size_x = textureSize(glyph, 0).r;
+ if (index >= size_x) {
+ return texelFetch(glyph, ivec2(index % size_x, index / size_x), 0).r;
+ }
+ return texelFetch(glyph, ivec2(index, 0), 0).r;
+}
+
+bool is_inside_box(ivec2 v)
+{
+ return all(greaterThanEqual(v, ivec2(0))) && all(lessThan(v, glyph_dim));
+}
+
+float texture_1D_custom_bilinear_filter(vec2 uv)
+{
+ vec2 texel_2d = uv * glyph_dim + 0.5;
+ ivec2 texel_2d_near = ivec2(texel_2d) - 1;
+ int frag_offset = glyph_offset + texel_2d_near.y * glyph_dim.x + texel_2d_near.x;
+
+ float tl = 0.0;
+
+ if (is_inside_box(texel_2d_near)) {
+ tl = texel_fetch(frag_offset);
+ }
+
+#ifdef GPU_NEAREST
+ return tl;
+#else //GPU_LINEAR
+ int offset_x = 1;
+ int offset_y = glyph_dim.x;
+
+ float tr = 0.0;
+ float bl = 0.0;
+ float br = 0.0;
+
+ if (is_inside_box(texel_2d_near + ivec2(1, 0))) {
+ tr = texel_fetch(frag_offset + offset_x);
+ }
+ if (is_inside_box(texel_2d_near + ivec2(0, 1))) {
+ bl = texel_fetch(frag_offset + offset_y);
+ }
+ if (is_inside_box(texel_2d_near + ivec2(1, 1))) {
+ br = texel_fetch(frag_offset + offset_x + offset_y);
+ }
+
+ vec2 f = fract(texel_2d);
+ float tA = mix(tl, tr, f.x);
+ float tB = mix(bl, br, f.x);
+
+ return mix(tA, tB, f.y);
+#endif
+}
void main()
{
// input color replaces texture color
fragColor.rgb = color_flat.rgb;
- vec2 texel = 1.0 / vec2(textureSize(glyph, 0));
- vec2 texco = abs(texCoord_interp);
-
// modulate input alpha & texture alpha
- if (texCoord_interp.x > 0) {
- fragColor.a = texture(glyph, texco).r;
+ if (interp_size == 0) {
+ fragColor.a = texture_1D_custom_bilinear_filter(texCoord_interp);
}
else {
+ vec2 texel = 1.0 / glyph_dim;
fragColor.a = 0.0;
- if (texCoord_interp.y > 0) {
+ if (interp_size == 1) {
/* 3x3 blur */
/* Manual unroll for perf. (stupid glsl compiler) */
- fragColor.a += sample_glyph_offset(texco, texel, offsets4[0]);
- fragColor.a += sample_glyph_offset(texco, texel, offsets4[1]);
- fragColor.a += sample_glyph_offset(texco, texel, offsets4[2]);
- fragColor.a += sample_glyph_offset(texco, texel, offsets4[3]);
+ fragColor.a += sample_glyph_offset(texel, offsets4[0]);
+ fragColor.a += sample_glyph_offset(texel, offsets4[1]);
+ fragColor.a += sample_glyph_offset(texel, offsets4[2]);
+ fragColor.a += sample_glyph_offset(texel, offsets4[3]);
fragColor.a *= (1.0 / 4.0);
}
else {
/* 5x5 blur */
/* Manual unroll for perf. (stupid glsl compiler) */
- fragColor.a += sample_glyph_offset(texco, texel, offsets16[0]);
- fragColor.a += sample_glyph_offset(texco, texel, offsets16[1]);
- fragColor.a += sample_glyph_offset(texco, texel, offsets16[2]);
- fragColor.a += sample_glyph_offset(texco, texel, offsets16[3]);
-
- fragColor.a += sample_glyph_offset(texco, texel, offsets16[4]);
- fragColor.a += sample_glyph_offset(texco, texel, offsets16[5]) * 2.0;
- fragColor.a += sample_glyph_offset(texco, texel, offsets16[6]) * 2.0;
- fragColor.a += sample_glyph_offset(texco, texel, offsets16[7]);
-
- fragColor.a += sample_glyph_offset(texco, texel, offsets16[8]);
- fragColor.a += sample_glyph_offset(texco, texel, offsets16[9]) * 2.0;
- fragColor.a += sample_glyph_offset(texco, texel, offsets16[10]) * 2.0;
- fragColor.a += sample_glyph_offset(texco, texel, offsets16[11]);
-
- fragColor.a += sample_glyph_offset(texco, texel, offsets16[12]);
- fragColor.a += sample_glyph_offset(texco, texel, offsets16[13]);
- fragColor.a += sample_glyph_offset(texco, texel, offsets16[14]);
- fragColor.a += sample_glyph_offset(texco, texel, offsets16[15]);
+ fragColor.a += sample_glyph_offset(texel, offsets16[0]);
+ fragColor.a += sample_glyph_offset(texel, offsets16[1]);
+ fragColor.a += sample_glyph_offset(texel, offsets16[2]);
+ fragColor.a += sample_glyph_offset(texel, offsets16[3]);
+
+ fragColor.a += sample_glyph_offset(texel, offsets16[4]);
+ fragColor.a += sample_glyph_offset(texel, offsets16[5]) * 2.0;
+ fragColor.a += sample_glyph_offset(texel, offsets16[6]) * 2.0;
+ fragColor.a += sample_glyph_offset(texel, offsets16[7]);
+
+ fragColor.a += sample_glyph_offset(texel, offsets16[8]);
+ fragColor.a += sample_glyph_offset(texel, offsets16[9]) * 2.0;
+ fragColor.a += sample_glyph_offset(texel, offsets16[10]) * 2.0;
+ fragColor.a += sample_glyph_offset(texel, offsets16[11]);
+
+ fragColor.a += sample_glyph_offset(texel, offsets16[12]);
+ fragColor.a += sample_glyph_offset(texel, offsets16[13]);
+ fragColor.a += sample_glyph_offset(texel, offsets16[14]);
+ fragColor.a += sample_glyph_offset(texel, offsets16[15]);
fragColor.a *= (1.0 / 20.0);
}
}
diff --git a/source/blender/gpu/shaders/gpu_shader_text_vert.glsl b/source/blender/gpu/shaders/gpu_shader_text_vert.glsl
index 28437208e91..768638e5229 100644
--- a/source/blender/gpu/shaders/gpu_shader_text_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_text_vert.glsl
@@ -2,20 +2,33 @@
uniform mat4 ModelViewProjectionMatrix;
in vec4 pos; /* rect */
-in vec4 tex; /* rect */
in vec4 col;
+in int offset;
+in ivec2 glyph_size;
flat out vec4 color_flat;
noperspective out vec2 texCoord_interp;
+flat out int glyph_offset;
+flat out ivec2 glyph_dim;
+flat out int interp_size;
void main()
{
+ color_flat = col;
+ glyph_offset = offset;
+ glyph_dim = abs(glyph_size);
+ interp_size = int(glyph_size.x < 0) + int(glyph_size.y < 0);
+
/* Quad expension using instanced rendering. */
float x = float(gl_VertexID % 2);
float y = float(gl_VertexID / 2);
vec2 quad = vec2(x, y);
- gl_Position = ModelViewProjectionMatrix * vec4(mix(pos.xy, pos.zw, quad), 0.0, 1.0);
- texCoord_interp = mix(abs(tex.xy), abs(tex.zw), quad) * sign(tex.xw);
- color_flat = col;
+ vec2 interp_offset = float(interp_size) / abs(pos.zw - pos.xy);
+ texCoord_interp = mix(-interp_offset, 1.0 + interp_offset, quad);
+
+ vec2 final_pos = mix(
+ pos.xy + ivec2(-interp_size, interp_size), pos.zw + ivec2(interp_size, -interp_size), quad);
+
+ gl_Position = ModelViewProjectionMatrix * vec4(final_pos, 0.0, 1.0);
}