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  * Copyright 2016, Blender Foundation.
17  */
18 
19 /** \file
20  * \ingroup draw
21  */
22 
23 #include "draw_manager.h"
24 
25 #include "BKE_curve.h"
26 #include "BKE_duplilist.h"
27 #include "BKE_global.h"
28 #include "BKE_image.h"
29 #include "BKE_mesh.h"
30 #include "BKE_object.h"
31 #include "BKE_paint.h"
32 #include "BKE_pbvh.h"
33 
34 #include "DNA_curve_types.h"
35 #include "DNA_mesh_types.h"
36 #include "DNA_meta_types.h"
37 
38 #include "BLI_alloca.h"
39 #include "BLI_hash.h"
40 #include "BLI_link_utils.h"
41 #include "BLI_listbase.h"
42 #include "BLI_memblock.h"
43 #include "BLI_mempool.h"
44 
45 #ifdef DRW_DEBUG_CULLING
46 #  include "BLI_math_bits.h"
47 #endif
48 
49 #include "GPU_buffers.h"
50 #include "GPU_material.h"
51 #include "GPU_uniform_buffer.h"
52 
53 #include "intern/gpu_codegen.h"
54 
55 /* -------------------------------------------------------------------- */
56 /** \name Uniform Buffer Object (DRW_uniformbuffer)
57  * \{ */
58 
draw_call_sort(DRWCommand * array,DRWCommand * array_tmp,int array_len)59 static void draw_call_sort(DRWCommand *array, DRWCommand *array_tmp, int array_len)
60 {
61   /* Count unique batches. Tt's not really important if
62    * there is collisions. If there is a lot of different batches,
63    * the sorting benefit will be negligible.
64    * So at least sort fast! */
65   uchar idx[128] = {0};
66   /* Shift by 6 positions knowing each GPUBatch is > 64 bytes */
67 #define KEY(a) ((((size_t)((a).draw.batch)) >> 6) % ARRAY_SIZE(idx))
68   BLI_assert(array_len <= ARRAY_SIZE(idx));
69 
70   for (int i = 0; i < array_len; i++) {
71     /* Early out if nothing to sort. */
72     if (++idx[KEY(array[i])] == array_len) {
73       return;
74     }
75   }
76   /* Cumulate batch indices */
77   for (int i = 1; i < ARRAY_SIZE(idx); i++) {
78     idx[i] += idx[i - 1];
79   }
80   /* Traverse in reverse to not change the order of the resource ID's. */
81   for (int src = array_len - 1; src >= 0; src--) {
82     array_tmp[--idx[KEY(array[src])]] = array[src];
83   }
84 #undef KEY
85 
86   memcpy(array, array_tmp, sizeof(*array) * array_len);
87 }
88 
drw_resource_buffer_finish(ViewportMemoryPool * vmempool)89 void drw_resource_buffer_finish(ViewportMemoryPool *vmempool)
90 {
91   int chunk_id = DRW_handle_chunk_get(&DST.resource_handle);
92   int elem_id = DRW_handle_id_get(&DST.resource_handle);
93   int ubo_len = 1 + chunk_id - ((elem_id == 0) ? 1 : 0);
94   size_t list_size = sizeof(GPUUniformBuf *) * ubo_len;
95 
96   /* TODO find a better system. currently a lot of obinfos UBO are going to be unused
97    * if not rendering with Eevee. */
98 
99   if (vmempool->matrices_ubo == NULL) {
100     vmempool->matrices_ubo = MEM_callocN(list_size, __func__);
101     vmempool->obinfos_ubo = MEM_callocN(list_size, __func__);
102     vmempool->ubo_len = ubo_len;
103   }
104 
105   /* Remove unnecessary buffers */
106   for (int i = ubo_len; i < vmempool->ubo_len; i++) {
107     GPU_uniformbuf_free(vmempool->matrices_ubo[i]);
108     GPU_uniformbuf_free(vmempool->obinfos_ubo[i]);
109   }
110 
111   if (ubo_len != vmempool->ubo_len) {
112     vmempool->matrices_ubo = MEM_recallocN(vmempool->matrices_ubo, list_size);
113     vmempool->obinfos_ubo = MEM_recallocN(vmempool->obinfos_ubo, list_size);
114     vmempool->ubo_len = ubo_len;
115   }
116 
117   /* Create/Update buffers. */
118   for (int i = 0; i < ubo_len; i++) {
119     void *data_obmat = BLI_memblock_elem_get(vmempool->obmats, i, 0);
120     void *data_infos = BLI_memblock_elem_get(vmempool->obinfos, i, 0);
121     if (vmempool->matrices_ubo[i] == NULL) {
122       vmempool->matrices_ubo[i] = GPU_uniformbuf_create(sizeof(DRWObjectMatrix) *
123                                                         DRW_RESOURCE_CHUNK_LEN);
124       vmempool->obinfos_ubo[i] = GPU_uniformbuf_create(sizeof(DRWObjectInfos) *
125                                                        DRW_RESOURCE_CHUNK_LEN);
126     }
127     GPU_uniformbuf_update(vmempool->matrices_ubo[i], data_obmat);
128     GPU_uniformbuf_update(vmempool->obinfos_ubo[i], data_infos);
129   }
130 
131   /* Aligned alloc to avoid unaligned memcpy. */
132   DRWCommandChunk *chunk_tmp = MEM_mallocN_aligned(sizeof(DRWCommandChunk), 16, "tmp call chunk");
133   DRWCommandChunk *chunk;
134   BLI_memblock_iter iter;
135   BLI_memblock_iternew(vmempool->commands, &iter);
136   while ((chunk = BLI_memblock_iterstep(&iter))) {
137     bool sortable = true;
138     /* We can only sort chunks that contain #DRWCommandDraw only. */
139     for (int i = 0; i < ARRAY_SIZE(chunk->command_type) && sortable; i++) {
140       if (chunk->command_type[i] != 0) {
141         sortable = false;
142       }
143     }
144     if (sortable) {
145       draw_call_sort(chunk->commands, chunk_tmp->commands, chunk->command_used);
146     }
147   }
148   MEM_freeN(chunk_tmp);
149 }
150 
151 /** \} */
152 
153 /* -------------------------------------------------------------------- */
154 /** \name Uniforms (DRW_shgroup_uniform)
155  * \{ */
156 
drw_shgroup_uniform_create_ex(DRWShadingGroup * shgroup,int loc,DRWUniformType type,const void * value,eGPUSamplerState sampler_state,int length,int arraysize)157 static void drw_shgroup_uniform_create_ex(DRWShadingGroup *shgroup,
158                                           int loc,
159                                           DRWUniformType type,
160                                           const void *value,
161                                           eGPUSamplerState sampler_state,
162                                           int length,
163                                           int arraysize)
164 {
165   if (loc == -1) {
166     /* Nice to enable eventually, for now EEVEE uses uniforms that might not exist. */
167     // BLI_assert(0);
168     return;
169   }
170 
171   DRWUniformChunk *unichunk = shgroup->uniforms;
172   /* Happens on first uniform or if chunk is full. */
173   if (!unichunk || unichunk->uniform_used == unichunk->uniform_len) {
174     unichunk = BLI_memblock_alloc(DST.vmempool->uniforms);
175     unichunk->uniform_len = ARRAY_SIZE(shgroup->uniforms->uniforms);
176     unichunk->uniform_used = 0;
177     BLI_LINKS_PREPEND(shgroup->uniforms, unichunk);
178   }
179 
180   DRWUniform *uni = unichunk->uniforms + unichunk->uniform_used++;
181 
182   uni->location = loc;
183   uni->type = type;
184   uni->length = length;
185   uni->arraysize = arraysize;
186 
187   switch (type) {
188     case DRW_UNIFORM_INT_COPY:
189       BLI_assert(length <= 4);
190       memcpy(uni->ivalue, value, sizeof(int) * length);
191       break;
192     case DRW_UNIFORM_FLOAT_COPY:
193       BLI_assert(length <= 4);
194       memcpy(uni->fvalue, value, sizeof(float) * length);
195       break;
196     case DRW_UNIFORM_BLOCK:
197       uni->block = (GPUUniformBuf *)value;
198       break;
199     case DRW_UNIFORM_BLOCK_REF:
200       uni->block_ref = (GPUUniformBuf **)value;
201       break;
202     case DRW_UNIFORM_IMAGE:
203     case DRW_UNIFORM_TEXTURE:
204       uni->texture = (GPUTexture *)value;
205       uni->sampler_state = sampler_state;
206       break;
207     case DRW_UNIFORM_IMAGE_REF:
208     case DRW_UNIFORM_TEXTURE_REF:
209       uni->texture_ref = (GPUTexture **)value;
210       uni->sampler_state = sampler_state;
211       break;
212     default:
213       uni->pvalue = (const float *)value;
214       break;
215   }
216 }
217 
drw_shgroup_uniform(DRWShadingGroup * shgroup,const char * name,DRWUniformType type,const void * value,int length,int arraysize)218 static void drw_shgroup_uniform(DRWShadingGroup *shgroup,
219                                 const char *name,
220                                 DRWUniformType type,
221                                 const void *value,
222                                 int length,
223                                 int arraysize)
224 {
225   BLI_assert(arraysize > 0 && arraysize <= 16);
226   BLI_assert(length >= 0 && length <= 16);
227   BLI_assert(!ELEM(type,
228                    DRW_UNIFORM_BLOCK,
229                    DRW_UNIFORM_BLOCK_REF,
230                    DRW_UNIFORM_TEXTURE,
231                    DRW_UNIFORM_TEXTURE_REF));
232   int location = GPU_shader_get_uniform(shgroup->shader, name);
233   drw_shgroup_uniform_create_ex(shgroup, location, type, value, 0, length, arraysize);
234 }
235 
DRW_shgroup_uniform_texture_ex(DRWShadingGroup * shgroup,const char * name,const GPUTexture * tex,eGPUSamplerState sampler_state)236 void DRW_shgroup_uniform_texture_ex(DRWShadingGroup *shgroup,
237                                     const char *name,
238                                     const GPUTexture *tex,
239                                     eGPUSamplerState sampler_state)
240 {
241   BLI_assert(tex != NULL);
242   int loc = GPU_shader_get_texture_binding(shgroup->shader, name);
243   drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_TEXTURE, tex, sampler_state, 0, 1);
244 }
245 
DRW_shgroup_uniform_texture(DRWShadingGroup * shgroup,const char * name,const GPUTexture * tex)246 void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, const GPUTexture *tex)
247 {
248   DRW_shgroup_uniform_texture_ex(shgroup, name, tex, GPU_SAMPLER_MAX);
249 }
250 
DRW_shgroup_uniform_texture_ref_ex(DRWShadingGroup * shgroup,const char * name,GPUTexture ** tex,eGPUSamplerState sampler_state)251 void DRW_shgroup_uniform_texture_ref_ex(DRWShadingGroup *shgroup,
252                                         const char *name,
253                                         GPUTexture **tex,
254                                         eGPUSamplerState sampler_state)
255 {
256   BLI_assert(tex != NULL);
257   int loc = GPU_shader_get_texture_binding(shgroup->shader, name);
258   drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_TEXTURE_REF, tex, sampler_state, 0, 1);
259 }
260 
DRW_shgroup_uniform_texture_ref(DRWShadingGroup * shgroup,const char * name,GPUTexture ** tex)261 void DRW_shgroup_uniform_texture_ref(DRWShadingGroup *shgroup, const char *name, GPUTexture **tex)
262 {
263   DRW_shgroup_uniform_texture_ref_ex(shgroup, name, tex, GPU_SAMPLER_MAX);
264 }
265 
DRW_shgroup_uniform_image(DRWShadingGroup * shgroup,const char * name,const GPUTexture * tex)266 void DRW_shgroup_uniform_image(DRWShadingGroup *shgroup, const char *name, const GPUTexture *tex)
267 {
268   BLI_assert(tex != NULL);
269   int loc = GPU_shader_get_texture_binding(shgroup->shader, name);
270   drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_IMAGE, tex, 0, 0, 1);
271 }
272 
DRW_shgroup_uniform_image_ref(DRWShadingGroup * shgroup,const char * name,GPUTexture ** tex)273 void DRW_shgroup_uniform_image_ref(DRWShadingGroup *shgroup, const char *name, GPUTexture **tex)
274 {
275   BLI_assert(tex != NULL);
276   int loc = GPU_shader_get_texture_binding(shgroup->shader, name);
277   drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_IMAGE_REF, tex, 0, 0, 1);
278 }
279 
DRW_shgroup_uniform_block(DRWShadingGroup * shgroup,const char * name,const GPUUniformBuf * ubo)280 void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup,
281                                const char *name,
282                                const GPUUniformBuf *ubo)
283 {
284   BLI_assert(ubo != NULL);
285   int loc = GPU_shader_get_uniform_block_binding(shgroup->shader, name);
286   drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_BLOCK, ubo, 0, 0, 1);
287 }
288 
DRW_shgroup_uniform_block_ref(DRWShadingGroup * shgroup,const char * name,GPUUniformBuf ** ubo)289 void DRW_shgroup_uniform_block_ref(DRWShadingGroup *shgroup, const char *name, GPUUniformBuf **ubo)
290 {
291   BLI_assert(ubo != NULL);
292   int loc = GPU_shader_get_uniform_block_binding(shgroup->shader, name);
293   drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_BLOCK_REF, ubo, 0, 0, 1);
294 }
295 
DRW_shgroup_uniform_bool(DRWShadingGroup * shgroup,const char * name,const int * value,int arraysize)296 void DRW_shgroup_uniform_bool(DRWShadingGroup *shgroup,
297                               const char *name,
298                               const int *value,
299                               int arraysize)
300 {
301   drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_INT, value, 1, arraysize);
302 }
303 
DRW_shgroup_uniform_float(DRWShadingGroup * shgroup,const char * name,const float * value,int arraysize)304 void DRW_shgroup_uniform_float(DRWShadingGroup *shgroup,
305                                const char *name,
306                                const float *value,
307                                int arraysize)
308 {
309   drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_FLOAT, value, 1, arraysize);
310 }
311 
DRW_shgroup_uniform_vec2(DRWShadingGroup * shgroup,const char * name,const float * value,int arraysize)312 void DRW_shgroup_uniform_vec2(DRWShadingGroup *shgroup,
313                               const char *name,
314                               const float *value,
315                               int arraysize)
316 {
317   drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_FLOAT, value, 2, arraysize);
318 }
319 
DRW_shgroup_uniform_vec3(DRWShadingGroup * shgroup,const char * name,const float * value,int arraysize)320 void DRW_shgroup_uniform_vec3(DRWShadingGroup *shgroup,
321                               const char *name,
322                               const float *value,
323                               int arraysize)
324 {
325   drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_FLOAT, value, 3, arraysize);
326 }
327 
DRW_shgroup_uniform_vec4(DRWShadingGroup * shgroup,const char * name,const float * value,int arraysize)328 void DRW_shgroup_uniform_vec4(DRWShadingGroup *shgroup,
329                               const char *name,
330                               const float *value,
331                               int arraysize)
332 {
333   drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_FLOAT, value, 4, arraysize);
334 }
335 
DRW_shgroup_uniform_int(DRWShadingGroup * shgroup,const char * name,const int * value,int arraysize)336 void DRW_shgroup_uniform_int(DRWShadingGroup *shgroup,
337                              const char *name,
338                              const int *value,
339                              int arraysize)
340 {
341   drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_INT, value, 1, arraysize);
342 }
343 
DRW_shgroup_uniform_ivec2(DRWShadingGroup * shgroup,const char * name,const int * value,int arraysize)344 void DRW_shgroup_uniform_ivec2(DRWShadingGroup *shgroup,
345                                const char *name,
346                                const int *value,
347                                int arraysize)
348 {
349   drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_INT, value, 2, arraysize);
350 }
351 
DRW_shgroup_uniform_ivec3(DRWShadingGroup * shgroup,const char * name,const int * value,int arraysize)352 void DRW_shgroup_uniform_ivec3(DRWShadingGroup *shgroup,
353                                const char *name,
354                                const int *value,
355                                int arraysize)
356 {
357   drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_INT, value, 3, arraysize);
358 }
359 
DRW_shgroup_uniform_ivec4(DRWShadingGroup * shgroup,const char * name,const int * value,int arraysize)360 void DRW_shgroup_uniform_ivec4(DRWShadingGroup *shgroup,
361                                const char *name,
362                                const int *value,
363                                int arraysize)
364 {
365   drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_INT, value, 4, arraysize);
366 }
367 
DRW_shgroup_uniform_mat3(DRWShadingGroup * shgroup,const char * name,const float (* value)[3])368 void DRW_shgroup_uniform_mat3(DRWShadingGroup *shgroup, const char *name, const float (*value)[3])
369 {
370   drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_FLOAT, (float *)value, 9, 1);
371 }
372 
DRW_shgroup_uniform_mat4(DRWShadingGroup * shgroup,const char * name,const float (* value)[4])373 void DRW_shgroup_uniform_mat4(DRWShadingGroup *shgroup, const char *name, const float (*value)[4])
374 {
375   drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_FLOAT, (float *)value, 16, 1);
376 }
377 
378 /* Stores the int instead of a pointer. */
DRW_shgroup_uniform_int_copy(DRWShadingGroup * shgroup,const char * name,const int value)379 void DRW_shgroup_uniform_int_copy(DRWShadingGroup *shgroup, const char *name, const int value)
380 {
381   drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_INT_COPY, &value, 1, 1);
382 }
383 
DRW_shgroup_uniform_ivec2_copy(DRWShadingGroup * shgroup,const char * name,const int * value)384 void DRW_shgroup_uniform_ivec2_copy(DRWShadingGroup *shgroup, const char *name, const int *value)
385 {
386   drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_INT_COPY, value, 2, 1);
387 }
388 
DRW_shgroup_uniform_ivec3_copy(DRWShadingGroup * shgroup,const char * name,const int * value)389 void DRW_shgroup_uniform_ivec3_copy(DRWShadingGroup *shgroup, const char *name, const int *value)
390 {
391   drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_INT_COPY, value, 3, 1);
392 }
393 
DRW_shgroup_uniform_ivec4_copy(DRWShadingGroup * shgroup,const char * name,const int * value)394 void DRW_shgroup_uniform_ivec4_copy(DRWShadingGroup *shgroup, const char *name, const int *value)
395 {
396   drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_INT_COPY, value, 4, 1);
397 }
398 
DRW_shgroup_uniform_bool_copy(DRWShadingGroup * shgroup,const char * name,const bool value)399 void DRW_shgroup_uniform_bool_copy(DRWShadingGroup *shgroup, const char *name, const bool value)
400 {
401   int ival = value;
402   drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_INT_COPY, &ival, 1, 1);
403 }
404 
DRW_shgroup_uniform_float_copy(DRWShadingGroup * shgroup,const char * name,const float value)405 void DRW_shgroup_uniform_float_copy(DRWShadingGroup *shgroup, const char *name, const float value)
406 {
407   drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_FLOAT_COPY, &value, 1, 1);
408 }
409 
DRW_shgroup_uniform_vec2_copy(DRWShadingGroup * shgroup,const char * name,const float * value)410 void DRW_shgroup_uniform_vec2_copy(DRWShadingGroup *shgroup, const char *name, const float *value)
411 {
412   drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_FLOAT_COPY, value, 2, 1);
413 }
414 
DRW_shgroup_uniform_vec3_copy(DRWShadingGroup * shgroup,const char * name,const float * value)415 void DRW_shgroup_uniform_vec3_copy(DRWShadingGroup *shgroup, const char *name, const float *value)
416 {
417   drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_FLOAT_COPY, value, 3, 1);
418 }
419 
DRW_shgroup_uniform_vec4_copy(DRWShadingGroup * shgroup,const char * name,const float * value)420 void DRW_shgroup_uniform_vec4_copy(DRWShadingGroup *shgroup, const char *name, const float *value)
421 {
422   drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_FLOAT_COPY, value, 4, 1);
423 }
424 
DRW_shgroup_uniform_vec4_array_copy(DRWShadingGroup * shgroup,const char * name,const float (* value)[4],int arraysize)425 void DRW_shgroup_uniform_vec4_array_copy(DRWShadingGroup *shgroup,
426                                          const char *name,
427                                          const float (*value)[4],
428                                          int arraysize)
429 {
430   int location = GPU_shader_get_uniform(shgroup->shader, name);
431 
432   if (location == -1) {
433     /* Nice to enable eventually, for now EEVEE uses uniforms that might not exist. */
434     // BLI_assert(0);
435     return;
436   }
437 
438   for (int i = 0; i < arraysize; i++) {
439     drw_shgroup_uniform_create_ex(
440         shgroup, location + i, DRW_UNIFORM_FLOAT_COPY, &value[i], 0, 4, 1);
441   }
442 }
443 
444 /** \} */
445 
446 /* -------------------------------------------------------------------- */
447 /** \name Draw Call (DRW_calls)
448  * \{ */
449 
drw_call_calc_orco(Object * ob,float (* r_orcofacs)[4])450 static void drw_call_calc_orco(Object *ob, float (*r_orcofacs)[4])
451 {
452   ID *ob_data = (ob) ? ob->data : NULL;
453   float *texcoloc = NULL;
454   float *texcosize = NULL;
455   if (ob_data != NULL) {
456     switch (GS(ob_data->name)) {
457       case ID_ME:
458         BKE_mesh_texspace_get_reference((Mesh *)ob_data, NULL, &texcoloc, &texcosize);
459         break;
460       case ID_CU: {
461         Curve *cu = (Curve *)ob_data;
462         BKE_curve_texspace_ensure(cu);
463         texcoloc = cu->loc;
464         texcosize = cu->size;
465         break;
466       }
467       case ID_MB: {
468         MetaBall *mb = (MetaBall *)ob_data;
469         texcoloc = mb->loc;
470         texcosize = mb->size;
471         break;
472       }
473       default:
474         break;
475     }
476   }
477 
478   if ((texcoloc != NULL) && (texcosize != NULL)) {
479     mul_v3_v3fl(r_orcofacs[1], texcosize, 2.0f);
480     invert_v3(r_orcofacs[1]);
481     sub_v3_v3v3(r_orcofacs[0], texcoloc, texcosize);
482     negate_v3(r_orcofacs[0]);
483     mul_v3_v3(r_orcofacs[0], r_orcofacs[1]); /* result in a nice MADD in the shader */
484   }
485   else {
486     copy_v3_fl(r_orcofacs[0], 0.0f);
487     copy_v3_fl(r_orcofacs[1], 1.0f);
488   }
489 }
490 
drw_call_matrix_init(DRWObjectMatrix * ob_mats,Object * ob,float (* obmat)[4])491 BLI_INLINE void drw_call_matrix_init(DRWObjectMatrix *ob_mats, Object *ob, float (*obmat)[4])
492 {
493   copy_m4_m4(ob_mats->model, obmat);
494   if (ob) {
495     copy_m4_m4(ob_mats->modelinverse, ob->imat);
496   }
497   else {
498     /* WATCH: Can be costly. */
499     invert_m4_m4(ob_mats->modelinverse, ob_mats->model);
500   }
501 }
502 
drw_call_obinfos_init(DRWObjectInfos * ob_infos,Object * ob)503 static void drw_call_obinfos_init(DRWObjectInfos *ob_infos, Object *ob)
504 {
505   BLI_assert(ob);
506   /* Index. */
507   ob_infos->ob_index = ob->index;
508   /* Orco factors. */
509   drw_call_calc_orco(ob, ob_infos->orcotexfac);
510   /* Random float value. */
511   uint random = (DST.dupli_source) ?
512                     DST.dupli_source->random_id :
513                     /* TODO(fclem): this is rather costly to do at runtime. Maybe we can
514                      * put it in ob->runtime and make depsgraph ensure it is up to date. */
515                     BLI_hash_int_2d(BLI_hash_string(ob->id.name + 2), 0);
516   ob_infos->ob_random = random * (1.0f / (float)0xFFFFFFFF);
517   /* Object State. */
518   ob_infos->ob_flag = 1.0f; /* Required to have a correct sign */
519   ob_infos->ob_flag += (ob->base_flag & BASE_SELECTED) ? (1 << 1) : 0;
520   ob_infos->ob_flag += (ob->base_flag & BASE_FROM_DUPLI) ? (1 << 2) : 0;
521   ob_infos->ob_flag += (ob->base_flag & BASE_FROM_SET) ? (1 << 3) : 0;
522   ob_infos->ob_flag += (ob == DST.draw_ctx.obact) ? (1 << 4) : 0;
523   /* Negative scaling. */
524   ob_infos->ob_flag *= (ob->transflag & OB_NEG_SCALE) ? -1.0f : 1.0f;
525   /* Object Color. */
526   copy_v4_v4(ob_infos->ob_color, ob->color);
527 }
528 
drw_call_culling_init(DRWCullingState * cull,Object * ob)529 static void drw_call_culling_init(DRWCullingState *cull, Object *ob)
530 {
531   BoundBox *bbox;
532   if (ob != NULL && (bbox = BKE_object_boundbox_get(ob))) {
533     float corner[3];
534     /* Get BoundSphere center and radius from the BoundBox. */
535     mid_v3_v3v3(cull->bsphere.center, bbox->vec[0], bbox->vec[6]);
536     mul_v3_m4v3(corner, ob->obmat, bbox->vec[0]);
537     mul_m4_v3(ob->obmat, cull->bsphere.center);
538     cull->bsphere.radius = len_v3v3(cull->bsphere.center, corner);
539 
540     /* Bypass test for very large objects (see T67319). */
541     if (UNLIKELY(cull->bsphere.radius > 1e12)) {
542       cull->bsphere.radius = -1.0f;
543     }
544   }
545   else {
546     /* Bypass test. */
547     cull->bsphere.radius = -1.0f;
548   }
549   /* Reset user data */
550   cull->user_data = NULL;
551 }
552 
drw_resource_handle_new(float (* obmat)[4],Object * ob)553 static DRWResourceHandle drw_resource_handle_new(float (*obmat)[4], Object *ob)
554 {
555   DRWCullingState *culling = BLI_memblock_alloc(DST.vmempool->cullstates);
556   DRWObjectMatrix *ob_mats = BLI_memblock_alloc(DST.vmempool->obmats);
557   /* FIXME Meh, not always needed but can be accessed after creation.
558    * Also it needs to have the same resource handle. */
559   DRWObjectInfos *ob_infos = BLI_memblock_alloc(DST.vmempool->obinfos);
560   UNUSED_VARS(ob_infos);
561 
562   DRWResourceHandle handle = DST.resource_handle;
563   DRW_handle_increment(&DST.resource_handle);
564 
565   if (ob && (ob->transflag & OB_NEG_SCALE)) {
566     DRW_handle_negative_scale_enable(&handle);
567   }
568 
569   drw_call_matrix_init(ob_mats, ob, obmat);
570   drw_call_culling_init(culling, ob);
571   /* ob_infos is init only if needed. */
572 
573   return handle;
574 }
575 
DRW_object_resource_id_get(Object * UNUSED (ob))576 uint32_t DRW_object_resource_id_get(Object *UNUSED(ob))
577 {
578   DRWResourceHandle handle = DST.ob_handle;
579   if (handle == 0) {
580     /* Handle not yet allocated. Return next handle. */
581     handle = DST.resource_handle;
582   }
583   return handle & ~(1u << 31);
584 }
585 
drw_resource_handle(DRWShadingGroup * shgroup,float (* obmat)[4],Object * ob)586 static DRWResourceHandle drw_resource_handle(DRWShadingGroup *shgroup,
587                                              float (*obmat)[4],
588                                              Object *ob)
589 {
590   if (ob == NULL) {
591     if (obmat == NULL) {
592       DRWResourceHandle handle = 0;
593       return handle;
594     }
595 
596     return drw_resource_handle_new(obmat, NULL);
597   }
598 
599   if (DST.ob_handle == 0) {
600     DST.ob_handle = drw_resource_handle_new(obmat, ob);
601     DST.ob_state_obinfo_init = false;
602   }
603 
604   if (shgroup->objectinfo) {
605     if (!DST.ob_state_obinfo_init) {
606       DST.ob_state_obinfo_init = true;
607       DRWObjectInfos *ob_infos = DRW_memblock_elem_from_handle(DST.vmempool->obinfos,
608                                                                &DST.ob_handle);
609 
610       drw_call_obinfos_init(ob_infos, ob);
611     }
612   }
613 
614   return DST.ob_handle;
615 }
616 
command_type_set(uint64_t * command_type_bits,int index,eDRWCommandType type)617 static void command_type_set(uint64_t *command_type_bits, int index, eDRWCommandType type)
618 {
619   command_type_bits[index / 16] |= ((uint64_t)type) << ((index % 16) * 4);
620 }
621 
command_type_get(const uint64_t * command_type_bits,int index)622 eDRWCommandType command_type_get(const uint64_t *command_type_bits, int index)
623 {
624   return ((command_type_bits[index / 16] >> ((index % 16) * 4)) & 0xF);
625 }
626 
drw_command_create(DRWShadingGroup * shgroup,eDRWCommandType type)627 static void *drw_command_create(DRWShadingGroup *shgroup, eDRWCommandType type)
628 {
629   DRWCommandChunk *chunk = shgroup->cmd.last;
630 
631   if (chunk == NULL) {
632     DRWCommandSmallChunk *smallchunk = BLI_memblock_alloc(DST.vmempool->commands_small);
633     smallchunk->command_len = ARRAY_SIZE(smallchunk->commands);
634     smallchunk->command_used = 0;
635     smallchunk->command_type[0] = 0x0lu;
636     chunk = (DRWCommandChunk *)smallchunk;
637     BLI_LINKS_APPEND(&shgroup->cmd, chunk);
638   }
639   else if (chunk->command_used == chunk->command_len) {
640     chunk = BLI_memblock_alloc(DST.vmempool->commands);
641     chunk->command_len = ARRAY_SIZE(chunk->commands);
642     chunk->command_used = 0;
643     memset(chunk->command_type, 0x0, sizeof(chunk->command_type));
644     BLI_LINKS_APPEND(&shgroup->cmd, chunk);
645   }
646 
647   command_type_set(chunk->command_type, chunk->command_used, type);
648 
649   return chunk->commands + chunk->command_used++;
650 }
651 
drw_command_draw(DRWShadingGroup * shgroup,GPUBatch * batch,DRWResourceHandle handle)652 static void drw_command_draw(DRWShadingGroup *shgroup, GPUBatch *batch, DRWResourceHandle handle)
653 {
654   DRWCommandDraw *cmd = drw_command_create(shgroup, DRW_CMD_DRAW);
655   cmd->batch = batch;
656   cmd->handle = handle;
657 }
658 
drw_command_draw_range(DRWShadingGroup * shgroup,GPUBatch * batch,DRWResourceHandle handle,uint start,uint count)659 static void drw_command_draw_range(
660     DRWShadingGroup *shgroup, GPUBatch *batch, DRWResourceHandle handle, uint start, uint count)
661 {
662   DRWCommandDrawRange *cmd = drw_command_create(shgroup, DRW_CMD_DRAW_RANGE);
663   cmd->batch = batch;
664   cmd->handle = handle;
665   cmd->vert_first = start;
666   cmd->vert_count = count;
667 }
668 
drw_command_draw_instance(DRWShadingGroup * shgroup,GPUBatch * batch,DRWResourceHandle handle,uint count,bool use_attr)669 static void drw_command_draw_instance(
670     DRWShadingGroup *shgroup, GPUBatch *batch, DRWResourceHandle handle, uint count, bool use_attr)
671 {
672   DRWCommandDrawInstance *cmd = drw_command_create(shgroup, DRW_CMD_DRAW_INSTANCE);
673   cmd->batch = batch;
674   cmd->handle = handle;
675   cmd->inst_count = count;
676   cmd->use_attrs = use_attr;
677 }
678 
drw_command_draw_intance_range(DRWShadingGroup * shgroup,GPUBatch * batch,DRWResourceHandle handle,uint start,uint count)679 static void drw_command_draw_intance_range(
680     DRWShadingGroup *shgroup, GPUBatch *batch, DRWResourceHandle handle, uint start, uint count)
681 {
682   DRWCommandDrawInstanceRange *cmd = drw_command_create(shgroup, DRW_CMD_DRAW_INSTANCE_RANGE);
683   cmd->batch = batch;
684   cmd->handle = handle;
685   cmd->inst_first = start;
686   cmd->inst_count = count;
687 }
688 
drw_command_draw_procedural(DRWShadingGroup * shgroup,GPUBatch * batch,DRWResourceHandle handle,uint vert_count)689 static void drw_command_draw_procedural(DRWShadingGroup *shgroup,
690                                         GPUBatch *batch,
691                                         DRWResourceHandle handle,
692                                         uint vert_count)
693 {
694   DRWCommandDrawProcedural *cmd = drw_command_create(shgroup, DRW_CMD_DRAW_PROCEDURAL);
695   cmd->batch = batch;
696   cmd->handle = handle;
697   cmd->vert_count = vert_count;
698 }
699 
drw_command_set_select_id(DRWShadingGroup * shgroup,GPUVertBuf * buf,uint select_id)700 static void drw_command_set_select_id(DRWShadingGroup *shgroup, GPUVertBuf *buf, uint select_id)
701 {
702   /* Only one can be valid. */
703   BLI_assert(buf == NULL || select_id == -1);
704   DRWCommandSetSelectID *cmd = drw_command_create(shgroup, DRW_CMD_SELECTID);
705   cmd->select_buf = buf;
706   cmd->select_id = select_id;
707 }
708 
drw_command_set_stencil_mask(DRWShadingGroup * shgroup,uint write_mask,uint reference,uint compare_mask)709 static void drw_command_set_stencil_mask(DRWShadingGroup *shgroup,
710                                          uint write_mask,
711                                          uint reference,
712                                          uint compare_mask)
713 {
714   BLI_assert(write_mask <= 0xFF);
715   BLI_assert(reference <= 0xFF);
716   BLI_assert(compare_mask <= 0xFF);
717   DRWCommandSetStencil *cmd = drw_command_create(shgroup, DRW_CMD_STENCIL);
718   cmd->write_mask = write_mask;
719   cmd->comp_mask = compare_mask;
720   cmd->ref = reference;
721 }
722 
drw_command_clear(DRWShadingGroup * shgroup,eGPUFrameBufferBits channels,uchar r,uchar g,uchar b,uchar a,float depth,uchar stencil)723 static void drw_command_clear(DRWShadingGroup *shgroup,
724                               eGPUFrameBufferBits channels,
725                               uchar r,
726                               uchar g,
727                               uchar b,
728                               uchar a,
729                               float depth,
730                               uchar stencil)
731 {
732   DRWCommandClear *cmd = drw_command_create(shgroup, DRW_CMD_CLEAR);
733   cmd->clear_channels = channels;
734   cmd->r = r;
735   cmd->g = g;
736   cmd->b = b;
737   cmd->a = a;
738   cmd->depth = depth;
739   cmd->stencil = stencil;
740 }
741 
drw_command_set_mutable_state(DRWShadingGroup * shgroup,DRWState enable,DRWState disable)742 static void drw_command_set_mutable_state(DRWShadingGroup *shgroup,
743                                           DRWState enable,
744                                           DRWState disable)
745 {
746   /* TODO Restrict what state can be changed. */
747   DRWCommandSetMutableState *cmd = drw_command_create(shgroup, DRW_CMD_DRWSTATE);
748   cmd->enable = enable;
749   cmd->disable = disable;
750 }
751 
DRW_shgroup_call_ex(DRWShadingGroup * shgroup,Object * ob,float (* obmat)[4],struct GPUBatch * geom,bool bypass_culling,void * user_data)752 void DRW_shgroup_call_ex(DRWShadingGroup *shgroup,
753                          Object *ob,
754                          float (*obmat)[4],
755                          struct GPUBatch *geom,
756                          bool bypass_culling,
757                          void *user_data)
758 {
759   BLI_assert(geom != NULL);
760   if (G.f & G_FLAG_PICKSEL) {
761     drw_command_set_select_id(shgroup, NULL, DST.select_id);
762   }
763   DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->obmat : obmat, ob);
764   drw_command_draw(shgroup, geom, handle);
765 
766   /* Culling data. */
767   if (user_data || bypass_culling) {
768     DRWCullingState *culling = DRW_memblock_elem_from_handle(DST.vmempool->cullstates,
769                                                              &DST.ob_handle);
770 
771     if (user_data) {
772       culling->user_data = user_data;
773     }
774     if (bypass_culling) {
775       /* NOTE this will disable culling for the whole object. */
776       culling->bsphere.radius = -1.0f;
777     }
778   }
779 }
780 
DRW_shgroup_call_range(DRWShadingGroup * shgroup,struct Object * ob,GPUBatch * geom,uint v_sta,uint v_ct)781 void DRW_shgroup_call_range(
782     DRWShadingGroup *shgroup, struct Object *ob, GPUBatch *geom, uint v_sta, uint v_ct)
783 {
784   BLI_assert(geom != NULL);
785   if (G.f & G_FLAG_PICKSEL) {
786     drw_command_set_select_id(shgroup, NULL, DST.select_id);
787   }
788   DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->obmat : NULL, ob);
789   drw_command_draw_range(shgroup, geom, handle, v_sta, v_ct);
790 }
791 
792 /* A count of 0 instance will use the default number of instance in the batch. */
DRW_shgroup_call_instance_range(DRWShadingGroup * shgroup,Object * ob,struct GPUBatch * geom,uint i_sta,uint i_ct)793 void DRW_shgroup_call_instance_range(
794     DRWShadingGroup *shgroup, Object *ob, struct GPUBatch *geom, uint i_sta, uint i_ct)
795 {
796   BLI_assert(geom != NULL);
797   if (G.f & G_FLAG_PICKSEL) {
798     drw_command_set_select_id(shgroup, NULL, DST.select_id);
799   }
800   DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->obmat : NULL, ob);
801   drw_command_draw_intance_range(shgroup, geom, handle, i_sta, i_ct);
802 }
803 
drw_shgroup_call_procedural_add_ex(DRWShadingGroup * shgroup,GPUBatch * geom,Object * ob,uint vert_count)804 static void drw_shgroup_call_procedural_add_ex(DRWShadingGroup *shgroup,
805                                                GPUBatch *geom,
806                                                Object *ob,
807                                                uint vert_count)
808 {
809   BLI_assert(vert_count > 0);
810   BLI_assert(geom != NULL);
811   if (G.f & G_FLAG_PICKSEL) {
812     drw_command_set_select_id(shgroup, NULL, DST.select_id);
813   }
814   DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->obmat : NULL, ob);
815   drw_command_draw_procedural(shgroup, geom, handle, vert_count);
816 }
817 
DRW_shgroup_call_procedural_points(DRWShadingGroup * shgroup,Object * ob,uint point_count)818 void DRW_shgroup_call_procedural_points(DRWShadingGroup *shgroup, Object *ob, uint point_count)
819 {
820   struct GPUBatch *geom = drw_cache_procedural_points_get();
821   drw_shgroup_call_procedural_add_ex(shgroup, geom, ob, point_count);
822 }
823 
DRW_shgroup_call_procedural_lines(DRWShadingGroup * shgroup,Object * ob,uint line_count)824 void DRW_shgroup_call_procedural_lines(DRWShadingGroup *shgroup, Object *ob, uint line_count)
825 {
826   struct GPUBatch *geom = drw_cache_procedural_lines_get();
827   drw_shgroup_call_procedural_add_ex(shgroup, geom, ob, line_count * 2);
828 }
829 
DRW_shgroup_call_procedural_triangles(DRWShadingGroup * shgroup,Object * ob,uint tri_count)830 void DRW_shgroup_call_procedural_triangles(DRWShadingGroup *shgroup, Object *ob, uint tri_count)
831 {
832   struct GPUBatch *geom = drw_cache_procedural_triangles_get();
833   drw_shgroup_call_procedural_add_ex(shgroup, geom, ob, tri_count * 3);
834 }
835 
836 /* Should be removed */
DRW_shgroup_call_instances(DRWShadingGroup * shgroup,Object * ob,struct GPUBatch * geom,uint count)837 void DRW_shgroup_call_instances(DRWShadingGroup *shgroup,
838                                 Object *ob,
839                                 struct GPUBatch *geom,
840                                 uint count)
841 {
842   BLI_assert(geom != NULL);
843   if (G.f & G_FLAG_PICKSEL) {
844     drw_command_set_select_id(shgroup, NULL, DST.select_id);
845   }
846   DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->obmat : NULL, ob);
847   drw_command_draw_instance(shgroup, geom, handle, count, false);
848 }
849 
DRW_shgroup_call_instances_with_attrs(DRWShadingGroup * shgroup,Object * ob,struct GPUBatch * geom,struct GPUBatch * inst_attributes)850 void DRW_shgroup_call_instances_with_attrs(DRWShadingGroup *shgroup,
851                                            Object *ob,
852                                            struct GPUBatch *geom,
853                                            struct GPUBatch *inst_attributes)
854 {
855   BLI_assert(geom != NULL);
856   BLI_assert(inst_attributes != NULL);
857   if (G.f & G_FLAG_PICKSEL) {
858     drw_command_set_select_id(shgroup, NULL, DST.select_id);
859   }
860   DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->obmat : NULL, ob);
861   GPUBatch *batch = DRW_temp_batch_instance_request(DST.idatalist, NULL, inst_attributes, geom);
862   drw_command_draw_instance(shgroup, batch, handle, 0, true);
863 }
864 
865 #define SCULPT_DEBUG_BUFFERS (G.debug_value == 889)
866 typedef struct DRWSculptCallbackData {
867   Object *ob;
868   DRWShadingGroup **shading_groups;
869   int num_shading_groups;
870   bool use_wire;
871   bool use_mats;
872   bool use_mask;
873   bool use_fsets;
874   bool fast_mode; /* Set by draw manager. Do not init. */
875 
876   int debug_node_nr;
877 } DRWSculptCallbackData;
878 
879 #define SCULPT_DEBUG_COLOR(id) (sculpt_debug_colors[id % 9])
880 static float sculpt_debug_colors[9][4] = {
881     {1.0f, 0.2f, 0.2f, 1.0f},
882     {0.2f, 1.0f, 0.2f, 1.0f},
883     {0.2f, 0.2f, 1.0f, 1.0f},
884     {1.0f, 1.0f, 0.2f, 1.0f},
885     {0.2f, 1.0f, 1.0f, 1.0f},
886     {1.0f, 0.2f, 1.0f, 1.0f},
887     {1.0f, 0.7f, 0.2f, 1.0f},
888     {0.2f, 1.0f, 0.7f, 1.0f},
889     {0.7f, 0.2f, 1.0f, 1.0f},
890 };
891 
sculpt_draw_cb(DRWSculptCallbackData * scd,GPU_PBVH_Buffers * buffers)892 static void sculpt_draw_cb(DRWSculptCallbackData *scd, GPU_PBVH_Buffers *buffers)
893 {
894   if (!buffers) {
895     return;
896   }
897 
898   /* Meh... use_mask is a bit misleading here. */
899   if (scd->use_mask && !GPU_pbvh_buffers_has_overlays(buffers)) {
900     return;
901   }
902 
903   GPUBatch *geom = GPU_pbvh_buffers_batch_get(buffers, scd->fast_mode, scd->use_wire);
904   short index = 0;
905 
906   if (scd->use_mats) {
907     index = GPU_pbvh_buffers_material_index_get(buffers);
908     if (index >= scd->num_shading_groups) {
909       index = 0;
910     }
911   }
912 
913   DRWShadingGroup *shgrp = scd->shading_groups[index];
914   if (geom != NULL && shgrp != NULL) {
915     if (SCULPT_DEBUG_BUFFERS) {
916       /* Color each buffers in different colors. Only work in solid/Xray mode. */
917       shgrp = DRW_shgroup_create_sub(shgrp);
918       DRW_shgroup_uniform_vec3(
919           shgrp, "materialDiffuseColor", SCULPT_DEBUG_COLOR(scd->debug_node_nr++), 1);
920     }
921     /* DRW_shgroup_call_no_cull reuses matrices calculations for all the drawcalls of this
922      * object. */
923     DRW_shgroup_call_no_cull(shgrp, geom, scd->ob);
924   }
925 }
926 
sculpt_debug_cb(void * user_data,const float bmin[3],const float bmax[3],PBVHNodeFlags flag)927 static void sculpt_debug_cb(void *user_data,
928                             const float bmin[3],
929                             const float bmax[3],
930                             PBVHNodeFlags flag)
931 {
932   int *debug_node_nr = (int *)user_data;
933   BoundBox bb;
934   BKE_boundbox_init_from_minmax(&bb, bmin, bmax);
935 
936 #if 0 /* Nodes hierarchy. */
937   if (flag & PBVH_Leaf) {
938     DRW_debug_bbox(&bb, (float[4]){0.0f, 1.0f, 0.0f, 1.0f});
939   }
940   else {
941     DRW_debug_bbox(&bb, (float[4]){0.5f, 0.5f, 0.5f, 0.6f});
942   }
943 #else /* Color coded leaf bounds. */
944   if (flag & PBVH_Leaf) {
945     DRW_debug_bbox(&bb, SCULPT_DEBUG_COLOR((*debug_node_nr)++));
946   }
947 #endif
948 }
949 
drw_sculpt_get_frustum_planes(Object * ob,float planes[6][4])950 static void drw_sculpt_get_frustum_planes(Object *ob, float planes[6][4])
951 {
952   /* TODO: take into account partial redraw for clipping planes. */
953   DRW_view_frustum_planes_get(DRW_view_default_get(), planes);
954 
955   /* Transform clipping planes to object space. Transforming a plane with a
956    * 4x4 matrix is done by multiplying with the transpose inverse.
957    * The inverse cancels out here since we transform by inverse(obmat). */
958   float tmat[4][4];
959   transpose_m4_m4(tmat, ob->obmat);
960   for (int i = 0; i < 6; i++) {
961     mul_m4_v4(tmat, planes[i]);
962   }
963 }
964 
drw_sculpt_generate_calls(DRWSculptCallbackData * scd)965 static void drw_sculpt_generate_calls(DRWSculptCallbackData *scd)
966 {
967   /* PBVH should always exist for non-empty meshes, created by depsgrah eval. */
968   PBVH *pbvh = (scd->ob->sculpt) ? scd->ob->sculpt->pbvh : NULL;
969   if (!pbvh) {
970     return;
971   }
972 
973   const DRWContextState *drwctx = DRW_context_state_get();
974   RegionView3D *rv3d = drwctx->rv3d;
975   const bool navigating = rv3d && (rv3d->rflag & RV3D_NAVIGATING);
976 
977   Paint *p = NULL;
978   if (drwctx->evil_C != NULL) {
979     p = BKE_paint_get_active_from_context(drwctx->evil_C);
980   }
981 
982   /* Frustum planes to show only visible PBVH nodes. */
983   float update_planes[6][4];
984   float draw_planes[6][4];
985   PBVHFrustumPlanes update_frustum;
986   PBVHFrustumPlanes draw_frustum;
987 
988   if (p && (p->flags & PAINT_SCULPT_DELAY_UPDATES)) {
989     update_frustum.planes = update_planes;
990     update_frustum.num_planes = 6;
991     BKE_pbvh_get_frustum_planes(pbvh, &update_frustum);
992     if (!navigating) {
993       drw_sculpt_get_frustum_planes(scd->ob, update_planes);
994       update_frustum.planes = update_planes;
995       update_frustum.num_planes = 6;
996       BKE_pbvh_set_frustum_planes(pbvh, &update_frustum);
997     }
998   }
999   else {
1000     drw_sculpt_get_frustum_planes(scd->ob, update_planes);
1001     update_frustum.planes = update_planes;
1002     update_frustum.num_planes = 6;
1003   }
1004 
1005   drw_sculpt_get_frustum_planes(scd->ob, draw_planes);
1006   draw_frustum.planes = draw_planes;
1007   draw_frustum.num_planes = 6;
1008 
1009   /* Fast mode to show low poly multires while navigating. */
1010   scd->fast_mode = false;
1011   if (p && (p->flags & PAINT_FAST_NAVIGATE)) {
1012     scd->fast_mode = rv3d && (rv3d->rflag & RV3D_NAVIGATING);
1013   }
1014 
1015   /* Update draw buffers only for visible nodes while painting.
1016    * But do update them otherwise so navigating stays smooth. */
1017   bool update_only_visible = rv3d && !(rv3d->rflag & RV3D_PAINTING);
1018   if (p && (p->flags & PAINT_SCULPT_DELAY_UPDATES)) {
1019     update_only_visible = true;
1020   }
1021 
1022   Mesh *mesh = scd->ob->data;
1023   BKE_pbvh_update_normals(pbvh, mesh->runtime.subdiv_ccg);
1024 
1025   BKE_pbvh_draw_cb(pbvh,
1026                    update_only_visible,
1027                    &update_frustum,
1028                    &draw_frustum,
1029                    (void (*)(void *, GPU_PBVH_Buffers *))sculpt_draw_cb,
1030                    scd);
1031 
1032   if (SCULPT_DEBUG_BUFFERS) {
1033     int debug_node_nr = 0;
1034     DRW_debug_modelmat(scd->ob->obmat);
1035     BKE_pbvh_draw_debug_cb(
1036         pbvh,
1037         (void (*)(
1038             void *d, const float min[3], const float max[3], PBVHNodeFlags f))sculpt_debug_cb,
1039         &debug_node_nr);
1040   }
1041 }
1042 
DRW_shgroup_call_sculpt(DRWShadingGroup * shgroup,Object * ob,bool use_wire,bool use_mask)1043 void DRW_shgroup_call_sculpt(DRWShadingGroup *shgroup, Object *ob, bool use_wire, bool use_mask)
1044 {
1045   DRWSculptCallbackData scd = {
1046       .ob = ob,
1047       .shading_groups = &shgroup,
1048       .num_shading_groups = 1,
1049       .use_wire = use_wire,
1050       .use_mats = false,
1051       .use_mask = use_mask,
1052   };
1053   drw_sculpt_generate_calls(&scd);
1054 }
1055 
DRW_shgroup_call_sculpt_with_materials(DRWShadingGroup ** shgroups,int num_shgroups,Object * ob)1056 void DRW_shgroup_call_sculpt_with_materials(DRWShadingGroup **shgroups,
1057                                             int num_shgroups,
1058                                             Object *ob)
1059 {
1060   DRWSculptCallbackData scd = {
1061       .ob = ob,
1062       .shading_groups = shgroups,
1063       .num_shading_groups = num_shgroups,
1064       .use_wire = false,
1065       .use_mats = true,
1066       .use_mask = false,
1067   };
1068   drw_sculpt_generate_calls(&scd);
1069 }
1070 
1071 static GPUVertFormat inst_select_format = {0};
1072 
DRW_shgroup_call_buffer(DRWShadingGroup * shgroup,struct GPUVertFormat * format,GPUPrimType prim_type)1073 DRWCallBuffer *DRW_shgroup_call_buffer(DRWShadingGroup *shgroup,
1074                                        struct GPUVertFormat *format,
1075                                        GPUPrimType prim_type)
1076 {
1077   BLI_assert(ELEM(prim_type, GPU_PRIM_POINTS, GPU_PRIM_LINES, GPU_PRIM_TRI_FAN));
1078   BLI_assert(format != NULL);
1079 
1080   DRWCallBuffer *callbuf = BLI_memblock_alloc(DST.vmempool->callbuffers);
1081   callbuf->buf = DRW_temp_buffer_request(DST.idatalist, format, &callbuf->count);
1082   callbuf->buf_select = NULL;
1083   callbuf->count = 0;
1084 
1085   if (G.f & G_FLAG_PICKSEL) {
1086     /* Not actually used for rendering but alloced in one chunk. */
1087     if (inst_select_format.attr_len == 0) {
1088       GPU_vertformat_attr_add(&inst_select_format, "selectId", GPU_COMP_I32, 1, GPU_FETCH_INT);
1089     }
1090     callbuf->buf_select = DRW_temp_buffer_request(
1091         DST.idatalist, &inst_select_format, &callbuf->count);
1092     drw_command_set_select_id(shgroup, callbuf->buf_select, -1);
1093   }
1094 
1095   DRWResourceHandle handle = drw_resource_handle(shgroup, NULL, NULL);
1096   GPUBatch *batch = DRW_temp_batch_request(DST.idatalist, callbuf->buf, prim_type);
1097   drw_command_draw(shgroup, batch, handle);
1098 
1099   return callbuf;
1100 }
1101 
DRW_shgroup_call_buffer_instance(DRWShadingGroup * shgroup,struct GPUVertFormat * format,GPUBatch * geom)1102 DRWCallBuffer *DRW_shgroup_call_buffer_instance(DRWShadingGroup *shgroup,
1103                                                 struct GPUVertFormat *format,
1104                                                 GPUBatch *geom)
1105 {
1106   BLI_assert(geom != NULL);
1107   BLI_assert(format != NULL);
1108 
1109   DRWCallBuffer *callbuf = BLI_memblock_alloc(DST.vmempool->callbuffers);
1110   callbuf->buf = DRW_temp_buffer_request(DST.idatalist, format, &callbuf->count);
1111   callbuf->buf_select = NULL;
1112   callbuf->count = 0;
1113 
1114   if (G.f & G_FLAG_PICKSEL) {
1115     /* Not actually used for rendering but alloced in one chunk. */
1116     if (inst_select_format.attr_len == 0) {
1117       GPU_vertformat_attr_add(&inst_select_format, "selectId", GPU_COMP_I32, 1, GPU_FETCH_INT);
1118     }
1119     callbuf->buf_select = DRW_temp_buffer_request(
1120         DST.idatalist, &inst_select_format, &callbuf->count);
1121     drw_command_set_select_id(shgroup, callbuf->buf_select, -1);
1122   }
1123 
1124   DRWResourceHandle handle = drw_resource_handle(shgroup, NULL, NULL);
1125   GPUBatch *batch = DRW_temp_batch_instance_request(DST.idatalist, callbuf->buf, NULL, geom);
1126   drw_command_draw(shgroup, batch, handle);
1127 
1128   return callbuf;
1129 }
1130 
DRW_buffer_add_entry_struct(DRWCallBuffer * callbuf,const void * data)1131 void DRW_buffer_add_entry_struct(DRWCallBuffer *callbuf, const void *data)
1132 {
1133   GPUVertBuf *buf = callbuf->buf;
1134   const bool resize = (callbuf->count == GPU_vertbuf_get_vertex_alloc(buf));
1135 
1136   if (UNLIKELY(resize)) {
1137     GPU_vertbuf_data_resize(buf, callbuf->count + DRW_BUFFER_VERTS_CHUNK);
1138   }
1139 
1140   GPU_vertbuf_vert_set(buf, callbuf->count, data);
1141 
1142   if (G.f & G_FLAG_PICKSEL) {
1143     if (UNLIKELY(resize)) {
1144       GPU_vertbuf_data_resize(callbuf->buf_select, callbuf->count + DRW_BUFFER_VERTS_CHUNK);
1145     }
1146     GPU_vertbuf_attr_set(callbuf->buf_select, 0, callbuf->count, &DST.select_id);
1147   }
1148 
1149   callbuf->count++;
1150 }
1151 
DRW_buffer_add_entry_array(DRWCallBuffer * callbuf,const void * attr[],uint attr_len)1152 void DRW_buffer_add_entry_array(DRWCallBuffer *callbuf, const void *attr[], uint attr_len)
1153 {
1154   GPUVertBuf *buf = callbuf->buf;
1155   const bool resize = (callbuf->count == GPU_vertbuf_get_vertex_alloc(buf));
1156 
1157   BLI_assert(attr_len == GPU_vertbuf_get_format(buf)->attr_len);
1158   UNUSED_VARS_NDEBUG(attr_len);
1159 
1160   if (UNLIKELY(resize)) {
1161     GPU_vertbuf_data_resize(buf, callbuf->count + DRW_BUFFER_VERTS_CHUNK);
1162   }
1163 
1164   for (int i = 0; i < attr_len; i++) {
1165     GPU_vertbuf_attr_set(buf, i, callbuf->count, attr[i]);
1166   }
1167 
1168   if (G.f & G_FLAG_PICKSEL) {
1169     if (UNLIKELY(resize)) {
1170       GPU_vertbuf_data_resize(callbuf->buf_select, callbuf->count + DRW_BUFFER_VERTS_CHUNK);
1171     }
1172     GPU_vertbuf_attr_set(callbuf->buf_select, 0, callbuf->count, &DST.select_id);
1173   }
1174 
1175   callbuf->count++;
1176 }
1177 
1178 /** \} */
1179 
1180 /* -------------------------------------------------------------------- */
1181 /** \name Shading Groups (DRW_shgroup)
1182  * \{ */
1183 
drw_shgroup_init(DRWShadingGroup * shgroup,GPUShader * shader)1184 static void drw_shgroup_init(DRWShadingGroup *shgroup, GPUShader *shader)
1185 {
1186   shgroup->uniforms = NULL;
1187 
1188   int view_ubo_location = GPU_shader_get_builtin_block(shader, GPU_UNIFORM_BLOCK_VIEW);
1189   int model_ubo_location = GPU_shader_get_builtin_block(shader, GPU_UNIFORM_BLOCK_MODEL);
1190   int info_ubo_location = GPU_shader_get_builtin_block(shader, GPU_UNIFORM_BLOCK_INFO);
1191   int baseinst_location = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_BASE_INSTANCE);
1192   int chunkid_location = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_RESOURCE_CHUNK);
1193   int resourceid_location = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_RESOURCE_ID);
1194 
1195   if (chunkid_location != -1) {
1196     drw_shgroup_uniform_create_ex(
1197         shgroup, chunkid_location, DRW_UNIFORM_RESOURCE_CHUNK, NULL, 0, 0, 1);
1198   }
1199 
1200   if (resourceid_location != -1) {
1201     drw_shgroup_uniform_create_ex(
1202         shgroup, resourceid_location, DRW_UNIFORM_RESOURCE_ID, NULL, 0, 0, 1);
1203   }
1204 
1205   if (baseinst_location != -1) {
1206     drw_shgroup_uniform_create_ex(
1207         shgroup, baseinst_location, DRW_UNIFORM_BASE_INSTANCE, NULL, 0, 0, 1);
1208   }
1209 
1210   if (model_ubo_location != -1) {
1211     drw_shgroup_uniform_create_ex(
1212         shgroup, model_ubo_location, DRW_UNIFORM_BLOCK_OBMATS, NULL, 0, 0, 1);
1213   }
1214   else {
1215     /* Note: This is only here to support old hardware fallback where uniform buffer is still
1216      * too slow or buggy. */
1217     int model = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODEL);
1218     int modelinverse = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODEL_INV);
1219     if (model != -1) {
1220       drw_shgroup_uniform_create_ex(shgroup, model, DRW_UNIFORM_MODEL_MATRIX, NULL, 0, 0, 1);
1221     }
1222     if (modelinverse != -1) {
1223       drw_shgroup_uniform_create_ex(
1224           shgroup, modelinverse, DRW_UNIFORM_MODEL_MATRIX_INVERSE, NULL, 0, 0, 1);
1225     }
1226   }
1227 
1228   if (info_ubo_location != -1) {
1229     drw_shgroup_uniform_create_ex(
1230         shgroup, info_ubo_location, DRW_UNIFORM_BLOCK_OBINFOS, NULL, 0, 0, 1);
1231 
1232     /* Abusing this loc to tell shgroup we need the obinfos. */
1233     shgroup->objectinfo = 1;
1234   }
1235   else {
1236     shgroup->objectinfo = 0;
1237   }
1238 
1239   if (view_ubo_location != -1) {
1240     drw_shgroup_uniform_create_ex(
1241         shgroup, view_ubo_location, DRW_UNIFORM_BLOCK, G_draw.view_ubo, 0, 0, 1);
1242   }
1243 
1244   /* Not supported. */
1245   BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODELVIEW_INV) == -1);
1246   BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODELVIEW) == -1);
1247   BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_NORMAL) == -1);
1248   BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_VIEW) == -1);
1249   BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_VIEW_INV) == -1);
1250   BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_VIEWPROJECTION) == -1);
1251   BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_VIEWPROJECTION_INV) == -1);
1252   BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_PROJECTION) == -1);
1253   BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_PROJECTION_INV) == -1);
1254   BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_CLIPPLANES) == -1);
1255   BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MVP) == -1);
1256 }
1257 
drw_shgroup_create_ex(struct GPUShader * shader,DRWPass * pass)1258 static DRWShadingGroup *drw_shgroup_create_ex(struct GPUShader *shader, DRWPass *pass)
1259 {
1260   DRWShadingGroup *shgroup = BLI_memblock_alloc(DST.vmempool->shgroups);
1261 
1262   BLI_LINKS_APPEND(&pass->shgroups, shgroup);
1263 
1264   shgroup->shader = shader;
1265   shgroup->cmd.first = NULL;
1266   shgroup->cmd.last = NULL;
1267   shgroup->pass_handle = pass->handle;
1268 
1269   return shgroup;
1270 }
1271 
drw_shgroup_material_create_ex(GPUPass * gpupass,DRWPass * pass)1272 static DRWShadingGroup *drw_shgroup_material_create_ex(GPUPass *gpupass, DRWPass *pass)
1273 {
1274   if (!gpupass) {
1275     /* Shader compilation error */
1276     return NULL;
1277   }
1278 
1279   GPUShader *sh = GPU_pass_shader_get(gpupass);
1280 
1281   if (!sh) {
1282     /* Shader not yet compiled */
1283     return NULL;
1284   }
1285 
1286   DRWShadingGroup *grp = drw_shgroup_create_ex(sh, pass);
1287   return grp;
1288 }
1289 
drw_shgroup_material_texture(DRWShadingGroup * grp,GPUTexture * gputex,const char * name,eGPUSamplerState state)1290 static void drw_shgroup_material_texture(DRWShadingGroup *grp,
1291                                          GPUTexture *gputex,
1292                                          const char *name,
1293                                          eGPUSamplerState state)
1294 {
1295   DRW_shgroup_uniform_texture_ex(grp, name, gputex, state);
1296 
1297   GPUTexture **gputex_ref = BLI_memblock_alloc(DST.vmempool->images);
1298   *gputex_ref = gputex;
1299   GPU_texture_ref(gputex);
1300 }
1301 
DRW_shgroup_add_material_resources(DRWShadingGroup * grp,struct GPUMaterial * material)1302 void DRW_shgroup_add_material_resources(DRWShadingGroup *grp, struct GPUMaterial *material)
1303 {
1304   ListBase textures = GPU_material_textures(material);
1305 
1306   /* Bind all textures needed by the material. */
1307   LISTBASE_FOREACH (GPUMaterialTexture *, tex, &textures) {
1308     if (tex->ima) {
1309       /* Image */
1310       GPUTexture *gputex;
1311       if (tex->tiled_mapping_name[0]) {
1312         gputex = BKE_image_get_gpu_tiles(tex->ima, tex->iuser, NULL);
1313         drw_shgroup_material_texture(grp, gputex, tex->sampler_name, tex->sampler_state);
1314         gputex = BKE_image_get_gpu_tilemap(tex->ima, tex->iuser, NULL);
1315         drw_shgroup_material_texture(grp, gputex, tex->tiled_mapping_name, tex->sampler_state);
1316       }
1317       else {
1318         gputex = BKE_image_get_gpu_texture(tex->ima, tex->iuser, NULL);
1319         drw_shgroup_material_texture(grp, gputex, tex->sampler_name, tex->sampler_state);
1320       }
1321     }
1322     else if (tex->colorband) {
1323       /* Color Ramp */
1324       DRW_shgroup_uniform_texture(grp, tex->sampler_name, *tex->colorband);
1325     }
1326   }
1327 
1328   GPUUniformBuf *ubo = GPU_material_uniform_buffer_get(material);
1329   if (ubo != NULL) {
1330     DRW_shgroup_uniform_block(grp, GPU_UBO_BLOCK_NAME, ubo);
1331   }
1332 }
1333 
DRW_shgroup_instance_format_array(const DRWInstanceAttrFormat attrs[],int arraysize)1334 GPUVertFormat *DRW_shgroup_instance_format_array(const DRWInstanceAttrFormat attrs[],
1335                                                  int arraysize)
1336 {
1337   GPUVertFormat *format = MEM_callocN(sizeof(GPUVertFormat), "GPUVertFormat");
1338 
1339   for (int i = 0; i < arraysize; i++) {
1340     GPU_vertformat_attr_add(format,
1341                             attrs[i].name,
1342                             (attrs[i].type == DRW_ATTR_INT) ? GPU_COMP_I32 : GPU_COMP_F32,
1343                             attrs[i].components,
1344                             (attrs[i].type == DRW_ATTR_INT) ? GPU_FETCH_INT : GPU_FETCH_FLOAT);
1345   }
1346   return format;
1347 }
1348 
DRW_shgroup_material_create(struct GPUMaterial * material,DRWPass * pass)1349 DRWShadingGroup *DRW_shgroup_material_create(struct GPUMaterial *material, DRWPass *pass)
1350 {
1351   GPUPass *gpupass = GPU_material_get_pass(material);
1352   DRWShadingGroup *shgroup = drw_shgroup_material_create_ex(gpupass, pass);
1353 
1354   if (shgroup) {
1355     drw_shgroup_init(shgroup, GPU_pass_shader_get(gpupass));
1356     DRW_shgroup_add_material_resources(shgroup, material);
1357   }
1358   return shgroup;
1359 }
1360 
DRW_shgroup_create(struct GPUShader * shader,DRWPass * pass)1361 DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass)
1362 {
1363   DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass);
1364   drw_shgroup_init(shgroup, shader);
1365   return shgroup;
1366 }
1367 
DRW_shgroup_transform_feedback_create(struct GPUShader * shader,DRWPass * pass,GPUVertBuf * tf_target)1368 DRWShadingGroup *DRW_shgroup_transform_feedback_create(struct GPUShader *shader,
1369                                                        DRWPass *pass,
1370                                                        GPUVertBuf *tf_target)
1371 {
1372   BLI_assert(tf_target != NULL);
1373   DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass);
1374   drw_shgroup_init(shgroup, shader);
1375   drw_shgroup_uniform_create_ex(shgroup, 0, DRW_UNIFORM_TFEEDBACK_TARGET, tf_target, 0, 0, 1);
1376   return shgroup;
1377 }
1378 
1379 /**
1380  * State is added to #Pass.state while drawing.
1381  * Use to temporarily enable draw options.
1382  */
DRW_shgroup_state_enable(DRWShadingGroup * shgroup,DRWState state)1383 void DRW_shgroup_state_enable(DRWShadingGroup *shgroup, DRWState state)
1384 {
1385   drw_command_set_mutable_state(shgroup, state, 0x0);
1386 }
1387 
DRW_shgroup_state_disable(DRWShadingGroup * shgroup,DRWState state)1388 void DRW_shgroup_state_disable(DRWShadingGroup *shgroup, DRWState state)
1389 {
1390   drw_command_set_mutable_state(shgroup, 0x0, state);
1391 }
1392 
DRW_shgroup_stencil_set(DRWShadingGroup * shgroup,uint write_mask,uint reference,uint compare_mask)1393 void DRW_shgroup_stencil_set(DRWShadingGroup *shgroup,
1394                              uint write_mask,
1395                              uint reference,
1396                              uint compare_mask)
1397 {
1398   drw_command_set_stencil_mask(shgroup, write_mask, reference, compare_mask);
1399 }
1400 
1401 /* TODO remove this function. */
DRW_shgroup_stencil_mask(DRWShadingGroup * shgroup,uint mask)1402 void DRW_shgroup_stencil_mask(DRWShadingGroup *shgroup, uint mask)
1403 {
1404   drw_command_set_stencil_mask(shgroup, 0xFF, mask, 0xFF);
1405 }
1406 
DRW_shgroup_clear_framebuffer(DRWShadingGroup * shgroup,eGPUFrameBufferBits channels,uchar r,uchar g,uchar b,uchar a,float depth,uchar stencil)1407 void DRW_shgroup_clear_framebuffer(DRWShadingGroup *shgroup,
1408                                    eGPUFrameBufferBits channels,
1409                                    uchar r,
1410                                    uchar g,
1411                                    uchar b,
1412                                    uchar a,
1413                                    float depth,
1414                                    uchar stencil)
1415 {
1416   drw_command_clear(shgroup, channels, r, g, b, a, depth, stencil);
1417 }
1418 
DRW_shgroup_is_empty(DRWShadingGroup * shgroup)1419 bool DRW_shgroup_is_empty(DRWShadingGroup *shgroup)
1420 {
1421   DRWCommandChunk *chunk = shgroup->cmd.first;
1422   for (; chunk; chunk = chunk->next) {
1423     for (int i = 0; i < chunk->command_used; i++) {
1424       if (command_type_get(chunk->command_type, i) <= DRW_MAX_DRAW_CMD_TYPE) {
1425         return false;
1426       }
1427     }
1428   }
1429   return true;
1430 }
1431 
DRW_shgroup_create_sub(DRWShadingGroup * shgroup)1432 DRWShadingGroup *DRW_shgroup_create_sub(DRWShadingGroup *shgroup)
1433 {
1434   DRWShadingGroup *shgroup_new = BLI_memblock_alloc(DST.vmempool->shgroups);
1435 
1436   *shgroup_new = *shgroup;
1437   drw_shgroup_init(shgroup_new, shgroup_new->shader);
1438   shgroup_new->cmd.first = NULL;
1439   shgroup_new->cmd.last = NULL;
1440 
1441   DRWPass *parent_pass = DRW_memblock_elem_from_handle(DST.vmempool->passes,
1442                                                        &shgroup->pass_handle);
1443 
1444   BLI_LINKS_INSERT_AFTER(&parent_pass->shgroups, shgroup, shgroup_new);
1445 
1446   return shgroup_new;
1447 }
1448 
1449 /** \} */
1450 
1451 /* -------------------------------------------------------------------- */
1452 /** \name View (DRW_view)
1453  * \{ */
1454 
1455 /* Extract the 8 corners from a Projection Matrix.
1456  * Although less accurate, this solution can be simplified as follows:
1457  * BKE_boundbox_init_from_minmax(&bbox, (const float[3]){-1.0f, -1.0f, -1.0f}, (const
1458  * float[3]){1.0f, 1.0f, 1.0f}); for (int i = 0; i < 8; i++) {mul_project_m4_v3(projinv,
1459  * bbox.vec[i]);}
1460  */
draw_frustum_boundbox_calc(const float (* viewinv)[4],const float (* projmat)[4],BoundBox * r_bbox)1461 static void draw_frustum_boundbox_calc(const float (*viewinv)[4],
1462                                        const float (*projmat)[4],
1463                                        BoundBox *r_bbox)
1464 {
1465   float left, right, bottom, top, near, far;
1466   bool is_persp = projmat[3][3] == 0.0f;
1467 
1468 #if 0 /* Equivalent to this but it has accuracy problems. */
1469   BKE_boundbox_init_from_minmax(
1470       &bbox, (const float[3]){-1.0f, -1.0f, -1.0f}, (const float[3]){1.0f, 1.0f, 1.0f});
1471   for (int i = 0; i < 8; i++) {
1472     mul_project_m4_v3(projinv, bbox.vec[i]);
1473   }
1474 #endif
1475 
1476   projmat_dimensions(projmat, &left, &right, &bottom, &top, &near, &far);
1477 
1478   if (is_persp) {
1479     left *= near;
1480     right *= near;
1481     bottom *= near;
1482     top *= near;
1483   }
1484 
1485   r_bbox->vec[0][2] = r_bbox->vec[3][2] = r_bbox->vec[7][2] = r_bbox->vec[4][2] = -near;
1486   r_bbox->vec[0][0] = r_bbox->vec[3][0] = left;
1487   r_bbox->vec[4][0] = r_bbox->vec[7][0] = right;
1488   r_bbox->vec[0][1] = r_bbox->vec[4][1] = bottom;
1489   r_bbox->vec[7][1] = r_bbox->vec[3][1] = top;
1490 
1491   /* Get the coordinates of the far plane. */
1492   if (is_persp) {
1493     float sca_far = far / near;
1494     left *= sca_far;
1495     right *= sca_far;
1496     bottom *= sca_far;
1497     top *= sca_far;
1498   }
1499 
1500   r_bbox->vec[1][2] = r_bbox->vec[2][2] = r_bbox->vec[6][2] = r_bbox->vec[5][2] = -far;
1501   r_bbox->vec[1][0] = r_bbox->vec[2][0] = left;
1502   r_bbox->vec[6][0] = r_bbox->vec[5][0] = right;
1503   r_bbox->vec[1][1] = r_bbox->vec[5][1] = bottom;
1504   r_bbox->vec[2][1] = r_bbox->vec[6][1] = top;
1505 
1506   /* Transform into world space. */
1507   for (int i = 0; i < 8; i++) {
1508     mul_m4_v3(viewinv, r_bbox->vec[i]);
1509   }
1510 }
1511 
draw_frustum_culling_planes_calc(const float (* persmat)[4],float (* frustum_planes)[4])1512 static void draw_frustum_culling_planes_calc(const float (*persmat)[4], float (*frustum_planes)[4])
1513 {
1514   planes_from_projmat(persmat,
1515                       frustum_planes[0],
1516                       frustum_planes[5],
1517                       frustum_planes[3],
1518                       frustum_planes[1],
1519                       frustum_planes[4],
1520                       frustum_planes[2]);
1521 
1522   /* Normalize. */
1523   for (int p = 0; p < 6; p++) {
1524     frustum_planes[p][3] /= normalize_v3(frustum_planes[p]);
1525   }
1526 }
1527 
draw_frustum_bound_sphere_calc(const BoundBox * bbox,const float (* viewinv)[4],const float (* projmat)[4],const float (* projinv)[4],BoundSphere * bsphere)1528 static void draw_frustum_bound_sphere_calc(const BoundBox *bbox,
1529                                            const float (*viewinv)[4],
1530                                            const float (*projmat)[4],
1531                                            const float (*projinv)[4],
1532                                            BoundSphere *bsphere)
1533 {
1534   /* Extract Bounding Sphere */
1535   if (projmat[3][3] != 0.0f) {
1536     /* Orthographic */
1537     /* The most extreme points on the near and far plane. (normalized device coords). */
1538     const float *nearpoint = bbox->vec[0];
1539     const float *farpoint = bbox->vec[6];
1540 
1541     /* just use median point */
1542     mid_v3_v3v3(bsphere->center, farpoint, nearpoint);
1543     bsphere->radius = len_v3v3(bsphere->center, farpoint);
1544   }
1545   else if (projmat[2][0] == 0.0f && projmat[2][1] == 0.0f) {
1546     /* Perspective with symmetrical frustum. */
1547 
1548     /* We obtain the center and radius of the circumscribed circle of the
1549      * isosceles trapezoid composed by the diagonals of the near and far clipping plane */
1550 
1551     /* center of each clipping plane */
1552     float mid_min[3], mid_max[3];
1553     mid_v3_v3v3(mid_min, bbox->vec[3], bbox->vec[4]);
1554     mid_v3_v3v3(mid_max, bbox->vec[2], bbox->vec[5]);
1555 
1556     /* square length of the diagonals of each clipping plane */
1557     float a_sq = len_squared_v3v3(bbox->vec[3], bbox->vec[4]);
1558     float b_sq = len_squared_v3v3(bbox->vec[2], bbox->vec[5]);
1559 
1560     /* distance squared between clipping planes */
1561     float h_sq = len_squared_v3v3(mid_min, mid_max);
1562 
1563     float fac = (4 * h_sq + b_sq - a_sq) / (8 * h_sq);
1564 
1565     /* The goal is to get the smallest sphere,
1566      * not the sphere that passes through each corner */
1567     CLAMP(fac, 0.0f, 1.0f);
1568 
1569     interp_v3_v3v3(bsphere->center, mid_min, mid_max, fac);
1570 
1571     /* distance from the center to one of the points of the far plane (1, 2, 5, 6) */
1572     bsphere->radius = len_v3v3(bsphere->center, bbox->vec[1]);
1573   }
1574   else {
1575     /* Perspective with asymmetrical frustum. */
1576 
1577     /* We put the sphere center on the line that goes from origin
1578      * to the center of the far clipping plane. */
1579 
1580     /* Detect which of the corner of the far clipping plane is the farthest to the origin */
1581     float nfar[4];               /* most extreme far point in NDC space */
1582     float farxy[2];              /* farpoint projection onto the near plane */
1583     float farpoint[3] = {0.0f};  /* most extreme far point in camera coordinate */
1584     float nearpoint[3];          /* most extreme near point in camera coordinate */
1585     float farcenter[3] = {0.0f}; /* center of far cliping plane in camera coordinate */
1586     float F = -1.0f, N;          /* square distance of far and near point to origin */
1587     float f, n; /* distance of far and near point to z axis. f is always > 0 but n can be < 0 */
1588     float e, s; /* far and near clipping distance (<0) */
1589     float c;    /* slope of center line = distance of far clipping center
1590                  * to z axis / far clipping distance. */
1591     float z;    /* projection of sphere center on z axis (<0) */
1592 
1593     /* Find farthest corner and center of far clip plane. */
1594     float corner[3] = {1.0f, 1.0f, 1.0f}; /* in clip space */
1595     for (int i = 0; i < 4; i++) {
1596       float point[3];
1597       mul_v3_project_m4_v3(point, projinv, corner);
1598       float len = len_squared_v3(point);
1599       if (len > F) {
1600         copy_v3_v3(nfar, corner);
1601         copy_v3_v3(farpoint, point);
1602         F = len;
1603       }
1604       add_v3_v3(farcenter, point);
1605       /* rotate by 90 degree to walk through the 4 points of the far clip plane */
1606       float tmp = corner[0];
1607       corner[0] = -corner[1];
1608       corner[1] = tmp;
1609     }
1610 
1611     /* the far center is the average of the far clipping points */
1612     mul_v3_fl(farcenter, 0.25f);
1613     /* the extreme near point is the opposite point on the near clipping plane */
1614     copy_v3_fl3(nfar, -nfar[0], -nfar[1], -1.0f);
1615     mul_v3_project_m4_v3(nearpoint, projinv, nfar);
1616     /* this is a frustum projection */
1617     N = len_squared_v3(nearpoint);
1618     e = farpoint[2];
1619     s = nearpoint[2];
1620     /* distance to view Z axis */
1621     f = len_v2(farpoint);
1622     /* get corresponding point on the near plane */
1623     mul_v2_v2fl(farxy, farpoint, s / e);
1624     /* this formula preserve the sign of n */
1625     sub_v2_v2(nearpoint, farxy);
1626     n = f * s / e - len_v2(nearpoint);
1627     c = len_v2(farcenter) / e;
1628     /* the big formula, it simplifies to (F-N)/(2(e-s)) for the symmetric case */
1629     z = (F - N) / (2.0f * (e - s + c * (f - n)));
1630 
1631     bsphere->center[0] = farcenter[0] * z / e;
1632     bsphere->center[1] = farcenter[1] * z / e;
1633     bsphere->center[2] = z;
1634     bsphere->radius = len_v3v3(bsphere->center, farpoint);
1635 
1636     /* Transform to world space. */
1637     mul_m4_v3(viewinv, bsphere->center);
1638   }
1639 }
1640 
draw_view_matrix_state_update(DRWViewUboStorage * storage,const float viewmat[4][4],const float winmat[4][4])1641 static void draw_view_matrix_state_update(DRWViewUboStorage *storage,
1642                                           const float viewmat[4][4],
1643                                           const float winmat[4][4])
1644 {
1645   copy_m4_m4(storage->viewmat, viewmat);
1646   invert_m4_m4(storage->viewinv, storage->viewmat);
1647 
1648   copy_m4_m4(storage->winmat, winmat);
1649   invert_m4_m4(storage->wininv, storage->winmat);
1650 
1651   mul_m4_m4m4(storage->persmat, winmat, viewmat);
1652   invert_m4_m4(storage->persinv, storage->persmat);
1653 
1654   const bool is_persp = (winmat[3][3] == 0.0f);
1655 
1656   /* Near clip distance. */
1657   storage->viewvecs[0][3] = (is_persp) ? -winmat[3][2] / (winmat[2][2] - 1.0f) :
1658                                          -(winmat[3][2] + 1.0f) / winmat[2][2];
1659 
1660   /* Far clip distance. */
1661   storage->viewvecs[1][3] = (is_persp) ? -winmat[3][2] / (winmat[2][2] + 1.0f) :
1662                                          -(winmat[3][2] - 1.0f) / winmat[2][2];
1663 
1664   /* view vectors for the corners of the view frustum.
1665    * Can be used to recreate the world space position easily */
1666   float view_vecs[4][3] = {
1667       {-1.0f, -1.0f, -1.0f},
1668       {1.0f, -1.0f, -1.0f},
1669       {-1.0f, 1.0f, -1.0f},
1670       {-1.0f, -1.0f, 1.0f},
1671   };
1672 
1673   /* convert the view vectors to view space */
1674   for (int i = 0; i < 4; i++) {
1675     mul_project_m4_v3(storage->wininv, view_vecs[i]);
1676     /* normalized trick see:
1677      * http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */
1678     if (is_persp) {
1679       /* Divide XY by Z. */
1680       mul_v2_fl(view_vecs[i], 1.0f / view_vecs[i][2]);
1681     }
1682   }
1683 
1684   /**
1685    * If ortho : view_vecs[0] is the near-bottom-left corner of the frustum and
1686    *            view_vecs[1] is the vector going from the near-bottom-left corner to
1687    *            the far-top-right corner.
1688    * If Persp : view_vecs[0].xy and view_vecs[1].xy are respectively the bottom-left corner
1689    *            when Z = 1, and top-left corner if Z = 1.
1690    *            view_vecs[0].z the near clip distance and view_vecs[1].z is the (signed)
1691    *            distance from the near plane to the far clip plane.
1692    */
1693   copy_v3_v3(storage->viewvecs[0], view_vecs[0]);
1694 
1695   /* we need to store the differences */
1696   storage->viewvecs[1][0] = view_vecs[1][0] - view_vecs[0][0];
1697   storage->viewvecs[1][1] = view_vecs[2][1] - view_vecs[0][1];
1698   storage->viewvecs[1][2] = view_vecs[3][2] - view_vecs[0][2];
1699 }
1700 
1701 /* Create a view with culling. */
DRW_view_create(const float viewmat[4][4],const float winmat[4][4],const float (* culling_viewmat)[4],const float (* culling_winmat)[4],DRWCallVisibilityFn * visibility_fn)1702 DRWView *DRW_view_create(const float viewmat[4][4],
1703                          const float winmat[4][4],
1704                          const float (*culling_viewmat)[4],
1705                          const float (*culling_winmat)[4],
1706                          DRWCallVisibilityFn *visibility_fn)
1707 {
1708   DRWView *view = BLI_memblock_alloc(DST.vmempool->views);
1709 
1710   if (DST.primary_view_ct < MAX_CULLED_VIEWS) {
1711     view->culling_mask = 1u << DST.primary_view_ct++;
1712   }
1713   else {
1714     BLI_assert(0);
1715     view->culling_mask = 0u;
1716   }
1717   view->clip_planes_len = 0;
1718   view->visibility_fn = visibility_fn;
1719   view->parent = NULL;
1720 
1721   copy_v4_fl4(view->storage.viewcamtexcofac, 1.0f, 1.0f, 0.0f, 0.0f);
1722 
1723   DRW_view_update(view, viewmat, winmat, culling_viewmat, culling_winmat);
1724 
1725   return view;
1726 }
1727 
1728 /* Create a view with culling done by another view. */
DRW_view_create_sub(const DRWView * parent_view,const float viewmat[4][4],const float winmat[4][4])1729 DRWView *DRW_view_create_sub(const DRWView *parent_view,
1730                              const float viewmat[4][4],
1731                              const float winmat[4][4])
1732 {
1733   /* Search original parent. */
1734   const DRWView *ori_view = parent_view;
1735   while (ori_view->parent != NULL) {
1736     ori_view = ori_view->parent;
1737   }
1738 
1739   DRWView *view = BLI_memblock_alloc(DST.vmempool->views);
1740 
1741   /* Perform copy. */
1742   *view = *ori_view;
1743   view->parent = (DRWView *)ori_view;
1744 
1745   DRW_view_update_sub(view, viewmat, winmat);
1746 
1747   return view;
1748 }
1749 
1750 /**
1751  * DRWView Update:
1752  * This is meant to be done on existing views when rendering in a loop and there is no
1753  * need to allocate more DRWViews.
1754  **/
1755 
1756 /* Update matrices of a view created with DRW_view_create_sub. */
DRW_view_update_sub(DRWView * view,const float viewmat[4][4],const float winmat[4][4])1757 void DRW_view_update_sub(DRWView *view, const float viewmat[4][4], const float winmat[4][4])
1758 {
1759   BLI_assert(view->parent != NULL);
1760 
1761   view->is_dirty = true;
1762   view->is_inverted = (is_negative_m4(viewmat) == is_negative_m4(winmat));
1763 
1764   draw_view_matrix_state_update(&view->storage, viewmat, winmat);
1765 }
1766 
1767 /* Update matrices of a view created with DRW_view_create. */
DRW_view_update(DRWView * view,const float viewmat[4][4],const float winmat[4][4],const float (* culling_viewmat)[4],const float (* culling_winmat)[4])1768 void DRW_view_update(DRWView *view,
1769                      const float viewmat[4][4],
1770                      const float winmat[4][4],
1771                      const float (*culling_viewmat)[4],
1772                      const float (*culling_winmat)[4])
1773 {
1774   /* DO NOT UPDATE THE DEFAULT VIEW.
1775    * Create sub-views instead, or a copy. */
1776   BLI_assert(view != DST.view_default);
1777   BLI_assert(view->parent == NULL);
1778 
1779   view->is_dirty = true;
1780   view->is_inverted = (is_negative_m4(viewmat) == is_negative_m4(winmat));
1781 
1782   draw_view_matrix_state_update(&view->storage, viewmat, winmat);
1783 
1784   /* Prepare frustum culling. */
1785 
1786 #ifdef DRW_DEBUG_CULLING
1787   static float mv[MAX_CULLED_VIEWS][4][4], mw[MAX_CULLED_VIEWS][4][4];
1788 
1789   /* Select view here. */
1790   if (view->culling_mask != 0) {
1791     uint index = bitscan_forward_uint(view->culling_mask);
1792 
1793     if (G.debug_value == 0) {
1794       copy_m4_m4(mv[index], culling_viewmat ? culling_viewmat : viewmat);
1795       copy_m4_m4(mw[index], culling_winmat ? culling_winmat : winmat);
1796     }
1797     else {
1798       culling_winmat = mw[index];
1799       culling_viewmat = mv[index];
1800     }
1801   }
1802 #endif
1803 
1804   float wininv[4][4];
1805   if (culling_winmat) {
1806     winmat = culling_winmat;
1807     invert_m4_m4(wininv, winmat);
1808   }
1809   else {
1810     copy_m4_m4(wininv, view->storage.wininv);
1811   }
1812 
1813   float viewinv[4][4];
1814   if (culling_viewmat) {
1815     viewmat = culling_viewmat;
1816     invert_m4_m4(viewinv, viewmat);
1817   }
1818   else {
1819     copy_m4_m4(viewinv, view->storage.viewinv);
1820   }
1821 
1822   draw_frustum_boundbox_calc(viewinv, winmat, &view->frustum_corners);
1823   draw_frustum_culling_planes_calc(view->storage.persmat, view->frustum_planes);
1824   draw_frustum_bound_sphere_calc(
1825       &view->frustum_corners, viewinv, winmat, wininv, &view->frustum_bsphere);
1826 
1827 #ifdef DRW_DEBUG_CULLING
1828   if (G.debug_value != 0) {
1829     DRW_debug_sphere(
1830         view->frustum_bsphere.center, view->frustum_bsphere.radius, (const float[4]){1, 1, 0, 1});
1831     DRW_debug_bbox(&view->frustum_corners, (const float[4]){1, 1, 0, 1});
1832   }
1833 #endif
1834 }
1835 
1836 /* Return default view if it is a viewport render. */
DRW_view_default_get(void)1837 const DRWView *DRW_view_default_get(void)
1838 {
1839   return DST.view_default;
1840 }
1841 
1842 /* WARNING: Only use in render AND only if you are going to set view_default again. */
DRW_view_reset(void)1843 void DRW_view_reset(void)
1844 {
1845   DST.view_default = NULL;
1846   DST.view_active = NULL;
1847   DST.view_previous = NULL;
1848 }
1849 
1850 /* MUST only be called once per render and only in render mode. Sets default view. */
DRW_view_default_set(DRWView * view)1851 void DRW_view_default_set(DRWView *view)
1852 {
1853   BLI_assert(DST.view_default == NULL);
1854   DST.view_default = view;
1855 }
1856 
1857 /**
1858  * This only works if DRWPasses have been tagged with DRW_STATE_CLIP_PLANES,
1859  * and if the shaders have support for it (see usage of gl_ClipDistance).
1860  * NOTE: planes must be in world space.
1861  */
DRW_view_clip_planes_set(DRWView * view,float (* planes)[4],int plane_len)1862 void DRW_view_clip_planes_set(DRWView *view, float (*planes)[4], int plane_len)
1863 {
1864   BLI_assert(plane_len <= MAX_CLIP_PLANES);
1865   view->clip_planes_len = plane_len;
1866   if (plane_len > 0) {
1867     memcpy(view->storage.clipplanes, planes, sizeof(float[4]) * plane_len);
1868   }
1869 }
1870 
DRW_view_camtexco_set(DRWView * view,float texco[4])1871 void DRW_view_camtexco_set(DRWView *view, float texco[4])
1872 {
1873   copy_v4_v4(view->storage.viewcamtexcofac, texco);
1874 }
1875 
1876 /* Return world space frustum corners. */
DRW_view_frustum_corners_get(const DRWView * view,BoundBox * corners)1877 void DRW_view_frustum_corners_get(const DRWView *view, BoundBox *corners)
1878 {
1879   memcpy(corners, &view->frustum_corners, sizeof(view->frustum_corners));
1880 }
1881 
1882 /* Return world space frustum sides as planes.
1883  * See draw_frustum_culling_planes_calc() for the plane order. */
DRW_view_frustum_planes_get(const DRWView * view,float planes[6][4])1884 void DRW_view_frustum_planes_get(const DRWView *view, float planes[6][4])
1885 {
1886   memcpy(planes, &view->frustum_planes, sizeof(view->frustum_planes));
1887 }
1888 
DRW_view_is_persp_get(const DRWView * view)1889 bool DRW_view_is_persp_get(const DRWView *view)
1890 {
1891   view = (view) ? view : DST.view_default;
1892   return view->storage.winmat[3][3] == 0.0f;
1893 }
1894 
DRW_view_near_distance_get(const DRWView * view)1895 float DRW_view_near_distance_get(const DRWView *view)
1896 {
1897   view = (view) ? view : DST.view_default;
1898   const float(*projmat)[4] = view->storage.winmat;
1899 
1900   if (DRW_view_is_persp_get(view)) {
1901     return -projmat[3][2] / (projmat[2][2] - 1.0f);
1902   }
1903 
1904   return -(projmat[3][2] + 1.0f) / projmat[2][2];
1905 }
1906 
DRW_view_far_distance_get(const DRWView * view)1907 float DRW_view_far_distance_get(const DRWView *view)
1908 {
1909   view = (view) ? view : DST.view_default;
1910   const float(*projmat)[4] = view->storage.winmat;
1911 
1912   if (DRW_view_is_persp_get(view)) {
1913     return -projmat[3][2] / (projmat[2][2] + 1.0f);
1914   }
1915 
1916   return -(projmat[3][2] - 1.0f) / projmat[2][2];
1917 }
1918 
DRW_view_viewmat_get(const DRWView * view,float mat[4][4],bool inverse)1919 void DRW_view_viewmat_get(const DRWView *view, float mat[4][4], bool inverse)
1920 {
1921   view = (view) ? view : DST.view_default;
1922   const DRWViewUboStorage *storage = &view->storage;
1923   copy_m4_m4(mat, (inverse) ? storage->viewinv : storage->viewmat);
1924 }
1925 
DRW_view_winmat_get(const DRWView * view,float mat[4][4],bool inverse)1926 void DRW_view_winmat_get(const DRWView *view, float mat[4][4], bool inverse)
1927 {
1928   view = (view) ? view : DST.view_default;
1929   const DRWViewUboStorage *storage = &view->storage;
1930   copy_m4_m4(mat, (inverse) ? storage->wininv : storage->winmat);
1931 }
1932 
DRW_view_persmat_get(const DRWView * view,float mat[4][4],bool inverse)1933 void DRW_view_persmat_get(const DRWView *view, float mat[4][4], bool inverse)
1934 {
1935   view = (view) ? view : DST.view_default;
1936   const DRWViewUboStorage *storage = &view->storage;
1937   copy_m4_m4(mat, (inverse) ? storage->persinv : storage->persmat);
1938 }
1939 
1940 /** \} */
1941 
1942 /* -------------------------------------------------------------------- */
1943 /** \name Passes (DRW_pass)
1944  * \{ */
1945 
DRW_pass_create(const char * name,DRWState state)1946 DRWPass *DRW_pass_create(const char *name, DRWState state)
1947 {
1948   DRWPass *pass = BLI_memblock_alloc(DST.vmempool->passes);
1949   pass->state = state | DRW_STATE_PROGRAM_POINT_SIZE;
1950   if (G.debug & G_DEBUG_GPU) {
1951     BLI_strncpy(pass->name, name, MAX_PASS_NAME);
1952   }
1953 
1954   pass->shgroups.first = NULL;
1955   pass->shgroups.last = NULL;
1956   pass->handle = DST.pass_handle;
1957   DRW_handle_increment(&DST.pass_handle);
1958 
1959   pass->original = NULL;
1960   pass->next = NULL;
1961 
1962   return pass;
1963 }
1964 
1965 /* Create an instance of the original pass that will execute the same drawcalls but with its own
1966  * DRWState. */
DRW_pass_create_instance(const char * name,DRWPass * original,DRWState state)1967 DRWPass *DRW_pass_create_instance(const char *name, DRWPass *original, DRWState state)
1968 {
1969   DRWPass *pass = DRW_pass_create(name, state);
1970   pass->original = original;
1971 
1972   return pass;
1973 }
1974 
1975 /* Link two passes so that they are both rendered if the first one is being drawn. */
DRW_pass_link(DRWPass * first,DRWPass * second)1976 void DRW_pass_link(DRWPass *first, DRWPass *second)
1977 {
1978   BLI_assert(first != second);
1979   BLI_assert(first->next == NULL);
1980   first->next = second;
1981 }
1982 
DRW_pass_is_empty(DRWPass * pass)1983 bool DRW_pass_is_empty(DRWPass *pass)
1984 {
1985   if (pass->original) {
1986     return DRW_pass_is_empty(pass->original);
1987   }
1988 
1989   LISTBASE_FOREACH (DRWShadingGroup *, shgroup, &pass->shgroups) {
1990     if (!DRW_shgroup_is_empty(shgroup)) {
1991       return false;
1992     }
1993   }
1994   return true;
1995 }
1996 
DRW_pass_foreach_shgroup(DRWPass * pass,void (* callback)(void * userData,DRWShadingGroup * shgrp),void * userData)1997 void DRW_pass_foreach_shgroup(DRWPass *pass,
1998                               void (*callback)(void *userData, DRWShadingGroup *shgrp),
1999                               void *userData)
2000 {
2001   LISTBASE_FOREACH (DRWShadingGroup *, shgroup, &pass->shgroups) {
2002     callback(userData, shgroup);
2003   }
2004 }
2005 
pass_shgroup_dist_sort(const void * a,const void * b)2006 static int pass_shgroup_dist_sort(const void *a, const void *b)
2007 {
2008   const DRWShadingGroup *shgrp_a = (const DRWShadingGroup *)a;
2009   const DRWShadingGroup *shgrp_b = (const DRWShadingGroup *)b;
2010 
2011   if (shgrp_a->z_sorting.distance < shgrp_b->z_sorting.distance) {
2012     return 1;
2013   }
2014   if (shgrp_a->z_sorting.distance > shgrp_b->z_sorting.distance) {
2015     return -1;
2016   }
2017 
2018   /* If distances are the same, keep original order. */
2019   if (shgrp_a->z_sorting.original_index > shgrp_b->z_sorting.original_index) {
2020     return -1;
2021   }
2022 
2023   return 0;
2024 }
2025 
2026 /* ------------------ Shading group sorting --------------------- */
2027 
2028 #define SORT_IMPL_LINKTYPE DRWShadingGroup
2029 
2030 #define SORT_IMPL_FUNC shgroup_sort_fn_r
2031 #include "../../blenlib/intern/list_sort_impl.h"
2032 #undef SORT_IMPL_FUNC
2033 
2034 #undef SORT_IMPL_LINKTYPE
2035 
2036 /**
2037  * Sort Shading groups by decreasing Z of their first draw call.
2038  * This is useful for order dependent effect such as alpha-blending.
2039  */
DRW_pass_sort_shgroup_z(DRWPass * pass)2040 void DRW_pass_sort_shgroup_z(DRWPass *pass)
2041 {
2042   const float(*viewinv)[4] = DST.view_active->storage.viewinv;
2043 
2044   if (!(pass->shgroups.first && pass->shgroups.first->next)) {
2045     /* Nothing to sort */
2046     return;
2047   }
2048 
2049   uint index = 0;
2050   DRWShadingGroup *shgroup = pass->shgroups.first;
2051   do {
2052     DRWResourceHandle handle = 0;
2053     /* Find first DRWCommandDraw. */
2054     DRWCommandChunk *cmd_chunk = shgroup->cmd.first;
2055     for (; cmd_chunk && handle == 0; cmd_chunk = cmd_chunk->next) {
2056       for (int i = 0; i < cmd_chunk->command_used && handle == 0; i++) {
2057         if (DRW_CMD_DRAW == command_type_get(cmd_chunk->command_type, i)) {
2058           handle = cmd_chunk->commands[i].draw.handle;
2059         }
2060       }
2061     }
2062     /* To be sorted a shgroup needs to have at least one draw command.  */
2063     /* FIXME(fclem) In some case, we can still have empty shading group to sort. However their
2064      * final order is not well defined.
2065      * (see T76730 & D7729). */
2066     // BLI_assert(handle != 0);
2067 
2068     DRWObjectMatrix *obmats = DRW_memblock_elem_from_handle(DST.vmempool->obmats, &handle);
2069 
2070     /* Compute distance to camera. */
2071     float tmp[3];
2072     sub_v3_v3v3(tmp, viewinv[3], obmats->model[3]);
2073     shgroup->z_sorting.distance = dot_v3v3(viewinv[2], tmp);
2074     shgroup->z_sorting.original_index = index++;
2075 
2076   } while ((shgroup = shgroup->next));
2077 
2078   /* Sort using computed distances. */
2079   pass->shgroups.first = shgroup_sort_fn_r(pass->shgroups.first, pass_shgroup_dist_sort);
2080 
2081   /* Find the new last */
2082   DRWShadingGroup *last = pass->shgroups.first;
2083   while ((last = last->next)) {
2084     /* Reset the pass id for debugging. */
2085     last->pass_handle = pass->handle;
2086   }
2087   pass->shgroups.last = last;
2088 }
2089 
2090 /**
2091  * Reverse Shading group submission order.
2092  */
DRW_pass_sort_shgroup_reverse(DRWPass * pass)2093 void DRW_pass_sort_shgroup_reverse(DRWPass *pass)
2094 {
2095   pass->shgroups.last = pass->shgroups.first;
2096   /* WARNING: Assume that DRWShadingGroup->next is the first member. */
2097   BLI_linklist_reverse((LinkNode **)&pass->shgroups.first);
2098 }
2099 
2100 /** \} */
2101