[renderer] Replace Draw_FontString with Draw_Glyph

While Draw_Glyph does draw only one glyph at a time, it doesn't shape
the text every time, so is a major win for performance (especially
coupled with pre-shaped text).
This commit is contained in:
Bill Currie 2022-12-10 18:55:08 +09:00
parent d98eb8abc6
commit 5668006087
13 changed files with 86 additions and 158 deletions

View file

@ -59,7 +59,7 @@ void gl_Draw_Picf (float x, float y, struct qpic_s *pic);
void gl_Draw_SubPic(int x, int y, struct qpic_s *pic, void gl_Draw_SubPic(int x, int y, struct qpic_s *pic,
int srcx, int srcy, int width, int height); int srcx, int srcy, int width, int height);
int gl_Draw_AddFont (struct font_s *font); int gl_Draw_AddFont (struct font_s *font);
void gl_Draw_FontString (int x, int y, int fontid, const char *str); void gl_Draw_Glyph (int x, int y, int fontid, int glyphid, int c);
void GL_Set2D (void); void GL_Set2D (void);
void GL_Set2DScaled (void); void GL_Set2DScaled (void);

View file

@ -60,7 +60,7 @@ void glsl_Draw_Picf (float x, float y, struct qpic_s *pic);
void glsl_Draw_SubPic(int x, int y, struct qpic_s *pic, void glsl_Draw_SubPic(int x, int y, struct qpic_s *pic,
int srcx, int srcy, int width, int height); int srcx, int srcy, int width, int height);
int glsl_Draw_AddFont (struct font_s *font); int glsl_Draw_AddFont (struct font_s *font);
void glsl_Draw_FontString (int x, int y, int fontid, const char *str); void glsl_Draw_Glyph (int x, int y, int fontid, int glyphid, int c);
void GLSL_Set2D (void); void GLSL_Set2D (void);
void GLSL_Set2DScaled (void); void GLSL_Set2DScaled (void);

View file

@ -82,8 +82,8 @@ void Vulkan_Draw_SubPic(int x, int y, struct qpic_s *pic,
int srcx, int srcy, int width, int height, int srcx, int srcy, int width, int height,
struct vulkan_ctx_s *ctx); struct vulkan_ctx_s *ctx);
int Vulkan_Draw_AddFont (struct font_s *font, struct vulkan_ctx_s *ctx); int Vulkan_Draw_AddFont (struct font_s *font, struct vulkan_ctx_s *ctx);
void Vulkan_Draw_FontString (int x, int y, int fontid, const char *str, void Vulkan_Draw_Glyph (int x, int y, int fontid, int glyphid, int c,
struct vulkan_ctx_s *ctx); struct vulkan_ctx_s *ctx);
void Vulkan_Set2D (struct vulkan_ctx_s *ctx); void Vulkan_Set2D (struct vulkan_ctx_s *ctx);
void Vulkan_Set2DScaled (struct vulkan_ctx_s *ctx); void Vulkan_Set2DScaled (struct vulkan_ctx_s *ctx);

View file

