Panda3D
|
00001 // Filename: vertexDataBuffer.cxx 00002 // Created by: drose (14May07) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "vertexDataBuffer.h" 00016 #include "pStatTimer.h" 00017 00018 TypeHandle VertexDataBuffer::_type_handle; 00019 00020 //////////////////////////////////////////////////////////////////// 00021 // Function: VertexDataBuffer::Copy Assignment Operator 00022 // Access: Public 00023 // Description: 00024 //////////////////////////////////////////////////////////////////// 00025 void VertexDataBuffer:: 00026 operator = (const VertexDataBuffer ©) { 00027 LightMutexHolder holder(_lock); 00028 LightMutexHolder holder2(copy._lock); 00029 00030 if (_resident_data != (unsigned char *)NULL) { 00031 nassertv(_reserved_size != 0); 00032 get_class_type().dec_memory_usage(TypeHandle::MC_array, (int)_reserved_size); 00033 PANDA_FREE_ARRAY(_resident_data); 00034 _resident_data = NULL; 00035 } 00036 if (copy._resident_data != (unsigned char *)NULL && copy._size != 0) { 00037 // We only allocate _size bytes, not the full _reserved_size 00038 // allocated by the original copy. 00039 get_class_type().inc_memory_usage(TypeHandle::MC_array, (int)copy._size); 00040 _resident_data = (unsigned char *)PANDA_MALLOC_ARRAY(copy._size); 00041 memcpy(_resident_data, copy._resident_data, copy._size); 00042 } 00043 _size = copy._size; 00044 _reserved_size = copy._size; 00045 _block = copy._block; 00046 nassertv(_reserved_size >= _size); 00047 } 00048 00049 //////////////////////////////////////////////////////////////////// 00050 // Function: VertexDataBuffer::swap 00051 // Access: Public 00052 // Description: Swaps the data buffers between this one and the other 00053 // one. 00054 //////////////////////////////////////////////////////////////////// 00055 void VertexDataBuffer:: 00056 swap(VertexDataBuffer &other) { 00057 LightMutexHolder holder(_lock); 00058 LightMutexHolder holder2(other._lock); 00059 00060 unsigned char *resident_data = _resident_data; 00061 size_t size = _size; 00062 size_t reserved_size = _reserved_size; 00063 PT(VertexDataBlock) block = _block; 00064 00065 _resident_data = other._resident_data; 00066 _size = other._size; 00067 _reserved_size = other._reserved_size; 00068 _block = other._block; 00069 00070 other._resident_data = resident_data; 00071 other._size = size; 00072 other._reserved_size = reserved_size; 00073 other._block = block; 00074 nassertv(_reserved_size >= _size); 00075 } 00076 00077 //////////////////////////////////////////////////////////////////// 00078 // Function: VertexDataBuffer::do_clean_realloc 00079 // Access: Private 00080 // Description: Changes the reserved size of the buffer, preserving 00081 // its data (except for any data beyond the new end of 00082 // the buffer, if the buffer is being reduced). If the 00083 // buffer is expanded, the new data is uninitialized. 00084 // 00085 // Assumes the lock is already held. 00086 //////////////////////////////////////////////////////////////////// 00087 void VertexDataBuffer:: 00088 do_clean_realloc(size_t reserved_size) { 00089 if (reserved_size != _reserved_size) { 00090 if (reserved_size == 0 || _size == 0) { 00091 do_unclean_realloc(reserved_size); 00092 return; 00093 } 00094 00095 if (gobj_cat.is_debug()) { 00096 gobj_cat.debug() 00097 << this << ".clean_realloc(" << reserved_size << ")\n"; 00098 } 00099 00100 // Page in if we're currently paged out. 00101 if (_reserved_size != 0 && _resident_data == (unsigned char *)NULL) { 00102 do_page_in(); 00103 } 00104 00105 get_class_type().inc_memory_usage(TypeHandle::MC_array, (int)reserved_size - (int)_reserved_size); 00106 if (_reserved_size == 0) { 00107 nassertv(_resident_data == (unsigned char *)NULL); 00108 _resident_data = (unsigned char *)PANDA_MALLOC_ARRAY(reserved_size); 00109 } else { 00110 nassertv(_resident_data != (unsigned char *)NULL); 00111 _resident_data = (unsigned char *)PANDA_REALLOC_ARRAY(_resident_data, reserved_size); 00112 } 00113 nassertv(_resident_data != (unsigned char *)NULL); 00114 _reserved_size = reserved_size; 00115 } 00116 00117 _size = min(_size, _reserved_size); 00118 } 00119 00120 //////////////////////////////////////////////////////////////////// 00121 // Function: VertexDataBuffer::do_unclean_realloc 00122 // Access: Private 00123 // Description: Changes the reserved size of the buffer, without 00124 // regard to preserving its data. This implicitly 00125 // resets the size to 0. 00126 // 00127 // Assumes the lock is already held. 00128 //////////////////////////////////////////////////////////////////// 00129 void VertexDataBuffer:: 00130 do_unclean_realloc(size_t reserved_size) { 00131 if (reserved_size != _reserved_size || _resident_data == (unsigned char *)NULL) { 00132 if (gobj_cat.is_debug()) { 00133 gobj_cat.debug() 00134 << this << ".unclean_realloc(" << reserved_size << ")\n"; 00135 } 00136 00137 // If we're paged out, discard the page. 00138 _block = NULL; 00139 00140 if (_resident_data != (unsigned char *)NULL) { 00141 nassertv(_reserved_size != 0); 00142 00143 get_class_type().dec_memory_usage(TypeHandle::MC_array, (int)_reserved_size); 00144 PANDA_FREE_ARRAY(_resident_data); 00145 _resident_data = NULL; 00146 _reserved_size = 0; 00147 } 00148 00149 if (reserved_size != 0) { 00150 get_class_type().inc_memory_usage(TypeHandle::MC_array, (int)reserved_size); 00151 nassertv(_resident_data == (unsigned char *)NULL); 00152 _resident_data = (unsigned char *)PANDA_MALLOC_ARRAY(reserved_size); 00153 } 00154 00155 _reserved_size = reserved_size; 00156 } 00157 00158 _size = 0; 00159 } 00160 00161 //////////////////////////////////////////////////////////////////// 00162 // Function: VertexDataBuffer::do_page_out 00163 // Access: Private 00164 // Description: Moves the buffer out of independent memory and puts 00165 // it on a page in the indicated book. The buffer may 00166 // still be directly accessible as long as its page 00167 // remains resident. Any subsequent attempt to rewrite 00168 // the buffer will implicitly move it off of the page 00169 // and back into independent memory. 00170 // 00171 // Assumes the lock is already held. 00172 //////////////////////////////////////////////////////////////////// 00173 void VertexDataBuffer:: 00174 do_page_out(VertexDataBook &book) { 00175 if (_block != (VertexDataBlock *)NULL || _reserved_size == 0) { 00176 // We're already paged out. 00177 return; 00178 } 00179 nassertv(_resident_data != (unsigned char *)NULL); 00180 00181 if (_size == 0) { 00182 // It's an empty buffer. Just deallocate it; don't bother to 00183 // create a block. 00184 get_class_type().dec_memory_usage(TypeHandle::MC_array, (int)_reserved_size); 00185 PANDA_FREE_ARRAY(_resident_data); 00186 _resident_data = NULL; 00187 _reserved_size = 0; 00188 00189 } else { 00190 // It's a nonempty buffer, so write _size bytes (but not the full 00191 // _reserved_size bytes) to a block. 00192 _block = book.alloc(_size); 00193 nassertv(_block != (VertexDataBlock *)NULL); 00194 unsigned char *pointer = _block->get_pointer(true); 00195 nassertv(pointer != (unsigned char *)NULL); 00196 memcpy(pointer, _resident_data, _size); 00197 00198 get_class_type().dec_memory_usage(TypeHandle::MC_array, (int)_reserved_size); 00199 PANDA_FREE_ARRAY(_resident_data); 00200 _resident_data = NULL; 00201 00202 _reserved_size = _size; 00203 } 00204 nassertv(_reserved_size >= _size); 00205 } 00206 00207 //////////////////////////////////////////////////////////////////// 00208 // Function: VertexDataBuffer::do_page_in 00209 // Access: Private 00210 // Description: Moves the buffer off of its current page and into 00211 // independent memory. If the page is not already 00212 // resident, it is forced resident first. 00213 // 00214 // Assumes the lock is already held. 00215 //////////////////////////////////////////////////////////////////// 00216 void VertexDataBuffer:: 00217 do_page_in() { 00218 if (_resident_data != (unsigned char *)NULL || _reserved_size == 0) { 00219 // We're already paged in. 00220 return; 00221 } 00222 00223 nassertv(_block != (VertexDataBlock *)NULL); 00224 nassertv(_reserved_size == _size); 00225 00226 get_class_type().inc_memory_usage(TypeHandle::MC_array, (int)_size); 00227 _resident_data = (unsigned char *)PANDA_MALLOC_ARRAY(_size); 00228 nassertv(_resident_data != (unsigned char *)NULL); 00229 00230 memcpy(_resident_data, _block->get_pointer(true), _size); 00231 }