Graphics.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. //
  2. // Copyright (c) 2008-2018 the Urho3D project.
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. #include "../Precompiled.h"
  23. #include "../Core/Profiler.h"
  24. #include "../Graphics/AnimatedModel.h"
  25. #include "../Graphics/Animation.h"
  26. #include "../Graphics/AnimationController.h"
  27. #include "../Graphics/Camera.h"
  28. #include "../Graphics/CustomGeometry.h"
  29. #include "../Graphics/DebugRenderer.h"
  30. #include "../Graphics/DecalSet.h"
  31. #include "../Graphics/Graphics.h"
  32. #include "../Graphics/GraphicsImpl.h"
  33. #include "../Graphics/Material.h"
  34. #include "../Graphics/Octree.h"
  35. #include "../Graphics/ParticleEffect.h"
  36. #include "../Graphics/ParticleEmitter.h"
  37. #include "../Graphics/RibbonTrail.h"
  38. #include "../Graphics/Shader.h"
  39. #include "../Graphics/ShaderPrecache.h"
  40. #include "../Graphics/Skybox.h"
  41. #include "../Graphics/StaticModelGroup.h"
  42. #include "../Graphics/Technique.h"
  43. #include "../Graphics/Terrain.h"
  44. #include "../Graphics/TerrainPatch.h"
  45. #ifdef _WIN32
  46. #include "../Graphics/Texture2D.h"
  47. #endif
  48. #include "../Graphics/Texture2DArray.h"
  49. #include "../Graphics/Texture3D.h"
  50. #include "../Graphics/TextureCube.h"
  51. #include "../Graphics/Zone.h"
  52. #include "../IO/FileSystem.h"
  53. #include "../IO/Log.h"
  54. #include <SDL/SDL.h>
  55. #include "../DebugNew.h"
  56. namespace Urho3D
  57. {
  58. void Graphics::SetExternalWindow(void* window)
  59. {
  60. if (!window_)
  61. externalWindow_ = window;
  62. else
  63. URHO3D_LOGERROR("Window already opened, can not set external window");
  64. }
  65. void Graphics::SetWindowTitle(const String& windowTitle)
  66. {
  67. windowTitle_ = windowTitle;
  68. if (window_)
  69. SDL_SetWindowTitle(window_, windowTitle_.CString());
  70. }
  71. void Graphics::SetWindowIcon(Image* windowIcon)
  72. {
  73. windowIcon_ = windowIcon;
  74. if (window_)
  75. CreateWindowIcon();
  76. }
  77. void Graphics::SetWindowPosition(const IntVector2& position)
  78. {
  79. if (window_)
  80. SDL_SetWindowPosition(window_, position.x_, position.y_);
  81. else
  82. position_ = position; // Sets as initial position for OpenWindow()
  83. }
  84. void Graphics::SetWindowPosition(int x, int y)
  85. {
  86. SetWindowPosition(IntVector2(x, y));
  87. }
  88. void Graphics::SetOrientations(const String& orientations)
  89. {
  90. orientations_ = orientations.Trimmed();
  91. SDL_SetHint(SDL_HINT_ORIENTATIONS, orientations_.CString());
  92. }
  93. bool Graphics::ToggleFullscreen()
  94. {
  95. return SetMode(width_, height_, !fullscreen_, borderless_, resizable_, highDPI_, vsync_, tripleBuffer_, multiSample_, monitor_, refreshRate_);
  96. }
  97. void Graphics::SetShaderParameter(StringHash param, const Variant& value)
  98. {
  99. switch (value.GetType())
  100. {
  101. case VAR_BOOL:
  102. SetShaderParameter(param, value.GetBool());
  103. break;
  104. case VAR_INT:
  105. SetShaderParameter(param, value.GetInt());
  106. break;
  107. case VAR_FLOAT:
  108. case VAR_DOUBLE:
  109. SetShaderParameter(param, value.GetFloat());
  110. break;
  111. case VAR_VECTOR2:
  112. SetShaderParameter(param, value.GetVector2());
  113. break;
  114. case VAR_VECTOR3:
  115. SetShaderParameter(param, value.GetVector3());
  116. break;
  117. case VAR_VECTOR4:
  118. SetShaderParameter(param, value.GetVector4());
  119. break;
  120. case VAR_COLOR:
  121. SetShaderParameter(param, value.GetColor());
  122. break;
  123. case VAR_MATRIX3:
  124. SetShaderParameter(param, value.GetMatrix3());
  125. break;
  126. case VAR_MATRIX3X4:
  127. SetShaderParameter(param, value.GetMatrix3x4());
  128. break;
  129. case VAR_MATRIX4:
  130. SetShaderParameter(param, value.GetMatrix4());
  131. break;
  132. case VAR_BUFFER:
  133. {
  134. const PODVector<unsigned char>& buffer = value.GetBuffer();
  135. if (buffer.Size() >= sizeof(float))
  136. SetShaderParameter(param, reinterpret_cast<const float*>(&buffer[0]), buffer.Size() / sizeof(float));
  137. }
  138. break;
  139. default:
  140. // Unsupported parameter type, do nothing
  141. break;
  142. }
  143. }
  144. IntVector2 Graphics::GetWindowPosition() const
  145. {
  146. if (window_)
  147. {
  148. IntVector2 position;
  149. SDL_GetWindowPosition(window_, &position.x_, &position.y_);
  150. return position;
  151. }
  152. return position_;
  153. }
  154. PODVector<IntVector3> Graphics::GetResolutions(int monitor) const
  155. {
  156. PODVector<IntVector3> ret;
  157. // Emscripten is not able to return a valid list
  158. #ifndef __EMSCRIPTEN__
  159. auto numModes = (unsigned)SDL_GetNumDisplayModes(monitor);
  160. for (unsigned i = 0; i < numModes; ++i)
  161. {
  162. SDL_DisplayMode mode;
  163. SDL_GetDisplayMode(monitor, i, &mode);
  164. int width = mode.w;
  165. int height = mode.h;
  166. int rate = mode.refresh_rate;
  167. // Store mode if unique
  168. bool unique = true;
  169. for (unsigned j = 0; j < ret.Size(); ++j)
  170. {
  171. if (ret[j].x_ == width && ret[j].y_ == height && ret[j].z_ == rate)
  172. {
  173. unique = false;
  174. break;
  175. }
  176. }
  177. if (unique)
  178. ret.Push(IntVector3(width, height, rate));
  179. }
  180. #endif
  181. return ret;
  182. }
  183. IntVector2 Graphics::GetDesktopResolution(int monitor) const
  184. {
  185. #if !defined(__ANDROID__) && !defined(IOS) && !defined(TVOS)
  186. SDL_DisplayMode mode;
  187. SDL_GetDesktopDisplayMode(monitor, &mode);
  188. return IntVector2(mode.w, mode.h);
  189. #else
  190. // SDL_GetDesktopDisplayMode() may not work correctly on mobile platforms. Rather return the window size
  191. return IntVector2(width_, height_);
  192. #endif
  193. }
  194. int Graphics::GetMonitorCount() const
  195. {
  196. return SDL_GetNumVideoDisplays();
  197. }
  198. int Graphics::GetCurrentMonitor() const
  199. {
  200. return window_ ? SDL_GetWindowDisplayIndex(window_) : 0;
  201. }
  202. bool Graphics::GetMaximized() const
  203. {
  204. return window_? static_cast<bool>(SDL_GetWindowFlags(window_) & SDL_WINDOW_MAXIMIZED) : false;
  205. }
  206. Vector3 Graphics::GetDisplayDPI(int monitor) const
  207. {
  208. Vector3 result;
  209. SDL_GetDisplayDPI(monitor, &result.z_, &result.x_, &result.y_);
  210. return result;
  211. }
  212. void Graphics::Maximize()
  213. {
  214. if (!window_)
  215. return;
  216. SDL_MaximizeWindow(window_);
  217. }
  218. void Graphics::Minimize()
  219. {
  220. if (!window_)
  221. return;
  222. SDL_MinimizeWindow(window_);
  223. }
  224. void Graphics::Raise() const
  225. {
  226. if (!window_)
  227. return;
  228. SDL_RaiseWindow(window_);
  229. }
  230. void Graphics::BeginDumpShaders(const String& fileName)
  231. {
  232. shaderPrecache_ = new ShaderPrecache(context_, fileName);
  233. }
  234. void Graphics::EndDumpShaders()
  235. {
  236. shaderPrecache_.Reset();
  237. }
  238. void Graphics::PrecacheShaders(Deserializer& source)
  239. {
  240. URHO3D_PROFILE(PrecacheShaders);
  241. ShaderPrecache::LoadShaders(this, source);
  242. }
  243. void Graphics::SetShaderCacheDir(const String& path)
  244. {
  245. String trimmedPath = path.Trimmed();
  246. if (trimmedPath.Length())
  247. shaderCacheDir_ = AddTrailingSlash(trimmedPath);
  248. }
  249. void Graphics::AddGPUObject(GPUObject* object)
  250. {
  251. MutexLock lock(gpuObjectMutex_);
  252. gpuObjects_.Push(object);
  253. }
  254. void Graphics::RemoveGPUObject(GPUObject* object)
  255. {
  256. MutexLock lock(gpuObjectMutex_);
  257. gpuObjects_.Remove(object);
  258. }
  259. void* Graphics::ReserveScratchBuffer(unsigned size)
  260. {
  261. if (!size)
  262. return nullptr;
  263. if (size > maxScratchBufferRequest_)
  264. maxScratchBufferRequest_ = size;
  265. // First check for a free buffer that is large enough
  266. for (Vector<ScratchBuffer>::Iterator i = scratchBuffers_.Begin(); i != scratchBuffers_.End(); ++i)
  267. {
  268. if (!i->reserved_ && i->size_ >= size)
  269. {
  270. i->reserved_ = true;
  271. return i->data_.Get();
  272. }
  273. }
  274. // Then check if a free buffer can be resized
  275. for (Vector<ScratchBuffer>::Iterator i = scratchBuffers_.Begin(); i != scratchBuffers_.End(); ++i)
  276. {
  277. if (!i->reserved_)
  278. {
  279. i->data_ = new unsigned char[size];
  280. i->size_ = size;
  281. i->reserved_ = true;
  282. URHO3D_LOGDEBUG("Resized scratch buffer to size " + String(size));
  283. return i->data_.Get();
  284. }
  285. }
  286. // Finally allocate a new buffer
  287. ScratchBuffer newBuffer;
  288. newBuffer.data_ = new unsigned char[size];
  289. newBuffer.size_ = size;
  290. newBuffer.reserved_ = true;
  291. scratchBuffers_.Push(newBuffer);
  292. return newBuffer.data_.Get();
  293. URHO3D_LOGDEBUG("Allocated scratch buffer with size " + String(size));
  294. }
  295. void Graphics::FreeScratchBuffer(void* buffer)
  296. {
  297. if (!buffer)
  298. return;
  299. for (Vector<ScratchBuffer>::Iterator i = scratchBuffers_.Begin(); i != scratchBuffers_.End(); ++i)
  300. {
  301. if (i->reserved_ && i->data_.Get() == buffer)
  302. {
  303. i->reserved_ = false;
  304. return;
  305. }
  306. }
  307. URHO3D_LOGWARNING("Reserved scratch buffer " + ToStringHex((unsigned)(size_t)buffer) + " not found");
  308. }
  309. void Graphics::CleanupScratchBuffers()
  310. {
  311. for (Vector<ScratchBuffer>::Iterator i = scratchBuffers_.Begin(); i != scratchBuffers_.End(); ++i)
  312. {
  313. if (!i->reserved_ && i->size_ > maxScratchBufferRequest_ * 2 && i->size_ >= 1024 * 1024)
  314. {
  315. i->data_ = maxScratchBufferRequest_ > 0 ? (new unsigned char[maxScratchBufferRequest_]) : nullptr;
  316. i->size_ = maxScratchBufferRequest_;
  317. URHO3D_LOGDEBUG("Resized scratch buffer to size " + String(maxScratchBufferRequest_));
  318. }
  319. }
  320. maxScratchBufferRequest_ = 0;
  321. }
  322. void Graphics::CreateWindowIcon()
  323. {
  324. if (windowIcon_)
  325. {
  326. SDL_Surface* surface = windowIcon_->GetSDLSurface();
  327. if (surface)
  328. {
  329. SDL_SetWindowIcon(window_, surface);
  330. SDL_FreeSurface(surface);
  331. }
  332. }
  333. }
  334. void RegisterGraphicsLibrary(Context* context)
  335. {
  336. Animation::RegisterObject(context);
  337. Material::RegisterObject(context);
  338. Model::RegisterObject(context);
  339. Shader::RegisterObject(context);
  340. Technique::RegisterObject(context);
  341. Texture2D::RegisterObject(context);
  342. Texture2DArray::RegisterObject(context);
  343. Texture3D::RegisterObject(context);
  344. TextureCube::RegisterObject(context);
  345. Camera::RegisterObject(context);
  346. Drawable::RegisterObject(context);
  347. Light::RegisterObject(context);
  348. StaticModel::RegisterObject(context);
  349. StaticModelGroup::RegisterObject(context);
  350. Skybox::RegisterObject(context);
  351. AnimatedModel::RegisterObject(context);
  352. AnimationController::RegisterObject(context);
  353. BillboardSet::RegisterObject(context);
  354. ParticleEffect::RegisterObject(context);
  355. ParticleEmitter::RegisterObject(context);
  356. RibbonTrail::RegisterObject(context);
  357. CustomGeometry::RegisterObject(context);
  358. DecalSet::RegisterObject(context);
  359. Terrain::RegisterObject(context);
  360. TerrainPatch::RegisterObject(context);
  361. DebugRenderer::RegisterObject(context);
  362. Octree::RegisterObject(context);
  363. Zone::RegisterObject(context);
  364. }
  365. }