Blender V5.0
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 "GPU_select.hh"
15
16#include "BLI_rect.h"
17
18#include "BLI_utildefines.h"
19
20#include "gpu_select_private.hh"
21
22/* -------------------------------------------------------------------- */
25
26/* Internal algorithm used */
41
43 /* To ignore selection id calls when not initialized */
45 /* mode of operation */
47 /* internal algorithm for selection */
49 /* allow GPU_select_begin/end without drawing */
60};
61
63
65
66/* -------------------------------------------------------------------- */
69
71 const rcti *input,
72 GPUSelectMode mode,
73 int oldhits,
74 bool use_select_next)
75{
77 /* In the case hits was '-1',
78 * don't start the second pass since it's not going to give useful results.
79 * As well as buffer overflow in 'gpu_select_query_load_id'. */
80 BLI_assert(oldhits != -1);
81 }
82
83 g_select_state.select_is_active = true;
84 g_select_state.mode = mode;
85
86 if (use_select_next) {
88 }
91 }
92 else {
94 }
95
96 /* This function is called when cache has already been initialized,
97 * so only manipulate cache values when cache is pending. */
98 if (g_select_state.use_cache_needs_init) {
99 g_select_state.use_cache_needs_init = false;
100
101 switch (g_select_state.algorithm) {
102 case ALGO_SELECT_NEXT:
103 case ALGO_SAMPLE_QUERY: {
104 g_select_state.use_cache = false;
105 break;
106 }
107 default: {
108 g_select_state.use_cache = true;
110 break;
111 }
112 }
113 }
114
115 switch (g_select_state.algorithm) {
116 case ALGO_SELECT_NEXT: {
117 gpu_select_next_begin(buffer, input, mode);
118 break;
119 }
120 case ALGO_SAMPLE_QUERY: {
121 gpu_select_query_begin(buffer, input, mode, oldhits);
122 break;
123 }
124 default: /* ALGO_DEPTH_PICK */
125 {
126 gpu_select_pick_begin(buffer, input, mode);
127 break;
128 }
129 }
130}
131
133 const rcti *input,
134 GPUSelectMode mode,
135 int oldhits)
136{
137 gpu_select_begin_ex(buffer, input, mode, oldhits, true);
138}
139
140void GPU_select_begin(GPUSelectBuffer *buffer, const rcti *input, GPUSelectMode mode, int oldhits)
141{
142 gpu_select_begin_ex(buffer, input, mode, oldhits, false);
143}
144
146{
147 /* if no selection mode active, ignore */
148 if (!g_select_state.select_is_active) {
149 return true;
150 }
151
152 switch (g_select_state.algorithm) {
153 case ALGO_SELECT_NEXT:
154 /* This shouldn't use this pipeline. */
156 return false;
157
158 case ALGO_SAMPLE_QUERY: {
159 return gpu_select_query_load_id(id);
160 }
161 default: /* ALGO_DEPTH_PICK */
162 {
163 return gpu_select_pick_load_id(id, false);
164 }
165 }
166}
167
169{
170 uint hits = 0;
171
172 switch (g_select_state.algorithm) {
173 case ALGO_SELECT_NEXT: {
174 hits = gpu_select_next_end();
175 break;
176 }
177 case ALGO_SAMPLE_QUERY: {
178 hits = gpu_select_query_end();
179 break;
180 }
181 default: /* ALGO_DEPTH_PICK */
182 {
183 hits = gpu_select_pick_end();
184 break;
185 }
186 }
187
188 g_select_state.select_is_active = false;
189
190 return hits;
191}
192
194
195/* -------------------------------------------------------------------- */
201
203{
204 BLI_assert(g_select_state.select_is_active == false);
205 /* Ensure #GPU_select_cache_end is always called. */
206 BLI_assert(g_select_state.use_cache_needs_init == false);
207
208 /* Signal that cache should be used, instead of calling the algorithms cache-begin function.
209 * This is more convenient as the exact method of selection may not be known by the caller. */
210 g_select_state.use_cache_needs_init = true;
211}
212
214{
215 BLI_assert(g_select_state.use_cache == true);
216 if (g_select_state.algorithm == ALGO_DEPTH_PICK) {
218 }
219}
220
222{
223 if (g_select_state.algorithm == ALGO_DEPTH_PICK) {
224 BLI_assert(g_select_state.use_cache == true);
226 }
227 g_select_state.use_cache = false;
228 /* Paranoid assignment, should already be false. */
229 g_select_state.use_cache_needs_init = false;
230}
231
233{
234 return g_select_state.use_cache && gpu_select_pick_is_cached();
235}
236
238
239/* -------------------------------------------------------------------- */
242
244{
245 const GPUSelectResult *hit_result_near = nullptr;
246 uint depth_min = uint(-1);
247 for (const GPUSelectResult &hit_result : hit_results) {
248 if (hit_result.depth < depth_min) {
249 BLI_assert(hit_result.id != -1);
250 depth_min = hit_result.depth;
251 hit_result_near = &hit_result;
252 }
253 }
254 return hit_result_near;
255}
256
258 uint select_id)
259{
260 uint index_src = 0;
261 uint index_dst = 0;
262 uint hits_final = 0;
263 for (const GPUSelectResult &hit_result : hit_results) {
264 if (hit_result.id != select_id) {
265 if (index_dst != index_src) {
266 hit_results[index_dst] = hit_result;
267 }
268 index_dst++;
269 hits_final++;
270 }
271 index_src++;
272 }
273 return hits_final;
274}
275
276void GPU_select_buffer_stride_realign(const rcti *src, const rcti *dst, uint *r_buf)
277{
278 const int x = dst->xmin - src->xmin;
279 const int y = dst->ymin - src->ymin;
280
281 BLI_assert(src->xmin <= dst->xmin && src->ymin <= dst->ymin && src->xmax >= dst->xmax &&
282 src->ymax >= dst->ymax);
283 BLI_assert(x >= 0 && y >= 0);
284
285 const int src_x = BLI_rcti_size_x(src);
286 const int src_y = BLI_rcti_size_y(src);
287 const int dst_x = BLI_rcti_size_x(dst);
288 const int dst_y = BLI_rcti_size_y(dst);
289
290 BLI_assert(dst_x > 0 && dst_y > 0);
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:93
#define BLI_assert(a)
Definition BLI_assert.h:46
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition BLI_rect.h:198
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition BLI_rect.h:194
unsigned int uint
#define ELEM(...)
GPUSelectMode
Definition GPU_select.hh:18
@ GPU_SELECT_NEAREST_SECOND_PASS
Definition GPU_select.hh:23
@ GPU_SELECT_PICK_ALL
Definition GPU_select.hh:25
@ GPU_SELECT_PICK_NEAREST
Definition GPU_select.hh:26
const GPUSelectResult * GPU_select_buffer_near(const blender::Span< GPUSelectResult > hit_results)
uint GPU_select_end()
static GPUSelectState g_select_state
Definition gpu_select.cc:62
void GPU_select_cache_end()
void GPU_select_begin(GPUSelectBuffer *buffer, const rcti *input, GPUSelectMode mode, int oldhits)
bool GPU_select_is_cached()
bool GPU_select_load_id(uint id)
void GPU_select_begin_next(GPUSelectBuffer *buffer, const rcti *input, GPUSelectMode mode, int oldhits)
static void gpu_select_begin_ex(GPUSelectBuffer *buffer, const rcti *input, GPUSelectMode mode, int oldhits, bool use_select_next)
Definition gpu_select.cc:70
void GPU_select_cache_load_id()
GPUSelectAlgo
Definition gpu_select.cc:27
@ ALGO_SAMPLE_QUERY
Definition gpu_select.cc:32
@ ALGO_SELECT_NEXT
Definition gpu_select.cc:39
@ ALGO_DEPTH_PICK
Definition gpu_select.cc:37
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)
void gpu_select_next_begin(GPUSelectBuffer *buffer, const rcti *input, GPUSelectMode mode)
uint gpu_select_next_end()
bool gpu_select_pick_load_id(uint id, bool end)
void gpu_select_pick_begin(GPUSelectBuffer *buffer, const rcti *input, GPUSelectMode mode)
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_cache_end()
bool gpu_select_query_load_id(uint id)
void gpu_select_query_begin(GPUSelectBuffer *buffer, const rcti *input, GPUSelectMode mode, int oldhits)
uint gpu_select_query_end()
#define input
GPUSelectMode mode
Definition gpu_select.cc:46
bool select_is_active
Definition gpu_select.cc:44
GPUSelectAlgo algorithm
Definition gpu_select.cc:48
bool use_cache_needs_init
Definition gpu_select.cc:59
int ymin
int ymax
int xmin
int xmax
i
Definition text_draw.cc:230