index_buffer.h

Go to the documentation of this file.
00001 
00005 /* Copyright, 2000 Nevrax Ltd.
00006  *
00007  * This file is part of NEVRAX NEL.
00008  * NEVRAX NEL is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2, or (at your option)
00011  * any later version.
00012 
00013  * NEVRAX NEL is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00016  * General Public License for more details.
00017 
00018  * You should have received a copy of the GNU General Public License
00019  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00020  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00021  * MA 02111-1307, USA.
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 // List typedef.
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; // default index type
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     //#define NL_LANDSCAPE_INDEX16
00070     #define NL_LOD_CHARACTER_INDEX16
00071     #define NL_COARSE_MESH_INDEX16
00072 #else
00073     typedef uint32 TIndexType; // default index type
00074     #define NL_DEFAULT_INDEX_BUFFER_FORMAT CIndexBuffer::Indices32
00075 #endif
00076 
00077 
00078 
00079 // 16 bit indices for meshs ?
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 // 16 bit indices for mesh_mrm ?
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 // 16 bit indices for skinned mesh_mrm ?
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 // 16 bit indices for landscape ?
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 // 16 bit for lod characters ?
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 // 16 bit for coarse meshs ?
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 /* *** IMPORTANT ********************
00151  * *** IF YOU MODIFY THE STRUCTURE OF THIS CLASS, PLEASE INCREMENT IDriver::InterfaceVersion TO INVALIDATE OLD DRIVER DLL
00152  * **********************************
00153  */
00154 
00155 // All these flags are similar to DX8
00156 class CIndexBuffer : public CRefCount
00157 {
00158 public:
00159     friend class CIndexBufferReadWrite;
00160     friend class CIndexBufferRead;
00161 
00165     enum TPreferredMemory
00166     {
00167         RAMPreferred = 0,   // A block of driver RAM memory is allocated for this buffer. The buffer is read/write.
00168         AGPPreferred,       // A block of driver AGP memory is allocated for this buffer. The buffer is writeonly.
00169         StaticPreferred,    // The buffer will not be modified. A block of driver AGP or VRAM memory is allocated for this buffer. The buffer is writeonly.
00170         RAMVolatile,        // A block of temporary driver RAM memory will be returned by lock(). The buffer must be entirely filled after each swapBuffers(). The buffer is writeonly.
00171         AGPVolatile,        // A block of temporary driver AGP memory will be returned by lock(). The buffer must be entirely filled after each swapBuffers(). The buffer is writeonly.
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 // reserved, for use by driver
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     // \name Private. For Driver only.
00215     // @{
00216     CRefPtr<IIBDrvInfos>    DrvInfos;
00217     uint                    getTouchFlags() const { return _InternalFlags&TouchedAll; }
00218 
00226     void                    setLocation (TLocation newLocation);    // The driver implementation must set the location after activeIndexBuffer.
00227 
00229     void                    fillBuffer ();
00230     // @}
00231 
00232 public:
00233     /* ***********************************************
00234      *  WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance
00235      *  It can be loaded/called through CAsyncFileManager for instance
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     // Set format for indices. This discards previous indices
00337     void                    setFormat(TFormat format);
00338 
00339     // Get format
00340     TFormat                 getFormat() const { return _Format; }
00341 
00342     // get number of bytes per index
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     // Return true if the vetx buffer is locked
00410     bool        isLocked () const {return _LockCounter!=0;}
00411 
00412     // debug name
00413     void        setName (const std::string &name) { _Name = name; };
00414     const std::string &getName () const { return _Name; };
00415 
00416 private:
00417 
00418     // Check locked buffers
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     // Reset the touch flags
00436     void        resetTouchFlags() {_InternalFlags &= (uint16)(~TouchedAll);}
00437 
00438     // Force non resident memory
00439     void        restaureNonResidentMemory();
00440 
00441     // Convert current index to a serializable vector
00442     void buildSerialVector(std::vector<uint32> &dest) const;
00443 
00444     // Convert current index from a serialized vector
00445     void restoreFromSerialVector(const std::vector<uint32> &src);
00446 
00447 
00448 private:
00449     // Internal flags
00450     uint16                  _InternalFlags;     // Offset 18 : aligned
00451 
00452     // Format of indices
00453     TFormat                 _Format;
00454 
00455     // Index count in the buffer
00456     uint32                  _NbIndexes;         // Offset 20 : aligned
00457 
00458     // Capacity of the buffer
00459     uint32                  _Capacity;
00460 
00461     // Index array
00462     std::vector<uint8>      _NonResidentIndexes;
00463 
00464     // The locked index buffer
00465     mutable void            *_LockedBuffer;
00466 
00467     // The index buffer is locked n times
00468     mutable uint            _LockCounter;
00469 
00470     // Location of the buffer
00471     TLocation               _Location;
00472 
00473     // Prefered memory
00474     TPreferredMemory        _PreferredMemory;
00475 
00476     // Resident buffer size
00477     uint32                  _ResidentSize;
00478 
00479     // Keep in local memory
00480     bool                    _KeepLocalMemory;
00481 
00482     // debug name
00483     std::string             _Name;
00484 };
00485 
00489 // *** IMPORTANT ********************
00490 // *** IF YOU MODIFY THE STRUCTURE OF THIS CLASS, PLEASE INCREMENT IDriver::InterfaceVersion TO INVALIDATE OLD DRIVER DLL
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     /* The virtual dtor is important.
00518      * The driver implementation must call setLocation (NotResident) if IndexBufferPtr!=NULL.*/
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     // Set a line index at index idx.
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     // Set a line index at index idx.
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     // Get a pointer on an index.
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     // No copy operators available
00649     void        operator=(const CIndexBufferReadWrite& /* other */) {}
00650     CIndexBufferReadWrite(const CIndexBufferReadWrite& /* other */) {}
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     // Get a pointer on an index.
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     // No copy operators available
00710     void        operator=(const CIndexBufferRead& /* other */) {}
00711     CIndexBufferRead(const CIndexBufferRead& /* other */) {}
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     // Already locked ?
00726     if (_LockCounter == 0)
00727     {
00728         nlassert (_LockedBuffer == NULL);
00729 
00730         // No
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     // Already locked ?
00759     if (_LockCounter == 0)
00760     {
00761         nlassert (_LockedBuffer == NULL);
00762 
00763         // No
00764         if (isResident() && !_KeepLocalMemory)
00765         {
00766             if (last == 0)
00767                 last = _NbIndexes;
00768             // Can read it ?
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 } // NL3D
00826 
00827 
00828 #endif // NL_INDEX_BUFFER_H
00829 
00830 /* End of index_buffer.h */

Generated on Thu Jan 7 08:26:18 2010 for NeL by  doxygen 1.6.1