From f30df15edc0b5bfce98809cfa8c2ca96cfe03e97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Sun, 16 Aug 2020 20:56:39 +0200 Subject: GPUState: Make use of GPUStateStack class This isolate most GL calls to the GL backend. Still a few remains. --- source/blender/gpu/intern/gpu_context.cc | 1 + source/blender/gpu/intern/gpu_context_private.hh | 3 + source/blender/gpu/intern/gpu_state.cc | 258 +++++++++++++---------- source/blender/gpu/intern/gpu_state_private.hh | 2 + 4 files changed, 150 insertions(+), 114 deletions(-) (limited to 'source/blender/gpu/intern') diff --git a/source/blender/gpu/intern/gpu_context.cc b/source/blender/gpu/intern/gpu_context.cc index e04631910c1..da12a58ba87 100644 --- a/source/blender/gpu/intern/gpu_context.cc +++ b/source/blender/gpu/intern/gpu_context.cc @@ -70,6 +70,7 @@ GPUContext::GPUContext() GPUContext::~GPUContext() { GPU_matrix_state_discard(matrix_state); + delete state_stack; } bool GPUContext::is_active_on_thread(void) diff --git a/source/blender/gpu/intern/gpu_context_private.hh b/source/blender/gpu/intern/gpu_context_private.hh index 3f9fca16ff7..04785187e8b 100644 --- a/source/blender/gpu/intern/gpu_context_private.hh +++ b/source/blender/gpu/intern/gpu_context_private.hh @@ -29,6 +29,8 @@ #include "GPU_context.h" +#include "gpu_state_private.hh" + #include #include #include @@ -44,6 +46,7 @@ struct GPUContext { GPUShader *shader = NULL; GPUFrameBuffer *current_fbo = NULL; GPUMatrixState *matrix_state = NULL; + blender::gpu::GPUStateStack *state_stack = NULL; protected: /** Thread on which this context is active. */ diff --git a/source/blender/gpu/intern/gpu_state.cc b/source/blender/gpu/intern/gpu_state.cc index 4c3b2cc119e..6d3d74e60f3 100644 --- a/source/blender/gpu/intern/gpu_state.cc +++ b/source/blender/gpu/intern/gpu_state.cc @@ -25,6 +25,7 @@ # define PIXELSIZE (1.0f) #endif +#include "BLI_math_vector.h" #include "BLI_utildefines.h" #include "BKE_global.h" @@ -33,6 +34,8 @@ #include "GPU_glew.h" #include "GPU_state.h" +#include "gpu_context_private.hh" + #include "gpu_state_private.hh" /* TODO remove */ @@ -40,194 +43,198 @@ using namespace blender::gpu; +#define SET_STATE(_prefix, _state, _value) \ + do { \ + GPUStateStack *stack = GPU_context_active_get()->state_stack; \ + auto &state_object = stack->_prefix##stack_top_get(); \ + state_object._state = _value; \ + /* TODO remove this and only push state at draw time. */ \ + stack->set_##_prefix##state(state_object); \ + } while (0) + +#define SET_IMMUTABLE_STATE(_state, _value) SET_STATE(, _state, _value) +#define SET_MUTABLE_STATE(_state, _value) SET_STATE(mutable_, _state, _value) + +/* -------------------------------------------------------------------- */ +/** \name Immutable state Setters + * \{ */ + void GPU_blend(eGPUBlend blend) { - GLStateStack::set_blend(blend); + SET_IMMUTABLE_STATE(blend, blend); } void GPU_face_culling(eGPUFaceCullTest culling) { - if (culling == GPU_CULL_NONE) { - glDisable(GL_CULL_FACE); - } - else { - glEnable(GL_CULL_FACE); - glCullFace((culling == GPU_CULL_FRONT) ? GL_FRONT : GL_BACK); - } + SET_IMMUTABLE_STATE(culling_test, culling); } void GPU_front_facing(bool invert) { - glFrontFace((invert) ? GL_CW : GL_CCW); + SET_IMMUTABLE_STATE(invert_facing, invert); } void GPU_provoking_vertex(eGPUProvokingVertex vert) { - glProvokingVertex((vert == GPU_VERTEX_FIRST) ? GL_FIRST_VERTEX_CONVENTION : - GL_LAST_VERTEX_CONVENTION); -} - -void GPU_depth_range(float near, float far) -{ - /* glDepthRangef is only for OpenGL 4.1 or higher */ - glDepthRange(near, far); + SET_IMMUTABLE_STATE(provoking_vert, vert); } +/* TODO explicit depth test. */ void GPU_depth_test(bool enable) { - if (enable) { - glEnable(GL_DEPTH_TEST); - } - else { - glDisable(GL_DEPTH_TEST); - } -} - -bool GPU_depth_test_enabled() -{ - return glIsEnabled(GL_DEPTH_TEST); + SET_IMMUTABLE_STATE(depth_test, (enable) ? GPU_DEPTH_LESS : GPU_DEPTH_NONE); } void GPU_line_smooth(bool enable) { - if (enable && ((G.debug & G_DEBUG_GPU) == 0)) { - glEnable(GL_LINE_SMOOTH); - } - else { - glDisable(GL_LINE_SMOOTH); - } + SET_IMMUTABLE_STATE(line_smooth, enable); } -void GPU_line_width(float width) +void GPU_polygon_smooth(bool enable) { - float max_size = GPU_max_line_width(); - float final_size = width * PIXELSIZE; - /* Fix opengl errors on certain platform / drivers. */ - CLAMP(final_size, 1.0f, max_size); - glLineWidth(final_size); + SET_IMMUTABLE_STATE(polygon_smooth, enable); } -void GPU_point_size(float size) +void GPU_logic_op_xor_set(bool enable) { - glPointSize(size * PIXELSIZE); + SET_IMMUTABLE_STATE(logic_op_xor, enable); } -void GPU_polygon_smooth(bool enable) +void GPU_color_mask(bool r, bool g, bool b, bool a) { - if (enable && ((G.debug & G_DEBUG_GPU) == 0)) { - glEnable(GL_POLYGON_SMOOTH); - } - else { - glDisable(GL_POLYGON_SMOOTH); - } + GPUStateStack *stack = GPU_context_active_get()->state_stack; + auto &state = stack->stack_top_get(); + eGPUWriteMask write_mask = state.write_mask; + SET_FLAG_FROM_TEST(write_mask, r, GPU_WRITE_RED); + SET_FLAG_FROM_TEST(write_mask, g, GPU_WRITE_GREEN); + SET_FLAG_FROM_TEST(write_mask, b, GPU_WRITE_BLUE); + SET_FLAG_FROM_TEST(write_mask, a, GPU_WRITE_ALPHA); + state.write_mask = write_mask; + /* TODO remove this and only push state at draw time. */ + stack->set_state(state); } -/* Programmable point size - * - shaders set their own point size when enabled - * - use glPointSize when disabled */ -void GPU_program_point_size(bool enable) +void GPU_depth_mask(bool depth) { - if (enable) { - glEnable(GL_PROGRAM_POINT_SIZE); - } - else { - glDisable(GL_PROGRAM_POINT_SIZE); - } + GPUStateStack *stack = GPU_context_active_get()->state_stack; + auto &state = stack->stack_top_get(); + eGPUWriteMask write_mask = state.write_mask; + SET_FLAG_FROM_TEST(write_mask, depth, GPU_WRITE_DEPTH); + state.write_mask = write_mask; + /* TODO remove this and only push state at draw time. */ + stack->set_state(state); } -void GPU_scissor_test(bool enable) +void GPU_clip_distances(int distances_enabled) { - if (enable) { - glEnable(GL_SCISSOR_TEST); - } - else { - glDisable(GL_SCISSOR_TEST); - } + SET_IMMUTABLE_STATE(clip_distances, distances_enabled); } -void GPU_scissor(int x, int y, int width, int height) -{ - glScissor(x, y, width, height); -} +/** \} */ -void GPU_viewport(int x, int y, int width, int height) -{ - glViewport(x, y, width, height); -} +/* -------------------------------------------------------------------- */ +/** \name Mutable State Setters + * \{ */ -void GPU_scissor_get(int coords[4]) +void GPU_depth_range(float near, float far) { - glGetIntegerv(GL_SCISSOR_BOX, coords); + GPUStateStack *stack = GPU_context_active_get()->state_stack; + auto &state = stack->mutable_stack_top_get(); + copy_v2_fl2(state.depth_range, near, far); + /* TODO remove this and only push state at draw time. */ + stack->set_mutable_state(state); } -void GPU_viewport_size_get_f(float coords[4]) +void GPU_line_width(float width) { - glGetFloatv(GL_VIEWPORT, coords); + SET_MUTABLE_STATE(line_width, width * PIXELSIZE); } -void GPU_viewport_size_get_i(int coords[4]) +void GPU_point_size(float size) { - glGetIntegerv(GL_VIEWPORT, coords); + SET_MUTABLE_STATE(point_size, size * PIXELSIZE); } -void GPU_flush(void) +/* Programmable point size + * - shaders set their own point size when enabled + * - use glPointSize when disabled */ +/* TODO remove and use program point size everywhere */ +void GPU_program_point_size(bool enable) { - glFlush(); + GPUStateStack *stack = GPU_context_active_get()->state_stack; + auto &state = stack->mutable_stack_top_get(); + /* Set point size sign negative to disable. */ + state.point_size = fabsf(state.point_size) * (enable ? 1 : -1); + /* TODO remove this and only push state at draw time. */ + stack->set_mutable_state(state); } -void GPU_finish(void) +void GPU_scissor_test(bool enable) { - glFinish(); + GPUStateStack *stack = GPU_context_active_get()->state_stack; + auto &state = stack->mutable_stack_top_get(); + /* Set point size sign negative to disable. */ + state.scissor_rect[2] = abs(state.scissor_rect[2]) * (enable ? 1 : -1); + /* TODO remove this and only push state at draw time. */ + stack->set_mutable_state(state); } -void GPU_unpack_row_length_set(uint len) +void GPU_scissor(int x, int y, int width, int height) { - glPixelStorei(GL_UNPACK_ROW_LENGTH, len); + GPUStateStack *stack = GPU_context_active_get()->state_stack; + auto &state = stack->mutable_stack_top_get(); + int scissor_rect[4] = {x, y, width, height}; + copy_v4_v4_int(state.scissor_rect, scissor_rect); + /* TODO remove this and only push state at draw time. */ + stack->set_mutable_state(state); } -void GPU_logic_op_xor_set(bool enable) +void GPU_viewport(int x, int y, int width, int height) { - if (enable) { - glLogicOp(GL_XOR); - glEnable(GL_COLOR_LOGIC_OP); - } - else { - glDisable(GL_COLOR_LOGIC_OP); - } + GPUStateStack *stack = GPU_context_active_get()->state_stack; + auto &state = stack->mutable_stack_top_get(); + int viewport_rect[4] = {x, y, width, height}; + copy_v4_v4_int(state.viewport_rect, viewport_rect); + /* TODO remove this and only push state at draw time. */ + stack->set_mutable_state(state); } -void GPU_color_mask(bool r, bool g, bool b, bool a) +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name State Getters + * \{ */ + +bool GPU_depth_test_enabled() { - glColorMask(r, g, b, a); + GPUState &state = GPU_context_active_get()->state_stack->stack_top_get(); + return state.depth_test != GPU_DEPTH_NONE; } -void GPU_depth_mask(bool depth) +void GPU_scissor_get(int coords[4]) { - glDepthMask(depth); + GPUStateMutable &state = GPU_context_active_get()->state_stack->mutable_stack_top_get(); + copy_v4_v4_int(coords, state.scissor_rect); } -bool GPU_depth_mask_get(void) +void GPU_viewport_size_get_f(float coords[4]) { - GLint mask; - glGetIntegerv(GL_DEPTH_WRITEMASK, &mask); - return mask == GL_TRUE; + GPUStateMutable &state = GPU_context_active_get()->state_stack->mutable_stack_top_get(); + for (int i = 0; i < 4; i++) { + coords[i] = state.viewport_rect[i]; + } } -void GPU_stencil_mask(uint stencil) +void GPU_viewport_size_get_i(int coords[4]) { - glStencilMask(stencil); + GPUStateMutable &state = GPU_context_active_get()->state_stack->mutable_stack_top_get(); + copy_v4_v4_int(coords, state.viewport_rect); } -void GPU_clip_distances(int distances_new) +bool GPU_depth_mask_get(void) { - static int distances_enabled = 0; - for (int i = 0; i < distances_new; i++) { - glEnable(GL_CLIP_DISTANCE0 + i); - } - for (int i = distances_new; i < distances_enabled; i++) { - glDisable(GL_CLIP_DISTANCE0 + i); - } - distances_enabled = distances_new; + GPUState &state = GPU_context_active_get()->state_stack->stack_top_get(); + return (state.write_mask & GPU_WRITE_DEPTH) != 0; } bool GPU_mipmap_enabled(void) @@ -236,8 +243,10 @@ bool GPU_mipmap_enabled(void) return true; } +/** \} */ + /* -------------------------------------------------------------------- */ -/** \name Draw State (DRW_state) +/** \name GPUStateStack * \{ */ void GPUStateStack::push_stack(void) @@ -264,6 +273,27 @@ void GPUStateStack::pop_mutable_stack(void) /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Context Utils + * \{ */ + +void GPU_flush(void) +{ + glFlush(); +} + +void GPU_finish(void) +{ + glFinish(); +} + +void GPU_unpack_row_length_set(uint len) +{ + glPixelStorei(GL_UNPACK_ROW_LENGTH, len); +} + +/** \} */ + /* -------------------------------------------------------------------- */ /** \name GPU Push/Pop State * \{ */ diff --git a/source/blender/gpu/intern/gpu_state_private.hh b/source/blender/gpu/intern/gpu_state_private.hh index 0ac538d117c..31840724ec0 100644 --- a/source/blender/gpu/intern/gpu_state_private.hh +++ b/source/blender/gpu/intern/gpu_state_private.hh @@ -137,6 +137,8 @@ class GPUStateStack { int mutable_stack_top = 0; public: + virtual ~GPUStateStack(){}; + virtual void set_state(GPUState &state) = 0; virtual void set_mutable_state(GPUStateMutable &state) = 0; -- cgit v1.2.3