Visualization Library v1.0.3A lightweight C++ OpenGL middleware for 2D/3D graphics |
[Download] [Tutorials] [All Classes] [Grouped Classes] |
00001 /**************************************************************************************/ 00002 /* */ 00003 /* Visualization Library */ 00004 /* http://visualizationlibrary.org */ 00005 /* */ 00006 /* Copyright (c) 2005-2010, Michele Bosi */ 00007 /* All rights reserved. */ 00008 /* */ 00009 /* Redistribution and use in source and binary forms, with or without modification, */ 00010 /* are permitted provided that the following conditions are met: */ 00011 /* */ 00012 /* - Redistributions of source code must retain the above copyright notice, this */ 00013 /* list of conditions and the following disclaimer. */ 00014 /* */ 00015 /* - Redistributions in binary form must reproduce the above copyright notice, this */ 00016 /* list of conditions and the following disclaimer in the documentation and/or */ 00017 /* other materials provided with the distribution. */ 00018 /* */ 00019 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */ 00020 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */ 00021 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ 00022 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */ 00023 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */ 00024 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ 00025 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */ 00026 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ 00027 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ 00028 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 00029 /* */ 00030 /**************************************************************************************/ 00031 00032 #ifndef Buffer_INCLUDE_ONCE 00033 #define Buffer_INCLUDE_ONCE 00034 00035 #include <vlCore/Object.hpp> 00036 #include <string.h> 00037 00038 namespace vl 00039 { 00040 //----------------------------------------------------------------------------- 00041 // Buffer 00042 //----------------------------------------------------------------------------- 00046 class Buffer: public Object 00047 { 00048 VL_INSTRUMENT_CLASS(vl::Buffer, Object) 00049 00050 public: 00051 typedef enum 00052 { 00053 UserAllocatedBuffer, 00054 AutoAllocatedBuffer 00055 } EAllocationMode; 00056 00057 public: 00058 Buffer() 00059 { 00060 VL_DEBUG_SET_OBJECT_NAME() 00061 mPtr = NULL; 00062 mByteCount = 0; 00063 mAlignment = VL_DEFAULT_BUFFER_BYTE_ALIGNMENT; 00064 mAllocationMode = AutoAllocatedBuffer; 00065 } 00066 Buffer(const Buffer& other): Object(other) 00067 { 00068 VL_DEBUG_SET_OBJECT_NAME() 00069 mPtr = NULL; 00070 mByteCount = 0; 00071 mAlignment = VL_DEFAULT_BUFFER_BYTE_ALIGNMENT; 00072 mAllocationMode = AutoAllocatedBuffer; 00073 // copy local data 00074 *this = other; 00075 } 00076 Buffer& operator=(const Buffer& other) 00077 { 00078 if ( mAllocationMode == AutoAllocatedBuffer) 00079 { 00080 // same alignment 00081 mAlignment = other.mAlignment; 00082 // make space for new data 00083 resize(other.bytesUsed()); 00084 // copy new data 00085 memcpy(mPtr, other.ptr(), bytesUsed()); 00086 } 00087 else 00088 { 00089 VL_CHECK(mPtr); 00090 VL_CHECK(other.mPtr); 00091 VL_CHECK(mByteCount == other.mByteCount); 00092 memcpy(mPtr, other.ptr(), bytesUsed()); 00093 } 00094 return *this; 00095 } 00096 00097 // swaps the data 00098 void swap(Buffer& other) 00099 { 00100 // temp 00101 unsigned char* tmp_ptr = mPtr; 00102 size_t tmp_byte_count = mByteCount; 00103 size_t tmp_alignment = mAlignment; 00104 // this <- other 00105 mPtr = other.mPtr; 00106 mByteCount = other.mByteCount; 00107 mAlignment = other.mAlignment; 00108 // this -> other 00109 other.mPtr = tmp_ptr; 00110 other.mByteCount = tmp_byte_count; 00111 other.mAlignment = tmp_alignment; 00112 } 00113 00114 ~Buffer() 00115 { 00116 clear(); 00117 } 00118 00119 void clear() 00120 { 00121 if ( mAllocationMode == AutoAllocatedBuffer ) 00122 alignedFree(mPtr); 00123 mPtr = NULL; 00124 mByteCount = 0; 00125 } 00126 00127 // if alignment < 1 uses the last specified alignment or the default one 00128 void resize(size_t byte_count, size_t alignment = 0) 00129 { 00130 VL_CHECK( mAllocationMode == AutoAllocatedBuffer ); 00131 00132 if (byte_count == 0) 00133 { 00134 clear(); 00135 return; 00136 } 00137 00138 alignment = alignment >= 1 ? alignment : mAlignment; 00139 if ( byte_count != mByteCount || alignment != mAlignment) 00140 { 00141 mAlignment = alignment; 00142 // allocate the new chunk 00143 unsigned char* ptr = NULL; 00144 if (byte_count) 00145 ptr = (unsigned char*)alignedMalloc(byte_count, mAlignment); 00146 if (mPtr) 00147 { 00148 if (byte_count) 00149 { 00150 size_t min = mByteCount < byte_count ? mByteCount : byte_count; 00151 // copy the old content brutally 00152 memcpy(ptr, mPtr, min); 00153 } 00154 // free the old pointer 00155 alignedFree(mPtr); 00156 } 00157 // set the new pointer 00158 mPtr = ptr; 00159 // set the new reserved bytes 00160 mByteCount = byte_count; 00161 } 00162 } 00163 00171 void setUserAllocatedBuffer(void* ptr, size_t bytes) 00172 { 00173 clear(); 00174 mPtr = (unsigned char*)ptr; 00175 mByteCount = bytes; 00176 mAlignment = 0; 00177 mAllocationMode = UserAllocatedBuffer; 00178 } 00179 00180 void setAllocationMode( EAllocationMode mode ) 00181 { 00182 if ( mAllocationMode != mode ) 00183 { 00184 clear(); 00185 mAllocationMode = mode; 00186 // reset buffer data 00187 mPtr = 0; 00188 mByteCount = 0; 00189 mAlignment = 0; 00190 } 00191 } 00192 00193 EAllocationMode allocationMode() const { return mAllocationMode; } 00194 00195 size_t bytesUsed() const { return mByteCount; } 00196 00197 bool empty() const { return mByteCount == 0; } 00198 00199 unsigned char* ptr() { return mPtr; } 00200 00201 const unsigned char* ptr() const { return mPtr; } 00202 00203 size_t alignment() const { return mAlignment; } 00204 00205 // returns a chunck of memory aligned to the specified amount 00206 // alignment must be a power of two 00207 static void *alignedMalloc(size_t bytes, size_t alignment) 00208 { 00209 // alignment must be a power of two 00210 if ( alignment & (alignment-1)) 00211 return NULL; 00212 00213 size_t actual_byte_count = bytes + alignment - 1; 00214 00215 // reserve space to store the delta 00216 actual_byte_count += sizeof(int); 00217 00218 // allocation 00219 char *original_ptr = new char[actual_byte_count]; 00220 00221 if (original_ptr == NULL) 00222 return NULL; 00223 00224 // move base pointer by the space required for our delta 00225 char *base_ptr = (char *)original_ptr + sizeof(int); 00226 00227 // align the pointer 00228 #if 1 00229 // warning-free workaround 00230 unsigned long long long_long_ptr = base_ptr - (char*)0; 00231 while( long_long_ptr % alignment ) ++long_long_ptr; 00232 void *aligned_ptr = (char*)0 + long_long_ptr; 00233 #else 00234 // this generates too many warnings 00235 void *aligned_ptr = (void *) (((unsigned long long)base_ptr + alignment - 1) & ~((unsigned long long)alignment - 1)); 00236 #endif 00237 00238 // compute the delta 00239 int delta = (int)((char*)aligned_ptr - (char*)original_ptr); 00240 00241 // store the delta just sizeof(int) bytes before the aligned pointer 00242 *((int *)aligned_ptr - 1) = delta; 00243 00244 return aligned_ptr; 00245 } 00246 00247 static void alignedFree(void *ptr) 00248 { 00249 if (ptr == NULL) 00250 return; 00251 00252 // gets the previously stored delta 00253 int delta = *( (int *)ptr - 1); 00254 00255 // calculate the pointer returned by malloc() 00256 char *original_ptr = (char*)ptr - delta; 00257 00258 // finally free the original pointer 00259 delete [] original_ptr; 00260 } 00261 00262 protected: 00263 unsigned char* mPtr; 00264 size_t mByteCount; 00265 size_t mAlignment; 00266 EAllocationMode mAllocationMode; 00267 }; 00268 00269 } 00270 00271 #endif