diff options
-rw-r--r-- | source/blender/blenfont/intern/blf_font.c | 11 | ||||
-rw-r--r-- | source/blender/blenfont/intern/blf_glyph.c | 55 | ||||
-rw-r--r-- | source/blender/blenfont/intern/blf_internal_types.h | 9 | ||||
-rw-r--r-- | source/blender/gpu/GPU_texture.h | 21 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_texture.c | 101 |
5 files changed, 142 insertions, 55 deletions
diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c index 1289dc6c5a6..13c857b0d4b 100644 --- a/source/blender/blenfont/intern/blf_font.c +++ b/source/blender/blenfont/intern/blf_font.c @@ -183,16 +183,13 @@ void blf_batch_draw(void) if (g_batch.glyph_len == 0) return; - glEnable(GL_BLEND); - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + GPU_blend(true); + GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); /* We need to flush widget base first to ensure correct ordering. */ UI_widgetbase_draw_cache_flush(); - BLI_assert(g_batch.tex_bind_state != 0); /* must still be valid */ - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, g_batch.tex_bind_state); - + GPU_texture_bind(g_batch.tex_bind_state, 0); GWN_vertbuf_vertex_count_set(g_batch.verts, g_batch.glyph_len); GWN_vertbuf_use(g_batch.verts); /* send data */ @@ -201,7 +198,7 @@ void blf_batch_draw(void) GWN_batch_uniform_1i(g_batch.batch, "glyph", 0); GWN_batch_draw(g_batch.batch); - glDisable(GL_BLEND); + GPU_blend(false); /* restart to 1st vertex data pointers */ GWN_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.pos_loc, &g_batch.pos_step); diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c index 5a87c726566..02d166739ec 100644 --- a/source/blender/blenfont/intern/blf_glyph.c +++ b/source/blender/blenfont/intern/blf_glyph.c @@ -57,6 +57,7 @@ #ifndef BLF_STANDALONE # include "GPU_immediate.h" +# include "GPU_extensions.h" #endif #include "blf_internal_types.h" @@ -146,7 +147,7 @@ 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 = (GLuint *)MEM_mallocN(sizeof(GLuint) * 256, __func__); + 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 */ @@ -196,16 +197,17 @@ void blf_glyph_cache_clear(FontBLF *font) void blf_glyph_cache_free(GlyphCacheBLF *gc) { GlyphBLF *g; - int i; + unsigned int i; for (i = 0; i < 257; i++) { while ((g = BLI_pophead(&gc->bucket[i]))) { blf_glyph_free(g); } } - - if (gc->texture_current != BLF_TEXTURE_UNSET) { - glDeleteTextures((int)gc->texture_current + 1, gc->textures); + for (i = 0; i < gc->textures_len; i++) { + if (gc->textures[i]) { + GPU_texture_free(gc->textures[i]); + } } MEM_freeN(gc->textures); MEM_freeN(gc); @@ -214,13 +216,14 @@ void blf_glyph_cache_free(GlyphCacheBLF *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_reallocN((void *)gc->textures, sizeof(GLuint) * gc->textures_len); + 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))); @@ -235,16 +238,12 @@ static void blf_glyph_cache_texture(FontBLF *font, GlyphCacheBLF *gc) gc->p2_height = font->tex_size_max; } - glGenTextures(1, &gc->textures[gc->texture_current]); - glBindTexture(GL_TEXTURE_2D, (font->tex_bind_state = gc->textures[gc->texture_current])); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - - unsigned char *pixels = MEM_callocN((size_t)gc->p2_width * (size_t)gc->p2_height, "BLF texture init"); - glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, gc->p2_width, gc->p2_height, 0, GL_RED, GL_UNSIGNED_BYTE, pixels); - MEM_freeN(pixels); + GPUTexture *tex = GPU_texture_create_2D(gc->p2_width, gc->p2_height, GPU_R8, NULL, error);; + gc->textures[gc->texture_current] = tex; + GPU_texture_bind(tex, 0); + GPU_texture_wrap_mode(tex, false); + GPU_texture_filters(tex, GPU_NEAREST, GPU_LINEAR); + GPU_texture_unbind(tex); } GlyphBLF *blf_glyph_search(GlyphCacheBLF *gc, unsigned int c) @@ -437,13 +436,11 @@ void blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y) if ((!g->width) || (!g->height)) return; - glActiveTexture(GL_TEXTURE0); - if (g->build_tex == 0) { GlyphCacheBLF *gc = font->glyph_cache; if (font->tex_size_max == -1) - glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *)&font->tex_size_max); + font->tex_size_max = GPU_max_texture_size(); if (gc->texture_current == BLF_TEXTURE_UNSET) { blf_glyph_cache_texture(font, gc); @@ -477,22 +474,7 @@ void blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y) BLI_assert(g->height > 0); } - - GLint lsb_first, row_length, alignment; - glGetIntegerv(GL_UNPACK_LSB_FIRST, &lsb_first); - glGetIntegerv(GL_UNPACK_ROW_LENGTH, &row_length); - glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment); - - glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE); - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - - glBindTexture(GL_TEXTURE_2D, g->tex); - glTexSubImage2D(GL_TEXTURE_2D, 0, g->offset_x, g->offset_y, g->width, g->height, GL_RED, GL_UNSIGNED_BYTE, g->bitmap); - - glPixelStorei(GL_UNPACK_LSB_FIRST, lsb_first); - glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length); - glPixelStorei(GL_UNPACK_ALIGNMENT, alignment); + GPU_texture_update_sub(g->tex, g->bitmap, g->offset_x, g->offset_y, 0, g->width, g->height, 0); g->uv[0][0] = ((float)g->offset_x) / ((float)gc->p2_width); g->uv[0][1] = ((float)g->offset_y) / ((float)gc->p2_height); @@ -520,7 +502,8 @@ void blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y) if (font->tex_bind_state != g->tex) { blf_batch_draw(); - glBindTexture(GL_TEXTURE_2D, (font->tex_bind_state = g->tex)); + font->tex_bind_state = g->tex; + GPU_texture_bind(font->tex_bind_state, 0); } g_batch.tex_bind_state = g->tex; diff --git a/source/blender/blenfont/intern/blf_internal_types.h b/source/blender/blenfont/intern/blf_internal_types.h index d7b526735d1..a8ed10bc0bc 100644 --- a/source/blender/blenfont/intern/blf_internal_types.h +++ b/source/blender/blenfont/intern/blf_internal_types.h @@ -32,6 +32,7 @@ #define __BLF_INTERNAL_TYPES_H__ #include "../../../intern/gawain/gawain/gwn_vertex_buffer.h" +#include "GPU_texture.h" #define BLF_BATCH_DRAW_LEN_MAX 2048 /* in glyph */ @@ -45,7 +46,7 @@ typedef struct BatchBLF { float ofs[2]; /* copy of font->pos */ float mat[4][4]; /* previous call modelmatrix. */ bool enabled, active, simple_shader; - unsigned int tex_bind_state; + GPUTexture *tex_bind_state; } BatchBLF; extern BatchBLF g_batch; @@ -78,7 +79,7 @@ typedef struct GlyphCacheBLF { struct GlyphBLF *glyph_ascii_table[256]; /* texture array, to draw the glyphs. */ - unsigned int *textures; + GPUTexture **textures; /* size of the array. */ unsigned int textures_len; @@ -133,7 +134,7 @@ typedef struct GlyphBLF { int advance_i; /* texture id where this glyph is store. */ - unsigned int tex; + GPUTexture* tex; /* position inside the texture where this glyph is store. */ int offset_x; @@ -244,7 +245,7 @@ typedef struct FontBLF { int tex_size_max; /* cache current OpenGL texture to save calls into the API */ - unsigned int tex_bind_state; + GPUTexture *tex_bind_state; /* font options. */ int flags; diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h index e53693e7b40..3ab270f9064 100644 --- a/source/blender/gpu/GPU_texture.h +++ b/source/blender/gpu/GPU_texture.h @@ -142,6 +142,19 @@ typedef enum GPUTextureFormat { GPU_DEPTH_COMPONENT16, } GPUTextureFormat; +/* These map directly to the GL_ blend functions, to minimize API add as needed*/ +typedef enum GPUBlendFunction { + GPU_ONE, + GPU_SRC_ALPHA, + GPU_ONE_MINUS_SRC_ALPHA +} GPUBlendFunction; + +/* These map directly to the GL_ filter functions, to minimize API add as needed*/ +typedef enum GPUFilterFunction { + GPU_NEAREST, + GPU_LINEAR +} GPUFilterFunction; + unsigned int GPU_texture_memory_usage_get(void); GPUTexture *GPU_texture_create_1D( @@ -166,7 +179,8 @@ GPUTexture *GPU_texture_from_blender( struct Image *ima, struct ImageUser *iuser, int textarget, bool is_data, double time); GPUTexture *GPU_texture_from_preview(struct PreviewImage *prv, int mipmap); -void GPU_texture_update(GPUTexture *tex, const float *pixels); +void GPU_texture_update(GPUTexture *tex, const void *pixels); +void GPU_texture_update_sub(GPUTexture *tex, const void *pixels, int offset_x, int offset_y, int offset_z, int width, int height, int depth); void GPU_invalid_tex_init(void); void GPU_invalid_tex_bind(int mode); @@ -189,6 +203,7 @@ void GPU_texture_compare_mode(GPUTexture *tex, bool use_compare); void GPU_texture_filter_mode(GPUTexture *tex, bool use_filter); void GPU_texture_mipmap_mode(GPUTexture *tex, bool use_mipmap, bool use_filter); void GPU_texture_wrap_mode(GPUTexture *tex, bool use_repeat); +void GPU_texture_filters(GPUTexture *tex, GPUFilterFunction min_filter, GPUFilterFunction mag_filter); void GPU_texture_attach_framebuffer(GPUTexture *tex, struct GPUFrameBuffer *fb, int attachment); int GPU_texture_detach_framebuffer(GPUTexture *tex, struct GPUFrameBuffer *fb); @@ -204,6 +219,10 @@ bool GPU_texture_stencil(const GPUTexture *tex); bool GPU_texture_integer(const GPUTexture *tex); int GPU_texture_opengl_bindcode(const GPUTexture *tex); +void GPU_blend(bool enable); +void GPU_blend_set_func_separate(GPUBlendFunction src_rgb, GPUBlendFunction dst_rgb, GPUBlendFunction src_alpha, GPUBlendFunction dst_alpha); +void GPU_blend_set_func(GPUBlendFunction sfactor, GPUBlendFunction dfactor); + #ifdef __cplusplus } #endif diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c index ee00a1381f4..8c66b67a869 100644 --- a/source/blender/gpu/intern/gpu_texture.c +++ b/source/blender/gpu/intern/gpu_texture.c @@ -171,6 +171,10 @@ static GLenum gpu_texture_get_format( default: break; } } + else if (ELEM(data_type, GPU_R8)) { + *data_format = GL_UNSIGNED_BYTE; + *format = GL_RED; + } else { *data_format = GL_FLOAT; *format_flag |= GPU_FORMAT_FLOAT; @@ -882,37 +886,52 @@ GPUTexture *GPU_texture_create_from_vertbuf(Gwn_VertBuf *vert) return GPU_texture_create_buffer(data_type, vert->vbo_id); } -void GPU_texture_update(GPUTexture *tex, const float *pixels) +void GPU_texture_update_sub(GPUTexture *tex, const void *pixels, int offset_x, int offset_y, int offset_z, int width, int height, int depth) { BLI_assert(tex->format > -1); BLI_assert(tex->components > -1); - + GLenum format, data_format; + GLint alignment; gpu_texture_get_format(tex->components, tex->format, &format, &data_format, - &tex->format_flag, &tex->bytesize); + &tex->format_flag, &tex->bytesize); - glBindTexture(tex->target, tex->bindcode); + /* The default pack size for textures is 4, which won't work for byte based textures */ + if (tex->bytesize == 1) { + glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + } + glBindTexture(tex->target, tex->bindcode); switch (tex->target) { case GL_TEXTURE_2D: case GL_TEXTURE_2D_MULTISAMPLE: case GL_TEXTURE_1D_ARRAY: - glTexSubImage2D(tex->target, 0, 0, 0, tex->w, tex->h, format, data_format, pixels); + glTexSubImage2D(tex->target, 0, offset_x, offset_y, width, height, format, data_format, pixels); break; case GL_TEXTURE_1D: - glTexSubImage1D(tex->target, 0, 0, tex->w, format, data_format, pixels); + glTexSubImage1D(tex->target, 0, offset_x, width, format, data_format, pixels); break; case GL_TEXTURE_3D: case GL_TEXTURE_2D_ARRAY: - glTexSubImage3D(tex->target, 0, 0, 0, 0, tex->w, tex->h, tex->d, format, data_format, pixels); + glTexSubImage3D(tex->target, 0, offset_x, offset_y, offset_z, width, height, depth, format, data_format, pixels); break; default: BLI_assert(!"tex->target mode not supported"); + } + + if (tex->bytesize == 1) { + glPixelStorei(GL_UNPACK_ALIGNMENT, alignment); } glBindTexture(tex->target, 0); } +void GPU_texture_update(GPUTexture *tex, const void *pixels) +{ + GPU_texture_update_sub(tex, pixels, 0, 0, 0, tex->w, tex->h, tex->d); +} + void GPU_invalid_tex_init(void) { memory_usage = 0; @@ -1068,6 +1087,34 @@ void GPU_texture_wrap_mode(GPUTexture *tex, bool use_repeat) glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, repeat); } +static GLenum gpu_get_gl_filterfunction(GPUFilterFunction filter) +{ + switch (filter) + { + case GPU_NEAREST: + return GL_NEAREST; + case GPU_LINEAR: + return GL_LINEAR; + default: + BLI_assert(!"Unhandled filter mode"); + return GL_NEAREST; + } +} + +void GPU_texture_filters(GPUTexture *tex, GPUFilterFunction min_filter, GPUFilterFunction mag_filter) +{ + WARN_NOT_BOUND(tex); + + /* Stencil and integer format does not support filtering. */ + BLI_assert(!(GPU_texture_stencil(tex) || GPU_texture_integer(tex))); + BLI_assert(mag_filter == GPU_NEAREST || mag_filter == GPU_LINEAR); + + glActiveTexture(GL_TEXTURE0 + tex->number); + glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, gpu_get_gl_filterfunction(min_filter)); + glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, gpu_get_gl_filterfunction(mag_filter)); +} + + static void gpu_texture_delete(GPUTexture *tex) { if (tex->bindcode) @@ -1207,3 +1254,43 @@ int GPU_texture_detach_framebuffer(GPUTexture *tex, GPUFrameBuffer *fb) BLI_assert(!"Error: Texture: Framebuffer is not attached"); return 0; } + +void GPU_blend(bool enable) +{ + if (enable) { + glEnable(GL_BLEND); + } + else { + glDisable(GL_BLEND); + } +} + +static GLenum gpu_get_gl_blendfunction(GPUBlendFunction blend) +{ + switch (blend) + { + case GPU_ONE: + return GL_ONE; + case GPU_SRC_ALPHA: + return GL_SRC_ALPHA; + case GPU_ONE_MINUS_SRC_ALPHA: + return GL_ONE_MINUS_SRC_ALPHA; + default: + BLI_assert(!"Unhandled blend mode"); + return GL_ZERO; + } +} + +void GPU_blend_set_func_separate(GPUBlendFunction src_rgb, GPUBlendFunction dst_rgb, GPUBlendFunction src_alpha, GPUBlendFunction dst_alpha) +{ + glBlendFuncSeparate(gpu_get_gl_blendfunction(src_rgb), + gpu_get_gl_blendfunction(dst_rgb), + gpu_get_gl_blendfunction(src_alpha), + gpu_get_gl_blendfunction(dst_alpha)); +} + +void GPU_blend_set_func(GPUBlendFunction sfactor, GPUBlendFunction dfactor) +{ + glBlendFunc(gpu_get_gl_blendfunction(sfactor), gpu_get_gl_blendfunction(dfactor)); +} + |