Blender  V3.3
gpu_select_pick.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2017 Blender Foundation. All rights reserved. */
3 
10 #include <float.h>
11 #include <stdlib.h>
12 #include <string.h>
13 
14 #include "GPU_debug.h"
15 #include "GPU_framebuffer.h"
16 #include "GPU_select.h"
17 #include "GPU_state.h"
18 
19 #include "MEM_guardedalloc.h"
20 
21 #include "BLI_listbase.h"
22 #include "BLI_rect.h"
23 #include "BLI_utildefines.h"
24 
25 #include "gpu_select_private.h"
26 
27 #include "BLI_strict_flags.h"
28 
29 /* #define DEBUG_PRINT */
30 
31 /* Alloc number for depths */
32 #define ALLOC_DEPTHS 200
33 
34 /* Z-depth of cleared depth buffer */
35 #define DEPTH_MAX 0xffffffff
36 
37 /* -------------------------------------------------------------------- */
42 typedef struct SubRectStride {
52 
54 typedef uint depth_t;
55 
61 static void rect_subregion_stride_calc(const rcti *src, const rcti *dst, SubRectStride *r_sub)
62 {
63  const int src_x = BLI_rcti_size_x(src);
64  // const int src_y = BLI_rcti_size_y(src);
65  const int dst_x = BLI_rcti_size_x(dst);
66  const int dst_y = BLI_rcti_size_y(dst);
67  const int x = dst->xmin - src->xmin;
68  const int y = dst->ymin - src->ymin;
69 
70  BLI_assert(src->xmin <= dst->xmin && src->ymin <= dst->ymin && src->xmax >= dst->xmax &&
71  src->ymax >= dst->ymax);
72  BLI_assert(x >= 0 && y >= 0);
73 
74  r_sub->start = (uint)((src_x * y) + x);
75  r_sub->span = (uint)dst_x;
76  r_sub->span_len = (uint)dst_y;
77  r_sub->skip = (uint)(src_x - dst_x);
78 }
79 
84 BLI_INLINE bool depth_is_filled(const depth_t *prev, const depth_t *curr)
85 {
86  return (*prev != *curr) && (*curr != DEPTH_MAX);
87 }
88 
91 /* -------------------------------------------------------------------- */
99 typedef struct DepthBufCache {
104 
106 {
107  DepthBufCache *rect = MEM_mallocN(sizeof(DepthBufCache) + sizeof(depth_t) * rect_len, __func__);
108  rect->id = SELECT_ID_NONE;
109  return rect;
110 }
111 
112 static bool depth_buf_rect_depth_any(const DepthBufCache *rect_depth, uint rect_len)
113 {
114  const depth_t *curr = rect_depth->buf;
115  for (uint i = 0; i < rect_len; i++, curr++) {
116  if (*curr != DEPTH_MAX) {
117  return true;
118  }
119  }
120  return false;
121 }
122 
123 static bool depth_buf_subrect_depth_any(const DepthBufCache *rect_depth,
124  const SubRectStride *sub_rect)
125 {
126  const depth_t *curr = rect_depth->buf + sub_rect->start;
127  for (uint i = 0; i < sub_rect->span_len; i++) {
128  const depth_t *curr_end = curr + sub_rect->span;
129  for (; curr < curr_end; curr++, curr++) {
130  if (*curr != DEPTH_MAX) {
131  return true;
132  }
133  }
134  curr += sub_rect->skip;
135  }
136  return false;
137 }
138 
139 static bool depth_buf_rect_depth_any_filled(const DepthBufCache *rect_prev,
140  const DepthBufCache *rect_curr,
141  uint rect_len)
142 {
143 #if 0
144  return memcmp(rect_depth_a->buf, rect_depth_b->buf, rect_len * sizeof(depth_t)) != 0;
145 #else
146  const depth_t *prev = rect_prev->buf;
147  const depth_t *curr = rect_curr->buf;
148  for (uint i = 0; i < rect_len; i++, curr++, prev++) {
149  if (depth_is_filled(prev, curr)) {
150  return true;
151  }
152  }
153  return false;
154 #endif
155 }
156 
161  const DepthBufCache *rect_dst,
162  const SubRectStride *sub_rect)
163 {
164  /* Same as above but different rectangle sizes. */
165  const depth_t *prev = rect_src->buf + sub_rect->start;
166  const depth_t *curr = rect_dst->buf + sub_rect->start;
167  for (uint i = 0; i < sub_rect->span_len; i++) {
168  const depth_t *curr_end = curr + sub_rect->span;
169  for (; curr < curr_end; prev++, curr++) {
170  if (depth_is_filled(prev, curr)) {
171  return true;
172  }
173  }
174  prev += sub_rect->skip;
175  curr += sub_rect->skip;
176  }
177  return false;
178 }
179 
182 /* -------------------------------------------------------------------- */
188 typedef struct DepthID {
192 
193 static int depth_id_cmp(const void *v1, const void *v2)
194 {
195  const DepthID *d1 = v1, *d2 = v2;
196  if (d1->id < d2->id) {
197  return -1;
198  }
199  if (d1->id > d2->id) {
200  return 1;
201  }
202 
203  return 0;
204 }
205 
206 static int depth_cmp(const void *v1, const void *v2)
207 {
208  const DepthID *d1 = v1, *d2 = v2;
209  if (d1->depth < d2->depth) {
210  return -1;
211  }
212  if (d1->depth > d2->depth) {
213  return 1;
214  }
215 
216  return 0;
217 }
218 
221 /* -------------------------------------------------------------------- */
226 typedef struct GPUPickState {
232 
234  struct {
239 
242 
244  bool is_init;
246  } gpu;
247 
252  struct {
255  } src, dst;
256 
258  bool use_cache;
259  bool is_cached;
260  struct {
266 
269  } cache;
270 
272  union {
274  struct {
278  } all;
279 
281  struct {
284  };
285 
287  int viewport[4];
288  int scissor[4];
292 
294 
296  const uint buffer_len,
297  const rcti *input,
298  eGPUSelectMode mode)
299 {
300  GPUPickState *ps = &g_pick_state;
301 
302 #ifdef DEBUG_PRINT
303  printf("%s: mode=%d, use_cache=%d, is_cache=%d\n",
304  __func__,
305  (int)mode,
306  ps->use_cache,
307  ps->is_cached);
308 #endif
309 
310  GPU_debug_group_begin("Selection Pick");
311 
312  ps->buffer = buffer;
313  ps->buffer_len = buffer_len;
314  ps->mode = mode;
315 
316  const uint rect_len = (uint)(BLI_rcti_size_x(input) * BLI_rcti_size_y(input));
317  ps->dst.clip_rect = *input;
318  ps->dst.rect_len = rect_len;
319 
320  /* Avoids unnecessary GPU operations when cache is available and they are unnecessary. */
321  if (ps->is_cached == false) {
325 
326  /* Disable writing to the frame-buffer. */
327  GPU_color_mask(false, false, false, false);
328 
329  GPU_depth_mask(true);
330  /* Always use #GPU_DEPTH_LESS_EQUAL even though #GPU_SELECT_PICK_ALL always clears the buffer.
331  * This is because individual objects themselves might have sections that overlap and we need
332  * these to have the correct distance information. */
334 
335  float viewport[4];
336  GPU_viewport_size_get_f(viewport);
337 
338  ps->src.clip_rect = *input;
339  ps->src.rect_len = rect_len;
340 
341  ps->gpu.clip_readpixels[0] = (int)viewport[0];
342  ps->gpu.clip_readpixels[1] = (int)viewport[1];
345 
347 
348  /* It's possible we don't want to clear depth buffer,
349  * so existing elements are masked by current z-buffer. */
350  GPU_clear_depth(1.0f);
351 
352  /* scratch buffer (read new values here) */
353  ps->gpu.rect_depth_test = depth_buf_malloc(rect_len);
354  ps->gpu.rect_depth = depth_buf_malloc(rect_len);
355 
356  /* Set initial 'far' value. */
357  for (uint i = 0; i < rect_len; i++) {
358  ps->gpu.rect_depth->buf[i] = DEPTH_MAX;
359  }
360 
361  ps->gpu.is_init = false;
362  ps->gpu.prev_id = 0;
363  }
364  else {
365  /* Using cache `ps->is_cached == true`. */
366  /* `src.clip_rect` -> `dst.clip_rect`. */
368  BLI_assert(ps->gpu.rect_depth == NULL);
370  }
371 
372  if (mode == GPU_SELECT_PICK_ALL) {
373  ps->all.hits = MEM_mallocN(sizeof(*ps->all.hits) * ALLOC_DEPTHS, __func__);
374  ps->all.hits_len = 0;
375  ps->all.hits_len_alloc = ALLOC_DEPTHS;
376  }
377  else {
378  /* Set to 0xff for #SELECT_ID_NONE. */
379  ps->nearest.rect_id = MEM_mallocN(sizeof(uint) * ps->dst.rect_len, __func__);
380  memset(ps->nearest.rect_id, 0xff, sizeof(uint) * ps->dst.rect_len);
381  }
382 }
383 
388 static void gpu_select_load_id_pass_all(const DepthBufCache *rect_curr)
389 {
390  GPUPickState *ps = &g_pick_state;
391  const uint id = rect_curr->id;
392  /* find the best depth for this pass and store in 'all.hits' */
393  depth_t depth_best = DEPTH_MAX;
394 
395 #define EVAL_TEST() \
396  if (depth_best > *curr) { \
397  depth_best = *curr; \
398  } \
399  ((void)0)
400 
401  if (ps->is_cached == false) {
402  const depth_t *curr = rect_curr->buf;
403  BLI_assert(ps->src.rect_len == ps->dst.rect_len);
404  const uint rect_len = ps->src.rect_len;
405  for (uint i = 0; i < rect_len; i++, curr++) {
406  EVAL_TEST();
407  }
408  }
409  else {
410  /* Same as above but different rectangle sizes. */
411  const depth_t *curr = rect_curr->buf + ps->cache.sub_rect.start;
412  for (uint i = 0; i < ps->cache.sub_rect.span_len; i++) {
413  const depth_t *curr_end = curr + ps->cache.sub_rect.span;
414  for (; curr < curr_end; curr++) {
415  EVAL_TEST();
416  }
417  curr += ps->cache.sub_rect.skip;
418  }
419  }
420 
421 #undef EVAL_TEST
422 
423  /* Ensure enough space. */
424  if (UNLIKELY(ps->all.hits_len == ps->all.hits_len_alloc)) {
425  ps->all.hits_len_alloc += ALLOC_DEPTHS;
426  ps->all.hits = MEM_reallocN(ps->all.hits, ps->all.hits_len_alloc * sizeof(*ps->all.hits));
427  }
428  DepthID *d = &ps->all.hits[ps->all.hits_len++];
429  d->id = id;
430  d->depth = depth_best;
431 }
432 
433 static void gpu_select_load_id_pass_nearest(const DepthBufCache *rect_prev,
434  const DepthBufCache *rect_curr)
435 {
436  GPUPickState *ps = &g_pick_state;
437  const uint id = rect_curr->id;
438  /* Keep track each pixels ID in `nearest.rect_id`. */
439  if (id != SELECT_ID_NONE) {
440  uint *id_ptr = ps->nearest.rect_id;
441 
442  /* Check against DEPTH_MAX because XRAY will clear the buffer,
443  * so previously set values will become unset.
444  * In this case just leave those id's left as-is. */
445 #define EVAL_TEST() \
446  if (depth_is_filled(prev, curr)) { \
447  *id_ptr = id; \
448  } \
449  ((void)0)
450 
451  if (ps->is_cached == false) {
452  const depth_t *prev = rect_prev->buf;
453  const depth_t *curr = rect_curr->buf;
454  BLI_assert(ps->src.rect_len == ps->dst.rect_len);
455  const uint rect_len = ps->src.rect_len;
456  for (uint i = 0; i < rect_len; i++, curr++, prev++, id_ptr++) {
457  EVAL_TEST();
458  }
459  }
460  else {
461  /* same as above but different rect sizes */
462  const depth_t *prev = rect_prev->buf + ps->cache.sub_rect.start;
463  const depth_t *curr = rect_curr->buf + ps->cache.sub_rect.start;
464  for (uint i = 0; i < ps->cache.sub_rect.span_len; i++) {
465  const depth_t *curr_end = curr + ps->cache.sub_rect.span;
466  for (; curr < curr_end; prev++, curr++, id_ptr++) {
467  EVAL_TEST();
468  }
469  prev += ps->cache.sub_rect.skip;
470  curr += ps->cache.sub_rect.skip;
471  }
472  }
473 
474 #undef EVAL_TEST
475  }
476 }
477 
478 bool gpu_select_pick_load_id(uint id, bool end)
479 {
480  GPUPickState *ps = &g_pick_state;
481 
482  if (ps->gpu.is_init) {
483  if (id == ps->gpu.prev_id && !end) {
484  /* No need to read if we are still drawing for the same id since
485  * all these depths will be merged / de-duplicated in the end. */
486  return true;
487  }
488 
489  const uint rect_len = ps->src.rect_len;
493  /* Perform initial check since most cases the array remains unchanged. */
494 
495  bool do_pass = false;
497  if (depth_buf_rect_depth_any(ps->gpu.rect_depth_test, rect_len)) {
498  ps->gpu.rect_depth_test->id = ps->gpu.prev_id;
500  do_pass = true;
501  }
502  }
503  else {
505  ps->gpu.rect_depth_test->id = ps->gpu.prev_id;
507  do_pass = true;
508  }
509  }
510 
511  if (do_pass) {
512  /* Store depth in cache */
513  if (ps->use_cache) {
514  BLI_addtail(&ps->cache.bufs, ps->gpu.rect_depth);
516  }
517 
519 
521  /* (fclem) This is to be on the safe side. I don't know if this is required. */
522  bool prev_depth_mask = GPU_depth_mask_get();
523  /* we want new depths every time */
524  GPU_depth_mask(true);
525  GPU_clear_depth(1.0f);
526 
527  GPU_depth_mask(prev_depth_mask);
528  }
529  }
530  }
531 
532  ps->gpu.is_init = true;
533  ps->gpu.prev_id = id;
534 
535  return true;
536 }
537 
539 {
540  GPUPickState *ps = &g_pick_state;
541 
542 #ifdef DEBUG_PRINT
543  printf("%s\n", __func__);
544 #endif
545 
546  if (ps->is_cached == false) {
547  if (ps->gpu.is_init) {
548  /* force finishing last pass */
550  }
554  }
555 
557 
558  /* Assign but never free directly since it may be in cache. */
559  DepthBufCache *rect_depth_final;
560 
561  /* Store depth in cache */
562  if (ps->use_cache && !ps->is_cached) {
563  BLI_addtail(&ps->cache.bufs, ps->gpu.rect_depth);
564  ps->gpu.rect_depth = NULL;
565  rect_depth_final = ps->cache.bufs.last;
566  }
567  else if (ps->is_cached) {
568  rect_depth_final = ps->cache.bufs.last;
569  }
570  else {
571  /* Common case, no cache. */
572  rect_depth_final = ps->gpu.rect_depth;
573  }
574 
575  uint maxhits = g_pick_state.buffer_len;
576  DepthID *depth_data;
577  uint depth_data_len = 0;
578 
580  depth_data = ps->all.hits;
581  depth_data_len = ps->all.hits_len;
582  /* Move ownership. */
583  ps->all.hits = NULL;
584  ps->all.hits_len = 0;
585  ps->all.hits_len_alloc = 0;
586  }
587  else {
588  /* #GPU_SELECT_PICK_NEAREST */
589 
590  /* Over allocate (unlikely we have as many depths as pixels). */
591  uint depth_data_len_first_pass = 0;
592  depth_data = MEM_mallocN(ps->dst.rect_len * sizeof(*depth_data), __func__);
593 
594  /* Partially de-duplicating copy,
595  * when contiguous ID's are found - update their closest depth.
596  * This isn't essential but means there is less data to sort. */
597 
598 #define EVAL_TEST(i_src, i_dst) \
599  { \
600  const uint id = ps->nearest.rect_id[i_dst]; \
601  if (id != SELECT_ID_NONE) { \
602  const depth_t depth = rect_depth_final->buf[i_src]; \
603  if (depth_last == NULL || depth_last->id != id) { \
604  DepthID *d = &depth_data[depth_data_len_first_pass++]; \
605  d->id = id; \
606  d->depth = depth; \
607  } \
608  else if (depth_last->depth > depth) { \
609  depth_last->depth = depth; \
610  } \
611  } \
612  } \
613  ((void)0)
614 
615  {
616  DepthID *depth_last = NULL;
617  if (ps->is_cached == false) {
618  for (uint i = 0; i < ps->src.rect_len; i++) {
619  EVAL_TEST(i, i);
620  }
621  }
622  else {
623  /* Same as above but different rectangle sizes. */
624  uint i_src = ps->cache.sub_rect.start, i_dst = 0;
625  for (uint j = 0; j < ps->cache.sub_rect.span_len; j++) {
626  const uint i_src_end = i_src + ps->cache.sub_rect.span;
627  for (; i_src < i_src_end; i_src++, i_dst++) {
628  EVAL_TEST(i_src, i_dst);
629  }
630  i_src += ps->cache.sub_rect.skip;
631  }
632  }
633  }
634 
635 #undef EVAL_TEST
636 
637  qsort(depth_data, depth_data_len_first_pass, sizeof(DepthID), depth_id_cmp);
638 
639  /* Sort by ID's then keep the best depth for each ID. */
640  depth_data_len = 0;
641  {
642  DepthID *depth_last = NULL;
643  for (uint i = 0; i < depth_data_len_first_pass; i++) {
644  if (depth_last == NULL || depth_last->id != depth_data[i].id) {
645  depth_last = &depth_data[depth_data_len++];
646  *depth_last = depth_data[i];
647  }
648  else if (depth_last->depth > depth_data[i].depth) {
649  depth_last->depth = depth_data[i].depth;
650  }
651  }
652  }
653  }
654 
655  /* Finally sort each unique (id, depth) pair by depth
656  * so the final hit-list is sorted by depth (nearest first). */
657  uint hits = 0;
658 
659  if (depth_data_len > maxhits) {
660  hits = (uint)-1;
661  }
662  else {
663  /* Leave sorting up to the caller. */
664  qsort(depth_data, depth_data_len, sizeof(DepthID), depth_cmp);
665 
666  for (uint i = 0; i < depth_data_len; i++) {
667 #ifdef DEBUG_PRINT
668  printf(" hit: %u: depth %u\n", depth_data[i].id, depth_data[i].depth);
669 #endif
670  g_pick_state.buffer[hits].depth = depth_data[i].depth;
671  g_pick_state.buffer[hits].id = depth_data[i].id;
672  hits++;
673  }
674  BLI_assert(hits < maxhits);
675  }
676 
677  MEM_freeN(depth_data);
678 
681 
683  /* 'hits' already freed as 'depth_data' */
684  }
685  else {
686  MEM_freeN(ps->nearest.rect_id);
687  ps->nearest.rect_id = NULL;
688  }
689 
690  if (ps->use_cache) {
691  ps->is_cached = true;
692  }
693 
694  return hits;
695 }
696 
699 /* -------------------------------------------------------------------- */
706 {
708 #ifdef DEBUG_PRINT
709  printf("%s\n", __func__);
710 #endif
711  g_pick_state.use_cache = true;
712  g_pick_state.is_cached = false;
713 }
714 
716 {
717 #ifdef DEBUG_PRINT
718  printf("%s: with %d buffers\n", __func__, BLI_listbase_count(&g_pick_state.cache.bufs));
719 #endif
720  g_pick_state.use_cache = false;
721  g_pick_state.is_cached = false;
722 
724 }
725 
727 {
728  return g_pick_state.is_cached;
729 }
730 
732 {
734  GPUPickState *ps = &g_pick_state;
735 #ifdef DEBUG_PRINT
736  printf("%s (building depth from cache)\n", __func__);
737 #endif
738  LISTBASE_FOREACH (DepthBufCache *, rect_depth, &ps->cache.bufs) {
739  if (rect_depth->next != NULL) {
740  /* We know the buffers differ, but this sub-region may not.
741  * Double check before adding an id-pass. */
743  if (depth_buf_subrect_depth_any(rect_depth->next, &ps->cache.sub_rect)) {
744  gpu_select_load_id_pass_all(rect_depth->next);
745  }
746  }
747  else {
749  rect_depth, rect_depth->next, &ps->cache.sub_rect)) {
750  gpu_select_load_id_pass_nearest(rect_depth, rect_depth->next);
751  }
752  }
753  }
754  }
755 }
756 
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_INLINE
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:466
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition: BLI_rect.h:190
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition: BLI_rect.h:186
Strict compiler flags for areas of code we want to ensure don't do conversions without us knowing abo...
unsigned int uint
Definition: BLI_sys_types.h:67
#define UNPACK4(a)
#define SWAP(type, a, b)
#define UNLIKELY(x)
void GPU_debug_group_end(void)
Definition: gpu_debug.cc:32
void GPU_debug_group_begin(const char *name)
Definition: gpu_debug.cc:21
struct GPUFrameBuffer GPUFrameBuffer
GPUFrameBuffer * GPU_framebuffer_active_get(void)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
eGPUSelectMode
Definition: GPU_select.h:19
@ GPU_SELECT_PICK_ALL
Definition: GPU_select.h:25
void GPU_write_mask(eGPUWriteMask mask)
Definition: gpu_state.cc:90
eGPUWriteMask
Definition: GPU_state.h:11
void GPU_depth_mask(bool depth)
Definition: gpu_state.cc:107
void GPU_color_mask(bool r, bool g, bool b, bool a)
Definition: gpu_state.cc:95
eGPUWriteMask GPU_write_mask_get(void)
Definition: gpu_state.cc:224
void GPU_viewport(int x, int y, int width, int height)
Definition: gpu_state.cc:191
bool GPU_depth_mask_get(void)
Definition: gpu_state.cc:273
eGPUDepthTest
Definition: GPU_state.h:82
@ GPU_DEPTH_LESS_EQUAL
Definition: GPU_state.h:86
eGPUDepthTest GPU_depth_test_get(void)
Definition: gpu_state.cc:236
void GPU_depth_test(eGPUDepthTest test)
Definition: gpu_state.cc:65
void GPU_viewport_size_get_f(float coords[4])
Definition: gpu_state.cc:259
void GPU_scissor_get(int coords[4])
Definition: gpu_state.cc:254
@ GPU_DATA_UINT
Definition: GPU_texture.h:173
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
#define MEM_reallocN(vmemh, len)
ATTR_WARN_UNUSED_RESULT const BMVert * v2
SyclQueue void void * src
void GPU_clear_depth(float depth)
void GPU_framebuffer_read_depth(GPUFrameBuffer *gpu_fb, int x, int y, int w, int h, eGPUDataFormat format, void *data)
bool gpu_select_pick_load_id(uint id, bool end)
#define DEPTH_MAX
void gpu_select_pick_begin(GPUSelectResult *buffer, const uint buffer_len, const rcti *input, eGPUSelectMode mode)
static bool depth_buf_subrect_depth_any(const DepthBufCache *rect_depth, const SubRectStride *sub_rect)
#define ALLOC_DEPTHS
struct GPUPickState GPUPickState
static int depth_cmp(const void *v1, const void *v2)
uint depth_t
struct SubRectStride SubRectStride
BLI_INLINE bool depth_is_filled(const depth_t *prev, const depth_t *curr)
bool gpu_select_pick_is_cached(void)
struct DepthID DepthID
static bool depth_buf_subrect_depth_any_filled(const DepthBufCache *rect_src, const DepthBufCache *rect_dst, const SubRectStride *sub_rect)
static void rect_subregion_stride_calc(const rcti *src, const rcti *dst, SubRectStride *r_sub)
#define EVAL_TEST()
void gpu_select_pick_cache_end(void)
static int depth_id_cmp(const void *v1, const void *v2)
uint gpu_select_pick_end(void)
static DepthBufCache * depth_buf_malloc(uint rect_len)
static GPUPickState g_pick_state
struct DepthBufCache DepthBufCache
static void gpu_select_load_id_pass_all(const DepthBufCache *rect_curr)
static bool depth_buf_rect_depth_any_filled(const DepthBufCache *rect_prev, const DepthBufCache *rect_curr, uint rect_len)
static void gpu_select_load_id_pass_nearest(const DepthBufCache *rect_prev, const DepthBufCache *rect_curr)
void gpu_select_pick_cache_begin(void)
static bool depth_buf_rect_depth_any(const DepthBufCache *rect_depth, uint rect_len)
void gpu_select_pick_cache_load_id(void)
#define SELECT_ID_NONE
BLI_INLINE float fb(float length, float L)
ccl_global float * buffer
ccl_global KernelShaderEvalInput * input
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
SymEdge< T > * prev(const SymEdge< T > *se)
Definition: delaunay_2d.cc:105
depth_t buf[0]
struct DepthBufCache * next
struct DepthBufCache * prev
depth_t depth
struct GPUPickState::@670::@672 all
struct GPUPickState::@668 dst
DepthBufCache * rect_depth
struct GPUPickState::@670::@673 nearest
struct GPUPickState::@668 src
struct GPUPickState::@667 gpu
eGPUWriteMask write_mask
GPUSelectResult * buffer
eGPUDepthTest depth_test
struct GPUPickState::@669 cache
SubRectStride sub_rect
int clip_readpixels[4]
DepthID * hits
DepthBufCache * rect_depth_test
eGPUSelectMode mode
unsigned int id
Definition: GPU_select.h:34
unsigned int depth
Definition: GPU_select.h:42
void * last
Definition: DNA_listBase.h:31
int ymin
Definition: DNA_vec_types.h:64
int ymax
Definition: DNA_vec_types.h:64
int xmin
Definition: DNA_vec_types.h:63
int xmax
Definition: DNA_vec_types.h:63