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:
authorClément Foucault <foucault.clem@gmail.com>2020-06-22 20:57:53 +0300
committerClément Foucault <foucault.clem@gmail.com>2020-06-22 20:57:53 +0300
commit15dda0115c783805753119984decb4d9249b1f01 (patch)
treec2d674f83d02edd6eb694c2510dbe1aaff510fe7 /source/blender/editors/interface/interface_widgets.c
parent3cea42ce29cb986cf9614d9b712d72915d52e546 (diff)
UI: Widget: Replace geometry by fragment shader drawing
This means all the antiailasing is done inside the fragment shader. We use a Signed Distance Field to draw the 2D rounded boxes. This ensure the best quality for AA. This reduce the averge Batch for widget to 16 verts instead of ~600 and reduce overshading a lot. Theme Emboss alpha and tria alpha needs to be changed after this refactor. The shadow drawing is left unchanged and still use geometry. Reviewed By: Severin Differential Revision: https://developer.blender.org/D7833
Diffstat (limited to 'source/blender/editors/interface/interface_widgets.c')
-rw-r--r--source/blender/editors/interface/interface_widgets.c250
1 files changed, 32 insertions, 218 deletions
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 0498b312618..16a5a13885b 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -393,35 +393,14 @@ static const uint g_shape_preset_hold_action_face[2][3] = {{2, 0, 1}, {3, 5, 4}}
*
* \{ */
-/* offset in triavec[] in shader per type */
-static const int tria_ofs[ROUNDBOX_TRIA_MAX] = {
- [ROUNDBOX_TRIA_NONE] = 0,
- [ROUNDBOX_TRIA_ARROWS] = 0,
- [ROUNDBOX_TRIA_SCROLL] = 12,
- [ROUNDBOX_TRIA_MENU] = 28,
- [ROUNDBOX_TRIA_CHECK] = 34,
- [ROUNDBOX_TRIA_HOLD_ACTION_ARROW] = 40,
-};
-static const int tria_vcount[ROUNDBOX_TRIA_MAX] = {
- [ROUNDBOX_TRIA_NONE] = 0,
- [ROUNDBOX_TRIA_ARROWS] = 6,
- [ROUNDBOX_TRIA_SCROLL] = 16,
- [ROUNDBOX_TRIA_MENU] = 6,
- [ROUNDBOX_TRIA_CHECK] = 6,
- [ROUNDBOX_TRIA_HOLD_ACTION_ARROW] = 3,
-};
-
static struct {
- GPUBatch *roundbox_widget[ROUNDBOX_TRIA_MAX];
-
- GPUBatch *roundbox_simple;
- GPUBatch *roundbox_simple_aa;
- GPUBatch *roundbox_simple_outline;
+ GPUBatch *roundbox_widget;
GPUBatch *roundbox_shadow;
+ /* TODO remove */
GPUVertFormat format;
uint vflag_id;
-} g_ui_batch_cache = {{0}};
+} g_ui_batch_cache = {0};
static GPUVertFormat *vflag_format(void)
{
@@ -436,7 +415,7 @@ static GPUVertFormat *vflag_format(void)
#define INNER 0
#define OUTLINE 1
#define EMBOSS 2
-#define NO_AA WIDGET_AA_JITTER
+#define NO_AA 0
static void set_roundbox_vertex_data(GPUVertBufRaw *vflag_step, uint32_t d)
{
@@ -462,176 +441,30 @@ static uint32_t set_roundbox_vertex(GPUVertBufRaw *vflag_step,
return *data;
}
-static uint32_t set_tria_vertex(
- GPUVertBufRaw *vflag_step, int tria_type, int tria_v, int tria_id, int jit_v)
-{
- uint32_t *data = GPU_vertbuf_raw_step(vflag_step);
- if (ELEM(tria_type, ROUNDBOX_TRIA_ARROWS)) {
- tria_v += tria_id * tria_vcount[ROUNDBOX_TRIA_ARROWS];
- }
- *data = tria_ofs[tria_type] + tria_v;
- *data |= jit_v << 6;
- *data |= (tria_id == 0) ? (1 << 10) : 0; /* is first tria */
- *data |= 1 << 14; /* is tria vert */
- return *data;
-}
-
-static void roundbox_batch_add_tria(GPUVertBufRaw *vflag_step, int tria, uint32_t last_data)
+GPUBatch *ui_batch_roundbox_widget_get(void)
{
- const int tria_num =
- ELEM(tria, ROUNDBOX_TRIA_CHECK, ROUNDBOX_TRIA_HOLD_ACTION_ARROW, ROUNDBOX_TRIA_MENU) ? 1 : 2;
- /* for each tria */
- for (int t = 0; t < tria_num; t++) {
- for (int j = 0; j < WIDGET_AA_JITTER; j++) {
- /* restart */
- set_roundbox_vertex_data(vflag_step, last_data);
- set_tria_vertex(vflag_step, tria, 0, t, j);
- for (int v = 0; v < tria_vcount[tria]; v++) {
- last_data = set_tria_vertex(vflag_step, tria, v, t, j);
- }
- }
- }
-}
-
-GPUBatch *ui_batch_roundbox_widget_get(int tria)
-{
- if (g_ui_batch_cache.roundbox_widget[tria] == NULL) {
- uint32_t last_data;
- GPUVertBufRaw vflag_step;
+ if (g_ui_batch_cache.roundbox_widget == NULL) {
GPUVertBuf *vbo = GPU_vertbuf_create_with_format(vflag_format());
- int vcount = WIDGET_SIZE_MAX; /* inner */
- vcount += 2; /* restart */
- vcount += ((WIDGET_SIZE_MAX + 1) * 2) * WIDGET_AA_JITTER; /* outline (edges) */
- vcount += 2; /* restart */
- vcount += ((WIDGET_CURVE_RESOLU * 2) * 2) * WIDGET_AA_JITTER; /* emboss */
- if (tria) {
- vcount += (tria_vcount[tria] + 2) * WIDGET_AA_JITTER; /* tria1 */
- if (!ELEM(tria, ROUNDBOX_TRIA_CHECK, ROUNDBOX_TRIA_HOLD_ACTION_ARROW, ROUNDBOX_TRIA_MENU)) {
- vcount += (tria_vcount[tria] + 2) * WIDGET_AA_JITTER; /* tria2 */
- }
- }
- GPU_vertbuf_data_alloc(vbo, vcount);
- GPU_vertbuf_attr_get_raw_data(vbo, g_ui_batch_cache.vflag_id, &vflag_step);
- /* Inner */
- for (int c1 = 0, c2 = 3; c1 < 2; c1++, c2--) {
- for (int a1 = 0, a2 = WIDGET_CURVE_RESOLU - 1; a2 >= 0; a1++, a2--) {
- last_data = set_roundbox_vertex(&vflag_step, c1, a1, NO_AA, true, false, INNER);
- last_data = set_roundbox_vertex(&vflag_step, c2, a2, NO_AA, true, false, INNER);
- }
- }
- /* restart */
- set_roundbox_vertex_data(&vflag_step, last_data);
- set_roundbox_vertex(&vflag_step, 0, 0, 0, true, false, OUTLINE);
- /* Outlines */
- for (int j = 0; j < WIDGET_AA_JITTER; j++) {
- for (int c = 0; c < 4; c++) {
- for (int a = 0; a < WIDGET_CURVE_RESOLU; a++) {
- set_roundbox_vertex(&vflag_step, c, a, j, true, false, OUTLINE);
- set_roundbox_vertex(&vflag_step, c, a, j, false, false, OUTLINE);
- }
- }
- /* Close the loop. */
- set_roundbox_vertex(&vflag_step, 0, 0, j, true, false, OUTLINE);
- last_data = set_roundbox_vertex(&vflag_step, 0, 0, j, false, false, OUTLINE);
- }
- /* restart */
- set_roundbox_vertex_data(&vflag_step, last_data);
- set_roundbox_vertex(&vflag_step, 0, 0, 0, false, false, EMBOSS);
- /* Emboss */
- /* go back and forth : avoid degenerate triangle (but beware of backface cull) */
- bool rev = false;
- for (int j = 0; j < WIDGET_AA_JITTER; j++, rev = !rev) {
- for (int c = (rev) ? 1 : 0; (rev) ? c >= 0 : c < 2; (rev) ? c-- : c++) {
- int sta = (rev) ? WIDGET_CURVE_RESOLU - 1 : 0;
- int end = WIDGET_CURVE_RESOLU;
- for (int a = sta; (rev) ? a >= 0 : a < end; (rev) ? a-- : a++) {
- set_roundbox_vertex(&vflag_step, c, a, j, false, false, EMBOSS);
- last_data = set_roundbox_vertex(&vflag_step, c, a, j, false, true, EMBOSS);
- }
- }
- }
- if (tria) {
- roundbox_batch_add_tria(&vflag_step, tria, last_data);
- }
- g_ui_batch_cache.roundbox_widget[tria] = GPU_batch_create_ex(
- GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO);
- gpu_batch_presets_register(g_ui_batch_cache.roundbox_widget[tria]);
- }
- return g_ui_batch_cache.roundbox_widget[tria];
-}
-GPUBatch *ui_batch_roundbox_get(bool filled, bool antialiased)
-{
- GPUBatch **batch = NULL;
+ GPU_vertbuf_data_alloc(vbo, 12);
- if (filled) {
- if (antialiased) {
- batch = &g_ui_batch_cache.roundbox_simple_aa;
- }
- else {
- batch = &g_ui_batch_cache.roundbox_simple;
- }
- }
- else {
- if (antialiased) {
- BLI_assert(0); /* Use GL_LINE_SMOOTH instead!!: */
- }
- else {
- batch = &g_ui_batch_cache.roundbox_simple_outline;
- }
- }
+ GPUIndexBufBuilder ibuf;
+ GPU_indexbuf_init(&ibuf, GPU_PRIM_TRIS, 6, 12);
+ /* Widget */
+ GPU_indexbuf_add_tri_verts(&ibuf, 0, 1, 2);
+ GPU_indexbuf_add_tri_verts(&ibuf, 2, 1, 3);
+ /* Trias */
+ GPU_indexbuf_add_tri_verts(&ibuf, 4, 5, 6);
+ GPU_indexbuf_add_tri_verts(&ibuf, 6, 5, 7);
- if (*batch == NULL) {
- uint32_t last_data;
- GPUVertBufRaw vflag_step;
- GPUVertBuf *vbo = GPU_vertbuf_create_with_format(vflag_format());
- int vcount = WIDGET_SIZE_MAX;
- vcount += (filled) ? 2 : 0;
- vcount *= (antialiased) ? WIDGET_AA_JITTER : 1;
- GPU_vertbuf_data_alloc(vbo, vcount);
- GPU_vertbuf_attr_get_raw_data(vbo, g_ui_batch_cache.vflag_id, &vflag_step);
+ GPU_indexbuf_add_tri_verts(&ibuf, 8, 9, 10);
+ GPU_indexbuf_add_tri_verts(&ibuf, 10, 9, 11);
- if (filled) {
- for (int j = 0; j < WIDGET_AA_JITTER; j++) {
- if (!antialiased) {
- j = NO_AA;
- }
- /* restart */
- set_roundbox_vertex(&vflag_step, 0, 0, j, true, false, INNER);
- for (int c1 = 0, c2 = 3; c1 < 2; c1++, c2--) {
- for (int a1 = 0, a2 = WIDGET_CURVE_RESOLU - 1; a2 >= 0; a1++, a2--) {
- last_data = set_roundbox_vertex(&vflag_step, c1, a1, j, true, false, INNER);
- last_data = set_roundbox_vertex(&vflag_step, c2, a2, j, true, false, INNER);
- }
- }
- /* restart */
- set_roundbox_vertex_data(&vflag_step, last_data);
- if (!antialiased) {
- break;
- }
- }
- *batch = GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO);
- }
- else {
- for (int j = 0; j < WIDGET_AA_JITTER; j++) {
- if (!antialiased) {
- j = NO_AA;
- }
- for (int c = 0; c < 4; c++) {
- for (int a = 0; a < WIDGET_CURVE_RESOLU; a++) {
- set_roundbox_vertex(&vflag_step, c, a, j, true, false, INNER);
- }
- }
- if (!antialiased) {
- break;
- }
- }
- *batch = GPU_batch_create_ex(GPU_PRIM_LINE_LOOP, vbo, NULL, GPU_BATCH_OWNS_VBO);
- }
-
- gpu_batch_presets_register(*batch);
+ g_ui_batch_cache.roundbox_widget = GPU_batch_create_ex(
+ GPU_PRIM_TRIS, vbo, GPU_indexbuf_build(&ibuf), GPU_BATCH_OWNS_INDEX | GPU_BATCH_OWNS_VBO);
+ gpu_batch_presets_register(g_ui_batch_cache.roundbox_widget);
}
- return *batch;
+ return g_ui_batch_cache.roundbox_widget;
}
GPUBatch *ui_batch_roundbox_shadow_get(void)
@@ -1314,14 +1147,13 @@ static void widgetbase_set_uniform_colors_ubv(uiWidgetBase *wtb,
/* keep in sync with shader */
#define MAX_WIDGET_BASE_BATCH 6
-#define MAX_WIDGET_PARAMETERS 11
+#define MAX_WIDGET_PARAMETERS 12
static struct {
- GPUBatch *batch; /* Batch type */
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH];
int count;
bool enabled;
-} g_widget_base_batch = {0};
+} g_widget_base_batch = {{{{0}}}};
void UI_widgetbase_draw_cache_flush(void)
{
@@ -1332,7 +1164,7 @@ void UI_widgetbase_draw_cache_flush(void)
return;
}
- GPUBatch *batch = g_widget_base_batch.batch;
+ GPUBatch *batch = ui_batch_roundbox_widget_get();
if (g_widget_base_batch.count == 1) {
/* draw single */
GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
@@ -1376,31 +1208,15 @@ void UI_widgetbase_draw_cache_end(void)
GPU_blend(false);
}
-static void draw_widgetbase_batch(GPUBatch *batch, uiWidgetBase *wtb)
+static void draw_widgetbase_batch(uiWidgetBase *wtb)
{
+ wtb->uniform_params.tria_type = wtb->tria1.type;
wtb->uniform_params.tria1_size = wtb->tria1.size;
wtb->uniform_params.tria2_size = wtb->tria2.size;
copy_v2_v2(wtb->uniform_params.tria1_center, wtb->tria1.center);
copy_v2_v2(wtb->uniform_params.tria2_center, wtb->tria2.center);
if (g_widget_base_batch.enabled) {
- if (g_widget_base_batch.batch == NULL) {
- g_widget_base_batch.batch = ui_batch_roundbox_widget_get(ROUNDBOX_TRIA_ARROWS);
- }
-
- /* draw multi */
- if (batch != g_ui_batch_cache.roundbox_widget[ROUNDBOX_TRIA_NONE] &&
- batch != g_widget_base_batch.batch) {
- /* issue previous calls before changing batch type. */
- UI_widgetbase_draw_cache_flush();
- g_widget_base_batch.batch = batch;
- }
-
- /* No need to change batch if tria is not visible. Just scale it to 0. */
- if (batch == g_ui_batch_cache.roundbox_widget[ROUNDBOX_TRIA_NONE]) {
- wtb->uniform_params.tria1_size = wtb->uniform_params.tria2_size = 0;
- }
-
g_widget_base_batch.params[g_widget_base_batch.count] = wtb->uniform_params;
g_widget_base_batch.count++;
@@ -1412,6 +1228,7 @@ static void draw_widgetbase_batch(GPUBatch *batch, uiWidgetBase *wtb)
const float checker_params[3] = {
UI_ALPHA_CHECKER_DARK / 255.0f, UI_ALPHA_CHECKER_LIGHT / 255.0f, 8.0f};
/* draw single */
+ GPUBatch *batch = ui_batch_roundbox_widget_get();
GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
GPU_batch_uniform_4fv_array(
batch, "parameters", MAX_WIDGET_PARAMETERS, (float *)&wtb->uniform_params);
@@ -1434,8 +1251,6 @@ static void widgetbase_draw_ex(uiWidgetBase *wtb,
show_alpha_checkers = false;
}
- GPU_blend(true);
-
/* backdrop non AA */
if (wtb->draw_inner) {
if (wcol->shaded == 0) {
@@ -1455,7 +1270,7 @@ static void widgetbase_draw_ex(uiWidgetBase *wtb,
outline_col[0] = wcol->outline[0];
outline_col[1] = wcol->outline[1];
outline_col[2] = wcol->outline[2];
- outline_col[3] = wcol->outline[3] / WIDGET_AA_JITTER;
+ outline_col[3] = wcol->outline[3];
/* emboss bottom shadow */
if (wtb->draw_emboss) {
@@ -1467,7 +1282,7 @@ static void widgetbase_draw_ex(uiWidgetBase *wtb,
tria_col[0] = wcol->item[0];
tria_col[1] = wcol->item[1];
tria_col[2] = wcol->item[2];
- tria_col[3] = (uchar)((float)wcol->item[3] / WIDGET_AA_JITTER);
+ tria_col[3] = wcol->item[3];
}
/* Draw everything in one drawcall */
@@ -1476,11 +1291,10 @@ static void widgetbase_draw_ex(uiWidgetBase *wtb,
widgetbase_set_uniform_colors_ubv(
wtb, inner_col1, inner_col2, outline_col, emboss_col, tria_col, show_alpha_checkers);
- GPUBatch *roundbox_batch = ui_batch_roundbox_widget_get(wtb->tria1.type);
- draw_widgetbase_batch(roundbox_batch, wtb);
+ GPU_blend(true);
+ draw_widgetbase_batch(wtb);
+ GPU_blend(false);
}
-
- GPU_blend(false);
}
static void widgetbase_draw(uiWidgetBase *wtb, const uiWidgetColors *wcol)