Merge branch 'ryzom/ark-features' into main/gingo-test
[ryzomcore.git] / nel / src / 3d / driver.cpp
blob0dd9f76173a444c66de2eee92ed2f44175b0ca6f
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013-2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
6 //
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "std3d.h"
22 #include <string>
24 #include "nel/misc/types_nl.h"
25 #include "nel/3d/driver.h"
26 #include "nel/3d/vertex_buffer.h"
27 #include "nel/misc/algo.h"
29 //#include <cstdio>
31 using namespace NLMISC;
32 using namespace std;
34 #ifdef DEBUG_NEW
35 #define new DEBUG_NEW
36 #endif
38 namespace NL3D
41 // ***************************************************************************
42 const uint32 IDriver::InterfaceVersion = 0x70; // total video memory
44 // ***************************************************************************
45 IDriver::IDriver() : _SyncTexDrvInfos( "IDriver::_SyncTexDrvInfos" )
47 _PolygonMode= Filled;
48 _StaticMemoryToVRAM=false;
49 _ResetCounter=0;
52 // ***************************************************************************
53 IDriver::~IDriver()
55 // Must clean up everything before closing driver.
56 // Must doing this in release(), so assert here if not done...
58 CSynchronized<TTexDrvInfoPtrMap>::CAccessor access(&_SyncTexDrvInfos);
59 TTexDrvInfoPtrMap &rTexDrvInfos = access.value();
60 nlassert(rTexDrvInfos.empty());
63 nlassert(_TexDrvShares.empty());
64 nlassert(_MatDrvInfos.empty());
65 nlassert(_VBDrvInfos.empty());
66 nlassert(_IBDrvInfos.empty());
67 nlassert(_GPUPrgDrvInfos.empty());
71 // ***************************************************************************
72 bool IDriver::release(void)
74 // Called by derived classes.
76 // DO THIS FIRST => to auto kill real textures (by smartptr).
77 // First, Because must not kill a pointer owned by a CSmartPtr.
78 // Release Textures drv.
79 ItTexDrvSharePtrList ittex;
80 while( (ittex = _TexDrvShares.begin()) !=_TexDrvShares.end() )
82 // NB: at CTextureDrvShare deletion, this->_TexDrvShares is updated (entry deleted);
83 delete *ittex;
87 // Release refptr of TextureDrvInfos. Should be all null (because of precedent pass).
89 CSynchronized<TTexDrvInfoPtrMap>::CAccessor access(&_SyncTexDrvInfos);
90 TTexDrvInfoPtrMap &rTexDrvInfos = access.value();
92 // must be empty, because precedent pass should have deleted all.
93 nlassert(rTexDrvInfos.empty());
96 // Release material drv.
97 ItMatDrvInfoPtrList itmat;
98 while( (itmat = _MatDrvInfos.begin()) != _MatDrvInfos.end() )
100 // NB: at IShader deletion, this->_MatDrvInfos is updated (entry deleted);
101 delete *itmat;
104 // Release VBs drv.
105 ItVBDrvInfoPtrList itvb;
106 while( (itvb = _VBDrvInfos.begin()) != _VBDrvInfos.end() )
108 // NB: at IVBDrvInfo deletion, this->_VBDrvInfos is updated (entry deleted);
109 delete *itvb;
112 // Release IBs drv.
113 ItIBDrvInfoPtrList itib;
114 while( (itib = _IBDrvInfos.begin()) != _IBDrvInfos.end() )
116 // NB: at IIBDrvInfo deletion, this->_IBDrvInfos is updated (entry deleted);
117 delete *itib;
120 // Release GPUPrg drv.
121 ItGPUPrgDrvInfoPtrList itGPUPrg;
122 while( (itGPUPrg = _GPUPrgDrvInfos.begin()) != _GPUPrgDrvInfos.end() )
124 // NB: at IVertexProgramDrvInfos deletion, this->_GPUPrgDrvInfos is updated (entry deleted);
125 delete *itGPUPrg;
128 return true;
132 // ***************************************************************************
133 GfxMode::GfxMode(uint16 w, uint16 h, uint8 d, bool windowed, bool offscreen, uint frequency, sint8 aa, const std::string &displayDevice)
135 DisplayDevice = displayDevice;
136 Windowed = windowed;
137 Width = w;
138 Height = h;
139 Depth = d;
140 OffScreen = offscreen;
141 Frequency = frequency;
142 AntiAlias = aa;
145 // ***************************************************************************
146 IDriver::TMessageBoxId IDriver::systemMessageBox (const char* message, const char* title, IDriver::TMessageBoxType type, IDriver::TMessageBoxIcon icon)
148 static const char* icons[iconCount]=
151 "WAIT:\n",
152 "QUESTION:\n",
153 "HEY!\n",
155 "WARNING!\n",
156 "ERROR!\n",
157 "INFORMATION:\n",
158 "STOP:\n"
160 static const char* messages[typeCount]=
162 "Press any key...",
163 "(O)k or (C)ancel ?",
164 "(Y)es or (N)o ?",
165 "(A)bort (R)etry (I)gnore ?",
166 "(Y)es (N)o (C)ancel ?",
167 "(R)etry (C)ancel ?"
169 printf ("%s%s\n%s", icons[icon], title, message);
170 for(;;)
172 printf ("\n%s", messages[type]);
173 int c=getchar();
174 if (type==okType)
175 return okId;
176 switch (c)
178 case 'O':
179 case 'o':
180 if ((type==okType)||(type==okCancelType))
181 return okId;
182 break;
183 case 'C':
184 case 'c':
185 if ((type==yesNoCancelType)||(type==okCancelType)||(type==retryCancelType))
186 return cancelId;
187 break;
188 case 'Y':
189 case 'y':
190 if ((type==yesNoCancelType)||(type==yesNoType))
191 return yesId;
192 break;
193 case 'N':
194 case 'n':
195 if ((type==yesNoCancelType)||(type==yesNoType))
196 return noId;
197 break;
198 case 'A':
199 case 'a':
200 if (type==abortRetryIgnoreType)
201 return abortId;
202 break;
203 case 'R':
204 case 'r':
205 if (type==abortRetryIgnoreType)
206 return retryId;
207 break;
208 case 'I':
209 case 'i':
210 if (type==abortRetryIgnoreType)
211 return ignoreId;
212 break;
215 nlassert (0); // no!
216 return okId;
222 // ***************************************************************************
223 void IDriver::removeVBDrvInfoPtr(ItVBDrvInfoPtrList vbDrvInfoIt)
225 _VBDrvInfos.erase(vbDrvInfoIt);
227 // ***************************************************************************
228 void IDriver::removeIBDrvInfoPtr(ItIBDrvInfoPtrList ibDrvInfoIt)
230 _IBDrvInfos.erase(ibDrvInfoIt);
232 // ***************************************************************************
233 void IDriver::removeTextureDrvInfoPtr(ItTexDrvInfoPtrMap texDrvInfoIt)
235 CSynchronized<TTexDrvInfoPtrMap>::CAccessor access(&_SyncTexDrvInfos);
236 TTexDrvInfoPtrMap &rTexDrvInfos = access.value();
238 rTexDrvInfos.erase(texDrvInfoIt);
240 // ***************************************************************************
241 void IDriver::removeTextureDrvSharePtr(ItTexDrvSharePtrList texDrvShareIt)
243 _TexDrvShares.erase(texDrvShareIt);
245 // ***************************************************************************
246 void IDriver::removeMatDrvInfoPtr(ItMatDrvInfoPtrList shaderIt)
248 _MatDrvInfos.erase(shaderIt);
250 // ***************************************************************************
251 void IDriver::removeGPUPrgDrvInfoPtr(ItGPUPrgDrvInfoPtrList gpuPrgDrvInfoIt)
253 _GPUPrgDrvInfos.erase(gpuPrgDrvInfoIt);
256 // ***************************************************************************
257 bool IDriver::invalidateShareTexture (ITexture &texture)
259 // Create the shared Name.
260 std::string name;
261 getTextureShareName (texture, name);
263 // Look for the driver info for this share name
264 CSynchronized<TTexDrvInfoPtrMap>::CAccessor access(&_SyncTexDrvInfos);
265 TTexDrvInfoPtrMap &rTexDrvInfos = access.value();
266 TTexDrvInfoPtrMap::iterator iteDrvInfo = rTexDrvInfos.find (name);
267 if (iteDrvInfo != rTexDrvInfos.end())
269 // Now parse all shared info
270 TTexDrvSharePtrList::iterator shareIte = _TexDrvShares.begin ();
271 while (shareIte != _TexDrvShares.end ())
273 // Good one ?
274 if ((*shareIte)->DrvTexture == iteDrvInfo->second)
276 // Remove this one
277 TTexDrvSharePtrList::iterator toRemove = shareIte;
278 shareIte++;
279 delete (*toRemove);
281 else
282 shareIte++;
285 // Ok
286 return true;
288 return false;
290 // ***************************************************************************
291 void IDriver::getTextureShareName (const ITexture& tex, string &output)
293 // Create the shared Name.
294 output= toLowerAscii(tex.getShareName());
296 // append format Id of the texture.
297 static char fmt[256];
298 smprintf(fmt, 256, "@Fmt:%d", (uint32)tex.getUploadFormat());
299 output+= fmt;
301 // append mipmap info
302 if(tex.mipMapOn())
303 output+= "@MMp:On";
304 else
305 output+= "@MMp:Off";
308 // ***************************************************************************
310 void IDriver::setStaticMemoryToVRAM (bool staticMemoryToVRAM)
312 _StaticMemoryToVRAM=staticMemoryToVRAM;
315 // ***************************************************************************
316 class CTextureDebugInfo
318 public:
319 uint MemoryCost;
320 string Line;
322 bool operator<(const CTextureDebugInfo &o) const {return Line<o.Line;}
325 class CTextureDebugKey
327 public:
328 ITexture::TUploadFormat UpLoadFormat;
329 ITexture::CTextureCategory *Category;
331 bool operator<(const CTextureDebugKey &o) const
333 const string &s0= Category?Category->Name:_EmptyString;
334 const string &s1= o.Category?o.Category->Name:_EmptyString;
335 if(s0 == s1)
336 return UpLoadFormat<o.UpLoadFormat;
337 else
338 return s0<s1;
341 private:
342 static std::string _EmptyString;
344 std::string CTextureDebugKey::_EmptyString;
347 // ***************************************************************************
348 void IDriver::profileTextureUsage(std::vector<std::string> &result)
350 std::set<ITextureDrvInfos *> texSet;
351 // uint i;
353 // reserve result, sort by UploadFormat
354 map<CTextureDebugKey, vector<CTextureDebugInfo> > tempInfo;
356 // Parse all the DrvShare list
357 uint totalSize= 0;
358 ItTexDrvSharePtrList it= _TexDrvShares.begin();
359 for(;it!=_TexDrvShares.end();it++)
361 // get TexDrvInfos and owner
362 ITextureDrvInfos *gltext= (ITextureDrvInfos*)(ITextureDrvInfos*)(*it)->DrvTexture;
363 ITexture *text= (*it)->getOwnerTexture();
364 nlassert(gltext && text);
366 // sort by upload format and texture category
367 CTextureDebugKey infoKey;
368 infoKey.UpLoadFormat= text->getUploadFormat();
369 nlassert(infoKey.UpLoadFormat<ITexture::UploadFormatCount);
370 infoKey.Category= text->getTextureCategory();
372 // get the shareName
373 string shareName;
374 if(text->supportSharing())
375 shareName= toLowerAscii(text->getShareName());
376 else
377 shareName= "Not Shared";
379 // only if not already append to the set
380 if(texSet.insert(gltext).second)
382 uint memCost= gltext->getTextureMemoryUsed();
383 totalSize+= memCost;
384 string typeStr= typeid(*text).name();
385 strFindReplace(typeStr, "class NL3D::", string());
386 tempInfo[infoKey].push_back(CTextureDebugInfo());
387 tempInfo[infoKey].back().Line= toString("Type: %15s. ShareName: %s. Size: %d Ko",
388 typeStr.c_str(),
389 shareName.c_str(),
390 memCost/1024);
391 tempInfo[infoKey].back().MemoryCost= memCost;
395 // For convenience, sort
396 map<CTextureDebugKey, vector<CTextureDebugInfo> >::iterator itCat;
397 for(itCat= tempInfo.begin();itCat!= tempInfo.end();itCat++)
398 sort(itCat->second.begin(), itCat->second.end());
400 // Store into result, appending Tag for each Mo reached. +10* is for extra lines and security
401 result.clear();
402 result.reserve(texSet.size() + 10*(tempInfo.size()) + totalSize/(1024*1024));
404 // copy and add tags
405 for(itCat= tempInfo.begin();itCat!= tempInfo.end();itCat++)
407 const CTextureDebugKey &infoKey= itCat->first;
408 vector<CTextureDebugInfo> &infoVect= itCat->second;
410 string strUploadFormat;
411 switch(infoKey.UpLoadFormat)
413 case ITexture::Auto: strUploadFormat= ("Format: Auto"); break;
414 case ITexture::RGBA8888: strUploadFormat= ("Format: RGBA8888"); break;
415 case ITexture::RGBA4444: strUploadFormat= ("Format: RGBA4444"); break;
416 case ITexture::RGBA5551: strUploadFormat= ("Format: RGBA5551"); break;
417 case ITexture::RGB888: strUploadFormat= ("Format: RGB888"); break;
418 case ITexture::RGB565: strUploadFormat= ("Format: RGB565"); break;
419 case ITexture::DXTC1: strUploadFormat= ("Format: DXTC1"); break;
420 case ITexture::DXTC1Alpha: strUploadFormat= ("Format: DXTC1Alpha"); break;
421 case ITexture::DXTC3: strUploadFormat= ("Format: DXTC3"); break;
422 case ITexture::DXTC5: strUploadFormat= ("Format: DXTC5"); break;
423 case ITexture::Luminance: strUploadFormat= ("Format: Luminance"); break;
424 case ITexture::Alpha: strUploadFormat= ("Format: Alpha"); break;
425 case ITexture::AlphaLuminance: strUploadFormat= ("Format: AlphaLuminance"); break;
426 case ITexture::DsDt: strUploadFormat= ("Format: DsDt"); break;
427 default: strUploadFormat= toString("Format??: %d", infoKey.UpLoadFormat); break;
430 // header info
431 result.push_back(toString("**** %s. %s ****", infoKey.Category?infoKey.Category->Name.c_str():"",
432 strUploadFormat.c_str()) );
434 // display stats for this format
435 uint tagTotal= 0;
436 uint curTotal= 0;
437 for(uint j=0;j<infoVect.size();j++)
439 result.push_back(infoVect[j].Line);
440 tagTotal+= infoVect[j].MemoryCost;
441 curTotal+= infoVect[j].MemoryCost;
442 if(tagTotal>=1024*1024)
444 result.push_back(toString("---- %.1f Mo", float(curTotal)/(1024*1024)));
445 tagTotal= 0;
448 // append last line?
449 if(tagTotal!=0)
450 result.push_back(toString("---- %.1f Mo", float(curTotal)/(1024*1024)));
453 // append the total
454 result.push_back(toString("**** Total ****"));
455 result.push_back(toString("Total: %d Ko", totalSize/1024));
458 // ***************************************************************************