Font rendering speedup
We now use a single texture for all text rendering instead of generating/freeing textures for every bit of text.
This commit is contained in:
parent
08657f9736
commit
b804f53a45
6 changed files with 109 additions and 12 deletions
|
@ -24,24 +24,80 @@ TTF_Font *load_font(char *name, int size) {
|
|||
return f;
|
||||
}
|
||||
|
||||
void fontrenderer_init(FontRenderer *f) {
|
||||
glGenBuffers(1,&f->pbo);
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, f->pbo);
|
||||
glBufferData(GL_PIXEL_UNPACK_BUFFER, FONTREN_MAXW*FONTREN_MAXH*4, NULL, GL_STREAM_DRAW);
|
||||
glGenTextures(1,&f->tex.gltex);
|
||||
|
||||
f->tex.truew = FONTREN_MAXW;
|
||||
f->tex.trueh = FONTREN_MAXH;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D,f->tex.gltex);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, f->tex.truew, f->tex.trueh, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
}
|
||||
|
||||
void fontrenderer_free(FontRenderer *f) {
|
||||
glDeleteBuffers(1,&f->pbo);
|
||||
glDeleteTextures(1,&f->tex.gltex);
|
||||
}
|
||||
|
||||
void fontrenderer_draw(FontRenderer *f, const char *text,TTF_Font *font) {
|
||||
SDL_Color clr = {255,255,255};
|
||||
SDL_Surface *surf = TTF_RenderUTF8_Blended(font, text, clr);
|
||||
assert(surf != NULL);
|
||||
|
||||
if(surf->w > FONTREN_MAXW || surf->h > FONTREN_MAXH) {
|
||||
log_fatal("Text drawn (%dx%d) is too big for the internal buffer (%dx%d).", surf->pitch, surf->h, FONTREN_MAXW, FONTREN_MAXH);
|
||||
}
|
||||
f->tex.w = surf->w;
|
||||
f->tex.h = surf->h;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D,f->tex.gltex);
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, f->pbo);
|
||||
|
||||
glBufferData(GL_PIXEL_UNPACK_BUFFER, FONTREN_MAXW*FONTREN_MAXH*4, NULL, GL_STREAM_DRAW);
|
||||
|
||||
// zero pad the texture
|
||||
int winw = surf->w+1; // zero pad the texture
|
||||
int winh = surf->h+1;
|
||||
|
||||
uint32_t *pixels = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
|
||||
for(int y = 0; y < surf->h; y++) {
|
||||
memcpy(pixels+y*winw, ((uint8_t *)surf->pixels)+y*surf->pitch, surf->w*4);
|
||||
pixels[y*winw+surf->w]=0; // set the border to zero to avoid previously drawn text bleeding in.
|
||||
}
|
||||
memset(pixels+(winh-1)*winw,0,winw*4);
|
||||
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
|
||||
glTexSubImage2D(GL_TEXTURE_2D,0,0,0,winw,winh,GL_RGBA,GL_UNSIGNED_BYTE,0);
|
||||
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
|
||||
|
||||
SDL_FreeSurface(surf);
|
||||
}
|
||||
|
||||
|
||||
void init_fonts(void) {
|
||||
TTF_Init();
|
||||
|
||||
fontrenderer_init(&resources.fontren);
|
||||
_fonts.standard = load_font("gfx/LinBiolinum.ttf", 20);
|
||||
_fonts.mainmenu = load_font("gfx/immortal.ttf", 35);
|
||||
|
||||
}
|
||||
|
||||
Texture *load_text(const char *text, TTF_Font *font) {
|
||||
Texture *tex = malloc(sizeof(Texture));
|
||||
SDL_Color clr = {255,255,255};
|
||||
SDL_Surface *surf = TTF_RenderUTF8_Blended(font, text, clr);
|
||||
assert(surf != NULL);
|
||||
void free_fonts(void) {
|
||||
fontrenderer_free(&resources.fontren);
|
||||
TTF_CloseFont(_fonts.standard);
|
||||
TTF_CloseFont(_fonts.mainmenu);
|
||||
|
||||
load_sdl_surf(surf, tex);
|
||||
SDL_FreeSurface(surf);
|
||||
|
||||
return tex;
|
||||
TTF_Quit();
|
||||
}
|
||||
|
||||
void draw_text(Alignment align, float x, float y, const char *text, TTF_Font *font) {
|
||||
|
@ -54,7 +110,8 @@ void draw_text(Alignment align, float x, float y, const char *text, TTF_Font *fo
|
|||
*nl = '\0';
|
||||
}
|
||||
|
||||
Texture *tex = load_text(buf, font);
|
||||
fontrenderer_draw(&resources.fontren, buf, font);
|
||||
Texture *tex = &resources.fontren.tex;
|
||||
|
||||
switch(align) {
|
||||
case AL_Center:
|
||||
|
@ -73,9 +130,9 @@ void draw_text(Alignment align, float x, float y, const char *text, TTF_Font *fo
|
|||
if(tex->h&1)
|
||||
y += 0.5;
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
draw_texture_p(x, y, tex);
|
||||
|
||||
free_texture(tex);
|
||||
free(buf);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,9 +17,28 @@ typedef enum {
|
|||
AL_Right
|
||||
} Alignment;
|
||||
|
||||
|
||||
// Size of the buffer used by the font renderer. No text larger than this can be drawn.
|
||||
enum {
|
||||
FONTREN_MAXW = 512,
|
||||
FONTREN_MAXH = 512
|
||||
};
|
||||
|
||||
typedef struct FontRenderer FontRenderer;
|
||||
struct FontRenderer {
|
||||
Texture tex;
|
||||
GLuint pbo;
|
||||
};
|
||||
|
||||
void fontrenderer_init(FontRenderer *f);
|
||||
void fontrenderer_free(FontRenderer *f);
|
||||
void fontrenderer_draw(FontRenderer *f, const char *text,TTF_Font *font);
|
||||
|
||||
Texture *load_text(const char *text, TTF_Font *font);
|
||||
void draw_text(Alignment align, float x, float y, const char *text, TTF_Font *font);
|
||||
void init_fonts(void);
|
||||
void free_fonts(void);
|
||||
|
||||
int stringwidth(char *s, TTF_Font *font);
|
||||
int stringheight(char *s, TTF_Font *font);
|
||||
int charwidth(char c, TTF_Font *font);
|
||||
|
|
|
@ -404,6 +404,7 @@ void load_resources(void) {
|
|||
}
|
||||
|
||||
void free_resources(bool all) {
|
||||
free_fonts();
|
||||
for(ResourceType type = 0; type < RES_NUMTYPES; ++type) {
|
||||
ResourceHandler *handler = get_handler(type);
|
||||
|
||||
|
|
|
@ -102,6 +102,7 @@ typedef struct Resources {
|
|||
FBO fbg[2];
|
||||
FBO fsec;
|
||||
PostprocessShader *stage_postprocess;
|
||||
FontRenderer fontren;
|
||||
} Resources;
|
||||
|
||||
extern Resources resources;
|
||||
|
|
|
@ -180,6 +180,7 @@ typedef const GLubyte * (GLAPIENTRY *tsglGetString_ptr)(GLenum name);
|
|||
typedef GLint (APIENTRY *tsglGetUniformLocation_ptr)(GLuint program, const GLchar *name);
|
||||
typedef void (APIENTRY *tsglLinkProgram_ptr)(GLuint program);
|
||||
typedef void (GLAPIENTRY *tsglLoadIdentity_ptr)(void);
|
||||
typedef void * (APIENTRY *tsglMapBuffer_ptr)(GLenum target, GLenum access);
|
||||
typedef void (GLAPIENTRY *tsglMatrixMode_ptr)(GLenum mode);
|
||||
typedef void (GLAPIENTRY *tsglNormalPointer_ptr)(GLenum type, GLsizei stride, const GLvoid *ptr);
|
||||
typedef void (GLAPIENTRY *tsglOrtho_ptr)(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near_val, GLdouble far_val);
|
||||
|
@ -195,6 +196,7 @@ typedef void (GLAPIENTRY *tsglTexCoordPointer_ptr)(GLint size, GLenum type, GLsi
|
|||
typedef void (GLAPIENTRY *tsglTexImage2D_ptr)(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
|
||||
typedef void (GLAPIENTRY *tsglTexParameterf_ptr)(GLenum target, GLenum pname, GLfloat param);
|
||||
typedef void (GLAPIENTRY *tsglTexParameteri_ptr)(GLenum target, GLenum pname, GLint param);
|
||||
typedef void (GLAPIENTRY *tsglTexSubImage2D_ptr)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
|
||||
typedef void (GLAPIENTRY *tsglTranslatef_ptr)(GLfloat x, GLfloat y, GLfloat z);
|
||||
typedef void (APIENTRY *tsglUniform1f_ptr)(GLint location, GLfloat v0);
|
||||
typedef void (APIENTRY *tsglUniform1fv_ptr)(GLint location, GLsizei count, const GLfloat *value);
|
||||
|
@ -215,6 +217,7 @@ typedef void (APIENTRY *tsglUniform4fv_ptr)(GLint location, GLsizei count, const
|
|||
typedef void (APIENTRY *tsglUniform4fv_ptr)(GLint location, GLsizei count, const GLfloat *value);
|
||||
typedef void (APIENTRY *tsglUniform4iv_ptr)(GLint location, GLsizei count, const GLint *value);
|
||||
typedef void (APIENTRY *tsglUniform4uiv_ptr)(GLint location, GLsizei count, const GLuint *value);
|
||||
typedef GLboolean (APIENTRY *tsglUnmapBuffer_ptr)(GLenum target);
|
||||
typedef void (APIENTRY *tsglUseProgram_ptr)(GLuint program);
|
||||
typedef void (GLAPIENTRY *tsglVertexPointer_ptr)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr);
|
||||
typedef void (GLAPIENTRY *tsglViewport_ptr)(GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
|
@ -270,6 +273,7 @@ typedef void (GLAPIENTRY *tsglViewport_ptr)(GLint x, GLint y, GLsizei width, GLs
|
|||
#undef glGetUniformLocation
|
||||
#undef glLinkProgram
|
||||
#undef glLoadIdentity
|
||||
#undef glMapBuffer
|
||||
#undef glMatrixMode
|
||||
#undef glNormalPointer
|
||||
#undef glOrtho
|
||||
|
@ -285,6 +289,7 @@ typedef void (GLAPIENTRY *tsglViewport_ptr)(GLint x, GLint y, GLsizei width, GLs
|
|||
#undef glTexImage2D
|
||||
#undef glTexParameterf
|
||||
#undef glTexParameteri
|
||||
#undef glTexSubImage2D
|
||||
#undef glTranslatef
|
||||
#undef glUniform1f
|
||||
#undef glUniform1fv
|
||||
|
@ -305,6 +310,7 @@ typedef void (GLAPIENTRY *tsglViewport_ptr)(GLint x, GLint y, GLsizei width, GLs
|
|||
#undef glUniform4fv
|
||||
#undef glUniform4iv
|
||||
#undef glUniform4uiv
|
||||
#undef glUnmapBuffer
|
||||
#undef glUseProgram
|
||||
#undef glVertexPointer
|
||||
#undef glViewport
|
||||
|
@ -361,6 +367,7 @@ typedef void (GLAPIENTRY *tsglViewport_ptr)(GLint x, GLint y, GLsizei width, GLs
|
|||
#define glGetUniformLocation tsglGetUniformLocation
|
||||
#define glLinkProgram tsglLinkProgram
|
||||
#define glLoadIdentity tsglLoadIdentity
|
||||
#define glMapBuffer tsglMapBuffer
|
||||
#define glMatrixMode tsglMatrixMode
|
||||
#define glNormalPointer tsglNormalPointer
|
||||
#define glOrtho tsglOrtho
|
||||
|
@ -376,6 +383,7 @@ typedef void (GLAPIENTRY *tsglViewport_ptr)(GLint x, GLint y, GLsizei width, GLs
|
|||
#define glTexImage2D tsglTexImage2D
|
||||
#define glTexParameterf tsglTexParameterf
|
||||
#define glTexParameteri tsglTexParameteri
|
||||
#define glTexSubImage2D tsglTexSubImage2D
|
||||
#define glTranslatef tsglTranslatef
|
||||
#define glUniform1f tsglUniform1f
|
||||
#define glUniform1fv tsglUniform1fv
|
||||
|
@ -396,6 +404,7 @@ typedef void (GLAPIENTRY *tsglViewport_ptr)(GLint x, GLint y, GLsizei width, GLs
|
|||
#define glUniform4fv tsglUniform4fv
|
||||
#define glUniform4iv tsglUniform4iv
|
||||
#define glUniform4uiv tsglUniform4uiv
|
||||
#define glUnmapBuffer tsglUnmapBuffer
|
||||
#define glUseProgram tsglUseProgram
|
||||
#define glVertexPointer tsglVertexPointer
|
||||
#define glViewport tsglViewport
|
||||
|
@ -454,6 +463,7 @@ GLDEF(glGetString, tsglGetString, tsglGetString_ptr) \
|
|||
GLDEF(glGetUniformLocation, tsglGetUniformLocation, tsglGetUniformLocation_ptr) \
|
||||
GLDEF(glLinkProgram, tsglLinkProgram, tsglLinkProgram_ptr) \
|
||||
GLDEF(glLoadIdentity, tsglLoadIdentity, tsglLoadIdentity_ptr) \
|
||||
GLDEF(glMapBuffer, tsglMapBuffer, tsglMapBuffer_ptr) \
|
||||
GLDEF(glMatrixMode, tsglMatrixMode, tsglMatrixMode_ptr) \
|
||||
GLDEF(glNormalPointer, tsglNormalPointer, tsglNormalPointer_ptr) \
|
||||
GLDEF(glOrtho, tsglOrtho, tsglOrtho_ptr) \
|
||||
|
@ -469,6 +479,7 @@ GLDEF(glTexCoordPointer, tsglTexCoordPointer, tsglTexCoordPointer_ptr) \
|
|||
GLDEF(glTexImage2D, tsglTexImage2D, tsglTexImage2D_ptr) \
|
||||
GLDEF(glTexParameterf, tsglTexParameterf, tsglTexParameterf_ptr) \
|
||||
GLDEF(glTexParameteri, tsglTexParameteri, tsglTexParameteri_ptr) \
|
||||
GLDEF(glTexSubImage2D, tsglTexSubImage2D, tsglTexSubImage2D_ptr) \
|
||||
GLDEF(glTranslatef, tsglTranslatef, tsglTranslatef_ptr) \
|
||||
GLDEF(glUniform1f, tsglUniform1f, tsglUniform1f_ptr) \
|
||||
GLDEF(glUniform1fv, tsglUniform1fv, tsglUniform1fv_ptr) \
|
||||
|
@ -489,6 +500,7 @@ GLDEF(glUniform4fv, tsglUniform4fv, tsglUniform4fv_ptr) \
|
|||
GLDEF(glUniform4fv, tsglUniform4fv, tsglUniform4fv_ptr) \
|
||||
GLDEF(glUniform4iv, tsglUniform4iv, tsglUniform4iv_ptr) \
|
||||
GLDEF(glUniform4uiv, tsglUniform4uiv, tsglUniform4uiv_ptr) \
|
||||
GLDEF(glUnmapBuffer, tsglUnmapBuffer, tsglUnmapBuffer_ptr) \
|
||||
GLDEF(glUseProgram, tsglUseProgram, tsglUseProgram_ptr) \
|
||||
GLDEF(glVertexPointer, tsglVertexPointer, tsglVertexPointer_ptr) \
|
||||
GLDEF(glViewport, tsglViewport, tsglViewport_ptr)
|
||||
|
@ -551,6 +563,7 @@ GLAPI const GLubyte * GLAPIENTRY glGetString( GLenum name );
|
|||
GLAPI GLint APIENTRY glGetUniformLocation (GLuint program, const GLchar *name);
|
||||
GLAPI void APIENTRY glLinkProgram (GLuint program);
|
||||
GLAPI void GLAPIENTRY glLoadIdentity( void );
|
||||
GLAPI void *APIENTRY glMapBuffer (GLenum target, GLenum access);
|
||||
GLAPI void GLAPIENTRY glMatrixMode( GLenum mode );
|
||||
GLAPI void GLAPIENTRY glNormalPointer( GLenum type, GLsizei stride, const GLvoid *ptr );
|
||||
GLAPI void GLAPIENTRY glOrtho( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near_val, GLdouble far_val );
|
||||
|
@ -566,6 +579,7 @@ GLAPI void GLAPIENTRY glTexCoordPointer( GLint size, GLenum type, GLsizei stride
|
|||
GLAPI void GLAPIENTRY glTexImage2D( GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels );
|
||||
GLAPI void GLAPIENTRY glTexParameterf( GLenum target, GLenum pname, GLfloat param );
|
||||
GLAPI void GLAPIENTRY glTexParameteri( GLenum target, GLenum pname, GLint param );
|
||||
GLAPI void GLAPIENTRY glTexSubImage2D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels );
|
||||
GLAPI void GLAPIENTRY glTranslatef( GLfloat x, GLfloat y, GLfloat z );
|
||||
GLAPI void APIENTRY glUniform1f (GLint location, GLfloat v0);
|
||||
GLAPI void APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat *value);
|
||||
|
@ -586,6 +600,7 @@ GLAPI void APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat *
|
|||
GLAPI void APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat *value);
|
||||
GLAPI void APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint *value);
|
||||
GLAPI void APIENTRY glUniform4uiv (GLint location, GLsizei count, const GLuint *value);
|
||||
GLAPI GLboolean APIENTRY glUnmapBuffer (GLenum target);
|
||||
GLAPI void APIENTRY glUseProgram (GLuint program);
|
||||
GLAPI void GLAPIENTRY glVertexPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *ptr );
|
||||
GLAPI void GLAPIENTRY glViewport( GLint x, GLint y, GLsizei width, GLsizei height );
|
||||
|
@ -641,6 +656,7 @@ GLAPI void GLAPIENTRY glViewport( GLint x, GLint y, GLsizei width, GLsizei heigh
|
|||
#define tsglGetUniformLocation glGetUniformLocation
|
||||
#define tsglLinkProgram glLinkProgram
|
||||
#define tsglLoadIdentity glLoadIdentity
|
||||
#define tsglMapBuffer glMapBuffer
|
||||
#define tsglMatrixMode glMatrixMode
|
||||
#define tsglNormalPointer glNormalPointer
|
||||
#define tsglOrtho glOrtho
|
||||
|
@ -656,6 +672,7 @@ GLAPI void GLAPIENTRY glViewport( GLint x, GLint y, GLsizei width, GLsizei heigh
|
|||
#define tsglTexImage2D glTexImage2D
|
||||
#define tsglTexParameterf glTexParameterf
|
||||
#define tsglTexParameteri glTexParameteri
|
||||
#define tsglTexSubImage2D glTexSubImage2D
|
||||
#define tsglTranslatef glTranslatef
|
||||
#define tsglUniform1f glUniform1f
|
||||
#define tsglUniform1fv glUniform1fv
|
||||
|
@ -676,6 +693,7 @@ GLAPI void GLAPIENTRY glViewport( GLint x, GLint y, GLsizei width, GLsizei heigh
|
|||
#define tsglUniform4fv glUniform4fv
|
||||
#define tsglUniform4iv glUniform4iv
|
||||
#define tsglUniform4uiv glUniform4uiv
|
||||
#define tsglUnmapBuffer glUnmapBuffer
|
||||
#define tsglUseProgram glUseProgram
|
||||
#define tsglVertexPointer glVertexPointer
|
||||
#define tsglViewport glViewport
|
||||
|
|
|
@ -107,6 +107,7 @@ static void APIENTRY video_gl_debug(
|
|||
case GL_DEBUG_SEVERITY_LOW: strsev = "low"; break;
|
||||
case GL_DEBUG_SEVERITY_MEDIUM: strsev = "medium"; break;
|
||||
case GL_DEBUG_SEVERITY_HIGH: strsev = "high"; break;
|
||||
case GL_DEBUG_SEVERITY_NOTIFICATION: if(type == GL_DEBUG_TYPE_OTHER) return; break;
|
||||
}
|
||||
|
||||
log_custom(lvl, "[OpenGL debug, %s, %s] %i: %s", strtype, strsev, id, message);
|
||||
|
|
Loading…
Reference in a new issue