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 = ®ion->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, ®ion_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