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:
Diffstat (limited to 'source/blender/draw/intern/draw_select_buffer.c')
-rw-r--r--source/blender/draw/intern/draw_select_buffer.c227
1 files changed, 139 insertions, 88 deletions
diff --git a/source/blender/draw/intern/draw_select_buffer.c b/source/blender/draw/intern/draw_select_buffer.c
index cd876b7b068..974ea22ccea 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) {
@@ -424,14 +468,15 @@ bool DRW_select_buffer_elem_get(const uint sel_id,
}
}
- if (base_index == select_ctx->objects_len) {
+ if (base_index == select_ctx->objects_drawn_len) {
return false;
}
*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));
+}
/** \} */