00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef __GA_DATAARRAYPAGETABLEIMPL_H_INCLUDED__
00019 #define __GA_DATAARRAYPAGETABLEIMPL_H_INCLUDED__
00020
00021 #include "GA_Memory.h"
00022 #include "GA_Types.h"
00023
00024 #include <UT/UT_ValArray.h>
00025 #include <UT/UT_Vector3.h>
00026 #include <SYS/SYS_AtomicInt.h>
00027 #include <SYS/SYS_Types.h>
00028
00029 #include <string.h>
00030
00031
00032
00033
00034 namespace GA_Private {
00035
00036
00037 template <typename T>
00038 class ga_DataArrayPage
00039 {
00040 public:
00041 ga_DataArrayPage()
00042 : myRefCount(1)
00043 {
00044 myData = (T *)GA_Memory::Malloc(GA_MEM_ATTRIBUTE_DATA,
00045 GA_PAGE_SIZE * sizeof(T));
00046 }
00047 ~ga_DataArrayPage()
00048 {
00049 GA_Memory::Free(GA_MEM_ATTRIBUTE_DATA, myData,
00050 GA_PAGE_SIZE * sizeof(T));
00051 }
00052
00053 exint
00054 getMemoryUsage() const
00055 {
00056 return sizeof(*this) + GA_PAGE_SIZE*sizeof(T);
00057 }
00058
00059
00060 void ref() const { myRefCount.add(1); }
00061 void unref() { if(myRefCount.add(-1) == 0) delete this; }
00062 bool isShared() const { return myRefCount.relaxedLoad() != 1; }
00063
00064 ga_DataArrayPage<T> *
00065 copy() const
00066 {
00067 ga_DataArrayPage<T> *d = new ga_DataArrayPage<T>();
00068 if (d && d->myData)
00069 memcpy(d->myData, myData, GA_PAGE_SIZE * sizeof(T));
00070 return d;
00071 }
00072
00073 const T *castToData() const { return myData; }
00074 T *castToData() { return myData; }
00075
00076 private:
00077 mutable SYS_AtomicInt32 myRefCount;
00078 T * myData;
00079 };
00080
00081
00082 template<typename T> static inline bool
00083 ga_IsNotZero(T a) { return (bool) a; }
00084 template<> inline bool
00085 ga_IsNotZero(UT_Vector3F a) { return a.x() || a.y() || a.z(); }
00086 template<> inline bool
00087 ga_IsNotZero(UT_Vector3D a) { return a.x() || a.y() || a.z(); }
00088
00089
00090 class ga_PageTableBaseImpl
00091 {
00092 };
00093
00094
00095
00096
00097
00098
00099
00100 template <typename T, typename TB, int SLICE, int VECTORSIZE>
00101 class ga_DataArrayPageTableImpl : public ga_PageTableBaseImpl
00102 {
00103 protected:
00104
00105 struct ga_DataArrayPagePtr
00106 {
00107 union
00108 {
00109 ga_DataArrayPage<T> * ptr;
00110 char rawvalue[sizeof(T)];
00111
00112
00113
00114 const T & value() const { return *((T*)rawvalue); }
00115 T & value() { return *((T*)rawvalue); }
00116 const TB & scalarValue() const { return ((TB*)rawvalue)[SLICE]; }
00117 } myData;
00118
00119 T * myRawData;
00120
00121
00122
00123 exint
00124 getMemoryUsage() const
00125 {
00126 if (!myRawData)
00127 return 0;
00128 else
00129 return myData.ptr->getMemoryUsage();
00130 }
00131 };
00132
00133 mutable UT_ValArray<ga_DataArrayPagePtr> myPages;
00134
00135 public:
00136
00137 SYS_FORCE_INLINE TB
00138 get(GA_Offset offset) const
00139 {
00140 return get(GAgetPageNum(offset), GAgetPageOff(offset));
00141 }
00142 SYS_FORCE_INLINE void
00143 set(GA_Offset offset, TB v)
00144 {
00145 return set(GAgetPageNum(offset), GAgetPageOff(offset), v);
00146 }
00147 SYS_FORCE_INLINE TB
00148 get(GA_PageNum pageid, GA_PageOff offset) const
00149 {
00150 const ga_DataArrayPagePtr &page = myPages(pageid);
00151 if (!page.myRawData)
00152 return page.myData.scalarValue();
00153 else
00154 return ((TB*)&(page.myRawData[offset]))[SLICE];
00155 }
00156 SYS_FORCE_INLINE void
00157 set(GA_PageNum pageid, GA_PageOff offset, TB v)
00158 {
00159 const ga_DataArrayPagePtr &page = myPages(pageid);
00160 if (page.myRawData)
00161 {
00162 if (page.myData.ptr->isShared())
00163 {
00164 ((TB*)&forceHardenToData(pageid)[offset])[SLICE] = v;
00165 }
00166 else
00167 ((TB*)&page.myRawData[offset])[SLICE] = v;
00168 }
00169 else
00170 {
00171
00172 if (page.myData.scalarValue() != v)
00173 {
00174
00175 ((TB*)&forceHardenToData(pageid)[offset])[SLICE] = v;
00176 }
00177 }
00178 }
00179
00180 SYS_FORCE_INLINE void
00181 add(GA_PageNum pageid, GA_PageOff offset, TB v)
00182 {
00183 ((TB*)&hardenToData(pageid)[offset])[SLICE] += v;
00184 }
00185
00186 SYS_FORCE_INLINE T
00187 getVector(GA_Offset offset) const
00188 {
00189 return getVector(GAgetPageNum(offset), GAgetPageOff(offset));
00190 }
00191 SYS_FORCE_INLINE void
00192 setVector(GA_Offset offset, T v)
00193 {
00194 return setVector(GAgetPageNum(offset), GAgetPageOff(offset), v);
00195 }
00196 SYS_FORCE_INLINE T
00197 getVector(GA_PageNum pageid, GA_PageOff offset) const
00198 {
00199 const ga_DataArrayPagePtr &page = myPages(pageid);
00200 if (!page.myRawData)
00201 return page.myData.value();
00202 else
00203 return page.myRawData[offset];
00204 }
00205 SYS_FORCE_INLINE void
00206 setVector(GA_PageNum pageid, GA_PageOff offset, T v)
00207 {
00208 const ga_DataArrayPagePtr &page = myPages(pageid);
00209 if (page.myRawData)
00210 {
00211 if (page.myData.ptr->isShared())
00212 {
00213 forceHardenToData(pageid)[offset] = v;
00214 }
00215 else
00216 page.myRawData[offset] = v;
00217 }
00218 else
00219 {
00220
00221 if (page.myData.value() != v)
00222 {
00223
00224 forceHardenToData(pageid)[offset] = v;
00225 }
00226 }
00227 }
00228 SYS_FORCE_INLINE void
00229 addVector(GA_PageNum pageid, GA_PageOff offset, T v)
00230 {
00231 hardenToData(pageid)[offset] += v;
00232 }
00233
00234 ga_DataArrayPage<T> *
00235 createConstantPage(T value) const
00236 {
00237 ga_DataArrayPage<T> * page = new ga_DataArrayPage<T>();
00238 T * data = page->castToData();
00239
00240 if (ga_IsNotZero(value))
00241 {
00242 for (GA_Size i = 0; i < GA_PAGE_SIZE; ++i)
00243 data[i] = value;
00244 }
00245 else
00246 {
00247 memset(data, 0, GA_PAGE_SIZE * sizeof(T));
00248 }
00249
00250 return page;
00251 }
00252
00253
00254 T *
00255 forceHardenToData(GA_Size i)
00256 {
00257 ga_DataArrayPagePtr & page = myPages(i);
00258 ga_DataArrayPage<T> * pageptr;
00259 T * result;
00260
00261 if (!page.myRawData)
00262 {
00263 pageptr = createConstantPage(page.myData.value());
00264 page.myData.ptr = pageptr;
00265 page.myRawData = result = pageptr->castToData();
00266 }
00267 else
00268 {
00269 pageptr = page.myData.ptr;
00270 ga_DataArrayPage<T> *oldpage = pageptr;
00271 pageptr = oldpage->copy();
00272 page.myData.ptr = pageptr;
00273 page.myRawData = result = pageptr->castToData();
00274 oldpage->unref();
00275 }
00276 return result;
00277 }
00278
00279 SYS_FORCE_INLINE T *
00280 hardenToData(GA_Size pageid)
00281 {
00282 const ga_DataArrayPagePtr &page = myPages(pageid);
00283
00284 if (!page.myRawData)
00285 {
00286 return forceHardenToData(pageid);
00287 }
00288 else
00289 {
00290
00291 if (page.myData.ptr->isShared())
00292 {
00293 return forceHardenToData(pageid);
00294 }
00295 return page.myRawData;
00296 }
00297 }
00298
00299
00300 SYS_FORCE_INLINE T *
00301 softenToData(GA_Size pageid)
00302 {
00303 const ga_DataArrayPagePtr &page = myPages(pageid);
00304
00305 if (!page.myRawData)
00306 {
00307 return forceHardenToData(pageid);
00308 }
00309 else
00310 {
00311 return page.myRawData;
00312 }
00313 }
00314
00315 };
00316
00317
00318 typedef ga_DataArrayPageTableImpl<UT_Vector3F,fpreal32,0,3>
00319 ga_DataArrayPageTableImplV3;
00320 typedef ga_DataArrayPageTableImpl<int16,int16,0,1>
00321 ga_DataArrayPageTableImplI16;
00322 typedef ga_DataArrayPageTableImpl<int32,int32,0,1>
00323 ga_DataArrayPageTableImplI32;
00324 typedef ga_DataArrayPageTableImpl<int64,int64,0,1>
00325 ga_DataArrayPageTableImplI64;
00326
00327 }
00328 #endif // __GA_DATAARRAYPAGETABLEIMPL_H_INCLUDED__