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:
authorCampbell Barton <ideasman42@gmail.com>2017-05-03 01:20:11 +0300
committerCampbell Barton <ideasman42@gmail.com>2017-05-03 01:24:50 +0300
commit8b2640f08858f200eda84e19f74ed234a2833eb2 (patch)
treeb310f7a52cfde3fdcb44a73650eebef119beb56e
parent85ca3156fc3539897789871fbb479ebc6e442fbc (diff)
Draw Manager: fix draw-state switching logic
Changing states didn't properly reset between shading groups causing the GL state to be wrong based on draw order. States are now only set when changed.
-rw-r--r--source/blender/draw/intern/DRW_render.h3
-rw-r--r--source/blender/draw/intern/draw_common.c6
-rw-r--r--source/blender/draw/intern/draw_manager.c326
-rw-r--r--source/blender/draw/intern/draw_view.c2
-rw-r--r--source/blender/draw/modes/edit_armature_mode.c2
-rw-r--r--source/blender/draw/modes/object_mode.c2
6 files changed, 224 insertions, 117 deletions
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index 15ed8aeb979..53fbd22e7ab 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -249,6 +249,7 @@ typedef enum {
DRW_STATE_TEST_STENCIL_ACTIVE = (1 << 17),
} DRWState;
+
DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass);
DRWShadingGroup *DRW_shgroup_material_create(struct GPUMaterial *material, DRWPass *pass);
DRWShadingGroup *DRW_shgroup_material_instance_create(struct GPUMaterial *material, DRWPass *pass, struct Batch *geom);
@@ -267,7 +268,7 @@ void DRW_shgroup_call_dynamic_add_array(DRWShadingGroup *shgroup, const void *at
DRW_shgroup_call_dynamic_add_array(shgroup, NULL, 0); \
} while (0)
-void DRW_shgroup_state_set(DRWShadingGroup *shgroup, DRWState state);
+void DRW_shgroup_state_enable(DRWShadingGroup *shgroup, DRWState state);
void DRW_shgroup_attrib_int(DRWShadingGroup *shgroup, const char *name, int size);
void DRW_shgroup_attrib_float(DRWShadingGroup *shgroup, const char *name, int size);
diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c
index e50d21e0eb0..c266c45e71c 100644
--- a/source/blender/draw/intern/draw_common.c
+++ b/source/blender/draw/intern/draw_common.c
@@ -131,7 +131,7 @@ DRWShadingGroup *shgroup_dynpoints_uniform_color(DRWPass *pass, float color[4],
DRWShadingGroup *grp = DRW_shgroup_point_batch_create(sh, pass);
DRW_shgroup_uniform_vec4(grp, "color", color, 1);
DRW_shgroup_uniform_float(grp, "size", size, 1);
- DRW_shgroup_state_set(grp, DRW_STATE_POINT);
+ DRW_shgroup_state_enable(grp, DRW_STATE_POINT);
return grp;
}
@@ -152,7 +152,7 @@ DRWShadingGroup *shgroup_groundpoints_uniform_color(DRWPass *pass, float color[4
DRWShadingGroup *grp = DRW_shgroup_point_batch_create(sh, pass);
DRW_shgroup_uniform_vec4(grp, "color", color, 1);
- DRW_shgroup_state_set(grp, DRW_STATE_POINT);
+ DRW_shgroup_state_enable(grp, DRW_STATE_POINT);
return grp;
}
@@ -167,7 +167,7 @@ DRWShadingGroup *shgroup_instance_screenspace(DRWPass *pass, struct Batch *geom,
DRW_shgroup_uniform_float(grp, "size", size, 1);
DRW_shgroup_uniform_float(grp, "pixel_size", DRW_viewport_pixelsize_get(), 1);
DRW_shgroup_uniform_vec3(grp, "screen_vecs[0]", DRW_viewport_screenvecs_get(), 2);
- DRW_shgroup_state_set(grp, DRW_STATE_STIPPLE_3);
+ DRW_shgroup_state_enable(grp, DRW_STATE_STIPPLE_3);
return grp;
}
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 06cebab1c72..196f239119e 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -196,7 +196,7 @@ struct DRWShadingGroup {
GPUShader *shader; /* Shader to bind */
DRWInterface *interface; /* Uniforms pointers */
ListBase calls; /* DRWCall or DRWCallDynamic depending of type */
- DRWState state; /* State changes for this batch only */
+ DRWState state_extra; /* State changes for this batch only (or'd with the pass's state) */
int type;
Batch *instance_geom; /* Geometry to instance */
@@ -229,6 +229,9 @@ static struct DRWGlobalState {
ListBase bound_texs;
int tex_bind_id;
+ /* Managed by `DRW_state_set`, `DRW_state_reset` */
+ DRWState state;
+
/* Per viewport */
GPUViewport *viewport;
struct GPUFrameBuffer *default_framebuffer;
@@ -608,7 +611,7 @@ DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass)
shgroup->type = DRW_SHG_NORMAL;
shgroup->shader = shader;
shgroup->interface = DRW_interface_create(shader);
- shgroup->state = 0;
+ shgroup->state_extra = 0;
shgroup->batch_geom = NULL;
shgroup->instance_geom = NULL;
@@ -797,9 +800,10 @@ void DRW_shgroup_call_dynamic_add_array(DRWShadingGroup *shgroup, const void *at
/* Make sure you know what you do when using this,
* State is not revert back at the end of the shgroup */
-void DRW_shgroup_state_set(DRWShadingGroup *shgroup, DRWState state)
+
+void DRW_shgroup_state_enable(DRWShadingGroup *shgroup, DRWState state)
{
- shgroup->state = state;
+ shgroup->state_extra |= state;
}
void DRW_shgroup_attrib_float(DRWShadingGroup *shgroup, const char *name, int size)
@@ -1027,127 +1031,226 @@ void DRW_pass_free(DRWPass *pass)
/** \name Draw (DRW_draw)
* \{ */
-static void set_state(DRWState flag, const bool reset)
+static void DRW_state_set(DRWState state)
{
- /* TODO Keep track of the state and only revert what is needed */
+ if (DST.state == state) {
+ return;
+ }
- if (reset) {
- /* Depth Write */
- if (flag & DRW_STATE_WRITE_DEPTH)
- glDepthMask(GL_TRUE);
- else
- glDepthMask(GL_FALSE);
- /* Color Write */
- if (flag & DRW_STATE_WRITE_COLOR)
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- else
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+#define CHANGED_TO(f) \
+ ((DST.state & (f)) ? \
+ ((state & (f)) ? 0 : -1) : \
+ ((state & (f)) ? 1 : 0))
- /* Backface Culling */
- if (flag & DRW_STATE_CULL_BACK ||
- flag & DRW_STATE_CULL_FRONT)
- {
- glEnable(GL_CULL_FACE);
+#define CHANGED_ANY(f) \
+ ((DST.state & (f)) != (state & (f)))
- if (flag & DRW_STATE_CULL_BACK)
- glCullFace(GL_BACK);
- else if (flag & DRW_STATE_CULL_FRONT)
- glCullFace(GL_FRONT);
+#define CHANGED_ANY_STORE_VAR(f, enabled) \
+ ((DST.state & (f)) != (enabled = (state & (f))))
+
+ /* Depth Write */
+ {
+ int test;
+ if ((test = CHANGED_TO(DRW_STATE_WRITE_DEPTH))) {
+ if (test == 1) {
+ glDepthMask(GL_TRUE);
+ }
+ else {
+ glDepthMask(GL_FALSE);
+ }
}
- else {
- glDisable(GL_CULL_FACE);
+ }
+
+ /* Color Write */
+ {
+ int test;
+ if ((test = CHANGED_TO(DRW_STATE_WRITE_COLOR))) {
+ if (test == 1) {
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ }
+ else {
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+ }
}
+ }
- /* Depth Test */
- if ((flag & (DRW_STATE_DEPTH_LESS | DRW_STATE_DEPTH_EQUAL | DRW_STATE_DEPTH_GREATER)) != 0) {
- glEnable(GL_DEPTH_TEST);
+ /* Cull */
+ {
+ DRWState test;
+ if (CHANGED_ANY_STORE_VAR(
+ DRW_STATE_CULL_BACK | DRW_STATE_CULL_FRONT,
+ test))
+ {
+ if (test) {
+ glEnable(GL_CULL_FACE);
- if (flag & DRW_STATE_DEPTH_LESS)
- glDepthFunc(GL_LEQUAL);
- else if (flag & DRW_STATE_DEPTH_EQUAL)
- glDepthFunc(GL_EQUAL);
- else if (flag & DRW_STATE_DEPTH_GREATER)
- glDepthFunc(GL_GREATER);
+ if ((state & DRW_STATE_CULL_BACK) != 0) {
+ glCullFace(GL_BACK);
+ }
+ else if ((state & DRW_STATE_CULL_FRONT) != 0) {
+ glCullFace(GL_FRONT);
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ else {
+ glDisable(GL_CULL_FACE);
+ }
}
- else {
- glDisable(GL_DEPTH_TEST);
+ }
+
+ /* Depth Test */
+ {
+ DRWState test;
+ if (CHANGED_ANY_STORE_VAR(
+ DRW_STATE_DEPTH_LESS | DRW_STATE_DEPTH_EQUAL | DRW_STATE_DEPTH_GREATER,
+ test))
+ {
+ if (test) {
+ glEnable(GL_DEPTH_TEST);
+
+ if (state & DRW_STATE_DEPTH_LESS) {
+ glDepthFunc(GL_LEQUAL);
+ }
+ else if (state & DRW_STATE_DEPTH_EQUAL) {
+ glDepthFunc(GL_EQUAL);
+ }
+ else if (state & DRW_STATE_DEPTH_GREATER) {
+ glDepthFunc(GL_GREATER);
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ else {
+ glDisable(GL_DEPTH_TEST);
+ }
}
}
/* Wire Width */
- if ((flag & DRW_STATE_WIRE) != 0) {
- glLineWidth(1.0f);
- }
- else if ((flag & DRW_STATE_WIRE_LARGE) != 0) {
- glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
+ {
+ if (CHANGED_ANY(DRW_STATE_WIRE | DRW_STATE_WIRE_LARGE)) {
+ if ((state & DRW_STATE_WIRE) != 0) {
+ glLineWidth(1.0f);
+ }
+ else if ((state & DRW_STATE_WIRE_LARGE) != 0) {
+ glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
+ }
+ else {
+ /* do nothing */
+ }
+ }
}
/* Points Size */
- if ((flag & DRW_STATE_POINT) != 0) {
- GPU_enable_program_point_size();
- glPointSize(5.0f);
- }
- else if (reset) {
- GPU_disable_program_point_size();
+ {
+ int test;
+ if ((test = CHANGED_TO(DRW_STATE_POINT))) {
+ if (test == 1) {
+ GPU_enable_program_point_size();
+ glPointSize(5.0f);
+ }
+ else {
+ GPU_disable_program_point_size();
+ }
+ }
}
/* Blending (all buffer) */
- if ((flag & DRW_STATE_BLEND) != 0) {
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
- else if (reset) {
- glDisable(GL_BLEND);
+ {
+ int test;
+ if ((test = CHANGED_TO(DRW_STATE_BLEND))) {
+ if (test == 1) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+ else {
+ glDisable(GL_BLEND);
+ }
+ }
}
/* Line Stipple */
- if ((flag & DRW_STATE_STIPPLE_2) != 0) {
- setlinestyle(2);
- }
- else if ((flag & DRW_STATE_STIPPLE_3) != 0) {
- setlinestyle(3);
- }
- else if ((flag & DRW_STATE_STIPPLE_4) != 0) {
- setlinestyle(4);
- }
- else if (reset) {
- setlinestyle(0);
+ {
+ int test;
+ if (CHANGED_ANY_STORE_VAR(
+ DRW_STATE_STIPPLE_2 | DRW_STATE_STIPPLE_3 | DRW_STATE_STIPPLE_4,
+ test))
+ {
+ if (test) {
+ if ((state & DRW_STATE_STIPPLE_2) != 0) {
+ setlinestyle(2);
+ }
+ else if ((state & DRW_STATE_STIPPLE_3) != 0) {
+ setlinestyle(3);
+ }
+ else if ((state & DRW_STATE_STIPPLE_4) != 0) {
+ setlinestyle(4);
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ else {
+ setlinestyle(0);
+ }
+ }
}
/* Stencil */
- if ((flag & (DRW_STATE_WRITE_STENCIL_SELECT | DRW_STATE_WRITE_STENCIL_ACTIVE |
- DRW_STATE_TEST_STENCIL_SELECT | DRW_STATE_TEST_STENCIL_ACTIVE)) != 0)
{
- glEnable(GL_STENCIL_TEST);
-
- /* Stencil Write */
- if ((flag & DRW_STATE_WRITE_STENCIL_SELECT) != 0) {
- glStencilMask(STENCIL_SELECT);
- glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
- glStencilFunc(GL_ALWAYS, 0xFF, STENCIL_SELECT);
- }
- else if ((flag & DRW_STATE_WRITE_STENCIL_ACTIVE) != 0) {
- glStencilMask(STENCIL_ACTIVE);
- glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
- glStencilFunc(GL_ALWAYS, 0xFF, STENCIL_ACTIVE);
- }
- /* Stencil Test */
- else if ((flag & DRW_STATE_TEST_STENCIL_SELECT) != 0) {
- glStencilMask(0x00); /* disable write */
- glStencilFunc(GL_NOTEQUAL, 0xFF, STENCIL_SELECT);
- }
- else if ((flag & DRW_STATE_TEST_STENCIL_ACTIVE) != 0) {
- glStencilMask(0x00); /* disable write */
- glStencilFunc(GL_NOTEQUAL, 0xFF, STENCIL_ACTIVE);
+ DRWState test;
+ if (CHANGED_ANY_STORE_VAR(
+ DRW_STATE_WRITE_STENCIL_SELECT |
+ DRW_STATE_WRITE_STENCIL_ACTIVE |
+ DRW_STATE_TEST_STENCIL_SELECT |
+ DRW_STATE_TEST_STENCIL_ACTIVE,
+ test))
+ {
+ if (test) {
+ glEnable(GL_STENCIL_TEST);
+
+ /* Stencil Write */
+ if ((state & DRW_STATE_WRITE_STENCIL_SELECT) != 0) {
+ glStencilMask(STENCIL_SELECT);
+ glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
+ glStencilFunc(GL_ALWAYS, 0xFF, STENCIL_SELECT);
+ }
+ else if ((state & DRW_STATE_WRITE_STENCIL_ACTIVE) != 0) {
+ glStencilMask(STENCIL_ACTIVE);
+ glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
+ glStencilFunc(GL_ALWAYS, 0xFF, STENCIL_ACTIVE);
+ }
+ /* Stencil Test */
+ else if ((state & DRW_STATE_TEST_STENCIL_SELECT) != 0) {
+ glStencilMask(0x00); /* disable write */
+ glStencilFunc(GL_NOTEQUAL, 0xFF, STENCIL_SELECT);
+ }
+ else if ((state & DRW_STATE_TEST_STENCIL_ACTIVE) != 0) {
+ glStencilMask(0x00); /* disable write */
+ glStencilFunc(GL_NOTEQUAL, 0xFF, STENCIL_ACTIVE);
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ else {
+ /* disable write & test */
+ glStencilMask(0x00);
+ glStencilFunc(GL_ALWAYS, 1, 0xFF);
+ glDisable(GL_STENCIL_TEST);
+ }
}
}
- else if (reset) {
- /* disable write & test */
- glStencilMask(0x00);
- glStencilFunc(GL_ALWAYS, 1, 0xFF);
- glDisable(GL_STENCIL_TEST);
- }
+
+#undef CHANGED_TO
+#undef CHANGED_ANY
+#undef CHANGED_ANY_STORE_VAR
+
+ DST.state = state;
}
typedef struct DRWBoundTexture {
@@ -1237,7 +1340,7 @@ static void draw_geometry(DRWShadingGroup *shgroup, Batch *geom, const float (*o
}
}
-static void draw_shgroup(DRWShadingGroup *shgroup)
+static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
{
BLI_assert(shgroup->shader);
BLI_assert(shgroup->interface);
@@ -1256,9 +1359,7 @@ static void draw_shgroup(DRWShadingGroup *shgroup)
shgroup_dynamic_batch_from_calls(shgroup);
}
- if (shgroup->state != 0) {
- set_state(shgroup->state, false);
- }
+ DRW_state_set(pass_state | shgroup->state_extra);
/* Binding Uniform */
/* Don't check anything, Interface should already contain the least uniform as possible */
@@ -1355,10 +1456,7 @@ static void draw_shgroup(DRWShadingGroup *shgroup)
}
}
- /* reset the state for the next group, note - we could only reset states we changed! */
- if (shgroup->state != 0) {
- DRW_state_reset();
- }
+ DRW_state_reset();
}
void DRW_draw_pass(DRWPass *pass)
@@ -1367,7 +1465,7 @@ void DRW_draw_pass(DRWPass *pass)
DST.shader = NULL;
DST.tex_bind_id = 0;
- set_state(pass->state, true);
+ DRW_state_set(pass->state);
BLI_listbase_clear(&DST.bound_texs);
pass->wasdrawn = true;
@@ -1394,7 +1492,7 @@ void DRW_draw_pass(DRWPass *pass)
glBeginQuery(GL_TIME_ELAPSED, pass->timer_queries[pass->back_idx]);
for (DRWShadingGroup *shgroup = pass->shgroups.first; shgroup; shgroup = shgroup->next) {
- draw_shgroup(shgroup);
+ draw_shgroup(shgroup, pass->state);
}
/* Clear Bound textures */
@@ -1431,11 +1529,12 @@ void DRW_draw_callbacks_post_scene(void)
/* Reset state to not interfer with other UI drawcall */
void DRW_state_reset(void)
{
- DRWState state = 0;
- state |= DRW_STATE_WRITE_DEPTH;
- state |= DRW_STATE_WRITE_COLOR;
- state |= DRW_STATE_DEPTH_LESS;
- set_state(state, true);
+ DRWState state =
+ DRW_STATE_WRITE_DEPTH |
+ DRW_STATE_WRITE_COLOR |
+ DRW_STATE_DEPTH_LESS;
+ DST.state = ~state;
+ DRW_state_set(state);
}
/** \} */
@@ -2238,6 +2337,7 @@ void DRW_draw_render_loop(
}
/* Start Drawing */
+ DRW_state_reset();
DRW_engines_draw_background();
DRW_draw_callbacks_pre_scene();
@@ -2252,6 +2352,8 @@ void DRW_draw_render_loop(
ED_region_draw_cb_draw(DST.draw_ctx.evil_C, DST.draw_ctx.ar, REGION_DRAW_POST_VIEW);
}
+ DRW_state_reset();
+
DRW_engines_draw_text();
/* needed so manipulator isn't obscured */
@@ -2400,6 +2502,7 @@ void DRW_draw_select_loop(
}
/* Start Drawing */
+ DRW_state_reset();
DRW_draw_callbacks_pre_scene();
DRW_engines_draw_scene();
DRW_draw_callbacks_post_scene();
@@ -2482,6 +2585,7 @@ void DRW_draw_depth_loop(
}
/* Start Drawing */
+ DRW_state_reset();
DRW_draw_callbacks_pre_scene();
DRW_engines_draw_scene();
DRW_draw_callbacks_post_scene();
diff --git a/source/blender/draw/intern/draw_view.c b/source/blender/draw/intern/draw_view.c
index db8edf1b33d..c6a0d6ed5b1 100644
--- a/source/blender/draw/intern/draw_view.c
+++ b/source/blender/draw/intern/draw_view.c
@@ -591,6 +591,8 @@ void DRW_draw_background(void)
gpuPopMatrix();
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+ glEnable(GL_DEPTH_TEST);
}
else {
/* Solid background Color */
diff --git a/source/blender/draw/modes/edit_armature_mode.c b/source/blender/draw/modes/edit_armature_mode.c
index 87570c35c70..7d13dbd78ee 100644
--- a/source/blender/draw/modes/edit_armature_mode.c
+++ b/source/blender/draw/modes/edit_armature_mode.c
@@ -90,7 +90,7 @@ static void EDIT_ARMATURE_cache_init(void *vedata)
/* Relationship Lines */
stl->g_data->relationship_lines = shgroup_dynlines_uniform_color(psl->relationship, ts.colorWire);
- DRW_shgroup_state_set(stl->g_data->relationship_lines, DRW_STATE_STIPPLE_3);
+ DRW_shgroup_state_enable(stl->g_data->relationship_lines, DRW_STATE_STIPPLE_3);
}
}
diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c
index 70f8e734b99..f28b0af5eb1 100644
--- a/source/blender/draw/modes/object_mode.c
+++ b/source/blender/draw/modes/object_mode.c
@@ -752,7 +752,7 @@ static void OBJECT_cache_init(void *vedata)
/* Relationship Lines */
stl->g_data->relationship_lines = shgroup_dynlines_uniform_color(psl->non_meshes, ts.colorWire);
- DRW_shgroup_state_set(stl->g_data->relationship_lines, DRW_STATE_STIPPLE_3);
+ DRW_shgroup_state_enable(stl->g_data->relationship_lines, DRW_STATE_STIPPLE_3);
/* Force Field Curve Guide End (here because of stipple) */
geom = DRW_cache_screenspace_circle_get();