diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/editors/include/UI_interface_icons.h | 3 | ||||
-rw-r--r-- | source/blender/editors/interface/interface.c | 3 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_icons.c | 107 | ||||
-rw-r--r-- | source/blender/gpu/CMakeLists.txt | 2 | ||||
-rw-r--r-- | source/blender/gpu/GPU_shader.h | 1 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_shader.c | 4 | ||||
-rw-r--r-- | source/blender/gpu/shaders/gpu_shader_2D_image_multi_rect_vert.glsl | 48 | ||||
-rw-r--r-- | source/blender/gpu/shaders/gpu_shader_image_varying_color_frag.glsl | 11 |
8 files changed, 178 insertions, 1 deletions
diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h index cee68ed361c..8b436942fdd 100644 --- a/source/blender/editors/include/UI_interface_icons.h +++ b/source/blender/editors/include/UI_interface_icons.h @@ -77,6 +77,9 @@ void UI_icon_draw_size(float x, float y, int size, int icon_id, float alpha); void UI_icons_free(void); void UI_icons_free_drawinfo(void *drawinfo); +void UI_icon_draw_cache_begin(void); +void UI_icon_draw_cache_end(void); + struct ListBase *UI_iconfile_list(void); int UI_iconfile_get_index(const char *filename); diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 0050340d842..0c786874180 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -64,6 +64,7 @@ #include "BLT_translation.h" #include "UI_interface.h" +#include "UI_interface_icons.h" #include "IMB_imbuf.h" @@ -1427,6 +1428,7 @@ void UI_block_draw(const bContext *C, uiBlock *block) ui_draw_aligned_panel(&style, block, &rect, UI_panel_category_is_visible(ar)); BLF_batch_draw_begin(); + UI_icon_draw_cache_begin(); /* widgets */ for (but = block->buttons.first; but; but = but->next) { @@ -1440,6 +1442,7 @@ void UI_block_draw(const bContext *C, uiBlock *block) } } + UI_icon_draw_cache_end(); BLF_batch_draw_end(); /* restore matrix */ diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index eca8273ee3a..bcc6c40a9e7 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -34,11 +34,13 @@ #include "MEM_guardedalloc.h" #include "GPU_draw.h" +#include "GPU_matrix.h" #include "GPU_immediate.h" #include "BLI_blenlib.h" #include "BLI_utildefines.h" #include "BLI_fileops_types.h" +#include "BLI_math_vector.h" #include "DNA_brush_types.h" #include "DNA_curve_types.h" @@ -1016,10 +1018,113 @@ static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect), IMB_freeImBuf(ima); } -static void icon_draw_texture( +/* High enough to make a difference, low enough so that + * small draws are still efficient with the use of glUniform. + * NOTE TODO: We could use UBO but we would need some triple + * buffer system + persistent mapping for this to be more + * efficient than simple glUniform calls. */ +#define ICON_DRAW_CACHE_SIZE 16 + +typedef struct IconDrawCall{ + rctf pos; + rctf tex; + float color[4]; +} IconDrawCall; + +static struct { + IconDrawCall drawcall_cache[ICON_DRAW_CACHE_SIZE]; + int calls; /* Number of calls batched together */ + bool enabled; + float mat[4][4]; +} g_icon_draw_cache = {0}; + +void UI_icon_draw_cache_begin(void) +{ + BLI_assert(g_icon_draw_cache.enabled == false); + g_icon_draw_cache.enabled = true; +} + +static void icon_draw_cache_flush_ex(void) +{ + if (g_icon_draw_cache.calls == 0) + return; + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, icongltex.id); + + GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR); + GPU_shader_bind(shader); + + int img_loc = GPU_shader_get_uniform(shader, "image"); + int data_loc = GPU_shader_get_uniform(shader, "calls_data[0]"); + + glUniform1i(img_loc, 0); + glUniform4fv(data_loc, ICON_DRAW_CACHE_SIZE * 3, (float *)g_icon_draw_cache.drawcall_cache); + + GWN_draw_primitive(GWN_PRIM_TRIS, 6 * g_icon_draw_cache.calls); + + glBindTexture(GL_TEXTURE_2D, 0); + + g_icon_draw_cache.calls = 0; +} + +void UI_icon_draw_cache_end(void) +{ + BLI_assert(g_icon_draw_cache.enabled == true); + g_icon_draw_cache.enabled = false; + + /* Don't change blend state if it's not needed. */ + if (g_icon_draw_cache.calls == 0) + return; + + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + + icon_draw_cache_flush_ex(); + + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_BLEND); +} + +static void icon_draw_texture_cached( float x, float y, float w, float h, int ix, int iy, int UNUSED(iw), int ih, float alpha, const float rgb[3]) { + + float mvp[4][4]; + gpuGetModelViewProjectionMatrix(mvp); + + IconDrawCall *call = &g_icon_draw_cache.drawcall_cache[g_icon_draw_cache.calls]; + g_icon_draw_cache.calls++; + + /* Manual mat4*vec2 */ + call->pos.xmin = x * mvp[0][0] + y * mvp[1][0] + mvp[3][0]; + call->pos.ymin = x * mvp[0][1] + y * mvp[1][1] + mvp[3][1]; + call->pos.xmax = call->pos.xmin + w * mvp[0][0] + h * mvp[1][0]; + call->pos.ymax = call->pos.ymin + w * mvp[0][1] + h * mvp[1][1]; + + call->tex.xmin = ix * icongltex.invw; + call->tex.xmax = (ix + ih) * icongltex.invw; + call->tex.ymin = iy * icongltex.invh; + call->tex.ymax = (iy + ih) * icongltex.invh; + + if (rgb) copy_v4_fl4(call->color, rgb[0], rgb[1], rgb[2], alpha); + else copy_v4_fl(call->color, alpha); + + if (g_icon_draw_cache.calls == ICON_DRAW_CACHE_SIZE) { + icon_draw_cache_flush_ex(); + } +} + +static void icon_draw_texture( + float x, float y, float w, float h, int ix, int iy, + int iw, int ih, float alpha, const float rgb[3]) +{ + if (g_icon_draw_cache.enabled) { + icon_draw_texture_cached(x, y, w, h, ix, iy, iw, ih, alpha, rgb); + return; + } + float x1, x2, y1, y2; x1 = ix * icongltex.invw; diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index f0e5b0842fc..b52817c68a8 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -141,6 +141,7 @@ data_to_c_simple(shaders/gpu_shader_2D_smooth_color_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_2D_smooth_color_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_2D_image_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_2D_image_rect_vert.glsl SRC) +data_to_c_simple(shaders/gpu_shader_2D_image_multi_rect_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_image_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_image_linear_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_image_shuffle_color_frag.glsl SRC) @@ -148,6 +149,7 @@ data_to_c_simple(shaders/gpu_shader_image_mask_uniform_color_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_image_modulate_alpha_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_image_alpha_color_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_image_color_frag.glsl SRC) +data_to_c_simple(shaders/gpu_shader_image_varying_color_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_image_depth_linear_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_image_depth_copy_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_image_interlace_frag.glsl SRC) diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h index 1a1ec120d28..5041d524f18 100644 --- a/source/blender/gpu/GPU_shader.h +++ b/source/blender/gpu/GPU_shader.h @@ -116,6 +116,7 @@ typedef enum GPUBuiltinShader { GPU_SHADER_2D_IMAGE_ALPHA_COLOR, GPU_SHADER_2D_IMAGE_ALPHA, GPU_SHADER_2D_IMAGE_RECT_COLOR, + GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR, GPU_SHADER_2D_CHECKER, GPU_SHADER_2D_DIAG_STRIPES, /* for simple 3D drawing */ diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c index ad6331befce..55184418284 100644 --- a/source/blender/gpu/intern/gpu_shader.c +++ b/source/blender/gpu/intern/gpu_shader.c @@ -66,12 +66,14 @@ extern char datatoc_gpu_shader_2D_smooth_color_vert_glsl[]; extern char datatoc_gpu_shader_2D_smooth_color_frag_glsl[]; extern char datatoc_gpu_shader_2D_image_vert_glsl[]; extern char datatoc_gpu_shader_2D_image_rect_vert_glsl[]; +extern char datatoc_gpu_shader_2D_image_multi_rect_vert_glsl[]; extern char datatoc_gpu_shader_2D_widget_base_vert_glsl[]; extern char datatoc_gpu_shader_3D_image_vert_glsl[]; extern char datatoc_gpu_shader_image_frag_glsl[]; extern char datatoc_gpu_shader_image_linear_frag_glsl[]; extern char datatoc_gpu_shader_image_color_frag_glsl[]; +extern char datatoc_gpu_shader_image_varying_color_frag_glsl[]; extern char datatoc_gpu_shader_image_alpha_color_frag_glsl[]; extern char datatoc_gpu_shader_image_shuffle_color_frag_glsl[]; extern char datatoc_gpu_shader_image_interlace_frag_glsl[]; @@ -710,6 +712,8 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader) datatoc_gpu_shader_image_shuffle_color_frag_glsl }, [GPU_SHADER_2D_IMAGE_RECT_COLOR] = { datatoc_gpu_shader_2D_image_rect_vert_glsl, datatoc_gpu_shader_image_color_frag_glsl }, + [GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR] = { datatoc_gpu_shader_2D_image_multi_rect_vert_glsl, + datatoc_gpu_shader_image_varying_color_frag_glsl }, [GPU_SHADER_3D_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl }, [GPU_SHADER_3D_UNIFORM_COLOR_U32] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl }, diff --git a/source/blender/gpu/shaders/gpu_shader_2D_image_multi_rect_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_image_multi_rect_vert.glsl new file mode 100644 index 00000000000..9fdf8ececc5 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_2D_image_multi_rect_vert.glsl @@ -0,0 +1,48 @@ +/** + * Simple shader that just draw multiple icons at the specified locations + * does not need any vertex input (producing less call to immBegin/End) + **/ + +/* Same as ICON_DRAW_CACHE_SIZE */ +#define MAX_CALLS 16 + +uniform vec4 calls_data[MAX_CALLS * 3]; + +out vec2 texCoord_interp; +flat out vec4 finalColor; + +void main() +{ + /* Rendering 2 triangle per icon. */ + int i = gl_VertexID / 6; + int v = gl_VertexID % 6; + + vec4 pos = calls_data[i*3]; + vec4 tex = calls_data[i*3+1]; + finalColor = calls_data[i*3+2]; + + /* TODO Remove this */ + if (v == 2) v = 4; + else if (v == 3) v = 0; + else if (v == 5) v = 2; + + if (v == 0) { + pos.xy = pos.xw; + tex.xy = tex.xw; + } + else if (v == 1) { + pos.xy = pos.xz; + tex.xy = tex.xz; + } + else if (v == 2) { + pos.xy = pos.yw; + tex.xy = tex.yw; + } + else { + pos.xy = pos.yz; + tex.xy = tex.yz; + } + + gl_Position = vec4(pos.xy, 0.0f, 1.0f); + texCoord_interp = tex.xy; +} diff --git a/source/blender/gpu/shaders/gpu_shader_image_varying_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_varying_color_frag.glsl new file mode 100644 index 00000000000..37686092700 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_image_varying_color_frag.glsl @@ -0,0 +1,11 @@ + +in vec2 texCoord_interp; +flat in vec4 finalColor; +out vec4 fragColor; + +uniform sampler2D image; + +void main() +{ + fragColor = texture(image, texCoord_interp) * finalColor; +} |