1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
17 /** \file
18  * \ingroup gpu
19  */
20 
21 #ifndef GPU_STANDALONE
22 #  include "DNA_userdef_types.h"
23 #  define PIXELSIZE (U.pixelsize)
24 #else
25 #  define PIXELSIZE (1.0f)
26 #endif
27 
28 #include "BLI_math_vector.h"
29 #include "BLI_utildefines.h"
30 
31 #include "BKE_global.h"
32 
33 #include "GPU_state.h"
34 
35 #include "gpu_context_private.hh"
36 
37 #include "gpu_state_private.hh"
38 
39 using namespace blender::gpu;
40 
41 #define SET_STATE(_prefix, _state, _value) \
42   do { \
43     StateManager *stack = Context::get()->state_manager; \
44     auto &state_object = stack->_prefix##state; \
45     state_object._state = (_value); \
46   } while (0)
47 
48 #define SET_IMMUTABLE_STATE(_state, _value) SET_STATE(, _state, _value)
49 #define SET_MUTABLE_STATE(_state, _value) SET_STATE(mutable_, _state, _value)
50 
51 /* -------------------------------------------------------------------- */
52 /** \name Immutable state Setters
53  * \{ */
54 
GPU_blend(eGPUBlend blend)55 void GPU_blend(eGPUBlend blend)
56 {
57   SET_IMMUTABLE_STATE(blend, blend);
58 }
59 
GPU_face_culling(eGPUFaceCullTest culling)60 void GPU_face_culling(eGPUFaceCullTest culling)
61 {
62   SET_IMMUTABLE_STATE(culling_test, culling);
63 }
64 
GPU_front_facing(bool invert)65 void GPU_front_facing(bool invert)
66 {
67   SET_IMMUTABLE_STATE(invert_facing, invert);
68 }
69 
GPU_provoking_vertex(eGPUProvokingVertex vert)70 void GPU_provoking_vertex(eGPUProvokingVertex vert)
71 {
72   SET_IMMUTABLE_STATE(provoking_vert, vert);
73 }
74 
GPU_depth_test(eGPUDepthTest test)75 void GPU_depth_test(eGPUDepthTest test)
76 {
77   SET_IMMUTABLE_STATE(depth_test, test);
78 }
79 
GPU_stencil_test(eGPUStencilTest test)80 void GPU_stencil_test(eGPUStencilTest test)
81 {
82   SET_IMMUTABLE_STATE(stencil_test, test);
83 }
84 
GPU_line_smooth(bool enable)85 void GPU_line_smooth(bool enable)
86 {
87   SET_IMMUTABLE_STATE(line_smooth, enable);
88 }
89 
GPU_polygon_smooth(bool enable)90 void GPU_polygon_smooth(bool enable)
91 {
92   SET_IMMUTABLE_STATE(polygon_smooth, enable);
93 }
94 
GPU_logic_op_xor_set(bool enable)95 void GPU_logic_op_xor_set(bool enable)
96 {
97   SET_IMMUTABLE_STATE(logic_op_xor, enable);
98 }
99 
GPU_write_mask(eGPUWriteMask mask)100 void GPU_write_mask(eGPUWriteMask mask)
101 {
102   SET_IMMUTABLE_STATE(write_mask, mask);
103 }
104 
GPU_color_mask(bool r,bool g,bool b,bool a)105 void GPU_color_mask(bool r, bool g, bool b, bool a)
106 {
107   StateManager *stack = Context::get()->state_manager;
108   auto &state = stack->state;
109   uint32_t write_mask = state.write_mask;
110   SET_FLAG_FROM_TEST(write_mask, r, (uint32_t)GPU_WRITE_RED);
111   SET_FLAG_FROM_TEST(write_mask, g, (uint32_t)GPU_WRITE_GREEN);
112   SET_FLAG_FROM_TEST(write_mask, b, (uint32_t)GPU_WRITE_BLUE);
113   SET_FLAG_FROM_TEST(write_mask, a, (uint32_t)GPU_WRITE_ALPHA);
114   state.write_mask = write_mask;
115 }
116 
GPU_depth_mask(bool depth)117 void GPU_depth_mask(bool depth)
118 {
119   StateManager *stack = Context::get()->state_manager;
120   auto &state = stack->state;
121   uint32_t write_mask = state.write_mask;
122   SET_FLAG_FROM_TEST(write_mask, depth, (uint32_t)GPU_WRITE_DEPTH);
123   state.write_mask = write_mask;
124 }
125 
GPU_shadow_offset(bool enable)126 void GPU_shadow_offset(bool enable)
127 {
128   SET_IMMUTABLE_STATE(shadow_bias, enable);
129 }
130 
GPU_clip_distances(int distances_enabled)131 void GPU_clip_distances(int distances_enabled)
132 {
133   SET_IMMUTABLE_STATE(clip_distances, distances_enabled);
134 }
135 
GPU_state_set(eGPUWriteMask write_mask,eGPUBlend blend,eGPUFaceCullTest culling_test,eGPUDepthTest depth_test,eGPUStencilTest stencil_test,eGPUStencilOp stencil_op,eGPUProvokingVertex provoking_vert)136 void GPU_state_set(eGPUWriteMask write_mask,
137                    eGPUBlend blend,
138                    eGPUFaceCullTest culling_test,
139                    eGPUDepthTest depth_test,
140                    eGPUStencilTest stencil_test,
141                    eGPUStencilOp stencil_op,
142                    eGPUProvokingVertex provoking_vert)
143 {
144   StateManager *stack = Context::get()->state_manager;
145   auto &state = stack->state;
146   state.write_mask = (uint32_t)write_mask;
147   state.blend = (uint32_t)blend;
148   state.culling_test = (uint32_t)culling_test;
149   state.depth_test = (uint32_t)depth_test;
150   state.stencil_test = (uint32_t)stencil_test;
151   state.stencil_op = (uint32_t)stencil_op;
152   state.provoking_vert = (uint32_t)provoking_vert;
153 }
154 
155 /** \} */
156 
157 /* -------------------------------------------------------------------- */
158 /** \name Mutable State Setters
159  * \{ */
160 
GPU_depth_range(float near,float far)161 void GPU_depth_range(float near, float far)
162 {
163   StateManager *stack = Context::get()->state_manager;
164   auto &state = stack->mutable_state;
165   copy_v2_fl2(state.depth_range, near, far);
166 }
167 
GPU_line_width(float width)168 void GPU_line_width(float width)
169 {
170   width = max_ff(1.0f, width * PIXELSIZE);
171   SET_MUTABLE_STATE(line_width, width);
172 }
173 
GPU_point_size(float size)174 void GPU_point_size(float size)
175 {
176   StateManager *stack = Context::get()->state_manager;
177   auto &state = stack->mutable_state;
178   /* Keep the sign of point_size since it represents the enable state. */
179   state.point_size = size * ((state.point_size > 0.0) ? 1.0f : -1.0f);
180 }
181 
182 /* Programmable point size
183  * - shaders set their own point size when enabled
184  * - use GPU_point_size when disabled */
185 /* TODO remove and use program point size everywhere */
GPU_program_point_size(bool enable)186 void GPU_program_point_size(bool enable)
187 {
188   StateManager *stack = Context::get()->state_manager;
189   auto &state = stack->mutable_state;
190   /* Set point size sign negative to disable. */
191   state.point_size = fabsf(state.point_size) * (enable ? 1 : -1);
192 }
193 
GPU_scissor_test(bool enable)194 void GPU_scissor_test(bool enable)
195 {
196   Context::get()->active_fb->scissor_test_set(enable);
197 }
198 
GPU_scissor(int x,int y,int width,int height)199 void GPU_scissor(int x, int y, int width, int height)
200 {
201   int scissor_rect[4] = {x, y, width, height};
202   Context::get()->active_fb->scissor_set(scissor_rect);
203 }
204 
GPU_viewport(int x,int y,int width,int height)205 void GPU_viewport(int x, int y, int width, int height)
206 {
207   int viewport_rect[4] = {x, y, width, height};
208   Context::get()->active_fb->viewport_set(viewport_rect);
209 }
210 
GPU_stencil_reference_set(uint reference)211 void GPU_stencil_reference_set(uint reference)
212 {
213   SET_MUTABLE_STATE(stencil_reference, (uint8_t)reference);
214 }
215 
GPU_stencil_write_mask_set(uint write_mask)216 void GPU_stencil_write_mask_set(uint write_mask)
217 {
218   SET_MUTABLE_STATE(stencil_write_mask, (uint8_t)write_mask);
219 }
220 
GPU_stencil_compare_mask_set(uint compare_mask)221 void GPU_stencil_compare_mask_set(uint compare_mask)
222 {
223   SET_MUTABLE_STATE(stencil_compare_mask, (uint8_t)compare_mask);
224 }
225 
226 /** \} */
227 
228 /* -------------------------------------------------------------------- */
229 /** \name State Getters
230  * \{ */
231 
GPU_blend_get()232 eGPUBlend GPU_blend_get()
233 {
234   GPUState &state = Context::get()->state_manager->state;
235   return (eGPUBlend)state.blend;
236 }
237 
GPU_write_mask_get()238 eGPUWriteMask GPU_write_mask_get()
239 {
240   GPUState &state = Context::get()->state_manager->state;
241   return (eGPUWriteMask)state.write_mask;
242 }
243 
GPU_stencil_mask_get()244 uint GPU_stencil_mask_get()
245 {
246   GPUStateMutable &state = Context::get()->state_manager->mutable_state;
247   return state.stencil_write_mask;
248 }
249 
GPU_depth_test_get()250 eGPUDepthTest GPU_depth_test_get()
251 {
252   GPUState &state = Context::get()->state_manager->state;
253   return (eGPUDepthTest)state.depth_test;
254 }
255 
GPU_stencil_test_get()256 eGPUStencilTest GPU_stencil_test_get()
257 {
258   GPUState &state = Context::get()->state_manager->state;
259   return (eGPUStencilTest)state.stencil_test;
260 }
261 
262 /* NOTE: Already premultiplied by U.pixelsize. */
GPU_line_width_get(void)263 float GPU_line_width_get(void)
264 {
265   GPUStateMutable &state = Context::get()->state_manager->mutable_state;
266   return state.line_width;
267 }
268 
GPU_scissor_get(int coords[4])269 void GPU_scissor_get(int coords[4])
270 {
271   Context::get()->active_fb->scissor_get(coords);
272 }
273 
GPU_viewport_size_get_f(float coords[4])274 void GPU_viewport_size_get_f(float coords[4])
275 {
276   int viewport[4];
277   Context::get()->active_fb->viewport_get(viewport);
278   for (int i = 0; i < 4; i++) {
279     coords[i] = viewport[i];
280   }
281 }
282 
GPU_viewport_size_get_i(int coords[4])283 void GPU_viewport_size_get_i(int coords[4])
284 {
285   Context::get()->active_fb->viewport_get(coords);
286 }
287 
GPU_depth_mask_get(void)288 bool GPU_depth_mask_get(void)
289 {
290   GPUState &state = Context::get()->state_manager->state;
291   return (state.write_mask & GPU_WRITE_DEPTH) != 0;
292 }
293 
GPU_mipmap_enabled(void)294 bool GPU_mipmap_enabled(void)
295 {
296   /* TODO(fclem): this used to be a userdef option. */
297   return true;
298 }
299 
300 /** \} */
301 
302 /* -------------------------------------------------------------------- */
303 /** \name Context Utils
304  * \{ */
305 
GPU_flush(void)306 void GPU_flush(void)
307 {
308   Context::get()->flush();
309 }
310 
GPU_finish(void)311 void GPU_finish(void)
312 {
313   Context::get()->finish();
314 }
315 
GPU_apply_state(void)316 void GPU_apply_state(void)
317 {
318   Context::get()->state_manager->apply_state();
319 }
320 
321 /** \} */
322 
323 /* -------------------------------------------------------------------- */
324 /** \name BGL workaround
325  *
326  * bgl makes direct GL calls that makes our state tracking out of date.
327  * This flag make it so that the pyGPU calls will not override the state set by
328  * bgl functions.
329  * \{ */
330 
GPU_bgl_start(void)331 void GPU_bgl_start(void)
332 {
333   Context *ctx = Context::get();
334   if (!(ctx && ctx->state_manager)) {
335     return;
336   }
337   StateManager &state_manager = *(Context::get()->state_manager);
338   if (state_manager.use_bgl == false) {
339     /* Expected by many addons (see T80169, T81289).
340      * This will reset the blend function. */
341     GPU_blend(GPU_BLEND_NONE);
342     state_manager.apply_state();
343     state_manager.use_bgl = true;
344   }
345 }
346 
347 /* Just turn off the bgl safeguard system. Can be called even without GPU_bgl_start. */
GPU_bgl_end(void)348 void GPU_bgl_end(void)
349 {
350   Context *ctx = Context::get();
351   if (!(ctx && ctx->state_manager)) {
352     return;
353   }
354   StateManager &state_manager = *ctx->state_manager;
355   if (state_manager.use_bgl == true) {
356     state_manager.use_bgl = false;
357     /* Resync state tracking. */
358     state_manager.force_state();
359   }
360 }
361 
GPU_bgl_get(void)362 bool GPU_bgl_get(void)
363 {
364   return Context::get()->state_manager->use_bgl;
365 }
366 
367 /** \} */
368 
369 /* -------------------------------------------------------------------- */
370 /** \name Synchronization Utils
371  * \{ */
372 
GPU_memory_barrier(eGPUBarrier barrier)373 void GPU_memory_barrier(eGPUBarrier barrier)
374 {
375   Context::get()->state_manager->issue_barrier(barrier);
376 }
377 
378 /** \} */
379 
380 /* -------------------------------------------------------------------- */
381 /** \name Default State
382  * \{ */
383 
StateManager(void)384 StateManager::StateManager(void)
385 {
386   /* Set default state. */
387   state.write_mask = GPU_WRITE_COLOR;
388   state.blend = GPU_BLEND_NONE;
389   state.culling_test = GPU_CULL_NONE;
390   state.depth_test = GPU_DEPTH_NONE;
391   state.stencil_test = GPU_STENCIL_NONE;
392   state.stencil_op = GPU_STENCIL_OP_NONE;
393   state.provoking_vert = GPU_VERTEX_LAST;
394   state.logic_op_xor = false;
395   state.invert_facing = false;
396   state.shadow_bias = false;
397   state.clip_distances = 0;
398   state.polygon_smooth = false;
399   state.line_smooth = false;
400 
401   mutable_state.depth_range[0] = 0.0f;
402   mutable_state.depth_range[1] = 1.0f;
403   mutable_state.point_size = -1.0f; /* Negative is not using point size. */
404   mutable_state.line_width = 1.0f;
405   mutable_state.stencil_write_mask = 0x00;
406   mutable_state.stencil_compare_mask = 0x00;
407   mutable_state.stencil_reference = 0x00;
408 }
409 
410 /** \} */
411