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