@ -269,7 +269,7 @@ void Draw_SubPic(int x, int y, qpic_t *pic, int srcx, int srcy, int width, int h
struct font_s; struct font_s;
int Draw_AddFont (struct font_s *font); int Draw_AddFont (struct font_s *font);
void Draw_FontString (int x, int y, int fontid, const char *str); void Draw_Glyph (int x, int y, int fontid, int glyphid, int c);
///@} ///@}

View file

@ -111,7 +111,7 @@ typedef struct vid_render_funcs_s {
void (*Draw_Picf) (float x, float y, qpic_t *pic); void (*Draw_Picf) (float x, float y, qpic_t *pic);
void (*Draw_SubPic) (int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height); void (*Draw_SubPic) (int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height);
int (*Draw_AddFont) (struct font_s *font); int (*Draw_AddFont) (struct font_s *font);
void (*Draw_FontString) (int x, int y, int fontid, const char *str); void (*Draw_Glyph) (int x, int y, int fontid, int glyphid, int c);
struct psystem_s *(*ParticleSystem) (void); struct psystem_s *(*ParticleSystem) (void);

View file

@ -1075,17 +1075,15 @@ gl_Draw_AddFont (font_t *rfont)
font->texid = GL_LoadTex ("", 0, &tex); font->texid = GL_LoadTex ("", 0, &tex);
return fontid; return fontid;
} }
#if 0
typedef struct {
int fontid;
byte color[4];
} glrgctx_t;
static void void
gl_render_glyph (uint32_t glyphid, int x, int y, void *_rgctx) gl_Draw_Glyph (int x, int y, int fontid, int glyphid, int c)
{ {
glrgctx_t *rgctx = _rgctx; if (fontid < 0 || (unsigned) fontid > gl_fonts.size) {
glfont_t *font = &gl_fonts.a[rgctx->fontid]; return;
}
glfont_t *font = &gl_fonts.a[fontid];
font_t *rfont = font->font; font_t *rfont = font->font;
vrect_t *rect = &rfont->glyph_rects[glyphid]; vrect_t *rect = &rfont->glyph_rects[glyphid];
@ -1095,7 +1093,12 @@ gl_render_glyph (uint32_t glyphid, int x, int y, void *_rgctx)
float v = rect->y; float v = rect->y;
float s = 1.0 / rfont->scrap.width; float s = 1.0 / rfont->scrap.width;
float t = 1.0 / rfont->scrap.height; float t = 1.0 / rfont->scrap.height;
qfglColor4ubv (rgctx->color);
qfglBindTexture (GL_TEXTURE_2D, gl_fonts.a[fontid].texid);
qfglBegin (GL_QUADS);
byte color[4] = { VectorExpand (vid.palette + c * 3), 255 };
qfglColor4ubv (color);
qfglTexCoord2f (u * s, v * t); qfglTexCoord2f (u * s, v * t);
qfglVertex2f (x, y); qfglVertex2f (x, y);
qfglTexCoord2f ((u + w) * s, v * t); qfglTexCoord2f ((u + w) * s, v * t);
@ -1104,35 +1107,7 @@ gl_render_glyph (uint32_t glyphid, int x, int y, void *_rgctx)
qfglVertex2f (x + w, y + h); qfglVertex2f (x + w, y + h);
qfglTexCoord2f (u * s, (v + h) * t); qfglTexCoord2f (u * s, (v + h) * t);
qfglVertex2f (x, y + h); qfglVertex2f (x, y + h);
}
#endif
void
gl_Draw_FontString (int x, int y, int fontid, const char *str)
{
#if 0
if (fontid < 0 || (unsigned) fontid > gl_fonts.size) {
return;
}
glrgctx_t rgctx = {
.fontid = fontid,
.color = { 127, 255, 153, 255 },
};
//FIXME ewwwwwww
rtext_t text = {
.text = str,
.language = "en",
.script = HB_SCRIPT_LATIN,
.direction = HB_DIRECTION_LTR,
};
qfglBindTexture (GL_TEXTURE_2D, gl_fonts.a[fontid].texid);
qfglBegin (GL_QUADS);
rshaper_t *shaper = RText_NewShaper (gl_fonts.a[fontid].font);
RText_RenderText (shaper, &text, x, y, gl_render_glyph, &rgctx);
RText_DeleteShaper (shaper);
qfglEnd (); qfglEnd ();
qfglColor4ubv (color_white); qfglColor4ubv (color_white);
#endif
} }

View file

