Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormano-wii <germano.costa@ig.com.br>2019-07-30 12:46:59 +0300
committermano-wii <germano.costa@ig.com.br>2019-07-30 12:46:59 +0300
commit651d8bfd98db11eb58018412cc030cfe2705c519 (patch)
treec1d0dbd948383c61636261a1ad113d094577e97e /source/blender/draw
parenta85963bed86bb25b29a70f893cc9e9279a0b9d15 (diff)
3D View: Move selection API to a Selection engine.
This commit moves the API of selecting faces, vertices and edges to a DRW manager engine. Reviewers: campbellbarton, fclem Subscribers: jbakker, brecht Differential Revision: https://developer.blender.org/D5090
Diffstat (limited to 'source/blender/draw')
-rw-r--r--source/blender/draw/CMakeLists.txt5
-rw-r--r--source/blender/draw/DRW_engine.h36
-rw-r--r--source/blender/draw/engines/select/select_engine.c647
-rw-r--r--source/blender/draw/engines/select/select_engine.h29
-rw-r--r--source/blender/draw/engines/select/shaders/selection_id_3D_vert.glsl26
-rw-r--r--source/blender/draw/engines/select/shaders/selection_id_frag.glsl14
-rw-r--r--source/blender/draw/intern/draw_manager.c392
7 files changed, 818 insertions, 331 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 8631a9f556b..664484d9a57 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -126,6 +126,7 @@ set(SRC
engines/gpencil/gpencil_engine.h
engines/gpencil/gpencil_render.c
engines/gpencil/gpencil_shader_fx.c
+ engines/select/select_engine.c
DRW_engine.h
intern/DRW_render.h
@@ -150,6 +151,7 @@ set(SRC
engines/external/external_engine.h
engines/workbench/workbench_engine.h
engines/workbench/workbench_private.h
+ engines/select/select_engine.h
)
set(LIB
@@ -363,6 +365,9 @@ data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_shadow_resolve_frag.glsl
data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_swirl_frag.glsl SRC)
data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_wave_frag.glsl SRC)
+data_to_c_simple(engines/select/shaders/selection_id_3D_vert.glsl SRC)
+data_to_c_simple(engines/select/shaders/selection_id_frag.glsl SRC)
+
list(APPEND INC
)
diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h
index 5919e100ddd..64a02f3931b 100644
--- a/source/blender/draw/DRW_engine.h
+++ b/source/blender/draw/DRW_engine.h
@@ -26,6 +26,7 @@
#include "BLI_sys_types.h" /* for bool */
struct ARegion;
+struct Base;
struct DRWInstanceDataList;
struct DRWPass;
struct Depsgraph;
@@ -136,19 +137,12 @@ void DRW_draw_depth_loop_gpencil(struct Depsgraph *depsgraph,
void DRW_draw_depth_object(struct ARegion *ar,
struct GPUViewport *viewport,
struct Object *object);
-void DRW_draw_select_id_object(struct Scene *scene,
- struct RegionView3D *rv3d,
- struct Object *ob,
- short select_mode,
- bool draw_facedot,
- uint initial_offset,
- uint *r_vert_offset,
- uint *r_edge_offset,
- uint *r_face_offset);
-
-void DRW_framebuffer_select_id_setup(struct ARegion *ar, const bool clear);
-void DRW_framebuffer_select_id_release(struct ARegion *ar);
-void DRW_framebuffer_select_id_read(const struct rcti *rect, uint *r_buf);
+void DRW_draw_select_id(struct Depsgraph *depsgraph,
+ struct ARegion *ar,
+ struct View3D *v3d,
+ struct Base **bases,
+ const uint bases_len,
+ short select_mode);
/* grease pencil render */
bool DRW_render_check_grease_pencil(struct Depsgraph *depsgraph);
@@ -181,4 +175,20 @@ void DRW_deferred_shader_remove(struct GPUMaterial *mat);
struct DrawDataList *DRW_drawdatalist_from_id(struct ID *id);
void DRW_drawdata_free(struct ID *id);
+/* select_engine.c */
+void DRW_select_context_create(struct Depsgraph *depsgraph,
+ struct Base **bases,
+ const uint bases_len,
+ short select_mode);
+bool DRW_select_elem_get(const uint sel_id, uint *r_elem, uint *r_base_index, char *r_elem_type);
+uint DRW_select_context_offset_for_object_elem(const uint base_index, char elem_type);
+uint DRW_select_context_elem_len(void);
+void DRW_framebuffer_select_id_read(const struct rcti *rect, uint *r_buf);
+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);
+
#endif /* __DRW_ENGINE_H__ */
diff --git a/source/blender/draw/engines/select/select_engine.c b/source/blender/draw/engines/select/select_engine.c
new file mode 100644
index 00000000000..f1fc9cbc0d6
--- /dev/null
+++ b/source/blender/draw/engines/select/select_engine.c
@@ -0,0 +1,647 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2019, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup draw_engine
+ *
+ * Engine for drawing a selection map where the pixels indicate the selection indices.
+ */
+
+#include "BLI_rect.h"
+
+#include "BKE_editmesh.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_screen_types.h"
+
+#include "ED_view3d.h"
+
+#include "GPU_shader.h"
+#include "GPU_select.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
+#include "UI_resources.h"
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+#include "draw_cache_impl.h"
+
+#include "select_engine.h"
+/* Shaders */
+
+#define SELECT_ENGINE "SELECT_ENGINE"
+
+/* *********** LISTS *********** */
+
+/* GPUViewport.storage
+ * Is freed everytime the viewport engine changes */
+typedef struct SELECTID_StorageList {
+ struct SELECTID_PrivateData *g_data;
+} SELECTID_StorageList;
+
+typedef struct SELECTID_PassList {
+ struct DRWPass *select_id_face_pass;
+ struct DRWPass *select_id_edge_pass;
+ struct DRWPass *select_id_vert_pass;
+} SELECTID_PassList;
+
+typedef struct SELECTID_Data {
+ void *engine_type;
+ DRWViewportEmptyList *fbl;
+ DRWViewportEmptyList *txl;
+ SELECTID_PassList *psl;
+ SELECTID_StorageList *stl;
+} SELECTID_Data;
+
+typedef struct SELECTID_Shaders {
+ /* Depth Pre Pass */
+ struct GPUShader *select_id_flat;
+ struct GPUShader *select_id_uniform;
+} SELECTID_Shaders;
+
+/* *********** STATIC *********** */
+
+static struct {
+ SELECTID_Shaders sh_data[GPU_SHADER_CFG_LEN];
+
+ struct GPUFrameBuffer *framebuffer_select_id;
+ struct GPUTexture *texture_u32;
+
+ struct {
+ struct BaseOffset *base_array_index_offsets;
+ uint bases_len;
+ uint last_base_drawn;
+ /** Total number of items `base_array_index_offsets[bases_len - 1].vert`. */
+ uint last_index_drawn;
+
+ struct Depsgraph *depsgraph;
+ short select_mode;
+ } context;
+} e_data = {{{NULL}}}; /* Engine data */
+
+typedef struct SELECTID_PrivateData {
+ DRWShadingGroup *shgrp_face_unif;
+ DRWShadingGroup *shgrp_face_flat;
+ DRWShadingGroup *shgrp_edge;
+ DRWShadingGroup *shgrp_vert;
+
+ DRWView *view_faces;
+ DRWView *view_edges;
+ DRWView *view_verts;
+} SELECTID_PrivateData; /* Transient data */
+
+struct BaseOffset {
+ /* For convenience only. */
+ union {
+ uint offset;
+ uint face_start;
+ };
+ union {
+ uint face;
+ uint edge_start;
+ };
+ union {
+ uint edge;
+ uint vert_start;
+ };
+ uint vert;
+};
+
+/* Shaders */
+extern char datatoc_common_view_lib_glsl[];
+extern char datatoc_selection_id_3D_vert_glsl[];
+extern char datatoc_selection_id_frag_glsl[];
+
+/* -------------------------------------------------------------------- */
+/** \name Selection Utilities
+ * \{ */
+
+static void draw_select_framebuffer_select_id_setup(void)
+{
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+ int size[2];
+ size[0] = GPU_texture_width(dtxl->depth);
+ size[1] = GPU_texture_height(dtxl->depth);
+
+ if (e_data.framebuffer_select_id == NULL) {
+ e_data.framebuffer_select_id = GPU_framebuffer_create();
+ }
+
+ if ((e_data.texture_u32 != NULL) && ((GPU_texture_width(e_data.texture_u32) != size[0]) ||
+ (GPU_texture_height(e_data.texture_u32) != size[1]))) {
+
+ GPU_texture_free(e_data.texture_u32);
+ e_data.texture_u32 = NULL;
+ }
+
+ if (e_data.texture_u32 == NULL) {
+ e_data.texture_u32 = GPU_texture_create_2d(size[0], size[1], GPU_R32UI, NULL, NULL);
+
+ GPU_framebuffer_texture_attach(e_data.framebuffer_select_id, dtxl->depth, 0, 0);
+ GPU_framebuffer_texture_attach(e_data.framebuffer_select_id, e_data.texture_u32, 0, 0);
+ GPU_framebuffer_check_valid(e_data.framebuffer_select_id, NULL);
+ }
+}
+
+static void draw_select_id_object(void *vedata,
+ Object *ob,
+ short select_mode,
+ bool draw_facedot,
+ uint initial_offset,
+ uint *r_vert_offset,
+ uint *r_edge_offset,
+ uint *r_face_offset)
+{
+ SELECTID_StorageList *stl = ((SELECTID_Data *)vedata)->stl;
+
+ BLI_assert(initial_offset > 0);
+
+ switch (ob->type) {
+ case OB_MESH:
+ if (ob->mode & OB_MODE_EDIT) {
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_mesh;
+ const bool use_faceselect = (select_mode & SCE_SELECT_FACE) != 0;
+
+ DRW_mesh_batch_cache_validate(me);
+
+ BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE | BM_FACE);
+
+ struct GPUBatch *geom_faces, *geom_edges, *geom_verts, *geom_facedots;
+ geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me);
+ if (select_mode & SCE_SELECT_EDGE) {
+ geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(me);
+ }
+ if (select_mode & SCE_SELECT_VERTEX) {
+ geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me);
+ }
+ if (use_faceselect && draw_facedot) {
+ geom_facedots = DRW_mesh_batch_cache_get_facedots_with_select_id(me);
+ }
+ DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, true);
+
+ DRWShadingGroup *face_shgrp;
+ if (use_faceselect) {
+ face_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_face_flat);
+ DRW_shgroup_uniform_int_copy(face_shgrp, "offset", *(int *)&initial_offset);
+
+ if (draw_facedot) {
+ DRW_shgroup_call(face_shgrp, geom_facedots, ob);
+ }
+ *r_face_offset = initial_offset + em->bm->totface;
+ }
+ else {
+ face_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_face_unif);
+ DRW_shgroup_uniform_int_copy(face_shgrp, "id", 0);
+
+ *r_face_offset = initial_offset;
+ }
+ DRW_shgroup_call(face_shgrp, geom_faces, ob);
+
+ /* Unlike faces, only draw edges if edge select mode. */
+ if (select_mode & SCE_SELECT_EDGE) {
+ 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);
+ *r_edge_offset = *r_face_offset + em->bm->totedge;
+ }
+ else {
+ /* Note that `r_vert_offset` is calculated from `r_edge_offset`.
+ * Otherwise the first vertex is never selected, see: T53512. */
+ *r_edge_offset = *r_face_offset;
+ }
+
+ /* Unlike faces, only verts if vert select mode. */
+ if (select_mode & SCE_SELECT_VERTEX) {
+ 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);
+ *r_vert_offset = *r_edge_offset + em->bm->totvert;
+ }
+ else {
+ *r_vert_offset = *r_edge_offset;
+ }
+ }
+ else {
+ Mesh *me_orig = DEG_get_original_object(ob)->data;
+ Mesh *me_eval = ob->data;
+
+ DRW_mesh_batch_cache_validate(me_eval);
+ struct GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me_eval);
+ if ((me_orig->editflag & ME_EDIT_PAINT_VERT_SEL) &&
+ /* Currently vertex select supports weight paint and vertex paint. */
+ ((ob->mode & OB_MODE_WEIGHT_PAINT) || (ob->mode & OB_MODE_VERTEX_PAINT))) {
+
+ struct GPUBatch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me_eval);
+ DRW_mesh_batch_cache_create_requested(ob, me_eval, NULL, false, true);
+
+ /* Only draw faces to mask out verts, we don't want their selection ID's. */
+ DRWShadingGroup *face_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_face_unif);
+ DRW_shgroup_uniform_int_copy(face_shgrp, "id", 0);
+ DRW_shgroup_call(face_shgrp, geom_faces, ob);
+
+ DRWShadingGroup *vert_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_vert);
+ DRW_shgroup_uniform_int_copy(vert_shgrp, "offset", 1);
+ DRW_shgroup_call(vert_shgrp, geom_verts, ob);
+
+ *r_face_offset = *r_edge_offset = initial_offset;
+ *r_vert_offset = me_eval->totvert + 1;
+ }
+ else {
+ const bool use_hide = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL);
+ DRW_mesh_batch_cache_create_requested(ob, me_eval, NULL, false, use_hide);
+
+ DRWShadingGroup *face_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_face_flat);
+ DRW_shgroup_uniform_int_copy(face_shgrp, "offset", *(int *)&initial_offset);
+ DRW_shgroup_call(face_shgrp, geom_faces, ob);
+
+ *r_face_offset = initial_offset + me_eval->totpoly;
+ *r_edge_offset = *r_vert_offset = *r_face_offset;
+ }
+ }
+ break;
+ case OB_CURVE:
+ case OB_SURF:
+ break;
+ }
+}
+
+static bool check_ob_drawface_dot(short select_mode, const View3D *v3d, char dt)
+{
+ if (select_mode & SCE_SELECT_FACE) {
+ if ((dt < OB_SOLID) || XRAY_FLAG_ENABLED(v3d)) {
+ return true;
+ }
+ if (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_DOT) {
+ return true;
+ }
+ if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_EDGES) == 0) {
+ /* Since we can't deduce face selection when edges aren't visible - show dots. */
+ return true;
+ }
+ }
+ return false;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Engine Functions
+ * \{ */
+
+static void select_engine_init(void *vedata)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ eGPUShaderConfig sh_cfg = draw_ctx->sh_cfg;
+
+ SELECTID_StorageList *stl = ((SELECTID_Data *)vedata)->stl;
+ SELECTID_Shaders *sh_data = &e_data.sh_data[sh_cfg];
+
+ /* Prepass */
+ if (!sh_data->select_id_flat) {
+ const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[sh_cfg];
+ sh_data->select_id_flat = GPU_shader_create_from_arrays({
+ .vert = (const char *[]){sh_cfg_data->lib,
+ datatoc_common_view_lib_glsl,
+ datatoc_selection_id_3D_vert_glsl,
+ NULL},
+ .frag = (const char *[]){datatoc_selection_id_frag_glsl, NULL},
+ .defs = (const char *[]){sh_cfg_data->def, NULL},
+ });
+ }
+ if (!sh_data->select_id_uniform) {
+ const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[sh_cfg];
+ sh_data->select_id_uniform = GPU_shader_create_from_arrays({
+ .vert = (const char *[]){sh_cfg_data->lib,
+ datatoc_common_view_lib_glsl,
+ datatoc_selection_id_3D_vert_glsl,
+ NULL},
+ .frag = (const char *[]){datatoc_selection_id_frag_glsl, NULL},
+ .defs = (const char *[]){sh_cfg_data->def, "#define UNIFORM_ID\n", NULL},
+ });
+ }
+
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
+ }
+
+ {
+ /* Create view with depth offset */
+ stl->g_data->view_faces = (DRWView *)DRW_view_default_get();
+ 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);
+ }
+}
+
+static void select_cache_init(void *vedata)
+{
+ SELECTID_PassList *psl = ((SELECTID_Data *)vedata)->psl;
+ SELECTID_StorageList *stl = ((SELECTID_Data *)vedata)->stl;
+
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ SELECTID_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
+ {
+ psl->select_id_face_pass = DRW_pass_create("Face Pass", DRW_STATE_DEFAULT);
+ stl->g_data->shgrp_face_unif = DRW_shgroup_create(sh_data->select_id_uniform,
+ psl->select_id_face_pass);
+
+ stl->g_data->shgrp_face_flat = DRW_shgroup_create(sh_data->select_id_flat,
+ psl->select_id_face_pass);
+
+ psl->select_id_edge_pass = DRW_pass_create(
+ "Edge Pass", DRW_STATE_DEFAULT | DRW_STATE_FIRST_VERTEX_CONVENTION);
+
+ stl->g_data->shgrp_edge = DRW_shgroup_create(sh_data->select_id_flat,
+ psl->select_id_edge_pass);
+
+ psl->select_id_vert_pass = DRW_pass_create("Vert Pass", DRW_STATE_DEFAULT);
+ stl->g_data->shgrp_vert = DRW_shgroup_create(sh_data->select_id_flat,
+ psl->select_id_vert_pass);
+
+ DRW_shgroup_uniform_float_copy(stl->g_data->shgrp_vert, "sizeVertex", G_draw.block.sizeVertex);
+
+ if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) {
+ DRW_shgroup_state_enable(stl->g_data->shgrp_face_unif, DRW_STATE_CLIP_PLANES);
+ DRW_shgroup_state_enable(stl->g_data->shgrp_face_flat, DRW_STATE_CLIP_PLANES);
+ DRW_shgroup_state_enable(stl->g_data->shgrp_edge, DRW_STATE_CLIP_PLANES);
+ DRW_shgroup_state_enable(stl->g_data->shgrp_vert, DRW_STATE_CLIP_PLANES);
+ }
+ }
+
+ e_data.context.last_base_drawn = 0;
+ e_data.context.last_index_drawn = 1;
+}
+
+static void select_cache_populate(void *vedata, Object *ob)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ short select_mode = e_data.context.select_mode;
+
+ if (select_mode == -1) {
+ ToolSettings *ts = draw_ctx->scene->toolsettings;
+ select_mode = ts->selectmode;
+ }
+
+ bool draw_facedot = check_ob_drawface_dot(select_mode, draw_ctx->v3d, ob->dt);
+
+ struct BaseOffset *base_ofs =
+ &e_data.context.base_array_index_offsets[e_data.context.last_base_drawn++];
+
+ uint offset = e_data.context.last_index_drawn;
+
+ draw_select_id_object(vedata,
+ ob,
+ select_mode,
+ draw_facedot,
+ offset,
+ &base_ofs->vert,
+ &base_ofs->edge,
+ &base_ofs->face);
+
+ base_ofs->offset = offset;
+ e_data.context.last_index_drawn = base_ofs->vert;
+}
+
+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();
+ GPU_framebuffer_bind(e_data.framebuffer_select_id);
+
+ /* dithering and AA break color coding, so disable */
+ glDisable(GL_DITHER);
+
+ GPU_framebuffer_clear_color_depth(e_data.framebuffer_select_id, (const float[4]){0.0f}, 1.0f);
+
+ DRW_view_set_active(stl->g_data->view_faces);
+ DRW_draw_pass(psl->select_id_face_pass);
+
+ DRW_view_set_active(stl->g_data->view_edges);
+ DRW_draw_pass(psl->select_id_edge_pass);
+
+ DRW_view_set_active(stl->g_data->view_verts);
+ DRW_draw_pass(psl->select_id_vert_pass);
+}
+
+static void select_engine_free(void)
+{
+ for (int sh_data_index = 0; sh_data_index < ARRAY_SIZE(e_data.sh_data); sh_data_index++) {
+ SELECTID_Shaders *sh_data = &e_data.sh_data[sh_data_index];
+ DRW_SHADER_FREE_SAFE(sh_data->select_id_flat);
+ DRW_SHADER_FREE_SAFE(sh_data->select_id_uniform);
+ }
+
+ DRW_TEXTURE_FREE_SAFE(e_data.texture_u32);
+ GPU_FRAMEBUFFER_FREE_SAFE(e_data.framebuffer_select_id);
+ MEM_SAFE_FREE(e_data.context.base_array_index_offsets);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Exposed `DRW_engine.h` functions
+ * \{ */
+
+bool DRW_select_elem_get(const uint sel_id, uint *r_elem, uint *r_base_index, char *r_elem_type)
+{
+ char elem_type = 0;
+ uint elem_id;
+ uint base_index = 0;
+
+ for (; base_index < e_data.context.bases_len; base_index++) {
+ struct BaseOffset *base_ofs = &e_data.context.base_array_index_offsets[base_index];
+
+ if (base_ofs->face > sel_id) {
+ elem_id = sel_id - base_ofs->face_start;
+ elem_type = SCE_SELECT_FACE;
+ break;
+ }
+ if (base_ofs->edge > sel_id) {
+ elem_id = sel_id - base_ofs->edge_start;
+ elem_type = SCE_SELECT_EDGE;
+ break;
+ }
+ if (base_ofs->vert > sel_id) {
+ elem_id = sel_id - base_ofs->vert_start;
+ elem_type = SCE_SELECT_VERTEX;
+ break;
+ }
+ }
+
+ if (base_index == e_data.context.bases_len) {
+ return false;
+ }
+
+ *r_elem = elem_id;
+
+ if (r_base_index) {
+ *r_base_index = base_index;
+ }
+
+ if (r_elem_type) {
+ *r_elem_type = elem_type;
+ }
+
+ return true;
+}
+
+uint DRW_select_context_offset_for_object_elem(const uint base_index, char elem_type)
+{
+ struct BaseOffset *base_ofs = &e_data.context.base_array_index_offsets[base_index];
+
+ if (elem_type == SCE_SELECT_VERTEX) {
+ return base_ofs->vert_start - 1;
+ }
+ if (elem_type == SCE_SELECT_EDGE) {
+ return base_ofs->edge_start - 1;
+ }
+ if (elem_type == SCE_SELECT_FACE) {
+ return base_ofs->face_start - 1;
+ }
+ BLI_assert(0);
+ return 0;
+}
+
+uint DRW_select_context_elem_len(void)
+{
+ return e_data.context.last_index_drawn;
+}
+
+/* Read a block of pixels from the select frame buffer. */
+void DRW_framebuffer_select_id_read(const rcti *rect, uint *r_buf)
+{
+ /* clamp rect by texture */
+ rcti r = {
+ .xmin = 0,
+ .xmax = GPU_texture_width(e_data.texture_u32),
+ .ymin = 0,
+ .ymax = GPU_texture_height(e_data.texture_u32),
+ };
+
+ rcti rect_clamp = *rect;
+ if (BLI_rcti_isect(&r, &rect_clamp, &rect_clamp)) {
+ DRW_opengl_context_enable();
+ GPU_framebuffer_bind(e_data.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);
+
+ GPU_framebuffer_restore();
+ DRW_opengl_context_disable();
+
+ if (!BLI_rcti_compare(rect, &rect_clamp)) {
+ GPU_select_buffer_stride_realign(rect, &rect_clamp, r_buf);
+ }
+ }
+ else {
+ size_t buf_size = BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect) * sizeof(*r_buf);
+
+ memset(r_buf, 0, buf_size);
+ }
+}
+
+void DRW_select_context_create(Depsgraph *depsgraph,
+ Base **UNUSED(bases),
+ const uint bases_len,
+ short select_mode)
+{
+ e_data.context.depsgraph = depsgraph;
+ e_data.context.select_mode = select_mode;
+ e_data.context.bases_len = bases_len;
+
+ MEM_SAFE_FREE(e_data.context.base_array_index_offsets);
+ e_data.context.base_array_index_offsets = MEM_mallocN(
+ sizeof(*e_data.context.base_array_index_offsets) * bases_len, __func__);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Legacy
+ * \{ */
+
+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);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Engine Type
+ * \{ */
+
+static const DrawEngineDataSize select_data_size = DRW_VIEWPORT_DATA_SIZE(SELECTID_Data);
+
+DrawEngineType draw_engine_select_type = {
+ NULL,
+ NULL,
+ N_("Select ID"),
+ &select_data_size,
+ &select_engine_init,
+ &select_engine_free,
+ &select_cache_init,
+ &select_cache_populate,
+ NULL,
+ NULL,
+ &select_draw_scene,
+ NULL,
+ NULL,
+ NULL,
+};
+
+/* Note: currently unused, we may want to register so we can see this when debugging the view. */
+
+RenderEngineType DRW_engine_viewport_select_type = {
+ NULL,
+ NULL,
+ SELECT_ENGINE,
+ N_("Select ID"),
+ RE_INTERNAL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ &draw_engine_select_type,
+ {NULL, NULL, NULL},
+};
+
+/** \} */
+
+#undef SELECT_ENGINE
diff --git a/source/blender/draw/engines/select/select_engine.h b/source/blender/draw/engines/select/select_engine.h
new file mode 100644
index 00000000000..5b900ccaf27
--- /dev/null
+++ b/source/blender/draw/engines/select/select_engine.h
@@ -0,0 +1,29 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2019, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup draw_engine
+ */
+
+#ifndef __SELECT_ENGINE_H__
+#define __SELECT_ENGINE_H__
+
+extern DrawEngineType draw_engine_select_type;
+extern RenderEngineType DRW_engine_viewport_select_type;
+
+#endif /* __SELECT_ID_ENGINE_H__ */
diff --git a/source/blender/draw/engines/select/shaders/selection_id_3D_vert.glsl b/source/blender/draw/engines/select/shaders/selection_id_3D_vert.glsl
new file mode 100644
index 00000000000..9b0107cffdb
--- /dev/null
+++ b/source/blender/draw/engines/select/shaders/selection_id_3D_vert.glsl
@@ -0,0 +1,26 @@
+
+uniform float sizeVertex;
+
+in vec3 pos;
+
+#ifndef UNIFORM_ID
+uniform int offset;
+in uint color;
+
+flat out uint id;
+#endif
+
+void main()
+{
+#ifndef UNIFORM_ID
+ id = floatBitsToUint(intBitsToFloat(offset)) + color;
+#endif
+
+ vec3 world_pos = point_object_to_world(pos);
+ gl_Position = point_world_to_ndc(world_pos);
+ gl_PointSize = sizeVertex;
+
+#ifdef USE_WORLD_CLIP_PLANES
+ world_clip_planes_calc_clip_distance(world_pos);
+#endif
+}
diff --git a/source/blender/draw/engines/select/shaders/selection_id_frag.glsl b/source/blender/draw/engines/select/shaders/selection_id_frag.glsl
new file mode 100644
index 00000000000..ea86ddc7301
--- /dev/null
+++ b/source/blender/draw/engines/select/shaders/selection_id_frag.glsl
@@ -0,0 +1,14 @@
+
+#ifdef UNIFORM_ID
+uniform int id;
+# define id floatBitsToUint(intBitsToFloat(id))
+#else
+flat in uint id;
+#endif
+
+out uint fragColor;
+
+void main()
+{
+ fragColor = id;
+}
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 2841e017ef6..320a6f6aaaa 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -89,6 +89,7 @@
#include "engines/workbench/workbench_engine.h"
#include "engines/external/external_engine.h"
#include "engines/gpencil/gpencil_engine.h"
+#include "engines/select/select_engine.h"
#include "GPU_context.h"
@@ -2136,16 +2137,13 @@ void DRW_custom_pipeline(DrawEngineType *draw_engine_type,
static struct DRWSelectBuffer {
struct GPUFrameBuffer *framebuffer_depth_only;
- struct GPUFrameBuffer *framebuffer_select_id;
struct GPUTexture *texture_depth;
- struct GPUTexture *texture_u32;
} g_select_buffer = {NULL};
static void draw_select_framebuffer_depth_only_setup(const int size[2])
{
if (g_select_buffer.framebuffer_depth_only == NULL) {
g_select_buffer.framebuffer_depth_only = GPU_framebuffer_create();
- g_select_buffer.framebuffer_select_id = GPU_framebuffer_create();
}
if ((g_select_buffer.texture_depth != NULL) &&
@@ -2162,32 +2160,7 @@ static void draw_select_framebuffer_depth_only_setup(const int size[2])
GPU_framebuffer_texture_attach(
g_select_buffer.framebuffer_depth_only, g_select_buffer.texture_depth, 0, 0);
- GPU_framebuffer_texture_attach(
- g_select_buffer.framebuffer_select_id, g_select_buffer.texture_depth, 0, 0);
-
GPU_framebuffer_check_valid(g_select_buffer.framebuffer_depth_only, NULL);
- GPU_framebuffer_check_valid(g_select_buffer.framebuffer_select_id, NULL);
- }
-}
-
-static void draw_select_framebuffer_select_id_setup(const int size[2])
-{
- draw_select_framebuffer_depth_only_setup(size);
-
- if ((g_select_buffer.texture_u32 != NULL) &&
- ((GPU_texture_width(g_select_buffer.texture_u32) != size[0]) ||
- (GPU_texture_height(g_select_buffer.texture_u32) != size[1]))) {
- GPU_texture_free(g_select_buffer.texture_u32);
- g_select_buffer.texture_u32 = NULL;
- }
-
- if (g_select_buffer.texture_u32 == NULL) {
- g_select_buffer.texture_u32 = GPU_texture_create_2d(size[0], size[1], GPU_R32UI, NULL, NULL);
-
- GPU_framebuffer_texture_attach(
- g_select_buffer.framebuffer_select_id, g_select_buffer.texture_u32, 0, 0);
-
- GPU_framebuffer_check_valid(g_select_buffer.framebuffer_select_id, NULL);
}
}
@@ -2575,6 +2548,78 @@ 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)
+{
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
+ ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
+
+ DRW_select_context_create(depsgraph, 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;
+
+ /* Instead of 'DRW_context_state_init(C, &DST.draw_ctx)', assign from args */
+ DST.draw_ctx = (DRWContextState){
+ .ar = ar,
+ .rv3d = ar->regiondata,
+ .v3d = v3d,
+ .scene = scene,
+ .view_layer = view_layer,
+ .obact = OBACT(view_layer),
+ .depsgraph = depsgraph,
+ };
+
+ use_drw_engine(&draw_engine_select_type);
+ drw_context_state_init();
+
+ /* Setup viewport */
+ DST.viewport = WM_draw_region_get_viewport(ar, 0);
+ drw_viewport_var_init();
+
+ /* Update ubos */
+ DRW_globals_update();
+
+ /* Init engines */
+ 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);
+ drw_engines_cache_populate(obj_eval);
+ }
+
+ drw_engines_cache_finish();
+ }
+
+ /* Start Drawing */
+ DRW_state_reset();
+ drw_engines_draw_scene();
+ DRW_state_reset();
+
+ drw_engines_disable();
+
+#ifdef DEBUG
+ /* 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. */
static void draw_world_clip_planes_from_rv3d(GPUBatch *batch, const float world_clip_planes[6][4])
{
@@ -2646,294 +2691,6 @@ void DRW_draw_depth_object(ARegion *ar, GPUViewport *viewport, Object *object)
DRW_opengl_context_disable();
}
-static void draw_mesh_verts(GPUBatch *batch, uint offset, const float world_clip_planes[6][4])
-{
- GPU_point_size(UI_GetThemeValuef(TH_VERTEX_SIZE));
-
- const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
- GPU_SHADER_CFG_DEFAULT;
- GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg);
- GPU_batch_uniform_1ui(batch, "offset", offset);
- if (world_clip_planes != NULL) {
- draw_world_clip_planes_from_rv3d(batch, world_clip_planes);
- }
- GPU_batch_draw(batch);
-}
-
-static void draw_mesh_edges(GPUBatch *batch, uint offset, const float world_clip_planes[6][4])
-{
- GPU_line_width(1.0f);
- glProvokingVertex(GL_FIRST_VERTEX_CONVENTION);
-
- const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
- GPU_SHADER_CFG_DEFAULT;
- GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg);
- GPU_batch_uniform_1ui(batch, "offset", offset);
- if (world_clip_planes != NULL) {
- draw_world_clip_planes_from_rv3d(batch, world_clip_planes);
- }
- GPU_batch_draw(batch);
-
- glProvokingVertex(GL_LAST_VERTEX_CONVENTION);
-}
-
-/* two options, facecolors or black */
-static void draw_mesh_face(GPUBatch *batch,
- uint offset,
- const bool use_select,
- const float world_clip_planes[6][4])
-{
- if (use_select) {
- const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
- GPU_SHADER_CFG_DEFAULT;
- GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg);
- GPU_batch_uniform_1ui(batch, "offset", offset);
- if (world_clip_planes != NULL) {
- draw_world_clip_planes_from_rv3d(batch, world_clip_planes);
- }
- GPU_batch_draw(batch);
- }
- else {
- const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
- GPU_SHADER_CFG_DEFAULT;
- GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_UNIFORM_SELECT_ID, sh_cfg);
- GPU_batch_uniform_1ui(batch, "id", 0);
- if (world_clip_planes != NULL) {
- draw_world_clip_planes_from_rv3d(batch, world_clip_planes);
- }
- GPU_batch_draw(batch);
- }
-}
-
-static void draw_mesh_face_dot(GPUBatch *batch, uint offset, const float world_clip_planes[6][4])
-{
- const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
- GPU_SHADER_CFG_DEFAULT;
- GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg);
- GPU_batch_uniform_1ui(batch, "offset", offset);
- if (world_clip_planes != NULL) {
- draw_world_clip_planes_from_rv3d(batch, world_clip_planes);
- }
- GPU_batch_draw(batch);
-}
-
-void DRW_draw_select_id_object(Scene *scene,
- RegionView3D *rv3d,
- Object *ob,
- short select_mode,
- bool draw_facedot,
- uint initial_offset,
- uint *r_vert_offset,
- uint *r_edge_offset,
- uint *r_face_offset)
-{
- ToolSettings *ts = scene->toolsettings;
- if (select_mode == -1) {
- select_mode = ts->selectmode;
- }
-
- /* Init the scene of the draw context. When using face dot selection on
- * when the subsurf modifier is active on the cage, the scene needs to be
- * valid. It is read from the context in the
- * `DRW_mesh_batch_cache_create_requested` and used in the `isDisabled`
- * method of the SubSurfModifier. */
- DRWContextState *draw_ctx = &DST.draw_ctx;
- draw_ctx->scene = scene;
-
- GPU_matrix_mul(ob->obmat);
-
- const float(*world_clip_planes)[4] = NULL;
- if (rv3d->rflag & RV3D_CLIPPING) {
- ED_view3d_clipping_local(rv3d, ob->obmat);
- world_clip_planes = rv3d->clip_local;
- }
-
- BLI_assert(initial_offset > 0);
-
- switch (ob->type) {
- case OB_MESH:
- if (ob->mode & OB_MODE_EDIT) {
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_mesh;
- const bool use_faceselect = (select_mode & SCE_SELECT_FACE) != 0;
-
- DRW_mesh_batch_cache_validate(me);
-
- BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE | BM_FACE);
-
- GPUBatch *geom_faces, *geom_edges, *geom_verts, *geom_facedots;
- geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me);
- if (select_mode & SCE_SELECT_EDGE) {
- geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(me);
- }
- if (select_mode & SCE_SELECT_VERTEX) {
- geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me);
- }
- if (use_faceselect && draw_facedot) {
- geom_facedots = DRW_mesh_batch_cache_get_facedots_with_select_id(me);
- }
- DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, true);
-
- draw_mesh_face(geom_faces, initial_offset, use_faceselect, world_clip_planes);
-
- if (use_faceselect && draw_facedot) {
- draw_mesh_face_dot(geom_facedots, initial_offset, world_clip_planes);
- }
-
- if (select_mode & SCE_SELECT_FACE) {
- *r_face_offset = initial_offset + em->bm->totface;
- }
- else {
- *r_face_offset = initial_offset;
- }
-
- ED_view3d_polygon_offset(rv3d, 1.0);
-
- /* Unlike faces, only draw edges if edge select mode. */
- if (select_mode & SCE_SELECT_EDGE) {
- draw_mesh_edges(geom_edges, *r_face_offset, world_clip_planes);
- *r_edge_offset = *r_face_offset + em->bm->totedge;
- }
- else {
- /* Note that `r_vert_offset` is calculated from `r_edge_offset`.
- * Otherwise the first vertex is never selected, see: T53512. */
- *r_edge_offset = *r_face_offset;
- }
-
- ED_view3d_polygon_offset(rv3d, 1.1);
-
- /* Unlike faces, only verts if vert select mode. */
- if (select_mode & SCE_SELECT_VERTEX) {
- draw_mesh_verts(geom_verts, *r_edge_offset, world_clip_planes);
- *r_vert_offset = *r_edge_offset + em->bm->totvert;
- }
- else {
- *r_vert_offset = *r_edge_offset;
- }
-
- ED_view3d_polygon_offset(rv3d, 0.0);
- }
- else {
- Mesh *me_orig = DEG_get_original_object(ob)->data;
- Mesh *me_eval = ob->data;
-
- DRW_mesh_batch_cache_validate(me_eval);
- GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me_eval);
- if ((me_orig->editflag & ME_EDIT_PAINT_VERT_SEL) &&
- /* Currently vertex select supports weight paint and vertex paint. */
- ((ob->mode & OB_MODE_WEIGHT_PAINT) || (ob->mode & OB_MODE_VERTEX_PAINT))) {
-
- GPUBatch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me_eval);
- DRW_mesh_batch_cache_create_requested(ob, me_eval, NULL, false, true);
-
- /* Only draw faces to mask out verts, we don't want their selection ID's. */
- draw_mesh_face(geom_faces, 0, false, world_clip_planes);
- draw_mesh_verts(geom_verts, 1, world_clip_planes);
-
- *r_face_offset = *r_edge_offset = initial_offset;
- *r_vert_offset = me_eval->totvert + 1;
- }
- else {
- const bool use_hide = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL);
- DRW_mesh_batch_cache_create_requested(ob, me_eval, NULL, false, use_hide);
-
- draw_mesh_face(geom_faces, initial_offset, true, world_clip_planes);
-
- *r_face_offset = initial_offset + me_eval->totpoly;
- *r_edge_offset = *r_vert_offset = *r_face_offset;
- }
- }
- break;
- case OB_CURVE:
- case OB_SURF:
- break;
- }
-
- GPU_matrix_set(rv3d->viewmat);
-}
-
-/* Set an opengl context to be used with shaders that draw on U32 colors. */
-void DRW_framebuffer_select_id_setup(ARegion *ar, const bool clear)
-{
- RegionView3D *rv3d = ar->regiondata;
-
- DRW_opengl_context_enable();
-
- /* Setup framebuffer */
- int viewport_size[2] = {ar->winx, ar->winy};
- draw_select_framebuffer_select_id_setup(viewport_size);
- GPU_framebuffer_bind(g_select_buffer.framebuffer_select_id);
-
- /* dithering and AA break color coding, so disable */
- glDisable(GL_DITHER);
-
- GPU_depth_test(true);
- GPU_program_point_size(false);
-
- if (clear) {
- GPU_framebuffer_clear_color_depth(
- g_select_buffer.framebuffer_select_id, (const float[4]){0.0f}, 1.0f);
- }
-
- if (rv3d->rflag & RV3D_CLIPPING) {
- ED_view3d_clipping_set(rv3d);
- }
-}
-
-/* Ends the context for selection and restoring the previous one. */
-void DRW_framebuffer_select_id_release(ARegion *ar)
-{
- RegionView3D *rv3d = ar->regiondata;
-
- if (rv3d->rflag & RV3D_CLIPPING) {
- ED_view3d_clipping_disable();
- }
-
- GPU_depth_test(false);
-
- GPU_framebuffer_restore();
-
- DRW_opengl_context_disable();
-}
-
-/* Read a block of pixels from the select frame buffer. */
-void DRW_framebuffer_select_id_read(const rcti *rect, uint *r_buf)
-{
- /* clamp rect by texture */
- rcti r = {
- .xmin = 0,
- .xmax = GPU_texture_width(g_select_buffer.texture_u32),
- .ymin = 0,
- .ymax = GPU_texture_height(g_select_buffer.texture_u32),
- };
-
- rcti rect_clamp = *rect;
- if (BLI_rcti_isect(&r, &rect_clamp, &rect_clamp)) {
- DRW_opengl_context_enable();
- GPU_framebuffer_bind(g_select_buffer.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);
-
- GPU_framebuffer_restore();
- DRW_opengl_context_disable();
-
- if (!BLI_rcti_compare(rect, &rect_clamp)) {
- GPU_select_buffer_stride_realign(rect, &rect_clamp, r_buf);
- }
- }
- else {
- size_t buf_size = BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect) * sizeof(*r_buf);
-
- memset(r_buf, 0, buf_size);
- }
-}
-
/** \} */
/* -------------------------------------------------------------------- */
@@ -3089,6 +2846,7 @@ void DRW_engines_register(void)
DRW_engine_register(&draw_engine_pose_type);
DRW_engine_register(&draw_engine_sculpt_type);
DRW_engine_register(&draw_engine_gpencil_type);
+ DRW_engine_register(&draw_engine_select_type);
/* setup callbacks */
{
@@ -3123,9 +2881,7 @@ void DRW_engines_free(void)
DRW_opengl_context_enable();
- DRW_TEXTURE_FREE_SAFE(g_select_buffer.texture_u32);
DRW_TEXTURE_FREE_SAFE(g_select_buffer.texture_depth);
- GPU_FRAMEBUFFER_FREE_SAFE(g_select_buffer.framebuffer_select_id);
GPU_FRAMEBUFFER_FREE_SAFE(g_select_buffer.framebuffer_depth_only);
DRW_hair_free();