Panda3D

vertexDataBuffer.cxx

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 &copy) {
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 }
 All Classes Functions Variables Enumerations