00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef NL_INDEX_BUFFER_H
00025 #define NL_INDEX_BUFFER_H
00026
00027 #include "nel/misc/types_nl.h"
00028 #include "nel/misc/smart_ptr.h"
00029 #include <vector>
00030
00031 namespace NLMISC
00032 {
00033 class IStream;
00034 };
00035
00036 namespace NL3D {
00037
00038 using NLMISC::CRefCount;
00039 using NLMISC::CRefPtr;
00040
00041
00042 class IIBDrvInfos;
00043 class CIndexBuffer;
00044 class IDriver;
00045 class CIndexBufferReadWrite;
00046 class CIndexBufferRead;
00047 typedef std::list<IIBDrvInfos*> TIBDrvInfoPtrList;
00048 typedef TIBDrvInfoPtrList::iterator ItIBDrvInfoPtrList;
00049
00050
00051 #define NL_NAMED_INDEX_BUFFER
00052 #ifdef NL_NAMED_INDEX_BUFFER
00053 #define NL_SET_IB_NAME(ib, n) if ((ib).getName().empty()) (ib).setName(n);
00054 #else
00055 #define NL_SET_IB_NAME(ib, n)
00056 #endif
00057
00058
00059
00060 #define NL_FORCE_INDEX_BUFFER_16
00061
00062 #ifdef NL_FORCE_INDEX_BUFFER_16
00063 typedef uint16 TIndexType;
00064 #define NL_DEFAULT_INDEX_BUFFER_FORMAT CIndexBuffer::Indices16
00065
00066 #define NL_MESH_INDEX16
00067 #define NL_MESH_MRM_INDEX16
00068 #define NL_SKINNED_MESH_MRM_INDEX16
00069
00070 #define NL_LOD_CHARACTER_INDEX16
00071 #define NL_COARSE_MESH_INDEX16
00072 #else
00073 typedef uint32 TIndexType;
00074 #define NL_DEFAULT_INDEX_BUFFER_FORMAT CIndexBuffer::Indices32
00075 #endif
00076
00077
00078
00079
00080 #ifdef NL_MESH_INDEX16
00081 typedef uint16 TMeshIndexType;
00082 #define NL_MESH_INDEX_FORMAT CIndexBuffer::Indices16
00083 #else
00084 typedef uint32 TMeshIndexType;
00085 #define NL_MESH_INDEX_FORMAT CIndexBuffer::Indices32
00086 #endif
00087
00088
00089 #ifdef NL_MESH_MRM_INDEX16
00090 typedef uint16 TMeshMRMIndexType;
00091 #define NL_MESH_MRM_INDEX_FORMAT CIndexBuffer::Indices16
00092 #else
00093 typedef uint32 TMeshMRMIndexType;
00094 #define NL_MESH_MRM_INDEX_FORMAT CIndexBuffer::Indices32
00095 #endif
00096
00097
00098 #ifdef NL_SKINNED_MESH_MRM_INDEX16
00099 typedef uint16 TSkinnedMeshMRMIndexType;
00100 #define NL_SKINNED_MESH_MRM_INDEX_FORMAT CIndexBuffer::Indices16
00101 #else
00102 typedef uint32 TSkinnedMeshMRMIndexType;
00103 #define NL_SKINNED_MESH_MRM_INDEX_FORMAT CIndexBuffer::Indices32
00104 #endif
00105
00106
00107
00108 #ifdef NL_LANDSCAPE_INDEX16
00109 typedef uint16 TLandscapeIndexType;
00110 #define NL_LANDSCAPE_INDEX_FORMAT CIndexBuffer::Indices16
00111 #else
00112 typedef uint32 TLandscapeIndexType;
00113 #define NL_LANDSCAPE_INDEX_FORMAT CIndexBuffer::Indices32
00114 #endif
00115
00116
00117 #ifdef NL_LOD_CHARACTER_INDEX16
00118 typedef uint16 TLodCharacterIndexType;
00119 #define NL_LOD_CHARACTER_INDEX_FORMAT CIndexBuffer::Indices16
00120 #else
00121 typedef uint32 TLodCharacterIndexType;
00122 #define NL_LOD_CHARACTER_INDEX_FORMAT CIndexBuffer::Indices32
00123 #endif
00124
00125
00126 #ifdef NL_COARSE_MESH_INDEX16
00127 typedef uint16 TCoarseMeshIndexType;
00128 #define NL_COARSE_MESH_INDEX_FORMAT CIndexBuffer::Indices16
00129 #else
00130 typedef uint32 TCoarseMeshIndexType;
00131 #define NL_COARSE_MESH_INDEX_FORMAT CIndexBuffer::Indices32
00132 #endif
00133
00134
00135
00150
00151
00152
00153
00154
00155
00156 class CIndexBuffer : public CRefCount
00157 {
00158 public:
00159 friend class CIndexBufferReadWrite;
00160 friend class CIndexBufferRead;
00161
00165 enum TPreferredMemory
00166 {
00167 RAMPreferred = 0,
00168 AGPPreferred,
00169 StaticPreferred,
00170 RAMVolatile,
00171 AGPVolatile,
00172 PreferredCount,
00173 };
00174
00178 enum TLocation
00179 {
00180 RAMResident = 0,
00181 AGPResident,
00182 VRAMResident,
00183 NotResident,
00184 LocationCount,
00185 };
00186
00187 enum TFormat
00188 {
00189 Indices16 = 0,
00190 Indices32,
00191 IndicesUnknownFormat
00192 };
00193
00197 enum
00198 {
00200 TouchedIndexFormat = 1,
00201
00203 TouchedNumIndexes = 2,
00204
00206 TouchedReserve = 4,
00207
00209 TouchedAll = 0xFFFF
00210 };
00211
00212 public:
00213
00214
00215
00216 CRefPtr<IIBDrvInfos> DrvInfos;
00217 uint getTouchFlags() const { return _InternalFlags&TouchedAll; }
00218
00226 void setLocation (TLocation newLocation);
00227
00229 void fillBuffer ();
00230
00231
00232 public:
00233
00234
00235
00236
00237
00241 CIndexBuffer(void);
00242
00246 CIndexBuffer(const char *name);
00247
00252 CIndexBuffer(const CIndexBuffer &vb);
00253
00257 ~CIndexBuffer(void);
00258
00265 CIndexBuffer &operator=(const CIndexBuffer &vb);
00266
00306 void setPreferredMemory (TPreferredMemory preferredMemory, bool keepLocalMemory);
00307
00311 TPreferredMemory getPreferredMemory () const { return _PreferredMemory; }
00312
00316 bool getKeepLocalMemory () const { return _KeepLocalMemory; }
00317
00321 TLocation getLocation () const { return _Location; }
00322
00327 bool isResident () const { return (_Location != NotResident) && DrvInfos; }
00328
00334 void setNumIndexes(uint32 n);
00335
00336
00337 void setFormat(TFormat format);
00338
00339
00340 TFormat getFormat() const { return _Format; }
00341
00342
00343 uint getIndexNumBytes() const { return _Format == Indices16 ? 2 : 4; }
00344
00348 uint32 getNumIndexes(void) const { return(_NbIndexes); }
00349
00358 void deleteAllIndexes();
00359
00368 void reserve(uint32 nIndexes);
00369
00373 uint32 capacity() { return _Capacity; }
00374
00381 void serial(NLMISC::IStream &f);
00382
00393 inline void lock (CIndexBufferReadWrite &accessor, uint first=0, uint last=0);
00394
00407 inline void lock (CIndexBufferRead &accessor, uint first=0, uint last=0) const;
00408
00409
00410 bool isLocked () const {return _LockCounter!=0;}
00411
00412
00413 void setName (const std::string &name) { _Name = name; };
00414 const std::string &getName () const { return _Name; };
00415
00416 private:
00417
00418
00419 bool checkLockedBuffer () const { return _LockedBuffer || (!isResident() && _NonResidentIndexes.empty()); }
00420
00426 inline void unlock (uint first, uint last);
00427
00433 inline void unlock () const;
00434
00435
00436 void resetTouchFlags() {_InternalFlags &= (uint16)(~TouchedAll);}
00437
00438
00439 void restaureNonResidentMemory();
00440
00441
00442 void buildSerialVector(std::vector<uint32> &dest) const;
00443
00444
00445 void restoreFromSerialVector(const std::vector<uint32> &src);
00446
00447
00448 private:
00449
00450 uint16 _InternalFlags;
00451
00452
00453 TFormat _Format;
00454
00455
00456 uint32 _NbIndexes;
00457
00458
00459 uint32 _Capacity;
00460
00461
00462 std::vector<uint8> _NonResidentIndexes;
00463
00464
00465 mutable void *_LockedBuffer;
00466
00467
00468 mutable uint _LockCounter;
00469
00470
00471 TLocation _Location;
00472
00473
00474 TPreferredMemory _PreferredMemory;
00475
00476
00477 uint32 _ResidentSize;
00478
00479
00480 bool _KeepLocalMemory;
00481
00482
00483 std::string _Name;
00484 };
00485
00489
00490
00491
00492 class IIBDrvInfos : public CRefCount
00493 {
00494 protected:
00495 IDriver *_Driver;
00496 private:
00497 ItIBDrvInfoPtrList _DriverIterator;
00498
00499 public:
00500 CRefPtr<CIndexBuffer> IndexBufferPtr;
00501
00502 IIBDrvInfos(IDriver *drv, ItIBDrvInfoPtrList it, CIndexBuffer *ib) {_Driver= drv; _DriverIterator= it; IndexBufferPtr = ib;}
00503
00509 virtual void *lock (uint first, uint last, bool readOnly) =0;
00510
00515 virtual void unlock (uint first, uint last) =0;
00516
00517
00518
00519 virtual ~IIBDrvInfos();
00520
00521
00522 CIndexBuffer::TFormat getFormat() const { nlassert(IndexBufferPtr); return IndexBufferPtr->getFormat(); }
00523 uint getIndexNumBytes() const { nlassert(IndexBufferPtr); return IndexBufferPtr->getIndexNumBytes(); }
00524 };
00525
00529 class CIndexBufferReadWrite
00530 {
00531 public:
00532 friend class CIndexBuffer;
00533
00534 CIndexBufferReadWrite()
00535 {
00536 _Parent = NULL;
00537 }
00538 ~CIndexBufferReadWrite()
00539 {
00540 unlock();
00541 }
00542
00547 void unlock()
00548 {
00549 if (_Parent)
00550 {
00551 _Parent->unlock(_First, _Last);
00552 _Parent = NULL;
00553 }
00554 }
00555
00556
00557 inline void setLine(uint idx, uint32 i0, uint32 i1)
00558 {
00559 nlassert (_Parent->checkLockedBuffer());
00560 #ifdef NL_DEBUG
00561 nlassert(idx < _Parent->getNumIndexes());
00562 nlassert(idx + 1 < _Parent->getNumIndexes());
00563 #endif
00564 if (_Parent->getFormat() == CIndexBuffer::Indices16)
00565 {
00566 #ifdef NL_DEBUG
00567 nlassert(i0 <= 65535);
00568 nlassert(i1 <= 65535);
00569 #endif
00570 ((uint16 *) _Parent->_LockedBuffer)[idx] = (uint16) i0;
00571 ((uint16 *) _Parent->_LockedBuffer)[idx+1] = (uint16) i1;
00572 }
00573 else if (_Parent->getFormat() == CIndexBuffer::Indices32)
00574 {
00575 ((uint32 *) _Parent->_LockedBuffer)[idx] = i0;
00576 ((uint32 *) _Parent->_LockedBuffer)[idx+1] = i1;
00577 }
00578 else
00579 {
00580 nlassert(0);
00581 }
00582 }
00583
00584
00585 inline void setTri(uint idx, uint32 i0, uint32 i1, uint32 i2)
00586 {
00587 nlassert (_Parent->checkLockedBuffer());
00588 #ifdef NL_DEBUG
00589 nlassert(idx < _Parent->getNumIndexes());
00590 nlassert(idx + 1 < _Parent->getNumIndexes());
00591 nlassert(idx + 2 < _Parent->getNumIndexes());
00592 #endif
00593 if (_Parent->getFormat() == CIndexBuffer::Indices16)
00594 {
00595 #ifdef NL_DEBUG
00596 nlassert(i0 <= 65535);
00597 nlassert(i1 <= 65535);
00598 nlassert(i2 <= 65535);
00599 #endif
00600 ((uint16 *) _Parent->_LockedBuffer)[idx] = (uint16) i0;
00601 ((uint16 *) _Parent->_LockedBuffer)[idx+1] = (uint16) i1;
00602 ((uint16 *) _Parent->_LockedBuffer)[idx+2] = (uint16) i2;
00603 }
00604 else if (_Parent->getFormat() == CIndexBuffer::Indices32)
00605 {
00606 ((uint32 *) _Parent->_LockedBuffer)[idx] = i0;
00607 ((uint32 *) _Parent->_LockedBuffer)[idx+1] = i1;
00608 ((uint32 *) _Parent->_LockedBuffer)[idx+2] = i2;
00609 }
00610 else
00611 {
00612 nlassert(0);
00613 }
00614 }
00615
00616
00617 void *getPtr (uint idx=0)
00618 {
00619 nlassert (_Parent->checkLockedBuffer());
00620 if (_Parent->getFormat() == CIndexBuffer::Indices16)
00621 {
00622 return &(((uint16 *) _Parent->_LockedBuffer)[idx]);
00623 }
00624 else if (_Parent->getFormat() == CIndexBuffer::Indices32)
00625 {
00626 return &(((uint32 *) _Parent->_LockedBuffer)[idx]);
00627 }
00628 else
00629 {
00630 nlassert(0);
00631 }
00632 return NULL;
00633 }
00634
00639 void touchIndexes (uint first, uint last);
00640
00641 const CIndexBuffer *getParent() const { return _Parent; }
00642
00643 CIndexBuffer::TFormat getFormat() const { nlassert(_Parent); return _Parent->getFormat(); }
00644 uint getIndexNumBytes() const { nlassert(_Parent); return _Parent->getIndexNumBytes(); }
00645
00646 private:
00647
00648
00649 void operator=(const CIndexBufferReadWrite& ) {}
00650 CIndexBufferReadWrite(const CIndexBufferReadWrite& ) {}
00651
00652 CIndexBuffer *_Parent;
00653 uint _First, _Last;
00654 };
00655
00659 class CIndexBufferRead
00660 {
00661 public:
00662 friend class CIndexBuffer;
00663
00664 CIndexBufferRead()
00665 {
00666 _Parent = NULL;
00667 }
00668 ~CIndexBufferRead()
00669 {
00670 unlock();
00671 }
00672
00677 void unlock()
00678 {
00679 if (_Parent)
00680 {
00681 _Parent->unlock();
00682 _Parent = NULL;
00683 }
00684 }
00685
00686
00687 const void *getPtr (uint idx=0) const
00688 {
00689 nlassert (_Parent->checkLockedBuffer());
00690 if (_Parent->getFormat() == CIndexBuffer::Indices16)
00691 {
00692 return &(((const uint16 *) _Parent->_LockedBuffer)[idx]);
00693 }
00694 else if (_Parent->getFormat() == CIndexBuffer::Indices32)
00695 {
00696 return &(((const uint32 *) _Parent->_LockedBuffer)[idx]);
00697 }
00698 else
00699 {
00700 nlassert(0);
00701 }
00702 return NULL;
00703 }
00704 const CIndexBuffer *getParent() const { return _Parent; }
00705 uint getIndexNumBytes() const { nlassert(_Parent); return _Parent->getIndexNumBytes(); }
00706 CIndexBuffer::TFormat getFormat() const { nlassert(_Parent); return _Parent->getFormat(); }
00707 private:
00708
00709
00710 void operator=(const CIndexBufferRead& ) {}
00711 CIndexBufferRead(const CIndexBufferRead& ) {}
00712
00713 const CIndexBuffer *_Parent;
00714 };
00715
00716
00717
00718 inline void CIndexBuffer::lock (CIndexBufferReadWrite &accessor, uint first, uint last)
00719 {
00720 accessor.unlock();
00721 accessor._Parent = this;
00722 accessor._First = 0;
00723 accessor._Last = 0;
00724
00725
00726 if (_LockCounter == 0)
00727 {
00728 nlassert (_LockedBuffer == NULL);
00729
00730
00731 if (isResident() && !_KeepLocalMemory)
00732 {
00733 if (last == 0)
00734 last = _NbIndexes;
00735 _LockedBuffer = DrvInfos->lock (first, last, false);
00736 }
00737 else
00738 {
00739 if (_NonResidentIndexes.empty())
00740 _LockedBuffer = NULL;
00741 else
00742 _LockedBuffer = &(_NonResidentIndexes[0]);
00743 }
00744 }
00745 else
00746 nlassert ((first==0)&&(last==0));
00747
00748 _LockCounter++;
00749 }
00750
00751
00752
00753 inline void CIndexBuffer::lock (CIndexBufferRead &accessor, uint first, uint last) const
00754 {
00755 accessor.unlock();
00756 accessor._Parent = this;
00757
00758
00759 if (_LockCounter == 0)
00760 {
00761 nlassert (_LockedBuffer == NULL);
00762
00763
00764 if (isResident() && !_KeepLocalMemory)
00765 {
00766 if (last == 0)
00767 last = _NbIndexes;
00768
00769 nlassertex (_Location==RAMResident, ("Try to read a write only index buffer"));
00770 _LockedBuffer = DrvInfos->lock (first, last, true);
00771 }
00772 else
00773 {
00774 if (_NonResidentIndexes.empty())
00775 _LockedBuffer = NULL;
00776 else
00777 _LockedBuffer = const_cast<void*>((const void *) &(_NonResidentIndexes[0]));
00778 }
00779 }
00780 else
00781 nlassert ((first==0)&&(last==0));
00782
00783 _LockCounter++;
00784 }
00785
00786
00787
00788 inline void CIndexBuffer::unlock (uint first, uint end)
00789 {
00790 nlassertex (_LockCounter!=0, ("Index buffer not locked"));
00791 nlassert (_LockedBuffer || (!isResident() && _NonResidentIndexes.empty()));
00792
00793 if (_LockCounter)
00794 _LockCounter--;
00795
00796 if (_LockCounter == 0)
00797 {
00798 if (isResident() && !_KeepLocalMemory)
00799 DrvInfos->unlock (0, 0);
00800
00801 _LockedBuffer = NULL;
00802 }
00803 }
00804
00805
00806
00807 inline void CIndexBuffer::unlock () const
00808 {
00809 nlassertex (_LockCounter!=0, ("Index buffer not locked"));
00810 nlassert (_LockedBuffer || (!isResident() && _NonResidentIndexes.empty()));
00811
00812 if (_LockCounter)
00813 _LockCounter--;
00814
00815 if (_LockCounter == 0)
00816 {
00817 if (isResident() && !_KeepLocalMemory)
00818 DrvInfos->unlock (0, 0);
00819
00820 _LockedBuffer = NULL;
00821 }
00822 }
00823
00824
00825 }
00826
00827
00828 #endif // NL_INDEX_BUFFER_H
00829
00830