// Filename: geomVertexArrayData.I // Created by: drose (17Mar05) // //////////////////////////////////////////////////////////////////// // // PANDA 3D SOFTWARE // Copyright (c) Carnegie Mellon University. All rights reserved. // // All use of this software is subject to the terms of the revised BSD // license. You should have received a copy of this license along // with this source code in a file named "LICENSE." // //////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayData::get_array_format // Access: Published // Description: Returns the format object that describes this array. //////////////////////////////////////////////////////////////////// INLINE const GeomVertexArrayFormat *GeomVertexArrayData:: get_array_format() const { return _array_format; } //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayData::get_usage_hint // Access: Published // Description: Returns the usage hint that describes to the // rendering backend how often the vertex data will be // modified and/or rendered. See geomEnums.h. //////////////////////////////////////////////////////////////////// INLINE GeomVertexArrayData::UsageHint GeomVertexArrayData:: get_usage_hint() const { CDReader cdata(_cycler); return cdata->_usage_hint; } //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayData::has_column // Access: Published // Description: Returns true if the array has the named column, // false otherwise. This is really just a shortcut for // asking the same thing from the format. //////////////////////////////////////////////////////////////////// INLINE bool GeomVertexArrayData:: has_column(const InternalName *name) const { return _array_format->has_column(name); } //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayData::get_num_rows // Access: Published // Description: Returns the number of rows stored in the array, // based on the number of bytes and the stride. This // should be the same for all arrays within a given // GeomVertexData object. //////////////////////////////////////////////////////////////////// INLINE int GeomVertexArrayData:: get_num_rows() const { return get_handle()->get_num_rows(); } //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayData::set_num_rows // Access: Published // Description: Sets the length of the array to n rows. // // Normally, you would not call this directly, since all // of the arrays in a particular GeomVertexData must // have the same number of rows; instead, call // GeomVertexData::set_num_rows(). // // The return value is true if the number of rows // was changed, false if the object already contained n // rows (or if there was some error). // // The new vertex data is initialized to 0, including // the "color" column (but see // GeomVertexData::set_num_rows()). // // Don't call this in a downstream thread unless you // don't mind it blowing away other changes you might // have recently made in an upstream thread. //////////////////////////////////////////////////////////////////// INLINE bool GeomVertexArrayData:: set_num_rows(int n) { return modify_handle()->set_num_rows(n); } //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayData::unclean_set_num_rows // Access: Published // Description: This method behaves like set_num_rows(), except the // new data is not initialized. Furthermore, after this // call, *any* of the data in the GeomVertexArrayData // may be uninitialized, including the earlier rows. // // Normally, you would not call this directly, since all // of the arrays in a particular GeomVertexData must // have the same number of rows; instead, call // GeomVertexData::unclean_set_num_rows(). //////////////////////////////////////////////////////////////////// INLINE bool GeomVertexArrayData:: unclean_set_num_rows(int n) { return modify_handle()->unclean_set_num_rows(n); } //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayData::clear_rows // Access: Published // Description: Removes all of the rows in the array. // Functionally equivalent to set_num_rows(0). //////////////////////////////////////////////////////////////////// INLINE void GeomVertexArrayData:: clear_rows() { return modify_handle()->clear_rows(); } //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayData::get_data_size_bytes // Access: Published // Description: Returns the number of bytes stored in the array. //////////////////////////////////////////////////////////////////// INLINE int GeomVertexArrayData:: get_data_size_bytes() const { CDReader cdata(_cycler); return cdata->_buffer.get_size(); } //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayData::get_modified // Access: Published // Description: Returns a sequence number which is guaranteed to // change at least every time the array vertex data is // modified. //////////////////////////////////////////////////////////////////// INLINE UpdateSeq GeomVertexArrayData:: get_modified() const { CDReader cdata(_cycler); return cdata->_modified; } //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayData::request_resident // Access: Published // Description: Returns true if the vertex data is currently resident // in memory. If this returns true, the next call to // get_handle()->get_read_pointer() will probably not // block. If this returns false, the vertex data will // be brought back into memory shortly; try again later. //////////////////////////////////////////////////////////////////// INLINE bool GeomVertexArrayData:: request_resident() const { CPT(GeomVertexArrayDataHandle) handle = get_handle(); return handle->request_resident(); } //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayData::get_handle // Access: Published // Description: Returns an object that can be used to read the actual // data bytes stored in the array. Calling this method // locks the data, and will block any other threads // attempting to read or write the data, until the // returned object destructs. //////////////////////////////////////////////////////////////////// INLINE CPT(GeomVertexArrayDataHandle) GeomVertexArrayData:: get_handle(Thread *current_thread) const { const CData *cdata = _cycler.read_unlocked(current_thread); return new GeomVertexArrayDataHandle(this, current_thread, cdata, false); } //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayData::modify_handle // Access: Published // Description: Returns an object that can be used to read or write // the actual data bytes stored in the array. Calling // this method locks the data, and will block any other // threads attempting to read or write the data, until // the returned object destructs. //////////////////////////////////////////////////////////////////// INLINE PT(GeomVertexArrayDataHandle) GeomVertexArrayData:: modify_handle(Thread *current_thread) { CData *cdata = _cycler.write_upstream(true, current_thread); return new GeomVertexArrayDataHandle(this, current_thread, cdata, true); } //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayData::get_independent_lru // Access: Published, Static // Description: Returns a pointer to the global LRU object that // manages the GeomVertexArrayData's that have not (yet) // been paged out. //////////////////////////////////////////////////////////////////// INLINE SimpleLru *GeomVertexArrayData:: get_independent_lru() { return &_independent_lru; } //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayData::get_small_lru // Access: Published, Static // Description: Returns a pointer to the global LRU object that // manages the GeomVertexArrayData's that are deemed too // small to be paged out. //////////////////////////////////////////////////////////////////// INLINE SimpleLru *GeomVertexArrayData:: get_small_lru() { return &_small_lru; } //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayData::get_book // Access: Published, Static // Description: Returns the global VertexDataBook that will be // used to allocate vertex data buffers. //////////////////////////////////////////////////////////////////// INLINE VertexDataBook &GeomVertexArrayData:: get_book() { return _book; } //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayData::set_lru_size // Access: Private // Description: Should be called when the size of the buffer changes. //////////////////////////////////////////////////////////////////// INLINE void GeomVertexArrayData:: set_lru_size(size_t lru_size) { SimpleLruPage::set_lru_size(lru_size); if ((int)lru_size <= vertex_data_small_size) { SimpleLruPage::mark_used_lru(&_small_lru); } else { SimpleLruPage::mark_used_lru(&_independent_lru); } } //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayData::CData::Constructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// INLINE GeomVertexArrayData::CData:: CData() : _usage_hint(UH_unspecified), _rw_lock("GeomVertexArrayData::CData::_rw_lock") { } //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayData::CData::Copy Constructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// INLINE GeomVertexArrayData::CData:: CData(const GeomVertexArrayData::CData ©) : _usage_hint(copy._usage_hint), _buffer(copy._buffer), _modified(copy._modified), _rw_lock("GeomVertexArrayData::CData::_rw_lock") { } //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayData::CData::Copy Assignment // Access: Public // Description: //////////////////////////////////////////////////////////////////// INLINE void GeomVertexArrayData::CData:: operator = (const GeomVertexArrayData::CData ©) { _usage_hint = copy._usage_hint; _buffer = copy._buffer; _modified = copy._modified; } //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayDataHandle::Constructor // Access: Private // Description: //////////////////////////////////////////////////////////////////// INLINE GeomVertexArrayDataHandle:: GeomVertexArrayDataHandle(const GeomVertexArrayData *object, Thread *current_thread, const GeomVertexArrayData::CData *cdata, bool writable) : _object((GeomVertexArrayData *)object), _current_thread(current_thread), _cdata((GeomVertexArrayData::CData *)cdata), _writable(writable) { #ifdef _DEBUG nassertv(_object->test_ref_count_nonzero()); #endif // _DEBUG #ifdef DO_PIPELINING _cdata->ref(); #endif // DO_PIPELINING // We must grab the lock *after* we have incremented the reference // count, above. _cdata->_rw_lock.acquire(); #ifdef DO_MEMORY_USAGE MemoryUsage::update_type(this, get_class_type()); #endif } //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayDataHandle::Copy Constructor // Access: Private // Description: Don't attempt to copy these objects. //////////////////////////////////////////////////////////////////// INLINE GeomVertexArrayDataHandle:: GeomVertexArrayDataHandle(const GeomVertexArrayDataHandle ©) { nassertv(false); } //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayDataHandle::Copy Assignment Operator // Access: Private // Description: Don't attempt to copy these objects. //////////////////////////////////////////////////////////////////// INLINE void GeomVertexArrayDataHandle:: operator = (const GeomVertexArrayDataHandle &) { nassertv(false); } //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayDataHandle::Destructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// INLINE GeomVertexArrayDataHandle:: ~GeomVertexArrayDataHandle() { #ifdef _DEBUG nassertv(_object->test_ref_count_nonzero()); #endif // _DEBUG if (_writable) { _object->_cycler.release_write(_cdata); } // We must release the lock *before* we decrement the reference // count, below. _cdata->_rw_lock.release(); #ifdef DO_PIPELINING unref_delete((CycleData *)_cdata); #endif // DO_PIPELINING #ifdef _DEBUG _object = NULL; _cdata = NULL; #endif // _DEBUG } //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayDataHandle::get_current_thread // Access: Public // Description: //////////////////////////////////////////////////////////////////// INLINE Thread *GeomVertexArrayDataHandle:: get_current_thread() const { return _current_thread; } //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayDataHandle::get_read_pointer // Access: Public // Description: Returns a readable pointer to the beginning of the // actual data stream, or NULL if the data is not // currently resident. If the data is not currently // resident, this will implicitly request it to become // resident soon. // // If force is true, this method will never return NULL, // but may block until the data is available. //////////////////////////////////////////////////////////////////// INLINE const unsigned char *GeomVertexArrayDataHandle:: get_read_pointer(bool force) const { mark_used(); return _cdata->_buffer.get_read_pointer(force); } //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayDataHandle::get_object // Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE const GeomVertexArrayData *GeomVertexArrayDataHandle:: get_object() const { return _object; } //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayDataHandle::get_object // Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE GeomVertexArrayData *GeomVertexArrayDataHandle:: get_object() { return _object; } //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayDataHandle::get_array_format // Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE const GeomVertexArrayFormat *GeomVertexArrayDataHandle:: get_array_format() const { return _object->_array_format; } //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayDataHandle::get_usage_hint // Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE GeomVertexArrayDataHandle::UsageHint GeomVertexArrayDataHandle:: get_usage_hint() const { return _cdata->_usage_hint; } //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayDataHandle::get_num_rows // Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE int GeomVertexArrayDataHandle:: get_num_rows() const { return get_data_size_bytes() / _object->_array_format->get_stride(); } //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayDataHandle::clear_rows // Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE void GeomVertexArrayDataHandle:: clear_rows() { set_num_rows(0); } //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayDataHandle::get_data_size_bytes // Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE int GeomVertexArrayDataHandle:: get_data_size_bytes() const { return _cdata->_buffer.get_size(); } //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayDataHandle::get_modified // Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE UpdateSeq GeomVertexArrayDataHandle:: get_modified() const { return _cdata->_modified; } //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayData::request_resident // Access: Published // Description: Returns true if the vertex data is currently resident // in memory. If this returns true, the next call to // get_handle()->get_read_pointer() will probably not // block. If this returns false, the vertex data will // be brought back into memory shortly; try again later. //////////////////////////////////////////////////////////////////// INLINE bool GeomVertexArrayDataHandle:: request_resident() const { return (get_read_pointer(false) != (const unsigned char *)NULL); } //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayDataHandle::get_data // Access: Published // Description: Returns the entire raw data of the // GeomVertexArrayData object, formatted as a string. // This is primarily for the benefit of high-level // languages such as Python. //////////////////////////////////////////////////////////////////// INLINE string GeomVertexArrayDataHandle:: get_data() const { mark_used(); return string((const char *)_cdata->_buffer.get_read_pointer(true), _cdata->_buffer.get_size()); } //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayDataHandle::get_subdata // Access: Published // Description: Returns a subset of the raw data of the // GeomVertexArrayData object, formatted as a string. // This is primarily for the benefit of high-level // languages such as Python. //////////////////////////////////////////////////////////////////// INLINE string GeomVertexArrayDataHandle:: get_subdata(size_t start, size_t size) const { mark_used(); start = min(start, _cdata->_buffer.get_size()); size = min(size, _cdata->_buffer.get_size() - start); return string((const char *)_cdata->_buffer.get_read_pointer(true) + start, size); } //////////////////////////////////////////////////////////////////// // Function: GeomVertexArrayDataHandle::mark_used // Access: Published // Description: Marks the array data recently-used. //////////////////////////////////////////////////////////////////// void GeomVertexArrayDataHandle:: mark_used() const { _object->set_lru_size(_object->get_lru_size()); } INLINE ostream & operator << (ostream &out, const GeomVertexArrayData &obj) { obj.output(out); return out; }