Blender V4.3
gpu_select.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2014 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
11#include <cstdlib>
12#include <cstring>
13
14#include "DNA_userdef_types.h"
15
16#include "GPU_select.hh"
17
18#include "BLI_rect.h"
19
20#include "BLI_utildefines.h"
21
22#include "gpu_select_private.hh"
23
24/* -------------------------------------------------------------------- */
28/* Internal algorithm used */
43
45 /* To ignore selection id calls when not initialized */
47 /* mode of operation */
49 /* internal algorithm for selection */
51 /* allow GPU_select_begin/end without drawing */
62};
63
65
68/* -------------------------------------------------------------------- */
73 const rcti *input,
74 eGPUSelectMode mode,
75 int oldhits,
76 bool use_select_next)
77{
79 /* In the case hits was '-1',
80 * don't start the second pass since it's not going to give useful results.
81 * As well as buffer overflow in 'gpu_select_query_load_id'. */
82 BLI_assert(oldhits != -1);
83 }
84
86 g_select_state.mode = mode;
87
88 if (use_select_next) {
90 }
93 }
94 else {
96 }
97
98 /* This function is called when cache has already been initialized,
99 * so only manipulate cache values when cache is pending. */
102
103 switch (g_select_state.algorithm) {
104 case ALGO_SELECT_NEXT:
105 case ALGO_GL_QUERY: {
107 break;
108 }
109 default: {
112 break;
113 }
114 }
115 }
116
117 switch (g_select_state.algorithm) {
118 case ALGO_SELECT_NEXT: {
119 gpu_select_next_begin(buffer, input, mode);
120 break;
121 }
122 case ALGO_GL_QUERY: {
123 gpu_select_query_begin(buffer, input, mode, oldhits);
124 break;
125 }
126 default: /* ALGO_GL_PICK */
127 {
128 gpu_select_pick_begin(buffer, input, mode);
129 break;
130 }
131 }
132}
133
135 const rcti *input,
136 eGPUSelectMode mode,
137 int oldhits)
138{
139 gpu_select_begin_ex(buffer, input, mode, oldhits, U.experimental.enable_overlay_next);
140}
141
142void GPU_select_begin(GPUSelectBuffer *buffer, const rcti *input, eGPUSelectMode mode, int oldhits)
143{
144 gpu_select_begin_ex(buffer, input, mode, oldhits, false);
145}
146
148{
149 /* if no selection mode active, ignore */
151 return true;
152 }
153
154 switch (g_select_state.algorithm) {
155 case ALGO_SELECT_NEXT:
156 /* This shouldn't use this pipeline. */
158 return false;
159
160 case ALGO_GL_QUERY: {
161 return gpu_select_query_load_id(id);
162 }
163 default: /* ALGO_GL_PICK */
164 {
165 return gpu_select_pick_load_id(id, false);
166 }
167 }
168}
169
171{
172 uint hits = 0;
173
174 switch (g_select_state.algorithm) {
175 case ALGO_SELECT_NEXT: {
176 hits = gpu_select_next_end();
177 break;
178 }
179 case ALGO_GL_QUERY: {
180 hits = gpu_select_query_end();
181 break;
182 }
183 default: /* ALGO_GL_PICK */
184 {
185 hits = gpu_select_pick_end();
186 break;
187 }
188 }
189
191
192 return hits;
193}
194
197/* -------------------------------------------------------------------- */
205{
207 /* Ensure #GPU_select_cache_end is always called. */
209
210 /* Signal that cache should be used, instead of calling the algorithms cache-begin function.
211 * This is more convenient as the exact method of selection may not be known by the caller. */
213}
214
222
224{
228 }
230 /* Paranoid assignment, should already be false. */
232}
233
238
241/* -------------------------------------------------------------------- */
246{
247 const GPUSelectResult *hit_result_near = nullptr;
248 uint depth_min = uint(-1);
249 for (const GPUSelectResult &hit_result : hit_results) {
250 if (hit_result.depth < depth_min) {
251 BLI_assert(hit_result.id != -1);
252 depth_min = hit_result.depth;
253 hit_result_near = &hit_result;
254 }
255 }
256 return hit_result_near;
257}
258
260 uint select_id)
261{
262 uint index_src = 0;
263 uint index_dst = 0;
264 uint hits_final = 0;
265 for (const GPUSelectResult &hit_result : hit_results) {
266 if (hit_result.id != select_id) {
267 if (index_dst != index_src) {
268 hit_results[index_dst] = hit_result;
269 }
270 index_dst++;
271 hits_final++;
272 }
273 index_src++;
274 }
275 return hits_final;
276}
277
278void GPU_select_buffer_stride_realign(const rcti *src, const rcti *dst, uint *r_buf)
279{
280 const int x = dst->xmin - src->xmin;
281 const int y = dst->ymin - src->ymin;
282
283 BLI_assert(src->xmin <= dst->xmin && src->ymin <= dst->ymin && src->xmax >= dst->xmax &&
284 src->ymax >= dst->ymax);
285 BLI_assert(x >= 0 && y >= 0);
286
287 const int src_x = BLI_rcti_size_x(src);
288 const int src_y = BLI_rcti_size_y(src);
289 const int dst_x = BLI_rcti_size_x(dst);
290 const int dst_y = BLI_rcti_size_y(dst);
291
292 int last_px_id = src_x * (y + dst_y - 1) + (x + dst_x - 1);
293 memset(&r_buf[last_px_id + 1], 0, (src_x * src_y - (last_px_id + 1)) * sizeof(*r_buf));
294
295 if (last_px_id < 0) {
296 /* Nothing to write. */
297 BLI_assert(last_px_id == -1);
298 return;
299 }
300
301 int last_px_written = dst_x * dst_y - 1;
302 const int skip = src_x - dst_x;
303
304 while (true) {
305 for (int i = dst_x; i--;) {
306 r_buf[last_px_id--] = r_buf[last_px_written--];
307 }
308 if (last_px_written < 0) {
309 break;
310 }
311 last_px_id -= skip;
312 memset(&r_buf[last_px_id + 1], 0, skip * sizeof(*r_buf));
313 }
314 memset(r_buf, 0, (last_px_id + 1) * sizeof(*r_buf));
315}
316
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition BLI_rect.h:193
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition BLI_rect.h:189
unsigned int uint
#define ELEM(...)
eGPUSelectMode
Definition GPU_select.hh:18
@ GPU_SELECT_NEAREST_SECOND_PASS
Definition GPU_select.hh:22
@ GPU_SELECT_PICK_ALL
Definition GPU_select.hh:24
@ GPU_SELECT_PICK_NEAREST
Definition GPU_select.hh:25
unsigned int U
Definition btGjkEpa3.h:78
const GPUSelectResult * GPU_select_buffer_near(const blender::Span< GPUSelectResult > hit_results)
uint GPU_select_end()
eGPUSelectAlgo
Definition gpu_select.cc:29
@ ALGO_SELECT_NEXT
Definition gpu_select.cc:41
@ ALGO_GL_QUERY
Definition gpu_select.cc:34
@ ALGO_GL_PICK
Definition gpu_select.cc:39
static GPUSelectState g_select_state
Definition gpu_select.cc:64
void GPU_select_cache_end()
bool GPU_select_is_cached()
bool GPU_select_load_id(uint id)
static void gpu_select_begin_ex(GPUSelectBuffer *buffer, const rcti *input, eGPUSelectMode mode, int oldhits, bool use_select_next)
Definition gpu_select.cc:72
void GPU_select_begin(GPUSelectBuffer *buffer, const rcti *input, eGPUSelectMode mode, int oldhits)
void GPU_select_cache_load_id()
void GPU_select_begin_next(GPUSelectBuffer *buffer, const rcti *input, eGPUSelectMode mode, int oldhits)
uint GPU_select_buffer_remove_by_id(blender::MutableSpan< GPUSelectResult > hit_results, uint select_id)
void GPU_select_cache_begin()
void GPU_select_buffer_stride_realign(const rcti *src, const rcti *dst, uint *r_buf)
uint gpu_select_next_end()
void gpu_select_next_begin(GPUSelectBuffer *buffer, const rcti *input, eGPUSelectMode mode)
bool gpu_select_pick_load_id(uint id, bool end)
uint gpu_select_pick_end()
void gpu_select_pick_cache_begin()
bool gpu_select_pick_is_cached()
void gpu_select_pick_cache_load_id()
void gpu_select_pick_begin(GPUSelectBuffer *buffer, const rcti *input, eGPUSelectMode mode)
void gpu_select_pick_cache_end()
bool gpu_select_query_load_id(uint id)
uint gpu_select_query_end()
void gpu_select_query_begin(GPUSelectBuffer *buffer, const rcti *input, eGPUSelectMode mode, int oldhits)
eGPUSelectAlgo algorithm
Definition gpu_select.cc:50
eGPUSelectMode mode
Definition gpu_select.cc:48
bool select_is_active
Definition gpu_select.cc:46
bool use_cache_needs_init
Definition gpu_select.cc:61
int ymin
int ymax
int xmin
int xmax