Blender V5.0
draw_context.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2016 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <cstdio>
10
11#include "CLG_log.h"
12
13#include "BLI_function_ref.hh"
14#include "BLI_listbase.h"
15#include "BLI_map.hh"
16#include "BLI_math_matrix.h"
18#include "BLI_math_vector.h"
19#include "BLI_rect.h"
20#include "BLI_string.h"
21#include "BLI_sys_types.h"
22#include "BLI_task.h"
23#include "BLI_threads.h"
24#include "BLI_utildefines.h"
25
26#include "BLF_api.hh"
27
28#include "BLT_translation.hh"
29
30#include "BKE_context.hh"
31#include "BKE_curve.hh"
32#include "BKE_curves.h"
33#include "BKE_duplilist.hh"
34#include "BKE_editmesh.hh"
35#include "BKE_global.hh"
36#include "BKE_grease_pencil.h"
37#include "BKE_idprop.hh"
38#include "BKE_lattice.hh"
39#include "BKE_layer.hh"
40#include "BKE_main.hh"
41#include "BKE_mball.hh"
42#include "BKE_mesh.hh"
43#include "BKE_mesh_wrapper.hh"
44#include "BKE_modifier.hh"
45#include "BKE_object.hh"
46#include "BKE_object_types.hh"
47#include "BKE_paint.hh"
48#include "BKE_particle.h"
49#include "BKE_pointcache.h"
50#include "BKE_pointcloud.hh"
51#include "BKE_scene.hh"
52#include "BKE_screen.hh"
54#include "BKE_volume.hh"
55
56#include "DNA_camera_types.h"
57#include "DNA_mesh_types.h"
58#include "DNA_userdef_types.h"
59#include "DNA_view3d_types.h"
60#include "DNA_world_types.h"
61
62#include "ED_gpencil_legacy.hh"
63#include "ED_screen.hh"
64#include "ED_space_api.hh"
65#include "ED_view3d.hh"
66
67#include "GPU_capabilities.hh"
68#include "GPU_framebuffer.hh"
69#include "GPU_matrix.hh"
70#include "GPU_platform.hh"
71#include "GPU_shader_shared.hh"
72#include "GPU_state.hh"
73#include "GPU_uniform_buffer.hh"
74#include "GPU_viewport.hh"
75
76#include "UI_resources.hh"
77#include "UI_view2d.hh"
78
79#include "WM_api.hh"
80
81#include "DRW_render.hh"
82#include "draw_cache.hh"
84#include "draw_common_c.hh"
86#include "draw_handle.hh"
87#include "draw_manager_text.hh"
88#include "draw_shader.hh"
89#include "draw_subdivision.hh"
90#include "draw_view_c.hh"
91#include "draw_view_data.hh"
92
93/* only for callbacks */
94#include "draw_cache_impl.hh"
95
104
105#include "GPU_context.hh"
106
107#include "DEG_depsgraph.hh"
108#include "DEG_depsgraph_query.hh"
109
110#include "BLI_time.h"
111
112#include "DRW_select_buffer.hh"
113
114thread_local DRWContext *DRWContext::g_context = nullptr;
115
116DRWContext::DRWContext(Mode mode_,
117 Depsgraph *depsgraph,
118 const int2 size,
119 const bContext *C,
120 ARegion *region,
121 View3D *v3d)
122 : mode(mode_)
123{
124 BLI_assert(size.x > 0 && size.y > 0);
125
126 this->size = float2(size);
127 this->inv_size = 1.0f / this->size;
128
129 this->depsgraph = depsgraph;
130 this->scene = DEG_get_evaluated_scene(depsgraph);
131 this->view_layer = DEG_get_evaluated_view_layer(depsgraph);
132
133 this->evil_C = C;
134
135 this->region = (region) ? region : ((C) ? CTX_wm_region(C) : nullptr);
136 this->space_data = (C) ? CTX_wm_space_data(C) : nullptr;
137 this->v3d = (v3d) ? v3d : ((C) ? CTX_wm_view3d(C) : nullptr);
138 if (this->v3d != nullptr && this->region != nullptr) {
139 this->rv3d = static_cast<RegionView3D *>(this->region->regiondata);
140 }
141 /* Active object. Set to nullptr for render (when region is nullptr). */
142 this->obact = (this->region) ? BKE_view_layer_active_object_get(this->view_layer) : nullptr;
143 /* Object mode. */
144 this->object_mode = (this->obact) ? eObjectMode(this->obact->mode) : OB_MODE_OBJECT;
145 /* Edit object. */
146 this->object_edit = (this->object_mode & OB_MODE_EDIT) ? this->obact : nullptr;
147 /* Pose object. */
148 if (this->object_mode & OB_MODE_POSE) {
149 this->object_pose = this->obact;
150 }
151 else if (this->object_mode & OB_MODE_ALL_WEIGHT_PAINT) {
152 this->object_pose = BKE_object_pose_armature_get(this->obact);
153 }
154 else {
155 this->object_pose = nullptr;
156 }
157
158 /* View layer can be lazily synced. */
159 BKE_view_layer_synced_ensure(this->scene, this->view_layer);
160
161 /* fclem: Is this still needed ? */
162 if (this->object_edit && rv3d) {
163 ED_view3d_init_mats_rv3d(this->object_edit, rv3d);
164 }
165
166 BLI_assert(g_context == nullptr);
167 g_context = this;
168}
169
188
190{
191 BLI_assert(g_context == this);
192 g_context = nullptr;
193}
194
199
204
209
211{
212 DRWContext &draw_ctx = drw_get();
213 SpaceLink *space_data = draw_ctx.space_data;
214 View3D *v3d = draw_ctx.v3d;
215
216 if (space_data != nullptr) {
217 switch (space_data->spacetype) {
218 case SPACE_IMAGE: {
219 SpaceImage *sima = (SpaceImage *)space_data;
220 return (sima->flag & SI_SHOW_GPENCIL) != 0;
221 }
222 case SPACE_NODE:
223 /* Don't draw the annotation for the node editor. Annotations are handled by space_image as
224 * the draw manager is only used to draw the background. */
225 return false;
226 default:
227 break;
228 }
229 }
230 return (v3d && ((v3d->flag2 & V3D_SHOW_ANNOTATION) != 0) &&
231 ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0));
232}
233
234/* -------------------------------------------------------------------- */
237
239 public:
241
242 private:
243 /* WORKAROUND: BLI_gset_free is not allowing to pass a data pointer to the free function. */
244 static thread_local TaskGraph *task_graph_ptr_;
245
246 public:
248 {
249 BLI_assert_msg(graph == nullptr, "Missing call to work_and_wait");
250 }
251
252 /* `delayed_extraction` is a set of object to add to the graph before running.
253 * The non-null, the set is consumed and freed after use. */
254 void work_and_wait(GSet *&delayed_extraction)
255 {
256 BLI_assert_msg(graph, "Trying to submit more than once");
257
258 if (delayed_extraction) {
259 task_graph_ptr_ = graph;
260 BLI_gset_free(delayed_extraction, delayed_extraction_free_callback);
261 task_graph_ptr_ = nullptr;
262 delayed_extraction = nullptr;
263 }
264
267 graph = nullptr;
268 }
269
270 private:
271 static void delayed_extraction_free_callback(void *object)
272 {
274 reinterpret_cast<Object *>(object), *task_graph_ptr_);
275 }
276};
277
278thread_local TaskGraph *ExtractionGraph::task_graph_ptr_ = nullptr;
279
281
282/* -------------------------------------------------------------------- */
285
287{
289
290 if (ob->type == OB_MESH) {
291 DRWContext &draw_ctx = drw_get();
292 /* The evaluated object might be a mesh even though the original object has a different type.
293 * Also make sure the original object is a mesh (see #140762). */
294 if (draw_ctx.object_edit && draw_ctx.object_edit->type != OB_MESH) {
295 /* Noop. */
296 }
297 else if ((ob == draw_ctx.object_edit) || ob->mode == OB_MODE_EDIT) {
298 View3D *v3d = draw_ctx.v3d;
299 if (v3d && ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) && RETOPOLOGY_ENABLED(v3d)) {
300 return false;
301 }
302 }
303 }
304
305 return true;
306}
307
309{
311 if (ELEM(ob->type, OB_MESH, OB_CURVES)) {
312 if ((ob->mode & OB_MODE_EDIT) == 0) {
313 return false;
314 }
315 }
316 return true;
317 }
318 return false;
319}
320
327
329{
330 if (ob->type == OB_MESH) {
331 switch (ob->mode) {
332 case OB_MODE_SCULPT:
336 return true;
337 }
338 }
339
340 return false;
341}
342
344{
345 const bool for_render = DRW_context_get()->is_image_render();
346 /* NOTE: psys_check_enabled is using object and particle system for only
347 * reading, but is using some other functions which are more generic and
348 * which are hard to make const-pointer. */
349 if (!psys_check_enabled((Object *)object, (ParticleSystem *)psys, for_render)) {
350 return false;
351 }
352 const DRWContext *draw_ctx = DRW_context_get();
353 const Scene *scene = draw_ctx->scene;
354 if (object == draw_ctx->object_edit) {
355 return false;
356 }
357 const ParticleSettings *part = psys->part;
358 const ParticleEditSettings *pset = &scene->toolsettings->particle;
359 if (object->mode == OB_MODE_PARTICLE_EDIT) {
360 if (psys_in_edit_mode(draw_ctx->depsgraph, psys)) {
361 if ((pset->flag & PE_DRAW_PART) == 0) {
362 return false;
363 }
364 if ((part->childtype == 0) &&
365 (psys->flag & PSYS_HAIR_DYNAMICS && psys->pointcache->flag & PTCACHE_BAKED) == 0)
366 {
367 return false;
368 }
369 }
370 }
371 return true;
372}
373
375{
376 /* Same as DRW_object_get_data_for_drawing, but for the cage mesh. */
377 BLI_assert(object.type == OB_MESH);
378 const Mesh *cage_mesh = BKE_object_get_editmesh_eval_cage(&object);
379 if (cage_mesh == nullptr) {
380 return nullptr;
381 }
382
384 return cage_mesh;
385 }
386 return BKE_mesh_wrapper_ensure_subdivision(cage_mesh);
387}
388
390
391/* -------------------------------------------------------------------- */
394
396{
397 DRWData *drw_data = MEM_callocN<DRWData>("DRWData");
398
399 drw_data->default_view = new blender::draw::View("DrawDefaultView");
400
401 for (int i = 0; i < 2; i++) {
402 drw_data->view_data[i] = new DRWViewData();
403 }
404 return drw_data;
405}
406
408{
409 using namespace blender::draw;
411 DRW_curves_init(this);
412 DRW_volume_init(this);
413}
414
416{
417 using namespace blender::draw;
420}
421
423{
424 DRW_smoke_exit(this);
425}
426
428{
429 for (int i = 0; i < 2; i++) {
430 delete drw_data->view_data[i];
431 }
435 delete drw_data->default_view;
436 MEM_freeN(drw_data);
437}
438
440{
441 DRWData **data_p = GPU_viewport_data_get(viewport);
442 DRWData *data = *data_p;
443
444 if (data == nullptr) {
445 *data_p = data = DRW_viewport_data_create();
446 }
447 return data;
448}
449
451{
453
455
456 {
457 /* Acquire DRWData. */
458 if (!this->viewport && this->data) {
459 /* Manager was init first without a viewport, created DRWData, but is being re-init.
460 * In this case, keep the old data. */
461 }
462 else if (this->viewport) {
463 /* Use viewport's persistent DRWData. */
465 }
466 else {
467 /* Create temporary DRWData. Freed in drw_manager_exit(). */
469 }
470 int view = (this->viewport) ? GPU_viewport_active_view_get(this->viewport) : 0;
471 this->view_data_active = this->data->view_data[view];
472
473 this->view_data_active->texture_list_size_validate(int2(this->size));
474
475 if (this->viewport) {
477 }
478 }
479 {
480 /* Create the default view. */
481 if (this->rv3d != nullptr) {
483 float4x4(this->rv3d->winmat));
484 }
485 else if (this->region) {
486 /* Assume that if rv3d is nullptr, we are drawing for a 2D area. */
487 View2D *v2d = &this->region->v2d;
488 rctf region_space = {0.0f, 1.0f, 0.0f, 1.0f};
489
490 float4x4 viewmat;
491 BLI_rctf_transform_calc_m4_pivot_min(&v2d->cur, &region_space, viewmat.ptr());
492
493 float4x4 winmat = float4x4::identity();
494 winmat[0][0] = winmat[1][1] = 2.0f;
495 winmat[3][0] = winmat[3][1] = -1.0f;
496
497 blender::draw::View::default_set(viewmat, winmat);
498 }
499 else {
500 /* Assume that this is the render mode or custom mode and
501 * that the default view will be set appropriately or not used. */
503 }
504 }
505
506 /* Init modules ahead of time because the begin_sync happens before DRW_render_object_iter. */
507 this->data->modules_init();
508}
509
511{
513
514 this->data->modules_exit();
515
516 /* Reset drawing state to avoid to side-effects. */
518
520
521 if (this->data != nullptr && this->viewport == nullptr) {
523 }
524 this->data = nullptr;
525 this->viewport = nullptr;
526}
527
529{
531 pass_name, [&]() { return std::make_unique<blender::draw::TextureFromPool>(pass_name); });
532}
533
535{
536 if (drw_get().viewport) {
538 }
539}
540
542
543/* -------------------------------------------------------------------- */
546
547/* The Dupli systems generate a lot of transient objects that share the batch caches.
548 * So we ensure to only clear and generate the cache once per source instance type using this
549 * set. */
550/* TODO(fclem): This should be reconsidered as this has some unneeded overhead and complexity.
551 * Maybe it isn't needed at all. */
553 private:
554 /* Key identifying a single instance source. */
555 struct DupliKey {
556 Object *ob = nullptr;
557 ID *ob_data = nullptr;
558
559 DupliKey() = default;
560 DupliKey(const DupliObject *ob_dupli) : ob(ob_dupli->ob), ob_data(ob_dupli->ob_data) {}
561
562 uint64_t hash() const
563 {
564 return blender::get_default_hash(this->ob, this->ob_data);
565 }
566
567 friend bool operator==(const DupliKey &a, const DupliKey &b)
568 {
569 return a.ob == b.ob && a.ob_data == b.ob_data;
570 }
571 };
572
573 /* Last key used. Allows to avoid the overhead of polling the `dupli_set` for each instance.
574 * This helps when a Dupli system generates a lot of similar geometry consecutively. */
575 DupliKey last_key_ = {};
576
577 /* Set containing all visited Dupli source object. */
578 blender::Set<DupliKey> *dupli_set_ = nullptr;
579
580 public:
581 void try_add(blender::draw::ObjectRef &ob_ref);
582 void extract_all(ExtractionGraph &extraction);
583};
584
586{
587 if (ob_ref.is_dupli() == false) {
588 return;
589 }
590 if (last_key_ == ob_ref.dupli_object_) {
591 /* Same data as previous iteration. No need to perform the check again. */
592 return;
593 }
594
595 last_key_ = ob_ref.dupli_object_;
596
597 if (dupli_set_ == nullptr) {
598 dupli_set_ = MEM_new<blender::Set<DupliKey>>("DupliCacheManager::dupli_set_");
599 }
600
601 if (dupli_set_->add(last_key_)) {
602 /* Key is newly added. It is the first time we sync this object. */
603 /* TODO: Meh a bit out of place but this is nice as it is
604 * only done once per instance type. */
605 /* Note that this can happen for geometry data whose type is different from the original
606 * object (e.g. Text evaluated as Mesh, Geometry node instance etc...).
607 * In this case, key.ob is not going to have the same data type as ob_ref.object nor the same
608 * data at all. */
610 }
611}
612
614{
615 /* Reset for next iter. */
616 last_key_ = {};
617
618 if (dupli_set_ == nullptr) {
619 return;
620 }
621
622 /* Note these can referenced by the temporary object pointer `Object *ob` and needs to have at
623 * least the same lifetime. */
624 blender::bke::ObjectRuntime tmp_runtime;
625 Object tmp_object;
626
628 Iter begin = dupli_set_->begin();
629 Iter end = dupli_set_->end();
630 for (Iter iter = begin; iter != end; ++iter) {
631 const DupliKey &key = *iter;
632 Object *ob = iter->ob;
633
634 if (key.ob_data != ob->data) {
635 /* Copy both object data and runtime. */
636 tmp_runtime = *ob->runtime;
637 tmp_object = blender::dna::shallow_copy(*ob);
638 tmp_object.runtime = &tmp_runtime;
639 /* Geometry instances shouldn't be rendered with edit mode overlays. */
640 tmp_object.mode = OB_MODE_OBJECT;
641 /* Do not modify the original bound-box. */
642 BKE_object_replace_data_on_shallow_copy(&tmp_object, key.ob_data);
643
644 ob = &tmp_object;
645 }
646
648 }
649
650 /* TODO(fclem): Could eventually keep the set allocated. */
651 MEM_SAFE_DELETE(dupli_set_);
652}
653
655
656/* -------------------------------------------------------------------- */
659
660namespace blender::draw {
661
662ObjectRef::ObjectRef(Object *ob, Object *dupli_parent, DupliObject *dupli_object)
663 : dupli_object_(dupli_object), dupli_parent_(dupli_parent), object(ob)
664{
665}
666
668 : dupli_object_(duplis[0]), dupli_parent_(dupli_parent), duplis_(&duplis), object(&ob)
669{
670}
671
672} // namespace blender::draw
673
675
676/* -------------------------------------------------------------------- */
679
680namespace blender::draw {
681
682static bool supports_handle_ranges(DupliObject *dupli, Object *parent)
683{
684 int ob_type = dupli->ob_data ? BKE_object_obdata_to_type(dupli->ob_data) : OB_EMPTY;
686 {
687 return false;
688 }
689
690 Object *ob = dupli->ob;
691 if (min(ob->dt, parent->dt) == OB_BOUNDBOX) {
692 return false;
693 }
694
695 if (ob_type == OB_MESH) {
696 /* Hair drawing doesn't support handle ranges. */
698 const int draw_as = (psys->part->draw_as == PART_DRAW_REND) ? psys->part->ren_as :
699 psys->part->draw_as;
701 return false;
702 }
703 }
704 /* Smoke drawing doesn't support handle ranges. */
706 }
707
708 if (ob_type == OB_GREASE_PENCIL) {
709 GreasePencil *grease_pencil = reinterpret_cast<GreasePencil *>(dupli->ob_data);
710 return grease_pencil->flag & GREASE_PENCIL_STROKE_ORDER_3D;
711 }
712
713 return true;
714}
715
716enum class InstancesFlags : uint8_t {
718};
720
723
729
747
749 {
750 return hash_value;
751 }
752
753 bool operator==(const InstancesKey &k) const
754 {
755 if (hash_value != k.hash_value) {
756 return false;
757 }
758 if (object != k.object) {
759 return false;
760 }
761 if (ob_data != k.ob_data) {
762 return false;
763 }
764 if (flags != k.flags) {
765 return false;
766 }
768 return false;
769 }
771 return false;
772 }
773 return true;
774 }
775};
776
777static void foreach_obref_in_scene(DRWContext &draw_ctx,
778 FunctionRef<bool(Object &)> should_draw_object_cb,
779 FunctionRef<void(ObjectRef &)> draw_object_cb)
780{
781 DupliList duplilist;
783
784 Object tmp_object;
785 ObjectRuntimeHandle tmp_runtime;
786
787 Depsgraph *depsgraph = draw_ctx.depsgraph;
789 View3D *v3d = draw_ctx.v3d;
790
791 /* EEVEE is not supported for now. */
792 const bool engines_support_handle_ranges = (v3d && v3d->shading.type <= OB_SOLID) ||
794
795 DEGObjectIterSettings deg_iter_settings = {nullptr};
796 deg_iter_settings.depsgraph = depsgraph;
797 deg_iter_settings.flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY |
799 if (v3d && v3d->flag2 & V3D_SHOW_VIEWER) {
800 deg_iter_settings.viewer_path = &v3d->viewer_path;
801 }
802
803 DEG_OBJECT_ITER_BEGIN (&deg_iter_settings, ob) {
804
805 if (!DEG_iterator_object_is_visible(eval_mode, ob)) {
806 continue;
807 }
808
809 int visibility = BKE_object_visibility(ob, eval_mode);
810 bool ob_visible = visibility & (OB_VISIBLE_SELF | OB_VISIBLE_PARTICLES);
811
812 if (ob_visible && should_draw_object_cb(*ob)) {
813 /* NOTE: object_duplilist_preview is still handled by DEG_OBJECT_ITER,
814 * dupli_parent and dupli_object_current won't be null for these. */
815 ObjectRef ob_ref(ob, data_.dupli_parent, data_.dupli_object_current);
816 draw_object_cb(ob_ref);
817 }
818
819 bool is_preview_dupli = data_.dupli_parent && data_.dupli_object_current;
820 if (is_preview_dupli) {
821 /* Don't create duplis from temporary preview objects, object_duplilist_preview already takes
822 * care of everything. (See #146194, #146211) */
823 continue;
824 }
825
826 bool instances_visible = (visibility & OB_VISIBLE_INSTANCES) &&
827 ((ob->transflag & OB_DUPLI) ||
828 ob->runtime->geometry_set_eval != nullptr);
829
830 if (!instances_visible) {
831 continue;
832 }
833
834 duplilist.clear();
836 draw_ctx.depsgraph, draw_ctx.scene, ob, deg_iter_settings.included_objects, duplilist);
837
838 if (duplilist.is_empty()) {
839 continue;
840 }
841
842 dupli_map.clear();
843 for (DupliObject &dupli : duplilist) {
844
845 if (!DEG_iterator_dupli_is_visible(&dupli, eval_mode)) {
846 continue;
847 }
848
849 /* TODO: Optimize.
850 * We can't check the dupli.ob since visibility may be different than the dupli itself.
851 * But we should be able to check the dupli visibility without creating a temp object. */
852#if 0
853 if (!should_draw_object_cb(*dupli.ob)) {
854 continue;
855 }
856#endif
857
858 if (!engines_support_handle_ranges || !supports_handle_ranges(&dupli, ob)) {
859 /* Sync the dupli as a single object. */
861 ob, &dupli, eval_mode, false, &tmp_object, &tmp_runtime) ||
862 !should_draw_object_cb(tmp_object))
863 {
865 continue;
866 }
867
868 tmp_object.light_linking = ob->light_linking;
870 tmp_object.runtime->object_to_world = float4x4(dupli.mat);
871 tmp_object.runtime->world_to_object = invert(tmp_object.runtime->object_to_world);
872
873 blender::draw::ObjectRef ob_ref(&tmp_object, ob, &dupli);
874 draw_object_cb(ob_ref);
875
877 continue;
878 }
879
881 {
883 }
884 InstancesKey key(dupli.ob,
885 dupli.ob_data,
886 flags,
887 dupli.preview_base_geometry,
888 dupli.preview_instance_index);
889
890 dupli_map.lookup_or_add_default(key).append(&dupli);
891 }
892
893 for (const auto &[key, instances] : dupli_map.items()) {
894 DupliObject *first_dupli = instances.first();
896 ob, first_dupli, eval_mode, false, &tmp_object, &tmp_runtime) ||
897 !should_draw_object_cb(tmp_object))
898 {
899 evil::DEG_iterator_temp_object_free_properties(first_dupli, &tmp_object);
900 continue;
901 }
902
903 tmp_object.light_linking = ob->light_linking;
905 tmp_object.transflag, bool(key.flags & InstancesFlags::IsNegativeScale), OB_NEG_SCALE);
906 /* Should use DrawInstances data instead. */
907 tmp_object.runtime->object_to_world = float4x4();
908 tmp_object.runtime->world_to_object = float4x4();
909
910 blender::draw::ObjectRef ob_ref(tmp_object, ob, instances);
911 draw_object_cb(ob_ref);
912
913 evil::DEG_iterator_temp_object_free_properties(first_dupli, &tmp_object);
914 }
915 }
917}
918
919} // namespace blender::draw
920
922
923/* -------------------------------------------------------------------- */
926
928{
929 using namespace blender::draw;
930 Scene *scene;
931 static int lasttime = 0;
932 int ctime = int(BLI_time_now_seconds());
933
934 if (U.vbotimeout == 0 || (ctime - lasttime) < U.vbocollectrate || ctime == lasttime) {
935 return;
936 }
937
938 lasttime = ctime;
939
940 for (scene = static_cast<Scene *>(bmain->scenes.first); scene;
941 scene = static_cast<Scene *>(scene->id.next))
942 {
943 LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
944 Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer);
945 if (depsgraph == nullptr) {
946 continue;
947 }
948
949 /* TODO(fclem): This is not optimal since it iter over all dupli instances.
950 * In this case only the source object should be tagged. */
951 DEGObjectIterSettings deg_iter_settings = {nullptr};
952 deg_iter_settings.depsgraph = depsgraph;
954 DEG_OBJECT_ITER_BEGIN (&deg_iter_settings, ob) {
955 DRW_batch_cache_free_old(ob, ctime);
956 }
958 }
959 }
960}
961
963
964/* -------------------------------------------------------------------- */
967
969 DupliCacheManager &dupli_cache,
970 ExtractionGraph &extraction)
971{
972 if (ref.is_dupli() == false) {
974 }
975 else {
976 dupli_cache.try_add(ref);
977 }
978
979 DRWContext &ctx = drw_get();
981 [&](DrawEngine &instance) { instance.object_sync(ref, *DRW_manager_get()); });
982
983 /* TODO: in the future it would be nice to generate once for all viewports.
984 * But we need threaded DRW manager first. */
985 if (ref.is_dupli() == false) {
987 }
988 /* Batch generation for duplis happens after iter_callback. */
989}
990
992{
993 /* Enable modules and init for next sync. */
994 data->modules_begin_sync();
995
996 DupliCacheManager dupli_handler;
997 ExtractionGraph extraction;
998
999 /* Custom callback defines the set of object to sync. */
1000 iter_callback(dupli_handler, extraction);
1001
1002 dupli_handler.extract_all(extraction);
1003 extraction.work_and_wait(this->delayed_extraction);
1004
1006}
1007
1009{
1010 view_data_active->foreach_enabled_engine([&](DrawEngine &instance) { instance.init(); });
1011
1012 view_data_active->manager->begin_sync(this->obact);
1013
1014 view_data_active->foreach_enabled_engine([&](DrawEngine &instance) { instance.begin_sync(); });
1015
1016 sync(iter_callback);
1017
1018 view_data_active->foreach_enabled_engine([&](DrawEngine &instance) { instance.end_sync(); });
1019
1020 view_data_active->manager->end_sync();
1021}
1022
1024{
1025 /* Start Drawing */
1027
1028 view_data_active->foreach_enabled_engine([&](DrawEngine &instance) {
1029#ifdef __APPLE__
1030 if (G.debug & G_DEBUG_GPU) {
1031 /* Put each engine inside their own command buffers. */
1032 GPU_flush();
1033 }
1034#endif
1035 GPU_debug_group_begin(instance.name_get().c_str());
1036 instance.draw(*DRW_manager_get());
1038 });
1039
1040 /* Reset state after drawing */
1042
1043 /* Fix 3D view "lagging" on APPLE and WIN32+NVIDIA. (See #56996, #61474) */
1045 GPU_flush();
1046 }
1047}
1048
1049void DRW_draw_region_engine_info(int xoffset, int *yoffset, int line_height)
1050{
1051 DRWContext &ctx = drw_get();
1053 if (instance.info[0] != '\0') {
1054 const char *buf_step = IFACE_(instance.info);
1055 do {
1056 const char *buf = buf_step;
1057 buf_step = BLI_strchr_or_end(buf, '\n');
1058 const int buf_len = buf_step - buf;
1059 *yoffset -= line_height;
1060 BLF_draw_default(xoffset, *yoffset, 0.0f, buf, buf_len);
1061 } while (*buf_step ? ((void)buf_step++, true) : false);
1062 }
1063 });
1064}
1065
1066void DRWContext::enable_engines(bool gpencil_engine_needed, RenderEngineType *render_engine_type)
1067{
1068 DRWViewData &view_data = *this->view_data_active;
1069
1070 SpaceLink *space_data = this->space_data;
1071 if (space_data && space_data->spacetype == SPACE_IMAGE) {
1073 view_data.external.set_used(true);
1074 }
1075 else {
1076 view_data.image.set_used(true);
1077 }
1078 view_data.overlay.set_used(true);
1079 return;
1080 }
1081
1082 if (space_data && space_data->spacetype == SPACE_NODE) {
1083 /* Only enable when drawing the space image backdrop. */
1084 SpaceNode *snode = (SpaceNode *)space_data;
1085 if ((snode->flag & SNODE_BACKDRAW) != 0) {
1086 view_data.image.set_used(true);
1087 view_data.overlay.set_used(true);
1088 }
1089 return;
1090 }
1091
1093 view_data.grease_pencil.set_used(gpencil_engine_needed);
1094 view_data.object_select.set_used(true);
1095 return;
1096 }
1097
1099 view_data.edit_select.set_used(true);
1100 return;
1101 }
1102
1104 view_data.grease_pencil.set_used(gpencil_engine_needed);
1105 view_data.overlay.set_used(true);
1106 return;
1107 }
1108
1109 /* Regular V3D drawing. */
1110 {
1111 const eDrawType drawtype = eDrawType(this->v3d->shading.type);
1112 const bool use_xray = XRAY_ENABLED(this->v3d);
1113
1114 /* Base engine. */
1115 switch (drawtype) {
1116 case OB_WIRE:
1117 case OB_SOLID:
1118 view_data.workbench.set_used(true);
1119 break;
1120 case OB_MATERIAL:
1121 case OB_RENDER:
1122 default:
1123 if (render_engine_type == &DRW_engine_viewport_eevee_type) {
1124 view_data.eevee.set_used(true);
1125 }
1126 else if (render_engine_type == &DRW_engine_viewport_workbench_type) {
1127 view_data.workbench.set_used(true);
1128 }
1129 else if ((render_engine_type->flag & RE_INTERNAL) == 0) {
1130 view_data.external.set_used(true);
1131 }
1132 else {
1134 }
1135 break;
1136 }
1137
1138 if ((drawtype >= OB_SOLID) || !use_xray) {
1139 view_data.grease_pencil.set_used(gpencil_engine_needed);
1140 }
1141
1143
1144 view_data.overlay.set_used(true);
1145
1146#ifdef WITH_DRAW_DEBUG
1147 if (G.debug_value == 31) {
1148 view_data.edit_select_debug.set_used(true);
1149 }
1150#endif
1151 }
1152}
1153
1158
1160{
1161 if (v3d) {
1162 return ((v3d->object_type_exclude_viewport & (1 << OB_GREASE_PENCIL)) != 0);
1163 }
1164 return false;
1165}
1166
1172
1174{
1175 if (gpencil_object_is_excluded(v3d)) {
1176 return false;
1177 }
1179}
1180
1181/* -------------------------------------------------------------------- */
1184
1186{
1187 RegionView3D *rv3d = draw_ctx.rv3d;
1188
1190 GPU_matrix_set(rv3d->viewmat);
1191
1192 if (draw_ctx.evil_C) {
1197 }
1198
1199 /* State is reset later at the beginning of `draw_ctx.engines_draw_scene()`. */
1200}
1201
1203{
1204 RegionView3D *rv3d = draw_ctx.rv3d;
1205 ARegion *region = draw_ctx.region;
1206 View3D *v3d = draw_ctx.v3d;
1207 Depsgraph *depsgraph = draw_ctx.depsgraph;
1208
1209 const bool do_annotations = draw_show_annotation();
1210
1211 /* State has been reset at the end `draw_ctx.engines_draw_scene()`. */
1212
1214 if (draw_ctx.evil_C) {
1216
1218
1220 GPU_matrix_set(rv3d->viewmat);
1221
1222 /* annotations - temporary drawing buffer (3d space) */
1223 /* XXX: Or should we use a proper draw/overlay engine for this case? */
1224 if (do_annotations) {
1226 /* XXX: as `scene->gpd` is not copied for copy-on-eval yet. */
1229 }
1230
1232 /* Apply state for callbacks. */
1234
1236
1237#ifdef WITH_XR_OPENXR
1238 /* XR callbacks (controllers, custom draw functions) for session mirror. */
1239 if ((v3d->flag & V3D_XR_SESSION_MIRROR) != 0) {
1240 if ((v3d->flag2 & V3D_XR_SHOW_CONTROLLERS) != 0) {
1242 if (art) {
1244 }
1245 }
1246 if ((v3d->flag2 & V3D_XR_SHOW_CUSTOM_OVERLAYS) != 0) {
1248 if (st) {
1250 if (art) {
1252 }
1253 }
1254 }
1255 }
1256#endif
1257
1258 /* Callback can be nasty and do whatever they want with the state.
1259 * Don't trust them! */
1261
1262 /* Needed so gizmo isn't occluded. */
1263 if ((v3d->gizmo_flag & V3D_GIZMO_HIDE) == 0) {
1265 DRW_draw_gizmo_3d(draw_ctx.evil_C, region);
1266 }
1267
1269 DRW_draw_region_info(draw_ctx.evil_C, region);
1270
1271 /* Annotations - temporary drawing buffer (screen-space). */
1272 /* XXX: Or should we use a proper draw/overlay engine for this case? */
1273 if (((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) && (do_annotations)) {
1275 /* XXX: as `scene->gpd` is not copied for copy-on-eval yet */
1277 }
1278
1279 if ((v3d->gizmo_flag & V3D_GIZMO_HIDE) == 0) {
1280 /* Draw 2D after region info so we can draw on top of the camera passepartout overlay.
1281 * 'DRW_draw_region_info' sets the projection in pixel-space. */
1283 DRW_draw_gizmo_2d(draw_ctx.evil_C, region);
1284 }
1285
1287 }
1288 else {
1289 if (v3d && ((v3d->flag2 & V3D_SHOW_ANNOTATION) != 0)) {
1291 /* XXX: as `scene->gpd` is not copied for copy-on-eval yet */
1294 }
1295
1296#ifdef WITH_XR_OPENXR
1297 if ((v3d->flag & V3D_XR_SESSION_SURFACE) != 0) {
1299
1301
1303
1305 GPU_matrix_set(rv3d->viewmat);
1306
1307 /* XR callbacks (controllers, custom draw functions) for session surface. */
1308 if (((v3d->flag2 & V3D_XR_SHOW_CONTROLLERS) != 0) ||
1309 ((v3d->flag2 & V3D_XR_SHOW_CUSTOM_OVERLAYS) != 0))
1310 {
1313
1314 if ((v3d->flag2 & V3D_XR_SHOW_CONTROLLERS) != 0) {
1316 if (art) {
1318 }
1319 }
1320 if ((v3d->flag2 & V3D_XR_SHOW_CUSTOM_OVERLAYS) != 0) {
1322 if (st) {
1324 if (art) {
1326 }
1327 }
1328 }
1329
1331 }
1332
1334 }
1335#endif
1336 }
1338
1340}
1341
1343{
1344 if (draw_ctx.evil_C) {
1349 }
1350
1351 /* State is reset later at the beginning of `draw_ctx.engines_draw_scene()`. */
1352}
1353
1355{
1356 const bool do_annotations = draw_show_annotation();
1357 const bool do_draw_gizmos = (draw_ctx.space_data->spacetype != SPACE_IMAGE);
1358
1359 /* State has been reset at the end `draw_ctx.engines_draw_scene()`. */
1360
1362 if (draw_ctx.evil_C) {
1364
1366
1369
1370 wmOrtho2(v2d.cur.xmin, v2d.cur.xmax, v2d.cur.ymin, v2d.cur.ymax);
1371
1372 if (do_annotations) {
1373 ED_annotation_draw_view2d(draw_ctx.evil_C, true);
1374 }
1375
1377
1379
1381 /* Callback can be nasty and do whatever they want with the state.
1382 * Don't trust them! */
1384
1386
1387 if (do_annotations) {
1388 ED_annotation_draw_view2d(draw_ctx.evil_C, false);
1389 }
1390 }
1391
1392 ED_region_pixelspace(draw_ctx.region);
1393
1394 if (do_draw_gizmos) {
1396 DRW_draw_gizmo_2d(draw_ctx.evil_C, draw_ctx.region);
1397 }
1398
1400
1402}
1403
1405{
1406 DRWContext &draw_ctx = drw_get();
1407 BLI_assert(draw_ctx.text_store_p);
1408 if (*draw_ctx.text_store_p == nullptr) {
1409 *draw_ctx.text_store_p = DRW_text_cache_create();
1410 }
1411 return *draw_ctx.text_store_p;
1412}
1413
1415
1416/* -------------------------------------------------------------------- */
1419
1424static void drw_draw_render_loop_3d(DRWContext &draw_ctx, RenderEngineType *engine_type)
1425{
1426 using namespace blender::draw;
1427 Depsgraph *depsgraph = draw_ctx.depsgraph;
1428 View3D *v3d = draw_ctx.v3d;
1429
1430 /* Check if scene needs to perform the populate loop */
1431 const bool internal_engine = (engine_type->flag & RE_INTERNAL) != 0;
1432 const bool draw_type_render = v3d->shading.type == OB_RENDER;
1433 const bool overlays_on = (v3d->flag2 & V3D_HIDE_OVERLAYS) == 0;
1434 const bool gpencil_engine_needed = DRW_gpencil_engine_needed_viewport(depsgraph, v3d);
1435 const bool do_populate_loop = internal_engine || overlays_on || !draw_type_render ||
1436 gpencil_engine_needed;
1437
1438 auto should_draw_object = [&](Object &ob) -> bool {
1439 return BKE_object_is_visible_in_viewport(v3d, &ob);
1440 };
1441
1442 draw_ctx.enable_engines(gpencil_engine_needed, engine_type);
1443 draw_ctx.engines_data_validate();
1444 draw_ctx.engines_init_and_sync([&](DupliCacheManager &duplis, ExtractionGraph &extraction) {
1445 /* Only iterate over objects for internal engines or when overlays are enabled */
1446 if (do_populate_loop) {
1447 foreach_obref_in_scene(draw_ctx, should_draw_object, [&](ObjectRef &ob_ref) {
1448 drw_engines_cache_populate(ob_ref, duplis, extraction);
1449 });
1450 }
1451 });
1452
1453 /* No frame-buffer allowed before drawing. */
1457
1458 drw_callbacks_pre_scene(draw_ctx);
1459 draw_ctx.engines_draw_scene();
1460 drw_callbacks_post_scene(draw_ctx);
1461
1463 /* Don't unbind the frame-buffer yet in this case and let
1464 * GPU_viewport_unbind do it, so that we can still do further
1465 * drawing of action zones on top. */
1466 }
1467 else {
1469 }
1470}
1471
1473{
1474 Depsgraph *depsgraph = draw_ctx.depsgraph;
1475 ARegion *region = draw_ctx.region;
1476
1477 /* TODO(jbakker): Only populate when editor needs to draw object.
1478 * for the image editor this is when showing UVs. */
1479 const bool do_populate_loop = (draw_ctx.space_data->spacetype == SPACE_IMAGE);
1480
1481 draw_ctx.enable_engines();
1482 draw_ctx.engines_data_validate();
1483 draw_ctx.engines_init_and_sync([&](DupliCacheManager &duplis, ExtractionGraph &extraction) {
1484 /* Only iterate over objects when overlay uses object data. */
1485 if (do_populate_loop) {
1486 DEGObjectIterSettings deg_iter_settings = {nullptr};
1487 deg_iter_settings.depsgraph = depsgraph;
1489 DEG_OBJECT_ITER_BEGIN (&deg_iter_settings, ob) {
1490 blender::draw::ObjectRef ob_ref(ob);
1491 drw_engines_cache_populate(ob_ref, duplis, extraction);
1492 }
1494 }
1495 });
1496
1497 /* No frame-buffer allowed before drawing. */
1501
1503 draw_ctx.engines_draw_scene();
1504 drw_callbacks_post_scene_2D(draw_ctx, region->v2d);
1505
1507 /* Don't unbind the frame-buffer yet in this case and let
1508 * GPU_viewport_unbind do it, so that we can still do further
1509 * drawing of action zones on top. */
1510 }
1511 else {
1513 }
1514}
1515
1517{
1519 ARegion *region = CTX_wm_region(C);
1521
1522 DRWContext draw_ctx(DRWContext::VIEWPORT, depsgraph, viewport, C);
1523 draw_ctx.acquire_data();
1524
1525 if (draw_ctx.v3d) {
1527 RenderEngineType *engine_type = ED_view3d_engine_type(scene, draw_ctx.v3d->shading.type);
1528
1529 draw_ctx.options.draw_background = (scene->r.alphamode == R_ADDSKY) ||
1530 (draw_ctx.v3d->shading.type != OB_RENDER);
1531
1532 drw_draw_render_loop_3d(draw_ctx, engine_type);
1533 }
1534 else {
1535 drw_draw_render_loop_2d(draw_ctx);
1536 }
1537
1538 draw_ctx.release_data();
1539}
1540
1542 RenderEngineType *engine_type,
1543 ARegion *region,
1544 View3D *v3d,
1545 const bool is_image_render,
1546 const bool draw_background,
1547 const bool do_color_management,
1548 GPUOffScreen *ofs,
1549 GPUViewport *viewport)
1550{
1551 const bool is_xr_surface = ((v3d->flag & V3D_XR_SESSION_SURFACE) != 0);
1552
1553 /* Create temporary viewport if needed or update the existing viewport. */
1554 GPUViewport *render_viewport = viewport;
1555 if (viewport == nullptr) {
1556 render_viewport = GPU_viewport_create();
1557 }
1558
1559 GPU_viewport_bind_from_offscreen(render_viewport, ofs, is_xr_surface);
1560
1561 /* Just here to avoid an assert but shouldn't be required in practice. */
1563
1564 /* TODO(fclem): We might want to differentiate between render preview and offscreen render in the
1565 * future. The later can do progressive rendering. */
1566 BLI_assert(is_xr_surface == !is_image_render);
1567 UNUSED_VARS_NDEBUG(is_image_render);
1569
1570 DRWContext draw_ctx(mode, depsgraph, render_viewport, nullptr, region, v3d);
1571 draw_ctx.acquire_data();
1573
1574 drw_draw_render_loop_3d(draw_ctx, engine_type);
1575
1576 draw_ctx.release_data();
1577
1578 if (draw_background) {
1579 /* HACK(@fclem): In this case we need to make sure the final alpha is 1.
1580 * We use the blend mode to ensure that. A better way to fix that would
1581 * be to do that in the color-management shader. */
1582 GPU_offscreen_bind(ofs, false);
1583 GPU_clear_color(0.0f, 0.0f, 0.0f, 1.0f);
1584 /* Pre-multiply alpha over black background. */
1586 }
1587
1590 const bool do_overlays = (v3d->flag2 & V3D_HIDE_OVERLAYS) == 0 ||
1591 ELEM(v3d->shading.type, OB_WIRE, OB_SOLID) ||
1592 (ELEM(v3d->shading.type, OB_MATERIAL) &&
1593 (v3d->shading.flag & V3D_SHADING_SCENE_WORLD) == 0) ||
1594 (ELEM(v3d->shading.type, OB_RENDER) &&
1596 GPU_viewport_unbind_from_offscreen(render_viewport, ofs, do_color_management, do_overlays);
1597
1598 if (draw_background) {
1599 /* Reset default. */
1601 }
1602
1603 /* Free temporary viewport. */
1604 if (viewport == nullptr) {
1605 GPU_viewport_free(render_viewport);
1606 }
1607}
1608
1610{
1612 return true;
1613 }
1614
1615 DEGObjectIterSettings deg_iter_settings = {nullptr};
1616 deg_iter_settings.depsgraph = depsgraph;
1618 DEG_OBJECT_ITER_BEGIN (&deg_iter_settings, ob) {
1619 if (ob->type == OB_GREASE_PENCIL) {
1621 return true;
1622 }
1623 }
1624 }
1626
1627 return false;
1628}
1629
1631{
1632 using namespace blender::draw;
1633 /* This function should only be called if there are grease pencil objects,
1634 * especially important to avoid failing in background renders without GPU context. */
1636
1639 RenderResult *render_result = RE_engine_get_result(engine);
1640 RenderLayer *render_layer = RE_GetRenderLayer(render_result, view_layer->name);
1641 if (render_layer == nullptr) {
1642 return;
1643 }
1644
1645 Render *render = engine->re;
1646
1648
1649 DRWContext draw_ctx(DRWContext::RENDER, depsgraph, {engine->resolution_x, engine->resolution_y});
1650 draw_ctx.acquire_data();
1651 draw_ctx.options.draw_background = scene->r.alphamode == R_ADDSKY;
1652
1653 /* Main rendering. */
1654 rctf view_rect;
1655 rcti render_rect;
1656 RE_GetViewPlane(render, &view_rect, &render_rect);
1657 if (BLI_rcti_is_empty(&render_rect)) {
1658 BLI_rcti_init(&render_rect, 0, draw_ctx.size[0], 0, draw_ctx.size[1]);
1659 }
1660
1661 for (RenderView *render_view = static_cast<RenderView *>(render_result->views.first);
1662 render_view != nullptr;
1663 render_view = render_view->next)
1664 {
1665 RE_SetActiveRenderView(render, render_view->name);
1666 gpencil::Engine::render_to_image(engine, render_layer, render_rect);
1667 }
1668
1670
1672
1674
1675 draw_ctx.release_data();
1676
1677 /* Restore Drawing area. */
1679
1681}
1682
1684 RenderEngine *engine,
1685 Depsgraph *depsgraph,
1686 std::function<void(RenderEngine *, RenderLayer *, const rcti)> render_view_cb,
1687 std::function<void(RenderResult *)> store_metadata_cb)
1688{
1689 using namespace blender::draw;
1692 Render *render = engine->re;
1693
1694 /* IMPORTANT: We don't support immediate mode in render mode!
1695 * This shall remain in effect until immediate mode supports
1696 * multiple threads. */
1697
1698 /* Begin GPU workload Boundary */
1700
1701 DRWContext draw_ctx(DRWContext::RENDER, depsgraph, {engine->resolution_x, engine->resolution_y});
1702 draw_ctx.acquire_data();
1703 draw_ctx.options.draw_background = scene->r.alphamode == R_ADDSKY;
1704
1705 /* Main rendering. */
1706 rctf view_rect;
1707 rcti render_rect;
1708 RE_GetViewPlane(render, &view_rect, &render_rect);
1709 if (BLI_rcti_is_empty(&render_rect)) {
1710 BLI_rcti_init(&render_rect, 0, draw_ctx.size[0], 0, draw_ctx.size[1]);
1711 }
1712
1713 /* Reset state before drawing */
1715
1716 /* set default viewport */
1717 GPU_viewport(0, 0, draw_ctx.size[0], draw_ctx.size[1]);
1718
1719 /* Init render result. */
1720 RenderResult *render_result = RE_engine_begin_result(engine,
1721 0,
1722 0,
1723 draw_ctx.size[0],
1724 draw_ctx.size[1],
1725 view_layer->name,
1726 /*RR_ALL_VIEWS*/ nullptr);
1727 RenderLayer *render_layer = static_cast<RenderLayer *>(render_result->layers.first);
1728 for (RenderView *render_view = static_cast<RenderView *>(render_result->views.first);
1729 render_view != nullptr;
1730 render_view = render_view->next)
1731 {
1732 RE_SetActiveRenderView(render, render_view->name);
1733 render_view_cb(engine, render_layer, render_rect);
1734 }
1735
1736 RE_engine_end_result(engine, render_result, false, false, false);
1737
1738 store_metadata_cb(RE_engine_get_result(engine));
1739
1741
1743
1744 draw_ctx.release_data();
1746
1747 /* End GPU workload Boundary */
1749}
1750
1752 RenderEngine *engine,
1753 Depsgraph *depsgraph,
1754 std::function<void(blender::draw::ObjectRef &, RenderEngine *, Depsgraph *)> callback)
1755{
1756 using namespace blender::draw;
1757
1758 DRWContext &draw_ctx = drw_get();
1759 View3D *v3d = draw_ctx.v3d;
1760
1761 auto should_draw_object = [&](Object &ob) -> bool {
1762 if (v3d) {
1763 return BKE_object_is_visible_in_viewport(v3d, &ob);
1764 }
1765 return true;
1766 };
1767
1768 draw_ctx.sync([&](DupliCacheManager &duplis, ExtractionGraph &extraction) {
1769 foreach_obref_in_scene(draw_ctx, should_draw_object, [&](ObjectRef &ob_ref) {
1770 if (ob_ref.is_dupli() == false) {
1772 }
1773 else {
1774 duplis.try_add(ob_ref);
1775 }
1776 callback(ob_ref, engine, depsgraph);
1777 if (ob_ref.is_dupli() == false) {
1779 }
1780 /* Batch generation for duplis happens after iter_callback. */
1781 });
1782 });
1783}
1784
1785void DRW_custom_pipeline_begin(DRWContext &draw_ctx, Depsgraph * /*depsgraph*/)
1786{
1787 draw_ctx.acquire_data();
1788 draw_ctx.data->modules_begin_sync();
1789}
1790
1792{
1794
1795 /* The use of custom pipeline in other thread using the same
1796 * resources as the main thread (viewport) may lead to data
1797 * races and undefined behavior on certain drivers. Using
1798 * GPU_finish to sync seems to fix the issue. (see #62997) */
1800 if (type == GPU_BACKEND_OPENGL) {
1801 GPU_finish();
1802 }
1803
1805 draw_ctx.release_data();
1806}
1807
1809{
1810 using namespace blender::draw;
1811 DRWContext &draw_ctx = drw_get();
1812 draw_ctx.data->modules_exit();
1813 draw_ctx.acquire_data();
1814 draw_ctx.data->modules_begin_sync();
1815}
1816
1817void DRW_render_set_time(RenderEngine *engine, Depsgraph *depsgraph, int frame, float subframe)
1818{
1819 DRWContext &draw_ctx = drw_get();
1820 RE_engine_frame_set(engine, frame, subframe);
1823}
1824
1829
1831{
1832 if (g_select_buffer.framebuffer_depth_only == nullptr) {
1833 g_select_buffer.framebuffer_depth_only = GPU_framebuffer_create("framebuffer_depth_only");
1834 }
1835
1836 if ((g_select_buffer.texture_depth != nullptr) &&
1837 ((GPU_texture_width(g_select_buffer.texture_depth) != size[0]) ||
1838 (GPU_texture_height(g_select_buffer.texture_depth) != size[1])))
1839 {
1840 GPU_texture_free(g_select_buffer.texture_depth);
1841 g_select_buffer.texture_depth = nullptr;
1842 }
1843
1844 if (g_select_buffer.texture_depth == nullptr) {
1846 g_select_buffer.texture_depth = GPU_texture_create_2d(
1847 "select_depth",
1848 size[0],
1849 size[1],
1850 1,
1851 blender::gpu::TextureFormat::SFLOAT_32_DEPTH,
1852 usage,
1853 nullptr);
1854
1856 g_select_buffer.framebuffer_depth_only, g_select_buffer.texture_depth, 0, 0);
1857
1858 GPU_framebuffer_check_valid(g_select_buffer.framebuffer_depth_only, nullptr);
1859 }
1860}
1861
1863 ARegion *region,
1864 View3D *v3d,
1865 bool use_obedit_skip,
1866 bool draw_surface,
1867 bool /*use_nearest*/,
1868 const bool do_material_sub_selection,
1869 const rcti *rect,
1870 DRW_SelectPassFn select_pass_fn,
1871 void *select_pass_user_data,
1872 DRW_ObjectFilterFn object_filter_fn,
1873 void *object_filter_user_data)
1874{
1875 using namespace blender::draw;
1878 const int viewport_size[2] = {BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)};
1879
1880 Object *obact = BKE_view_layer_active_object_get(view_layer);
1881 Object *obedit = use_obedit_skip ? nullptr : OBEDIT_FROM_OBACT(obact);
1882
1883 bool use_obedit = false;
1884 const ToolSettings *ts = scene->toolsettings;
1885
1886 /* obedit_ctx_mode is used for selecting the right draw engines */
1887 // eContextObjectMode obedit_ctx_mode;
1888 /* object_mode is used for filtering objects in the depsgraph */
1889 eObjectMode object_mode = eObjectMode::OB_MODE_EDIT;
1890 int object_type = 0;
1891 if (obedit != nullptr) {
1892 object_type = obedit->type;
1893 object_mode = eObjectMode(obedit->mode);
1894 if (obedit->type == OB_MBALL) {
1895 use_obedit = true;
1896 // obedit_ctx_mode = CTX_MODE_EDIT_METABALL;
1897 }
1898 else if (obedit->type == OB_ARMATURE) {
1899 use_obedit = true;
1900 // obedit_ctx_mode = CTX_MODE_EDIT_ARMATURE;
1901 }
1902 }
1903
1904 if ((v3d->overlay.flag & V3D_OVERLAY_BONE_SELECT) &&
1905 /* Only restrict selection to bones when the user turns on "Lock Object Modes".
1906 * If the lock is off, skip this so other objects can still be selected.
1907 * See #66950 & #125822. */
1909 {
1910 if (!(v3d->flag2 & V3D_HIDE_OVERLAYS)) {
1911 /* NOTE: don't use "BKE_object_pose_armature_get" here, it breaks selection. */
1912 Object *obpose = OBPOSE_FROM_OBACT(obact);
1913 if (obpose == nullptr) {
1914 Object *obweight = OBWEIGHTPAINT_FROM_OBACT(obact);
1915 if (obweight) {
1916 /* Only use Armature pose selection, when connected armature is in pose mode. */
1917 Object *ob_armature = BKE_modifiers_is_deformed_by_armature(obweight);
1918 if (ob_armature && ob_armature->mode == OB_MODE_POSE) {
1919 obpose = ob_armature;
1920 }
1921 }
1922 }
1923
1924 if (obpose) {
1925 use_obedit = true;
1926 object_type = obpose->type;
1927 object_mode = eObjectMode(obpose->mode);
1928 // obedit_ctx_mode = CTX_MODE_POSE;
1929 }
1930 }
1931 }
1932
1933 bool use_gpencil = !use_obedit && !draw_surface &&
1935
1936 DRWContext::Mode mode = do_material_sub_selection ? DRWContext::SELECT_OBJECT_MATERIAL :
1938
1939 DRWContext draw_ctx(mode, depsgraph, viewport_size, nullptr, region, v3d);
1940 draw_ctx.acquire_data();
1941 draw_ctx.enable_engines(use_gpencil);
1942 draw_ctx.engines_data_validate();
1943 draw_ctx.engines_init_and_sync([&](DupliCacheManager &duplis, ExtractionGraph &extraction) {
1944 if (use_obedit) {
1945 FOREACH_OBJECT_IN_MODE_BEGIN (scene, view_layer, v3d, object_type, object_mode, ob_iter) {
1946 /* Depsgraph usually does this, but we use a different iterator.
1947 * So we have to do it manually. */
1948 ob_iter->runtime->select_id = DEG_get_original(ob_iter)->runtime->select_id;
1949
1950 blender::draw::ObjectRef ob_ref(ob_iter);
1951 drw_engines_cache_populate(ob_ref, duplis, extraction);
1952 }
1954 }
1955 else {
1956 /* When selecting pose-bones in pose mode, check for visibility not select-ability
1957 * as pose-bones have their own selection restriction flag. */
1958 const bool use_pose_exception = (draw_ctx.object_pose != nullptr);
1959
1960 const int object_type_exclude_select = v3d->object_type_exclude_select;
1961 bool filter_exclude = false;
1962
1963 auto should_draw_object = [&](Object &ob) {
1964 if (!BKE_object_is_visible_in_viewport(v3d, &ob)) {
1965 return false;
1966 }
1967 if (use_pose_exception && (ob.mode & OB_MODE_POSE)) {
1968 if ((ob.base_flag & BASE_ENABLED_AND_VISIBLE_IN_DEFAULT_VIEWPORT) == 0) {
1969 return false;
1970 }
1971 }
1972 else {
1973 if ((ob.base_flag & BASE_SELECTABLE) == 0) {
1974 return false;
1975 }
1976 }
1977
1978 if ((object_type_exclude_select & (1 << ob.type)) == 0) {
1979 if (object_filter_fn != nullptr) {
1980 if (ob.base_flag & BASE_FROM_DUPLI) {
1981 /* pass (use previous filter_exclude value) */
1982 }
1983 else {
1984 filter_exclude = (object_filter_fn(&ob, object_filter_user_data) == false);
1985 }
1986 if (filter_exclude) {
1987 return false;
1988 }
1989 }
1990 }
1991 return true;
1992 };
1993
1994 foreach_obref_in_scene(draw_ctx, should_draw_object, [&](ObjectRef &ob_ref) {
1995 drw_engines_cache_populate(ob_ref, duplis, extraction);
1996 });
1997 }
1998 });
1999
2000 /* Setup frame-buffer. */
2002 GPU_framebuffer_bind(g_select_buffer.framebuffer_depth_only);
2003 GPU_framebuffer_clear_depth(g_select_buffer.framebuffer_depth_only, 1.0f);
2004
2005 /* WORKAROUND: Needed for Select-Next for keeping the same code-flow as Overlay-Next. */
2006 /* TODO(pragma37): Some engines retrieve the depth texture before this point (See #132922).
2007 * Check with @fclem. */
2008 BLI_assert(DRW_context_get()->viewport_texture_list_get()->depth == nullptr);
2010
2011 drw_callbacks_pre_scene(draw_ctx);
2012 /* Only 1-2 passes. */
2013 while (true) {
2014 if (!select_pass_fn(DRW_SELECT_PASS_PRE, select_pass_user_data)) {
2015 break;
2016 }
2017 draw_ctx.engines_draw_scene();
2018 if (!select_pass_fn(DRW_SELECT_PASS_POST, select_pass_user_data)) {
2019 break;
2020 }
2021 }
2022
2023 /* WORKAROUND: Do not leave ownership to the viewport list. */
2025
2026 draw_ctx.release_data();
2027
2029}
2030
2032 ARegion *region,
2033 View3D *v3d,
2034 GPUViewport *viewport,
2035 const bool use_gpencil,
2036 const bool use_only_selected,
2037 const bool use_only_active_object)
2038{
2039 using namespace blender::draw;
2040
2041 DRWContext draw_ctx(use_only_active_object ? DRWContext::DEPTH_ACTIVE_OBJECT : DRWContext::DEPTH,
2042 depsgraph,
2043 viewport,
2044 nullptr,
2045 region,
2046 v3d);
2047 draw_ctx.acquire_data();
2048 draw_ctx.enable_engines(use_gpencil);
2049 draw_ctx.engines_init_and_sync([&](DupliCacheManager &duplis, ExtractionGraph &extraction) {
2050 auto should_draw_object = [&](Object &ob) {
2051 if (!BKE_object_is_visible_in_viewport(v3d, &ob)) {
2052 return false;
2053 }
2054 if (use_only_selected && !(ob.base_flag & BASE_SELECTED)) {
2055 return false;
2056 }
2057 return true;
2058 };
2059
2060 if (use_only_active_object) {
2061 blender::draw::ObjectRef ob_ref(draw_ctx.obact);
2062 drw_engines_cache_populate(ob_ref, duplis, extraction);
2063 }
2064 else {
2065 foreach_obref_in_scene(draw_ctx, should_draw_object, [&](ObjectRef &ob_ref) {
2066 drw_engines_cache_populate(ob_ref, duplis, extraction);
2067 });
2068 }
2069 });
2070
2071 /* Setup frame-buffer. */
2073 blender::gpu::FrameBuffer *depth_fb = nullptr;
2075 {
2076 GPU_ATTACHMENT_TEXTURE(depth_tx),
2078 });
2079 GPU_framebuffer_bind(depth_fb);
2080 GPU_framebuffer_clear_depth(depth_fb, 1.0f);
2081
2082 draw_ctx.engines_draw_scene();
2083
2084 /* TODO: Reading depth for operators should be done here. */
2085
2087 GPU_framebuffer_free(depth_fb);
2088
2089 draw_ctx.release_data();
2090}
2091
2092void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *region, View3D *v3d)
2093{
2095 GPUViewport *viewport = WM_draw_region_get_viewport(region);
2096 if (!viewport) {
2097 /* Selection engine requires a viewport.
2098 * TODO(@germano): This should be done internally in the engine. */
2099 sel_ctx->max_index_drawn_len = 1;
2100 return;
2101 }
2102
2103 using namespace blender::draw;
2104
2105 /* Make sure select engine gets the correct vertex size. */
2107
2108 DRWContext draw_ctx(DRWContext::SELECT_EDIT_MESH, depsgraph, viewport, nullptr, region, v3d);
2109 draw_ctx.acquire_data();
2110 draw_ctx.enable_engines();
2111 draw_ctx.engines_init_and_sync([&](DupliCacheManager &duplis, ExtractionGraph &extraction) {
2112 for (Object *obj_eval : sel_ctx->objects) {
2113 blender::draw::ObjectRef ob_ref(obj_eval);
2114 drw_engines_cache_populate(ob_ref, duplis, extraction);
2115 }
2116
2117 if (RETOPOLOGY_ENABLED(v3d) && !XRAY_ENABLED(v3d)) {
2118 auto should_draw_object = [&](Object &ob) {
2119 if (ob.type != OB_MESH) {
2120 /* The iterator has evaluated meshes for all solid objects.
2121 * It also has non-mesh objects however, which are not supported here. */
2122 return false;
2123 }
2124 if (DRW_object_is_in_edit_mode(&ob)) {
2125 /* Only background (non-edit) objects are used for occlusion. */
2126 return false;
2127 }
2128 if (!BKE_object_is_visible_in_viewport(v3d, &ob)) {
2129 return false;
2130 }
2131 return true;
2132 };
2133
2134 foreach_obref_in_scene(draw_ctx, should_draw_object, [&](ObjectRef &ob_ref) {
2135 drw_engines_cache_populate(ob_ref, duplis, extraction);
2136 });
2137 }
2138 });
2139
2140 draw_ctx.engines_draw_scene();
2141
2142 draw_ctx.release_data();
2143}
2144
2146{
2147 return DRWContext::is_active();
2148}
2149
2151
2152/* -------------------------------------------------------------------- */
2155
2157{
2158 return &drw_get();
2159}
2160
2162{
2163 if (this->evil_C != nullptr) {
2165 return ED_screen_animation_playing(wm) != nullptr;
2166 }
2167 return false;
2168}
2169
2171{
2172 return (rv3d) && (rv3d->rflag & (RV3D_NAVIGATING | RV3D_PAINTING));
2173}
2174
2176{
2177 return (rv3d) && (rv3d->rflag & (RV3D_PAINTING));
2178}
2179
2181{
2182 return (G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) != 0;
2183}
2184
2186{
2187 if (!this->v3d) {
2188 return false;
2189 }
2190
2192 return false;
2193 }
2194
2195 if (!(this->v3d->shading.type >= OB_MATERIAL)) {
2196 return false;
2197 }
2198
2199 if (!this->scene->compositing_node_group) {
2200 return false;
2201 }
2202
2203 if (!this->rv3d) {
2204 return false;
2205 }
2206
2208 this->rv3d->persp != RV3D_CAMOB)
2209 {
2210 return false;
2211 }
2212
2213 return true;
2214}
2215
2217
2218/* -------------------------------------------------------------------- */
2221
2227
2240
2242
2243/* -------------------------------------------------------------------- */
2246
2277
2279{
2281 GPU_FRAMEBUFFER_FREE_SAFE(g_select_buffer.framebuffer_depth_only);
2282
2284}
2285
Depsgraph * CTX_data_expect_evaluated_depsgraph(const bContext *C)
SpaceLink * CTX_wm_space_data(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
void(* BKE_curve_batch_cache_free_cb)(Curve *cu)
Definition curve.cc:5500
void(* BKE_curve_batch_cache_dirty_tag_cb)(Curve *cu, int mode)
Definition curve.cc:5499
Low-level operations for curves that cannot be defined in the C++ header yet.
void(* BKE_curves_batch_cache_dirty_tag_cb)(struct Curves *curves, int mode)
void(* BKE_curves_batch_cache_free_cb)(struct Curves *curves)
blender::VectorList< DupliObject > DupliList
void object_duplilist(Depsgraph *depsgraph, Scene *sce, Object *ob, blender::Set< const Object * > *include_objects, DupliList &r_duplilist)
@ G_DEBUG_GPU
@ G_TRANSFORM_OBJ
@ G_TRANSFORM_EDIT
Low-level operations for grease pencil that cannot be defined in the C++ header yet.
void(* BKE_grease_pencil_batch_cache_dirty_tag_cb)(GreasePencil *grease_pencil, int mode)
void(* BKE_grease_pencil_batch_cache_free_cb)(GreasePencil *grease_pencil)
void(* BKE_lattice_batch_cache_dirty_tag_cb)(Lattice *lt, int mode)
Definition lattice.cc:701
void(* BKE_lattice_batch_cache_free_cb)(Lattice *lt)
Definition lattice.cc:702
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
#define FOREACH_OBJECT_IN_MODE_END
Definition BKE_layer.hh:382
Object * BKE_view_layer_active_object_get(const ViewLayer *view_layer)
bool BKE_object_is_visible_in_viewport(const View3D *v3d, const Object *ob)
#define FOREACH_OBJECT_IN_MODE_BEGIN(_scene, _view_layer, _v3d, _object_type, _object_mode, _instance)
Definition BKE_layer.hh:377
void(* BKE_mesh_batch_cache_free_cb)(void *batch_cache)
void(* BKE_mesh_batch_cache_dirty_tag_cb)(Mesh *mesh, eMeshBatchDirtyMode mode)
Mesh * BKE_mesh_wrapper_ensure_subdivision(Mesh *mesh)
ModifierData * BKE_modifiers_findby_type(const Object *ob, ModifierType type)
Object * BKE_modifiers_is_deformed_by_armature(Object *ob)
General operations, lookup, etc. for blender objects.
const Mesh * BKE_object_get_editmesh_eval_cage(const Object *object)
bool BKE_object_is_in_editmode(const Object *ob)
void BKE_object_replace_data_on_shallow_copy(Object *ob, ID *new_data)
@ OB_VISIBLE_INSTANCES
@ OB_VISIBLE_SELF
@ OB_VISIBLE_PARTICLES
Object * BKE_object_pose_armature_get(Object *ob)
int BKE_object_obdata_to_type(const ID *id) ATTR_NONNULL(1)
int BKE_object_visibility(const Object *ob, int dag_eval_mode)
bool psys_check_enabled(struct Object *ob, struct ParticleSystem *psys, bool use_render_params)
Definition particle.cc:710
void(* BKE_particle_batch_cache_dirty_tag_cb)(struct ParticleSystem *psys, int mode)
Definition particle.cc:5285
bool psys_in_edit_mode(struct Depsgraph *depsgraph, const struct ParticleSystem *psys)
void(* BKE_particle_batch_cache_free_cb)(struct ParticleSystem *psys)
Definition particle.cc:5286
General operations for point clouds.
void(* BKE_pointcloud_batch_cache_free_cb)(PointCloud *pointcloud)
void(* BKE_pointcloud_batch_cache_dirty_tag_cb)(PointCloud *pointcloud, int mode)
Depsgraph * BKE_scene_get_depsgraph(const Scene *scene, const ViewLayer *view_layer)
Definition scene.cc:3403
bool BKE_scene_uses_blender_workbench(const Scene *scene)
Definition scene.cc:2829
SpaceType * BKE_spacetype_from_id(int spaceid)
Definition screen.cc:257
ARegionType * BKE_regiontype_from_id(const SpaceType *st, int regionid)
Definition screen.cc:267
bool BKE_subsurf_modifier_has_gpu_subdiv(const Mesh *mesh)
void(* BKE_subsurf_modifier_free_gpu_cache_cb)(blender::bke::subdiv::Subdiv *subdiv)
Volume data-block.
void(* BKE_volume_batch_cache_dirty_tag_cb)(Volume *volume, int mode)
void(* BKE_volume_batch_cache_free_cb)(Volume *volume)
void BLF_draw_default(float x, float y, float z, const char *str, size_t str_len) ATTR_NONNULL()
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
struct GSet GSet
Definition BLI_ghash.h:337
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
#define LISTBASE_FOREACH(type, var, list)
bool is_negative_m4(const float mat[4][4])
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition BLI_rect.h:198
void BLI_rcti_init(struct rcti *rect, int xmin, int xmax, int ymin, int ymax)
Definition rct.cc:414
void BLI_rctf_transform_calc_m4_pivot_min(const rctf *dst, const rctf *src, float matrix[4][4])
Definition rct.cc:551
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition BLI_rect.h:194
bool BLI_rcti_is_empty(const struct rcti *rect)
char char size_t char const char * BLI_strchr_or_end(const char *str, char ch) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(1)
Definition string.cc:931
void BLI_task_graph_free(struct TaskGraph *task_graph)
struct TaskGraph * BLI_task_graph_create(void)
Definition task_graph.cc:96
void BLI_task_graph_work_and_wait(struct TaskGraph *task_graph)
Platform independent time functions.
double BLI_time_now_seconds(void)
Definition time.cc:113
#define ENUM_OPERATORS(_type, _max)
#define UNUSED_VARS_NDEBUG(...)
#define SET_FLAG_FROM_TEST(value, test, flag)
#define ELEM(...)
#define IFACE_(msgid)
eEvaluationMode
@ DAG_EVAL_RENDER
@ DAG_EVAL_VIEWPORT
#define DEG_OBJECT_ITER_BEGIN(settings_, instance_)
bool DEG_iterator_dupli_is_visible(const DupliObject *dupli, eEvaluationMode eval_mode)
#define DEG_OBJECT_ITER_END
Scene * DEG_get_evaluated_scene(const Depsgraph *graph)
eEvaluationMode DEG_get_mode(const Depsgraph *graph)
ViewLayer * DEG_get_evaluated_view_layer(const Depsgraph *graph)
#define DEG_OBJECT_ITER_FOR_RENDER_ENGINE_FLAGS
bool DEG_iterator_object_is_visible(eEvaluationMode eval_mode, const Object *ob)
T * DEG_get_original(T *id)
Scene * DEG_get_input_scene(const Depsgraph *graph)
bool DEG_id_type_any_exists(const Depsgraph *depsgraph, short id_type)
@ DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY
@ DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET
@ ID_GD_LEGACY
@ ID_GP
@ GREASE_PENCIL_STROKE_ORDER_3D
@ BASE_FROM_DUPLI
@ BASE_ENABLED_AND_VISIBLE_IN_DEFAULT_VIEWPORT
@ BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT
@ eModifierType_Fluid
eDrawType
@ OB_WIRE
@ OB_BOUNDBOX
@ OB_SOLID
@ OB_RENDER
@ OB_MATERIAL
#define OB_MODE_ALL_WEIGHT_PAINT
eObjectMode
@ OB_MODE_PARTICLE_EDIT
@ OB_MODE_EDIT
@ OB_MODE_WEIGHT_PAINT
@ OB_MODE_SCULPT
@ OB_MODE_POSE
@ OB_MODE_TEXTURE_PAINT
@ OB_MODE_OBJECT
@ OB_MODE_VERTEX_PAINT
@ OB_MBALL
@ OB_EMPTY
@ OB_SURF
@ OB_FONT
@ OB_GREASE_PENCIL
@ OB_ARMATURE
@ OB_MESH
@ OB_POINTCLOUD
@ OB_CURVES_LEGACY
@ OB_CURVES
struct ObjectRuntimeHandle ObjectRuntimeHandle
@ OB_DUPLI
@ OB_NEG_SCALE
@ PSYS_HAIR_DYNAMICS
@ PART_DRAW_PATH
@ PART_DRAW_REND
@ PTCACHE_BAKED
#define OBPOSE_FROM_OBACT(ob)
#define BASE_SELECTED(v3d, base)
@ PE_DRAW_PART
#define OBEDIT_FROM_OBACT(ob)
#define OBWEIGHTPAINT_FROM_OBACT(ob)
@ R_ADDSKY
@ SCE_OBJECT_MODE_LOCK
#define BASE_SELECTABLE(v3d, base)
@ RGN_TYPE_WINDOW
@ RGN_TYPE_XR
@ SI_SHOW_GPENCIL
@ SNODE_BACKDRAW
@ SPACE_NODE
@ SPACE_IMAGE
@ SPACE_VIEW3D
@ V3D_SHADING_USE_COMPOSITOR_CAMERA
@ V3D_SHADING_USE_COMPOSITOR_DISABLED
@ V3D_SHOW_VIEWER
@ V3D_XR_SHOW_CUSTOM_OVERLAYS
@ V3D_HIDE_OVERLAYS
@ V3D_SHOW_ANNOTATION
@ V3D_XR_SHOW_CONTROLLERS
@ V3D_SHADING_SCENE_WORLD_RENDER
@ V3D_SHADING_SCENE_WORLD
@ V3D_GIZMO_HIDE
@ RV3D_PAINTING
@ RV3D_NAVIGATING
@ V3D_XR_SESSION_SURFACE
@ V3D_XR_SESSION_MIRROR
@ RV3D_CAMOB
@ V3D_OVERLAY_BONE_SELECT
void DRW_submission_end()
bool DRW_render_check_grease_pencil(Depsgraph *depsgraph)
DRWData * DRW_viewport_data_create()
void DRW_draw_region_engine_info(int xoffset, int *yoffset, int line_height)
bool DRW_draw_in_progress()
void DRW_draw_view(const bContext *C)
void DRW_module_exit()
bool DRW_gpencil_engine_needed_viewport(Depsgraph *depsgraph, View3D *v3d)
bool(*)(Object *ob, void *user_data) DRW_ObjectFilterFn
Definition DRW_engine.hh:51
void DRW_draw_depth_loop(Depsgraph *depsgraph, ARegion *region, View3D *v3d, GPUViewport *viewport, const bool use_gpencil, const bool use_only_selected, const bool use_only_active_object)
void DRW_cache_free_old_batches(Main *bmain)
void DRW_draw_render_loop_offscreen(Depsgraph *depsgraph, RenderEngineType *engine_type, ARegion *region, View3D *v3d, bool is_image_render, bool draw_background, bool do_color_management, GPUOffScreen *ofs, GPUViewport *viewport)
void DRW_engines_free()
@ DRW_SELECT_PASS_POST
Definition DRW_engine.hh:48
@ DRW_SELECT_PASS_PRE
Definition DRW_engine.hh:47
void DRW_draw_select_loop(Depsgraph *depsgraph, ARegion *region, View3D *v3d, bool use_obedit_skip, bool draw_surface, bool use_nearest, bool do_material_sub_selection, const rcti *rect, DRW_SelectPassFn select_pass_fn, void *select_pass_user_data, DRW_ObjectFilterFn object_filter_fn, void *object_filter_user_data)
void DRW_render_context_disable(Render *render)
void DRW_viewport_data_free(DRWData *drw_data)
void DRW_module_init()
void DRW_submission_start()
void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *region, View3D *v3d)
void DRW_render_gpencil(RenderEngine *engine, Depsgraph *depsgraph)
void DRW_engines_register()
void DRW_render_context_enable(Render *render)
bool(*)(eDRWSelectStage stage, void *user_data) DRW_SelectPassFn
Definition DRW_engine.hh:50
void ED_region_pixelspace(const ARegion *region)
Definition area.cc:87
bScreen * ED_screen_animation_playing(const wmWindowManager *wm)
void ED_region_draw_cb_draw(const bContext *C, ARegion *region, int type)
#define REGION_DRAW_POST_VIEW
void ED_region_surface_draw_cb_draw(ARegionType *art, int type)
#define REGION_DRAW_PRE_VIEW
#define XRAY_ENABLED(v3d)
#define RETOPOLOGY_ENABLED(v3d)
void ED_view3d_init_mats_rv3d(const Object *ob, RegionView3D *rv3d)
RenderEngineType * ED_view3d_engine_type(const Scene *scene, int drawtype)
static AppView * view
void GPU_render_end()
void GPU_render_begin()
GPUContext * GPU_context_active_get()
GPUBackendType GPU_backend_get_type()
void GPU_debug_group_end()
Definition gpu_debug.cc:33
void GPU_debug_group_begin(const char *name)
Definition gpu_debug.cc:22
blender::gpu::FrameBuffer * GPU_framebuffer_create(const char *name)
#define GPU_FRAMEBUFFER_FREE_SAFE(fb)
#define GPU_ATTACHMENT_TEXTURE(_texture)
void GPU_offscreen_bind(GPUOffScreen *offscreen, bool save)
void GPU_framebuffer_restore()
void GPU_framebuffer_clear_depth_stencil(blender::gpu::FrameBuffer *fb, float clear_depth, uint clear_stencil)
blender::gpu::FrameBuffer * GPU_framebuffer_back_get()
#define GPU_ATTACHMENT_NONE
void GPU_framebuffer_free(blender::gpu::FrameBuffer *fb)
void GPU_framebuffer_texture_attach(blender::gpu::FrameBuffer *fb, blender::gpu::Texture *texture, int slot, int mip)
void GPU_clear_color(float red, float green, float blue, float alpha)
bool GPU_framebuffer_check_valid(blender::gpu::FrameBuffer *fb, char err_out[256])
void GPU_framebuffer_clear_depth(blender::gpu::FrameBuffer *fb, float clear_depth)
#define GPU_framebuffer_ensure_config(_fb,...)
void GPU_framebuffer_bind(blender::gpu::FrameBuffer *fb)
blender::gpu::FrameBuffer * GPU_framebuffer_active_get()
void GPU_matrix_identity_projection_set()
void GPU_matrix_identity_set()
#define GPU_matrix_set(x)
void GPU_matrix_push_projection()
void GPU_matrix_pop_projection()
#define GPU_matrix_projection_set(x)
@ GPU_DEVICE_ANY
@ GPU_DRIVER_ANY
@ GPU_OS_ANY
bool GPU_type_matches_ex(GPUDeviceType device, GPUOSType os, GPUDriverType driver, GPUBackendType backend)
void GPU_flush()
Definition gpu_state.cc:305
@ GPU_DEPTH_LESS_EQUAL
Definition GPU_state.hh:114
@ GPU_DEPTH_NONE
Definition GPU_state.hh:111
void GPU_finish()
Definition gpu_state.cc:310
@ GPU_BLEND_NONE
Definition GPU_state.hh:85
@ GPU_BLEND_ALPHA_PREMULT
Definition GPU_state.hh:88
void GPU_blend(GPUBlend blend)
Definition gpu_state.cc:42
void GPU_depth_test(GPUDepthTest test)
Definition gpu_state.cc:68
void GPU_viewport(int x, int y, int width, int height)
Definition gpu_state.cc:199
void GPU_apply_state()
Definition gpu_state.cc:315
int GPU_texture_height(const blender::gpu::Texture *texture)
int GPU_texture_width(const blender::gpu::Texture *texture)
eGPUTextureUsage
@ GPU_TEXTURE_USAGE_SHADER_READ
@ GPU_TEXTURE_USAGE_ATTACHMENT
#define GPU_TEXTURE_FREE_SAFE(texture)
blender::gpu::Texture * GPU_texture_create_2d(const char *name, int width, int height, int mip_len, blender::gpu::TextureFormat format, eGPUTextureUsage usage, const float *data)
void GPU_texture_free(blender::gpu::Texture *texture)
void GPU_viewport_unbind_from_offscreen(GPUViewport *viewport, GPUOffScreen *ofs, bool display_colorspace, bool do_overlay_merge)
GPUViewport * GPU_viewport_create()
void GPU_viewport_bind_from_offscreen(GPUViewport *viewport, GPUOffScreen *ofs, bool is_xr_surface)
int GPU_viewport_active_view_get(GPUViewport *viewport)
void GPU_viewport_free(GPUViewport *viewport)
void GPU_viewport_tag_update(GPUViewport *viewport)
blender::gpu::Texture * GPU_viewport_color_texture(GPUViewport *viewport, int view)
blender::gpu::Texture * GPU_viewport_depth_texture(GPUViewport *viewport)
DRWData ** GPU_viewport_data_get(GPUViewport *viewport)
@ RE_INTERNAL
Definition RE_engine.h:43
#define C
Definition RandGen.cpp:29
void UI_SetTheme(int spacetype, int regionid)
void ED_annotation_draw_view3d(Scene *scene, Depsgraph *depsgraph, View3D *v3d, ARegion *region, bool only3d)
void ED_annotation_draw_view2d(const bContext *C, bool onlyv2d)
bool operator==(const AssetWeakReference &a, const AssetWeakReference &b)
#define U
iter begin(iter)
BMesh const char void * data
BPy_StructRNA * depsgraph
unsigned long long int uint64_t
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
Value & lookup_or_add_cb(const Key &key, const CreateValueF &create_value)
Definition BLI_map.hh:620
void clear()
Definition BLI_map.hh:1038
Value & lookup_or_add_default(const Key &key)
Definition BLI_map.hh:639
ItemIterator items() const &
Definition BLI_map.hh:902
constexpr const char * c_str() const
ObjectRef(Object *ob, Object *dupli_parent=nullptr, DupliObject *dupli_object=nullptr)
static void default_set(const float4x4 &view_mat, const float4x4 &win_mat)
Definition draw_view.cc:322
void reset(bool force_free=false)
static TexturePool & get()
void DRW_smoke_begin_sync(DRWData *drw_data)
void DRW_smoke_exit(DRWData *drw_data)
static bool draw_show_annotation()
const DRWContext * DRW_context_get()
DRWData * DRW_viewport_data_create()
static void drw_draw_render_loop_2d(DRWContext &draw_ctx)
void DRW_custom_pipeline_begin(DRWContext &draw_ctx, Depsgraph *)
static void drw_draw_render_loop_3d(DRWContext &draw_ctx, RenderEngineType *engine_type)
static void drw_callbacks_post_scene(DRWContext &draw_ctx)
static void drw_callbacks_pre_scene(DRWContext &draw_ctx)
static void drw_callbacks_post_scene_2D(DRWContext &draw_ctx, View2D &v2d)
void DRW_cache_restart()
bool DRW_object_is_in_edit_mode(const Object *ob)
static void drw_engines_cache_populate(blender::draw::ObjectRef &ref, DupliCacheManager &dupli_cache, ExtractionGraph &extraction)
blender::draw::TextureFromPool & DRW_viewport_pass_texture_get(const char *pass_name)
void DRW_render_to_image(RenderEngine *engine, Depsgraph *depsgraph, std::function< void(RenderEngine *, RenderLayer *, const rcti)> render_view_cb, std::function< void(RenderResult *)> store_metadata_cb)
static DRWData * drw_viewport_data_ensure(GPUViewport *viewport)
bool DRW_object_use_hide_faces(const Object *ob)
void DRW_render_object_iter(RenderEngine *engine, Depsgraph *depsgraph, std::function< void(blender::draw::ObjectRef &, RenderEngine *, Depsgraph *)> callback)
bool DRW_object_is_renderable(const Object *ob)
DRWTextStore * DRW_text_cache_ensure()
static bool gpencil_object_is_excluded(View3D *v3d)
int DRW_object_visibility_in_active_context(const Object *ob)
bool DRW_object_is_visible_psys_in_active_context(const Object *object, const ParticleSystem *psys)
void DRW_viewport_data_free(DRWData *drw_data)
const Mesh * DRW_object_get_editmesh_cage_for_drawing(const Object &object)
static struct DRWSelectBuffer g_select_buffer
void DRW_render_set_time(RenderEngine *engine, Depsgraph *depsgraph, int frame, float subframe)
void DRW_custom_pipeline_end(DRWContext &draw_ctx)
void DRW_viewport_request_redraw()
static void draw_select_framebuffer_depth_only_setup(const int size[2])
static bool gpencil_any_exists(Depsgraph *depsgraph)
static void drw_callbacks_pre_scene_2D(DRWContext &draw_ctx)
DRWContext & drw_get()
blender::draw::Manager * DRW_manager_get()
DRWTextStore * DRW_text_cache_create()
void DRW_shaders_free()
void DRW_draw_region_info(const bContext *C, ARegion *region)
void DRW_draw_gizmo_3d(const bContext *C, ARegion *region)
void DRW_draw_gizmo_2d(const bContext *C, ARegion *region)
void DRW_view_data_default_lists_from_viewport(DRWViewData *view_data, GPUViewport *viewport)
void DRW_view_data_reset(DRWViewData *view_data)
void DRW_view_data_free_unused(DRWViewData *view_data)
RenderEngineType DRW_engine_viewport_eevee_type
bool DRW_engine_external_acquire_for_image_editor(const DRWContext *draw_ctx)
void RE_GetViewPlane(Render *re, rctf *r_viewplane, rcti *r_disprect)
void RE_engine_frame_set(RenderEngine *engine, int frame, float subframe)
RenderResult * RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h, const char *layername, const char *viewname)
RenderResult * RE_engine_get_result(RenderEngine *engine)
void RE_engines_register(RenderEngineType *render_type)
void RE_engine_end_result(RenderEngine *engine, RenderResult *result, bool cancel, bool highlight, bool merge_results)
CCL_NAMESPACE_BEGIN ccl_device float invert(const float color, const float factor)
Definition invert.h:11
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
#define G(x, y, z)
void viewport_color_management_set(GPUViewport &viewport, DRWContext &draw_ctx)
void DRW_curves_module_free(draw::CurvesModule *module)
void DRW_particle_batch_cache_free(ParticleSystem *psys)
void DRW_pointcloud_module_free(draw::PointCloudModule *module)
void DRW_lattice_batch_cache_dirty_tag(Lattice *lt, int mode)
static bool supports_handle_ranges(DupliObject *dupli, Object *parent)
void DRW_lattice_batch_cache_free(Lattice *lt)
void DRW_grease_pencil_batch_cache_free(GreasePencil *grease_pencil)
void drw_batch_cache_generate_requested_evaluated_mesh_or_curve(Object *ob, TaskGraph &task_graph)
void DRW_pointcloud_batch_cache_dirty_tag(PointCloud *pointcloud, int mode)
void DRW_curves_init(DRWData *drw_data=nullptr)
void drw_batch_cache_validate(Object *ob)
void DRW_subdiv_cache_free(bke::subdiv::Subdiv *subdiv)
void DRW_grease_pencil_batch_cache_dirty_tag(GreasePencil *grease_pencil, int mode)
void DRW_volume_batch_cache_free(Volume *volume)
void DRW_mesh_batch_cache_free(void *batch_cache)
void DRW_curves_update(draw::Manager &manager)
void DRW_volume_init(DRWData *drw_data=nullptr)
void DRW_volume_batch_cache_dirty_tag(Volume *volume, int mode)
void DRW_curve_batch_cache_free(Curve *cu)
void DRW_curves_begin_sync(DRWData *drw_data)
void drw_batch_cache_generate_requested(Object *ob, TaskGraph &task_graph)
void DRW_curves_batch_cache_dirty_tag(Curves *curves, int mode)
void DRW_pointcloud_init(DRWData *drw_data=nullptr)
void DRW_mesh_batch_cache_dirty_tag(Mesh *mesh, eMeshBatchDirtyMode mode)
void DRW_particle_batch_cache_dirty_tag(ParticleSystem *psys, int mode)
void DRW_pointcloud_batch_cache_free(PointCloud *pointcloud)
void DRW_batch_cache_free_old(Object *ob, int ctime)
static void foreach_obref_in_scene(DRWContext &draw_ctx, FunctionRef< bool(Object &)> should_draw_object_cb, FunctionRef< void(ObjectRef &)> draw_object_cb)
void DRW_volume_module_free(draw::VolumeModule *module)
void DRW_curves_batch_cache_free(Curves *curves)
void DRW_curve_batch_cache_dirty_tag(Curve *cu, int mode)
MatBase< float, 4, 4 > float4x4
uint64_t get_default_hash(const T &v, const Args &...args)
Definition BLI_hash.hh:233
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
void DEG_iterator_temp_object_free_properties(const DupliObject *dupli, Object *temp_object)
bool DEG_iterator_temp_object_from_dupli(const Object *dupli_parent, const DupliObject *dupli, eEvaluationMode eval_mode, bool do_matrix_setup, Object *r_temp_object, ObjectRuntimeHandle *r_temp_runtime)
#define hash
Definition noise_c.cc:154
SELECTID_Context * DRW_select_engine_context_get()
#define min(a, b)
Definition sort.cc:36
RenderLayer * RE_GetRenderLayer(RenderResult *rr, const char *name)
void RE_SetActiveRenderView(Render *re, const char *viewname)
void * regiondata
blender::Set< const Object * > * included_objects
const ViewerPath * viewer_path
bool is_image_render() const
DRWContext(Mode mode, Depsgraph *depsgraph, GPUViewport *viewport, const bContext *C=nullptr, ARegion *region=nullptr, View3D *v3d=nullptr)
bool is_playback() const
DRWViewData * view_data_active
static bool is_active()
Object * object_edit
std::function< void(struct DupliCacheManager &, struct ExtractionGraph &)> iter_callback_t
GSet * delayed_extraction
bool draw_background
void sync(iter_callback_t iter_callback)
DefaultFramebufferList * viewport_framebuffer_list_get() const
DRWData * data
View3D * v3d
Depsgraph * depsgraph
bool is_scene_render() const
DRWTextStore ** text_store_p
void enable_engines(bool gpencil_engine_needed=false, RenderEngineType *render_engine_type=nullptr)
RegionView3D * rv3d
@ DEPTH_ACTIVE_OBJECT
@ SELECT_OBJECT_MATERIAL
blender::float2 size
Object * obact
enum DRWContext::Mode mode
void engines_draw_scene()
Scene * scene
Object * object_pose
void acquire_data()
const bContext * evil_C
bool is_painting() const
void release_data()
ARegion * region
void engines_init_and_sync(iter_callback_t iter_callback)
SpaceLink * space_data
bool is_transforming() const
blender::gpu::FrameBuffer * default_framebuffer()
DefaultTextureList * viewport_texture_list_get() const
GPUViewport * viewport
struct DRWContext::@137223300060360004345077367045216134275315355136 options
ViewLayer * view_layer
void engines_data_validate()
bool is_navigating() const
bool is_viewport_compositor_enabled() const
blender::draw::VolumeModule * volume_module
blender::draw::View * default_view
blender::draw::CurvesModule * curves_module
void modules_exit()
void modules_init()
blender::draw::PointCloudModule * pointcloud_module
DRWViewData * view_data[2]
void modules_begin_sync()
blender::gpu::Texture * texture_depth
blender::gpu::FrameBuffer * framebuffer_depth_only
blender::draw::external::Engine external
blender::draw::select::Engine object_select
blender::Map< std::string, std::unique_ptr< blender::draw::TextureFromPool > > viewport_compositor_passes
void foreach_enabled_engine(CallbackT callback)
blender::workbench::Engine workbench
blender::draw::compositor_engine::Engine compositor
blender::draw::gpencil::Engine grease_pencil
blender::image_engine::Engine image
blender::draw::overlay::Engine overlay
blender::draw::edit_select::Engine edit_select
blender::eevee::Engine eevee
blender::gpu::FrameBuffer * overlay_fb
blender::gpu::Texture * depth
void set_used(bool used)
virtual void begin_sync()=0
virtual void object_sync(blender::draw::ObjectRef &ob_ref, blender::draw::Manager &manager)=0
virtual void draw(blender::draw::Manager &manager)=0
virtual void init()=0
char info[GPU_INFO_SIZE]
Definition DRW_render.hh:72
virtual blender::StringRefNull name_get()=0
virtual void end_sync()=0
void try_add(blender::draw::ObjectRef &ob_ref)
void extract_all(ExtractionGraph &extraction)
TaskGraph * graph
void work_and_wait(GSet *&delayed_extraction)
Definition DNA_ID.h:414
void * next
Definition DNA_ID.h:417
void * first
ListBase scenes
Definition BKE_main.hh:278
ListBase particlesystem
short transflag
short base_flag
ObjectRuntimeHandle * runtime
LightLinking * light_linking
ParticleSettings * part
struct PointCache * pointcache
float viewmat[4][4]
float winmat[4][4]
struct Render * re
Definition RE_engine.h:137
ListBase views
ListBase layers
struct RenderView * next
Definition RE_pipeline.h:41
blender::Vector< Object * > objects
struct ToolSettings * toolsettings
struct RenderData r
ListBase view_layers
struct ParticleEditSettings particle
View3DOverlay overlay
ViewerPath viewer_path
int object_type_exclude_select
int object_type_exclude_viewport
View3DShading shading
char name[64]
const c_style_mat & ptr() const
InstancesKey(Object *object, ID *ob_data, InstancesFlags flags, const blender::bke::GeometrySet *preview_base_geometry, int preview_instance_index)
bool operator==(const InstancesKey &k) const
const blender::bke::GeometrySet * preview_base_geometry
static void set(DRWState state=DRW_STATE_DEFAULT)
static void render_to_image(RenderEngine *engine, RenderLayer *render_layer, const rcti rect)
static void free_static()
float xmax
float xmin
float ymax
float ymin
i
Definition text_draw.cc:230
static void draw_background(const rcti *rect)
GPUViewport * WM_draw_region_get_viewport(ARegion *region)
Definition wm_draw.cc:940
GPUViewport * WM_draw_region_get_bound_viewport(ARegion *region)
Definition wm_draw.cc:950
void wmOrtho2(float x1, float x2, float y1, float y2)
ARegionType * WM_xr_surface_controller_region_type_get()
RenderEngineType DRW_engine_viewport_workbench_type