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