1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include "nel/3d/index_buffer.h"
20 #include "nel/3d/driver.h"
21 #include "nel/misc/stream.h"
22 #include "nel/misc/fast_mem.h"
24 using namespace NLMISC
;
32 // ***************************************************************************
34 // ***************************************************************************
36 IIBDrvInfos::~IIBDrvInfos()
38 _Driver
->removeIBDrvInfoPtr(_DriverIterator
);
41 // ***************************************************************************
43 // ***************************************************************************
45 CIndexBuffer::CIndexBuffer()
47 /* ***********************************************
48 * WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance
49 * It can be loaded/called through CAsyncFileManager for instance
50 * ***********************************************/
57 _PreferredMemory
= RAMPreferred
;
58 _Location
= NotResident
;
60 _KeepLocalMemory
= false;
64 // ***************************************************************************
66 CIndexBuffer::CIndexBuffer(const CIndexBuffer
&vb
) : CRefCount()
68 /* ***********************************************
69 * WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance
70 * It can be loaded/called through CAsyncFileManager for instance
71 * ***********************************************/
76 _PreferredMemory
= RAMPreferred
;
77 _Location
= NotResident
;
79 _KeepLocalMemory
= false;
83 // ***************************************************************************
84 CIndexBuffer::CIndexBuffer(const char *name
)
86 /* ***********************************************
87 * WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance
88 * It can be loaded/called through CAsyncFileManager for instance
89 * ***********************************************/
95 _PreferredMemory
= RAMPreferred
;
96 _Location
= NotResident
;
98 _KeepLocalMemory
= false;
102 // ***************************************************************************
104 CIndexBuffer::~CIndexBuffer()
106 /* ***********************************************
107 * WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance
108 * It can be loaded/called through CAsyncFileManager for instance
109 * ***********************************************/
113 DrvInfos
->IndexBufferPtr
= NULL
; // Tell the driver info to not restore memory when it will die
115 // Must kill the drv mirror of this VB.
119 // ***************************************************************************
121 CIndexBuffer
&CIndexBuffer::operator=(const CIndexBuffer
&vb
)
123 nlassertex (!isLocked(), ("The index buffer is locked."));
125 _InternalFlags
= vb
._InternalFlags
;
126 _NbIndexes
= vb
._NbIndexes
;
127 _Capacity
= vb
._Capacity
;
128 _NonResidentIndexes
= vb
._NonResidentIndexes
;
129 _PreferredMemory
= vb
._PreferredMemory
;
130 _KeepLocalMemory
= vb
._KeepLocalMemory
;
131 _Format
= vb
._Format
;
134 _InternalFlags
|= TouchedAll
;
135 _Location
= NotResident
;
141 // ***************************************************************************
143 void CIndexBuffer::setPreferredMemory (TPreferredMemory preferredMemory
, bool keepLocalMemory
)
145 if ((_PreferredMemory
!= preferredMemory
) || (_KeepLocalMemory
!= keepLocalMemory
))
147 _PreferredMemory
= preferredMemory
;
148 _KeepLocalMemory
= keepLocalMemory
;
150 // Force non resident
151 restoreNonResidentMemory();
155 // ***************************************************************************
157 void CIndexBuffer::reserve(uint32 n
)
159 nlassert (!isLocked());
163 _NbIndexes
=std::min (_NbIndexes
,_Capacity
);
165 // Force non resident
166 restoreNonResidentMemory();
170 // ***************************************************************************
172 void CIndexBuffer::setNumIndexes(uint32 n
)
180 _InternalFlags
|= TouchedNumIndexes
;
185 // ***************************************************************************
187 void CIndexBuffer::setFormat(TFormat format
)
189 if (format
== _Format
) return;
190 uint numIndexes
= getNumIndexes();
193 setNumIndexes(numIndexes
);
196 // ***************************************************************************
198 void CIndexBuffer::deleteAllIndexes()
202 nlassert (!isLocked());
204 contReset(_NonResidentIndexes
);
209 _InternalFlags
|= TouchedNumIndexes
;
212 // Force non resident
213 restoreNonResidentMemory();
215 // Delete driver info
216 nlassert (DrvInfos
== NULL
);
220 // ***************************************************************************
222 void CIndexBuffer::setLocation (TLocation newLocation
)
225 if (newLocation
!= NotResident
)
227 // The driver must have setuped the driver info
230 // Current size of the buffer
231 const uint size
= ((_PreferredMemory
==RAMVolatile
)||(_PreferredMemory
==AGPVolatile
))?_NbIndexes
:_Capacity
;
233 // The buffer must not be resident
234 if (_Location
!= NotResident
)
235 setLocation (NotResident
);
237 // Copy the buffer content
238 void *dest
= DrvInfos
->lock (0, size
, false);
239 nlassert (_NonResidentIndexes
.size() / getIndexNumBytes() == _Capacity
); // Internal buffer must have the good size
241 memcpy (dest
, &(_NonResidentIndexes
[0]), size
*getIndexNumBytes());
242 DrvInfos
->unlock(0, 0);
244 // Reset the non resident container if not a static preferred memory and not put in RAM
245 if ((_PreferredMemory
!= StaticPreferred
) && (_Location
!= RAMResident
) && !_KeepLocalMemory
)
246 contReset(_NonResidentIndexes
);
248 // Clear touched flags
251 _Location
= newLocation
;
252 _ResidentSize
= _Capacity
;
256 // Resize the non resident buffer
257 _NonResidentIndexes
.resize (_Capacity
* getIndexNumBytes());
259 // If resident in RAM, backup the data in non resident memory
260 if ((_Location
== RAMResident
) && (_PreferredMemory
!= RAMVolatile
) && (_PreferredMemory
!= AGPVolatile
) && !_KeepLocalMemory
)
262 // The driver must have setuped the driver info
265 // Copy the old buffer data
266 const void *src
= DrvInfos
->lock (0, _ResidentSize
, true);
267 uint size
= std::min ((uint
)(_Capacity
*getIndexNumBytes()), (uint
)(_ResidentSize
*getIndexNumBytes()));
269 memcpy (&(_NonResidentIndexes
[0]), src
, size
);
270 DrvInfos
->unlock(0, 0);
273 _Location
= NotResident
;
277 _InternalFlags
|= TouchedAll
;
281 // ***************************************************************************
283 void CIndexBuffer::restoreNonResidentMemory()
285 setLocation (NotResident
);
288 DrvInfos
->IndexBufferPtr
= NULL
; // Tell the driver info to not restore memory when it will die
290 // Must kill the drv mirror of this VB.
295 // ***************************************************************************
296 void CIndexBuffer::buildSerialVector(std::vector
<uint32
> &dest
) const
298 dest
.resize(getNumIndexes());
299 if (_Format
== Indices16
)
301 const uint16
*src
= (const uint16
*) &_NonResidentIndexes
[0];
302 // convert to 32 bits
303 for(uint k
= 0; k
< getNumIndexes(); ++k
)
311 memcpy(&dest
[0], &_NonResidentIndexes
[0], sizeof(uint32
) * getNumIndexes());
315 // ***************************************************************************
316 void CIndexBuffer::restoreFromSerialVector(const std::vector
<uint32
> &src
)
318 // for now, just convert to wanted format
319 if (_Format
== Indices16
)
321 _NonResidentIndexes
.resize(sizeof(uint16
) * src
.size());
322 uint16
*dest
= (uint16
*) &_NonResidentIndexes
[0];
323 for(uint k
= 0; k
< src
.size(); ++k
)
325 nlassert(src
[k
] <= 0xffff);
326 *dest
++ = (uint16
) src
[k
];
331 nlassert(_Format
== Indices32
);
332 _NonResidentIndexes
.resize(sizeof(uint32
) * src
.size());
333 memcpy(&_NonResidentIndexes
[0], &src
[0], sizeof(uint32
) * src
.size());
337 // ***************************************************************************
338 void CIndexBuffer::serial(NLMISC::IStream
&f
)
340 /* ***********************************************
341 * WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance
342 * It can be loaded/called through CAsyncFileManager for instance
343 * ***********************************************/
345 /** Version 2 : no more write only flags
346 * Version 1 : index buffer
347 * Version 0 : primitive block
350 sint ver
= f
.serialVersion(2);
356 std::vector
<uint32
> indexes
;
359 f
.serial(nb
, capacity
);
360 f
.serialCont(indexes
);
363 // NB : for backward compatibility, indices are always saved in 32 bit format
364 std::vector
<uint32
> nonResidentIndexes
;
367 buildSerialVector(nonResidentIndexes
);
369 f
.serial(nb
, capacity
);
371 _Capacity
= capacity
*3;
372 f
.serialCont(nonResidentIndexes
);
376 restoreFromSerialVector(nonResidentIndexes
);
380 f
.serial(nb
, capacity
);
381 f
.serialCont(indexes
);
387 // NB : for backward compatibility, indices are always saved in 32 bit format
388 std::vector
<uint32
> nonResidentIndexes
;
391 buildSerialVector(nonResidentIndexes
);
393 f
.serial(_NbIndexes
, _Capacity
);
394 f
.serialCont(nonResidentIndexes
);
395 f
.serialEnum(_PreferredMemory
);
398 restoreFromSerialVector(nonResidentIndexes
);
400 // Read the old format
405 for (i
=0; i
<PreferredCount
; i
++)
413 // Force non resident
414 restoreNonResidentMemory();
418 // ***************************************************************************
420 void CIndexBuffer::fillBuffer ()
422 if (DrvInfos
&& _KeepLocalMemory
)
424 // Copy the local memory in local memory
425 nlassert ((_NbIndexes
* getIndexNumBytes()) <=_NonResidentIndexes
.size());
426 void *dest
= DrvInfos
->lock (0, _NbIndexes
, false);
427 NLMISC::CFastMem::memcpy (dest
, &(_NonResidentIndexes
[0]), _NbIndexes
*getIndexNumBytes());
428 DrvInfos
->unlock(0, _NbIndexes
);
432 // ***************************************************************************