GPU: Refactor GPU_batch_draw_range_ex
[blender.git] / source / blender / draw / intern / draw_manager.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 <stdio.h>
24
25 #include "BLI_alloca.h"
26 #include "BLI_listbase.h"
27 #include "BLI_memblock.h"
28 #include "BLI_rect.h"
29 #include "BLI_string.h"
30 #include "BLI_threads.h"
31
32 #include "BLF_api.h"
33
34 #include "BKE_anim.h"
35 #include "BKE_colortools.h"
36 #include "BKE_curve.h"
37 #include "BKE_editmesh.h"
38 #include "BKE_global.h"
39 #include "BKE_gpencil.h"
40 #include "BKE_lattice.h"
41 #include "BKE_main.h"
42 #include "BKE_mball.h"
43 #include "BKE_mesh.h"
44 #include "BKE_object.h"
45 #include "BKE_particle.h"
46 #include "BKE_paint.h"
47 #include "BKE_pointcache.h"
48
49 #include "draw_manager.h"
50 #include "DNA_camera_types.h"
51 #include "DNA_mesh_types.h"
52 #include "DNA_meshdata_types.h"
53 #include "DNA_world_types.h"
54
55 #include "ED_space_api.h"
56 #include "ED_screen.h"
57 #include "ED_gpencil.h"
58 #include "ED_view3d.h"
59
60 #include "GPU_draw.h"
61 #include "GPU_extensions.h"
62 #include "GPU_framebuffer.h"
63 #include "GPU_immediate.h"
64 #include "GPU_uniformbuffer.h"
65 #include "GPU_viewport.h"
66 #include "GPU_matrix.h"
67 #include "GPU_select.h"
68
69 #include "IMB_colormanagement.h"
70
71 #include "RE_engine.h"
72 #include "RE_pipeline.h"
73
74 #include "UI_resources.h"
75
76 #include "WM_api.h"
77 #include "wm_window.h"
78
79 #include "draw_manager_text.h"
80 #include "draw_manager_profiling.h"
81
82 /* only for callbacks */
83 #include "draw_cache_impl.h"
84
85 #include "draw_mode_engines.h"
86 #include "engines/eevee/eevee_engine.h"
87 #include "engines/basic/basic_engine.h"
88 #include "engines/workbench/workbench_engine.h"
89 #include "engines/external/external_engine.h"
90
91 #include "GPU_context.h"
92
93 #include "DEG_depsgraph.h"
94 #include "DEG_depsgraph_query.h"
95
96 #ifdef USE_GPU_SELECT
97 #  include "GPU_select.h"
98 #endif
99
100 /** Render State: No persistent data between draw calls. */
101 DRWManager DST = {NULL};
102
103 static ListBase DRW_engines = {NULL, NULL};
104
105 static void drw_state_prepare_clean_for_draw(DRWManager *dst)
106 {
107   memset(dst, 0x0, offsetof(DRWManager, gl_context));
108
109   /* Maybe not the best place for this. */
110   if (!DST.uniform_names.buffer) {
111     DST.uniform_names.buffer = MEM_callocN(DRW_UNIFORM_BUFFER_NAME, "Name Buffer");
112     DST.uniform_names.buffer_len = DRW_UNIFORM_BUFFER_NAME;
113   }
114   else if (DST.uniform_names.buffer_len > DRW_UNIFORM_BUFFER_NAME) {
115     DST.uniform_names.buffer = MEM_reallocN(DST.uniform_names.buffer, DRW_UNIFORM_BUFFER_NAME);
116     DST.uniform_names.buffer_len = DRW_UNIFORM_BUFFER_NAME;
117   }
118   DST.uniform_names.buffer_ofs = 0;
119 }
120
121 /* This function is used to reset draw manager to a state
122  * where we don't re-use data by accident across different
123  * draw calls.
124  */
125 #ifdef DEBUG
126 static void drw_state_ensure_not_reused(DRWManager *dst)
127 {
128   memset(dst, 0xff, offsetof(DRWManager, gl_context));
129 }
130 #endif
131
132 /* -------------------------------------------------------------------- */
133
134 void DRW_draw_callbacks_pre_scene(void)
135 {
136   RegionView3D *rv3d = DST.draw_ctx.rv3d;
137
138   GPU_matrix_projection_set(rv3d->winmat);
139   GPU_matrix_set(rv3d->viewmat);
140 }
141
142 void DRW_draw_callbacks_post_scene(void)
143 {
144   RegionView3D *rv3d = DST.draw_ctx.rv3d;
145
146   GPU_matrix_projection_set(rv3d->winmat);
147   GPU_matrix_set(rv3d->viewmat);
148 }
149
150 struct DRWTextStore *DRW_text_cache_ensure(void)
151 {
152   BLI_assert(DST.text_store_p);
153   if (*DST.text_store_p == NULL) {
154     *DST.text_store_p = DRW_text_cache_create();
155   }
156   return *DST.text_store_p;
157 }
158
159 /* -------------------------------------------------------------------- */
160 /** \name Settings
161  * \{ */
162
163 bool DRW_object_is_renderable(const Object *ob)
164 {
165   BLI_assert((ob->base_flag & BASE_VISIBLE) != 0);
166
167   if (ob->type == OB_MESH) {
168     if ((ob == DST.draw_ctx.object_edit) || BKE_object_is_in_editmode(ob)) {
169       View3D *v3d = DST.draw_ctx.v3d;
170       const int mask = (V3D_OVERLAY_EDIT_OCCLUDE_WIRE | V3D_OVERLAY_EDIT_WEIGHT);
171
172       if (v3d && v3d->overlay.edit_flag & mask) {
173         return false;
174       }
175     }
176   }
177
178   return true;
179 }
180
181 /**
182  * Return whether this object is visible depending if
183  * we are rendering or drawing in the viewport.
184  */
185 int DRW_object_visibility_in_active_context(const Object *ob)
186 {
187   const eEvaluationMode mode = DRW_state_is_scene_render() ? DAG_EVAL_RENDER : DAG_EVAL_VIEWPORT;
188   return BKE_object_visibility(ob, mode);
189 }
190
191 bool DRW_object_is_flat_normal(const Object *ob)
192 {
193   if (ob->type == OB_MESH) {
194     const Mesh *me = ob->data;
195     if (me->mpoly && me->mpoly[0].flag & ME_SMOOTH) {
196       return false;
197     }
198   }
199   return true;
200 }
201
202 bool DRW_object_use_hide_faces(const struct Object *ob)
203 {
204   if (ob->type == OB_MESH) {
205     const Mesh *me = ob->data;
206
207     switch (ob->mode) {
208       case OB_MODE_TEXTURE_PAINT:
209         return (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
210       case OB_MODE_VERTEX_PAINT:
211       case OB_MODE_WEIGHT_PAINT:
212         return (me->editflag & (ME_EDIT_PAINT_FACE_SEL | ME_EDIT_PAINT_VERT_SEL)) != 0;
213     }
214   }
215
216   return false;
217 }
218
219 bool DRW_object_use_pbvh_drawing(const struct Object *ob)
220 {
221   return ob->sculpt && (ob->sculpt->mode_type == OB_MODE_SCULPT);
222 }
223
224 bool DRW_object_is_visible_psys_in_active_context(const Object *object, const ParticleSystem *psys)
225 {
226   const bool for_render = DRW_state_is_image_render();
227   /* NOTE: psys_check_enabled is using object and particle system for only
228    * reading, but is using some other functions which are more generic and
229    * which are hard to make const-pointer. */
230   if (!psys_check_enabled((Object *)object, (ParticleSystem *)psys, for_render)) {
231     return false;
232   }
233   const DRWContextState *draw_ctx = DRW_context_state_get();
234   const Scene *scene = draw_ctx->scene;
235   if (object == draw_ctx->object_edit) {
236     return false;
237   }
238   const ParticleSettings *part = psys->part;
239   const ParticleEditSettings *pset = &scene->toolsettings->particle;
240   if (object->mode == OB_MODE_PARTICLE_EDIT) {
241     if (psys_in_edit_mode(draw_ctx->depsgraph, psys)) {
242       if ((pset->flag & PE_DRAW_PART) == 0) {
243         return false;
244       }
245       if ((part->childtype == 0) &&
246           (psys->flag & PSYS_HAIR_DYNAMICS && psys->pointcache->flag & PTCACHE_BAKED) == 0) {
247         return false;
248       }
249     }
250   }
251   return true;
252 }
253
254 struct Object *DRW_object_get_dupli_parent(const Object *UNUSED(ob))
255 {
256   return DST.dupli_parent;
257 }
258
259 struct DupliObject *DRW_object_get_dupli(const Object *UNUSED(ob))
260 {
261   return DST.dupli_source;
262 }
263
264 /** \} */
265
266 /* -------------------------------------------------------------------- */
267 /** \name Color Management
268  * \{ */
269
270 /* Use color management profile to draw texture to framebuffer */
271 void DRW_transform_to_display(GPUTexture *tex, bool use_view_transform, bool use_render_settings)
272 {
273   drw_state_set(DRW_STATE_WRITE_COLOR);
274
275   GPUVertFormat *vert_format = immVertexFormat();
276   uint pos = GPU_vertformat_attr_add(vert_format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
277   uint texco = GPU_vertformat_attr_add(vert_format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
278
279   const float dither = 1.0f;
280
281   bool use_ocio = false;
282
283   /* View transform is already applied for offscreen, don't apply again, see: T52046 */
284   if (!(DST.options.is_image_render && !DST.options.is_scene_render)) {
285     Scene *scene = DST.draw_ctx.scene;
286     ColorManagedDisplaySettings *display_settings = &scene->display_settings;
287     ColorManagedViewSettings view_settings;
288     if (use_render_settings) {
289       /* Use full render settings, for renders with scene lighting. */
290       view_settings = scene->view_settings;
291     }
292     else if (use_view_transform) {
293       /* Use only view transform + look and nothing else for lookdev without
294        * scene lighting, as exposure depends on scene light intensity. */
295       BKE_color_managed_view_settings_init_render(&view_settings, display_settings, NULL);
296       STRNCPY(view_settings.view_transform, scene->view_settings.view_transform);
297       STRNCPY(view_settings.look, scene->view_settings.look);
298     }
299     else {
300       /* For workbench use only default view transform in configuration,
301        * using no scene settings. */
302       BKE_color_managed_view_settings_init_render(&view_settings, display_settings, NULL);
303     }
304
305     use_ocio = IMB_colormanagement_setup_glsl_draw_from_space(
306         &view_settings, display_settings, NULL, dither, false);
307   }
308
309   if (!use_ocio) {
310     /* View transform is already applied for offscreen, don't apply again, see: T52046 */
311     if (DST.options.is_image_render && !DST.options.is_scene_render) {
312       immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR);
313       immUniformColor4f(1.0f, 1.0f, 1.0f, 1.0f);
314     }
315     else {
316       immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_LINEAR_TO_SRGB);
317     }
318     immUniform1i("image", 0);
319   }
320
321   GPU_texture_bind(tex, 0); /* OCIO texture bind point is 0 */
322
323   float mat[4][4];
324   unit_m4(mat);
325   immUniformMatrix4fv("ModelViewProjectionMatrix", mat);
326
327   /* Full screen triangle */
328   immBegin(GPU_PRIM_TRIS, 3);
329   immAttr2f(texco, 0.0f, 0.0f);
330   immVertex2f(pos, -1.0f, -1.0f);
331
332   immAttr2f(texco, 2.0f, 0.0f);
333   immVertex2f(pos, 3.0f, -1.0f);
334
335   immAttr2f(texco, 0.0f, 2.0f);
336   immVertex2f(pos, -1.0f, 3.0f);
337   immEnd();
338
339   GPU_texture_unbind(tex);
340
341   if (use_ocio) {
342     IMB_colormanagement_finish_glsl_draw();
343   }
344   else {
345     immUnbindProgram();
346   }
347 }
348
349 /* Draw texture to framebuffer without any color transforms */
350 void DRW_transform_none(GPUTexture *tex)
351 {
352   drw_state_set(DRW_STATE_WRITE_COLOR);
353
354   /* Draw as texture for final render (without immediate mode). */
355   GPUBatch *geom = DRW_cache_fullscreen_quad_get();
356   GPU_batch_program_set_builtin(geom, GPU_SHADER_2D_IMAGE_COLOR);
357
358   GPU_texture_bind(tex, 0);
359
360   const float white[4] = {1.0f, 1.0f, 1.0f, 1.0f};
361   GPU_batch_uniform_4fv(geom, "color", white);
362
363   float mat[4][4];
364   unit_m4(mat);
365   GPU_batch_uniform_mat4(geom, "ModelViewProjectionMatrix", mat);
366
367   GPU_batch_program_use_begin(geom);
368   GPU_batch_bind(geom);
369   GPU_batch_draw_advanced(geom, 0, 0, 0, 0);
370   GPU_batch_program_use_end(geom);
371
372   GPU_texture_unbind(tex);
373 }
374
375 /** \} */
376
377 /* -------------------------------------------------------------------- */
378 /** \name Multisample Resolve
379  * \{ */
380
381 /**
382  * Use manual multisample resolve pass.
383  * Much quicker than blitting back and forth.
384  * Assume destination fb is bound.
385  */
386 void DRW_multisamples_resolve(GPUTexture *src_depth, GPUTexture *src_color, bool use_depth)
387 {
388   DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_PREMUL;
389
390   if (use_depth) {
391     state |= DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
392   }
393   drw_state_set(state);
394
395   int samples = GPU_texture_samples(src_depth);
396
397   BLI_assert(samples > 0);
398   BLI_assert(GPU_texture_samples(src_color) == samples);
399
400   GPUBatch *geom = DRW_cache_fullscreen_quad_get();
401
402   int builtin;
403   if (use_depth) {
404     switch (samples) {
405       case 2:
406         builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_2_DEPTH_TEST;
407         break;
408       case 4:
409         builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_4_DEPTH_TEST;
410         break;
411       case 8:
412         builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_8_DEPTH_TEST;
413         break;
414       case 16:
415         builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_16_DEPTH_TEST;
416         break;
417       default:
418         BLI_assert(!"Mulisample count unsupported by blit shader.");
419         builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_2_DEPTH_TEST;
420         break;
421     }
422   }
423   else {
424     switch (samples) {
425       case 2:
426         builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_2;
427         break;
428       case 4:
429         builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_4;
430         break;
431       case 8:
432         builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_8;
433         break;
434       case 16:
435         builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_16;
436         break;
437       default:
438         BLI_assert(!"Mulisample count unsupported by blit shader.");
439         builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_2;
440         break;
441     }
442   }
443
444   GPU_batch_program_set_builtin(geom, builtin);
445
446   if (use_depth) {
447     GPU_texture_bind(src_depth, 0);
448     GPU_batch_uniform_1i(geom, "depthMulti", 0);
449   }
450
451   GPU_texture_bind(src_color, 1);
452   GPU_batch_uniform_1i(geom, "colorMulti", 1);
453
454   float mat[4][4];
455   unit_m4(mat);
456   GPU_batch_uniform_mat4(geom, "ModelViewProjectionMatrix", mat);
457
458   /* avoid gpuMatrix calls */
459   GPU_batch_program_use_begin(geom);
460   GPU_batch_bind(geom);
461   GPU_batch_draw_advanced(geom, 0, 0, 0, 0);
462   GPU_batch_program_use_end(geom);
463 }
464
465 /** \} */
466
467 /* -------------------------------------------------------------------- */
468 /** \name Viewport (DRW_viewport)
469  * \{ */
470
471 void *drw_viewport_engine_data_ensure(void *engine_type)
472 {
473   void *data = GPU_viewport_engine_data_get(DST.viewport, engine_type);
474
475   if (data == NULL) {
476     data = GPU_viewport_engine_data_create(DST.viewport, engine_type);
477   }
478   return data;
479 }
480
481 void DRW_engine_viewport_data_size_get(
482     const void *engine_type_v, int *r_fbl_len, int *r_txl_len, int *r_psl_len, int *r_stl_len)
483 {
484   const DrawEngineType *engine_type = engine_type_v;
485
486   if (r_fbl_len) {
487     *r_fbl_len = engine_type->vedata_size->fbl_len;
488   }
489   if (r_txl_len) {
490     *r_txl_len = engine_type->vedata_size->txl_len;
491   }
492   if (r_psl_len) {
493     *r_psl_len = engine_type->vedata_size->psl_len;
494   }
495   if (r_stl_len) {
496     *r_stl_len = engine_type->vedata_size->stl_len;
497   }
498 }
499
500 /* WARNING: only use for custom pipeline. 99% of the time, you don't want to use this. */
501 void DRW_render_viewport_size_set(int size[2])
502 {
503   DST.size[0] = size[0];
504   DST.size[1] = size[1];
505 }
506
507 const float *DRW_viewport_size_get(void)
508 {
509   return DST.size;
510 }
511
512 const float *DRW_viewport_invert_size_get(void)
513 {
514   return DST.inv_size;
515 }
516
517 const float *DRW_viewport_screenvecs_get(void)
518 {
519   return &DST.screenvecs[0][0];
520 }
521
522 const float *DRW_viewport_pixelsize_get(void)
523 {
524   return &DST.pixsize;
525 }
526
527 static void drw_viewport_cache_resize(void)
528 {
529   /* Release the memiter before clearing the mempools that references them */
530   GPU_viewport_cache_release(DST.viewport);
531
532   if (DST.vmempool != NULL) {
533     /* Release Image textures. */
534     BLI_memblock_iter iter;
535     GPUTexture **tex;
536     BLI_memblock_iternew(DST.vmempool->images, &iter);
537     while ((tex = BLI_memblock_iterstep(&iter))) {
538       GPU_texture_free(*tex);
539     }
540
541     BLI_memblock_clear(DST.vmempool->calls, NULL);
542     BLI_memblock_clear(DST.vmempool->states, NULL);
543     BLI_memblock_clear(DST.vmempool->cullstates, NULL);
544     BLI_memblock_clear(DST.vmempool->shgroups, NULL);
545     BLI_memblock_clear(DST.vmempool->uniforms, NULL);
546     BLI_memblock_clear(DST.vmempool->passes, NULL);
547     BLI_memblock_clear(DST.vmempool->views, NULL);
548     BLI_memblock_clear(DST.vmempool->images, NULL);
549   }
550
551   DRW_instance_data_list_free_unused(DST.idatalist);
552   DRW_instance_data_list_resize(DST.idatalist);
553 }
554
555 /* Not a viewport variable, we could split this out. */
556 static void drw_context_state_init(void)
557 {
558   if (DST.draw_ctx.obact) {
559     DST.draw_ctx.object_mode = DST.draw_ctx.obact->mode;
560   }
561   else {
562     DST.draw_ctx.object_mode = OB_MODE_OBJECT;
563   }
564
565   /* Edit object. */
566   if (DST.draw_ctx.object_mode & OB_MODE_EDIT) {
567     DST.draw_ctx.object_edit = DST.draw_ctx.obact;
568   }
569   else {
570     DST.draw_ctx.object_edit = NULL;
571   }
572
573   /* Pose object. */
574   if (DST.draw_ctx.object_mode & OB_MODE_POSE) {
575     DST.draw_ctx.object_pose = DST.draw_ctx.obact;
576   }
577   else if (DST.draw_ctx.object_mode & OB_MODE_WEIGHT_PAINT) {
578     DST.draw_ctx.object_pose = BKE_object_pose_armature_get(DST.draw_ctx.obact);
579   }
580   else {
581     DST.draw_ctx.object_pose = NULL;
582   }
583
584   DST.draw_ctx.sh_cfg = GPU_SHADER_CFG_DEFAULT;
585   if (DST.draw_ctx.rv3d && DST.draw_ctx.rv3d->rflag & RV3D_CLIPPING) {
586     DST.draw_ctx.sh_cfg = GPU_SHADER_CFG_CLIPPED;
587   }
588 }
589
590 /* It also stores viewport variable to an immutable place: DST
591  * This is because a cache uniform only store reference
592  * to its value. And we don't want to invalidate the cache
593  * if this value change per viewport */
594 static void drw_viewport_var_init(void)
595 {
596   RegionView3D *rv3d = DST.draw_ctx.rv3d;
597   /* Refresh DST.size */
598   if (DST.viewport) {
599     int size[2];
600     GPU_viewport_size_get(DST.viewport, size);
601     DST.size[0] = size[0];
602     DST.size[1] = size[1];
603     DST.inv_size[0] = 1.0f / size[0];
604     DST.inv_size[1] = 1.0f / size[1];
605
606     DefaultFramebufferList *fbl = (DefaultFramebufferList *)GPU_viewport_framebuffer_list_get(
607         DST.viewport);
608     DST.default_framebuffer = fbl->default_fb;
609
610     DST.vmempool = GPU_viewport_mempool_get(DST.viewport);
611
612     if (DST.vmempool->calls == NULL) {
613       DST.vmempool->calls = BLI_memblock_create(sizeof(DRWCall));
614     }
615     if (DST.vmempool->states == NULL) {
616       DST.vmempool->states = BLI_memblock_create(sizeof(DRWCallState));
617     }
618     if (DST.vmempool->cullstates == NULL) {
619       DST.vmempool->cullstates = BLI_memblock_create(sizeof(DRWCullingState));
620     }
621     if (DST.vmempool->shgroups == NULL) {
622       DST.vmempool->shgroups = BLI_memblock_create(sizeof(DRWShadingGroup));
623     }
624     if (DST.vmempool->uniforms == NULL) {
625       DST.vmempool->uniforms = BLI_memblock_create(sizeof(DRWUniform));
626     }
627     if (DST.vmempool->views == NULL) {
628       DST.vmempool->views = BLI_memblock_create(sizeof(DRWView));
629     }
630     if (DST.vmempool->passes == NULL) {
631       DST.vmempool->passes = BLI_memblock_create(sizeof(DRWPass));
632     }
633     if (DST.vmempool->images == NULL) {
634       DST.vmempool->images = BLI_memblock_create(sizeof(GPUTexture *));
635     }
636
637     DST.idatalist = GPU_viewport_instance_data_list_get(DST.viewport);
638     DRW_instance_data_list_reset(DST.idatalist);
639   }
640   else {
641     DST.size[0] = 0;
642     DST.size[1] = 0;
643
644     DST.inv_size[0] = 0;
645     DST.inv_size[1] = 0;
646
647     DST.default_framebuffer = NULL;
648     DST.vmempool = NULL;
649   }
650
651   DST.primary_view_ct = 0;
652
653   if (rv3d != NULL) {
654     normalize_v3_v3(DST.screenvecs[0], rv3d->viewinv[0]);
655     normalize_v3_v3(DST.screenvecs[1], rv3d->viewinv[1]);
656
657     DST.pixsize = rv3d->pixsize;
658     DST.view_default = DRW_view_create(rv3d->viewmat, rv3d->winmat, NULL, NULL, NULL);
659     copy_v4_v4(DST.view_default->storage.viewcamtexcofac, rv3d->viewcamtexcofac);
660
661     if (DST.draw_ctx.sh_cfg == GPU_SHADER_CFG_CLIPPED) {
662       int plane_len = (rv3d->viewlock & RV3D_BOXCLIP) ? 4 : 6;
663       DRW_view_clip_planes_set(DST.view_default, rv3d->clip, plane_len);
664     }
665
666     DST.view_active = DST.view_default;
667     DST.view_previous = NULL;
668   }
669   else {
670     zero_v3(DST.screenvecs[0]);
671     zero_v3(DST.screenvecs[1]);
672
673     DST.pixsize = 1.0f;
674     DST.view_default = NULL;
675     DST.view_active = NULL;
676     DST.view_previous = NULL;
677   }
678
679   /* fclem: Is this still needed ? */
680   if (DST.draw_ctx.object_edit) {
681     ED_view3d_init_mats_rv3d(DST.draw_ctx.object_edit, rv3d);
682   }
683
684   /* Alloc array of texture reference. */
685   memset(&DST.RST, 0x0, sizeof(DST.RST));
686
687   if (G_draw.view_ubo == NULL) {
688     G_draw.view_ubo = DRW_uniformbuffer_create(sizeof(DRWViewUboStorage), NULL);
689   }
690
691   memset(DST.object_instance_data, 0x0, sizeof(DST.object_instance_data));
692 }
693
694 DefaultFramebufferList *DRW_viewport_framebuffer_list_get(void)
695 {
696   return GPU_viewport_framebuffer_list_get(DST.viewport);
697 }
698
699 DefaultTextureList *DRW_viewport_texture_list_get(void)
700 {
701   return GPU_viewport_texture_list_get(DST.viewport);
702 }
703
704 void DRW_viewport_request_redraw(void)
705 {
706   GPU_viewport_tag_update(DST.viewport);
707 }
708
709 /** \} */
710
711 /* -------------------------------------------------------------------- */
712 /** \name Duplis
713  * \{ */
714
715 static void drw_duplidata_load(DupliObject *dupli)
716 {
717   if (dupli == NULL) {
718     return;
719   }
720
721   if (DST.dupli_origin != dupli->ob) {
722     DST.dupli_origin = dupli->ob;
723   }
724   else {
725     /* Same data as previous iter. No need to poll ghash for this. */
726     return;
727   }
728
729   if (DST.dupli_ghash == NULL) {
730     DST.dupli_ghash = BLI_ghash_ptr_new(__func__);
731   }
732
733   void **value;
734   if (!BLI_ghash_ensure_p(DST.dupli_ghash, DST.dupli_origin, &value)) {
735     *value = MEM_callocN(sizeof(void *) * DST.enabled_engine_count, __func__);
736
737     /* TODO: Meh a bit out of place but this is nice as it is
738      * only done once per "original" object. */
739     drw_batch_cache_validate(DST.dupli_origin);
740   }
741   DST.dupli_datas = *(void ***)value;
742 }
743
744 static void duplidata_value_free(void *val)
745 {
746   void **dupli_datas = val;
747   for (int i = 0; i < DST.enabled_engine_count; i++) {
748     MEM_SAFE_FREE(dupli_datas[i]);
749   }
750   MEM_freeN(val);
751 }
752
753 static void drw_duplidata_free(void)
754 {
755   if (DST.dupli_ghash != NULL) {
756     BLI_ghash_free(DST.dupli_ghash,
757                    (void (*)(void *key))drw_batch_cache_generate_requested,
758                    duplidata_value_free);
759     DST.dupli_ghash = NULL;
760   }
761 }
762
763 /* Return NULL if not a dupli or a pointer of pointer to the engine data */
764 void **DRW_duplidata_get(void *vedata)
765 {
766   if (DST.dupli_source == NULL) {
767     return NULL;
768   }
769   /* XXX Search engine index by using vedata array */
770   for (int i = 0; i < DST.enabled_engine_count; i++) {
771     if (DST.vedata_array[i] == vedata) {
772       return &DST.dupli_datas[i];
773     }
774   }
775   return NULL;
776 }
777
778 /** \} */
779
780 /* -------------------------------------------------------------------- */
781 /** \name ViewLayers (DRW_scenelayer)
782  * \{ */
783
784 void *DRW_view_layer_engine_data_get(DrawEngineType *engine_type)
785 {
786   for (ViewLayerEngineData *sled = DST.draw_ctx.view_layer->drawdata.first; sled;
787        sled = sled->next) {
788     if (sled->engine_type == engine_type) {
789       return sled->storage;
790     }
791   }
792   return NULL;
793 }
794
795 void **DRW_view_layer_engine_data_ensure_ex(ViewLayer *view_layer,
796                                             DrawEngineType *engine_type,
797                                             void (*callback)(void *storage))
798 {
799   ViewLayerEngineData *sled;
800
801   for (sled = view_layer->drawdata.first; sled; sled = sled->next) {
802     if (sled->engine_type == engine_type) {
803       return &sled->storage;
804     }
805   }
806
807   sled = MEM_callocN(sizeof(ViewLayerEngineData), "ViewLayerEngineData");
808   sled->engine_type = engine_type;
809   sled->free = callback;
810   BLI_addtail(&view_layer->drawdata, sled);
811
812   return &sled->storage;
813 }
814
815 void **DRW_view_layer_engine_data_ensure(DrawEngineType *engine_type,
816                                          void (*callback)(void *storage))
817 {
818   return DRW_view_layer_engine_data_ensure_ex(DST.draw_ctx.view_layer, engine_type, callback);
819 }
820
821 /** \} */
822
823 /* -------------------------------------------------------------------- */
824 /** \name Draw Data (DRW_drawdata)
825  * \{ */
826
827 /* Used for DRW_drawdata_from_id()
828  * All ID-datablocks which have their own 'local' DrawData
829  * should have the same arrangement in their structs.
830  */
831 typedef struct IdDdtTemplate {
832   ID id;
833   struct AnimData *adt;
834   DrawDataList drawdata;
835 } IdDdtTemplate;
836
837 /* Check if ID can have AnimData */
838 static bool id_type_can_have_drawdata(const short id_type)
839 {
840   /* Only some ID-blocks have this info for now */
841   /* TODO: finish adding this for the other blocktypes */
842   switch (id_type) {
843     /* has DrawData */
844     case ID_OB:
845     case ID_WO:
846       return true;
847
848     /* no DrawData */
849     default:
850       return false;
851   }
852 }
853
854 static bool id_can_have_drawdata(const ID *id)
855 {
856   /* sanity check */
857   if (id == NULL) {
858     return false;
859   }
860
861   return id_type_can_have_drawdata(GS(id->name));
862 }
863
864 /* Get DrawData from the given ID-block. In order for this to work, we assume that
865  * the DrawData pointer is stored in the struct in the same fashion as in IdDdtTemplate.
866  */
867 DrawDataList *DRW_drawdatalist_from_id(ID *id)
868 {
869   /* only some ID-blocks have this info for now, so we cast the
870    * types that do to be of type IdDdtTemplate, and extract the
871    * DrawData that way
872    */
873   if (id_can_have_drawdata(id)) {
874     IdDdtTemplate *idt = (IdDdtTemplate *)id;
875     return &idt->drawdata;
876   }
877   else {
878     return NULL;
879   }
880 }
881
882 DrawData *DRW_drawdata_get(ID *id, DrawEngineType *engine_type)
883 {
884   DrawDataList *drawdata = DRW_drawdatalist_from_id(id);
885
886   if (drawdata == NULL) {
887     return NULL;
888   }
889
890   LISTBASE_FOREACH (DrawData *, dd, drawdata) {
891     if (dd->engine_type == engine_type) {
892       return dd;
893     }
894   }
895   return NULL;
896 }
897
898 DrawData *DRW_drawdata_ensure(ID *id,
899                               DrawEngineType *engine_type,
900                               size_t size,
901                               DrawDataInitCb init_cb,
902                               DrawDataFreeCb free_cb)
903 {
904   BLI_assert(size >= sizeof(DrawData));
905   BLI_assert(id_can_have_drawdata(id));
906   /* Try to re-use existing data. */
907   DrawData *dd = DRW_drawdata_get(id, engine_type);
908   if (dd != NULL) {
909     return dd;
910   }
911
912   DrawDataList *drawdata = DRW_drawdatalist_from_id(id);
913
914   /* Allocate new data. */
915   if ((GS(id->name) == ID_OB) && (((Object *)id)->base_flag & BASE_FROM_DUPLI) != 0) {
916     /* NOTE: data is not persistent in this case. It is reset each redraw. */
917     BLI_assert(free_cb == NULL); /* No callback allowed. */
918     /* Round to sizeof(float) for DRW_instance_data_request(). */
919     const size_t t = sizeof(float) - 1;
920     size = (size + t) & ~t;
921     size_t fsize = size / sizeof(float);
922     BLI_assert(fsize < MAX_INSTANCE_DATA_SIZE);
923     if (DST.object_instance_data[fsize] == NULL) {
924       DST.object_instance_data[fsize] = DRW_instance_data_request(DST.idatalist, fsize);
925     }
926     dd = (DrawData *)DRW_instance_data_next(DST.object_instance_data[fsize]);
927     memset(dd, 0, size);
928   }
929   else {
930     dd = MEM_callocN(size, "DrawData");
931   }
932   dd->engine_type = engine_type;
933   dd->free = free_cb;
934   /* Perform user-side initialization, if needed. */
935   if (init_cb != NULL) {
936     init_cb(dd);
937   }
938   /* Register in the list. */
939   BLI_addtail((ListBase *)drawdata, dd);
940   return dd;
941 }
942
943 void DRW_drawdata_free(ID *id)
944 {
945   DrawDataList *drawdata = DRW_drawdatalist_from_id(id);
946
947   if (drawdata == NULL) {
948     return;
949   }
950
951   LISTBASE_FOREACH (DrawData *, dd, drawdata) {
952     if (dd->free != NULL) {
953       dd->free(dd);
954     }
955   }
956
957   BLI_freelistN((ListBase *)drawdata);
958 }
959
960 /* Unlink (but don't free) the drawdata from the DrawDataList if the ID is an OB from dupli. */
961 static void drw_drawdata_unlink_dupli(ID *id)
962 {
963   if ((GS(id->name) == ID_OB) && (((Object *)id)->base_flag & BASE_FROM_DUPLI) != 0) {
964     DrawDataList *drawdata = DRW_drawdatalist_from_id(id);
965
966     if (drawdata == NULL) {
967       return;
968     }
969
970     BLI_listbase_clear((ListBase *)drawdata);
971   }
972 }
973
974 /** \} */
975
976 /* -------------------------------------------------------------------- */
977 /** \name Garbage Collection
978  * \{ */
979
980 void DRW_cache_free_old_batches(Main *bmain)
981 {
982   Scene *scene;
983   ViewLayer *view_layer;
984   static int lasttime = 0;
985   int ctime = (int)PIL_check_seconds_timer();
986
987   if (U.vbotimeout == 0 || (ctime - lasttime) < U.vbocollectrate || ctime == lasttime) {
988     return;
989   }
990
991   lasttime = ctime;
992
993   for (scene = bmain->scenes.first; scene; scene = scene->id.next) {
994     for (view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
995       Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, false);
996       if (depsgraph == NULL) {
997         continue;
998       }
999
1000       /* TODO(fclem): This is not optimal since it iter over all dupli instances.
1001        * In this case only the source object should be tagged. */
1002       int iter_flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET |
1003                        DEG_ITER_OBJECT_FLAG_VISIBLE | DEG_ITER_OBJECT_FLAG_DUPLI;
1004
1005       DEG_OBJECT_ITER_BEGIN (depsgraph, ob, iter_flags) {
1006         DRW_batch_cache_free_old(ob, ctime);
1007       }
1008       DEG_OBJECT_ITER_END;
1009     }
1010   }
1011 }
1012
1013 /** \} */
1014
1015 /* -------------------------------------------------------------------- */
1016 /** \name Rendering (DRW_engines)
1017  * \{ */
1018
1019 static void drw_engines_init(void)
1020 {
1021   for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
1022     DrawEngineType *engine = link->data;
1023     ViewportEngineData *data = drw_viewport_engine_data_ensure(engine);
1024     PROFILE_START(stime);
1025
1026     if (engine->engine_init) {
1027       engine->engine_init(data);
1028     }
1029
1030     PROFILE_END_UPDATE(data->init_time, stime);
1031   }
1032 }
1033
1034 static void drw_engines_cache_init(void)
1035 {
1036   DST.enabled_engine_count = BLI_listbase_count(&DST.enabled_engines);
1037   DST.vedata_array = MEM_mallocN(sizeof(void *) * DST.enabled_engine_count, __func__);
1038
1039   int i = 0;
1040   for (LinkData *link = DST.enabled_engines.first; link; link = link->next, i++) {
1041     DrawEngineType *engine = link->data;
1042     ViewportEngineData *data = drw_viewport_engine_data_ensure(engine);
1043     DST.vedata_array[i] = data;
1044
1045     if (data->text_draw_cache) {
1046       DRW_text_cache_destroy(data->text_draw_cache);
1047       data->text_draw_cache = NULL;
1048     }
1049     if (DST.text_store_p == NULL) {
1050       DST.text_store_p = &data->text_draw_cache;
1051     }
1052
1053     if (engine->cache_init) {
1054       engine->cache_init(data);
1055     }
1056   }
1057 }
1058
1059 static void drw_engines_world_update(Scene *scene)
1060 {
1061   if (scene->world == NULL) {
1062     return;
1063   }
1064
1065   for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
1066     DrawEngineType *engine = link->data;
1067     ViewportEngineData *data = drw_viewport_engine_data_ensure(engine);
1068
1069     if (engine->id_update) {
1070       engine->id_update(data, &scene->world->id);
1071     }
1072   }
1073 }
1074
1075 static void drw_engines_cache_populate(Object *ob)
1076 {
1077   DST.ob_state = NULL;
1078
1079   /* HACK: DrawData is copied by COW from the duplicated object.
1080    * This is valid for IDs that cannot be instantiated but this
1081    * is not what we want in this case so we clear the pointer
1082    * ourselves here. */
1083   drw_drawdata_unlink_dupli((ID *)ob);
1084
1085   /* Validation for dupli objects happen elsewhere. */
1086   if (!DST.dupli_source) {
1087     drw_batch_cache_validate(ob);
1088   }
1089
1090   int i = 0;
1091   for (LinkData *link = DST.enabled_engines.first; link; link = link->next, i++) {
1092     DrawEngineType *engine = link->data;
1093     ViewportEngineData *data = DST.vedata_array[i];
1094
1095     if (engine->id_update) {
1096       engine->id_update(data, &ob->id);
1097     }
1098
1099     if (engine->cache_populate) {
1100       engine->cache_populate(data, ob);
1101     }
1102   }
1103
1104   /* TODO: in the future it would be nice to generate once for all viewports.
1105    * But we need threaded DRW manager first. */
1106   if (!DST.dupli_source) {
1107     drw_batch_cache_generate_requested(ob);
1108   }
1109
1110   /* ... and clearing it here too because theses draw data are
1111    * from a mempool and must not be free individually by depsgraph. */
1112   drw_drawdata_unlink_dupli((ID *)ob);
1113 }
1114
1115 static void drw_engines_cache_finish(void)
1116 {
1117   int i = 0;
1118   for (LinkData *link = DST.enabled_engines.first; link; link = link->next, i++) {
1119     DrawEngineType *engine = link->data;
1120     ViewportEngineData *data = DST.vedata_array[i];
1121
1122     if (engine->cache_finish) {
1123       engine->cache_finish(data);
1124     }
1125   }
1126   MEM_freeN(DST.vedata_array);
1127 }
1128
1129 static void drw_engines_draw_background(void)
1130 {
1131   for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
1132     DrawEngineType *engine = link->data;
1133     ViewportEngineData *data = drw_viewport_engine_data_ensure(engine);
1134
1135     if (engine->draw_background) {
1136       PROFILE_START(stime);
1137
1138       DRW_stats_group_start(engine->idname);
1139       engine->draw_background(data);
1140       DRW_stats_group_end();
1141
1142       PROFILE_END_UPDATE(data->background_time, stime);
1143       return;
1144     }
1145   }
1146
1147   /* No draw_background found, doing default background */
1148   const bool do_alpha_checker = !DRW_state_draw_background();
1149   DRW_draw_background(do_alpha_checker);
1150 }
1151
1152 static void drw_engines_draw_scene(void)
1153 {
1154   for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
1155     DrawEngineType *engine = link->data;
1156     ViewportEngineData *data = drw_viewport_engine_data_ensure(engine);
1157     PROFILE_START(stime);
1158
1159     if (engine->draw_scene) {
1160       DRW_stats_group_start(engine->idname);
1161       engine->draw_scene(data);
1162       /* Restore for next engine */
1163       if (DRW_state_is_fbo()) {
1164         GPU_framebuffer_bind(DST.default_framebuffer);
1165       }
1166       DRW_stats_group_end();
1167     }
1168
1169     PROFILE_END_UPDATE(data->render_time, stime);
1170   }
1171   /* Reset state after drawing */
1172   DRW_state_reset();
1173 }
1174
1175 static void drw_engines_draw_text(void)
1176 {
1177   for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
1178     DrawEngineType *engine = link->data;
1179     ViewportEngineData *data = drw_viewport_engine_data_ensure(engine);
1180     PROFILE_START(stime);
1181
1182     if (data->text_draw_cache) {
1183       DRW_text_cache_draw(data->text_draw_cache, DST.draw_ctx.ar);
1184     }
1185
1186     PROFILE_END_UPDATE(data->render_time, stime);
1187   }
1188 }
1189
1190 /* Draw render engine info. */
1191 void DRW_draw_region_engine_info(int xoffset, int yoffset)
1192 {
1193   for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
1194     DrawEngineType *engine = link->data;
1195     ViewportEngineData *data = drw_viewport_engine_data_ensure(engine);
1196
1197     if (data->info[0] != '\0') {
1198       char *chr_current = data->info;
1199       char *chr_start = chr_current;
1200       int line_len = 0;
1201
1202       const int font_id = BLF_default();
1203       UI_FontThemeColor(font_id, TH_TEXT_HI);
1204
1205       BLF_enable(font_id, BLF_SHADOW);
1206       BLF_shadow(font_id, 5, (const float[4]){0.0f, 0.0f, 0.0f, 1.0f});
1207       BLF_shadow_offset(font_id, 1, -1);
1208
1209       while (*chr_current++ != '\0') {
1210         line_len++;
1211         if (*chr_current == '\n') {
1212           char info[GPU_INFO_SIZE];
1213           BLI_strncpy(info, chr_start, line_len + 1);
1214           yoffset -= U.widget_unit;
1215           BLF_draw_default(xoffset, yoffset, 0.0f, info, sizeof(info));
1216
1217           /* Re-start counting. */
1218           chr_start = chr_current + 1;
1219           line_len = -1;
1220         }
1221       }
1222
1223       char info[GPU_INFO_SIZE];
1224       BLI_strncpy(info, chr_start, line_len + 1);
1225       yoffset -= U.widget_unit;
1226       BLF_draw_default(xoffset, yoffset, 0.0f, info, sizeof(info));
1227
1228       BLF_disable(font_id, BLF_SHADOW);
1229     }
1230   }
1231 }
1232
1233 static void use_drw_engine(DrawEngineType *engine)
1234 {
1235   LinkData *ld = MEM_callocN(sizeof(LinkData), "enabled engine link data");
1236   ld->data = engine;
1237   BLI_addtail(&DST.enabled_engines, ld);
1238 }
1239
1240 /**
1241  * Use for external render engines.
1242  */
1243 static void drw_engines_enable_external(void)
1244 {
1245   use_drw_engine(DRW_engine_viewport_external_type.draw_engine);
1246 }
1247
1248 /* TODO revisit this when proper layering is implemented */
1249 /* Gather all draw engines needed and store them in DST.enabled_engines
1250  * That also define the rendering order of engines */
1251 static void drw_engines_enable_from_engine(RenderEngineType *engine_type,
1252                                            int drawtype,
1253                                            bool use_xray)
1254 {
1255   switch (drawtype) {
1256     case OB_WIRE:
1257       use_drw_engine(&draw_engine_workbench_transparent);
1258       break;
1259
1260     case OB_SOLID:
1261       if (use_xray) {
1262         use_drw_engine(&draw_engine_workbench_transparent);
1263       }
1264       else {
1265         use_drw_engine(&draw_engine_workbench_solid);
1266       }
1267       break;
1268
1269     case OB_MATERIAL:
1270     case OB_RENDER:
1271     default:
1272       /* TODO layers */
1273       if (engine_type->draw_engine != NULL) {
1274         use_drw_engine(engine_type->draw_engine);
1275       }
1276
1277       if ((engine_type->flag & RE_INTERNAL) == 0) {
1278         drw_engines_enable_external();
1279       }
1280       break;
1281   }
1282 }
1283
1284 static void drw_engines_enable_from_object_mode(void)
1285 {
1286   use_drw_engine(&draw_engine_object_type);
1287   /* TODO(fclem) remove this, it does not belong to it's own engine. */
1288   use_drw_engine(&draw_engine_motion_path_type);
1289 }
1290
1291 static void drw_engines_enable_from_paint_mode(int mode)
1292 {
1293   switch (mode) {
1294     case CTX_MODE_SCULPT:
1295       use_drw_engine(&draw_engine_sculpt_type);
1296       break;
1297     case CTX_MODE_PAINT_WEIGHT:
1298     case CTX_MODE_PAINT_VERTEX:
1299       use_drw_engine(&draw_engine_paint_vertex_type);
1300       break;
1301     case CTX_MODE_PAINT_TEXTURE:
1302       use_drw_engine(&draw_engine_paint_texture_type);
1303       break;
1304     default:
1305       break;
1306   }
1307 }
1308
1309 static void drw_engines_enable_from_mode(int mode)
1310 {
1311   switch (mode) {
1312     case CTX_MODE_EDIT_MESH:
1313       use_drw_engine(&draw_engine_edit_mesh_type);
1314       break;
1315     case CTX_MODE_EDIT_SURFACE:
1316     case CTX_MODE_EDIT_CURVE:
1317       use_drw_engine(&draw_engine_edit_curve_type);
1318       break;
1319     case CTX_MODE_EDIT_TEXT:
1320       use_drw_engine(&draw_engine_edit_text_type);
1321       break;
1322     case CTX_MODE_EDIT_ARMATURE:
1323       use_drw_engine(&draw_engine_edit_armature_type);
1324       break;
1325     case CTX_MODE_EDIT_METABALL:
1326       use_drw_engine(&draw_engine_edit_metaball_type);
1327       break;
1328     case CTX_MODE_EDIT_LATTICE:
1329       use_drw_engine(&draw_engine_edit_lattice_type);
1330       break;
1331     case CTX_MODE_PARTICLE:
1332       use_drw_engine(&draw_engine_particle_type);
1333       break;
1334     case CTX_MODE_POSE:
1335     case CTX_MODE_PAINT_WEIGHT:
1336       /* The pose engine clears the depth of the default framebuffer
1337        * to draw an object with `OB_DRAWXRAY`.
1338        * (different of workbench that has its own framebuffer).
1339        * So make sure you call its `draw_scene` after all the other engines. */
1340       use_drw_engine(&draw_engine_pose_type);
1341       break;
1342     case CTX_MODE_SCULPT:
1343     case CTX_MODE_PAINT_VERTEX:
1344     case CTX_MODE_PAINT_TEXTURE:
1345     case CTX_MODE_OBJECT:
1346     case CTX_MODE_PAINT_GPENCIL:
1347     case CTX_MODE_EDIT_GPENCIL:
1348     case CTX_MODE_SCULPT_GPENCIL:
1349     case CTX_MODE_WEIGHT_GPENCIL:
1350       break;
1351     default:
1352       BLI_assert(!"Draw mode invalid");
1353       break;
1354   }
1355 }
1356
1357 static void drw_engines_enable_from_overlays(int UNUSED(overlay_flag))
1358 {
1359   use_drw_engine(&draw_engine_overlay_type);
1360 }
1361 /**
1362  * Use for select and depth-drawing.
1363  */
1364 static void drw_engines_enable_basic(void)
1365 {
1366   use_drw_engine(DRW_engine_viewport_basic_type.draw_engine);
1367 }
1368
1369 static void drw_engines_enable(ViewLayer *view_layer, RenderEngineType *engine_type)
1370 {
1371   Object *obact = OBACT(view_layer);
1372   const enum eContextObjectMode mode = CTX_data_mode_enum_ex(
1373       DST.draw_ctx.object_edit, obact, DST.draw_ctx.object_mode);
1374   View3D *v3d = DST.draw_ctx.v3d;
1375   const int drawtype = v3d->shading.type;
1376   const bool use_xray = XRAY_ENABLED(v3d);
1377
1378   drw_engines_enable_from_engine(engine_type, drawtype, use_xray);
1379   /* grease pencil */
1380   use_drw_engine(&draw_engine_gpencil_type);
1381
1382   if (DRW_state_draw_support()) {
1383     /* Draw paint modes first so that they are drawn below the wireframes. */
1384     drw_engines_enable_from_paint_mode(mode);
1385     drw_engines_enable_from_overlays(v3d->overlay.flag);
1386     drw_engines_enable_from_object_mode();
1387     drw_engines_enable_from_mode(mode);
1388   }
1389   else {
1390     /* Force enable overlays engine for wireframe mode */
1391     if (v3d->shading.type == OB_WIRE) {
1392       drw_engines_enable_from_overlays(v3d->overlay.flag);
1393     }
1394   }
1395 }
1396
1397 static void drw_engines_disable(void)
1398 {
1399   BLI_freelistN(&DST.enabled_engines);
1400 }
1401
1402 static void drw_engines_data_validate(void)
1403 {
1404   int enabled_engines = BLI_listbase_count(&DST.enabled_engines);
1405   void **engine_handle_array = BLI_array_alloca(engine_handle_array, enabled_engines + 1);
1406   int i = 0;
1407
1408   for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
1409     DrawEngineType *engine = link->data;
1410     engine_handle_array[i++] = engine;
1411   }
1412   engine_handle_array[i] = NULL;
1413
1414   GPU_viewport_engines_data_validate(DST.viewport, engine_handle_array);
1415 }
1416
1417 /* -------------------------------------------------------------------- */
1418 /** \name View Update
1419  * \{ */
1420
1421 void DRW_notify_view_update(const DRWUpdateContext *update_ctx)
1422 {
1423   RenderEngineType *engine_type = update_ctx->engine_type;
1424   ARegion *ar = update_ctx->ar;
1425   View3D *v3d = update_ctx->v3d;
1426   RegionView3D *rv3d = ar->regiondata;
1427   Depsgraph *depsgraph = update_ctx->depsgraph;
1428   Scene *scene = update_ctx->scene;
1429   ViewLayer *view_layer = update_ctx->view_layer;
1430
1431   /* Separate update for each stereo view. */
1432   for (int view = 0; view < 2; view++) {
1433     GPUViewport *viewport = WM_draw_region_get_viewport(ar, view);
1434     if (!viewport) {
1435       continue;
1436     }
1437
1438     /* XXX Really nasty locking. But else this could
1439      * be executed by the material previews thread
1440      * while rendering a viewport. */
1441     BLI_ticket_mutex_lock(DST.gl_context_mutex);
1442
1443     /* Reset before using it. */
1444     drw_state_prepare_clean_for_draw(&DST);
1445
1446     DST.viewport = viewport;
1447     DST.draw_ctx = (DRWContextState){
1448         .ar = ar,
1449         .rv3d = rv3d,
1450         .v3d = v3d,
1451         .scene = scene,
1452         .view_layer = view_layer,
1453         .obact = OBACT(view_layer),
1454         .engine_type = engine_type,
1455         .depsgraph = depsgraph,
1456         .object_mode = OB_MODE_OBJECT,
1457     };
1458
1459     drw_engines_enable(view_layer, engine_type);
1460
1461     for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
1462       DrawEngineType *draw_engine = link->data;
1463       ViewportEngineData *data = drw_viewport_engine_data_ensure(draw_engine);
1464
1465       if (draw_engine->view_update) {
1466         draw_engine->view_update(data);
1467       }
1468     }
1469
1470     DST.viewport = NULL;
1471
1472     drw_engines_disable();
1473
1474     BLI_ticket_mutex_unlock(DST.gl_context_mutex);
1475   }
1476 }
1477
1478 /** \} */
1479
1480 /* -------------------------------------------------------------------- */
1481 /** \name Main Draw Loops (DRW_draw)
1482  * \{ */
1483
1484 /* Everything starts here.
1485  * This function takes care of calling all cache and rendering functions
1486  * for each relevant engine / mode engine. */
1487 void DRW_draw_view(const bContext *C)
1488 {
1489   Depsgraph *depsgraph = CTX_data_depsgraph(C);
1490   ARegion *ar = CTX_wm_region(C);
1491   View3D *v3d = CTX_wm_view3d(C);
1492   Scene *scene = DEG_get_evaluated_scene(depsgraph);
1493   RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->shading.type);
1494   GPUViewport *viewport = WM_draw_region_get_bound_viewport(ar);
1495
1496   /* Reset before using it. */
1497   drw_state_prepare_clean_for_draw(&DST);
1498   DST.options.draw_text = ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0 &&
1499                            (v3d->overlay.flag & V3D_OVERLAY_HIDE_TEXT) != 0);
1500   DST.options.draw_background = scene->r.alphamode == R_ADDSKY;
1501   DRW_draw_render_loop_ex(depsgraph, engine_type, ar, v3d, viewport, C);
1502 }
1503
1504 /**
1505  * Used for both regular and off-screen drawing.
1506  * Need to reset DST before calling this function
1507  */
1508 void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
1509                              RenderEngineType *engine_type,
1510                              ARegion *ar,
1511                              View3D *v3d,
1512                              GPUViewport *viewport,
1513                              const bContext *evil_C)
1514 {
1515
1516   Scene *scene = DEG_get_evaluated_scene(depsgraph);
1517   ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
1518   RegionView3D *rv3d = ar->regiondata;
1519   const bool do_annotations = (((v3d->flag2 & V3D_SHOW_ANNOTATION) != 0) &&
1520                                ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0));
1521   const bool do_camera_frame = !DST.options.is_image_render;
1522
1523   DST.draw_ctx.evil_C = evil_C;
1524   DST.viewport = viewport;
1525
1526   /* Setup viewport */
1527   DST.draw_ctx = (DRWContextState){
1528       .ar = ar,
1529       .rv3d = rv3d,
1530       .v3d = v3d,
1531       .scene = scene,
1532       .view_layer = view_layer,
1533       .obact = OBACT(view_layer),
1534       .engine_type = engine_type,
1535       .depsgraph = depsgraph,
1536
1537       /* reuse if caller sets */
1538       .evil_C = DST.draw_ctx.evil_C,
1539   };
1540   drw_context_state_init();
1541   drw_viewport_var_init();
1542
1543   /* Get list of enabled engines */
1544   drw_engines_enable(view_layer, engine_type);
1545
1546   drw_engines_data_validate();
1547
1548   /* Update ubos */
1549   DRW_globals_update();
1550
1551   drw_debug_init();
1552   DRW_hair_init();
1553
1554   /* No framebuffer allowed before drawing. */
1555   BLI_assert(GPU_framebuffer_active_get() == NULL);
1556
1557   /* Init engines */
1558   drw_engines_init();
1559
1560   /* Cache filling */
1561   {
1562     PROFILE_START(stime);
1563     drw_engines_cache_init();
1564     drw_engines_world_update(scene);
1565
1566     /* Only iterate over objects for internal engines or when overlays are enabled */
1567     const bool internal_engine = (engine_type->flag & RE_INTERNAL) != 0;
1568     const bool draw_type_render = v3d->shading.type == OB_RENDER;
1569     const bool overlays_on = (v3d->flag2 & V3D_HIDE_OVERLAYS) == 0;
1570     if (internal_engine || overlays_on || !draw_type_render) {
1571       const int object_type_exclude_viewport = v3d->object_type_exclude_viewport;
1572       const int iter_flag = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY |
1573                             DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | DEG_ITER_OBJECT_FLAG_VISIBLE |
1574                             DEG_ITER_OBJECT_FLAG_DUPLI;
1575       DEG_OBJECT_ITER_BEGIN (depsgraph, ob, iter_flag) {
1576         if ((object_type_exclude_viewport & (1 << ob->type)) != 0) {
1577           continue;
1578         }
1579         if (v3d->localvd && ((v3d->local_view_uuid & ob->base_local_view_bits) == 0)) {
1580           continue;
1581         }
1582         DST.dupli_parent = data_.dupli_parent;
1583         DST.dupli_source = data_.dupli_object_current;
1584         drw_duplidata_load(DST.dupli_source);
1585         drw_engines_cache_populate(ob);
1586       }
1587       DEG_OBJECT_ITER_END;
1588     }
1589
1590     drw_duplidata_free();
1591     drw_engines_cache_finish();
1592
1593     DRW_render_instance_buffer_finish();
1594
1595 #ifdef USE_PROFILE
1596     double *cache_time = GPU_viewport_cache_time_get(DST.viewport);
1597     PROFILE_END_UPDATE(*cache_time, stime);
1598 #endif
1599   }
1600
1601   DRW_stats_begin();
1602
1603   GPU_framebuffer_bind(DST.default_framebuffer);
1604
1605   /* Start Drawing */
1606   DRW_state_reset();
1607
1608   DRW_hair_update();
1609
1610   drw_engines_draw_background();
1611
1612   /* WIP, single image drawn over the camera view (replace) */
1613   bool do_bg_image = false;
1614   if (rv3d->persp == RV3D_CAMOB) {
1615     Object *cam_ob = v3d->camera;
1616     if (cam_ob && cam_ob->type == OB_CAMERA) {
1617       Camera *cam = cam_ob->data;
1618       if (!BLI_listbase_is_empty(&cam->bg_images)) {
1619         do_bg_image = true;
1620       }
1621     }
1622   }
1623
1624   GPU_framebuffer_bind(DST.default_framebuffer);
1625
1626   if (do_bg_image) {
1627     ED_view3d_draw_bgpic_test(scene, depsgraph, ar, v3d, false, do_camera_frame);
1628   }
1629
1630   DRW_draw_callbacks_pre_scene();
1631   if (DST.draw_ctx.evil_C) {
1632     ED_region_draw_cb_draw(DST.draw_ctx.evil_C, DST.draw_ctx.ar, REGION_DRAW_PRE_VIEW);
1633   }
1634
1635   drw_engines_draw_scene();
1636
1637   /* Fix 3D view being "laggy" on macos and win+nvidia. (See T56996, T61474) */
1638   GPU_flush();
1639
1640   /* annotations - temporary drawing buffer (3d space) */
1641   /* XXX: Or should we use a proper draw/overlay engine for this case? */
1642   if (do_annotations) {
1643     GPU_depth_test(false);
1644     /* XXX: as scene->gpd is not copied for COW yet */
1645     ED_annotation_draw_view3d(DEG_get_input_scene(depsgraph), depsgraph, v3d, ar, true);
1646     GPU_depth_test(true);
1647   }
1648
1649   DRW_draw_callbacks_post_scene();
1650   DRW_state_reset();
1651
1652   if (DST.draw_ctx.evil_C) {
1653     ED_region_draw_cb_draw(DST.draw_ctx.evil_C, DST.draw_ctx.ar, REGION_DRAW_POST_VIEW);
1654     /* Callback can be nasty and do whatever they want with the state.
1655      * Don't trust them! */
1656     DRW_state_reset();
1657   }
1658
1659   drw_debug_draw();
1660
1661   GPU_depth_test(false);
1662   drw_engines_draw_text();
1663   GPU_depth_test(true);
1664
1665   if (DST.draw_ctx.evil_C) {
1666     /* needed so gizmo isn't obscured */
1667     if ((v3d->gizmo_flag & V3D_GIZMO_HIDE) == 0) {
1668       glDisable(GL_DEPTH_TEST);
1669       DRW_draw_gizmo_3d();
1670     }
1671
1672     DRW_draw_region_info();
1673
1674     /* annotations - temporary drawing buffer (screenspace) */
1675     /* XXX: Or should we use a proper draw/overlay engine for this case? */
1676     if (((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) && (do_annotations)) {
1677       GPU_depth_test(false);
1678       /* XXX: as scene->gpd is not copied for COW yet */
1679       ED_annotation_draw_view3d(DEG_get_input_scene(depsgraph), depsgraph, v3d, ar, false);
1680       GPU_depth_test(true);
1681     }
1682
1683     if ((v3d->gizmo_flag & V3D_GIZMO_HIDE) == 0) {
1684       /* Draw 2D after region info so we can draw on top of the camera passepartout overlay.
1685        * 'DRW_draw_region_info' sets the projection in pixel-space. */
1686       GPU_depth_test(false);
1687       DRW_draw_gizmo_2d();
1688       GPU_depth_test(true);
1689     }
1690   }
1691
1692   DRW_stats_reset();
1693
1694   if (do_bg_image) {
1695     ED_view3d_draw_bgpic_test(scene, depsgraph, ar, v3d, true, do_camera_frame);
1696   }
1697
1698   if (G.debug_value > 20 && G.debug_value < 30) {
1699     GPU_depth_test(false);
1700     rcti rect; /* local coordinate visible rect inside region, to accommodate overlapping ui */
1701     ED_region_visible_rect(DST.draw_ctx.ar, &rect);
1702     DRW_stats_draw(&rect);
1703     GPU_depth_test(true);
1704   }
1705
1706   if (WM_draw_region_get_bound_viewport(ar)) {
1707     /* Don't unbind the framebuffer yet in this case and let
1708      * GPU_viewport_unbind do it, so that we can still do further
1709      * drawing of action zones on top. */
1710   }
1711   else {
1712     GPU_framebuffer_restore();
1713   }
1714
1715   DRW_state_reset();
1716   drw_engines_disable();
1717
1718   drw_viewport_cache_resize();
1719
1720 #ifdef DEBUG
1721   /* Avoid accidental reuse. */
1722   drw_state_ensure_not_reused(&DST);
1723 #endif
1724 }
1725
1726 void DRW_draw_render_loop(struct Depsgraph *depsgraph,
1727                           ARegion *ar,
1728                           View3D *v3d,
1729                           GPUViewport *viewport)
1730 {
1731   /* Reset before using it. */
1732   drw_state_prepare_clean_for_draw(&DST);
1733
1734   Scene *scene = DEG_get_evaluated_scene(depsgraph);
1735   RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->shading.type);
1736
1737   DRW_draw_render_loop_ex(depsgraph, engine_type, ar, v3d, viewport, NULL);
1738 }
1739
1740 /* @viewport CAN be NULL, in this case we create one. */
1741 void DRW_draw_render_loop_offscreen(struct Depsgraph *depsgraph,
1742                                     RenderEngineType *engine_type,
1743                                     ARegion *ar,
1744                                     View3D *v3d,
1745                                     const bool draw_background,
1746                                     const bool do_color_management,
1747                                     GPUOffScreen *ofs,
1748                                     GPUViewport *viewport)
1749 {
1750   /* Create temporary viewport if needed. */
1751   GPUViewport *render_viewport = viewport;
1752   if (viewport == NULL) {
1753     render_viewport = GPU_viewport_create_from_offscreen(ofs);
1754   }
1755
1756   GPU_framebuffer_restore();
1757
1758   /* Reset before using it. */
1759   drw_state_prepare_clean_for_draw(&DST);
1760   /* WATCH: Force color management to output CManaged byte buffer by
1761    * forcing is_image_render to false. */
1762   DST.options.is_image_render = !do_color_management;
1763   DST.options.draw_background = draw_background;
1764   DRW_draw_render_loop_ex(depsgraph, engine_type, ar, v3d, render_viewport, NULL);
1765
1766   /* Free temporary viewport. */
1767   if (viewport == NULL) {
1768     /* don't free data owned by 'ofs' */
1769     GPU_viewport_clear_from_offscreen(render_viewport);
1770     GPU_viewport_free(render_viewport);
1771   }
1772
1773   /* we need to re-bind (annoying!) */
1774   GPU_offscreen_bind(ofs, false);
1775 }
1776
1777 /* Helper to check if exit object type to render. */
1778 bool DRW_render_check_grease_pencil(Depsgraph *depsgraph)
1779 {
1780   DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN (depsgraph, ob) {
1781     if (ob->type == OB_GPENCIL) {
1782       if (DRW_object_visibility_in_active_context(ob) & OB_VISIBLE_SELF) {
1783         return true;
1784       }
1785     }
1786   }
1787   DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END;
1788
1789   return false;
1790 }
1791
1792 static void DRW_render_gpencil_to_image(RenderEngine *engine,
1793                                         struct RenderLayer *render_layer,
1794                                         const rcti *rect)
1795 {
1796   if (draw_engine_gpencil_type.render_to_image) {
1797     ViewportEngineData *gpdata = drw_viewport_engine_data_ensure(&draw_engine_gpencil_type);
1798     draw_engine_gpencil_type.render_to_image(gpdata, engine, render_layer, rect);
1799   }
1800 }
1801
1802 void DRW_render_gpencil(struct RenderEngine *engine, struct Depsgraph *depsgraph)
1803 {
1804   /* This function is only valid for Cycles & Workbench
1805    * Eevee does all work in the Eevee render directly.
1806    * Maybe it can be done equal for all engines?
1807    */
1808   if (STREQ(engine->type->name, "Eevee")) {
1809     return;
1810   }
1811
1812   /* Early out if there are no grease pencil objects, especially important
1813    * to avoid failing in in background renders without OpenGL context. */
1814   if (!DRW_render_check_grease_pencil(depsgraph)) {
1815     return;
1816   }
1817
1818   Scene *scene = DEG_get_evaluated_scene(depsgraph);
1819   ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
1820   RenderEngineType *engine_type = engine->type;
1821   RenderData *r = &scene->r;
1822   Render *render = engine->re;
1823   /* Changing Context */
1824   if (G.background && DST.gl_context == NULL) {
1825     WM_init_opengl(G_MAIN);
1826   }
1827
1828   void *re_gl_context = RE_gl_context_get(render);
1829   void *re_gpu_context = NULL;
1830
1831   /* Changing Context */
1832   if (re_gl_context != NULL) {
1833     DRW_opengl_render_context_enable(re_gl_context);
1834     /* We need to query gpu context after a gl context has been bound. */
1835     re_gpu_context = RE_gpu_context_get(render);
1836     DRW_gawain_render_context_enable(re_gpu_context);
1837   }
1838   else {
1839     DRW_opengl_context_enable();
1840   }
1841
1842   /* Reset before using it. */
1843   drw_state_prepare_clean_for_draw(&DST);
1844   DST.options.is_image_render = true;
1845   DST.options.is_scene_render = true;
1846   DST.options.draw_background = scene->r.alphamode == R_ADDSKY;
1847   DST.buffer_finish_called = true;
1848
1849   DST.draw_ctx = (DRWContextState){
1850       .scene = scene,
1851       .view_layer = view_layer,
1852       .engine_type = engine_type,
1853       .depsgraph = depsgraph,
1854       .object_mode = OB_MODE_OBJECT,
1855   };
1856   drw_context_state_init();
1857
1858   DST.viewport = GPU_viewport_create();
1859   const int size[2] = {(r->size * r->xsch) / 100, (r->size * r->ysch) / 100};
1860   GPU_viewport_size_set(DST.viewport, size);
1861
1862   drw_viewport_var_init();
1863
1864   /* Main rendering. */
1865   rctf view_rect;
1866   rcti render_rect;
1867   RE_GetViewPlane(render, &view_rect, &render_rect);
1868   if (BLI_rcti_is_empty(&render_rect)) {
1869     BLI_rcti_init(&render_rect, 0, size[0], 0, size[1]);
1870   }
1871
1872   RenderResult *render_result = RE_engine_get_result(engine);
1873   RenderLayer *render_layer = RE_GetRenderLayer(render_result, view_layer->name);
1874
1875   DRW_render_gpencil_to_image(engine, render_layer, &render_rect);
1876
1877   /* Force cache to reset. */
1878   drw_viewport_cache_resize();
1879   GPU_viewport_free(DST.viewport);
1880   DRW_state_reset();
1881
1882   glDisable(GL_DEPTH_TEST);
1883
1884   /* Restore Drawing area. */
1885   GPU_framebuffer_restore();
1886
1887   /* Changing Context */
1888   /* GPXX Review this context */
1889   DRW_opengl_context_disable();
1890
1891   DST.buffer_finish_called = false;
1892 }
1893
1894 void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph)
1895 {
1896   Scene *scene = DEG_get_evaluated_scene(depsgraph);
1897   ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
1898   RenderEngineType *engine_type = engine->type;
1899   DrawEngineType *draw_engine_type = engine_type->draw_engine;
1900   Render *render = engine->re;
1901
1902   if (G.background && DST.gl_context == NULL) {
1903     WM_init_opengl(G_MAIN);
1904   }
1905
1906   void *re_gl_context = RE_gl_context_get(render);
1907   void *re_gpu_context = NULL;
1908
1909   /* Changing Context */
1910   if (re_gl_context != NULL) {
1911     DRW_opengl_render_context_enable(re_gl_context);
1912     /* We need to query gpu context after a gl context has been bound. */
1913     re_gpu_context = RE_gpu_context_get(render);
1914     DRW_gawain_render_context_enable(re_gpu_context);
1915   }
1916   else {
1917     DRW_opengl_context_enable();
1918   }
1919
1920   /* IMPORTANT: We dont support immediate mode in render mode!
1921    * This shall remain in effect until immediate mode supports
1922    * multiple threads. */
1923
1924   /* Reset before using it. */
1925   drw_state_prepare_clean_for_draw(&DST);
1926   DST.options.is_image_render = true;
1927   DST.options.is_scene_render = true;
1928   DST.options.draw_background = scene->r.alphamode == R_ADDSKY;
1929
1930   DST.draw_ctx = (DRWContextState){
1931       .scene = scene,
1932       .view_layer = view_layer,
1933       .engine_type = engine_type,
1934       .depsgraph = depsgraph,
1935       .object_mode = OB_MODE_OBJECT,
1936   };
1937   drw_context_state_init();
1938
1939   DST.viewport = GPU_viewport_create();
1940   const int size[2] = {engine->resolution_x, engine->resolution_y};
1941   GPU_viewport_size_set(DST.viewport, size);
1942
1943   drw_viewport_var_init();
1944
1945   ViewportEngineData *data = drw_viewport_engine_data_ensure(draw_engine_type);
1946
1947   /* set default viewport */
1948   glViewport(0, 0, size[0], size[1]);
1949
1950   /* Main rendering. */
1951   rctf view_rect;
1952   rcti render_rect;
1953   RE_GetViewPlane(render, &view_rect, &render_rect);
1954   if (BLI_rcti_is_empty(&render_rect)) {
1955     BLI_rcti_init(&render_rect, 0, size[0], 0, size[1]);
1956   }
1957
1958   /* Reset state before drawing */
1959   DRW_state_reset();
1960
1961   /* Init render result. */
1962   RenderResult *render_result = RE_engine_begin_result(engine,
1963                                                        0,
1964                                                        0,
1965                                                        (int)size[0],
1966                                                        (int)size[1],
1967                                                        view_layer->name,
1968                                                        /* RR_ALL_VIEWS */ NULL);
1969
1970   RenderLayer *render_layer = render_result->layers.first;
1971   for (RenderView *render_view = render_result->views.first; render_view != NULL;
1972        render_view = render_view->next) {
1973     RE_SetActiveRenderView(render, render_view->name);
1974     engine_type->draw_engine->render_to_image(data, engine, render_layer, &render_rect);
1975     /* grease pencil: render result is merged in the previous render result. */
1976     if (DRW_render_check_grease_pencil(depsgraph)) {
1977       DRW_state_reset();
1978       DRW_render_gpencil_to_image(engine, render_layer, &render_rect);
1979     }
1980     DST.buffer_finish_called = false;
1981   }
1982
1983   RE_engine_end_result(engine, render_result, false, false, false);
1984
1985   /* Force cache to reset. */
1986   drw_viewport_cache_resize();
1987
1988   GPU_viewport_free(DST.viewport);
1989   GPU_framebuffer_restore();
1990
1991 #ifdef DEBUG
1992   /* Avoid accidental reuse. */
1993   drw_state_ensure_not_reused(&DST);
1994 #endif
1995
1996   /* Reset state after drawing */
1997   DRW_state_reset();
1998
1999   /* Changing Context */
2000   if (re_gl_context != NULL) {
2001     DRW_gawain_render_context_disable(re_gpu_context);
2002     DRW_opengl_render_context_disable(re_gl_context);
2003   }
2004   else {
2005     DRW_opengl_context_disable();
2006   }
2007 }
2008
2009 void DRW_render_object_iter(
2010     void *vedata,
2011     RenderEngine *engine,
2012     struct Depsgraph *depsgraph,
2013     void (*callback)(void *vedata, Object *ob, RenderEngine *engine, struct Depsgraph *depsgraph))
2014 {
2015   const DRWContextState *draw_ctx = DRW_context_state_get();
2016
2017   DRW_hair_init();
2018
2019   const int object_type_exclude_viewport = draw_ctx->v3d ?
2020                                                draw_ctx->v3d->object_type_exclude_viewport :
2021                                                0;
2022   const int iter_flag = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY |
2023                         DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | DEG_ITER_OBJECT_FLAG_VISIBLE |
2024                         DEG_ITER_OBJECT_FLAG_DUPLI;
2025   DEG_OBJECT_ITER_BEGIN (depsgraph, ob, iter_flag) {
2026     if ((object_type_exclude_viewport & (1 << ob->type)) == 0) {
2027       DST.dupli_parent = data_.dupli_parent;
2028       DST.dupli_source = data_.dupli_object_current;
2029       DST.ob_state = NULL;
2030       drw_duplidata_load(DST.dupli_source);
2031
2032       if (!DST.dupli_source) {
2033         drw_batch_cache_validate(ob);
2034       }
2035       callback(vedata, ob, engine, depsgraph);
2036       if (!DST.dupli_source) {
2037         drw_batch_cache_generate_requested(ob);
2038       }
2039     }
2040   }
2041   DEG_OBJECT_ITER_END;
2042
2043   drw_duplidata_free();
2044 }
2045
2046 /* Assume a valid gl context is bound (and that the gl_context_mutex has been acquired).
2047  * This function only setup DST and execute the given function.
2048  * Warning: similar to DRW_render_to_image you cannot use default lists (dfbl & dtxl). */
2049 void DRW_custom_pipeline(DrawEngineType *draw_engine_type,
2050                          struct Depsgraph *depsgraph,
2051                          void (*callback)(void *vedata, void *user_data),
2052                          void *user_data)
2053 {
2054   Scene *scene = DEG_get_evaluated_scene(depsgraph);
2055   ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
2056
2057   /* Reset before using it. */
2058   drw_state_prepare_clean_for_draw(&DST);
2059   DST.options.is_image_render = true;
2060   DST.options.is_scene_render = true;
2061   DST.options.draw_background = false;
2062
2063   DST.draw_ctx = (DRWContextState){
2064       .scene = scene,
2065       .view_layer = view_layer,
2066       .engine_type = NULL,
2067       .depsgraph = depsgraph,
2068       .object_mode = OB_MODE_OBJECT,
2069   };
2070   drw_context_state_init();
2071
2072   DST.viewport = GPU_viewport_create();
2073   const int size[2] = {1, 1};
2074   GPU_viewport_size_set(DST.viewport, size);
2075
2076   drw_viewport_var_init();
2077
2078   DRW_hair_init();
2079
2080   ViewportEngineData *data = drw_viewport_engine_data_ensure(draw_engine_type);
2081
2082   /* Execute the callback */
2083   callback(data, user_data);
2084   DST.buffer_finish_called = false;
2085
2086   GPU_viewport_free(DST.viewport);
2087   GPU_framebuffer_restore();
2088
2089   /* The use of custom pipeline in other thread using the same
2090    * resources as the main thread (viewport) may lead to data
2091    * races and undefined behavior on certain drivers. Using
2092    * GPU_finish to sync seems to fix the issue. (see T62997) */
2093   GPU_finish();
2094
2095 #ifdef DEBUG
2096   /* Avoid accidental reuse. */
2097   drw_state_ensure_not_reused(&DST);
2098 #endif
2099 }
2100
2101 static struct DRWSelectBuffer {
2102   struct GPUFrameBuffer *framebuffer_depth_only;
2103   struct GPUFrameBuffer *framebuffer_select_id;
2104   struct GPUTexture *texture_depth;
2105   struct GPUTexture *texture_u32;
2106 } g_select_buffer = {NULL};
2107
2108 static void draw_select_framebuffer_depth_only_setup(const int size[2])
2109 {
2110   if (g_select_buffer.framebuffer_depth_only == NULL) {
2111     g_select_buffer.framebuffer_depth_only = GPU_framebuffer_create();
2112     g_select_buffer.framebuffer_select_id = GPU_framebuffer_create();
2113   }
2114
2115   if ((g_select_buffer.texture_depth != NULL) &&
2116       ((GPU_texture_width(g_select_buffer.texture_depth) != size[0]) ||
2117        (GPU_texture_height(g_select_buffer.texture_depth) != size[1]))) {
2118     GPU_texture_free(g_select_buffer.texture_depth);
2119     g_select_buffer.texture_depth = NULL;
2120   }
2121
2122   if (g_select_buffer.texture_depth == NULL) {
2123     g_select_buffer.texture_depth = GPU_texture_create_2d(
2124         size[0], size[1], GPU_DEPTH_COMPONENT24, NULL, NULL);
2125
2126     GPU_framebuffer_texture_attach(
2127         g_select_buffer.framebuffer_depth_only, g_select_buffer.texture_depth, 0, 0);
2128
2129     GPU_framebuffer_texture_attach(
2130         g_select_buffer.framebuffer_select_id, g_select_buffer.texture_depth, 0, 0);
2131
2132     GPU_framebuffer_check_valid(g_select_buffer.framebuffer_depth_only, NULL);
2133     GPU_framebuffer_check_valid(g_select_buffer.framebuffer_select_id, NULL);
2134   }
2135 }
2136
2137 static void draw_select_framebuffer_select_id_setup(const int size[2])
2138 {
2139   draw_select_framebuffer_depth_only_setup(size);
2140
2141   if ((g_select_buffer.texture_u32 != NULL) &&
2142       ((GPU_texture_width(g_select_buffer.texture_u32) != size[0]) ||
2143        (GPU_texture_height(g_select_buffer.texture_u32) != size[1]))) {
2144     GPU_texture_free(g_select_buffer.texture_u32);
2145     g_select_buffer.texture_u32 = NULL;
2146   }
2147
2148   if (g_select_buffer.texture_u32 == NULL) {
2149     g_select_buffer.texture_u32 = GPU_texture_create_2d(size[0], size[1], GPU_R32UI, NULL, NULL);
2150
2151     GPU_framebuffer_texture_attach(
2152         g_select_buffer.framebuffer_select_id, g_select_buffer.texture_u32, 0, 0);
2153
2154     GPU_framebuffer_check_valid(g_select_buffer.framebuffer_select_id, NULL);
2155   }
2156 }
2157
2158 /* Must run after all instance datas have been added. */
2159 void DRW_render_instance_buffer_finish(void)
2160 {
2161   BLI_assert(!DST.buffer_finish_called && "DRW_render_instance_buffer_finish called twice!");
2162   DST.buffer_finish_called = true;
2163   DRW_instance_buffer_finish(DST.idatalist);
2164 }
2165
2166 /**
2167  * object mode select-loop, see: ED_view3d_draw_select_loop (legacy drawing).
2168  */
2169 void DRW_draw_select_loop(struct Depsgraph *depsgraph,
2170                           ARegion *ar,
2171                           View3D *v3d,
2172                           bool UNUSED(use_obedit_skip),
2173                           bool draw_surface,
2174                           bool UNUSED(use_nearest),
2175                           const rcti *rect,
2176                           DRW_SelectPassFn select_pass_fn,
2177                           void *select_pass_user_data,
2178                           DRW_ObjectFilterFn object_filter_fn,
2179                           void *object_filter_user_data)
2180 {
2181   Scene *scene = DEG_get_evaluated_scene(depsgraph);
2182   RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->shading.type);
2183   ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
2184   Object *obact = OBACT(view_layer);
2185   Object *obedit = OBEDIT_FROM_OBACT(obact);
2186 #ifndef USE_GPU_SELECT
2187   UNUSED_VARS(vc, scene, view_layer, v3d, ar, rect);
2188 #else
2189   RegionView3D *rv3d = ar->regiondata;
2190
2191   /* Reset before using it. */
2192   drw_state_prepare_clean_for_draw(&DST);
2193
2194   bool use_obedit = false;
2195   int obedit_mode = 0;
2196   if (obedit != NULL) {
2197     if (obedit->type == OB_MBALL) {
2198       use_obedit = true;
2199       obedit_mode = CTX_MODE_EDIT_METABALL;
2200     }
2201     else if (obedit->type == OB_ARMATURE) {
2202       use_obedit = true;
2203       obedit_mode = CTX_MODE_EDIT_ARMATURE;
2204     }
2205   }
2206   if (v3d->overlay.flag & V3D_OVERLAY_BONE_SELECT) {
2207     if (!(v3d->flag2 & V3D_HIDE_OVERLAYS)) {
2208       /* Note: don't use "BKE_object_pose_armature_get" here, it breaks selection. */
2209       Object *obpose = OBPOSE_FROM_OBACT(obact);
2210       if (obpose) {
2211         use_obedit = true;
2212         obedit_mode = CTX_MODE_POSE;
2213       }
2214     }
2215   }
2216
2217   int viewport_size[2] = {BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)};
2218   struct GPUViewport *viewport = GPU_viewport_create();
2219   GPU_viewport_size_set(viewport, viewport_size);
2220
2221   DST.viewport = viewport;
2222   DST.options.is_select = true;
2223
2224   /* Get list of enabled engines */
2225   if (use_obedit) {
2226     drw_engines_enable_from_paint_mode(obedit_mode);
2227     drw_engines_enable_from_mode(obedit_mode);
2228   }
2229   else if (!draw_surface) {
2230     /* grease pencil selection */
2231     use_drw_engine(&draw_engine_gpencil_type);
2232
2233     drw_engines_enable_from_overlays(v3d->overlay.flag);
2234     drw_engines_enable_from_object_mode();
2235   }
2236   else {
2237     drw_engines_enable_basic();
2238     /* grease pencil selection */
2239     use_drw_engine(&draw_engine_gpencil_type);
2240
2241     drw_engines_enable_from_overlays(v3d->overlay.flag);
2242     drw_engines_enable_from_object_mode();
2243   }
2244
2245   /* Setup viewport */
2246
2247   /* Instead of 'DRW_context_state_init(C, &DST.draw_ctx)', assign from args */
2248   DST.draw_ctx = (DRWContextState){
2249       .ar = ar,
2250       .rv3d = rv3d,
2251       .v3d = v3d,
2252       .scene = scene,
2253       .view_layer = view_layer,
2254       .obact = obact,
2255       .engine_type = engine_type,
2256       .depsgraph = depsgraph,
2257   };
2258   drw_context_state_init();
2259   drw_viewport_var_init();
2260
2261   /* Update ubos */
2262   DRW_globals_update();
2263
2264   /* Init engines */
2265   drw_engines_init();
2266   DRW_hair_init();
2267
2268   {
2269     drw_engines_cache_init();
2270     drw_engines_world_update(scene);
2271
2272     if (use_obedit) {
2273       FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, obact->type, obact->mode, ob_iter) {
2274         drw_engines_cache_populate(ob_iter);
2275       }
2276       FOREACH_OBJECT_IN_MODE_END;
2277     }
2278     else {
2279       const int iter_flag = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY |
2280                             DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | DEG_ITER_OBJECT_FLAG_VISIBLE |
2281                             DEG_ITER_OBJECT_FLAG_DUPLI;
2282       const int object_type_exclude_select = (v3d->object_type_exclude_viewport |
2283                                               v3d->object_type_exclude_select);
2284       bool filter_exclude = false;
2285       DEG_OBJECT_ITER_BEGIN (depsgraph, ob, iter_flag) {
2286         if (v3d->localvd && ((v3d->local_view_uuid & ob->base_local_view_bits) == 0)) {
2287           continue;
2288         }
2289
2290         if ((ob->base_flag & BASE_SELECTABLE) &&
2291             (object_type_exclude_select & (1 << ob->type)) == 0) {
2292           if (object_filter_fn != NULL) {
2293             if (ob->base_flag & BASE_FROM_DUPLI) {
2294               /* pass (use previous filter_exclude value) */
2295             }
2296             else {
2297               filter_exclude = (object_filter_fn(ob, object_filter_user_data) == false);
2298             }
2299             if (filter_exclude) {
2300               continue;
2301             }
2302           }
2303
2304           /* This relies on dupli instances being after their instancing object. */
2305           if ((ob->base_flag & BASE_FROM_DUPLI) == 0) {
2306             Object *ob_orig = DEG_get_original_object(ob);
2307             DRW_select_load_id(ob_orig->runtime.select_id);
2308           }
2309           DST.dupli_parent = data_.dupli_parent;
2310           DST.dupli_source = data_.dupli_object_current;
2311           drw_duplidata_load(DST.dupli_source);
2312           drw_engines_cache_populate(ob);
2313         }
2314       }
2315       DEG_OBJECT_ITER_END;
2316     }
2317
2318     drw_duplidata_free();
2319     drw_engines_cache_finish();
2320
2321     DRW_render_instance_buffer_finish();
2322   }
2323
2324   /* Setup framebuffer */
2325   draw_select_framebuffer_depth_only_setup(viewport_size);
2326   GPU_framebuffer_bind(g_select_buffer.framebuffer_depth_only);
2327   GPU_framebuffer_clear_depth(g_select_buffer.framebuffer_depth_only, 1.0f);
2328
2329   /* Start Drawing */
2330   DRW_state_reset();
2331   DRW_draw_callbacks_pre_scene();
2332
2333   DRW_hair_update();
2334
2335   DRW_state_lock(DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS | DRW_STATE_DEPTH_LESS_EQUAL |
2336                  DRW_STATE_DEPTH_EQUAL | DRW_STATE_DEPTH_GREATER | DRW_STATE_DEPTH_ALWAYS);
2337
2338   /* Only 1-2 passes. */
2339   while (true) {
2340     if (!select_pass_fn(DRW_SELECT_PASS_PRE, select_pass_user_data)) {
2341       break;
2342     }
2343
2344     drw_engines_draw_scene();
2345
2346     if (!select_pass_fn(DRW_SELECT_PASS_POST, select_pass_user_data)) {
2347       break;
2348     }
2349   }
2350
2351   DRW_state_lock(0);
2352
2353   DRW_draw_callbacks_post_scene();
2354
2355   DRW_state_reset();
2356   drw_engines_disable();
2357
2358 #  ifdef DEBUG
2359   /* Avoid accidental reuse. */
2360   drw_state_ensure_not_reused(&DST);
2361 #  endif
2362   GPU_framebuffer_restore();
2363
2364   /* Cleanup for selection state */
2365   GPU_viewport_free(viewport);
2366 #endif /* USE_GPU_SELECT */
2367 }
2368
2369 /**
2370  * object mode select-loop, see: ED_view3d_draw_depth_loop (legacy drawing).
2371  */
2372 static void drw_draw_depth_loop_imp(void)
2373 {
2374   /* Setup framebuffer */
2375   DefaultFramebufferList *fbl = (DefaultFramebufferList *)GPU_viewport_framebuffer_list_get(
2376       DST.viewport);
2377   GPU_framebuffer_bind(fbl->depth_only_fb);
2378   GPU_framebuffer_clear_depth(fbl->depth_only_fb, 1.0f);
2379
2380   /* Setup viewport */
2381   drw_context_state_init();
2382   drw_viewport_var_init();
2383
2384   /* Update ubos */
2385   DRW_globals_update();
2386
2387   /* Init engines */
2388   drw_engines_init();
2389   DRW_hair_init();
2390
2391   {
2392     drw_engines_cache_init();
2393     drw_engines_world_update(DST.draw_ctx.scene);
2394
2395     View3D *v3d = DST.draw_ctx.v3d;
2396     const int object_type_exclude_viewport = v3d->object_type_exclude_viewport;
2397     const int iter_flag = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY |
2398                           DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | DEG_ITER_OBJECT_FLAG_VISIBLE |
2399                           DEG_ITER_OBJECT_FLAG_DUPLI;
2400     DEG_OBJECT_ITER_BEGIN (DST.draw_ctx.depsgraph, ob, iter_flag) {
2401       if ((object_type_exclude_viewport & (1 << ob->type)) != 0) {
2402         continue;
2403       }
2404
2405       if (v3d->localvd && ((v3d->local_view_uuid & ob->base_local_view_bits) == 0)) {
2406         continue;
2407       }
2408
2409       DST.dupli_parent = data_.dupli_parent;
2410       DST.dupli_source = data_.dupli_object_current;
2411       drw_duplidata_load(DST.dupli_source);
2412       drw_engines_cache_populate(ob);
2413     }
2414     DEG_OBJECT_ITER_END;
2415
2416     drw_duplidata_free();
2417     drw_engines_cache_finish();
2418
2419     DRW_render_instance_buffer_finish();
2420   }
2421
2422   /* Start Drawing */
2423   DRW_state_reset();
2424
2425   DRW_hair_update();
2426
2427   DRW_draw_callbacks_pre_scene();
2428   drw_engines_draw_scene();
2429   DRW_draw_callbacks_post_scene();
2430
2431   DRW_state_reset();
2432
2433   /* TODO: Reading depth for operators should be done here. */
2434
2435   GPU_framebuffer_restore();
2436 }
2437
2438 /**
2439  * object mode select-loop, see: ED_view3d_draw_depth_loop (legacy drawing).
2440  */
2441 void DRW_draw_depth_loop(struct Depsgraph *depsgraph,
2442                          ARegion *ar,
2443                          View3D *v3d,
2444                          GPUViewport *viewport)
2445 {
2446   Scene *scene = DEG_get_evaluated_scene(depsgraph);
2447   RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->shading.type);
2448   ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
2449   RegionView3D *rv3d = ar->regiondata;
2450
2451   DRW_opengl_context_enable();
2452
2453   /* Reset before using it. */
2454   drw_state_prepare_clean_for_draw(&DST);
2455
2456   DST.viewport = viewport;
2457   DST.options.is_depth = true;
2458
2459   /* Instead of 'DRW_context_state_init(C, &DST.draw_ctx)', assign from args */
2460   DST.draw_ctx = (DRWContextState){
2461       .ar = ar,
2462       .rv3d = rv3d,
2463       .v3d = v3d,
2464       .scene = scene,
2465       .view_layer = view_layer,
2466       .obact = OBACT(view_layer),
2467       .engine_type = engine_type,
2468       .depsgraph = depsgraph,
2469   };
2470
2471   /* Get list of enabled engines */
2472   {
2473     drw_engines_enable_basic();
2474     if (DRW_state_draw_support()) {
2475       drw_engines_enable_from_object_mode();
2476     }
2477   }
2478
2479   drw_draw_depth_loop_imp();
2480
2481   drw_engines_disable();
2482
2483 #ifdef DEBUG
2484   /* Avoid accidental reuse. */
2485   drw_state_ensure_not_reused(&DST);
2486 #endif
2487
2488   /* Changin context */
2489   DRW_opengl_context_disable();
2490 }
2491
2492 /**
2493  * Converted from ED_view3d_draw_depth_gpencil (legacy drawing).
2494  */
2495 void DRW_draw_depth_loop_gpencil(struct Depsgraph *depsgraph,
2496                                  ARegion *ar,
2497                                  View3D *v3d,
2498                                  GPUViewport *viewport)
2499 {
2500   Scene *scene = DEG_get_evaluated_scene(depsgraph);
2501   ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
2502   RegionView3D *rv3d = ar->regiondata;
2503
2504   DRW_opengl_context_enable();
2505
2506   /* Reset before using it. */
2507   drw_state_prepare_clean_for_draw(&DST);
2508
2509   DST.viewport = viewport;
2510   DST.options.is_depth = true;
2511
2512   /* Instead of 'DRW_context_state_init(C, &DST.draw_ctx)', assign from args */
2513   DST.draw_ctx = (DRWContextState){
2514       .ar = ar,
2515       .rv3d = rv3d,
2516       .v3d = v3d,
2517       .scene = scene,
2518       .view_layer = view_layer,
2519       .obact = OBACT(view_layer),
2520       .depsgraph = depsgraph,
2521   };
2522
2523   use_drw_engine(&draw_engine_gpencil_type);
2524   drw_draw_depth_loop_imp();
2525   drw_engines_disable();
2526
2527 #ifdef DEBUG
2528   /* Avoid accidental reuse. */
2529   drw_state_ensure_not_reused(&DST);
2530 #endif
2531
2532   /* Changin context */
2533   DRW_opengl_context_disable();
2534 }
2535
2536 /** See #DRW_shgroup_world_clip_planes_from_rv3d. */
2537 static void draw_world_clip_planes_from_rv3d(GPUBatch *batch, const float world_clip_planes[6][4])
2538 {
2539   GPU_batch_uniform_4fv_array(batch, "WorldClipPlanes", 6, world_clip_planes[0]);
2540 }
2541
2542 /**
2543  * Clears the Depth Buffer and draws only the specified object.
2544  */
2545 void DRW_draw_depth_object(ARegion *ar, GPUViewport *viewport, Object *object)
2546 {
2547   RegionView3D *rv3d = ar->regiondata;
2548
2549   DRW_opengl_context_enable();
2550
2551   /* Setup framebuffer */
2552   DefaultFramebufferList *fbl = GPU_viewport_framebuffer_list_get(viewport);
2553
2554   GPU_framebuffer_bind(fbl->depth_only_fb);
2555   GPU_framebuffer_clear_depth(fbl->depth_only_fb, 1.0f);
2556   GPU_depth_test(true);
2557   GPU_matrix_mul(object->obmat);
2558
2559   const float(*world_clip_planes)[4] = NULL;
2560   if (rv3d->rflag & RV3D_CLIPPING) {
2561     ED_view3d_clipping_set(rv3d);
2562     ED_view3d_clipping_local(rv3d, object->obmat);
2563     world_clip_planes = rv3d->clip_local;
2564   }
2565
2566   switch (object->type) {
2567     case OB_MESH: {
2568       GPUBatch *batch;
2569
2570       Mesh *me = object->data;
2571
2572       if (object->mode & OB_MODE_EDIT) {
2573         batch = DRW_mesh_batch_cache_get_edit_triangles(me);
2574       }
2575       else {
2576         batch = DRW_mesh_batch_cache_get_surface(me);
2577       }
2578
2579       DRW_mesh_batch_cache_create_requested(object, me, NULL, false, true);
2580
2581       const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
2582                                                           GPU_SHADER_CFG_DEFAULT;
2583       GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_DEPTH_ONLY, sh_cfg);
2584       if (world_clip_planes != NULL) {
2585         draw_world_clip_planes_from_rv3d(batch, world_clip_planes);
2586       }
2587
2588       GPU_batch_draw(batch);
2589     } break;
2590     case OB_CURVE:
2591     case OB_SURF:
2592       break;
2593   }
2594
2595   if (rv3d->rflag & RV3D_CLIPPING) {
2596     ED_view3d_clipping_disable();
2597   }
2598
2599   GPU_matrix_set(rv3d->viewmat);
2600   GPU_depth_test(false);
2601   GPU_framebuffer_restore();
2602   DRW_opengl_context_disable();
2603 }
2604
2605 static void draw_mesh_verts(GPUBatch *batch, uint offset, const float world_clip_planes[6][4])
2606 {
2607   GPU_point_size(UI_GetThemeValuef(TH_VERTEX_SIZE));
2608
2609   const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
2610                                                       GPU_SHADER_CFG_DEFAULT;
2611   GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg);
2612   GPU_batch_uniform_1ui(batch, "offset", offset);
2613   if (world_clip_planes != NULL) {
2614     draw_world_clip_planes_from_rv3d(batch, world_clip_planes);
2615   }
2616   GPU_batch_draw(batch);
2617 }
2618
2619 static void draw_mesh_edges(GPUBatch *batch, uint offset, const float world_clip_planes[6][4])
2620 {
2621   GPU_line_width(1.0f);
2622   glProvokingVertex(GL_FIRST_VERTEX_CONVENTION);
2623
2624   const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
2625                                                       GPU_SHADER_CFG_DEFAULT;
2626   GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg);
2627   GPU_batch_uniform_1ui(batch, "offset", offset);
2628   if (world_clip_planes != NULL) {
2629     draw_world_clip_planes_from_rv3d(batch, world_clip_planes);
2630   }
2631   GPU_batch_draw(batch);
2632
2633   glProvokingVertex(GL_LAST_VERTEX_CONVENTION);
2634 }
2635
2636 /* two options, facecolors or black */
2637 static void draw_mesh_face(GPUBatch *batch,
2638                            uint offset,
2639                            const bool use_select,
2640                            const float world_clip_planes[6][4])
2641 {
2642   if (use_select) {
2643     const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
2644                                                         GPU_SHADER_CFG_DEFAULT;
2645     GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg);
2646     GPU_batch_uniform_1ui(batch, "offset", offset);
2647     if (world_clip_planes != NULL) {
2648       draw_world_clip_planes_from_rv3d(batch, world_clip_planes);
2649     }
2650     GPU_batch_draw(batch);
2651   }
2652   else {
2653     const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
2654                                                         GPU_SHADER_CFG_DEFAULT;
2655     GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_UNIFORM_SELECT_ID, sh_cfg);
2656     GPU_batch_uniform_1ui(batch, "id", 0);
2657     if (world_clip_planes != NULL) {
2658       draw_world_clip_planes_from_rv3d(batch, world_clip_planes);
2659     }
2660     GPU_batch_draw(batch);
2661   }
2662 }
2663
2664 static void draw_mesh_face_dot(GPUBatch *batch, uint offset, const float world_clip_planes[6][4])
2665 {
2666   const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
2667                                                       GPU_SHADER_CFG_DEFAULT;
2668   GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg);
2669   GPU_batch_uniform_1ui(batch, "offset", offset);
2670   if (world_clip_planes != NULL) {
2671     draw_world_clip_planes_from_rv3d(batch, world_clip_planes);
2672   }
2673   GPU_batch_draw(batch);
2674 }
2675
2676 void DRW_draw_select_id_object(Scene *scene,
2677                                RegionView3D *rv3d,
2678                                Object *ob,
2679                                short select_mode,
2680                                bool draw_facedot,
2681                                uint initial_offset,
2682                                uint *r_vert_offset,
2683                                uint *r_edge_offset,
2684                                uint *r_face_offset)
2685 {
2686   ToolSettings *ts = scene->toolsettings;
2687   if (select_mode == -1) {
2688     select_mode = ts->selectmode;
2689   }
2690
2691   GPU_matrix_mul(ob->obmat);
2692
2693   const float(*world_clip_planes)[4] = NULL;
2694   if (rv3d->rflag & RV3D_CLIPPING) {
2695     ED_view3d_clipping_local(rv3d, ob->obmat);
2696     world_clip_planes = rv3d->clip_local;
2697   }
2698
2699   BLI_assert(initial_offset > 0);
2700
2701   switch (ob->type) {
2702     case OB_MESH:
2703       if (ob->mode & OB_MODE_EDIT) {
2704         Mesh *me = ob->data;
2705         BMEditMesh *em = me->edit_mesh;
2706         const bool use_faceselect = (select_mode & SCE_SELECT_FACE) != 0;
2707
2708         DRW_mesh_batch_cache_validate(me);
2709
2710         BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE | BM_FACE);
2711
2712         GPUBatch *geom_faces, *geom_edges, *geom_verts, *geom_facedots;
2713         geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me);
2714         if (select_mode & SCE_SELECT_EDGE) {
2715           geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(me);
2716         }
2717         if (select_mode & SCE_SELECT_VERTEX) {
2718           geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me);
2719         }
2720         if (use_faceselect && draw_facedot) {
2721           geom_facedots = DRW_mesh_batch_cache_get_facedots_with_select_id(me);
2722         }
2723         DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, true);
2724
2725         draw_mesh_face(geom_faces, initial_offset, use_faceselect, world_clip_planes);
2726
2727         if (use_faceselect && draw_facedot) {
2728           draw_mesh_face_dot(geom_facedots, initial_offset, world_clip_planes);
2729         }
2730
2731         if (select_mode & SCE_SELECT_FACE) {
2732           *r_face_offset = initial_offset + em->bm->totface;
2733         }
2734         else {
2735           *r_face_offset = initial_offset;
2736         }
2737
2738         ED_view3d_polygon_offset(rv3d, 1.0);
2739
2740         /* Unlike faces, only draw edges if edge select mode. */
2741         if (select_mode & SCE_SELECT_EDGE) {
2742           draw_mesh_edges(geom_edges, *r_face_offset, world_clip_planes);
2743           *r_edge_offset = *r_face_offset + em->bm->totedge;
2744         }
2745         else {
2746           /* Note that `r_vert_offset` is calculated from `r_edge_offset`.
2747            * Otherwise the first vertex is never selected, see: T53512. */
2748           *r_edge_offset = *r_face_offset;
2749         }
2750
2751         ED_view3d_polygon_offset(rv3d, 1.1);
2752
2753         /* Unlike faces, only verts if vert select mode. */
2754         if (select_mode & SCE_SELECT_VERTEX) {
2755           draw_mesh_verts(geom_verts, *r_edge_offset, world_clip_planes);
2756           *r_vert_offset = *r_edge_offset + em->bm->totvert;
2757         }
2758         else {
2759           *r_vert_offset = *r_edge_offset;
2760         }
2761
2762         ED_view3d_polygon_offset(rv3d, 0.0);
2763       }
2764       else {
2765         Mesh *me_orig = DEG_get_original_object(ob)->data;
2766         Mesh *me_eval = ob->data;
2767
2768         DRW_mesh_batch_cache_validate(me_eval);
2769         GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me_eval);
2770         if ((me_orig->editflag & ME_EDIT_PAINT_VERT_SEL) &&
2771             /* Currently vertex select supports weight paint and vertex paint. */
2772             ((ob->mode & OB_MODE_WEIGHT_PAINT) || (ob->mode & OB_MODE_VERTEX_PAINT))) {
2773
2774           GPUBatch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me_eval);
2775           DRW_mesh_batch_cache_create_requested(ob, me_eval, NULL, false, true);
2776
2777           /* Only draw faces to mask out verts, we don't want their selection ID's. */
2778           draw_mesh_face(geom_faces, 0, false, world_clip_planes);
2779           draw_mesh_verts(geom_verts, 1, world_clip_planes);
2780
2781           *r_face_offset = *r_edge_offset = initial_offset;
2782           *r_vert_offset = me_eval->totvert + 1;
2783         }
2784         else {
2785           const bool use_hide = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL);
2786           DRW_mesh_batch_cache_create_requested(ob, me_eval, NULL, false, use_hide);
2787
2788           draw_mesh_face(geom_faces, initial_offset, true, world_clip_planes);
2789
2790           *r_face_offset = initial_offset + me_eval->totpoly;
2791           *r_edge_offset = *r_vert_offset = *r_face_offset;
2792         }
2793       }
2794       break;
2795     case OB_CURVE:
2796     case OB_SURF:
2797       break;
2798   }
2799
2800   GPU_matrix_set(rv3d->viewmat);
2801 }
2802
2803 /* Set an opengl context to be used with shaders that draw on U32 colors. */
2804 void DRW_framebuffer_select_id_setup(ARegion *ar, const bool clear)
2805 {
2806   RegionView3D *rv3d = ar->regiondata;
2807
2808   DRW_opengl_context_enable();
2809
2810   /* Setup framebuffer */
2811   int viewport_size[2] = {ar->winx, ar->winy};
2812   draw_select_framebuffer_select_id_setup(viewport_size);
2813   GPU_framebuffer_bind(g_select_buffer.framebuffer_select_id);
2814
2815   /* dithering and AA break color coding, so disable */
2816   glDisable(GL_DITHER);
2817
2818   GPU_depth_test(true);
2819   GPU_disable_program_point_size();
2820
2821   if (clear) {
2822     GPU_framebuffer_clear_color_depth(
2823         g_select_buffer.framebuffer_select_id, (const float[4]){0.0f}, 1.0f);
2824   }
2825
2826   if (rv3d->rflag & RV3D_CLIPPING) {
2827     ED_view3d_clipping_set(rv3d);
2828   }
2829 }
2830
2831 /* Ends the context for selection and restoring the previous one. */
2832 void DRW_framebuffer_select_id_release(ARegion *ar)
2833 {
2834   RegionView3D *rv3d = ar->regiondata;
2835
2836   if (rv3d->rflag & RV3D_CLIPPING) {
2837     ED_view3d_clipping_disable();
2838   }
2839
2840   GPU_depth_test(false);
2841
2842   GPU_framebuffer_restore();
2843
2844   DRW_opengl_context_disable();
2845 }
2846
2847 /* Read a block of pixels from the select frame buffer. */
2848 void DRW_framebuffer_select_id_read(const rcti *rect, uint *r_buf)
2849 {
2850   /* clamp rect by texture */
2851   rcti r = {
2852       .xmin = 0,
2853       .xmax = GPU_texture_width(g_select_buffer.texture_u32),
2854       .ymin = 0,
2855       .ymax = GPU_texture_height(g_select_buffer.texture_u32),
2856   };
2857
2858   rcti rect_clamp = *rect;
2859   if (BLI_rcti_isect(&r, &rect_clamp, &rect_clamp)) {
2860     GPU_texture_read_rect(g_select_buffer.texture_u32, GPU_DATA_UNSIGNED_INT, &rect_clamp, r_buf);
2861
2862     if (!BLI_rcti_compare(rect, &rect_clamp)) {
2863       GPU_select_buffer_stride_realign(rect, &rect_clamp, r_buf);
2864     }
2865   }
2866   else {
2867     size_t buf_size = BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect) * sizeof(*r_buf);
2868
2869     memset(r_buf, 0, buf_size);
2870   }
2871 }
2872
2873 /** \} */
2874
2875 /* -------------------------------------------------------------------- */
2876 /** \name Draw Manager State (DRW_state)
2877  * \{ */
2878
2879 void DRW_state_dfdy_factors_get(float dfdyfac[2])
2880 {
2881   GPU_get_dfdy_factors(dfdyfac);
2882 }
2883
2884 /**
2885  * When false, drawing doesn't output to a pixel buffer
2886  * eg: Occlusion queries, or when we have setup a context to draw in already.
2887  */
2888 bool DRW_state_is_fbo(void)
2889 {
2890   return ((DST.default_framebuffer != NULL) || DST.options.is_image_render) &&
2891          !DRW_state_is_depth() && !DRW_state_is_select();
2892 }
2893
2894 /**
2895  * For when engines need to know if this is drawing for selection or not.
2896  */
2897 bool DRW_state_is_select(void)
2898 {
2899   return DST.options.is_select;
2900 }
2901
2902 bool DRW_state_is_depth(void)
2903 {
2904   return DST.options.is_depth;
2905 }
2906
2907 /**
2908  * Whether we are rendering for an image
2909  */
2910 bool DRW_state_is_image_render(void)
2911 {
2912   return DST.options.is_image_render;
2913 }
2914
2915 /**
2916  * Whether we are rendering only the render engine,
2917  * or if we should also render the mode engines.
2918  */
2919 bool DRW_state_is_scene_render(void)
2920 {
2921   BLI_assert(DST.options.is_scene_render ? DST.options.is_image_render : true);
2922   return DST.options.is_scene_render;
2923 }
2924
2925 /**
2926  * Whether we are rendering simple opengl render
2927  */
2928 bool DRW_state_is_opengl_render(void)
2929 {
2930   return DST.options.is_image_render && !DST.options.is_scene_render;
2931 }
2932
2933 bool DRW_state_is_playback(void)
2934 {
2935   if (DST.draw_ctx.evil_C != NULL) {
2936     struct wmWindowManager *wm = CTX_wm_manager(DST.draw_ctx.evil_C);
2937     return ED_screen_animation_playing(wm) != NULL;
2938   }
2939   return false;
2940 }
2941
2942 /**
2943  * Should text draw in this mode?
2944  */
2945 bool DRW_state_show_text(void)
2946 {
2947   return (DST.options.is_select) == 0 && (DST.options.is_depth) == 0 &&
2948          (DST.options.is_scene_render) == 0 && (DST.options.draw_text) == 0;
2949 }
2950
2951 /**
2952  * Should draw support elements
2953  * Objects center, selection outline, probe data, ...
2954  */
2955 bool DRW_state_draw_support(void)
2956 {
2957   View3D *v3d = DST.draw_ctx.v3d;
2958   return (DRW_state_is_scene_render() == false) && (v3d != NULL) &&
2959          ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0);
2960 }
2961
2962 /**
2963  * Whether we should render the background
2964  */
2965 bool DRW_state_draw_background(void)
2966 {
2967   return DST.options.draw_background;
2968 }
2969
2970 /** \} */
2971
2972 /* -------------------------------------------------------------------- */
2973 /** \name Context State (DRW_context_state)
2974  * \{ */
2975
2976 const DRWContextState *DRW_context_state_get(void)
2977 {
2978   return &DST.draw_ctx;
2979 }
2980
2981 /** \} */
2982
2983 /* -------------------------------------------------------------------- */
2984 /** \name Init/Exit (DRW_engines)
2985  * \{ */
2986
2987 bool DRW_engine_render_support(DrawEngineType *draw_engine_type)
2988 {
2989   return draw_engine_type->render_to_image;
2990 }
2991
2992 void DRW_engine_register(DrawEngineType *draw_engine_type)
2993 {
2994   BLI_addtail(&DRW_engines, draw_engine_type);
2995 }
2996
2997 void DRW_engines_register(void)
2998 {
2999   RE_engines_register(&DRW_engine_viewport_eevee_type);
3000   RE_engines_register(&DRW_engine_viewport_workbench_type);
3001
3002   DRW_engine_register(&draw_engine_workbench_solid);
3003   DRW_engine_register(&draw_engine_workbench_transparent);
3004
3005   DRW_engine_register(&draw_engine_object_type);
3006   DRW_engine_register(&draw_engine_edit_armature_type);
3007   DRW_engine_register(&draw_engine_edit_curve_type);
3008   DRW_engine_register(&draw_engine_edit_lattice_type);
3009   DRW_engine_register(&draw_engine_edit_mesh_type);
3010   DRW_engine_register(&draw_engine_edit_metaball_type);
3011   DRW_engine_register(&draw_engine_edit_text_type);
3012   DRW_engine_register(&draw_engine_motion_path_type);
3013   DRW_engine_register(&draw_engine_overlay_type);
3014   DRW_engine_register(&draw_engine_paint_texture_type);
3015   DRW_engine_register(&draw_engine_paint_vertex_type);
3016   DRW_engine_register(&draw_engine_particle_type);
3017   DRW_engine_register(&draw_engine_pose_type);
3018   DRW_engine_register(&draw_engine_sculpt_type);
3019   DRW_engine_register(&draw_engine_gpencil_type);
3020
3021   /* setup callbacks */
3022   {
3023     BKE_mball_batch_cache_dirty_tag_cb = DRW_mball_batch_cache_dirty_tag;
3024     BKE_mball_batch_cache_free_cb = DRW_mball_batch_cache_free;
3025
3026     BKE_curve_batch_cache_dirty_tag_cb = DRW_curve_batch_cache_dirty_tag;
3027     BKE_curve_batch_cache_free_cb = DRW_curve_batch_cache_free;
3028
3029     BKE_mesh_batch_cache_dirty_tag_cb = DRW_mesh_batch_cache_dirty_tag;
3030     BKE_mesh_batch_cache_free_cb = DRW_mesh_batch_cache_free;
3031
3032     BKE_lattice_batch_cache_dirty_tag_cb = DRW_lattice_batch_cache_dirty_tag;
3033     BKE_lattice_batch_cache_free_cb = DRW_lattice_batch_cache_free;
3034
3035     BKE_particle_batch_cache_dirty_tag_cb = DRW_particle_batch_cache_dirty_tag;
3036     BKE_particle_batch_cache_free_cb = DRW_particle_batch_cache_free;
3037
3038     BKE_gpencil_batch_cache_dirty_tag_cb = DRW_gpencil_batch_cache_dirty_tag;
3039     BKE_gpencil_batch_cache_free_cb = DRW_gpencil_batch_cache_free;
3040   }
3041 }
3042
3043 void DRW_engines_free(void)
3044 {
3045   if (DST.gl_context == NULL) {
3046     /* Nothing has been setup. Nothing to clear.
3047      * Otherwise, DRW_opengl_context_enable can
3048      * create a context in background mode. (see T62355) */
3049     return;
3050   }
3051
3052   DRW_opengl_context_enable();
3053
3054   DRW_TEXTURE_FREE_SAFE(g_select_buffer.texture_u32);
3055   DRW_TEXTURE_FREE_SAFE(g_select_buffer.texture_depth);
3056   GPU_FRAMEBUFFER_FREE_SAFE(g_select_buffer.framebuffer_select_id);
3057   GPU_FRAMEBUFFER_FREE_SAFE(g_select_buffer.framebuffer_depth_only);
3058
3059   DRW_hair_free();
3060   DRW_shape_cache_free();
3061   DRW_stats_free();
3062   DRW_globals_free();
3063
3064   DrawEngineType *next;
3065   for (DrawEngineType *type = DRW_engines.first; type; type = next) {
3066     next = type->next;
3067     BLI_remlink(&R_engines, type);
3068
3069     if (type->engine_free) {
3070       type->engine_free();
3071     }
3072   }
3073
3074   DRW_UBO_FREE_SAFE(G_draw.block_ubo);
3075   DRW_UBO_FREE_SAFE(G_draw.view_ubo);
3076   DRW_TEXTURE_FREE_SAFE(G_draw.ramp);
3077   DRW_TEXTURE_FREE_SAFE(G_draw.weight_ramp);
3078
3079   MEM_SAFE_FREE(DST.uniform_names.buffer);
3080
3081   DRW_opengl_context_disable();
3082 }
3083
3084 /** \} */
3085
3086 /** \name Init/Exit (DRW_opengl_ctx)
3087  * \{ */
3088
3089 void DRW_opengl_context_create(void)
3090 {
3091   BLI_assert(DST.gl_context == NULL); /* Ensure it's called once */
3092
3093   DST.gl_context_mutex = BLI_ticket_mutex_alloc();
3094   if (!G.background) {
3095     immDeactivate();
3096   }
3097   /* This changes the active context. */
3098   DST.gl_context = WM_opengl_context_create();
3099   WM_opengl_context_activate(DST.gl_context);
3100   /* Be sure to create gawain.context too. */
3101   DST.gpu_context = GPU_context_create();
3102   if (!G.background) {
3103     immActivate();
3104   }
3105   /* Set default Blender OpenGL state */
3106   GPU_state_init();
3107   /* So we activate the window's one afterwards. */
3108   wm_window_reset_drawable();
3109 }
3110
3111 void DRW_opengl_context_destroy(void)
3112 {
3113   BLI_assert(BLI_thread_is_main());
3114   if (DST.gl_context != NULL) {
3115     WM_opengl_context_activate(DST.gl_context);
3116     GPU_context_active_set(DST.gpu_context);
3117     GPU_context_discard(DST.gpu_context);
3118     WM_opengl_context_dispose(DST.gl_context);
3119     BLI_ticket_mutex_free(DST.gl_context_mutex);
3120   }
3121 }
3122
3123 void DRW_opengl_context_enable_ex(bool restore)
3124 {
3125   if (DST.gl_context != NULL) {
3126     /* IMPORTANT: We dont support immediate mode in render mode!
3127      * This shall remain in effect until immediate mode supports
3128      * multiple threads. */
3129     BLI_ticket_mutex_lock(DST.gl_context_mutex);
3130     if (BLI_thread_is_main() && restore) {
3131       if (!G.background) {
3132         immDeactivate();
3133       }
3134     }
3135     WM_opengl_context_activate(DST.gl_context);
3136     GPU_context_active_set(DST.gpu_context);
3137     if (BLI_thread_is_main() && restore) {
3138       if (!G.background) {
3139         immActivate();
3140       }
3141       BLF_batch_reset();
3142     }
3143   }
3144 }
3145
3146 void DRW_opengl_context_disable_ex(bool restore)
3147 {
3148   if (DST.gl_context != NULL) {
3149 #ifdef __APPLE__
3150     /* Need to flush before disabling draw context, otherwise it does not
3151      * always finish drawing and viewport can be empty or partially drawn */
3152     GPU_flush();
3153 #endif
3154
3155     if (BLI_thread_is_main() && restore) {
3156       wm_window_reset_drawable();
3157     }
3158     else {
3159       WM_opengl_context_release(DST.gl_context);
3160       GPU_context_active_set(NULL);
3161     }
3162
3163     BLI_ticket_mutex_unlock(DST.gl_context_mutex);
3164   }
3165 }
3166
3167 void DRW_opengl_context_enable(void)
3168 {
3169   if (G.background && DST.gl_context == NULL) {
3170     WM_init_opengl(G_MAIN);
3171   }
3172   DRW_opengl_context_enable_ex(true);
3173 }
3174
3175 void DRW_opengl_context_disable(void)
3176 {
3177   DRW_opengl_context_disable_ex(true);
3178 }
3179
3180 void DRW_opengl_render_context_enable(void *re_gl_context)
3181 {
3182   /* If thread is main you should use DRW_opengl_context_enable(). */
3183   BLI_assert(!BLI_thread_is_main());
3184
3185   /* TODO get rid of the blocking. Only here because of the static global DST. */
3186   BLI_ticket_mutex_lock(DST.gl_context_mutex);
3187   WM_opengl_context_activate(re_gl_context);
3188 }
3189
3190 void DRW_opengl_render_context_disable(void *re_gl_context)
3191 {
3192   GPU_flush();
3193   WM_opengl_context_release(re_gl_context);
3194   /* TODO get rid of the blocking. */
3195   BLI_ticket_mutex_unlock(DST.gl_context_mutex);
3196 }
3197
3198 /* Needs to be called AFTER DRW_opengl_render_context_enable() */
3199 void DRW_gawain_render_context_enable(void *re_gpu_context)
3200 {
3201   /* If thread is main you should use DRW_opengl_context_enable(). */
3202   BLI_assert(!BLI_thread_is_main());
3203
3204   GPU_context_active_set(re_gpu_context);
3205   DRW_shape_cache_reset(); /* XXX fix that too. */
3206 }
3207
3208 /* Needs to be called BEFORE DRW_opengl_render_context_disable() */
3209 void DRW_gawain_render_context_disable(void *UNUSED(re_gpu_context))
3210 {
3211   DRW_shape_cache_reset(); /* XXX fix that too. */
3212   GPU_context_active_set(NULL);
3213 }
3214
3215 /** \} */