@ -944,8 +944,21 @@ glsl_render_glyph (uint32_t glyphid, int x, int y, void *_rgctx)
glslrgctx_t *rgctx = _rgctx; glslrgctx_t *rgctx = _rgctx;
vrect_t *rect = &rgctx->glyph_rects[glyphid]; vrect_t *rect = &rgctx->glyph_rects[glyphid];
dstring_t *batch = rgctx->batch; dstring_t *batch = rgctx->batch;
int size = 6 * sizeof (drawvert_t);
}
#endif
void
glsl_Draw_Glyph (int x, int y, int fontid, int glyphid, int c)
{
if (fontid < 0 || (unsigned) fontid > glsl_fonts.size) {
return;
}
glslfont_t *font = &glsl_fonts.a[fontid];
font_t *rfont = font->font;
vrect_t *rect = &rfont->glyph_rects[glyphid];
dstring_t *batch = glyph_queue;
int size = 6 * sizeof (drawvert_t);
batch->size += size; batch->size += size;
dstring_adjust (batch); dstring_adjust (batch);
drawvert_t *verts = (drawvert_t *) (batch->str + batch->size - size); drawvert_t *verts = (drawvert_t *) (batch->str + batch->size - size);
@ -954,8 +967,8 @@ glsl_render_glyph (uint32_t glyphid, int x, int y, void *_rgctx)
float h = rect->height; float h = rect->height;
float u = rect->x; float u = rect->x;
float v = rect->y; float v = rect->y;
float s = 1.0 / rgctx->width; float s = 1.0 / rfont->scrap.width;
float t = 1.0 / rgctx->height; float t = 1.0 / rfont->scrap.height;
verts[0] = (drawvert_t) { verts[0] = (drawvert_t) {
.xyst = { x, y, u * s, v * t }, .xyst = { x, y, u * s, v * t },
@ -976,42 +989,14 @@ glsl_render_glyph (uint32_t glyphid, int x, int y, void *_rgctx)
.xyst = { x, y + h, u * s, (v + h) * t }, .xyst = { x, y + h, u * s, (v + h) * t },
}; };
QuatCopy (rgctx->color, verts[0].color); quat_t color = { VectorExpand (vid.palette + c * 3), 255 };
QuatCopy (rgctx->color, verts[1].color); QuatScale (color, 1.0f/255.0f, color);
QuatCopy (rgctx->color, verts[2].color); QuatCopy (color, verts[0].color);
QuatCopy (rgctx->color, verts[3].color); QuatCopy (color, verts[1].color);
QuatCopy (rgctx->color, verts[4].color); QuatCopy (color, verts[2].color);
QuatCopy (rgctx->color, verts[5].color); QuatCopy (color, verts[3].color);
} QuatCopy (color, verts[4].color);
#endif QuatCopy (color, verts[5].color);
void
glsl_Draw_FontString (int x, int y, int fontid, const char *str)
{
#if 0
if (fontid < 0 || (unsigned) fontid > glsl_fonts.size) {
return;
}
glslfont_t *font = &glsl_fonts.a[fontid];
font_t *rfont = font->font;
glslrgctx_t rgctx = {
.glyph_rects = rfont->glyph_rects,
.batch = glyph_queue,
.width = rfont->scrap.width,
.height = rfont->scrap.height,
};
quat_t color = { 127, 255, 153, 255 };
QuatScale (color, 1.0f/255.0f, rgctx.color);
//FIXME ewwwwwww
rtext_t text = {
.text = str,
.language = "en",
.script = HB_SCRIPT_LATIN,
.direction = HB_DIRECTION_LTR,
};
rshaper_t *shaper = RText_NewShaper (rfont);
RText_RenderText (shaper, &text, x, y, glsl_render_glyph, &rgctx);
RText_DeleteShaper (shaper);
qfeglUseProgram (alpha_2d.program); qfeglUseProgram (alpha_2d.program);
qfeglEnableVertexAttribArray (alpha_2d.vertex.location); qfeglEnableVertexAttribArray (alpha_2d.vertex.location);
@ -1030,5 +1015,4 @@ glsl_Draw_FontString (int x, int y, int fontid, const char *str)
glyph_queue->size = 0; glyph_queue->size = 0;
qfeglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); qfeglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
qfeglUseProgram (quake_2d.program); qfeglUseProgram (quake_2d.program);
#endif
} }

View file

