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 */
17 INLINE const GeomVertexArrayFormat *GeomVertexArrayData::
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 */
36 INLINE bool GeomVertexArrayData::
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 */
46 INLINE int GeomVertexArrayData::
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 */
69 INLINE bool GeomVertexArrayData::
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 */
83 INLINE bool GeomVertexArrayData::
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 */
95 INLINE bool GeomVertexArrayData::
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 */
104 INLINE void GeomVertexArrayData::
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 */
122 INLINE UpdateSeq GeomVertexArrayData::
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 */
134 INLINE bool GeomVertexArrayData::
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 */
182 INLINE SimpleLru *GeomVertexArrayData::
183 get_independent_lru() {
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 */
191 INLINE SimpleLru *GeomVertexArrayData::
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 */
200 INLINE VertexDataBook &GeomVertexArrayData::
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 */
496 INLINE bool GeomVertexArrayDataHandle::
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 */
512 INLINE VertexBufferContext *GeomVertexArrayDataHandle::
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 */
547 void GeomVertexArrayDataHandle::
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 }
CycleDataReader
This template class calls PipelineCycler::read_unlocked(), and then provides a transparent read-only ...
Definition: cycleDataReader.h:35
CycleData
A single page of data maintained by a PipelineCycler.
Definition: cycleData.h:50
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
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
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
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::request_resident
bool request_resident() const
Returns true if the vertex data is currently resident in memory.
Definition: geomVertexArrayData.I:497
GeomVertexArrayDataHandle::mark_used
void mark_used() const
Marks the array data recently-used.
Definition: geomVertexArrayData.I:548
GeomVertexArrayData
This is the data for one array of a GeomVertexData structure.
Definition: geomVertexArrayData.h:58
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
GeomVertexArrayData::get_data_size_bytes
get_data_size_bytes
Returns the number of bytes stored in the array.
Definition: geomVertexArrayData.h:92
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
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::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
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
GeomVertexArrayData::set_num_rows
bool set_num_rows(int n)
Sets the length of the array to n rows.
Definition: geomVertexArrayData.I:70
GeomVertexArrayData::clear_rows
void clear_rows()
Removes all of the rows in the array.
Definition: geomVertexArrayData.I:105
GeomVertexArrayData::get_array_format
get_array_format
Returns the format object that describes this array.
Definition: geomVertexArrayData.h:76
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
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
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
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::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
GeomVertexArrayFormat
This describes the structure of a single array within a Geom data.
Definition: geomVertexArrayFormat.h:47
GraphicsStateGuardianBase
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
Definition: graphicsStateGuardianBase.h:110
InternalName
Encodes a string name in a hash table, mapping it to a pointer.
Definition: internalName.h:38
MemoryUsage::update_type
static void update_type(ReferenceCount *ptr, TypeHandle type)
Associates the indicated type with the given pointer.
Definition: memoryUsage.I:55
PreparedGraphicsObjects
A table of objects that are saved within the graphics context for reference by handle later.
Definition: preparedGraphicsObjects.h:58
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
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
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
SimpleLru
An implementation of a very simple LRU algorithm.
Definition: simpleLru.h:28
Thread
A thread; that is, a lightweight process.
Definition: thread.h:46
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
VertexDataBook
A collection of VertexDataPages, which can be used to allocate new VertexDataBlock objects.
Definition: vertexDataBook.h:30
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
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
PipelineCycler::read_unlocked
const CycleDataType * read_unlocked(Thread *current_thread) const
See PipelineCyclerBase::read_unlocked().
Definition: pipelineCycler.I:231