diff options
author | mano-wii <germano.costa@ig.com.br> | 2019-08-15 16:31:54 +0300 |
---|---|---|
committer | mano-wii <germano.costa@ig.com.br> | 2019-08-15 16:31:54 +0300 |
commit | 4d320f43133b02a43212b017eecdb390476189f2 (patch) | |
tree | 33ce479a4f9185724dcce31f4b70b335161c2b32 /source/blender | |
parent | 261a02fc596db0e91667d4e3af9204b165ec4006 (diff) |
Edit Mesh Selection: Refactor: Redraw idmap buffer at runtime with only objects inside the rect
But in the future the selection code may also be used in object mode (eg for snapping).
So to avoid using too much VRAM resources, it is good to avoid drawing all objects in the viewport.
The solution was to create an array with only objects that are detected within the selection area.
If the selection operator is modal, objects already detected are not removed from the array until view3d is moved or orbited.
To detect the object, its BoundBox is tested.
Since the Select Engine does not have a dedicated depth texture, whenever a new object is "found" the depth of the objects in the array already drawn is redrawn.
Reviewers: campbellbarton, fclem
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D5435
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/draw/DRW_engine.h | 4 | ||||
-rw-r--r-- | source/blender/draw/DRW_select_buffer.h | 83 | ||||
-rw-r--r-- | source/blender/draw/engines/select/select_draw_utils.c | 44 | ||||
-rw-r--r-- | source/blender/draw/engines/select/select_engine.c | 145 | ||||
-rw-r--r-- | source/blender/draw/engines/select/select_private.h | 6 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_manager.c | 30 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_select_buffer.c | 225 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_select.c | 14 | ||||
-rw-r--r-- | source/blender/editors/mesh/meshtools.c | 10 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_utils.c | 2 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_draw_legacy.c | 3 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_select.c | 139 |
12 files changed, 467 insertions, 238 deletions
diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h index 53cec599b82..6cae9ceb7d6 100644 --- a/source/blender/draw/DRW_engine.h +++ b/source/blender/draw/DRW_engine.h @@ -141,9 +141,7 @@ void DRW_draw_depth_object(struct ARegion *ar, void DRW_draw_select_id(struct Depsgraph *depsgraph, struct ARegion *ar, struct View3D *v3d, - struct Base **bases, - const uint bases_len, - short select_mode); + const struct rcti *rect); /* grease pencil render */ bool DRW_render_check_grease_pencil(struct Depsgraph *depsgraph); diff --git a/source/blender/draw/DRW_select_buffer.h b/source/blender/draw/DRW_select_buffer.h index ff40508b1a1..4aa1c403710 100644 --- a/source/blender/draw/DRW_select_buffer.h +++ b/source/blender/draw/DRW_select_buffer.h @@ -33,6 +33,13 @@ struct View3D; struct ViewLayer; struct rcti; +typedef struct SELECTID_ObjectData { + DrawData dd; + + uint drawn_index; + bool is_drawn; +} SELECTID_ObjectData; + struct ObjectOffsets { /* For convenience only. */ union { @@ -54,43 +61,75 @@ struct SELECTID_Context { struct GPUFrameBuffer *framebuffer_select_id; struct GPUTexture *texture_u32; - struct ObjectOffsets *index_offsets; + /* All context objects */ + struct Object **objects; uint objects_len; - uint last_object_drawn; - /** Total number of items `base_array_index_offsets[bases_len - 1].vert`. */ - uint last_index_drawn; + + /* Array with only drawn objects. When a new object is found within the rect, + * it is added to the end of the list. + * The list is reset to any viewport or context update. */ + struct ObjectOffsets *index_offsets; + struct Object **objects_drawn; + uint objects_drawn_len; + + /** Total number of element indices `index_offsets[object_drawn_len - 1].vert`. */ + uint index_drawn_len; short select_mode; + + /* To check for updates. */ + float persmat[4][4]; + bool is_dirty; + + /* rect is used to check which objects whose indexes need to be drawn. */ + rcti last_rect; }; -/* select_buffer.c */ -void DRW_select_buffer_context_create(struct Base **bases, - const uint bases_len, - short select_mode); +/* draw_select_buffer.c */ bool DRW_select_buffer_elem_get(const uint sel_id, uint *r_elem, uint *r_base_index, char *r_elem_type); -uint DRW_select_buffer_context_offset_for_object_elem(const uint base_index, char elem_type); -uint *DRW_select_buffer_read(const struct rcti *rect, uint *r_buf_len); -void DRW_draw_select_id_object(struct Depsgraph *depsgraph, - struct ViewLayer *view_layer, - struct ARegion *ar, - struct View3D *v3d, - struct Object *ob, - short select_mode); -uint *DRW_select_buffer_bitmap_from_rect(const struct rcti *rect, uint *r_bitmap_len); -uint *DRW_select_buffer_bitmap_from_circle(const int center[2], +uint DRW_select_buffer_context_offset_for_object_elem(struct Depsgraph *depsgraph, + struct Object *object, + char elem_type); +uint *DRW_select_buffer_read(struct Depsgraph *depsgraph, + struct ARegion *ar, + struct View3D *v3d, + const rcti *rect, + uint *r_buf_len); +uint *DRW_select_buffer_bitmap_from_rect(struct Depsgraph *depsgraph, + struct ARegion *ar, + struct View3D *v3d, + const struct rcti *rect, + uint *r_bitmap_len); +uint *DRW_select_buffer_bitmap_from_circle(struct Depsgraph *depsgraph, + struct ARegion *ar, + struct View3D *v3d, + const int center[2], const int radius, uint *r_bitmap_len); -uint *DRW_select_buffer_bitmap_from_poly(const int poly[][2], +uint *DRW_select_buffer_bitmap_from_poly(struct Depsgraph *depsgraph, + struct ARegion *ar, + struct View3D *v3d, + const int poly[][2], const int poly_len, - const struct rcti *rect); -uint DRW_select_buffer_sample_point(const int center[2]); -uint DRW_select_buffer_find_nearest_to_point(const int center[2], + const struct rcti *rect, + uint *r_bitmap_len); +uint DRW_select_buffer_sample_point(struct Depsgraph *depsgraph, + struct ARegion *ar, + struct View3D *v3d, + const int center[2]); +uint DRW_select_buffer_find_nearest_to_point(struct Depsgraph *depsgraph, + struct ARegion *ar, + struct View3D *v3d, + const int center[2], const uint id_min, const uint id_max, uint *dist); +void DRW_select_buffer_context_create(struct Base **bases, + const uint bases_len, + short select_mode); /* select_engine.c */ struct SELECTID_Context *DRW_select_engine_context_get(void); diff --git a/source/blender/draw/engines/select/select_draw_utils.c b/source/blender/draw/engines/select/select_draw_utils.c index b65a158cdcf..268cd60a8aa 100644 --- a/source/blender/draw/engines/select/select_draw_utils.c +++ b/source/blender/draw/engines/select/select_draw_utils.c @@ -23,6 +23,8 @@ */ #include "BKE_editmesh.h" +#include "BKE_mesh.h" +#include "BKE_object.h" #include "DNA_mesh_types.h" #include "DNA_scene_types.h" @@ -42,7 +44,7 @@ /** \name Draw Utilities * \{ */ -void draw_select_framebuffer_select_id_setup(struct SELECTID_Context *select_ctx) +static void select_id_framebuffer_setup(struct SELECTID_Context *select_ctx) { DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); int size[2]; @@ -73,6 +75,32 @@ void draw_select_framebuffer_select_id_setup(struct SELECTID_Context *select_ctx } } +/* Remove all tags from drawn or culled objects. */ +void select_id_context_clear(struct SELECTID_Context *select_ctx) +{ + select_ctx->objects_drawn_len = 0; + select_ctx->index_drawn_len = 1; + select_id_framebuffer_setup(select_ctx); + GPU_framebuffer_bind(select_ctx->framebuffer_select_id); + GPU_framebuffer_clear_color_depth( + select_ctx->framebuffer_select_id, (const float[4]){0.0f}, 1.0f); +} + +void select_id_object_min_max(Object *obj, float r_min[3], float r_max[3]) +{ + BoundBox *bb; + BMEditMesh *em = BKE_editmesh_from_object(obj); + if (em) { + /* Use Object Texture Space. */ + bb = BKE_mesh_texspace_get(em->mesh_eval_cage, NULL, NULL, NULL); + } + else { + bb = BKE_object_boundbox_get(obj); + } + copy_v3_v3(r_min, bb->vec[0]); + copy_v3_v3(r_max, bb->vec[6]); +} + short select_id_get_object_select_mode(Scene *scene, Object *ob) { short r_select_mode = 0; @@ -132,7 +160,7 @@ static void draw_select_id_edit_mesh(SELECTID_StorageList *stl, if (draw_facedot) { struct GPUBatch *geom_facedots = DRW_mesh_batch_cache_get_facedots_with_select_id(me); - DRW_shgroup_call(face_shgrp, geom_facedots, ob); + DRW_shgroup_call_no_cull(face_shgrp, geom_facedots, ob); } *r_face_offset = initial_offset + em->bm->totface; } @@ -141,14 +169,14 @@ static void draw_select_id_edit_mesh(SELECTID_StorageList *stl, face_shgrp = stl->g_data->shgrp_face_unif; *r_face_offset = initial_offset; } - DRW_shgroup_call(face_shgrp, geom_faces, ob); + DRW_shgroup_call_no_cull(face_shgrp, geom_faces, ob); /* Unlike faces, only draw edges if edge select mode. */ if (select_mode & SCE_SELECT_EDGE) { struct GPUBatch *geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(me); DRWShadingGroup *edge_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_edge); DRW_shgroup_uniform_int_copy(edge_shgrp, "offset", *(int *)r_face_offset); - DRW_shgroup_call(edge_shgrp, geom_edges, ob); + DRW_shgroup_call_no_cull(edge_shgrp, geom_edges, ob); *r_edge_offset = *r_face_offset + em->bm->totedge; } else { @@ -162,7 +190,7 @@ static void draw_select_id_edit_mesh(SELECTID_StorageList *stl, struct GPUBatch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me); DRWShadingGroup *vert_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_vert); DRW_shgroup_uniform_int_copy(vert_shgrp, "offset", *(int *)r_edge_offset); - DRW_shgroup_call(vert_shgrp, geom_verts, ob); + DRW_shgroup_call_no_cull(vert_shgrp, geom_verts, ob); *r_vert_offset = *r_edge_offset + em->bm->totvert; } else { @@ -192,13 +220,13 @@ static void draw_select_id_mesh(SELECTID_StorageList *stl, face_shgrp = stl->g_data->shgrp_face_unif; *r_face_offset = initial_offset; } - DRW_shgroup_call(face_shgrp, geom_faces, ob); + DRW_shgroup_call_no_cull(face_shgrp, geom_faces, ob); if (select_mode & SCE_SELECT_EDGE) { struct GPUBatch *geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(me); DRWShadingGroup *edge_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_edge); DRW_shgroup_uniform_int_copy(edge_shgrp, "offset", *(int *)r_face_offset); - DRW_shgroup_call(edge_shgrp, geom_edges, ob); + DRW_shgroup_call_no_cull(edge_shgrp, geom_edges, ob); *r_edge_offset = *r_face_offset + me->totedge; } else { @@ -209,7 +237,7 @@ static void draw_select_id_mesh(SELECTID_StorageList *stl, struct GPUBatch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me); DRWShadingGroup *vert_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_vert); DRW_shgroup_uniform_int_copy(vert_shgrp, "offset", *r_edge_offset); - DRW_shgroup_call(vert_shgrp, geom_verts, ob); + DRW_shgroup_call_no_cull(vert_shgrp, geom_verts, ob); *r_vert_offset = *r_edge_offset + me->totvert; } else { diff --git a/source/blender/draw/engines/select/select_engine.c b/source/blender/draw/engines/select/select_engine.c index 67e926452b9..f437efe0c41 100644 --- a/source/blender/draw/engines/select/select_engine.c +++ b/source/blender/draw/engines/select/select_engine.c @@ -31,6 +31,11 @@ #include "DRW_engine.h" #include "DRW_select_buffer.h" +#include "DRW_select_buffer.h" + +#include "draw_cache_impl.h" +#include "draw_manager.h" + #include "select_private.h" #include "select_engine.h" @@ -41,6 +46,7 @@ static struct { SELECTID_Shaders sh_data[GPU_SHADER_CFG_LEN]; struct SELECTID_Context context; + uint runtime_new_objects; } e_data = {{{NULL}}}; /* Engine data */ /* Shaders */ @@ -90,8 +96,23 @@ static void select_engine_init(void *vedata) } { + /* Create view from a subregion */ + const DRWView *view_default = DRW_view_default_get(); + float viewmat[4][4], winmat[4][4], winmat_subregion[4][4]; + DRW_view_viewmat_get(view_default, viewmat, false); + DRW_view_winmat_get(view_default, winmat, false); + projmat_from_subregion(winmat, + (int[2]){draw_ctx->ar->winx, draw_ctx->ar->winy}, + e_data.context.last_rect.xmin, + e_data.context.last_rect.xmax, + e_data.context.last_rect.ymin, + e_data.context.last_rect.ymax, + winmat_subregion); + + stl->g_data->view_subregion = DRW_view_create(viewmat, winmat_subregion, NULL, NULL, NULL); + /* Create view with depth offset */ - stl->g_data->view_faces = (DRWView *)DRW_view_default_get(); + stl->g_data->view_faces = (DRWView *)view_default; stl->g_data->view_edges = DRW_view_create_with_zoffset(draw_ctx->rv3d, 1.0f); stl->g_data->view_verts = DRW_view_create_with_zoffset(draw_ctx->rv3d, 1.1f); } @@ -107,11 +128,19 @@ static void select_cache_init(void *vedata) if (e_data.context.select_mode == -1) { e_data.context.select_mode = select_id_get_object_select_mode(draw_ctx->scene, - OBACT(draw_ctx->view_layer)); + draw_ctx->obact); BLI_assert(e_data.context.select_mode != 0); } { + psl->depth_only_pass = DRW_pass_create("Depth Only Pass", DRW_STATE_DEFAULT); + stl->g_data->shgrp_depth_only = DRW_shgroup_create(sh_data->select_id_uniform, + psl->depth_only_pass); + + if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { + DRW_shgroup_state_enable(stl->g_data->shgrp_depth_only, DRW_STATE_CLIP_PLANES); + } + psl->select_id_face_pass = DRW_pass_create("Face Pass", DRW_STATE_DEFAULT); if (e_data.context.select_mode & SCE_SELECT_FACE) { @@ -157,29 +186,82 @@ static void select_cache_init(void *vedata) } } - e_data.context.last_object_drawn = 0; - e_data.context.last_index_drawn = 1; + /* Check if the viewport has changed. */ + float(*persmat)[4] = draw_ctx->rv3d->persmat; + e_data.context.is_dirty = !compare_m4m4(e_data.context.persmat, persmat, FLT_EPSILON); + if (e_data.context.is_dirty) { + copy_m4_m4(e_data.context.persmat, persmat); + select_id_context_clear(&e_data.context); + } + e_data.runtime_new_objects = 0; } static void select_cache_populate(void *vedata, Object *ob) { + SELECTID_StorageList *stl = ((SELECTID_Data *)vedata)->stl; const DRWContextState *draw_ctx = DRW_context_state_get(); - struct ObjectOffsets *base_ofs = - &e_data.context.index_offsets[e_data.context.last_object_drawn++]; - - uint offset = e_data.context.last_index_drawn; - - select_id_draw_object(vedata, - draw_ctx->v3d, - ob, - e_data.context.select_mode, - offset, - &base_ofs->vert, - &base_ofs->edge, - &base_ofs->face); - - base_ofs->offset = offset; - e_data.context.last_index_drawn = base_ofs->vert; + + SELECTID_ObjectData *sel_data = (SELECTID_ObjectData *)DRW_drawdata_get( + &ob->id, &draw_engine_select_type); + + if (!e_data.context.is_dirty && sel_data && sel_data->is_drawn) { + /* The object indices have already been drawn. Fill depth pass. + * Opti: Most of the time this depth pass is not used. */ + struct Mesh *me = ob->data; + struct GPUBatch *geom_faces; + if (e_data.context.select_mode & SCE_SELECT_FACE) { + geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me); + } + else { + geom_faces = DRW_mesh_batch_cache_get_surface(me); + } + DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_faces, ob->obmat); + + if (e_data.context.select_mode & SCE_SELECT_EDGE) { + struct GPUBatch *geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(me); + DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_edges, ob->obmat); + } + + if (e_data.context.select_mode & SCE_SELECT_VERTEX) { + struct GPUBatch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me); + DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_verts, ob->obmat); + } + return; + } + + float min[3], max[3]; + select_id_object_min_max(ob, min, max); + + if (DRW_culling_min_max_test(stl->g_data->view_subregion, ob->obmat, min, max)) { + if (sel_data == NULL) { + sel_data = (SELECTID_ObjectData *)DRW_drawdata_ensure( + &ob->id, &draw_engine_select_type, sizeof(SELECTID_ObjectData), NULL, NULL); + } + sel_data->drawn_index = e_data.context.objects_drawn_len; + sel_data->is_drawn = true; + + struct ObjectOffsets *ob_offsets = + &e_data.context.index_offsets[e_data.context.objects_drawn_len]; + + uint offset = e_data.context.index_drawn_len; + select_id_draw_object(vedata, + draw_ctx->v3d, + ob, + e_data.context.select_mode, + offset, + &ob_offsets->vert, + &ob_offsets->edge, + &ob_offsets->face); + + ob_offsets->offset = offset; + e_data.context.index_drawn_len = ob_offsets->vert; + e_data.context.objects_drawn[e_data.context.objects_drawn_len] = ob; + e_data.context.objects_drawn_len++; + e_data.runtime_new_objects++; + } + else if (sel_data) { + sel_data->is_drawn = false; + } } static void select_draw_scene(void *vedata) @@ -187,17 +269,26 @@ static void select_draw_scene(void *vedata) SELECTID_StorageList *stl = ((SELECTID_Data *)vedata)->stl; SELECTID_PassList *psl = ((SELECTID_Data *)vedata)->psl; - /* Setup framebuffer */ - draw_select_framebuffer_select_id_setup(&e_data.context); - GPU_framebuffer_bind(e_data.context.framebuffer_select_id); + if (!e_data.runtime_new_objects) { + /* Nothing new needs to be drawn. */ + return; + } /* dithering and AA break color coding, so disable */ glDisable(GL_DITHER); - GPU_framebuffer_clear_color_depth( - e_data.context.framebuffer_select_id, (const float[4]){0.0f}, 1.0f); - DRW_view_set_active(stl->g_data->view_faces); + + if (!DRW_pass_is_empty(psl->depth_only_pass)) { + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + GPU_framebuffer_bind(dfbl->depth_only_fb); + GPU_framebuffer_clear_depth(dfbl->depth_only_fb, 1.0f); + DRW_draw_pass(psl->depth_only_pass); + } + + /* Setup framebuffer */ + GPU_framebuffer_bind(e_data.context.framebuffer_select_id); + DRW_draw_pass(psl->select_id_face_pass); if (e_data.context.select_mode & SCE_SELECT_EDGE) { @@ -221,7 +312,9 @@ static void select_engine_free(void) DRW_TEXTURE_FREE_SAFE(e_data.context.texture_u32); GPU_FRAMEBUFFER_FREE_SAFE(e_data.context.framebuffer_select_id); + MEM_SAFE_FREE(e_data.context.objects); MEM_SAFE_FREE(e_data.context.index_offsets); + MEM_SAFE_FREE(e_data.context.objects_drawn); } /** \} */ diff --git a/source/blender/draw/engines/select/select_private.h b/source/blender/draw/engines/select/select_private.h index d95b14ff2b6..e48ce4314ae 100644 --- a/source/blender/draw/engines/select/select_private.h +++ b/source/blender/draw/engines/select/select_private.h @@ -32,6 +32,7 @@ typedef struct SELECTID_StorageList { } SELECTID_StorageList; typedef struct SELECTID_PassList { + struct DRWPass *depth_only_pass; struct DRWPass *select_id_face_pass; struct DRWPass *select_id_edge_pass; struct DRWPass *select_id_vert_pass; @@ -52,18 +53,21 @@ typedef struct SELECTID_Shaders { } SELECTID_Shaders; typedef struct SELECTID_PrivateData { + DRWShadingGroup *shgrp_depth_only; DRWShadingGroup *shgrp_face_unif; DRWShadingGroup *shgrp_face_flat; DRWShadingGroup *shgrp_edge; DRWShadingGroup *shgrp_vert; + DRWView *view_subregion; DRWView *view_faces; DRWView *view_edges; DRWView *view_verts; } SELECTID_PrivateData; /* Transient data */ /* select_draw_utils.c */ -void draw_select_framebuffer_select_id_setup(struct SELECTID_Context *r_select_ctx); +void select_id_context_clear(struct SELECTID_Context *select_ctx); +void select_id_object_min_max(struct Object *obj, float r_min[3], float r_max[3]); short select_id_get_object_select_mode(Scene *scene, Object *ob); void select_id_draw_object(void *vedata, View3D *v3d, diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 070713ad404..1046e0422c1 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -2555,20 +2555,11 @@ void DRW_draw_depth_loop_gpencil(struct Depsgraph *depsgraph, DRW_opengl_context_disable(); } -void DRW_draw_select_id(Depsgraph *depsgraph, - ARegion *ar, - View3D *v3d, - Base **bases, - const uint bases_len, - short select_mode) +void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *ar, View3D *v3d, const rcti *rect) { Scene *scene = DEG_get_evaluated_scene(depsgraph); ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); - DRW_select_buffer_context_create(bases, bases_len, select_mode); - - DRW_opengl_context_enable(); - /* Reset before using it. */ drw_state_prepare_clean_for_draw(&DST); DST.buffer_finish_called = true; @@ -2584,7 +2575,6 @@ void DRW_draw_select_id(Depsgraph *depsgraph, .depsgraph = depsgraph, }; - use_drw_engine(&draw_engine_select_type); drw_context_state_init(); /* Setup viewport */ @@ -2594,16 +2584,18 @@ void DRW_draw_select_id(Depsgraph *depsgraph, /* Update ubos */ DRW_globals_update(); - /* Init engines */ - drw_engines_init(); + /* Init Select Engine */ + struct SELECTID_Context *sel_ctx = DRW_select_engine_context_get(); + sel_ctx->last_rect = *rect; + use_drw_engine(&draw_engine_select_type); + drw_engines_init(); { drw_engines_cache_init(); - /* Keep `base_index` in sync with `e_data.context.last_base_drawn`. - * So don't skip objects. */ - for (uint base_index = 0; base_index < bases_len; base_index++) { - Object *obj_eval = DEG_get_evaluated_object(depsgraph, bases[base_index]->object); + Object **obj = &sel_ctx->objects[0]; + for (uint remaining = sel_ctx->objects_len; remaining--; obj++) { + Object *obj_eval = DEG_get_evaluated_object(depsgraph, *obj); drw_engines_cache_populate(obj_eval); } @@ -2621,10 +2613,6 @@ void DRW_draw_select_id(Depsgraph *depsgraph, /* Avoid accidental reuse. */ drw_state_ensure_not_reused(&DST); #endif - - /* Changin context */ - GPU_framebuffer_restore(); - DRW_opengl_context_disable(); } /** See #DRW_shgroup_world_clip_planes_from_rv3d. */ diff --git a/source/blender/draw/intern/draw_select_buffer.c b/source/blender/draw/intern/draw_select_buffer.c index cd876b7b068..06bfd7a0d52 100644 --- a/source/blender/draw/intern/draw_select_buffer.c +++ b/source/blender/draw/intern/draw_select_buffer.c @@ -32,58 +32,81 @@ #include "GPU_select.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" + #include "DRW_engine.h" #include "DRW_select_buffer.h" #include "draw_manager.h" +#include "../engines/select/select_engine.h" + /* -------------------------------------------------------------------- */ /** \name Buffer of select ID's * \{ */ -/* Read a block of pixels from the select frame buffer. */ -uint *DRW_select_buffer_read(const rcti *rect, uint *r_buf_len) +/* Main function to read a block of pixels from the select frame buffer. */ +uint *DRW_select_buffer_read(struct Depsgraph *depsgraph, + struct ARegion *ar, + struct View3D *v3d, + const rcti *rect, + uint *r_buf_len) { - struct SELECTID_Context *select_ctx = DRW_select_engine_context_get(); + uint *r_buf = NULL; + uint buf_len = 0; - /* clamp rect by texture */ + /* Clamp rect. */ rcti r = { .xmin = 0, - .xmax = GPU_texture_width(select_ctx->texture_u32), + .xmax = ar->winx, .ymin = 0, - .ymax = GPU_texture_height(select_ctx->texture_u32), + .ymax = ar->winy, }; + /* Make sure that the rect is within the bounds of the viewport. + * Some GPUs have problems reading pixels off limits. */ rcti rect_clamp = *rect; if (BLI_rcti_isect(&r, &rect_clamp, &rect_clamp)) { - uint buf_len = BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect); - uint *r_buf = MEM_mallocN(buf_len * sizeof(*r_buf), __func__); + struct SELECTID_Context *select_ctx = DRW_select_engine_context_get(); DRW_opengl_context_enable(); - GPU_framebuffer_bind(select_ctx->framebuffer_select_id); - glReadBuffer(GL_COLOR_ATTACHMENT0); - glReadPixels(rect_clamp.xmin, - rect_clamp.ymin, - BLI_rcti_size_x(&rect_clamp), - BLI_rcti_size_y(&rect_clamp), - GL_RED_INTEGER, - GL_UNSIGNED_INT, - r_buf); + /* Update the drawing. */ + DRW_draw_select_id(depsgraph, ar, v3d, rect); + + if (select_ctx->index_drawn_len > 1) { + BLI_assert(ar->winx == GPU_texture_width(select_ctx->texture_u32) && + ar->winy == GPU_texture_height(select_ctx->texture_u32)); + + /* Read the UI32 pixels. */ + buf_len = BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect); + r_buf = MEM_mallocN(buf_len * sizeof(*r_buf), __func__); + + GPU_framebuffer_bind(select_ctx->framebuffer_select_id); + glReadBuffer(GL_COLOR_ATTACHMENT0); + glReadPixels(rect_clamp.xmin, + rect_clamp.ymin, + BLI_rcti_size_x(&rect_clamp), + BLI_rcti_size_y(&rect_clamp), + GL_RED_INTEGER, + GL_UNSIGNED_INT, + r_buf); + + if (!BLI_rcti_compare(rect, &rect_clamp)) { + /* The rect has been clamped so you need to realign the buffer and fill in the blanks */ + GPU_select_buffer_stride_realign(rect, &rect_clamp, r_buf); + } + } GPU_framebuffer_restore(); DRW_opengl_context_disable(); + } - if (!BLI_rcti_compare(rect, &rect_clamp)) { - GPU_select_buffer_stride_realign(rect, &rect_clamp, r_buf); - } - - if (r_buf_len) { - *r_buf_len = buf_len; - } - - return r_buf; + if (r_buf_len) { + *r_buf_len = buf_len; } - return NULL; + + return r_buf; } /** \} */ @@ -101,25 +124,27 @@ uint *DRW_select_buffer_read(const rcti *rect, uint *r_buf_len) * \param mask: Specifies the rect pixels (optional). * \returns a #BLI_bitmap the length of \a bitmap_len or NULL on failure. */ -uint *DRW_select_buffer_bitmap_from_rect(const rcti *rect, uint *r_bitmap_len) +uint *DRW_select_buffer_bitmap_from_rect(struct Depsgraph *depsgraph, + struct ARegion *ar, + struct View3D *v3d, + const rcti *rect, + uint *r_bitmap_len) { struct SELECTID_Context *select_ctx = DRW_select_engine_context_get(); - const uint bitmap_len = select_ctx->last_index_drawn; - if (bitmap_len == 0) { - return NULL; - } - rcti rect_px = *rect; rect_px.xmax += 1; rect_px.ymax += 1; uint buf_len; - uint *buf = DRW_select_buffer_read(&rect_px, &buf_len); + uint *buf = DRW_select_buffer_read(depsgraph, ar, v3d, &rect_px, &buf_len); if (buf == NULL) { return NULL; } + BLI_assert(select_ctx->index_drawn_len > 0); + const uint bitmap_len = select_ctx->index_drawn_len - 1; + BLI_bitmap *bitmap_buf = BLI_BITMAP_NEW(bitmap_len, __func__); const uint *buf_iter = buf; while (buf_len--) { @@ -144,17 +169,15 @@ uint *DRW_select_buffer_bitmap_from_rect(const rcti *rect, uint *r_bitmap_len) * \param radius: Circle radius. * \returns a #BLI_bitmap the length of \a bitmap_len or NULL on failure. */ -uint *DRW_select_buffer_bitmap_from_circle(const int center[2], +uint *DRW_select_buffer_bitmap_from_circle(struct Depsgraph *depsgraph, + struct ARegion *ar, + struct View3D *v3d, + const int center[2], const int radius, uint *r_bitmap_len) { struct SELECTID_Context *select_ctx = DRW_select_engine_context_get(); - const uint bitmap_len = select_ctx->last_index_drawn; - if (bitmap_len == 0) { - return NULL; - } - const rcti rect = { .xmin = center[0] - radius, .xmax = center[0] + radius + 1, @@ -162,15 +185,17 @@ uint *DRW_select_buffer_bitmap_from_circle(const int center[2], .ymax = center[1] + radius + 1, }; - const uint *buf = DRW_select_buffer_read(&rect, NULL); + const uint *buf = DRW_select_buffer_read(depsgraph, ar, v3d, &rect, NULL); if (buf == NULL) { return NULL; } - const uint *buf_iter = buf; + BLI_assert(select_ctx->index_drawn_len > 0); + const uint bitmap_len = select_ctx->index_drawn_len - 1; BLI_bitmap *bitmap_buf = BLI_BITMAP_NEW(bitmap_len, __func__); + const uint *buf_iter = buf; const int radius_sq = radius * radius; for (int yc = -radius; yc <= radius; yc++) { for (int xc = -radius; xc <= radius; xc++, buf_iter++) { @@ -214,21 +239,22 @@ static void drw_select_mask_px_cb(int x, int x_end, int y, void *user_data) * \param rect: Polygon boundaries. * \returns a #BLI_bitmap. */ -uint *DRW_select_buffer_bitmap_from_poly(const int poly[][2], const int poly_len, const rcti *rect) +uint *DRW_select_buffer_bitmap_from_poly(struct Depsgraph *depsgraph, + struct ARegion *ar, + struct View3D *v3d, + const int poly[][2], + const int poly_len, + const rcti *rect, + uint *r_bitmap_len) { struct SELECTID_Context *select_ctx = DRW_select_engine_context_get(); - const uint bitmap_len = select_ctx->last_index_drawn; - if (bitmap_len == 0) { - return NULL; - } - rcti rect_px = *rect; rect_px.xmax += 1; rect_px.ymax += 1; uint buf_len; - uint *buf = DRW_select_buffer_read(&rect_px, &buf_len); + uint *buf = DRW_select_buffer_read(depsgraph, ar, v3d, &rect_px, &buf_len); if (buf == NULL) { return NULL; } @@ -248,6 +274,9 @@ uint *DRW_select_buffer_bitmap_from_poly(const int poly[][2], const int poly_len drw_select_mask_px_cb, &poly_mask_data); + BLI_assert(select_ctx->index_drawn_len > 0); + const uint bitmap_len = select_ctx->index_drawn_len - 1; + BLI_bitmap *bitmap_buf = BLI_BITMAP_NEW(bitmap_len, __func__); const uint *buf_iter = buf; int i = 0; @@ -262,6 +291,10 @@ uint *DRW_select_buffer_bitmap_from_poly(const int poly[][2], const int poly_len MEM_freeN((void *)buf); MEM_freeN(buf_mask); + if (r_bitmap_len) { + *r_bitmap_len = bitmap_len; + } + return bitmap_buf; } @@ -277,8 +310,13 @@ uint *DRW_select_buffer_bitmap_from_poly(const int poly[][2], const int poly_len /** * Samples a single pixel. */ -uint DRW_select_buffer_sample_point(const int center[2]) +uint DRW_select_buffer_sample_point(struct Depsgraph *depsgraph, + struct ARegion *ar, + struct View3D *v3d, + const int center[2]) { + uint ret = 0; + const rcti rect = { .xmin = center[0], .xmax = center[0] + 1, @@ -287,10 +325,13 @@ uint DRW_select_buffer_sample_point(const int center[2]) }; uint buf_len; - uint *buf = DRW_select_buffer_read(&rect, &buf_len); - BLI_assert(0 != buf_len); - uint ret = buf[0]; - MEM_freeN(buf); + uint *buf = DRW_select_buffer_read(depsgraph, ar, v3d, &rect, &buf_len); + if (buf) { + BLI_assert(0 != buf_len); + ret = buf[0]; + MEM_freeN(buf); + } + return ret; } @@ -299,7 +340,10 @@ uint DRW_select_buffer_sample_point(const int center[2]) * \param dist[in,out]: Use to initialize the distance, * when found, this value is set to the distance of the selection that's returned. */ -uint DRW_select_buffer_find_nearest_to_point(const int center[2], +uint DRW_select_buffer_find_nearest_to_point(struct Depsgraph *depsgraph, + struct ARegion *ar, + struct View3D *v3d, + const int center[2], const uint id_min, const uint id_max, uint *dist) @@ -324,7 +368,7 @@ uint DRW_select_buffer_find_nearest_to_point(const int center[2], /* Read from selection framebuffer. */ uint buf_len; - const uint *buf = DRW_select_buffer_read(&rect, &buf_len); + const uint *buf = DRW_select_buffer_read(depsgraph, ar, v3d, &rect, &buf_len); if (buf == NULL) { return index; @@ -401,10 +445,10 @@ bool DRW_select_buffer_elem_get(const uint sel_id, struct SELECTID_Context *select_ctx = DRW_select_engine_context_get(); char elem_type = 0; - uint elem_id; + uint elem_id = 0; uint base_index = 0; - for (; base_index < select_ctx->objects_len; base_index++) { + for (; base_index < select_ctx->objects_drawn_len; base_index++) { struct ObjectOffsets *base_ofs = &select_ctx->index_offsets[base_index]; if (base_ofs->face > sel_id) { @@ -431,7 +475,8 @@ bool DRW_select_buffer_elem_get(const uint sel_id, *r_elem = elem_id; if (r_base_index) { - *r_base_index = base_index; + Object *obj_orig = DEG_get_original_object(select_ctx->objects_drawn[base_index]); + *r_base_index = obj_orig->runtime.select_id; } if (r_elem_type) { @@ -441,19 +486,31 @@ bool DRW_select_buffer_elem_get(const uint sel_id, return true; } -uint DRW_select_buffer_context_offset_for_object_elem(const uint base_index, char elem_type) +uint DRW_select_buffer_context_offset_for_object_elem(Depsgraph *depsgraph, + Object *object, + char elem_type) { struct SELECTID_Context *select_ctx = DRW_select_engine_context_get(); - struct ObjectOffsets *base_ofs = &select_ctx->index_offsets[base_index]; + + Object *ob_eval = DEG_get_evaluated_object(depsgraph, object); + + SELECTID_ObjectData *sel_data = (SELECTID_ObjectData *)DRW_drawdata_get( + &ob_eval->id, &draw_engine_select_type); + + if (!sel_data || !sel_data->is_drawn) { + return 0; + } + + struct ObjectOffsets *base_ofs = &select_ctx->index_offsets[sel_data->drawn_index]; if (elem_type == SCE_SELECT_VERTEX) { - return base_ofs->vert_start - 1; + return base_ofs->vert_start; } if (elem_type == SCE_SELECT_EDGE) { - return base_ofs->edge_start - 1; + return base_ofs->edge_start; } if (elem_type == SCE_SELECT_FACE) { - return base_ofs->face_start - 1; + return base_ofs->face_start; } BLI_assert(0); return 0; @@ -465,35 +522,29 @@ uint DRW_select_buffer_context_offset_for_object_elem(const uint base_index, cha /** \name Context * \{ */ -void DRW_select_buffer_context_create(Base **UNUSED(bases), - const uint bases_len, - short select_mode) +void DRW_select_buffer_context_create(Base **bases, const uint bases_len, short select_mode) { struct SELECTID_Context *select_ctx = DRW_select_engine_context_get(); - select_ctx->select_mode = select_mode; - select_ctx->objects_len = bases_len; + select_ctx->objects = MEM_reallocN(select_ctx->objects, + sizeof(*select_ctx->objects) * bases_len); - MEM_SAFE_FREE(select_ctx->index_offsets); - select_ctx->index_offsets = MEM_mallocN(sizeof(*select_ctx->index_offsets) * bases_len, - __func__); -} + select_ctx->index_offsets = MEM_reallocN(select_ctx->index_offsets, + sizeof(*select_ctx->index_offsets) * bases_len); -/** \} */ + select_ctx->objects_drawn = MEM_reallocN(select_ctx->objects_drawn, + sizeof(*select_ctx->objects_drawn) * bases_len); -/* -------------------------------------------------------------------- */ -/** \name Legacy - * \{ */ + for (uint base_index = 0; base_index < bases_len; base_index++) { + Object *obj = bases[base_index]->object; + select_ctx->objects[base_index] = obj; -void DRW_draw_select_id_object(Depsgraph *depsgraph, - ViewLayer *view_layer, - ARegion *ar, - View3D *v3d, - Object *ob, - short select_mode) -{ - Base *base = BKE_view_layer_base_find(view_layer, ob); - DRW_draw_select_id(depsgraph, ar, v3d, &base, 1, select_mode); -} + /* Weak but necessary for `DRW_select_buffer_elem_get`. */ + obj->runtime.select_id = base_index; + } + select_ctx->objects_len = bases_len; + select_ctx->select_mode = select_mode; + memset(select_ctx->persmat, 0, sizeof(select_ctx->persmat)); +} /** \} */ diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 2f4688e2de7..94ffd9a34d6 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -317,9 +317,10 @@ BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc, /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */ { - DRW_draw_select_id(vc->depsgraph, vc->ar, vc->v3d, bases, bases_len, SCE_SELECT_VERTEX); + DRW_select_buffer_context_create(bases, bases_len, SCE_SELECT_VERTEX); - index = DRW_select_buffer_find_nearest_to_point(vc->mval, 1, UINT_MAX, &dist_px); + index = DRW_select_buffer_find_nearest_to_point( + vc->depsgraph, vc->ar, vc->v3d, vc->mval, 1, UINT_MAX, &dist_px); if (index) { eve = (BMVert *)edbm_select_id_bm_elem_get(bases, index, &base_index); @@ -539,9 +540,10 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc, /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */ { - DRW_draw_select_id(vc->depsgraph, vc->ar, vc->v3d, bases, bases_len, SCE_SELECT_EDGE); + DRW_select_buffer_context_create(bases, bases_len, SCE_SELECT_EDGE); - index = DRW_select_buffer_find_nearest_to_point(vc->mval, 1, UINT_MAX, &dist_px); + index = DRW_select_buffer_find_nearest_to_point( + vc->depsgraph, vc->ar, vc->v3d, vc->mval, 1, UINT_MAX, &dist_px); if (index) { eed = (BMEdge *)edbm_select_id_bm_elem_get(bases, index, &base_index); @@ -745,9 +747,9 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc, BMFace *efa; { - DRW_draw_select_id(vc->depsgraph, vc->ar, vc->v3d, bases, bases_len, SCE_SELECT_FACE); + DRW_select_buffer_context_create(bases, bases_len, SCE_SELECT_FACE); - index = DRW_select_buffer_sample_point(vc->mval); + index = DRW_select_buffer_sample_point(vc->depsgraph, vc->ar, vc->v3d, vc->mval); if (index) { efa = (BMFace *)edbm_select_id_bm_elem_get(bases, index, &base_index); diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index 0bdc59c7185..8d9d0e40f44 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -1116,11 +1116,12 @@ bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], uint dist_px, if (dist_px) { /* sample rect to increase chances of selecting, so that when clicking * on an edge in the backbuf, we can still select a face */ - *r_index = DRW_select_buffer_find_nearest_to_point(mval, 1, me->totpoly + 1, &dist_px); + *r_index = DRW_select_buffer_find_nearest_to_point( + vc.depsgraph, vc.ar, vc.v3d, mval, 1, me->totpoly + 1, &dist_px); } else { /* sample only on the exact position */ - *r_index = DRW_select_buffer_sample_point(mval); + *r_index = DRW_select_buffer_sample_point(vc.depsgraph, vc.ar, vc.v3d, mval); } if ((*r_index) == 0 || (*r_index) > (unsigned int)me->totpoly) { @@ -1297,11 +1298,12 @@ bool ED_mesh_pick_vert( if (dist_px > 0) { /* sample rect to increase chances of selecting, so that when clicking * on an face in the backbuf, we can still select a vert */ - *r_index = DRW_select_buffer_find_nearest_to_point(mval, 1, me->totvert + 1, &dist_px); + *r_index = DRW_select_buffer_find_nearest_to_point( + vc.depsgraph, vc.ar, vc.v3d, mval, 1, me->totvert + 1, &dist_px); } else { /* sample only on the exact position */ - *r_index = DRW_select_buffer_sample_point(mval); + *r_index = DRW_select_buffer_sample_point(vc.depsgraph, vc.ar, vc.v3d, mval); } if ((*r_index) == 0 || (*r_index) > (uint)me->totvert) { diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index 806b7c471c6..4b9d9a2cc01 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -392,7 +392,7 @@ static int imapaint_pick_face(ViewContext *vc, /* sample only on the exact position */ ED_view3d_select_id_validate(vc); - *r_index = DRW_select_buffer_sample_point(mval); + *r_index = DRW_select_buffer_sample_point(vc->depsgraph, vc->ar, vc->v3d, mval); if ((*r_index) == 0 || (*r_index) > (unsigned int)totpoly) { return 0; diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c index 040b257bb90..02ad481e6ce 100644 --- a/source/blender/editors/space_view3d/view3d_draw_legacy.c +++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c @@ -185,7 +185,8 @@ static void validate_object_select_id( } if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE) != 0)) { - DRW_draw_select_id_object(depsgraph, view_layer, ar, v3d, obact, -1); + Base *base = BKE_view_layer_base_find(view_layer, obact); + DRW_select_buffer_context_create(&base, 1, -1); } /* TODO: Create a flag in `DRW_manager` because the drawing is no longer diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index a6728aef705..9a37c10180d 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -197,8 +197,6 @@ static bool object_deselect_all_except(ViewLayer *view_layer, Base *b) * \{ */ struct EditSelectBuf_Cache { - Base **bases; - uint bases_len; BLI_bitmap *select_bitmap; }; @@ -207,33 +205,25 @@ static void editselect_buf_cache_init(struct EditSelectBuf_Cache *esel, short select_mode) { if (vc->obedit) { - esel->bases = BKE_view_layer_array_from_bases_in_edit_mode( - vc->view_layer, vc->v3d, &esel->bases_len); + uint bases_len = 0; + Base **bases = BKE_view_layer_array_from_bases_in_edit_mode( + vc->view_layer, vc->v3d, &bases_len); + + DRW_select_buffer_context_create(bases, bases_len, select_mode); + MEM_freeN(bases); } else { /* Use for paint modes, currently only a single object at a time. */ if (vc->obact) { - esel->bases = MEM_mallocN(sizeof(esel->bases), __func__); - esel->bases[0] = BKE_view_layer_base_find(vc->view_layer, vc->obact); - esel->bases_len = 1; - } - else { - esel->bases = NULL; - esel->bases_len = 0; + Base *base = BKE_view_layer_base_find(vc->view_layer, vc->obact); + DRW_select_buffer_context_create(&base, 1, select_mode); } } - - DRW_draw_select_id(vc->depsgraph, vc->ar, vc->v3d, esel->bases, esel->bases_len, select_mode); - - for (int i = 0; i < esel->bases_len; i++) { - esel->bases[i]->object->runtime.select_id = i; - } } static void editselect_buf_cache_free(struct EditSelectBuf_Cache *esel) { MEM_SAFE_FREE(esel->select_bitmap); - MEM_SAFE_FREE(esel->bases); } static void editselect_buf_cache_free_voidp(void *esel_voidp) @@ -260,6 +250,7 @@ static void editselect_buf_cache_init_with_generic_userdata(wmGenericUserData *w * \{ */ static bool edbm_backbuf_check_and_select_verts(struct EditSelectBuf_Cache *esel, + Depsgraph *depsgraph, Object *ob, BMEditMesh *em, const eSelectOp sel_op) @@ -269,9 +260,12 @@ static bool edbm_backbuf_check_and_select_verts(struct EditSelectBuf_Cache *esel bool changed = false; const BLI_bitmap *select_bitmap = esel->select_bitmap; - uint index = DRW_select_buffer_context_offset_for_object_elem(ob->runtime.select_id, - SCE_SELECT_VERTEX); + uint index = DRW_select_buffer_context_offset_for_object_elem(depsgraph, ob, SCE_SELECT_VERTEX); + if (index == 0) { + return false; + } + index -= 1; BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { const bool is_select = BM_elem_flag_test(eve, BM_ELEM_SELECT); @@ -288,6 +282,7 @@ static bool edbm_backbuf_check_and_select_verts(struct EditSelectBuf_Cache *esel } static bool edbm_backbuf_check_and_select_edges(struct EditSelectBuf_Cache *esel, + Depsgraph *depsgraph, Object *ob, BMEditMesh *em, const eSelectOp sel_op) @@ -297,9 +292,12 @@ static bool edbm_backbuf_check_and_select_edges(struct EditSelectBuf_Cache *esel bool changed = false; const BLI_bitmap *select_bitmap = esel->select_bitmap; - uint index = DRW_select_buffer_context_offset_for_object_elem(ob->runtime.select_id, - SCE_SELECT_EDGE); + uint index = DRW_select_buffer_context_offset_for_object_elem(depsgraph, ob, SCE_SELECT_EDGE); + if (index == 0) { + return false; + } + index -= 1; BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); @@ -316,6 +314,7 @@ static bool edbm_backbuf_check_and_select_edges(struct EditSelectBuf_Cache *esel } static bool edbm_backbuf_check_and_select_faces(struct EditSelectBuf_Cache *esel, + Depsgraph *depsgraph, Object *ob, BMEditMesh *em, const eSelectOp sel_op) @@ -325,9 +324,12 @@ static bool edbm_backbuf_check_and_select_faces(struct EditSelectBuf_Cache *esel bool changed = false; const BLI_bitmap *select_bitmap = esel->select_bitmap; - uint index = DRW_select_buffer_context_offset_for_object_elem(ob->runtime.select_id, - SCE_SELECT_FACE); + uint index = DRW_select_buffer_context_offset_for_object_elem(depsgraph, ob, SCE_SELECT_FACE); + if (index == 0) { + return false; + } + index -= 1; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { const bool is_select = BM_elem_flag_test(efa, BM_ELEM_SELECT); @@ -737,10 +739,12 @@ static void do_lasso_select_mesh__doSelectEdge_pass0(void *user_data, { struct LassoSelectUserData_ForMeshEdge *data_for_edge = user_data; LassoSelectUserData *data = data_for_edge->data; - const bool is_visible = (data_for_edge->esel ? - BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap, - data_for_edge->backbuf_offset + index) : - true); + bool is_visible = true; + if (data_for_edge->backbuf_offset) { + uint bitmap_inedx = data_for_edge->backbuf_offset + index - 1; + is_visible = BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap, bitmap_inedx); + } + const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); const bool is_inside = (is_visible && edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b) && @@ -761,10 +765,12 @@ static void do_lasso_select_mesh__doSelectEdge_pass1(void *user_data, { struct LassoSelectUserData_ForMeshEdge *data_for_edge = user_data; LassoSelectUserData *data = data_for_edge->data; - const bool is_visible = (data_for_edge->esel ? - BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap, - data_for_edge->backbuf_offset + index) : - true); + bool is_visible = true; + if (data_for_edge->backbuf_offset) { + uint bitmap_inedx = data_for_edge->backbuf_offset + index - 1; + is_visible = BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap, bitmap_inedx); + } + const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); const bool is_inside = (is_visible && BLI_lasso_is_edge_inside(data->mcords, data->moves, @@ -831,13 +837,15 @@ static bool do_lasso_select_mesh(ViewContext *vc, if (wm_userdata->data == NULL) { editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, ts->selectmode); esel = wm_userdata->data; - esel->select_bitmap = DRW_select_buffer_bitmap_from_poly(mcords, moves, &rect); + esel->select_bitmap = DRW_select_buffer_bitmap_from_poly( + vc->depsgraph, vc->ar, vc->v3d, mcords, moves, &rect, NULL); } } if (ts->selectmode & SCE_SELECT_VERTEX) { if (use_zbuf) { - data.is_changed |= edbm_backbuf_check_and_select_verts(esel, vc->obedit, vc->em, sel_op); + data.is_changed |= edbm_backbuf_check_and_select_verts( + esel, vc->depsgraph, vc->obedit, vc->em, sel_op); } else { mesh_foreachScreenVert( @@ -850,7 +858,7 @@ static bool do_lasso_select_mesh(ViewContext *vc, .data = &data, .esel = use_zbuf ? esel : NULL, .backbuf_offset = use_zbuf ? DRW_select_buffer_context_offset_for_object_elem( - vc->obedit->runtime.select_id, SCE_SELECT_EDGE) : + vc->depsgraph, vc->obedit, SCE_SELECT_EDGE) : 0, }; @@ -866,7 +874,8 @@ static bool do_lasso_select_mesh(ViewContext *vc, if (ts->selectmode & SCE_SELECT_FACE) { if (use_zbuf) { - data.is_changed |= edbm_backbuf_check_and_select_faces(esel, vc->obedit, vc->em, sel_op); + data.is_changed |= edbm_backbuf_check_and_select_faces( + esel, vc->depsgraph, vc->obedit, vc->em, sel_op); } else { mesh_foreachScreenFace( @@ -1141,7 +1150,8 @@ static bool do_lasso_select_paintvert(ViewContext *vc, if (wm_userdata->data == NULL) { editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, SCE_SELECT_VERTEX); esel = wm_userdata->data; - esel->select_bitmap = DRW_select_buffer_bitmap_from_poly(mcords, moves, &rect); + esel->select_bitmap = DRW_select_buffer_bitmap_from_poly( + vc->depsgraph, vc->ar, vc->v3d, mcords, moves, &rect, NULL); } } @@ -1199,7 +1209,8 @@ static bool do_lasso_select_paintface(ViewContext *vc, if (esel == NULL) { editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, SCE_SELECT_FACE); esel = wm_userdata->data; - esel->select_bitmap = DRW_select_buffer_bitmap_from_poly(mcords, moves, &rect); + esel->select_bitmap = DRW_select_buffer_bitmap_from_poly( + vc->depsgraph, vc->ar, vc->v3d, mcords, moves, &rect, NULL); } if (esel->select_bitmap) { @@ -2554,7 +2565,8 @@ static bool do_paintvert_box_select(ViewContext *vc, if (wm_userdata->data == NULL) { editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, SCE_SELECT_VERTEX); esel = wm_userdata->data; - esel->select_bitmap = DRW_select_buffer_bitmap_from_rect(rect, NULL); + esel->select_bitmap = DRW_select_buffer_bitmap_from_rect( + vc->depsgraph, vc->ar, vc->v3d, rect, NULL); } if (esel->select_bitmap != NULL) { changed |= edbm_backbuf_check_and_select_verts_obmode(me, esel, sel_op); @@ -2608,7 +2620,8 @@ static bool do_paintface_box_select(ViewContext *vc, if (wm_userdata->data == NULL) { editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, SCE_SELECT_FACE); esel = wm_userdata->data; - esel->select_bitmap = DRW_select_buffer_bitmap_from_rect(rect, NULL); + esel->select_bitmap = DRW_select_buffer_bitmap_from_rect( + vc->depsgraph, vc->ar, vc->v3d, rect, NULL); } if (esel->select_bitmap != NULL) { changed |= edbm_backbuf_check_and_select_faces_obmode(me, esel, sel_op); @@ -2731,10 +2744,12 @@ static void do_mesh_box_select__doSelectEdge_pass0( { struct BoxSelectUserData_ForMeshEdge *data_for_edge = userData; BoxSelectUserData *data = data_for_edge->data; - const bool is_visible = (data_for_edge->esel ? - BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap, - data_for_edge->backbuf_offset + index) : - true); + bool is_visible = true; + if (data_for_edge->backbuf_offset) { + uint bitmap_inedx = data_for_edge->backbuf_offset + index - 1; + is_visible = BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap, bitmap_inedx); + } + const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); const bool is_inside = (is_visible && edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b)); @@ -2750,10 +2765,12 @@ static void do_mesh_box_select__doSelectEdge_pass1( { struct BoxSelectUserData_ForMeshEdge *data_for_edge = userData; BoxSelectUserData *data = data_for_edge->data; - const bool is_visible = (data_for_edge->esel ? - BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap, - data_for_edge->backbuf_offset + index) : - true); + bool is_visible = true; + if (data_for_edge->backbuf_offset) { + uint bitmap_inedx = data_for_edge->backbuf_offset + index - 1; + is_visible = BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap, bitmap_inedx); + } + const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); const bool is_inside = (is_visible && edge_inside_rect(data->rect_fl, screen_co_a, screen_co_b)); const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); @@ -2805,13 +2822,15 @@ static bool do_mesh_box_select(ViewContext *vc, if (wm_userdata->data == NULL) { editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, ts->selectmode); esel = wm_userdata->data; - esel->select_bitmap = DRW_select_buffer_bitmap_from_rect(rect, NULL); + esel->select_bitmap = DRW_select_buffer_bitmap_from_rect( + vc->depsgraph, vc->ar, vc->v3d, rect, NULL); } } if (ts->selectmode & SCE_SELECT_VERTEX) { if (use_zbuf) { - data.is_changed |= edbm_backbuf_check_and_select_verts(esel, vc->obedit, vc->em, sel_op); + data.is_changed |= edbm_backbuf_check_and_select_verts( + esel, vc->depsgraph, vc->obedit, vc->em, sel_op); } else { mesh_foreachScreenVert( @@ -2824,7 +2843,7 @@ static bool do_mesh_box_select(ViewContext *vc, .data = &data, .esel = use_zbuf ? esel : NULL, .backbuf_offset = use_zbuf ? DRW_select_buffer_context_offset_for_object_elem( - vc->obedit->runtime.select_id, SCE_SELECT_EDGE) : + vc->depsgraph, vc->obedit, SCE_SELECT_EDGE) : 0, }; @@ -2840,7 +2859,8 @@ static bool do_mesh_box_select(ViewContext *vc, if (ts->selectmode & SCE_SELECT_FACE) { if (use_zbuf) { - data.is_changed |= edbm_backbuf_check_and_select_faces(esel, vc->obedit, vc->em, sel_op); + data.is_changed |= edbm_backbuf_check_and_select_faces( + esel, vc->depsgraph, vc->obedit, vc->em, sel_op); } else { mesh_foreachScreenFace( @@ -3393,7 +3413,8 @@ static bool mesh_circle_select(ViewContext *vc, if (use_zbuf) { if (esel->select_bitmap == NULL) { - esel->select_bitmap = DRW_select_buffer_bitmap_from_circle(mval, (int)(rad + 1.0f), NULL); + esel->select_bitmap = DRW_select_buffer_bitmap_from_circle( + vc->depsgraph, vc->ar, vc->v3d, mval, (int)(rad + 1.0f), NULL); } } @@ -3401,7 +3422,7 @@ static bool mesh_circle_select(ViewContext *vc, if (use_zbuf) { if (esel->select_bitmap != NULL) { changed |= edbm_backbuf_check_and_select_verts( - esel, vc->obedit, vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); + esel, vc->depsgraph, vc->obedit, vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); } } else { @@ -3413,7 +3434,7 @@ static bool mesh_circle_select(ViewContext *vc, if (use_zbuf) { if (esel->select_bitmap != NULL) { changed |= edbm_backbuf_check_and_select_edges( - esel, vc->obedit, vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); + esel, vc->depsgraph, vc->obedit, vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); } } else { @@ -3426,7 +3447,7 @@ static bool mesh_circle_select(ViewContext *vc, if (use_zbuf) { if (esel->select_bitmap != NULL) { changed |= edbm_backbuf_check_and_select_faces( - esel, vc->obedit, vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); + esel, vc->depsgraph, vc->obedit, vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); } } else { @@ -3464,7 +3485,8 @@ static bool paint_facesel_circle_select(ViewContext *vc, { struct EditSelectBuf_Cache *esel = wm_userdata->data; - esel->select_bitmap = DRW_select_buffer_bitmap_from_circle(mval, (int)(rad + 1.0f), NULL); + esel->select_bitmap = DRW_select_buffer_bitmap_from_circle( + vc->depsgraph, vc->ar, vc->v3d, mval, (int)(rad + 1.0f), NULL); if (esel->select_bitmap != NULL) { changed |= edbm_backbuf_check_and_select_faces_obmode(me, esel, sel_op); MEM_freeN(esel->select_bitmap); @@ -3518,7 +3540,8 @@ static bool paint_vertsel_circle_select(ViewContext *vc, if (use_zbuf) { struct EditSelectBuf_Cache *esel = wm_userdata->data; - esel->select_bitmap = DRW_select_buffer_bitmap_from_circle(mval, (int)(rad + 1.0f), NULL); + esel->select_bitmap = DRW_select_buffer_bitmap_from_circle( + vc->depsgraph, vc->ar, vc->v3d, mval, (int)(rad + 1.0f), NULL); if (esel->select_bitmap != NULL) { changed |= edbm_backbuf_check_and_select_verts_obmode(me, esel, sel_op); MEM_freeN(esel->select_bitmap); |