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:
-rw-r--r--source/blender/blenfont/intern/blf_font.c11
-rw-r--r--source/blender/blenfont/intern/blf_glyph.c55
-rw-r--r--source/blender/blenfont/intern/blf_internal_types.h9
-rw-r--r--source/blender/gpu/GPU_texture.h21
-rw-r--r--source/blender/gpu/intern/gpu_texture.c101
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));
+}
+