diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2020-08-17 19:11:09 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2020-08-18 22:30:10 +0300 |
commit | a9f2ebb215084debae70099b3d2e58195d9a9e32 (patch) | |
tree | 839b142dc49f8d6727a4d6e076a6227ea2e573d2 /source | |
parent | 536c2e0ec916eb49c534b4937b36da278dbe2364 (diff) |
Cleanup: DRW: Use GPUState instead of raw opengl calls
Should not break anything! Huh!
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/draw/intern/DRW_render.h | 4 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_manager_exec.c | 428 | ||||
-rw-r--r-- | source/blender/gpu/GPU_state.h | 13 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_state.cc | 37 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_state.cc | 7 |
5 files changed, 200 insertions, 289 deletions
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index 134fdc0ba7c..63625fae185 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -361,6 +361,10 @@ typedef enum { #define DRW_STATE_DEFAULT \ (DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL) +#define DRW_STATE_BLEND_ENABLED \ + (DRW_STATE_BLEND_ADD | DRW_STATE_BLEND_ADD_FULL | DRW_STATE_BLEND_ALPHA | \ + DRW_STATE_BLEND_ALPHA_PREMUL | DRW_STATE_BLEND_BACKGROUND | DRW_STATE_BLEND_OIT | \ + DRW_STATE_BLEND_MUL | DRW_STATE_BLEND_SUB | DRW_STATE_BLEND_CUSTOM | DRW_STATE_LOGIC_INVERT) #define DRW_STATE_RASTERIZER_ENABLED \ (DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_STENCIL | \ DRW_STATE_WRITE_STENCIL_SHADOW_PASS | DRW_STATE_WRITE_STENCIL_SHADOW_FAIL) diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c index b23bcd97f41..f08c3231e8c 100644 --- a/source/blender/draw/intern/draw_manager_exec.c +++ b/source/blender/draw/intern/draw_manager_exec.c @@ -32,6 +32,7 @@ #include "GPU_extensions.h" #include "GPU_platform.h" #include "GPU_shader.h" +#include "GPU_state.h" #ifdef USE_GPU_SELECT # include "GPU_select.h" @@ -81,309 +82,166 @@ void drw_state_set(DRWState state) return; } -#define CHANGED_TO(f) \ - ((DST.state_lock & (f)) ? \ - 0 : \ - (((DST.state & (f)) ? ((state & (f)) ? 0 : -1) : ((state & (f)) ? 1 : 0)))) + eGPUWriteMask write_mask = 0; + eGPUBlend blend = 0; + eGPUFaceCullTest culling_test = 0; + eGPUDepthTest depth_test = 0; + eGPUStencilTest stencil_test = 0; + eGPUStencilOp stencil_op = 0; + eGPUProvokingVertex provoking_vert = 0; -#define CHANGED_ANY(f) (((DST.state & (f)) != (state & (f))) && ((DST.state_lock & (f)) == 0)) - -#define CHANGED_ANY_STORE_VAR(f, enabled) \ - (((DST.state & (f)) != (enabled = (state & (f)))) && (((DST.state_lock & (f)) == 0))) - - /* Depth Write */ - { - int test; - if ((test = CHANGED_TO(DRW_STATE_WRITE_DEPTH))) { - GPU_depth_mask(test == 1); - } + if (state & DRW_STATE_WRITE_DEPTH) { + write_mask |= GPU_WRITE_DEPTH; } - - /* Stencil Write */ - { - DRWState test; - if (CHANGED_ANY_STORE_VAR(DRW_STATE_WRITE_STENCIL_ENABLED, test)) { - /* Stencil Write */ - if (test) { - glStencilMask(0xFF); - switch (test) { - case DRW_STATE_WRITE_STENCIL: - glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); - break; - case DRW_STATE_WRITE_STENCIL_SHADOW_PASS: - glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_INCR_WRAP); - glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_DECR_WRAP); - break; - case DRW_STATE_WRITE_STENCIL_SHADOW_FAIL: - glStencilOpSeparate(GL_BACK, GL_KEEP, GL_DECR_WRAP, GL_KEEP); - glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_INCR_WRAP, GL_KEEP); - break; - default: - BLI_assert(0); - } - } - else { - glStencilMask(0x00); - glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - } - } + if (state & DRW_STATE_WRITE_COLOR) { + write_mask |= GPU_WRITE_COLOR; } - /* Color Write */ - { - int test; - if ((test = CHANGED_TO(DRW_STATE_WRITE_COLOR))) { - if (test == 1) { - GPU_color_mask(true, true, true, true); - } - else { - GPU_color_mask(false, false, false, false); - } - } + switch (state & (DRW_STATE_CULL_BACK | DRW_STATE_CULL_FRONT)) { + case DRW_STATE_CULL_BACK: + culling_test = GPU_CULL_BACK; + break; + case DRW_STATE_CULL_FRONT: + culling_test = GPU_CULL_FRONT; + break; + default: + culling_test = GPU_CULL_NONE; + break; } - /* Raster Discard */ - { - if (CHANGED_ANY(DRW_STATE_RASTERIZER_ENABLED)) { - if ((state & DRW_STATE_RASTERIZER_ENABLED) != 0) { - glDisable(GL_RASTERIZER_DISCARD); - } - else { - glEnable(GL_RASTERIZER_DISCARD); - } - } + switch (state & DRW_STATE_DEPTH_TEST_ENABLED) { + case DRW_STATE_DEPTH_LESS: + depth_test = GPU_DEPTH_LESS; + break; + case DRW_STATE_DEPTH_LESS_EQUAL: + depth_test = GPU_DEPTH_LESS_EQUAL; + break; + case DRW_STATE_DEPTH_EQUAL: + depth_test = GPU_DEPTH_EQUAL; + break; + case DRW_STATE_DEPTH_GREATER: + depth_test = GPU_DEPTH_GREATER; + break; + case DRW_STATE_DEPTH_GREATER_EQUAL: + depth_test = GPU_DEPTH_GREATER_EQUAL; + break; + case DRW_STATE_DEPTH_ALWAYS: + depth_test = GPU_DEPTH_ALWAYS; + break; + default: + depth_test = GPU_DEPTH_NONE; + break; } - /* Cull */ - { - DRWState test; - if (CHANGED_ANY_STORE_VAR(DRW_STATE_CULL_BACK | DRW_STATE_CULL_FRONT, test)) { - if (test) { - glEnable(GL_CULL_FACE); - - 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); - } - } + switch (state & DRW_STATE_WRITE_STENCIL_ENABLED) { + case DRW_STATE_WRITE_STENCIL: + stencil_op = GPU_STENCIL_OP_REPLACE; + break; + case DRW_STATE_WRITE_STENCIL_SHADOW_PASS: + stencil_op = GPU_STENCIL_OP_COUNT_DEPTH_PASS; + break; + case DRW_STATE_WRITE_STENCIL_SHADOW_FAIL: + stencil_op = GPU_STENCIL_OP_COUNT_DEPTH_FAIL; + break; + default: + stencil_op = GPU_STENCIL_OP_NONE; + break; } + GPU_stencil_write_mask_set(0xFF); - /* Depth Test */ - { - DRWState test; - if (CHANGED_ANY_STORE_VAR(DRW_STATE_DEPTH_TEST_ENABLED, test)) { - if (test) { - glEnable(GL_DEPTH_TEST); - - switch (test) { - case DRW_STATE_DEPTH_LESS: - glDepthFunc(GL_LESS); - break; - case DRW_STATE_DEPTH_LESS_EQUAL: - glDepthFunc(GL_LEQUAL); - break; - case DRW_STATE_DEPTH_EQUAL: - glDepthFunc(GL_EQUAL); - break; - case DRW_STATE_DEPTH_GREATER: - glDepthFunc(GL_GREATER); - break; - case DRW_STATE_DEPTH_GREATER_EQUAL: - glDepthFunc(GL_GEQUAL); - break; - case DRW_STATE_DEPTH_ALWAYS: - glDepthFunc(GL_ALWAYS); - break; - default: - BLI_assert(0); - } - } - else { - glDisable(GL_DEPTH_TEST); - } - } + switch (state & DRW_STATE_STENCIL_TEST_ENABLED) { + case DRW_STATE_STENCIL_ALWAYS: + stencil_test = GPU_STENCIL_ALWAYS; + break; + case DRW_STATE_STENCIL_EQUAL: + stencil_test = GPU_STENCIL_EQUAL; + break; + case DRW_STATE_STENCIL_NEQUAL: + stencil_test = GPU_STENCIL_NEQUAL; + break; + default: + stencil_test = GPU_STENCIL_NONE; + break; } - /* Stencil Test */ - { - int test; - if (CHANGED_ANY_STORE_VAR(DRW_STATE_STENCIL_TEST_ENABLED, test)) { - if (test) { - glEnable(GL_STENCIL_TEST); - } - else { - glDisable(GL_STENCIL_TEST); - } - } + switch (state & DRW_STATE_BLEND_ENABLED) { + case DRW_STATE_BLEND_ADD: + blend = GPU_BLEND_ADDITIVE; + break; + case DRW_STATE_BLEND_ADD_FULL: + blend = GPU_BLEND_ADDITIVE_PREMULT; + break; + case DRW_STATE_BLEND_ALPHA: + blend = GPU_BLEND_ALPHA; + break; + case DRW_STATE_BLEND_ALPHA_PREMUL: + blend = GPU_BLEND_ALPHA_PREMULT; + break; + case DRW_STATE_BLEND_BACKGROUND: + blend = GPU_BLEND_BACKGROUND; + break; + case DRW_STATE_BLEND_OIT: + blend = GPU_BLEND_OIT; + break; + case DRW_STATE_BLEND_MUL: + blend = GPU_BLEND_MULTIPLY; + break; + case DRW_STATE_BLEND_SUB: + blend = GPU_BLEND_SUBTRACT; + break; + case DRW_STATE_BLEND_CUSTOM: + blend = GPU_BLEND_CUSTOM; + break; + case DRW_STATE_LOGIC_INVERT: + blend = GPU_BLEND_INVERT; + break; + default: + blend = GPU_BLEND_NONE; + break; } - /* Blending (all buffer) */ - { - int test; - if (CHANGED_ANY_STORE_VAR(DRW_STATE_BLEND_ALPHA | DRW_STATE_BLEND_ALPHA_PREMUL | - DRW_STATE_BLEND_ADD | DRW_STATE_BLEND_MUL | - DRW_STATE_BLEND_ADD_FULL | DRW_STATE_BLEND_OIT | - DRW_STATE_BLEND_BACKGROUND | DRW_STATE_BLEND_CUSTOM | - DRW_STATE_LOGIC_INVERT | DRW_STATE_BLEND_SUB, - test)) { - if (test) { - glEnable(GL_BLEND); - - switch (test) { - case DRW_STATE_BLEND_ALPHA: - glBlendFuncSeparate(GL_SRC_ALPHA, - GL_ONE_MINUS_SRC_ALPHA, /* RGB */ - GL_ONE, - GL_ONE_MINUS_SRC_ALPHA); /* Alpha */ - break; - case DRW_STATE_BLEND_BACKGROUND: - /* Special blend to add color under and multiply dst by alpha. */ - glBlendFuncSeparate(GL_ONE_MINUS_DST_ALPHA, - GL_SRC_ALPHA, /* RGB */ - GL_ZERO, - GL_SRC_ALPHA); /* Alpha */ - break; - case DRW_STATE_BLEND_ALPHA_PREMUL: - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - break; - case DRW_STATE_BLEND_MUL: - glBlendFunc(GL_DST_COLOR, GL_ZERO); - break; - case DRW_STATE_BLEND_OIT: - glBlendFuncSeparate(GL_ONE, - GL_ONE, /* RGB */ - GL_ZERO, - GL_ONE_MINUS_SRC_ALPHA); /* Alpha */ - break; - case DRW_STATE_BLEND_ADD: - /* Do not let alpha accumulate but premult the source RGB by it. */ - glBlendFuncSeparate(GL_SRC_ALPHA, - GL_ONE, /* RGB */ - GL_ZERO, - GL_ONE); /* Alpha */ - break; - case DRW_STATE_BLEND_ADD_FULL: - /* Let alpha accumulate. */ - glBlendFunc(GL_ONE, GL_ONE); - break; - case DRW_STATE_BLEND_SUB: - glBlendFunc(GL_ONE, GL_ONE); - break; - case DRW_STATE_BLEND_CUSTOM: - /* Custom blend parameters using dual source blending. - * Can only be used with one Draw Buffer. */ - glBlendFunc(GL_ONE, GL_SRC1_COLOR); - break; - case DRW_STATE_LOGIC_INVERT: - /* Replace logic op by blend func to support floating point framebuffer. */ - glBlendFuncSeparate(GL_ONE_MINUS_DST_COLOR, - GL_ZERO, /* RGB */ - GL_ZERO, - GL_ONE); /* Alpha */ - break; - default: - BLI_assert(0); - } + GPU_state_set( + write_mask, blend, culling_test, depth_test, stencil_test, stencil_op, provoking_vert); - if (test == DRW_STATE_BLEND_SUB) { - glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); - } - else { - glBlendEquation(GL_FUNC_ADD); - } - } - else { - glDisable(GL_BLEND); - glBlendFunc(GL_ONE, GL_ONE); /* Don't multiply incoming color by alpha. */ - } - } + if (state & DRW_STATE_SHADOW_OFFSET) { + GPU_shadow_offset(true); } - - /* Shadow Bias */ - { - int test; - if ((test = CHANGED_TO(DRW_STATE_SHADOW_OFFSET))) { - if (test == 1) { - glEnable(GL_POLYGON_OFFSET_FILL); - glEnable(GL_POLYGON_OFFSET_LINE); - /* 2.0 Seems to be the lowest possible slope bias that works in every case. */ - glPolygonOffset(2.0f, 1.0f); - } - else { - glDisable(GL_POLYGON_OFFSET_FILL); - glDisable(GL_POLYGON_OFFSET_LINE); - } - } + else { + GPU_shadow_offset(false); } - /* In Front objects selection */ - { - int test; - if ((test = CHANGED_TO(DRW_STATE_IN_FRONT_SELECT))) { - if (test == 1) { - /* XXX `GPU_depth_range` is not a perfect solution - * since very distant geometries can still be occluded. - * Also the depth test precision of these geometries is impaired. - * However, it solves the selection for the vast majority of cases. */ - GPU_depth_range(0.0f, 0.01f); - } - else { - GPU_depth_range(0.0f, 1.0f); - } - } + /* TODO this should be part of shader state. */ + if (state & DRW_STATE_CLIP_PLANES) { + GPU_clip_distances(DST.view_active->clip_planes_len); } - - /* Clip Planes */ - { - int test; - if ((test = CHANGED_TO(DRW_STATE_CLIP_PLANES))) { - if (test == 1) { - GPU_clip_distances(DST.view_active->clip_planes_len); - } - else { - GPU_clip_distances(0); - } - } + else { + GPU_clip_distances(0); } - /* Program Points Size */ - { - int test; - if ((test = CHANGED_TO(DRW_STATE_PROGRAM_POINT_SIZE))) { - if (test == 1) { - GPU_program_point_size(true); - } - else { - GPU_program_point_size(false); - } - } + if (state & DRW_STATE_IN_FRONT_SELECT) { + /* XXX `GPU_depth_range` is not a perfect solution + * since very distant geometries can still be occluded. + * Also the depth test precision of these geometries is impaired. + * However, it solves the selection for the vast majority of cases. */ + GPU_depth_range(0.0f, 0.01f); + } + else { + GPU_depth_range(0.0f, 1.0f); } - /* Provoking Vertex */ - { - int test; - if ((test = CHANGED_TO(DRW_STATE_FIRST_VERTEX_CONVENTION))) { - if (test == 1) { - glProvokingVertex(GL_FIRST_VERTEX_CONVENTION); - } - else { - glProvokingVertex(GL_LAST_VERTEX_CONVENTION); - } - } + if (state & DRW_STATE_PROGRAM_POINT_SIZE) { + GPU_program_point_size(true); + } + else { + GPU_program_point_size(false); } -#undef CHANGED_TO -#undef CHANGED_ANY -#undef CHANGED_ANY_STORE_VAR + if (state & DRW_STATE_FIRST_VERTEX_CONVENTION) { + GPU_provoking_vertex(GPU_VERTEX_FIRST); + } + else { + GPU_provoking_vertex(GPU_VERTEX_LAST); + } DST.state = state; } @@ -395,17 +253,9 @@ static void drw_stencil_state_set(uint write_mask, uint reference, uint compare_ * stencil_value being the value stored in the stencil buffer. * - (write-mask & reference) is what gets written if the test condition is fulfilled. **/ - glStencilMask(write_mask); - DRWState stencil_test = DST.state & DRW_STATE_STENCIL_TEST_ENABLED; - if (stencil_test == DRW_STATE_STENCIL_ALWAYS) { - glStencilFunc(GL_ALWAYS, reference, compare_mask); - } - else if (stencil_test == DRW_STATE_STENCIL_EQUAL) { - glStencilFunc(GL_EQUAL, reference, compare_mask); - } - else if (stencil_test == DRW_STATE_STENCIL_NEQUAL) { - glStencilFunc(GL_NOTEQUAL, reference, compare_mask); - } + GPU_stencil_write_mask_set(write_mask); + GPU_stencil_reference_set(reference); + GPU_stencil_compare_mask_set(compare_mask); } /* Reset state to not interfer with other UI drawcall */ diff --git a/source/blender/gpu/GPU_state.h b/source/blender/gpu/GPU_state.h index 1e2b772224c..14617eeb614 100644 --- a/source/blender/gpu/GPU_state.h +++ b/source/blender/gpu/GPU_state.h @@ -23,6 +23,7 @@ #include "BLI_utildefines.h" typedef enum eGPUWriteMask { + GPU_WRITE_NONE = 0, GPU_WRITE_RED = (1 << 0), GPU_WRITE_GREEN = (1 << 1), GPU_WRITE_BLUE = (1 << 2), @@ -133,8 +134,20 @@ void GPU_color_mask(bool r, bool g, bool b, bool a); void GPU_depth_mask(bool depth); bool GPU_depth_mask_get(void); void GPU_unpack_row_length_set(uint len); +void GPU_shadow_offset(bool enable); void GPU_clip_distances(int enabled_len); bool GPU_mipmap_enabled(void); +void GPU_state_set(eGPUWriteMask write_mask, + eGPUBlend blend, + eGPUFaceCullTest culling_test, + eGPUDepthTest depth_test, + eGPUStencilTest stencil_test, + eGPUStencilOp stencil_op, + eGPUProvokingVertex provoking_vert); + +void GPU_stencil_reference_set(uint reference); +void GPU_stencil_write_mask_set(uint write_mask); +void GPU_stencil_compare_mask_set(uint compare_mask); eGPUBlend GPU_blend_get(void); eGPUWriteMask GPU_write_mask_get(void); diff --git a/source/blender/gpu/intern/gpu_state.cc b/source/blender/gpu/intern/gpu_state.cc index 039bce1f0ac..619f52da852 100644 --- a/source/blender/gpu/intern/gpu_state.cc +++ b/source/blender/gpu/intern/gpu_state.cc @@ -121,11 +121,35 @@ void GPU_depth_mask(bool depth) state.write_mask = write_mask; } +void GPU_shadow_offset(bool enable) +{ + SET_IMMUTABLE_STATE(shadow_bias, enable); +} + void GPU_clip_distances(int distances_enabled) { SET_IMMUTABLE_STATE(clip_distances, distances_enabled); } +void GPU_state_set(eGPUWriteMask write_mask, + eGPUBlend blend, + eGPUFaceCullTest culling_test, + eGPUDepthTest depth_test, + eGPUStencilTest stencil_test, + eGPUStencilOp stencil_op, + eGPUProvokingVertex provoking_vert) +{ + GPUStateManager *stack = GPU_context_active_get()->state_manager; + auto &state = stack->state; + state.write_mask = write_mask; + state.blend = blend; + state.culling_test = culling_test; + state.depth_test = depth_test; + state.stencil_test = stencil_test; + state.stencil_op = stencil_op; + state.provoking_vert = provoking_vert; +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -185,6 +209,19 @@ void GPU_viewport(int x, int y, int width, int height) copy_v4_v4_int(state.viewport_rect, viewport_rect); } +void GPU_stencil_reference_set(uint reference) +{ + SET_MUTABLE_STATE(stencil_reference, (uint8_t)reference); +} +void GPU_stencil_write_mask_set(uint write_mask) +{ + SET_MUTABLE_STATE(stencil_write_mask, (uint8_t)write_mask); +} +void GPU_stencil_compare_mask_set(uint compare_mask) +{ + SET_MUTABLE_STATE(stencil_compare_mask, (uint8_t)compare_mask); +} + /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/gpu/opengl/gl_state.cc b/source/blender/gpu/opengl/gl_state.cc index 5274a86ebe5..f85fb804317 100644 --- a/source/blender/gpu/opengl/gl_state.cc +++ b/source/blender/gpu/opengl/gl_state.cc @@ -153,6 +153,13 @@ void GLStateManager::set_write_mask(const eGPUWriteMask value) (value & GPU_WRITE_GREEN) != 0, (value & GPU_WRITE_BLUE) != 0, (value & GPU_WRITE_ALPHA) != 0); + + if (value == GPU_WRITE_NONE) { + glEnable(GL_RASTERIZER_DISCARD); + } + else { + glDisable(GL_RASTERIZER_DISCARD); + } } void GLStateManager::set_depth_test(const eGPUDepthTest value) |