Blender  V3.3
draw_cache_impl_displist.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 
12 #include "BLI_edgehash.h"
13 #include "BLI_listbase.h"
14 #include "BLI_math_vector.h"
15 #include "BLI_utildefines.h"
16 
17 #include "DNA_curve_types.h"
18 #include "DNA_scene_types.h"
19 
20 #include "BKE_displist.h"
21 
22 #include "GPU_batch.h"
23 #include "GPU_capabilities.h"
24 
25 #include "draw_cache_inline.h"
26 
27 #include "draw_cache_impl.h" /* own include */
28 
29 static int dl_vert_len(const DispList *dl)
30 {
31  switch (dl->type) {
32  case DL_INDEX3:
33  case DL_INDEX4:
34  return dl->nr;
35  case DL_SURF:
36  return dl->parts * dl->nr;
37  }
38  return 0;
39 }
40 
41 static int dl_tri_len(const DispList *dl)
42 {
43  switch (dl->type) {
44  case DL_INDEX3:
45  return dl->parts;
46  case DL_INDEX4:
47  return dl->parts * 2;
48  case DL_SURF:
49  return dl->totindex * 2;
50  }
51  return 0;
52 }
53 
54 /* see: displist_vert_coords_alloc */
56 {
57  int vert_len = 0;
58  LISTBASE_FOREACH (const DispList *, dl, lb) {
59  vert_len += dl_vert_len(dl);
60  }
61  return vert_len;
62 }
63 
65 {
66  int tri_len = 0;
67  LISTBASE_FOREACH (const DispList *, dl, lb) {
68  tri_len += dl_tri_len(dl);
69  }
70  return tri_len;
71 }
72 
73 typedef void(SetTriIndicesFn)(void *thunk, uint v1, uint v2, uint v3);
74 
76  SetTriIndicesFn *set_tri_indices,
77  SetTriIndicesFn *set_quad_tri_indices, /* meh, find a better solution. */
78  void *thunk,
79  const DispList *dl,
80  const int ofs)
81 {
82  if (ELEM(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) {
83  const int *idx = dl->index;
84  if (dl->type == DL_INDEX3) {
85  const int i_end = dl->parts;
86  for (int i = 0; i < i_end; i++, idx += 3) {
87  set_tri_indices(thunk, idx[0] + ofs, idx[2] + ofs, idx[1] + ofs);
88  }
89  }
90  else if (dl->type == DL_SURF) {
91  const int i_end = dl->totindex;
92  for (int i = 0; i < i_end; i++, idx += 4) {
93  set_quad_tri_indices(thunk, idx[0] + ofs, idx[2] + ofs, idx[1] + ofs);
94  set_quad_tri_indices(thunk, idx[2] + ofs, idx[0] + ofs, idx[3] + ofs);
95  }
96  }
97  else {
98  BLI_assert(dl->type == DL_INDEX4);
99  const int i_end = dl->parts;
100  for (int i = 0; i < i_end; i++, idx += 4) {
101  if (idx[2] != idx[3]) {
102  set_quad_tri_indices(thunk, idx[2] + ofs, idx[0] + ofs, idx[1] + ofs);
103  set_quad_tri_indices(thunk, idx[0] + ofs, idx[2] + ofs, idx[3] + ofs);
104  }
105  else {
106  set_tri_indices(thunk, idx[2] + ofs, idx[0] + ofs, idx[1] + ofs);
107  }
108  }
109  }
110  }
111 }
112 
114 {
115  const bool do_hq_normals = (scene->r.perf_flag & SCE_PERF_HQ_NORMALS) != 0 ||
117 
118  static GPUVertFormat format = {0};
119  static GPUVertFormat format_hq = {0};
120  static struct {
121  uint pos, nor;
122  uint pos_hq, nor_hq;
123  } attr_id;
124  if (format.attr_len == 0) {
125  /* initialize vertex format */
129  /* initialize vertex format */
130  attr_id.pos_hq = GPU_vertformat_attr_add(&format_hq, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
132  &format_hq, "nor", GPU_COMP_I16, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
133  }
134 
135  uint pos_id = do_hq_normals ? attr_id.pos_hq : attr_id.pos;
136  uint nor_id = do_hq_normals ? attr_id.nor_hq : attr_id.nor;
137 
138  GPU_vertbuf_init_with_format(vbo, do_hq_normals ? &format_hq : &format);
140 
142 
143  int vbo_len_used = 0;
144  LISTBASE_FOREACH (const DispList *, dl, lb) {
145  const bool ndata_is_single = dl->type == DL_INDEX3;
146  if (ELEM(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) {
147  const float *fp_co = dl->verts;
148  const float *fp_no = dl->nors;
149  const int vbo_end = vbo_len_used + dl_vert_len(dl);
150  while (vbo_len_used < vbo_end) {
151  GPU_vertbuf_attr_set(vbo, pos_id, vbo_len_used, fp_co);
152  if (fp_no) {
153  GPUNormal vnor_pack;
154  GPU_normal_convert_v3(&vnor_pack, fp_no, do_hq_normals);
155  GPU_vertbuf_attr_set(vbo, nor_id, vbo_len_used, &vnor_pack);
156  if (ndata_is_single == false) {
157  fp_no += 3;
158  }
159  }
160  fp_co += 3;
161  vbo_len_used += 1;
162  }
163  }
164  }
165 }
166 
167 void DRW_vertbuf_create_wiredata(GPUVertBuf *vbo, const int vert_len)
168 {
169  static GPUVertFormat format = {0};
170  static struct {
171  uint wd;
172  } attr_id;
173  if (format.attr_len == 0) {
174  /* initialize vertex format */
175  if (!GPU_crappy_amd_driver()) {
176  /* Some AMD drivers strangely crash with a vbo with this format. */
179  }
180  else {
182  }
183  }
184 
186  GPU_vertbuf_data_alloc(vbo, vert_len);
187 
188  if (GPU_vertbuf_get_format(vbo)->stride == 1) {
189  memset(GPU_vertbuf_get_data(vbo), 0xFF, (size_t)vert_len);
190  }
191  else {
192  GPUVertBufRaw wd_step;
193  GPU_vertbuf_attr_get_raw_data(vbo, attr_id.wd, &wd_step);
194  for (int i = 0; i < vert_len; i++) {
195  *((float *)GPU_vertbuf_raw_step(&wd_step)) = 1.0f;
196  }
197  }
198 }
199 
201 {
202  const int vert_len = curve_render_surface_vert_len_get(lb);
203  DRW_vertbuf_create_wiredata(vbo, vert_len);
204 }
205 
207 {
208  const int tri_len = curve_render_surface_tri_len_get(lb);
209  const int vert_len = curve_render_surface_vert_len_get(lb);
210 
211  GPUIndexBufBuilder elb;
212  GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, tri_len, vert_len);
213 
214  int ofs = 0;
215  LISTBASE_FOREACH (const DispList *, dl, lb) {
218  &elb,
219  dl,
220  ofs);
221  ofs += dl_vert_len(dl);
222  }
223 
224  GPU_indexbuf_build_in_place(&elb, ibo);
225 }
226 
227 static void set_overlay_wires_tri_indices(void *thunk, uint v1, uint v2, uint v3)
228 {
229  GPUIndexBufBuilder *eld = (GPUIndexBufBuilder *)thunk;
233 }
234 
235 static void set_overlay_wires_quad_tri_indices(void *thunk, uint v1, uint v2, uint v3)
236 {
237  GPUIndexBufBuilder *eld = (GPUIndexBufBuilder *)thunk;
240 }
241 
243 {
244  const int tri_len = curve_render_surface_tri_len_get(lb);
245  const int vert_len = curve_render_surface_vert_len_get(lb);
246 
247  GPUIndexBufBuilder elb;
248  GPU_indexbuf_init(&elb, GPU_PRIM_LINES, tri_len * 3, vert_len);
249 
250  int ofs = 0;
251  LISTBASE_FOREACH (const DispList *, dl, lb) {
254  ofs += dl_vert_len(dl);
255  }
256 
257  GPU_indexbuf_build_in_place(&elb, ibo);
258 }
259 
260 /* Edge detection/adjacency. */
261 #define NO_EDGE INT_MAX
263  EdgeHash *eh, GPUIndexBufBuilder *elb, bool *r_is_manifold, uint v1, uint v2, uint v3)
264 {
265  bool inv_indices = (v2 > v3);
266  void **pval;
267  bool value_is_init = BLI_edgehash_ensure_p(eh, v2, v3, &pval);
268  int v_data = POINTER_AS_INT(*pval);
269  if (!value_is_init || v_data == NO_EDGE) {
270  /* Save the winding order inside the sign bit. Because the
271  * edgehash sort the keys and we need to compare winding later. */
272  int value = (int)v1 + 1; /* Int 0 bm_looptricannot be signed */
273  *pval = POINTER_FROM_INT((inv_indices) ? -value : value);
274  }
275  else {
276  /* HACK Tag as not used. Prevent overhead of BLI_edgehash_remove. */
277  *pval = POINTER_FROM_INT(NO_EDGE);
278  bool inv_opposite = (v_data < 0);
279  uint v_opposite = (uint)abs(v_data) - 1;
280 
281  if (inv_opposite == inv_indices) {
282  /* Don't share edge if triangles have non matching winding. */
284  GPU_indexbuf_add_line_adj_verts(elb, v_opposite, v2, v3, v_opposite);
285  *r_is_manifold = false;
286  }
287  else {
288  GPU_indexbuf_add_line_adj_verts(elb, v1, v2, v3, v_opposite);
289  }
290  }
291 }
292 
293 static void set_edges_adjacency_lines_indices(void *thunk, uint v1, uint v2, uint v3)
294 {
295  void **packed = (void **)thunk;
296  GPUIndexBufBuilder *elb = (GPUIndexBufBuilder *)packed[0];
297  EdgeHash *eh = (EdgeHash *)packed[1];
298  bool *r_is_manifold = (bool *)packed[2];
299 
300  set_edge_adjacency_lines_indices(eh, elb, r_is_manifold, v1, v2, v3);
301  set_edge_adjacency_lines_indices(eh, elb, r_is_manifold, v2, v3, v1);
302  set_edge_adjacency_lines_indices(eh, elb, r_is_manifold, v3, v1, v2);
303 }
304 
306  struct GPUIndexBuf *ibo,
307  bool *r_is_manifold)
308 {
309  const int tri_len = curve_render_surface_tri_len_get(lb);
310  const int vert_len = curve_render_surface_vert_len_get(lb);
311 
312  *r_is_manifold = true;
313 
314  /* Allocate max but only used indices are sent to GPU. */
315  GPUIndexBufBuilder elb;
316  GPU_indexbuf_init(&elb, GPU_PRIM_LINES_ADJ, tri_len * 3, vert_len);
317 
318  EdgeHash *eh = BLI_edgehash_new_ex(__func__, tri_len * 3);
319 
320  /* pack values to pass to `set_edges_adjacency_lines_indices` function. */
321  void *thunk[3] = {&elb, eh, r_is_manifold};
322  int v_idx = 0;
323  LISTBASE_FOREACH (const DispList *, dl, lb) {
326  thunk,
327  dl,
328  v_idx);
329  v_idx += dl_vert_len(dl);
330  }
331 
332  /* Create edges for remaining non manifold edges. */
333  EdgeHashIterator *ehi;
334  for (ehi = BLI_edgehashIterator_new(eh); BLI_edgehashIterator_isDone(ehi) == false;
336  uint v1, v2;
338  if (v_data == NO_EDGE) {
339  continue;
340  }
342  uint v0 = (uint)abs(v_data) - 1;
343  if (v_data < 0) { /* inv_opposite */
344  SWAP(uint, v1, v2);
345  }
346  GPU_indexbuf_add_line_adj_verts(&elb, v0, v1, v2, v0);
347  *r_is_manifold = false;
348  }
350  BLI_edgehash_free(eh, NULL);
351 
352  GPU_indexbuf_build_in_place(&elb, ibo);
353 }
354 #undef NO_EDGE
display list (or rather multi purpose list) stuff.
@ DL_SURF
Definition: BKE_displist.h:24
@ DL_INDEX4
Definition: BKE_displist.h:28
@ DL_INDEX3
Definition: BKE_displist.h:26
void BKE_displist_normals_add(struct ListBase *lb)
Definition: displist.cc:102
#define BLI_assert(a)
Definition: BLI_assert.h:46
void BLI_edgehash_free(EdgeHash *eh, EdgeHashFreeFP free_value)
Definition: edgehash.c:230
BLI_INLINE void BLI_edgehashIterator_getKey(EdgeHashIterator *ehi, unsigned int *r_v0, unsigned int *r_v1)
Definition: BLI_edgehash.h:161
EdgeHashIterator * BLI_edgehashIterator_new(EdgeHash *eh) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition: edgehash.c:394
bool BLI_edgehash_ensure_p(EdgeHash *eh, unsigned int v0, unsigned int v1, void ***r_val) ATTR_WARN_UNUSED_RESULT
Definition: edgehash.c:307
BLI_INLINE void BLI_edgehashIterator_step(EdgeHashIterator *ehi)
Definition: BLI_edgehash.h:153
void BLI_edgehashIterator_free(EdgeHashIterator *ehi)
Definition: edgehash.c:408
BLI_INLINE void * BLI_edgehashIterator_getValue(EdgeHashIterator *ehi)
Definition: BLI_edgehash.h:169
BLI_INLINE bool BLI_edgehashIterator_isDone(const EdgeHashIterator *ehi)
Definition: BLI_edgehash.h:157
EdgeHash * BLI_edgehash_new_ex(const char *info, unsigned int nentries_reserve)
Definition: edgehash.c:212
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
unsigned int uint
Definition: BLI_sys_types.h:67
#define SWAP(type, a, b)
#define POINTER_FROM_INT(i)
#define POINTER_AS_INT(i)
#define ELEM(...)
@ SCE_PERF_HQ_NORMALS
bool GPU_use_hq_normals_workaround(void)
bool GPU_crappy_amd_driver(void)
struct GPUIndexBuf GPUIndexBuf
void GPU_indexbuf_init(GPUIndexBufBuilder *, GPUPrimType, uint prim_len, uint vertex_len)
void GPU_indexbuf_add_line_verts(GPUIndexBufBuilder *, uint v1, uint v2)
void GPU_indexbuf_add_line_adj_verts(GPUIndexBufBuilder *, uint v1, uint v2, uint v3, uint v4)
void GPU_indexbuf_build_in_place(GPUIndexBufBuilder *, GPUIndexBuf *)
void GPU_indexbuf_add_tri_verts(GPUIndexBufBuilder *, uint v1, uint v2, uint v3)
_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 stride
_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
@ GPU_PRIM_LINES
Definition: GPU_primitive.h:20
@ GPU_PRIM_LINES_ADJ
Definition: GPU_primitive.h:29
@ GPU_PRIM_TRIS
Definition: GPU_primitive.h:21
const GPUVertFormat * GPU_vertbuf_get_format(const GPUVertBuf *verts)
struct GPUVertBuf GPUVertBuf
void GPU_vertbuf_data_alloc(GPUVertBuf *, uint v_len)
#define GPU_vertbuf_init_with_format(verts, format)
void * GPU_vertbuf_get_data(const GPUVertBuf *verts)
GPU_INLINE void * GPU_vertbuf_raw_step(GPUVertBufRaw *a)
void GPU_vertbuf_attr_get_raw_data(GPUVertBuf *, uint a_idx, GPUVertBufRaw *access)
void GPU_vertbuf_attr_set(GPUVertBuf *, uint a_idx, uint v_idx, const void *data)
@ GPU_FETCH_FLOAT
@ GPU_FETCH_INT_TO_FLOAT_UNIT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
BLI_INLINE void GPU_normal_convert_v3(GPUNormal *gpu_normal, const float data[3], const bool do_hq_normals)
@ GPU_COMP_I10
@ GPU_COMP_F32
@ GPU_COMP_I16
@ GPU_COMP_U8
ATTR_WARN_UNUSED_RESULT const BMVert * v2
Scene scene
SyclQueue void void size_t num_bytes void
void DRW_displist_indexbuf_create_edges_adjacency_lines(struct ListBase *lb, struct GPUIndexBuf *ibo, bool *r_is_manifold)
void() SetTriIndicesFn(void *thunk, uint v1, uint v2, uint v3)
static int curve_render_surface_vert_len_get(const ListBase *lb)
static void set_edges_adjacency_lines_indices(void *thunk, uint v1, uint v2, uint v3)
#define NO_EDGE
static void displist_indexbufbuilder_set(SetTriIndicesFn *set_tri_indices, SetTriIndicesFn *set_quad_tri_indices, void *thunk, const DispList *dl, const int ofs)
void DRW_displist_vertbuf_create_wiredata(ListBase *lb, GPUVertBuf *vbo)
void DRW_displist_vertbuf_create_pos_and_nor(ListBase *lb, GPUVertBuf *vbo, const Scene *scene)
static int dl_vert_len(const DispList *dl)
static void set_overlay_wires_tri_indices(void *thunk, uint v1, uint v2, uint v3)
static int curve_render_surface_tri_len_get(const ListBase *lb)
void DRW_displist_indexbuf_create_triangles_in_order(ListBase *lb, GPUIndexBuf *ibo)
void DRW_vertbuf_create_wiredata(GPUVertBuf *vbo, const int vert_len)
static void set_overlay_wires_quad_tri_indices(void *thunk, uint v1, uint v2, uint v3)
void DRW_displist_indexbuf_create_lines_in_order(ListBase *lb, GPUIndexBuf *ibo)
static int dl_tri_len(const DispList *dl)
static void set_edge_adjacency_lines_indices(EdgeHash *eh, GPUIndexBufBuilder *elb, bool *r_is_manifold, uint v1, uint v2, uint v3)
uint pos
uint nor
struct @653::@656 attr_id
format
Definition: logImageCore.h:38
T abs(const T &a)
short type
Definition: BKE_displist.h:55
int totindex
Definition: BKE_displist.h:61
int * index
Definition: BKE_displist.h:59
struct RenderData r