Panda3D
Loading...
Searching...
No Matches
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 */
18get_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 */
26INLINE GeomVertexArrayData::UsageHint GeomVertexArrayData::
27get_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 */
37has_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 */
47get_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 */
70set_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 */
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 */
96reserve_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 */
105clear_rows() {
106 return modify_handle()->clear_rows();
107}
108
109/**
110 * Returns the number of bytes stored in the array.
111 */
112INLINE size_t GeomVertexArrayData::
113get_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 */
123get_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 */
135request_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 */
162INLINE CPT(GeomVertexArrayDataHandle) GeomVertexArrayData::
163get_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 */
173INLINE PT(GeomVertexArrayDataHandle) GeomVertexArrayData::
174modify_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 */
193 return &_small_lru;
194}
195
196/**
197 * Returns the global VertexDataBook that will be used to allocate vertex data
198 * buffers.
199 */
201get_book() {
202 return _book;
203}
204
205/**
206 * Should be called when the size of the buffer changes.
207 */
208INLINE void GeomVertexArrayData::
209set_lru_size(size_t 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 */
221INLINE void GeomVertexArrayData::
222mark_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 */
233INLINE GeomVertexArrayData::CData::
234CData(UsageHint usage_hint) :
235 _usage_hint(usage_hint),
236 _rw_lock("GeomVertexArrayData::CData::_rw_lock")
237{
238}
239
240/**
241 *
242 */
243INLINE GeomVertexArrayData::CData::
244CData(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 */
255INLINE GeomVertexArrayData::CData::
256CData(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 */
267INLINE void GeomVertexArrayData::CData::
268operator = (const GeomVertexArrayData::CData &copy) {
269 _usage_hint = copy._usage_hint;
270 _buffer = copy._buffer;
271 _modified = copy._modified;
272}
273
274/**
275 *
276 */
277INLINE GeomVertexArrayDataHandle::
278GeomVertexArrayDataHandle(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 */
303INLINE GeomVertexArrayDataHandle::
304GeomVertexArrayDataHandle(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 */
328INLINE GeomVertexArrayDataHandle::
329GeomVertexArrayDataHandle(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 */
354INLINE GeomVertexArrayDataHandle::
355GeomVertexArrayDataHandle(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 */
379INLINE 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 */
406INLINE Thread *GeomVertexArrayDataHandle::
407get_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 */
419INLINE const unsigned char *GeomVertexArrayDataHandle::
420get_read_pointer(bool force) const {
421 mark_used();
422 return _cdata->_buffer.get_read_pointer(force);
423}
424
425/**
426 *
427 */
428INLINE const GeomVertexArrayData *GeomVertexArrayDataHandle::
429get_object() const {
430 return _object;
431}
432
433/**
434 *
435 */
436INLINE GeomVertexArrayData *GeomVertexArrayDataHandle::
437get_object() {
438 return _object;
439}
440
441/**
442 *
443 */
444INLINE const GeomVertexArrayFormat *GeomVertexArrayDataHandle::
445get_array_format() const {
446 return _object->_array_format;
447}
448
449/**
450 *
451 */
452INLINE GeomVertexArrayDataHandle::UsageHint GeomVertexArrayDataHandle::
453get_usage_hint() const {
454 return _cdata->_usage_hint;
455}
456
457/**
458 *
459 */
460INLINE int GeomVertexArrayDataHandle::
461get_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 */
469INLINE void GeomVertexArrayDataHandle::
470clear_rows() {
471 set_num_rows(0);
472}
473
474/**
475 *
476 */
477INLINE size_t GeomVertexArrayDataHandle::
478get_data_size_bytes() const {
479 return _cdata->_buffer.get_size();
480}
481
482/**
483 *
484 */
485INLINE UpdateSeq GeomVertexArrayDataHandle::
486get_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 */
497request_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 */
513prepare_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 */
524get_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 */
536get_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 */
548mark_used() const {
549 _object->mark_used();
550}
551
552INLINE std::ostream &
553operator << (std::ostream &out, const GeomVertexArrayData &obj) {
554 obj.output(out);
555 return out;
556}
This template class calls PipelineCycler::read_unlocked(), and then provides a transparent read-only ...
A single page of data maintained by a PipelineCycler.
Definition cycleData.h:50
This data object is returned by GeomVertexArrayData::get_handle() or modify_handle().
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.
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.
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...
vector_uchar get_data() const
Returns the entire raw data of the GeomVertexArrayData object, formatted as a string.
bool request_resident() const
Returns true if the vertex data is currently resident in memory.
void mark_used() const
Marks the array data recently-used.
This is the data for one array of a GeomVertexData structure.
get_usage_hint
Returns the usage hint that describes to the rendering backend how often the vertex data will be modi...
get_data_size_bytes
Returns the number of bytes stored in the array.
get_modified
Returns a sequence number which is guaranteed to change at least every time the array vertex data is ...
static VertexDataBook & get_book()
Returns the global VertexDataBook that will be used to allocate vertex data buffers.
bool request_resident(Thread *current_thread=Thread::get_current_thread()) const
Returns true if the vertex data is currently resident in memory.
static SimpleLru * get_small_lru()
Returns a pointer to the global LRU object that manages the GeomVertexArrayData's that are deemed too...
bool set_num_rows(int n)
Sets the length of the array to n rows.
void clear_rows()
Removes all of the rows in the array.
get_array_format
Returns the format object that describes this array.
int get_num_rows() const
Returns the number of rows stored in the array, based on the number of bytes and the stride.
static SimpleLru * get_independent_lru()
Returns a pointer to the global LRU object that manages the GeomVertexArrayData's that have not (yet)...
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...
bool has_column(const InternalName *name) const
Returns true if the array has the named column, false otherwise.
bool unclean_set_num_rows(int n)
This method behaves like set_num_rows(), except the new data is not initialized.
This describes the structure of a single array within a Geom data.
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
Encodes a string name in a hash table, mapping it to a pointer.
static void update_type(ReferenceCount *ptr, TypeHandle type)
Associates the indicated type with the given pointer.
Definition memoryUsage.I:55
A table of objects that are saved within the graphics context for reference by handle later.
void acquire() const
Grabs the reMutex if it is available.
void release() const
Releases the reMutex.
size_t get_lru_size() const
Returns the size of this page as reported to the LRU, presumably in bytes.
Definition simpleLru.I:171
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
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
An implementation of a very simple LRU algorithm.
Definition simpleLru.h:28
A thread; that is, a lightweight process.
Definition thread.h:46
This is a sequence number that increments monotonically.
Definition updateSeq.h:37
This is a special class object that holds all the information returned by a particular GSG to indicat...
A collection of VertexDataPages, which can be used to allocate new VertexDataBlock objects.
const unsigned char * get_read_pointer(bool force) const
Returns a read-only pointer to the raw data, or NULL if the data is not currently resident.
size_t get_size() const
Returns the number of bytes in the buffer.
void unref_delete(RefCountType *ptr)
This global helper function will unref the given ReferenceCount object, and if the reference count re...
const CycleDataType * read_unlocked(Thread *current_thread) const
See PipelineCyclerBase::read_unlocked().