Panda3D
geomVertexArrayData.I
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file geomVertexArrayData.I
10  * @author drose
11  * @date 2005-03-17
12  */
13 
14 /**
15  * Returns the format object that describes this array.
16  */
18 get_array_format() const {
19  return _array_format;
20 }
21 
22 /**
23  * Returns the usage hint that describes to the rendering backend how often
24  * the vertex data will be modified and/or rendered. See geomEnums.h.
25  */
26 INLINE GeomVertexArrayData::UsageHint GeomVertexArrayData::
27 get_usage_hint() const {
28  CDReader cdata(_cycler);
29  return cdata->_usage_hint;
30 }
31 
32 /**
33  * Returns true if the array has the named column, false otherwise. This is
34  * really just a shortcut for asking the same thing from the format.
35  */
37 has_column(const InternalName *name) const {
38  return _array_format->has_column(name);
39 }
40 
41 /**
42  * Returns the number of rows stored in the array, based on the number of
43  * bytes and the stride. This should be the same for all arrays within a
44  * given GeomVertexData object.
45  */
47 get_num_rows() const {
48  CDReader cdata(_cycler);
49  nassertr(_array_format->get_stride() != 0, 0);
50  return cdata->_buffer.get_size() / _array_format->get_stride();
51 }
52 
53 /**
54  * Sets the length of the array to n rows.
55  *
56  * Normally, you would not call this directly, since all of the arrays in a
57  * particular GeomVertexData must have the same number of rows; instead, call
58  * GeomVertexData::set_num_rows().
59  *
60  * The return value is true if the number of rows was changed, false if the
61  * object already contained n rows (or if there was some error).
62  *
63  * The new vertex data is initialized to 0, including the "color" column (but
64  * see GeomVertexData::set_num_rows()).
65  *
66  * Don't call this in a downstream thread unless you don't mind it blowing
67  * away other changes you might have recently made in an upstream thread.
68  */
70 set_num_rows(int n) {
71  return modify_handle()->set_num_rows(n);
72 }
73 
74 /**
75  * This method behaves like set_num_rows(), except the new data is not
76  * initialized. Furthermore, after this call, *any* of the data in the
77  * GeomVertexArrayData may be uninitialized, including the earlier rows.
78  *
79  * Normally, you would not call this directly, since all of the arrays in a
80  * particular GeomVertexData must have the same number of rows; instead, call
81  * GeomVertexData::unclean_set_num_rows().
82  */
84 unclean_set_num_rows(int n) {
85  return modify_handle()->unclean_set_num_rows(n);
86 }
87 
88 /**
89  * This ensures that enough memory space for n rows is allocated, so that you
90  * may increase the number of rows to n without causing a new memory
91  * allocation. This is a performance optimization only; it is especially
92  * useful when you know ahead of time that you will be adding n rows to the
93  * data.
94  */
96 reserve_num_rows(int n) {
97  return modify_handle()->reserve_num_rows(n);
98 }
99 
100 /**
101  * Removes all of the rows in the array. Functionally equivalent to
102  * set_num_rows(0).
103  */
105 clear_rows() {
106  return modify_handle()->clear_rows();
107 }
108 
109 /**
110  * Returns the number of bytes stored in the array.
111  */
112 INLINE size_t GeomVertexArrayData::
113 get_data_size_bytes() const {
114  CDReader cdata(_cycler);
115  return cdata->_buffer.get_size();
116 }
117 
118 /**
119  * Returns a sequence number which is guaranteed to change at least every time
120  * the array vertex data is modified.
121  */
123 get_modified() const {
124  CDReader cdata(_cycler);
125  return cdata->_modified;
126 }
127 
128 /**
129  * Returns true if the vertex data is currently resident in memory. If this
130  * returns true, the next call to get_handle()->get_read_pointer() will
131  * probably not block. If this returns false, the vertex data will be brought
132  * back into memory shortly; try again later.
133  */
135 request_resident(Thread *current_thread) const {
136  const GeomVertexArrayData::CData *cdata = _cycler.read_unlocked(current_thread);
137 
138 #ifdef DO_PIPELINING
139  cdata->ref();
140 #endif
141 
142  cdata->_rw_lock.acquire();
143 
144  ((GeomVertexArrayData *)this)->mark_used();
145  bool is_resident = (cdata->_buffer.get_read_pointer(false) != nullptr);
146 
147  cdata->_rw_lock.release();
148 
149 #ifdef DO_PIPELINING
150  unref_delete((CycleData *)cdata);
151 #endif
152 
153  return is_resident;
154 }
155 
156 /**
157  * Returns an object that can be used to read the actual data bytes stored in
158  * the array. Calling this method locks the data, and will block any other
159  * threads attempting to read or write the data, until the returned object
160  * destructs.
161  */
162 INLINE CPT(GeomVertexArrayDataHandle) GeomVertexArrayData::
163 get_handle(Thread *current_thread) const {
164  return new GeomVertexArrayDataHandle(this, current_thread);
165 }
166 
167 /**
168  * Returns an object that can be used to read or write the actual data bytes
169  * stored in the array. Calling this method locks the data, and will block
170  * any other threads attempting to read or write the data, until the returned
171  * object destructs.
172  */
173 INLINE PT(GeomVertexArrayDataHandle) GeomVertexArrayData::
174 modify_handle(Thread *current_thread) {
175  return new GeomVertexArrayDataHandle(PT(GeomVertexArrayData)(this), current_thread);
176 }
177 
178 /**
179  * Returns a pointer to the global LRU object that manages the
180  * GeomVertexArrayData's that have not (yet) been paged out.
181  */
184  return &_independent_lru;
185 }
186 
187 /**
188  * Returns a pointer to the global LRU object that manages the
189  * GeomVertexArrayData's that are deemed too small to be paged out.
190  */
192 get_small_lru() {
193  return &_small_lru;
194 }
195 
196 /**
197  * Returns the global VertexDataBook that will be used to allocate vertex data
198  * buffers.
199  */
201 get_book() {
202  return _book;
203 }
204 
205 /**
206  * Should be called when the size of the buffer changes.
207  */
208 INLINE void GeomVertexArrayData::
209 set_lru_size(size_t lru_size) {
210  SimpleLruPage::set_lru_size(lru_size);
211 
212  if ((int)lru_size <= vertex_data_small_size) {
213  SimpleLruPage::mark_used_lru(&_small_lru);
214  } else {
215  SimpleLruPage::mark_used_lru(&_independent_lru);
216  }
217 }
218 
219 /**
220  */
221 INLINE void GeomVertexArrayData::
222 mark_used() {
223  if ((int)get_lru_size() <= vertex_data_small_size) {
224  SimpleLruPage::mark_used_lru(&_small_lru);
225  } else {
226  SimpleLruPage::mark_used_lru(&_independent_lru);
227  }
228 }
229 
230 /**
231  *
232  */
233 INLINE GeomVertexArrayData::CData::
234 CData(UsageHint usage_hint) :
235  _usage_hint(usage_hint),
236  _rw_lock("GeomVertexArrayData::CData::_rw_lock")
237 {
238 }
239 
240 /**
241  *
242  */
243 INLINE GeomVertexArrayData::CData::
244 CData(GeomVertexArrayData::CData &&from) noexcept :
245  _usage_hint(std::move(from._usage_hint)),
246  _buffer(std::move(from._buffer)),
247  _modified(std::move(from._modified)),
248  _rw_lock("GeomVertexArrayData::CData::_rw_lock")
249 {
250 }
251 
252 /**
253  *
254  */
255 INLINE GeomVertexArrayData::CData::
256 CData(const GeomVertexArrayData::CData &copy) :
257  _usage_hint(copy._usage_hint),
258  _buffer(copy._buffer),
259  _modified(copy._modified),
260  _rw_lock("GeomVertexArrayData::CData::_rw_lock")
261 {
262 }
263 
264 /**
265  *
266  */
267 INLINE void GeomVertexArrayData::CData::
268 operator = (const GeomVertexArrayData::CData &copy) {
269  _usage_hint = copy._usage_hint;
270  _buffer = copy._buffer;
271  _modified = copy._modified;
272 }
273 
274 /**
275  *
276  */
277 INLINE GeomVertexArrayDataHandle::
278 GeomVertexArrayDataHandle(CPT(GeomVertexArrayData) object,
279  Thread *current_thread) :
280  _current_thread(current_thread),
281  _cdata((GeomVertexArrayData::CData *)object->_cycler.read_unlocked(current_thread)),
282  _writable(false)
283 {
284  _object.swap(object);
285 
286 #ifdef _DEBUG
287  nassertv(_object->test_ref_count_nonzero());
288 #endif // _DEBUG
289 #ifdef DO_PIPELINING
290  _cdata->ref();
291 #endif // DO_PIPELINING
292  // We must grab the lock *after* we have incremented the reference count,
293  // above.
294  _cdata->_rw_lock.acquire();
295 #ifdef DO_MEMORY_USAGE
296  MemoryUsage::update_type(this, get_class_type());
297 #endif
298 }
299 
300 /**
301  *
302  */
303 INLINE GeomVertexArrayDataHandle::
304 GeomVertexArrayDataHandle(const GeomVertexArrayData *object,
305  Thread *current_thread) :
306  _object((GeomVertexArrayData *)object),
307  _current_thread(current_thread),
308  _cdata((GeomVertexArrayData::CData *)object->_cycler.read_unlocked(current_thread)),
309  _writable(false)
310 {
311 #ifdef _DEBUG
312  nassertv(_object->test_ref_count_nonzero());
313 #endif // _DEBUG
314 #ifdef DO_PIPELINING
315  _cdata->ref();
316 #endif // DO_PIPELINING
317  // We must grab the lock *after* we have incremented the reference count,
318  // above.
319  _cdata->_rw_lock.acquire();
320 #ifdef DO_MEMORY_USAGE
321  MemoryUsage::update_type(this, get_class_type());
322 #endif
323 }
324 
325 /**
326  *
327  */
328 INLINE GeomVertexArrayDataHandle::
329 GeomVertexArrayDataHandle(PT(GeomVertexArrayData) object,
330  Thread *current_thread) :
331  _current_thread(current_thread),
332  _cdata(object->_cycler.write_upstream(true, current_thread)),
333  _writable(true)
334 {
335  _object.swap(object);
336 
337 #ifdef _DEBUG
338  nassertv(_object->test_ref_count_nonzero());
339 #endif // _DEBUG
340 #ifdef DO_PIPELINING
341  _cdata->ref();
342 #endif // DO_PIPELINING
343  // We must grab the lock *after* we have incremented the reference count,
344  // above.
345  _cdata->_rw_lock.acquire();
346 #ifdef DO_MEMORY_USAGE
347  MemoryUsage::update_type(this, get_class_type());
348 #endif
349 }
350 
351 /**
352  *
353  */
354 INLINE GeomVertexArrayDataHandle::
355 GeomVertexArrayDataHandle(GeomVertexArrayData *object,
356  Thread *current_thread) :
357  _object(object),
358  _current_thread(current_thread),
359  _cdata(object->_cycler.write_upstream(true, current_thread)),
360  _writable(true)
361 {
362 #ifdef _DEBUG
363  nassertv(_object->test_ref_count_nonzero());
364 #endif // _DEBUG
365 #ifdef DO_PIPELINING
366  _cdata->ref();
367 #endif // DO_PIPELINING
368  // We must grab the lock *after* we have incremented the reference count,
369  // above.
370  _cdata->_rw_lock.acquire();
371 #ifdef DO_MEMORY_USAGE
372  MemoryUsage::update_type(this, get_class_type());
373 #endif
374 }
375 
376 /**
377  *
378  */
379 INLINE GeomVertexArrayDataHandle::
380 ~GeomVertexArrayDataHandle() {
381 #ifdef _DEBUG
382  nassertv(_object->test_ref_count_nonzero());
383 #endif // _DEBUG
384 
385  if (_writable) {
386  _object->_cycler.release_write(_cdata);
387  }
388 
389  // We must release the lock *before* we decrement the reference count,
390  // below.
391  _cdata->_rw_lock.release();
392 
393 #ifdef DO_PIPELINING
394  unref_delete((CycleData *)_cdata);
395 #endif // DO_PIPELINING
396 
397 #ifdef _DEBUG
398  _object = nullptr;
399  _cdata = nullptr;
400 #endif // _DEBUG
401 }
402 
403 /**
404  *
405  */
406 INLINE Thread *GeomVertexArrayDataHandle::
407 get_current_thread() const {
408  return _current_thread;
409 }
410 
411 /**
412  * Returns a readable pointer to the beginning of the actual data stream, or
413  * NULL if the data is not currently resident. If the data is not currently
414  * resident, this will implicitly request it to become resident soon.
415  *
416  * If force is true, this method will never return NULL, but may block until
417  * the data is available.
418  */
419 INLINE const unsigned char *GeomVertexArrayDataHandle::
420 get_read_pointer(bool force) const {
421  mark_used();
422  return _cdata->_buffer.get_read_pointer(force);
423 }
424 
425 /**
426  *
427  */
428 INLINE const GeomVertexArrayData *GeomVertexArrayDataHandle::
429 get_object() const {
430  return _object;
431 }
432 
433 /**
434  *
435  */
436 INLINE GeomVertexArrayData *GeomVertexArrayDataHandle::
437 get_object() {
438  return _object;
439 }
440 
441 /**
442  *
443  */
444 INLINE const GeomVertexArrayFormat *GeomVertexArrayDataHandle::
445 get_array_format() const {
446  return _object->_array_format;
447 }
448 
449 /**
450  *
451  */
452 INLINE GeomVertexArrayDataHandle::UsageHint GeomVertexArrayDataHandle::
453 get_usage_hint() const {
454  return _cdata->_usage_hint;
455 }
456 
457 /**
458  *
459  */
460 INLINE int GeomVertexArrayDataHandle::
461 get_num_rows() const {
462  nassertr(_object->_array_format->get_stride() != 0, 0);
463  return get_data_size_bytes() / _object->_array_format->get_stride();
464 }
465 
466 /**
467  *
468  */
469 INLINE void GeomVertexArrayDataHandle::
470 clear_rows() {
471  set_num_rows(0);
472 }
473 
474 /**
475  *
476  */
477 INLINE size_t GeomVertexArrayDataHandle::
478 get_data_size_bytes() const {
479  return _cdata->_buffer.get_size();
480 }
481 
482 /**
483  *
484  */
485 INLINE UpdateSeq GeomVertexArrayDataHandle::
486 get_modified() const {
487  return _cdata->_modified;
488 }
489 
490 /**
491  * Returns true if the vertex data is currently resident in memory. If this
492  * returns true, the next call to get_handle()->get_read_pointer() will
493  * probably not block. If this returns false, the vertex data will be brought
494  * back into memory shortly; try again later.
495  */
497 request_resident() const {
498  return (get_read_pointer(false) != nullptr);
499 }
500 
501 /**
502  * Creates a context for the data on the particular GSG, if it does not
503  * already exist. Returns the new (or old) VertexBufferContext. This assumes
504  * that the GraphicsStateGuardian is the currently active rendering context
505  * and that it is ready to accept new datas. If this is not necessarily the
506  * case, you should use prepare() instead.
507  *
508  * Normally, this is not called directly except by the GraphicsStateGuardian;
509  * a data does not need to be explicitly prepared by the user before it may be
510  * rendered.
511  */
513 prepare_now(PreparedGraphicsObjects *prepared_objects,
514  GraphicsStateGuardianBase *gsg) const {
515  return _object->prepare_now(prepared_objects, gsg);
516 }
517 
518 /**
519  * Returns the entire raw data of the GeomVertexArrayData object, formatted as
520  * a string. This is primarily for the benefit of high-level languages such
521  * as Python.
522  */
523 INLINE vector_uchar GeomVertexArrayDataHandle::
524 get_data() const {
525  mark_used();
526  const unsigned char *ptr = _cdata->_buffer.get_read_pointer(true);
527  return vector_uchar(ptr, ptr + _cdata->_buffer.get_size());
528 }
529 
530 /**
531  * Returns a subset of the raw data of the GeomVertexArrayData object,
532  * formatted as a string. This is primarily for the benefit of high-level
533  * languages such as Python.
534  */
535 INLINE vector_uchar GeomVertexArrayDataHandle::
536 get_subdata(size_t start, size_t size) const {
537  mark_used();
538  start = std::min(start, _cdata->_buffer.get_size());
539  size = std::min(size, _cdata->_buffer.get_size() - start);
540  const unsigned char *ptr = _cdata->_buffer.get_read_pointer(true) + start;
541  return vector_uchar(ptr, ptr + size);
542 }
543 
544 /**
545  * Marks the array data recently-used.
546  */
548 mark_used() const {
549  _object->mark_used();
550 }
551 
552 INLINE std::ostream &
553 operator << (std::ostream &out, const GeomVertexArrayData &obj) {
554  obj.output(out);
555  return out;
556 }
PreparedGraphicsObjects
A table of objects that are saved within the graphics context for reference by handle later.
Definition: preparedGraphicsObjects.h:58
GeomVertexArrayDataHandle::request_resident
bool request_resident() const
Returns true if the vertex data is currently resident in memory.
Definition: geomVertexArrayData.I:497
GeomVertexArrayData::get_independent_lru
static SimpleLru * get_independent_lru()
Returns a pointer to the global LRU object that manages the GeomVertexArrayData's that have not (yet)...
Definition: geomVertexArrayData.I:183
UpdateSeq
This is a sequence number that increments monotonically.
Definition: updateSeq.h:37
VertexBufferContext
This is a special class object that holds all the information returned by a particular GSG to indicat...
Definition: vertexBufferContext.h:33
GeomVertexArrayData
This is the data for one array of a GeomVertexData structure.
Definition: geomVertexArrayData.h:58
CycleData
A single page of data maintained by a PipelineCycler.
Definition: cycleData.h:50
GeomVertexArrayDataHandle::mark_used
void mark_used() const
Marks the array data recently-used.
Definition: geomVertexArrayData.I:548
GeomVertexArrayData::get_modified
get_modified
Returns a sequence number which is guaranteed to change at least every time the array vertex data is ...
Definition: geomVertexArrayData.h:93
GeomVertexArrayDataHandle::prepare_now
VertexBufferContext * prepare_now(PreparedGraphicsObjects *prepared_objects, GraphicsStateGuardianBase *gsg) const
Creates a context for the data on the particular GSG, if it does not already exist.
Definition: geomVertexArrayData.I:513
GeomVertexArrayData::request_resident
bool request_resident(Thread *current_thread=Thread::get_current_thread()) const
Returns true if the vertex data is currently resident in memory.
Definition: geomVertexArrayData.I:135
SimpleLruPage::get_lru_size
size_t get_lru_size() const
Returns the size of this page as reported to the LRU, presumably in bytes.
Definition: simpleLru.I:171
VertexDataBook
A collection of VertexDataPages, which can be used to allocate new VertexDataBlock objects.
Definition: vertexDataBook.h:30
PipelineCycler::read_unlocked
const CycleDataType * read_unlocked(Thread *current_thread) const
See PipelineCyclerBase::read_unlocked().
Definition: pipelineCycler.I:231
unref_delete
void unref_delete(RefCountType *ptr)
This global helper function will unref the given ReferenceCount object, and if the reference count re...
Definition: referenceCount.I:344
GeomVertexArrayData::has_column
bool has_column(const InternalName *name) const
Returns true if the array has the named column, false otherwise.
Definition: geomVertexArrayData.I:37
GeomVertexArrayData::get_array_format
get_array_format
Returns the format object that describes this array.
Definition: geomVertexArrayData.h:76
InternalName
Encodes a string name in a hash table, mapping it to a pointer.
Definition: internalName.h:38
SimpleLruPage::mark_used_lru
void mark_used_lru() const
To be called when the page is used; this will move it to the tail of the SimpleLru queue it is alread...
Definition: simpleLru.I:152
GeomVertexArrayDataHandle::get_read_pointer
const unsigned char * get_read_pointer(bool force) const
Returns a readable pointer to the beginning of the actual data stream, or NULL if the data is not cur...
Definition: geomVertexArrayData.I:420
MemoryUsage::update_type
static void update_type(ReferenceCount *ptr, TypeHandle type)
Associates the indicated type with the given pointer.
Definition: memoryUsage.I:55
GeomVertexArrayData::get_num_rows
int get_num_rows() const
Returns the number of rows stored in the array, based on the number of bytes and the stride.
Definition: geomVertexArrayData.I:47
SimpleLruPage::set_lru_size
void set_lru_size(size_t lru_size)
Specifies the size of this page, presumably in bytes, although any unit is possible.
Definition: simpleLru.I:180
CycleDataReader
This template class calls PipelineCycler::read_unlocked(), and then provides a transparent read-only ...
Definition: cycleDataReader.h:35
GeomVertexArrayDataHandle::get_data
vector_uchar get_data() const
Returns the entire raw data of the GeomVertexArrayData object, formatted as a string.
Definition: geomVertexArrayData.I:524
GeomVertexArrayDataHandle
This data object is returned by GeomVertexArrayData::get_handle() or modify_handle().
Definition: geomVertexArrayData.h:250
GeomVertexArrayDataHandle::get_subdata
vector_uchar get_subdata(size_t start, size_t size) const
Returns a subset of the raw data of the GeomVertexArrayData object, formatted as a string.
Definition: geomVertexArrayData.I:536
GeomVertexArrayData::get_usage_hint
get_usage_hint
Returns the usage hint that describes to the rendering backend how often the vertex data will be modi...
Definition: geomVertexArrayData.h:80
CPT
CPT(GeomVertexArrayDataHandle) GeomVertexArrayData
Returns an object that can be used to read the actual data bytes stored in the array.
Definition: geomVertexArrayData.I:162
GeomVertexArrayData::get_data_size_bytes
get_data_size_bytes
Returns the number of bytes stored in the array.
Definition: geomVertexArrayData.h:92
GeomVertexArrayData::get_book
static VertexDataBook & get_book()
Returns the global VertexDataBook that will be used to allocate vertex data buffers.
Definition: geomVertexArrayData.I:201
GeomVertexArrayData::reserve_num_rows
bool reserve_num_rows(int n)
This ensures that enough memory space for n rows is allocated, so that you may increase the number of...
Definition: geomVertexArrayData.I:96
GraphicsStateGuardianBase
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
Definition: graphicsStateGuardianBase.h:110
SimpleLru
An implementation of a very simple LRU algorithm.
Definition: simpleLru.h:28
GeomVertexArrayData::get_small_lru
static SimpleLru * get_small_lru()
Returns a pointer to the global LRU object that manages the GeomVertexArrayData's that are deemed too...
Definition: geomVertexArrayData.I:192
Thread
A thread; that is, a lightweight process.
Definition: thread.h:46
GeomVertexArrayData::unclean_set_num_rows
bool unclean_set_num_rows(int n)
This method behaves like set_num_rows(), except the new data is not initialized.
Definition: geomVertexArrayData.I:84
GeomVertexArrayData::clear_rows
void clear_rows()
Removes all of the rows in the array.
Definition: geomVertexArrayData.I:105
GeomVertexArrayFormat
This describes the structure of a single array within a Geom data.
Definition: geomVertexArrayFormat.h:47
GeomVertexArrayData::set_num_rows
bool set_num_rows(int n)
Sets the length of the array to n rows.
Definition: geomVertexArrayData.I:70