@ -1023,7 +1023,6 @@ static void
sw_render_glyph (uint32_t glyphid, int x, int y, void *_rgctx) sw_render_glyph (uint32_t glyphid, int x, int y, void *_rgctx)
{ {
swrgctx_t *rgctx = _rgctx; swrgctx_t *rgctx = _rgctx;
vrect_t *rect = &rgctx->glyph_rects[glyphid];
float w = rect->width; float w = rect->width;
float h = rect->height; float h = rect->height;
@ -1047,30 +1046,32 @@ sw_render_glyph (uint32_t glyphid, int x, int y, void *_rgctx)
} }
#endif #endif
void void
Draw_FontString (int x, int y, int fontid, const char *str) Draw_Glyph (int x, int y, int fontid, int glyphid, int c)
{ {
#if 0
if (fontid < 0 || (unsigned) fontid > sw_fonts.size) { if (fontid < 0 || (unsigned) fontid > sw_fonts.size) {
return; return;
} }
swfont_t *font = &sw_fonts.a[fontid]; swfont_t *font = &sw_fonts.a[fontid];
font_t *rfont = font->font; font_t *rfont = font->font;
swrgctx_t rgctx = { vrect_t *rect = &rfont->glyph_rects[glyphid];
.glyph_rects = rfont->glyph_rects, int width = rfont->scrap.width;
.bitmap = rfont->scrap_bitmap,
.width = rfont->scrap.width,
.color = 63,
};
//FIXME ewwwwwww
rtext_t text = {
.text = str,
.language = "en",
.script = HB_SCRIPT_LATIN,
.direction = HB_DIRECTION_LTR,
};
rshaper_t *shaper = RText_NewShaper (rfont); float w = rect->width;
RText_RenderText (shaper, &text, x, y, sw_render_glyph, &rgctx); float h = rect->height;
RText_DeleteShaper (shaper); if (x < 0 || y < 0 || x + w > vid.width || y + h > vid.height) {
#endif return;
}
int u = rect->x;
int v = rect->y;
byte *src = rfont->scrap_bitmap + v * width + u;
byte *dst = d_viewbuffer + y * d_rowbytes + x;
while (h-- > 0) {
for (int i = 0; i < w; i++) {
if (src[i] > 127) {
dst[i] = c;
}
}
src += width;
dst += d_rowbytes;
}
} }

View file

