Cleanup: preprocessor indentation
[blender.git] / source / blender / draw / intern / draw_manager_exec.c
1 /*
2  * Copyright 2016, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Blender Institute
19  *
20  */
21
22 /** \file blender/draw/intern/draw_manager_exec.c
23  *  \ingroup draw
24  */
25
26 #include "draw_manager.h"
27
28 #include "BLI_mempool.h"
29
30 #include "BIF_glutil.h"
31
32 #include "BKE_global.h"
33 #include "BKE_object.h"
34
35 #include "GPU_draw.h"
36 #include "GPU_extensions.h"
37 #include "intern/gpu_shader_private.h"
38
39 #ifdef USE_GPU_SELECT
40 #  include "ED_view3d.h"
41 #  include "ED_armature.h"
42 #  include "GPU_select.h"
43 #endif
44
45 #ifdef USE_GPU_SELECT
46 void DRW_select_load_id(uint id)
47 {
48         BLI_assert(G.f & G_PICKSEL);
49         DST.select_id = id;
50 }
51 #endif
52
53 #define DEBUG_UBO_BINDING
54
55 struct GPUUniformBuffer *view_ubo;
56
57 /* -------------------------------------------------------------------- */
58
59 /** \name Draw State (DRW_state)
60  * \{ */
61
62 void drw_state_set(DRWState state)
63 {
64         if (DST.state == state) {
65                 return;
66         }
67
68 #define CHANGED_TO(f) \
69         ((DST.state_lock & (f)) ? 0 : \
70          (((DST.state & (f)) ? \
71            ((state & (f)) ?  0 : -1) : \
72            ((state & (f)) ?  1 :  0))))
73
74 #define CHANGED_ANY(f) \
75         (((DST.state & (f)) != (state & (f))) && \
76          ((DST.state_lock & (f)) == 0))
77
78 #define CHANGED_ANY_STORE_VAR(f, enabled) \
79         (((DST.state & (f)) != (enabled = (state & (f)))) && \
80          (((DST.state_lock & (f)) == 0)))
81
82         /* Depth Write */
83         {
84                 int test;
85                 if ((test = CHANGED_TO(DRW_STATE_WRITE_DEPTH))) {
86                         if (test == 1) {
87                                 glDepthMask(GL_TRUE);
88                         }
89                         else {
90                                 glDepthMask(GL_FALSE);
91                         }
92                 }
93         }
94
95         /* Color Write */
96         {
97                 int test;
98                 if ((test = CHANGED_TO(DRW_STATE_WRITE_COLOR))) {
99                         if (test == 1) {
100                                 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
101                         }
102                         else {
103                                 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
104                         }
105                 }
106         }
107
108         /* Raster Discard */
109         {
110                 if (CHANGED_ANY(DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR |
111                                 DRW_STATE_WRITE_STENCIL |
112                                 DRW_STATE_WRITE_STENCIL_SHADOW_PASS |
113                                 DRW_STATE_WRITE_STENCIL_SHADOW_FAIL))
114                 {
115                         if ((state & (DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR |
116                                       DRW_STATE_WRITE_STENCIL | DRW_STATE_WRITE_STENCIL_SHADOW_PASS |
117                                       DRW_STATE_WRITE_STENCIL_SHADOW_FAIL)) != 0)
118                         {
119                                 glDisable(GL_RASTERIZER_DISCARD);
120                         }
121                         else {
122                                 glEnable(GL_RASTERIZER_DISCARD);
123                         }
124                 }
125         }
126
127         /* Cull */
128         {
129                 DRWState test;
130                 if (CHANGED_ANY_STORE_VAR(
131                         DRW_STATE_CULL_BACK | DRW_STATE_CULL_FRONT,
132                         test))
133                 {
134                         if (test) {
135                                 glEnable(GL_CULL_FACE);
136
137                                 if ((state & DRW_STATE_CULL_BACK) != 0) {
138                                         glCullFace(GL_BACK);
139                                 }
140                                 else if ((state & DRW_STATE_CULL_FRONT) != 0) {
141                                         glCullFace(GL_FRONT);
142                                 }
143                                 else {
144                                         BLI_assert(0);
145                                 }
146                         }
147                         else {
148                                 glDisable(GL_CULL_FACE);
149                         }
150                 }
151         }
152
153         /* Depth Test */
154         {
155                 DRWState test;
156                 if (CHANGED_ANY_STORE_VAR(
157                         DRW_STATE_DEPTH_LESS | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_DEPTH_EQUAL |
158                         DRW_STATE_DEPTH_GREATER | DRW_STATE_DEPTH_GREATER_EQUAL | DRW_STATE_DEPTH_ALWAYS,
159                         test))
160                 {
161                         if (test) {
162                                 glEnable(GL_DEPTH_TEST);
163
164                                 if (state & DRW_STATE_DEPTH_LESS) {
165                                         glDepthFunc(GL_LESS);
166                                 }
167                                 else if (state & DRW_STATE_DEPTH_LESS_EQUAL) {
168                                         glDepthFunc(GL_LEQUAL);
169                                 }
170                                 else if (state & DRW_STATE_DEPTH_EQUAL) {
171                                         glDepthFunc(GL_EQUAL);
172                                 }
173                                 else if (state & DRW_STATE_DEPTH_GREATER) {
174                                         glDepthFunc(GL_GREATER);
175                                 }
176                                 else if (state & DRW_STATE_DEPTH_GREATER_EQUAL) {
177                                         glDepthFunc(GL_GEQUAL);
178                                 }
179                                 else if (state & DRW_STATE_DEPTH_ALWAYS) {
180                                         glDepthFunc(GL_ALWAYS);
181                                 }
182                                 else {
183                                         BLI_assert(0);
184                                 }
185                         }
186                         else {
187                                 glDisable(GL_DEPTH_TEST);
188                         }
189                 }
190         }
191
192         /* Wire Width */
193         {
194                 if (CHANGED_ANY(DRW_STATE_WIRE | DRW_STATE_WIRE_SMOOTH)) {
195                         if ((state & DRW_STATE_WIRE_SMOOTH) != 0) {
196                                 GPU_line_width(2.0f);
197                                 GPU_line_smooth(true);
198                         }
199                         else if ((state & DRW_STATE_WIRE) != 0) {
200                                 GPU_line_width(1.0f);
201                         }
202                         else {
203                                 GPU_line_smooth(false);
204                         }
205                 }
206         }
207
208         /* Points Size */
209         {
210                 int test;
211                 if ((test = CHANGED_TO(DRW_STATE_POINT))) {
212                         if (test == 1) {
213                                 GPU_enable_program_point_size();
214                                 glPointSize(5.0f);
215                         }
216                         else {
217                                 GPU_disable_program_point_size();
218                         }
219                 }
220         }
221
222         /* Blending (all buffer) */
223         {
224                 int test;
225                 if (CHANGED_ANY_STORE_VAR(
226                         DRW_STATE_BLEND | DRW_STATE_BLEND_PREMUL | DRW_STATE_ADDITIVE |
227                         DRW_STATE_MULTIPLY | DRW_STATE_ADDITIVE_FULL |
228                         DRW_STATE_BLEND_OIT,
229                         test))
230                 {
231                         if (test) {
232                                 glEnable(GL_BLEND);
233
234                                 if ((state & DRW_STATE_BLEND) != 0) {
235                                         glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, /* RGB */
236                                                             GL_ONE, GL_ONE_MINUS_SRC_ALPHA); /* Alpha */
237                                 }
238                                 else if ((state & DRW_STATE_BLEND_PREMUL) != 0) {
239                                         glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
240                                 }
241                                 else if ((state & DRW_STATE_MULTIPLY) != 0) {
242                                         glBlendFunc(GL_DST_COLOR, GL_ZERO);
243                                 }
244                                 else if ((state & DRW_STATE_BLEND_OIT) != 0) {
245                                         glBlendFuncSeparate(GL_ONE, GL_ONE, /* RGB */
246                                                             GL_ZERO, GL_ONE_MINUS_SRC_ALPHA); /* Alpha */
247                                 }
248                                 else if ((state & DRW_STATE_ADDITIVE) != 0) {
249                                         /* Do not let alpha accumulate but premult the source RGB by it. */
250                                         glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, /* RGB */
251                                                             GL_ZERO, GL_ONE); /* Alpha */
252                                 }
253                                 else if ((state & DRW_STATE_ADDITIVE_FULL) != 0) {
254                                         /* Let alpha accumulate. */
255                                         glBlendFunc(GL_ONE, GL_ONE);
256                                 }
257                                 else {
258                                         BLI_assert(0);
259                                 }
260                         }
261                         else {
262                                 glDisable(GL_BLEND);
263                                 glBlendFunc(GL_ONE, GL_ONE); /* Don't multiply incoming color by alpha. */
264                         }
265                 }
266         }
267
268         /* Clip Planes */
269         {
270                 int test;
271                 if ((test = CHANGED_TO(DRW_STATE_CLIP_PLANES))) {
272                         if (test == 1) {
273                                 for (int i = 0; i < DST.num_clip_planes; ++i) {
274                                         glEnable(GL_CLIP_DISTANCE0 + i);
275                                 }
276                         }
277                         else {
278                                 for (int i = 0; i < MAX_CLIP_PLANES; ++i) {
279                                         glDisable(GL_CLIP_DISTANCE0 + i);
280                                 }
281                         }
282                 }
283         }
284
285         /* Stencil */
286         {
287                 DRWState test;
288                 if (CHANGED_ANY_STORE_VAR(
289                         DRW_STATE_WRITE_STENCIL |
290                         DRW_STATE_WRITE_STENCIL_SHADOW_PASS |
291                         DRW_STATE_WRITE_STENCIL_SHADOW_FAIL |
292                         DRW_STATE_STENCIL_EQUAL |
293                         DRW_STATE_STENCIL_NEQUAL,
294                         test))
295                 {
296                         if (test) {
297                                 glEnable(GL_STENCIL_TEST);
298                                 /* Stencil Write */
299                                 if ((state & DRW_STATE_WRITE_STENCIL) != 0) {
300                                         glStencilMask(0xFF);
301                                         glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
302                                 }
303                                 else if ((state & DRW_STATE_WRITE_STENCIL_SHADOW_PASS) != 0) {
304                                         glStencilMask(0xFF);
305                                         glStencilOpSeparate(GL_BACK,  GL_KEEP, GL_KEEP, GL_INCR_WRAP);
306                                         glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_DECR_WRAP);
307                                 }
308                                 else if ((state & DRW_STATE_WRITE_STENCIL_SHADOW_FAIL) != 0) {
309                                         glStencilMask(0xFF);
310                                         glStencilOpSeparate(GL_BACK,  GL_KEEP, GL_DECR_WRAP, GL_KEEP);
311                                         glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_INCR_WRAP, GL_KEEP);
312                                 }
313                                 /* Stencil Test */
314                                 else if ((state & (DRW_STATE_STENCIL_EQUAL | DRW_STATE_STENCIL_NEQUAL)) != 0) {
315                                         glStencilMask(0x00); /* disable write */
316                                         DST.stencil_mask = STENCIL_UNDEFINED;
317                                 }
318                                 else {
319                                         BLI_assert(0);
320                                 }
321                         }
322                         else {
323                                 /* disable write & test */
324                                 DST.stencil_mask = 0;
325                                 glStencilMask(0x00);
326                                 glStencilFunc(GL_ALWAYS, 0, 0xFF);
327                                 glDisable(GL_STENCIL_TEST);
328                         }
329                 }
330         }
331
332         /* Provoking Vertex */
333         {
334                 int test;
335                 if ((test = CHANGED_TO(DRW_STATE_FIRST_VERTEX_CONVENTION))) {
336                         if (test == 1) {
337                                 glProvokingVertex(GL_FIRST_VERTEX_CONVENTION);
338                         }
339                         else {
340                                 glProvokingVertex(GL_LAST_VERTEX_CONVENTION);
341                         }
342                 }
343         }
344
345         /* Polygon Offset */
346         {
347                 int test;
348                 if (CHANGED_ANY_STORE_VAR(
349                         DRW_STATE_OFFSET_POSITIVE |
350                         DRW_STATE_OFFSET_NEGATIVE,
351                         test))
352                 {
353                         if (test) {
354                                 glEnable(GL_POLYGON_OFFSET_FILL);
355                                 glEnable(GL_POLYGON_OFFSET_LINE);
356                                 glEnable(GL_POLYGON_OFFSET_POINT);
357                                 /* Stencil Write */
358                                 if ((state & DRW_STATE_OFFSET_POSITIVE) != 0) {
359                                         glPolygonOffset(1.0f, 1.0f);
360                                 }
361                                 else if ((state & DRW_STATE_OFFSET_NEGATIVE) != 0) {
362                                         glPolygonOffset(-1.0f, -1.0f);
363                                 }
364                                 else {
365                                         BLI_assert(0);
366                                 }
367                         }
368                         else {
369                                 glDisable(GL_POLYGON_OFFSET_FILL);
370                                 glDisable(GL_POLYGON_OFFSET_LINE);
371                                 glDisable(GL_POLYGON_OFFSET_POINT);
372                         }
373                 }
374         }
375
376 #undef CHANGED_TO
377 #undef CHANGED_ANY
378 #undef CHANGED_ANY_STORE_VAR
379
380         DST.state = state;
381 }
382
383 static void drw_stencil_set(uint mask)
384 {
385         if (DST.stencil_mask != mask) {
386                 DST.stencil_mask = mask;
387                 /* Stencil Write */
388                 if ((DST.state & DRW_STATE_WRITE_STENCIL) != 0) {
389                         glStencilFunc(GL_ALWAYS, mask, 0xFF);
390                 }
391                 /* Stencil Test */
392                 else if ((DST.state & DRW_STATE_STENCIL_EQUAL) != 0) {
393                         glStencilFunc(GL_EQUAL, mask, 0xFF);
394                 }
395                 else if ((DST.state & DRW_STATE_STENCIL_NEQUAL) != 0) {
396                         glStencilFunc(GL_NOTEQUAL, mask, 0xFF);
397                 }
398         }
399 }
400
401 /* Reset state to not interfer with other UI drawcall */
402 void DRW_state_reset_ex(DRWState state)
403 {
404         DST.state = ~state;
405         drw_state_set(state);
406 }
407
408 /**
409  * Use with care, intended so selection code can override passes depth settings,
410  * which is important for selection to work properly.
411  *
412  * Should be set in main draw loop, cleared afterwards
413  */
414 void DRW_state_lock(DRWState state)
415 {
416         DST.state_lock = state;
417 }
418
419 void DRW_state_reset(void)
420 {
421         DRW_state_reset_ex(DRW_STATE_DEFAULT);
422
423         /* Reset blending function */
424         glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
425 }
426
427 /* NOTE : Make sure to reset after use! */
428 void DRW_state_invert_facing(void)
429 {
430         SWAP(GLenum, DST.backface, DST.frontface);
431         glFrontFace(DST.frontface);
432 }
433
434 /**
435  * This only works if DRWPasses have been tagged with DRW_STATE_CLIP_PLANES,
436  * and if the shaders have support for it (see usage of gl_ClipDistance).
437  * Be sure to call DRW_state_clip_planes_reset() after you finish drawing.
438  **/
439 void DRW_state_clip_planes_count_set(uint plane_len)
440 {
441         BLI_assert(plane_len <= MAX_CLIP_PLANES);
442         DST.num_clip_planes = plane_len;
443 }
444
445 void DRW_state_clip_planes_reset(void)
446 {
447         DST.num_clip_planes = 0;
448 }
449
450 /** \} */
451
452 /* -------------------------------------------------------------------- */
453
454 /** \name Clipping (DRW_clipping)
455  * \{ */
456
457 /* Extract the 8 corners from a Projection Matrix.
458  * Although less accurate, this solution can be simplified as follows:
459  * BKE_boundbox_init_from_minmax(&bbox, (const float[3]){-1.0f, -1.0f, -1.0f}, (const float[3]){1.0f, 1.0f, 1.0f});
460  * for (int i = 0; i < 8; i++) {mul_project_m4_v3(projinv, bbox.vec[i]);}
461  */
462 static void draw_frustum_boundbox_calc(const float(*projmat)[4], BoundBox *r_bbox)
463 {
464         float near, far, left, right, bottom, top;
465         bool is_persp = projmat[3][3] == 0.0f;
466
467         if (is_persp) {
468                 near   = projmat[3][2] / (projmat[2][2] - 1.0f);
469                 far    = projmat[3][2] / (projmat[2][2] + 1.0f);
470                 left   = near * (projmat[2][0] - 1.0f) / projmat[0][0];
471                 right  = near * (projmat[2][0] + 1.0f) / projmat[0][0];
472                 bottom = near * (projmat[2][1] - 1.0f) / projmat[1][1];
473                 top    = near * (projmat[2][1] + 1.0f) / projmat[1][1];
474         }
475         else {
476                 near   = ( projmat[3][2] + 1.0f) / projmat[2][2];
477                 far    = ( projmat[3][2] - 1.0f) / projmat[2][2];
478                 left   = (-projmat[3][0] - 1.0f) / projmat[0][0];
479                 right  = (-projmat[3][0] + 1.0f) / projmat[0][0];
480                 bottom = (-projmat[3][1] - 1.0f) / projmat[1][1];
481                 top    = (-projmat[3][1] + 1.0f) / projmat[1][1];
482         }
483
484         r_bbox->vec[0][2] = r_bbox->vec[3][2] = r_bbox->vec[7][2] = r_bbox->vec[4][2] = -near;
485         r_bbox->vec[0][0] = r_bbox->vec[3][0] = left;
486         r_bbox->vec[4][0] = r_bbox->vec[7][0] = right;
487         r_bbox->vec[0][1] = r_bbox->vec[4][1] = bottom;
488         r_bbox->vec[7][1] = r_bbox->vec[3][1] = top;
489
490         /* Get the coordinates of the far plane. */
491         if (is_persp) {
492                 float sca_far = far / near;
493                 left   *= sca_far;
494                 bottom *= sca_far;
495                 right  *= sca_far;
496                 top    *= sca_far;
497         }
498
499         r_bbox->vec[1][2] = r_bbox->vec[2][2] = r_bbox->vec[6][2] = r_bbox->vec[5][2] = -far;
500         r_bbox->vec[1][0] = r_bbox->vec[2][0] = left;
501         r_bbox->vec[6][0] = r_bbox->vec[5][0] = right;
502         r_bbox->vec[1][1] = r_bbox->vec[5][1] = bottom;
503         r_bbox->vec[2][1] = r_bbox->vec[6][1] = top;
504 }
505
506 static void draw_clipping_setup_from_view(void)
507 {
508         if (DST.clipping.updated)
509                 return;
510
511         float (*viewinv)[4] = DST.view_data.matstate.mat[DRW_MAT_VIEWINV];
512         float (*projmat)[4] = DST.view_data.matstate.mat[DRW_MAT_WIN];
513         float (*projinv)[4] = DST.view_data.matstate.mat[DRW_MAT_WININV];
514         BoundSphere *bsphere = &DST.clipping.frustum_bsphere;
515
516         /* Extract Clipping Planes */
517         BoundBox bbox;
518 #if 0 /* It has accuracy problems. */
519         BKE_boundbox_init_from_minmax(&bbox, (const float[3]){-1.0f, -1.0f, -1.0f}, (const float[3]){1.0f, 1.0f, 1.0f});
520         for (int i = 0; i < 8; i++) {
521                 mul_project_m4_v3(projinv, bbox.vec[i]);
522         }
523 #else
524         draw_frustum_boundbox_calc(projmat, &bbox);
525 #endif
526         /* Transform into world space. */
527         for (int i = 0; i < 8; i++) {
528                 mul_m4_v3(viewinv, bbox.vec[i]);
529         }
530
531         memcpy(&DST.clipping.frustum_corners, &bbox, sizeof(BoundBox));
532
533         /* Compute clip planes using the world space frustum corners. */
534         for (int p = 0; p < 6; p++) {
535                 int q, r;
536                 switch (p) {
537                         case 0:  q = 1; r = 2; break; /* -X */
538                         case 1:  q = 0; r = 5; break; /* -Y */
539                         case 2:  q = 1; r = 5; break; /* +Z (far) */
540                         case 3:  q = 2; r = 6; break; /* +Y */
541                         case 4:  q = 0; r = 3; break; /* -Z (near) */
542                         default: q = 4; r = 7; break; /* +X */
543                 }
544                 if (DST.frontface == GL_CW) {
545                         SWAP(int, q, r);
546                 }
547
548                 normal_tri_v3(DST.clipping.frustum_planes[p], bbox.vec[p], bbox.vec[q], bbox.vec[r]);
549                 DST.clipping.frustum_planes[p][3] = -dot_v3v3(DST.clipping.frustum_planes[p], bbox.vec[p]);
550         }
551
552         /* Extract Bounding Sphere */
553         if (projmat[3][3] != 0.0f) {
554                 /* Orthographic */
555                 /* The most extreme points on the near and far plane. (normalized device coords). */
556                 float *nearpoint = bbox.vec[0];
557                 float *farpoint = bbox.vec[6];
558
559                 /* just use median point */
560                 mid_v3_v3v3(bsphere->center, farpoint, nearpoint);
561                 bsphere->radius = len_v3v3(bsphere->center, farpoint);
562         }
563         else if (projmat[2][0] == 0.0f && projmat[2][1] == 0.0f) {
564                 /* Perspective with symmetrical frustum. */
565
566                 /* We obtain the center and radius of the circumscribed circle of the
567                  * isosceles trapezoid composed by the diagonals of the near and far clipping plane */
568
569                 /* center of each clipping plane */
570                 float mid_min[3], mid_max[3];
571                 mid_v3_v3v3(mid_min, bbox.vec[3], bbox.vec[4]);
572                 mid_v3_v3v3(mid_max, bbox.vec[2], bbox.vec[5]);
573
574                 /* square length of the diagonals of each clipping plane */
575                 float a_sq = len_squared_v3v3(bbox.vec[3], bbox.vec[4]);
576                 float b_sq = len_squared_v3v3(bbox.vec[2], bbox.vec[5]);
577
578                 /* distance squared between clipping planes */
579                 float h_sq = len_squared_v3v3(mid_min, mid_max);
580
581                 float fac = (4 * h_sq + b_sq - a_sq) / (8 * h_sq);
582
583                 /* The goal is to get the smallest sphere,
584                  * not the sphere that passes through each corner */
585                 CLAMP(fac, 0.0f, 1.0f);
586
587                 interp_v3_v3v3(bsphere->center, mid_min, mid_max, fac);
588
589                 /* distance from the center to one of the points of the far plane (1, 2, 5, 6) */
590                 bsphere->radius = len_v3v3(bsphere->center, bbox.vec[1]);
591         }
592         else {
593                 /* Perspective with asymmetrical frustum. */
594
595                 /* We put the sphere center on the line that goes from origin
596                  * to the center of the far clipping plane. */
597
598                 /* Detect which of the corner of the far clipping plane is the farthest to the origin */
599                 float nfar[4];       /* most extreme far point in NDC space */
600                 float farxy[2];      /* farpoint projection onto the near plane */
601                 float farpoint[3] = {0.0f}; /* most extreme far point in camera coordinate */
602                 float nearpoint[3];  /* most extreme near point in camera coordinate */
603                 float farcenter[3] = {0.0f}; /* center of far cliping plane in camera coordinate */
604                 float F = -1.0f, N;  /* square distance of far and near point to origin */
605                 float f, n;          /* distance of far and near point to z axis. f is always > 0 but n can be < 0 */
606                 float e, s;          /* far and near clipping distance (<0) */
607                 float c;             /* slope of center line = distance of far clipping center to z axis / far clipping distance */
608                 float z;             /* projection of sphere center on z axis (<0) */
609
610                 /* Find farthest corner and center of far clip plane. */
611                 float corner[3] = {1.0f, 1.0f, 1.0f}; /* in clip space */
612                 for (int i = 0; i < 4; i++) {
613                         float point[3];
614                         mul_v3_project_m4_v3(point, projinv, corner);
615                         float len = len_squared_v3(point);
616                         if (len > F) {
617                                 copy_v3_v3(nfar, corner);
618                                 copy_v3_v3(farpoint, point);
619                                 F = len;
620                         }
621                         add_v3_v3(farcenter, point);
622                         /* rotate by 90 degree to walk through the 4 points of the far clip plane */
623                         float tmp = corner[0];
624                         corner[0] = -corner[1];
625                         corner[1] = tmp;
626                 }
627
628                 /* the far center is the average of the far clipping points */
629                 mul_v3_fl(farcenter, 0.25f);
630                 /* the extreme near point is the opposite point on the near clipping plane */
631                 copy_v3_fl3(nfar, -nfar[0], -nfar[1], -1.0f);
632                 mul_v3_project_m4_v3(nearpoint, projinv, nfar);
633                 /* this is a frustum projection */
634                 N = len_squared_v3(nearpoint);
635                 e = farpoint[2];
636                 s = nearpoint[2];
637                 /* distance to view Z axis */
638                 f = len_v2(farpoint);
639                 /* get corresponding point on the near plane */
640                 mul_v2_v2fl(farxy, farpoint, s / e);
641                 /* this formula preserve the sign of n */
642                 sub_v2_v2(nearpoint, farxy);
643                 n = f * s / e - len_v2(nearpoint);
644                 c = len_v2(farcenter) / e;
645                 /* the big formula, it simplifies to (F-N)/(2(e-s)) for the symmetric case */
646                 z = (F - N) / (2.0f * (e - s + c * (f - n)));
647
648                 bsphere->center[0] = farcenter[0] * z / e;
649                 bsphere->center[1] = farcenter[1] * z / e;
650                 bsphere->center[2] = z;
651                 bsphere->radius = len_v3v3(bsphere->center, farpoint);
652
653                 /* Transform to world space. */
654                 mul_m4_v3(viewinv, bsphere->center);
655         }
656
657         DST.clipping.updated = true;
658 }
659
660 /* Return True if the given BoundSphere intersect the current view frustum */
661 bool DRW_culling_sphere_test(BoundSphere *bsphere)
662 {
663         draw_clipping_setup_from_view();
664
665         /* Bypass test if radius is negative. */
666         if (bsphere->radius < 0.0f)
667                 return true;
668
669         /* Do a rough test first: Sphere VS Sphere intersect. */
670         BoundSphere *frustum_bsphere = &DST.clipping.frustum_bsphere;
671         float center_dist = len_squared_v3v3(bsphere->center, frustum_bsphere->center);
672         if (center_dist > SQUARE(bsphere->radius + frustum_bsphere->radius))
673                 return false;
674
675         /* Test against the 6 frustum planes. */
676         for (int p = 0; p < 6; p++) {
677                 float dist = plane_point_side_v3(DST.clipping.frustum_planes[p], bsphere->center);
678                 if (dist < -bsphere->radius) {
679                         return false;
680                 }
681         }
682
683         return true;
684 }
685
686 /* Return True if the given BoundBox intersect the current view frustum.
687  * bbox must be in world space. */
688 bool DRW_culling_box_test(BoundBox *bbox)
689 {
690         draw_clipping_setup_from_view();
691
692         /* 6 view frustum planes */
693         for (int p = 0; p < 6; p++) {
694                 /* 8 box vertices. */
695                 for (int v = 0; v < 8 ; v++) {
696                         float dist = plane_point_side_v3(DST.clipping.frustum_planes[p], bbox->vec[v]);
697                         if (dist > 0.0f) {
698                                 /* At least one point in front of this plane.
699                                  * Go to next plane. */
700                                 break;
701                         }
702                         else if (v == 7) {
703                                 /* 8 points behind this plane. */
704                                 return false;
705                         }
706                 }
707         }
708
709         return true;
710 }
711
712 /* Return True if the current view frustum is inside or intersect the given plane */
713 bool DRW_culling_plane_test(float plane[4])
714 {
715         draw_clipping_setup_from_view();
716
717         /* Test against the 8 frustum corners. */
718         for (int c = 0; c < 8; c++) {
719                 float dist = plane_point_side_v3(plane, DST.clipping.frustum_corners.vec[c]);
720                 if (dist < 0.0f) {
721                         return true;
722                 }
723         }
724
725         return false;
726 }
727
728 void DRW_culling_frustum_corners_get(BoundBox *corners)
729 {
730         draw_clipping_setup_from_view();
731         memcpy(corners, &DST.clipping.frustum_corners, sizeof(BoundBox));
732 }
733
734 /* See draw_clipping_setup_from_view() for the plane order. */
735 void DRW_culling_frustum_planes_get(float planes[6][4])
736 {
737         draw_clipping_setup_from_view();
738         memcpy(planes, &DST.clipping.frustum_planes, sizeof(DST.clipping.frustum_planes));
739 }
740
741 /** \} */
742
743 /* -------------------------------------------------------------------- */
744
745 /** \name Draw (DRW_draw)
746  * \{ */
747
748 static void draw_visibility_eval(DRWCallState *st)
749 {
750         bool culled = st->flag & DRW_CALL_CULLED;
751
752         if (st->cache_id != DST.state_cache_id) {
753                 /* Update culling result for this view. */
754                 culled = !DRW_culling_sphere_test(&st->bsphere);
755         }
756
757         if (st->visibility_cb) {
758                 culled = !st->visibility_cb(!culled, st->user_data);
759         }
760
761         SET_FLAG_FROM_TEST(st->flag, culled, DRW_CALL_CULLED);
762 }
763
764 static void draw_matrices_model_prepare(DRWCallState *st)
765 {
766         if (st->cache_id == DST.state_cache_id) {
767                 /* Values are already updated for this view. */
768                 return;
769         }
770         else {
771                 st->cache_id = DST.state_cache_id;
772         }
773
774         /* No need to go further the call will not be used. */
775         if ((st->flag & DRW_CALL_CULLED) != 0 &&
776             (st->flag & DRW_CALL_BYPASS_CULLING) == 0)
777         {
778                 return;
779         }
780         /* Order matters */
781         if (st->matflag & (DRW_CALL_MODELVIEW | DRW_CALL_MODELVIEWINVERSE |
782                            DRW_CALL_NORMALVIEW | DRW_CALL_EYEVEC))
783         {
784                 mul_m4_m4m4(st->modelview, DST.view_data.matstate.mat[DRW_MAT_VIEW], st->model);
785         }
786         if (st->matflag & DRW_CALL_MODELVIEWINVERSE) {
787                 invert_m4_m4(st->modelviewinverse, st->modelview);
788         }
789         if (st->matflag & DRW_CALL_MODELVIEWPROJECTION) {
790                 mul_m4_m4m4(st->modelviewprojection, DST.view_data.matstate.mat[DRW_MAT_PERS], st->model);
791         }
792         if (st->matflag & (DRW_CALL_NORMALVIEW | DRW_CALL_EYEVEC)) {
793                 copy_m3_m4(st->normalview, st->modelview);
794                 invert_m3(st->normalview);
795                 transpose_m3(st->normalview);
796         }
797         if (st->matflag & DRW_CALL_EYEVEC) {
798                 /* Used by orthographic wires */
799                 float tmp[3][3];
800                 copy_v3_fl3(st->eyevec, 0.0f, 0.0f, 1.0f);
801                 invert_m3_m3(tmp, st->normalview);
802                 /* set eye vector, transformed to object coords */
803                 mul_m3_v3(tmp, st->eyevec);
804         }
805         /* Non view dependent */
806         if (st->matflag & DRW_CALL_MODELINVERSE) {
807                 invert_m4_m4(st->modelinverse, st->model);
808                 st->matflag &= ~DRW_CALL_MODELINVERSE;
809         }
810         if (st->matflag & DRW_CALL_NORMALWORLD) {
811                 copy_m3_m4(st->normalworld, st->model);
812                 invert_m3(st->normalworld);
813                 transpose_m3(st->normalworld);
814                 st->matflag &= ~DRW_CALL_NORMALWORLD;
815         }
816 }
817
818 static void draw_geometry_prepare(DRWShadingGroup *shgroup, DRWCall *call)
819 {
820         /* step 1 : bind object dependent matrices */
821         if (call != NULL) {
822                 DRWCallState *state = call->state;
823                 float objectinfo[3];
824                 objectinfo[0] = state->objectinfo[0];
825                 objectinfo[1] = call->single.ma_index; /* WATCH this is only valid for single drawcalls. */
826                 objectinfo[2] = state->objectinfo[1];
827
828                 GPU_shader_uniform_vector(shgroup->shader, shgroup->model, 16, 1, (float *)state->model);
829                 GPU_shader_uniform_vector(shgroup->shader, shgroup->modelinverse, 16, 1, (float *)state->modelinverse);
830                 GPU_shader_uniform_vector(shgroup->shader, shgroup->modelview, 16, 1, (float *)state->modelview);
831                 GPU_shader_uniform_vector(shgroup->shader, shgroup->modelviewinverse, 16, 1, (float *)state->modelviewinverse);
832                 GPU_shader_uniform_vector(shgroup->shader, shgroup->modelviewprojection, 16, 1, (float *)state->modelviewprojection);
833                 GPU_shader_uniform_vector(shgroup->shader, shgroup->normalview, 9, 1, (float *)state->normalview);
834                 GPU_shader_uniform_vector(shgroup->shader, shgroup->normalworld, 9, 1, (float *)state->normalworld);
835                 GPU_shader_uniform_vector(shgroup->shader, shgroup->objectinfo, 3, 1, (float *)objectinfo);
836                 GPU_shader_uniform_vector(shgroup->shader, shgroup->orcotexfac, 3, 2, (float *)state->orcotexfac);
837                 GPU_shader_uniform_vector(shgroup->shader, shgroup->eye, 3, 1, (float *)state->eyevec);
838         }
839         else {
840                 BLI_assert((shgroup->normalview == -1) && (shgroup->normalworld == -1) && (shgroup->eye == -1));
841                 /* For instancing and batching. */
842                 float unitmat[4][4];
843                 unit_m4(unitmat);
844                 GPU_shader_uniform_vector(shgroup->shader, shgroup->model, 16, 1, (float *)unitmat);
845                 GPU_shader_uniform_vector(shgroup->shader, shgroup->modelinverse, 16, 1, (float *)unitmat);
846                 GPU_shader_uniform_vector(shgroup->shader, shgroup->modelview, 16, 1, (float *)DST.view_data.matstate.mat[DRW_MAT_VIEW]);
847                 GPU_shader_uniform_vector(shgroup->shader, shgroup->modelviewinverse, 16, 1, (float *)DST.view_data.matstate.mat[DRW_MAT_VIEWINV]);
848                 GPU_shader_uniform_vector(shgroup->shader, shgroup->modelviewprojection, 16, 1, (float *)DST.view_data.matstate.mat[DRW_MAT_PERS]);
849                 GPU_shader_uniform_vector(shgroup->shader, shgroup->objectinfo, 3, 1, (float *)unitmat);
850                 GPU_shader_uniform_vector(shgroup->shader, shgroup->orcotexfac, 3, 2, (float *)shgroup->instance_orcofac);
851         }
852 }
853
854 static void draw_geometry_execute_ex(
855         DRWShadingGroup *shgroup, GPUBatch *geom, uint start, uint count, bool draw_instance)
856 {
857         /* Special case: empty drawcall, placement is done via shader, don't bind anything. */
858         /* TODO use DRW_CALL_PROCEDURAL instead */
859         if (geom == NULL) {
860                 BLI_assert(shgroup->type == DRW_SHG_TRIANGLE_BATCH); /* Add other type if needed. */
861                 /* Shader is already bound. */
862                 GPU_draw_primitive(GPU_PRIM_TRIS, count);
863                 return;
864         }
865
866         /* step 2 : bind vertex array & draw */
867         GPU_batch_program_set_no_use(
868                 geom, GPU_shader_get_program(shgroup->shader), GPU_shader_get_interface(shgroup->shader));
869         /* XXX hacking gawain. we don't want to call glUseProgram! (huge performance loss) */
870         geom->program_in_use = true;
871
872         GPU_batch_draw_range_ex(geom, start, count, draw_instance);
873
874         geom->program_in_use = false; /* XXX hacking gawain */
875 }
876
877 static void draw_geometry_execute(DRWShadingGroup *shgroup, GPUBatch *geom)
878 {
879         draw_geometry_execute_ex(shgroup, geom, 0, 0, false);
880 }
881
882 enum {
883         BIND_NONE = 0,
884         BIND_TEMP = 1,         /* Release slot after this shading group. */
885         BIND_PERSIST = 2,      /* Release slot only after the next shader change. */
886 };
887
888 static void bind_texture(GPUTexture *tex, char bind_type)
889 {
890         int index;
891         char *slot_flags = DST.RST.bound_tex_slots;
892         int bind_num = GPU_texture_bound_number(tex);
893         if (bind_num == -1) {
894                 for (int i = 0; i < GPU_max_textures(); ++i) {
895                         index = DST.RST.bind_tex_inc = (DST.RST.bind_tex_inc + 1) % GPU_max_textures();
896                         if (slot_flags[index] == BIND_NONE) {
897                                 if (DST.RST.bound_texs[index] != NULL) {
898                                         GPU_texture_unbind(DST.RST.bound_texs[index]);
899                                 }
900                                 GPU_texture_bind(tex, index);
901                                 DST.RST.bound_texs[index] = tex;
902                                 slot_flags[index] = bind_type;
903                                 // printf("Binds Texture %d %p\n", DST.RST.bind_tex_inc, tex);
904                                 return;
905                         }
906                 }
907                 printf("Not enough texture slots! Reduce number of textures used by your shader.\n");
908         }
909         slot_flags[bind_num] = bind_type;
910 }
911
912 static void bind_ubo(GPUUniformBuffer *ubo, char bind_type)
913 {
914         int index;
915         char *slot_flags = DST.RST.bound_ubo_slots;
916         int bind_num = GPU_uniformbuffer_bindpoint(ubo);
917         if (bind_num == -1) {
918                 for (int i = 0; i < GPU_max_ubo_binds(); ++i) {
919                         index = DST.RST.bind_ubo_inc = (DST.RST.bind_ubo_inc + 1) % GPU_max_ubo_binds();
920                         if (slot_flags[index] == BIND_NONE) {
921                                 if (DST.RST.bound_ubos[index] != NULL) {
922                                         GPU_uniformbuffer_unbind(DST.RST.bound_ubos[index]);
923                                 }
924                                 GPU_uniformbuffer_bind(ubo, index);
925                                 DST.RST.bound_ubos[index] = ubo;
926                                 slot_flags[index] = bind_type;
927                                 return;
928                         }
929                 }
930                 /* printf so user can report bad behavior */
931                 printf("Not enough ubo slots! This should not happen!\n");
932                 /* This is not depending on user input.
933                  * It is our responsibility to make sure there is enough slots. */
934                 BLI_assert(0);
935         }
936         slot_flags[bind_num] = bind_type;
937 }
938
939 #ifndef NDEBUG
940 /**
941  * Opengl specification is strict on buffer binding.
942  *
943  * " If any active uniform block is not backed by a
944  * sufficiently large buffer object, the results of shader
945  * execution are undefined, and may result in GL interruption or
946  * termination. " - Opengl 3.3 Core Specification
947  *
948  * For now we only check if the binding is correct. Not the size of
949  * the bound ubo.
950  *
951  * See T55475.
952  * */
953 static bool ubo_bindings_validate(DRWShadingGroup *shgroup)
954 {
955         bool valid = true;
956 #  ifdef DEBUG_UBO_BINDING
957         /* Check that all active uniform blocks have a non-zero buffer bound. */
958         GLint program = 0;
959         GLint active_blocks = 0;
960
961         glGetIntegerv(GL_CURRENT_PROGRAM, &program);
962         glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &active_blocks);
963
964         for (uint i = 0; i < active_blocks; ++i) {
965                 int binding = 0;
966                 int buffer = 0;
967
968                 glGetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_BINDING, &binding);
969                 glGetIntegeri_v(GL_UNIFORM_BUFFER_BINDING, binding, &buffer);
970
971                 if (buffer == 0) {
972                         char blockname[64];
973                         glGetActiveUniformBlockName(program, i, sizeof(blockname), NULL, blockname);
974
975                         if (valid) {
976                                 printf("Trying to draw with missing UBO binding.\n");
977                                 valid = false;
978                         }
979                         printf("Pass : %s, Shader : %s, Block : %s\n", shgroup->pass_parent->name, shgroup->shader->name, blockname);
980                 }
981         }
982 #  endif
983         return valid;
984 }
985 #endif
986
987 static void release_texture_slots(bool with_persist)
988 {
989         if (with_persist) {
990                 memset(DST.RST.bound_tex_slots, 0x0, sizeof(*DST.RST.bound_tex_slots) * GPU_max_textures());
991         }
992         else {
993                 for (int i = 0; i < GPU_max_textures(); ++i) {
994                         if (DST.RST.bound_tex_slots[i] != BIND_PERSIST)
995                                 DST.RST.bound_tex_slots[i] = BIND_NONE;
996                 }
997         }
998
999         /* Reset so that slots are consistently assigned for different shader
1000          * draw calls, to avoid shader specialization/patching by the driver. */
1001         DST.RST.bind_tex_inc = 0;
1002 }
1003
1004 static void release_ubo_slots(bool with_persist)
1005 {
1006         if (with_persist) {
1007                 memset(DST.RST.bound_ubo_slots, 0x0, sizeof(*DST.RST.bound_ubo_slots) * GPU_max_ubo_binds());
1008         }
1009         else {
1010                 for (int i = 0; i < GPU_max_ubo_binds(); ++i) {
1011                         if (DST.RST.bound_ubo_slots[i] != BIND_PERSIST)
1012                                 DST.RST.bound_ubo_slots[i] = BIND_NONE;
1013                 }
1014         }
1015
1016         /* Reset so that slots are consistently assigned for different shader
1017          * draw calls, to avoid shader specialization/patching by the driver. */
1018         DST.RST.bind_ubo_inc = 0;
1019 }
1020
1021 static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
1022 {
1023         BLI_assert(shgroup->shader);
1024
1025         GPUTexture *tex;
1026         GPUUniformBuffer *ubo;
1027         int val;
1028         float fval;
1029         const bool shader_changed = (DST.shader != shgroup->shader);
1030         bool use_tfeedback = false;
1031
1032         if (shader_changed) {
1033                 if (DST.shader) GPU_shader_unbind();
1034                 GPU_shader_bind(shgroup->shader);
1035                 DST.shader = shgroup->shader;
1036         }
1037
1038         if ((pass_state & DRW_STATE_TRANS_FEEDBACK) != 0 &&
1039             (shgroup->type == DRW_SHG_FEEDBACK_TRANSFORM))
1040         {
1041                 use_tfeedback = GPU_shader_transform_feedback_enable(shgroup->shader,
1042                                                                      shgroup->tfeedback_target->vbo_id);
1043         }
1044
1045         release_ubo_slots(shader_changed);
1046         release_texture_slots(shader_changed);
1047
1048         drw_state_set((pass_state & shgroup->state_extra_disable) | shgroup->state_extra);
1049         drw_stencil_set(shgroup->stencil_mask);
1050
1051         /* Binding Uniform */
1052         for (DRWUniform *uni = shgroup->uniforms; uni; uni = uni->next) {
1053                 switch (uni->type) {
1054                         case DRW_UNIFORM_SHORT_TO_INT:
1055                                 val = (int)*((short *)uni->pvalue);
1056                                 GPU_shader_uniform_vector_int(
1057                                         shgroup->shader, uni->location, uni->length, uni->arraysize, &val);
1058                                 break;
1059                         case DRW_UNIFORM_SHORT_TO_FLOAT:
1060                                 fval = (float)*((short *)uni->pvalue);
1061                                 GPU_shader_uniform_vector(
1062                                         shgroup->shader, uni->location, uni->length, uni->arraysize, (float *)&fval);
1063                                 break;
1064                         case DRW_UNIFORM_BOOL_COPY:
1065                         case DRW_UNIFORM_INT_COPY:
1066                                 GPU_shader_uniform_vector_int(
1067                                         shgroup->shader, uni->location, uni->length, uni->arraysize, &uni->ivalue);
1068                                 break;
1069                         case DRW_UNIFORM_BOOL:
1070                         case DRW_UNIFORM_INT:
1071                                 GPU_shader_uniform_vector_int(
1072                                         shgroup->shader, uni->location, uni->length, uni->arraysize, (int *)uni->pvalue);
1073                                 break;
1074                         case DRW_UNIFORM_FLOAT_COPY:
1075                                 GPU_shader_uniform_vector(
1076                                         shgroup->shader, uni->location, uni->length, uni->arraysize, &uni->fvalue);
1077                                 break;
1078                         case DRW_UNIFORM_FLOAT:
1079                                 GPU_shader_uniform_vector(
1080                                         shgroup->shader, uni->location, uni->length, uni->arraysize, (float *)uni->pvalue);
1081                                 break;
1082                         case DRW_UNIFORM_TEXTURE:
1083                                 tex = (GPUTexture *)uni->pvalue;
1084                                 BLI_assert(tex);
1085                                 bind_texture(tex, BIND_TEMP);
1086                                 GPU_shader_uniform_texture(shgroup->shader, uni->location, tex);
1087                                 break;
1088                         case DRW_UNIFORM_TEXTURE_PERSIST:
1089                                 tex = (GPUTexture *)uni->pvalue;
1090                                 BLI_assert(tex);
1091                                 bind_texture(tex, BIND_PERSIST);
1092                                 GPU_shader_uniform_texture(shgroup->shader, uni->location, tex);
1093                                 break;
1094                         case DRW_UNIFORM_TEXTURE_REF:
1095                                 tex = *((GPUTexture **)uni->pvalue);
1096                                 BLI_assert(tex);
1097                                 bind_texture(tex, BIND_TEMP);
1098                                 GPU_shader_uniform_texture(shgroup->shader, uni->location, tex);
1099                                 break;
1100                         case DRW_UNIFORM_BLOCK:
1101                                 ubo = (GPUUniformBuffer *)uni->pvalue;
1102                                 bind_ubo(ubo, BIND_TEMP);
1103                                 GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo);
1104                                 break;
1105                         case DRW_UNIFORM_BLOCK_PERSIST:
1106                                 ubo = (GPUUniformBuffer *)uni->pvalue;
1107                                 bind_ubo(ubo, BIND_PERSIST);
1108                                 GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo);
1109                                 break;
1110                 }
1111         }
1112
1113 #ifdef USE_GPU_SELECT
1114 #  define GPU_SELECT_LOAD_IF_PICKSEL(_select_id) \
1115         if (G.f & G_PICKSEL) { \
1116                 GPU_select_load_id(_select_id); \
1117         } ((void)0)
1118
1119 #  define GPU_SELECT_LOAD_IF_PICKSEL_CALL(_call) \
1120         if ((G.f & G_PICKSEL) && (_call)) { \
1121                 GPU_select_load_id((_call)->select_id); \
1122         } ((void)0)
1123
1124 #  define GPU_SELECT_LOAD_IF_PICKSEL_LIST(_shgroup, _start, _count)  \
1125         _start = 0;                                                      \
1126         _count = _shgroup->instance_count;                     \
1127         int *select_id = NULL;                                           \
1128         if (G.f & G_PICKSEL) {                                           \
1129                 if (_shgroup->override_selectid == -1) {                        \
1130                         /* Hack : get vbo data without actually drawing. */     \
1131                         GPUVertBufRaw raw;                   \
1132                         GPU_vertbuf_attr_get_raw_data(_shgroup->inst_selectid, 0, &raw); \
1133                         select_id = GPU_vertbuf_raw_step(&raw);                               \
1134                         switch (_shgroup->type) {                                             \
1135                                 case DRW_SHG_TRIANGLE_BATCH: _count = 3; break;                   \
1136                                 case DRW_SHG_LINE_BATCH: _count = 2; break;                       \
1137                                 default: _count = 1; break;                                       \
1138                         }                                                                     \
1139                 }                                                                         \
1140                 else {                                                                    \
1141                         GPU_select_load_id(_shgroup->override_selectid);            \
1142                 }                                                                         \
1143         }                                                                \
1144         while (_start < _shgroup->instance_count) {            \
1145                 if (select_id) {                                             \
1146                         GPU_select_load_id(select_id[_start]);                   \
1147                 }
1148
1149 #  define GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(_start, _count) \
1150                 _start += _count;                                    \
1151         }
1152
1153 #else
1154 #  define GPU_SELECT_LOAD_IF_PICKSEL(select_id)
1155 #  define GPU_SELECT_LOAD_IF_PICKSEL_CALL(call)
1156 #  define GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(start, count)
1157 #  define GPU_SELECT_LOAD_IF_PICKSEL_LIST(_shgroup, _start, _count) \
1158         _start = 0;                                                     \
1159         _count = _shgroup->instance_count;
1160
1161 #endif
1162
1163         BLI_assert(ubo_bindings_validate(shgroup));
1164
1165         /* Rendering Calls */
1166         if (!ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM)) {
1167                 /* Replacing multiple calls with only one */
1168                 if (ELEM(shgroup->type, DRW_SHG_INSTANCE, DRW_SHG_INSTANCE_EXTERNAL)) {
1169                         if (shgroup->type == DRW_SHG_INSTANCE_EXTERNAL) {
1170                                 if (shgroup->instance_geom != NULL) {
1171                                         GPU_SELECT_LOAD_IF_PICKSEL(shgroup->override_selectid);
1172                                         draw_geometry_prepare(shgroup, NULL);
1173                                         draw_geometry_execute_ex(shgroup, shgroup->instance_geom, 0, 0, true);
1174                                 }
1175                         }
1176                         else {
1177                                 if (shgroup->instance_count > 0) {
1178                                         uint count, start;
1179                                         draw_geometry_prepare(shgroup, NULL);
1180                                         GPU_SELECT_LOAD_IF_PICKSEL_LIST(shgroup, start, count)
1181                                         {
1182                                                 draw_geometry_execute_ex(shgroup, shgroup->instance_geom, start, count, true);
1183                                         }
1184                                         GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(start, count)
1185                                 }
1186                         }
1187                 }
1188                 else { /* DRW_SHG_***_BATCH */
1189                         /* Some dynamic batch can have no geom (no call to aggregate) */
1190                         if (shgroup->instance_count > 0) {
1191                                 uint count, start;
1192                                 draw_geometry_prepare(shgroup, NULL);
1193                                 GPU_SELECT_LOAD_IF_PICKSEL_LIST(shgroup, start, count)
1194                                 {
1195                                         draw_geometry_execute_ex(shgroup, shgroup->batch_geom, start, count, false);
1196                                 }
1197                                 GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(start, count)
1198                         }
1199                 }
1200         }
1201         else {
1202                 bool prev_neg_scale = false;
1203                 int callid = 0;
1204                 for (DRWCall *call = shgroup->calls.first; call; call = call->next) {
1205
1206                         /* OPTI/IDEA(clem): Do this preparation in another thread. */
1207                         draw_visibility_eval(call->state);
1208                         draw_matrices_model_prepare(call->state);
1209
1210                         if ((call->state->flag & DRW_CALL_CULLED) != 0 &&
1211                             (call->state->flag & DRW_CALL_BYPASS_CULLING) == 0)
1212                         {
1213                                 continue;
1214                         }
1215
1216                         /* XXX small exception/optimisation for outline rendering. */
1217                         if (shgroup->callid != -1) {
1218                                 GPU_shader_uniform_vector_int(shgroup->shader, shgroup->callid, 1, 1, &callid);
1219                                 callid += 1;
1220                         }
1221
1222                         /* Negative scale objects */
1223                         bool neg_scale = call->state->flag & DRW_CALL_NEGSCALE;
1224                         if (neg_scale != prev_neg_scale) {
1225                                 glFrontFace((neg_scale) ? DST.backface : DST.frontface);
1226                                 prev_neg_scale = neg_scale;
1227                         }
1228
1229                         GPU_SELECT_LOAD_IF_PICKSEL_CALL(call);
1230                         draw_geometry_prepare(shgroup, call);
1231
1232                         switch (call->type) {
1233                                 case DRW_CALL_SINGLE:
1234                                         draw_geometry_execute(shgroup, call->single.geometry);
1235                                         break;
1236                                 case DRW_CALL_RANGE:
1237                                         draw_geometry_execute_ex(shgroup, call->range.geometry, call->range.start, call->range.count, false);
1238                                         break;
1239                                 case DRW_CALL_INSTANCES:
1240                                         draw_geometry_execute_ex(shgroup, call->instances.geometry, 0, *call->instances.count, true);
1241                                         break;
1242                                 case DRW_CALL_GENERATE:
1243                                         call->generate.geometry_fn(shgroup, draw_geometry_execute, call->generate.user_data);
1244                                         break;
1245                                 case DRW_CALL_PROCEDURAL:
1246                                         GPU_draw_primitive(call->procedural.prim_type, call->procedural.vert_count);
1247                                         break;
1248                                 default:
1249                                         BLI_assert(0);
1250                         }
1251                 }
1252                 /* Reset state */
1253                 glFrontFace(DST.frontface);
1254         }
1255
1256         if (use_tfeedback) {
1257                 GPU_shader_transform_feedback_disable(shgroup->shader);
1258         }
1259
1260         /* TODO: remove, (currently causes alpha issue with sculpt, need to investigate) */
1261         DRW_state_reset();
1262 }
1263
1264 static void drw_update_view(void)
1265 {
1266         if (DST.dirty_mat) {
1267                 DST.state_cache_id++;
1268                 DST.dirty_mat = false;
1269
1270                 DRW_uniformbuffer_update(view_ubo, &DST.view_data);
1271
1272                 /* Catch integer wrap around. */
1273                 if (UNLIKELY(DST.state_cache_id == 0)) {
1274                         DST.state_cache_id = 1;
1275                         /* We must reset all CallStates to ensure that not
1276                          * a single one stayed with cache_id equal to 1. */
1277                         BLI_mempool_iter iter;
1278                         DRWCallState *state;
1279                         BLI_mempool_iternew(DST.vmempool->states, &iter);
1280                         while ((state = BLI_mempool_iterstep(&iter))) {
1281                                 state->cache_id = 0;
1282                         }
1283                 }
1284
1285                 /* TODO dispatch threads to compute matrices/culling */
1286         }
1287
1288         draw_clipping_setup_from_view();
1289 }
1290
1291 static void drw_draw_pass_ex(DRWPass *pass, DRWShadingGroup *start_group, DRWShadingGroup *end_group)
1292 {
1293         if (start_group == NULL)
1294                 return;
1295
1296         DST.shader = NULL;
1297
1298         BLI_assert(DST.buffer_finish_called && "DRW_render_instance_buffer_finish had not been called before drawing");
1299
1300         drw_update_view();
1301
1302         drw_state_set(pass->state);
1303
1304         DRW_stats_query_start(pass->name);
1305
1306         for (DRWShadingGroup *shgroup = start_group; shgroup; shgroup = shgroup->next) {
1307                 draw_shgroup(shgroup, pass->state);
1308                 /* break if upper limit */
1309                 if (shgroup == end_group) {
1310                         break;
1311                 }
1312         }
1313
1314         /* Clear Bound textures */
1315         for (int i = 0; i < GPU_max_textures(); i++) {
1316                 if (DST.RST.bound_texs[i] != NULL) {
1317                         GPU_texture_unbind(DST.RST.bound_texs[i]);
1318                         DST.RST.bound_texs[i] = NULL;
1319                 }
1320         }
1321
1322         /* Clear Bound Ubos */
1323         for (int i = 0; i < GPU_max_ubo_binds(); i++) {
1324                 if (DST.RST.bound_ubos[i] != NULL) {
1325                         GPU_uniformbuffer_unbind(DST.RST.bound_ubos[i]);
1326                         DST.RST.bound_ubos[i] = NULL;
1327                 }
1328         }
1329
1330         if (DST.shader) {
1331                 GPU_shader_unbind();
1332                 DST.shader = NULL;
1333         }
1334
1335         DRW_stats_query_end();
1336 }
1337
1338 void DRW_draw_pass(DRWPass *pass)
1339 {
1340         drw_draw_pass_ex(pass, pass->shgroups.first, pass->shgroups.last);
1341 }
1342
1343 /* Draw only a subset of shgroups. Used in special situations as grease pencil strokes */
1344 void DRW_draw_pass_subset(DRWPass *pass, DRWShadingGroup *start_group, DRWShadingGroup *end_group)
1345 {
1346         drw_draw_pass_ex(pass, start_group, end_group);
1347 }
1348
1349 /** \} */