@ -525,7 +525,7 @@ vid_render_funcs_t gl_vid_render_funcs = {
.Draw_Picf = gl_Draw_Picf, .Draw_Picf = gl_Draw_Picf,
.Draw_SubPic = gl_Draw_SubPic, .Draw_SubPic = gl_Draw_SubPic,
.Draw_AddFont = gl_Draw_AddFont, .Draw_AddFont = gl_Draw_AddFont,
.Draw_FontString = gl_Draw_FontString, .Draw_Glyph = gl_Draw_Glyph,
.ParticleSystem = gl_ParticleSystem, .ParticleSystem = gl_ParticleSystem,
.R_Init = gl_R_Init, .R_Init = gl_R_Init,

View file

@ -469,7 +469,7 @@ vid_render_funcs_t glsl_vid_render_funcs = {
.Draw_Picf = glsl_Draw_Picf, .Draw_Picf = glsl_Draw_Picf,
.Draw_SubPic = glsl_Draw_SubPic, .Draw_SubPic = glsl_Draw_SubPic,
.Draw_AddFont = glsl_Draw_AddFont, .Draw_AddFont = glsl_Draw_AddFont,
.Draw_FontString = glsl_Draw_FontString, .Draw_Glyph = glsl_Draw_Glyph,
.ParticleSystem = glsl_ParticleSystem, .ParticleSystem = glsl_ParticleSystem,
.R_Init = glsl_R_Init, .R_Init = glsl_R_Init,

View file

@ -482,7 +482,7 @@ vid_render_funcs_t sw_vid_render_funcs = {
.Draw_Picf = Draw_Picf, .Draw_Picf = Draw_Picf,
.Draw_SubPic = Draw_SubPic, .Draw_SubPic = Draw_SubPic,
.Draw_AddFont = Draw_AddFont, .Draw_AddFont = Draw_AddFont,
.Draw_FontString = Draw_FontString, .Draw_Glyph = Draw_Glyph,
.ParticleSystem = sw_ParticleSystem, .ParticleSystem = sw_ParticleSystem,
.R_Init = sw_R_Init, .R_Init = sw_R_Init,

View file

@ -291,9 +291,9 @@ vulkan_Draw_AddFont (struct font_s *font)
} }
static void static void
vulkan_Draw_FontString (int x, int y, int fontid, const char *str) vulkan_Draw_Glyph (int x, int y, int fontid, int glyphid, int c)
{ {
Vulkan_Draw_FontString (x, y, fontid, str, vulkan_ctx); Vulkan_Draw_Glyph (x, y, fontid, glyphid, c, vulkan_ctx);
} }
static void static void
@ -792,7 +792,7 @@ vid_render_funcs_t vulkan_vid_render_funcs = {
.Draw_Picf = vulkan_Draw_Picf, .Draw_Picf = vulkan_Draw_Picf,
.Draw_SubPic = vulkan_Draw_SubPic, .Draw_SubPic = vulkan_Draw_SubPic,
.Draw_AddFont = vulkan_Draw_AddFont, .Draw_AddFont = vulkan_Draw_AddFont,
.Draw_FontString = vulkan_Draw_FontString, .Draw_Glyph = vulkan_Draw_Glyph,
.ParticleSystem = vulkan_ParticleSystem, .ParticleSystem = vulkan_ParticleSystem,
.R_Init = vulkan_R_Init, .R_Init = vulkan_R_Init,

View file

@ -1515,65 +1515,33 @@ Vulkan_Draw_AddFont (font_t *rfont, vulkan_ctx_t *ctx)
return fontid; return fontid;
} }
#if 0
typedef struct {
drawframe_t *dframe;
descbatch_t *batch;
byte color[4];
} rgctx_t;
static void void
vulkan_render_glyph (uint32_t glyphid, int x, int y, void *_rgctx) Vulkan_Draw_Glyph (int x, int y, int fontid, int glyph, int c,
vulkan_ctx_t *ctx)
{ {
rgctx_t *rgctx = _rgctx; drawctx_t *dctx = ctx->draw_context;
glyphqueue_t *queue = &rgctx->dframe->glyph_insts;; drawframe_t *dframe = &dctx->frames.a[ctx->curFrame];
glyphqueue_t *queue = &dframe->glyph_insts;;
if (queue->count >= queue->size) { if (queue->count >= queue->size) {
return; return;
} }
rgctx->batch->count++; descbatch_t *batch = &dframe->glyph_batch.a[dframe->glyph_batch.size - 1];
glyphinst_t *inst = &queue->glyphs[queue->count++]; if (!dframe->glyph_batch.size || batch->descid != fontid) {
inst->index = glyphid;
QuatCopy (rgctx->color, inst->color);
inst->position[0] = x;
inst->position[1] = y;
}
#endif
void
Vulkan_Draw_FontString (int x, int y, int fontid, const char *str,
vulkan_ctx_t *ctx)
{
#if 0
drawctx_t *dctx = ctx->draw_context;
if (fontid < 0 || (unsigned) fontid > dctx->fonts.size) {
return;
}
drawframe_t *dframe = &dctx->frames.a[ctx->curFrame];
rgctx_t rgctx = {
.dframe = dframe,
.color = { 127, 255, 153, 255 },
};
//FIXME ewwwwwww
rtext_t text = {
.text = str,
.language = "en",
.script = HB_SCRIPT_LATIN,
.direction = HB_DIRECTION_LTR,
};
rgctx.batch = &dframe->glyph_batch.a[dframe->glyph_batch.size - 1];
if (!dframe->glyph_batch.size || rgctx.batch->descid != fontid) {
DARRAY_APPEND(&dframe->glyph_batch, DARRAY_APPEND(&dframe->glyph_batch,
((descbatch_t) { .descid = fontid })); ((descbatch_t) { .descid = fontid }));
rgctx.batch = &dframe->glyph_batch.a[dframe->glyph_batch.size - 1]; batch = &dframe->glyph_batch.a[dframe->glyph_batch.size - 1];
} }
rshaper_t *shaper = RText_NewShaper (dctx->fonts.a[fontid].font); batch->count++;
RText_RenderText (shaper, &text, x, y, vulkan_render_glyph, &rgctx); glyphinst_t *inst = &queue->glyphs[queue->count++];
RText_DeleteShaper (shaper); inst->index = glyph;
#endif VectorCopy (vid.palette + c * 3, inst->color);
inst->color[3] = 255;
inst->position[0] = x;
inst->position[1] = y;
} }
void void